diff --git a/api/api.go b/api/api.go index 6915727..b9eac4f 100644 --- a/api/api.go +++ b/api/api.go @@ -31,6 +31,7 @@ import ( "go.fifitido.net/twitch/api/teams" "go.fifitido.net/twitch/api/users" "go.fifitido.net/twitch/api/videos" + "go.fifitido.net/twitch/api/whispers" ) const HelixBaseUrl = "https://api.twitch.tv/helix" @@ -66,6 +67,7 @@ type API struct { Teams *teams.Teams Users *users.Users Videos *videos.Videos + Whispers *whispers.Whispers } func New(client *http.Client, baseUrl *url.URL) *API { @@ -100,6 +102,7 @@ func New(client *http.Client, baseUrl *url.URL) *API { Teams: teams.New(client, baseUrl), Users: users.New(client, baseUrl), Videos: videos.New(client, baseUrl), + Whispers: whispers.New(client, baseUrl), } } diff --git a/api/whispers/send_whisper.go b/api/whispers/send_whisper.go new file mode 100644 index 0000000..7f7f70f --- /dev/null +++ b/api/whispers/send_whisper.go @@ -0,0 +1,74 @@ +package whispers + +import ( + "context" + "encoding/json" + "io" + "net/http" + "net/url" + + "github.com/google/go-querystring/query" +) + +type SendWhisperParams struct { + // The ID of the user sending the whisper. + // This user must have a verified phone number. + // This ID must match the user ID in the user access token. + FromUserID string `json:"from_user_id"` + + // The ID of the user to receive the whisper. + ToUserID string `json:"to_user_id"` +} + +type SendWhisperRequest struct { + // The whisper message to send. The message must not be empty. + // + // The maximum message lengths are: + // + // 500 characters if the user you're sending the message to hasn't whispered you before. + // + // 10,000 characters if the user you're sending the message to has whispered you before. + // + // Messages that exceed the maximum length are truncated. + Message string `json:"message"` +} + +// Sends a whisper message to the specified user. +// +// NOTE: The user sending the whisper must have a verified phone number +// (see the Phone Number setting in your Security and Privacy settings). +// +// NOTE: The API may silently drop whispers that it suspects of violating Twitch policies. +// (The API does not indicate that it dropped the whisper; it returns a 204 status code as if it succeeded.) +// +// Rate Limits: You may whisper to a maximum of 40 unique recipients per day. +// Within the per day limit, you may whisper a maximum of 3 whispers per second and a maximum of 100 whispers per minute. +// +// Requires a user access token that includes the user:manage:whispers scope. +func (c *Whispers) SendWhisper(ctx context.Context, params *SendWhisperParams, body *SendWhisperRequest) error { + v, _ := query.Values(params) + endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "whispers", RawQuery: v.Encode()}) + + r, w := io.Pipe() + + go func() { + if err := json.NewEncoder(w).Encode(body); err != nil { + w.CloseWithError(err) + } else { + w.Close() + } + }() + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), r) + if err != nil { + return err + } + + res, err := c.client.Do(req) + if err != nil { + return err + } + defer res.Body.Close() + + return nil +} diff --git a/api/whispers/whispers.go b/api/whispers/whispers.go new file mode 100644 index 0000000..da4e064 --- /dev/null +++ b/api/whispers/whispers.go @@ -0,0 +1,18 @@ +package whispers + +import ( + "net/http" + "net/url" +) + +type Whispers struct { + client *http.Client + baseUrl *url.URL +} + +func New(client *http.Client, baseUrl *url.URL) *Whispers { + return &Whispers{ + client: client, + baseUrl: baseUrl, + } +}