Add chat endpoints to API

This commit is contained in:
Evan Fiordeliso 2024-02-28 10:30:20 -05:00
parent 616cb935a0
commit 990b1da80c
18 changed files with 1146 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import (
"go.fifitido.net/twitch/api/channelpoints" "go.fifitido.net/twitch/api/channelpoints"
"go.fifitido.net/twitch/api/channels" "go.fifitido.net/twitch/api/channels"
"go.fifitido.net/twitch/api/charity" "go.fifitido.net/twitch/api/charity"
"go.fifitido.net/twitch/api/chat"
"go.fifitido.net/twitch/api/eventsub" "go.fifitido.net/twitch/api/eventsub"
) )
@ -25,6 +26,7 @@ type API struct {
Channels *channels.Channels Channels *channels.Channels
ChannelPoints *channelpoints.ChannelPoints ChannelPoints *channelpoints.ChannelPoints
Charity *charity.Charity Charity *charity.Charity
Chat *chat.Chat
EventSub *eventsub.EventSub EventSub *eventsub.EventSub
} }
@ -42,6 +44,7 @@ func New() *API {
Channels: channels.New(client, baseUrl), Channels: channels.New(client, baseUrl),
ChannelPoints: channelpoints.New(client, baseUrl), ChannelPoints: channelpoints.New(client, baseUrl),
Charity: charity.New(client, baseUrl), Charity: charity.New(client, baseUrl),
Chat: chat.New(client, baseUrl),
EventSub: eventsub.New(client, baseUrl), EventSub: eventsub.New(client, baseUrl),
} }
} }

18
api/chat/chat.go Normal file
View File

@ -0,0 +1,18 @@
package chat
import (
"net/http"
"net/url"
)
type Chat struct {
client *http.Client
baseUrl *url.URL
}
func New(client *http.Client, baseUrl *url.URL) *Chat {
return &Chat{
client: client,
baseUrl: baseUrl,
}
}

View File

@ -0,0 +1,41 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
)
type GetChannelChatBadgesResponse struct {
// The list of chat badges. The list is sorted in ascending order by set_id, and within a set, the list is sorted in ascending order by id.
Data []Badge `json:"data"`
}
// Gets the broadcasters list of custom chat badges. The list is empty if the broadcaster hasnt created custom chat badges.
// For information about custom badges,
// see subscriber badges: https://help.twitch.tv/s/article/subscriber-badge-guide
// and Bits badges: https://help.twitch.tv/s/article/custom-bit-badges-guide.
//
// Requires an app access token or user access token.
func (c *Chat) GetChannelChatBadges(ctx context.Context, broadcasterID string) (*GetChannelChatBadgesResponse, error) {
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/badges", RawQuery: "broadcaster_id=" + broadcasterID})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data GetChannelChatBadgesResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

View File

@ -0,0 +1,110 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
)
type GetChannelEmotesResponse struct {
// The list of emotes that the specified broadcaster created.
// If the broadcaster hasn't created custom emotes, the list is empty.
Data []ChannelEmote `json:"data"`
// A templated URL. Use the values from the id, format, scale, and theme_mode fields to replace the like-named placeholder strings
// in the templated URL to create a CDN (content delivery network) URL that you use to fetch the emote.
// For information about what the template looks like and how to use it to fetch emotes.
// See Emote CDN URL format: https://dev.twitch.tv/docs/irc/emotes#cdn-template
// You should use this template instead of using the URLs in the images object.
Template string `json:"template"`
}
type ChannelEmote struct {
// An ID that identifies this emote.
ID string `json:"id"`
// The name of the emote. This is the name that viewers type in the chat window to get the emote to appear.
Name string `json:"name"`
// The image URLs for the emote. These image URLs always provide a static, non-animated emote image with a light background.
//
// NOTE: You should use the templated URL in the template field to fetch the image instead of using these URLs.
Images EmoteImages `json:"images"`
// The subscriber tier at which the emote is unlocked.
// This field contains the tier information only if emote_type is set to subscriptions, otherwise, it's an empty string.
Tier string `json:"tier"`
// The type of emote. The possible values are:
//
// bitstier — A custom Bits tier emote.
//
// follower — A custom follower emote.
//
// subscriptions — A custom subscriber emote.
EmoteType string `json:"emote_type"`
// An ID that identifies the emote set that the emote belongs to.
EmoteSetID string `json:"emote_set_id"`
// The formats that the emote is available in.
// For example, if the emote is available only as a static PNG, the array contains only static.
// But if the emote is available as a static PNG and an animated GIF, the array contains static and animated.
// The possible formats are:
//
// animated — An animated GIF is available for this emote.
//
// static — A static PNG file is available for this emote.
Formats []EmoteFormat `json:"format"`
// The sizes that the emote is available in.
// For example, if the emote is available in small and medium sizes, the array contains 1.0 and 2.0.
// Possible sizes are:
//
// 1.0 — A small version (28px x 28px) is available.
//
// 2.0 — A medium version (56px x 56px) is available.
//
// 3.0 — A large version (112px x 112px) is available.
Scales []EmoteScale `json:"scale"`
// The background themes that the emote is available in. Possible themes are:
//
// dark, light
ThemeMode []EmoteThemeMode `json:"theme_mode"`
}
// Gets the broadcasters list of custom emotes.
// Broadcasters create these custom emotes for users who subscribe to or follow the channel or cheer Bits in the channels chat window.
// Learn More: https://dev.twitch.tv/docs/irc/emotes
//
// For information about the custom emotes
// see subscriber emotes: https://help.twitch.tv/s/article/subscriber-emote-guide,
// Bits tier emotes: https://help.twitch.tv/s/article/custom-bit-badges-guide?language=bg#slots,
// and follower emotes: https://blog.twitch.tv/en/2021/06/04/kicking-off-10-years-with-our-biggest-emote-update-ever/
//
// NOTE: With the exception of custom follower emotes, users may use custom emotes in any Twitch chat.
//
// Requires an app access token or user access token.
func (c *Chat) GetChannelEmotes(ctx context.Context, broadcasterID string) (*GetChannelEmotesResponse, error) {
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/emotes", RawQuery: "broadcaster_id=" + broadcasterID})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var response GetChannelEmotesResponse
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, err
}
return &response, nil
}

View File

@ -0,0 +1,57 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
type GetChatSettingsParams struct {
// The ID of the broadcaster whose chat settings you want to get.
BroadcasterID string `url:"broadcaster_id"`
// The ID of the broadcaster or one of the broadcasters moderators.
//
// This field is required only if you want to include the non_moderator_chat_delay and non_moderator_chat_delay_duration settings in the response.
//
// If you specify this field, this ID must match the user ID in the user access token.
ModeratorID *string `url:"moderator_id,omitempty"`
}
type GetChatSettingsResponse struct {
// The list of chat settings. The list contains a single object with all the settings.
Data []Settings `json:"data"`
}
// Gets the broadcasters chat settings.
//
// For an overview of chat settings,
// see Chat Commands for Broadcasters and Moderators: https://help.twitch.tv/s/article/chat-commands#AllMods
// and Moderator Preferences: https://help.twitch.tv/s/article/setting-up-moderation-for-your-twitch-channel#modpreferences
//
// Requires an app access token or user access token.
func (c *Chat) GetChatSettings(ctx context.Context, params *GetChatSettingsParams) (*GetChatSettingsResponse, error) {
v, _ := query.Values(params)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/settings", RawQuery: v.Encode()})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data GetChatSettingsResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

84
api/chat/get_chatters.go Normal file
View File

@ -0,0 +1,84 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
"go.fifitido.net/twitch/api/types"
)
type GetChattersParams struct {
// The ID of the broadcaster whose list of chatters you want to get.
BroadcasterID string `url:"broadcaster_id"`
// The ID of the broadcaster or one of the broadcasters moderators.
// This ID must match the user ID in the user access token.
ModeratorID string `url:"moderator_id"`
// The maximum number of items to return per page in the response.
// The minimum page size is 1 item per page and the maximum is 1,000.
// The default is 100.
First *int `url:"first,omitempty"`
// The cursor used to get the next page of results. The Pagination object in the response contains the cursors value.
// Read More: https://dev.twitch.tv/docs/api/guide#pagination
After *types.Cursor `url:"after,omitempty"`
}
type GetChattersResponse struct {
// The list of users that are connected to the broadcasters chat room.
// The list is empty if no users are connected to the chat room.
Data []Chatter `json:"data"`
// Contains the information used to page through the list of results. The object is empty if there are no more pages left to page through.
// Read more: https://dev.twitch.tv/docs/api/guide#pagination
Pagination types.Pagination `json:"pagination"`
// The total number of users that are connected to the broadcasters chat room.
// As you page through the list, the number of users may change as users join and leave the chat room.
Total int `json:"total"`
}
type Chatter struct {
// The ID of a user thats connected to the broadcasters chat room.
UserID string `json:"user_id"`
// The users login name.
UserLogin string `json:"user_login"`
// The users display name.
UserName string `json:"user_name"`
}
// Gets the list of users that are connected to the broadcasters chat session.
//
// NOTE: There is a delay between when users join and leave a chat and when the list is updated accordingly.
//
// To determine whether a user is a moderator or VIP, use the Get Moderators and Get VIPs endpoints. You can check the roles of up to 100 users.
//
// Requires a user access token that includes the moderator:read:chatters scope.
func (c *Chat) GetChatters(ctx context.Context, params *GetChattersParams) (*GetChattersResponse, error) {
v, _ := query.Values(params)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/chatters", RawQuery: v.Encode()})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var response GetChattersResponse
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, err
}
return &response, nil
}

116
api/chat/get_emote_sets.go Normal file
View File

@ -0,0 +1,116 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
type GetEmoteSetsParams struct {
// An ID that identifies the emote set to get. Include this parameter for each emote set you want to get.
// For example, emote_set_id=1234&emote_set_id=5678. You may specify a maximum of 25 IDs.
// The response contains only the IDs that were found and ignores duplicate IDs.
//
// To get emote set IDs, use the Get Channel Emotes API.
EmoteSetIDs []string `url:"emote_set_id,omitempty"`
}
type GetEmoteSetsResponse struct {
// The list of emotes found in the specified emote sets. The list is empty if none of the IDs were found.
// The list is in the same order as the set IDs specified in the request. Each set contains one or more emoticons.
Data []EmoteSetEmote `json:"data"`
// A templated URL. Use the values from the id, format, scale, and theme_mode fields to replace the like-named placeholder strings
// in the templated URL to create a CDN (content delivery network) URL that you use to fetch the emote.
// For information about what the template looks like and how to use it to fetch emotes.
// See Emote CDN URL format: https://dev.twitch.tv/docs/irc/emotes#cdn-template
// You should use this template instead of using the URLs in the images object.
Template string `json:"template"`
}
type EmoteSetEmote struct {
// An ID that identifies this emote.
ID string `json:"id"`
// The name of the emote. This is the name that viewers type in the chat window to get the emote to appear.
Name string `json:"name"`
// The image URLs for the emote. These image URLs always provide a static, non-animated emote image with a light background.
//
// NOTE: You should use the templated URL in the template field to fetch the image instead of using these URLs.
Images EmoteImages `json:"images"`
// The type of emote. The possible values are:
//
// bitstier — A custom Bits tier emote.
//
// follower — A custom follower emote.
//
// subscriptions — A custom subscriber emote.
EmoteType string `json:"emote_type"`
// An ID that identifies the emote set that the emote belongs to.
EmoteSetID string `json:"emote_set_id"`
// The ID of the broadcaster who owns the emote.
OwnerID string `json:"owner_id"`
// The formats that the emote is available in.
// For example, if the emote is available only as a static PNG, the array contains only static.
// But if the emote is available as a static PNG and an animated GIF, the array contains static and animated.
// The possible formats are:
//
// animated — An animated GIF is available for this emote.
//
// static — A static PNG file is available for this emote.
Formats []EmoteFormat `json:"format"`
// The sizes that the emote is available in.
// For example, if the emote is available in small and medium sizes, the array contains 1.0 and 2.0.
// Possible sizes are:
//
// 1.0 — A small version (28px x 28px) is available.
//
// 2.0 — A medium version (56px x 56px) is available.
//
// 3.0 — A large version (112px x 112px) is available.
Scales []EmoteScale `json:"scale"`
// The background themes that the emote is available in. Possible themes are:
//
// dark, light
ThemeMode []EmoteThemeMode `json:"theme_mode"`
}
// Gets emotes for one or more specified emote sets.
//
// An emote set groups emotes that have a similar context. For example, Twitch places all the subscriber emotes that a broadcaster uploads for their channel in the same emote set.
//
// Learn More: https://dev.twitch.tv/docs/irc/emotes
//
// Requires an app access token or user access token.
func (c *Chat) GetEmoteSets(ctx context.Context, params *GetEmoteSetsParams) (*GetEmoteSetsResponse, error) {
v, _ := query.Values(params)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/emotes/set", RawQuery: v.Encode()})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data GetEmoteSetsResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

View File

@ -0,0 +1,39 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
)
type GetGlobalChatBadgesResponse struct {
// The list of chat badges. The list is sorted in ascending order by set_id, and within a set, the list is sorted in ascending order by id.
Data []Badge `json:"data"`
}
// Gets Twitchs list of chat badges, which users may use in any channels chat room.
// For information about chat badges, see Twitch Chat Badges Guide: https://help.twitch.tv/s/article/twitch-chat-badges-guide
//
// Requires an app access token or user access token.
func (c *Chat) GetGlobalChatBadges(ctx context.Context) (*GetGlobalChatBadgesResponse, error) {
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/badges/global"})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data GetGlobalChatBadgesResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

View File

@ -0,0 +1,86 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
)
type GetGlobalEmotesResponse struct {
// The list of global emotes.
Data []GlobalEmote `json:"data"`
// A templated URL. Use the values from the id, format, scale, and theme_mode fields to replace the like-named placeholder strings
// in the templated URL to create a CDN (content delivery network) URL that you use to fetch the emote.
// For information about what the template looks like and how to use it to fetch emotes.
// See Emote CDN URL format: https://dev.twitch.tv/docs/irc/emotes#cdn-template
// You should use this template instead of using the URLs in the images object.
Template string `json:"template"`
}
type GlobalEmote struct {
// An ID that identifies this emote.
ID string `json:"id"`
// The name of the emote. This is the name that viewers type in the chat window to get the emote to appear.
Name string `json:"name"`
// The image URLs for the emote. These image URLs always provide a static, non-animated emote image with a light background.
//
// NOTE: You should use the templated URL in the template field to fetch the image instead of using these URLs.
Images EmoteImages `json:"images"`
// The formats that the emote is available in.
// For example, if the emote is available only as a static PNG, the array contains only static.
// But if the emote is available as a static PNG and an animated GIF, the array contains static and animated.
// The possible formats are:
//
// animated — An animated GIF is available for this emote.
//
// static — A static PNG file is available for this emote.
Formats []EmoteFormat `json:"format"`
// The sizes that the emote is available in.
// For example, if the emote is available in small and medium sizes, the array contains 1.0 and 2.0.
// Possible sizes are:
//
// 1.0 — A small version (28px x 28px) is available.
//
// 2.0 — A medium version (56px x 56px) is available.
//
// 3.0 — A large version (112px x 112px) is available.
Scales []EmoteScale `json:"scale"`
// The background themes that the emote is available in. Possible themes are:
//
// dark, light
ThemeMode []EmoteThemeMode `json:"theme_mode"`
}
// Gets the list of global emotes. Global emotes are Twitch-created emotes that users can use in any Twitch chat.
//
// Learn More: https://dev.twitch.tv/docs/irc/emotes
//
// Requires an app access token or user access token.
func (c *Chat) GetGlobalEmotes(ctx context.Context) (*GetGlobalEmotesResponse, error) {
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/emotes/global"})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data GetGlobalEmotesResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

View File

@ -0,0 +1,65 @@
package chat
import (
"context"
"encoding/json"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
type GetUserChatColorParams struct {
// The ID of the user whose username color you want to get.
// To specify more than one user, include the user_id parameter for each user to get.
// For example, &user_id=1234&user_id=5678. The maximum number of IDs that you may specify is 100.
//
// The API ignores duplicate IDs and IDs that werent found.
UserIDs []string `url:"user_id"`
}
type GetUserChatColorResponse struct {
// The list of users and the color code they use for their name.
Data []UserChatColor `json:"data"`
}
type UserChatColor struct {
// An ID that uniquely identifies the user.
UserID string `json:"user_id"`
// The users login name.
UserLogin string `json:"user_login"`
// The users display name.
UserName string `json:"user_name"`
// The Hex color code that the user uses in chat for their name.
// If the user hasnt specified a color in their settings, the string is empty.
Color string `json:"color"`
}
// Gets the color used for the users name in chat.
//
// Requires an app access token or user access token.
func (c *Chat) GetUserChatColor(ctx context.Context, params *GetUserChatColorParams) (*GetUserChatColorResponse, error) {
v, _ := query.Values(params)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/color", RawQuery: v.Encode()})
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data GetUserChatColorResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

134
api/chat/models.go Normal file
View File

@ -0,0 +1,134 @@
package chat
type EmoteImages struct {
// A URL to the small version (28px x 28px) of the emote.
URL1x string `json:"url_1x"`
// A URL to the medium version (56px x 56px) of the emote.
URL2x string `json:"url_2x"`
// A URL to the large version (112px x 112px) of the emote.
URL4x string `json:"url_4x"`
}
type EmoteFormat string
const (
EmoteFormatStatic EmoteFormat = "static"
EmoteFormatAnimated EmoteFormat = "animated"
)
type EmoteScale string
const (
// 1.0 — A small version (28px x 28px) is available.
EmoteScale1 EmoteScale = "1.0"
// 2.0 — A medium version (56px x 56px) is available.
EmoteScale2 EmoteScale = "2x"
// 3.0 — A large version (112px x 112px) is available.
EmoteScale4 EmoteScale = "4x"
)
type EmoteThemeMode string
const (
EmoteThemeModeDark EmoteThemeMode = "dark"
EmoteThemeModeLight EmoteThemeMode = "light"
)
type Badge struct {
// An ID that identifies this set of chat badges. For example, Bits or Subscriber.
SetID string `json:"set_id"`
// The list of chat badges in this set.
Versions []BadgeVersion `json:"versions"`
}
type BadgeVersion struct {
// An ID that identifies this version of the badge. The ID can be any value.
// For example, for Bits, the ID is the Bits tier level, but for World of Warcraft, it could be Alliance or Horde.
ID string `json:"id"`
// A URL to the small version (18px x 18px) of the badge.
ImageURL1x string `json:"image_url_1x"`
// A URL to the medium version (36px x 36px) of the badge.
ImageURL2x string `json:"image_url_2x"`
// A URL to the large version (72px x 72px) of the badge.
ImageURL4x string `json:"image_url_4x"`
// The title of the badge.
Title string `json:"title"`
// The description of the badge.
Description string `json:"description"`
// The action to take when clicking on the badge. Set to null if no action is specified.
ClickAction *string `json:"click_action"`
// The URL to navigate to when clicking on the badge. Set to null if no URL is specified.
ClickURL *string `json:"click_url"`
}
type Settings struct {
// The ID of the broadcaster specified in the request.
BroadcasterID string `json:"broadcaster_id"`
// A Boolean value that determines whether chat messages must contain only emotes. Is true if chat messages may contain only emotes; otherwise, false.
EmoteMode bool `json:"emote_mode"`
// A Boolean value that determines whether the broadcaster restricts the chat room to followers only.
//
// Is true if the broadcaster restricts the chat room to followers only; otherwise, false.
//
// See the follower_mode_duration field for how long users must follow the broadcaster before being able to participate in the chat room.
FollowerMode bool `json:"follower_mode"`
// The length of time, in minutes, that users must follow the broadcaster before being able to participate in the chat room.
// Is null if follower_mode is false.
FollowerModeDuration *int `json:"follower_mode_duration"`
// The moderators ID.
// The response includes this field only if the request specifies a user access token that includes the moderator:read:chat_settings scope.
ModeratorID *string `json:"moderator_id"`
// A Boolean value that determines whether the broadcaster adds a short delay before chat messages appear in the chat room.
// This gives chat moderators and bots a chance to remove them before viewers can see the message.
// See the non_moderator_chat_delay_duration field for the length of the delay.
// Is true if the broadcaster applies a delay; otherwise, false.
//
// The response includes this field only if the request specifies a user access token that includes the moderator:read:chat_settings
// scope and the user in the moderator_id query parameter is one of the broadcasters moderators.
NonModeratorChatDelay *bool `json:"non_moderator_chat_delay"`
// The amount of time, in seconds, that messages are delayed before appearing in chat. Is null if non_moderator_chat_delay is false.
//
// The response includes this field only if the request specifies a user access token that includes the moderator:read:chat_settings
// scope and the user in the moderator_id query parameter is one of the broadcasters moderators.
NonModeratorChatDelayDuration *int `json:"non_moderator_chat_delay_duration"`
// A Boolean value that determines whether the broadcaster limits how often users in the chat room are allowed to send messages.
//
// Is true if the broadcaster applies a delay; otherwise, false.
//
// See the slow_mode_wait_time field for the delay.
SlowMode bool `json:"slow_mode"`
// The amount of time, in seconds, that users must wait between sending messages.
//
// Is null if slow_mode is false.
SlowModeWaitTime *int `json:"slow_mode_wait_time"`
// A Boolean value that determines whether only users that subscribe to the broadcasters channel may talk in the chat room.
//
// Is true if the broadcaster restricts the chat room to subscribers only; otherwise, false.
SubscriberMode bool `json:"subscriber_mode"`
// A Boolean value that determines whether the broadcaster requires users to post only unique messages in the chat room.
//
// Is true if the broadcaster requires unique messages only; otherwise, false.
UniqueChatMode bool `json:"unique_chat_mode"`
}

View File

@ -0,0 +1,64 @@
package chat
import (
"context"
"encoding/json"
"io"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
"go.fifitido.net/twitch/api/types"
)
type SendChatAnnouncementParams struct {
// The ID of the broadcaster that owns the chat room to send the announcement to.
BroadcasterID string `url:"broadcaster_id"`
// The ID of a user who has permission to moderate the broadcasters chat room, or the broadcasters ID if theyre sending the announcement.
// This ID must match the user ID in the user access token.
ModeratorID string `url:"moderator_id"`
}
type SendChatAnnouncementRequest struct {
// The announcement to make in the broadcasters chat room.
// Announcements are limited to a maximum of 500 characters; announcements longer than 500 characters are truncated.
Message string `json:"message"`
// The color used to highlight the announcement. Possible case-sensitive values are:
//
// If color is set to primary or is not set, the channels accent color is used to highlight the announcement
// (see Profile Accent Color under profile settings, Channel and Videos, and Brand).
Color *types.AccentColor `json:"color"`
}
// Sends an announcement to the broadcasters chat room.
//
// Requires a user access token that includes the moderator:manage:announcements scope.
func (c *Chat) SendChatAnnouncement(ctx context.Context, params *SendChatAnnouncementParams, body *SendChatAnnouncementRequest) error {
v, _ := query.Values(params)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/announcements", 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
}

View File

@ -0,0 +1,85 @@
package chat
import (
"context"
"encoding/json"
"io"
"net/http"
"net/url"
)
type SendChatMessageRequest struct {
// The ID of the broadcaster whose chat room the message will be sent to.
BroadcasterID string `json:"broadcaster_id"`
// The ID of the user sending the message. This ID must match the user ID in the user access token.
SenderID string `json:"sender_id"`
// The message to send. The message is limited to a maximum of 500 characters. Chat messages can also include emoticons.
// To include emoticons, use the name of the emote. The names are case sensitive. Dont include colons around the name (e.g., :bleedPurple:).
// If Twitch recognizes the name, Twitch converts the name to the emote before writing the chat message to the chat room
Message string `json:"message"`
// The ID of the chat message being replied to.
ReplyParentMessageID *string `json:"reply_parent_message_id,omitempty"`
}
type SendChatMessageResponse struct {
Data []SendChatMessageData `json:"data"`
}
type SendChatMessageData struct {
// The message id for the message that was sent.
MessageID string `json:"message_id"`
// If the message passed all checks and was sent
IsSent bool `json:"is_sent"`
// The reason the message was dropped, if any.
DropReason []DropReason `json:"drop_reason,omitempty"`
}
type DropReason struct {
// Code for why the message was dropped.
Code string `json:"code"`
// Message for why the message was dropped.
Message string `json:"message"`
}
// Sends a message to the broadcasters chat room.
//
// Requires an app access token or user access token that includes the user:write:chat scope.
// If app access token used, then additionally requires user:bot scope from chatting user,
// and either channel:bot scope from broadcaster or moderator status.
func (c *Chat) SendChatMessage(ctx context.Context, body *SendChatMessageRequest) (*SendChatMessageResponse, error) {
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/messages"})
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 nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data SendChatMessageResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

55
api/chat/send_shoutout.go Normal file
View File

@ -0,0 +1,55 @@
package chat
import (
"context"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
type SendShoutoutParams struct {
// The ID of the broadcaster thats sending the Shoutout.
FromBroadcasterID string `url:"from_broadcaster_id"`
// The ID of the broadcaster thats receiving the Shoutout.
ToBroadcasterID string `url:"to_broadcaster_id"`
// The ID of the broadcaster or a user that is one of the broadcasters moderators.
// This ID must match the user ID in the access token.
ModeratorID string `url:"moderator_id"`
}
// Sends a Shoutout to the specified broadcaster.
// Typically, you send Shoutouts when you or one of your moderators notice another broadcaster in your chat,
// the other broadcaster is coming up in conversation, or after they raid your broadcast.
//
// Twitchs Shoutout feature is a great way for you to show support for other broadcasters and help them grow.
// Viewers who do not follow the other broadcaster will see a pop-up Follow button in your chat that they can click to follow the other broadcaster.
// Learn More: https://help.twitch.tv/s/article/shoutouts
//
// Rate Limits The broadcaster may send a Shoutout once every 2 minutes.
// They may send the same broadcaster a Shoutout once every 60 minutes.
//
// To receive notifications when a Shoutout is sent or received, subscribe to the channel.shoutout.create and channel.shoutout.receive subscription types.
// The channel.shoutout.create event includes cooldown periods that indicate when the broadcaster may send another
// Shoutout without exceeding the endpoints rate limit.
//
// Requires a user access token that includes the moderator:manage:shoutouts scope.
func (c *Chat) SendShoutout(ctx context.Context, params *SendShoutoutParams) error {
v, _ := query.Values(params)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/shoutouts", RawQuery: v.Encode()})
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), nil)
if err != nil {
return err
}
res, err := c.client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
return nil
}

View File

@ -0,0 +1,125 @@
package chat
import (
"context"
"encoding/json"
"io"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
type UpdateChatSettingsParams struct {
// The ID of the broadcaster whose chat settings you want to update.
BroadcasterID string `url:"broadcaster_id"`
// The ID of a user that has permission to moderate the broadcasters chat room, or the broadcasters ID if theyre making the update.
// This ID must match the user ID in the user access token.
ModeratorID string `url:"moderator_id"`
}
type UpdateChatSettingsRequest struct {
// A Boolean value that determines whether chat messages must contain only emotes.
//
// Set to true if only emotes are allowed; otherwise, false. The default is false.
EmoteMode *bool `json:"emote_mode"`
// A Boolean value that determines whether the broadcaster restricts the chat room to followers only.
//
// Set to true if the broadcaster restricts the chat room to followers only; otherwise, false. The default is true.
//
// To specify how long users must follow the broadcaster before being able to participate in the chat room, see the follower_mode_duration field.
FollowerMode *bool `json:"follower_mode"`
// The length of time, in minutes, that users must follow the broadcaster before being able to participate in the chat room.
// Set only if follower_mode is true.
// Possible values are: 0 (no restriction) through 129600 (3 months).
// The default is 0.
FollowerModeDuration *int `json:"follower_mode_duration"`
// A Boolean value that determines whether the broadcaster adds a short delay before chat messages appear in the chat room.
// This gives chat moderators and bots a chance to remove them before viewers can see the message.
//
// Set to true if the broadcaster applies a delay; otherwise, false.
// The default is false.
//
// To specify the length of the delay, see the non_moderator_chat_delay_duration field.
NonModeratorChatDelay *bool `json:"non_moderator_chat_delay"`
// The amount of time, in seconds, that messages are delayed before appearing in chat. Set only if non_moderator_chat_delay is true.
// Possible values are:
//
// 2 — 2 second delay (recommended)
//
// 4 — 4 second delay
//
// 6 — 6 second delay
NonModeratorChatDelayDuration *int `json:"non_moderator_chat_delay_duration"`
// A Boolean value that determines whether the broadcaster limits how often users in the chat room are allowed to send messages.
// Set to true if the broadcaster applies a wait period between messages; otherwise, false.
// The default is false.
//
// To specify the delay, see the slow_mode_wait_time field.
SlowMode bool `json:"slow_mode"`
// The amount of time, in seconds, that users must wait between sending messages.
// Set only if slow_mode is true.
//
// Possible values are: 3 (3 second delay) through 120 (2 minute delay). The default is 30 seconds.
SlowModeWaitTime *int `json:"slow_mode_wait_time"`
// A Boolean value that determines whether only users that subscribe to the broadcasters channel may talk in the chat room.
//
// Set to true if the broadcaster restricts the chat room to subscribers only; otherwise, false.
// The default is false.
SubscriberMode *bool `json:"subscriber_mode"`
// A Boolean value that determines whether the broadcaster requires users to post only unique messages in the chat room.
//
// Set to true if the broadcaster allows only unique messages; otherwise, false.
// The default is false.
UniqueChatMode *bool `json:"unique_chat_mode"`
}
type UpdateChatSettingsResponse struct {
// The list of chat settings. The list contains a single object with all the settings.
Data []Settings `json:"data"`
}
// Updates the broadcasters chat settings.
//
// Requires a user access token that includes the moderator:manage:chat_settings scope.
func (c *Chat) UpdateChatSettings(ctx context.Context, params *UpdateChatSettingsParams, body *UpdateChatSettingsRequest) (*UpdateChatSettingsResponse, error) {
v, _ := query.Values(body)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/settings", 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.MethodPatch, endpoint.String(), r)
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data UpdateChatSettingsResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return &data, nil
}

View File

@ -0,0 +1,43 @@
package chat
import (
"context"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
type UpdateUserChatColorParams struct {
// The ID of the user whose chat color you want to update. This ID must match the user ID in the access token.
UserID string `url:"user_id"`
// The color to use for the user's name in chat. All users may specify one of the following named color values:
//
// blue, blue_violet, cadet_blue, chocolate, coral, dodger_blue, firebrick
// golden_rod, green, hot_pink, orange_red, red, sea_green, spring_green, yellow_green
//
// Turbo and Prime users may specify a named color or a Hex color code like #9146FF. If you use a Hex color code, remember to URL encode it.
Color string `url:"color"`
}
// Updates the color used for the users name in chat.
//
// Requires a user access token that includes the user:manage:chat_color scope.
func (c *Chat) UpdateUserChatColor(ctx context.Context, params *UpdateUserChatColorParams) error {
v, _ := query.Values(params)
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "chat/color", RawQuery: v.Encode()})
req, err := http.NewRequestWithContext(ctx, http.MethodPut, endpoint.String(), nil)
if err != nil {
return err
}
res, err := c.client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
return nil
}

View File

@ -81,3 +81,13 @@ type CurrencyAmount struct {
// The ISO-4217 three-letter currency code that identifies the type of currency in value. // The ISO-4217 three-letter currency code that identifies the type of currency in value.
Currency string `json:"currency"` Currency string `json:"currency"`
} }
type AccentColor string
const (
AccentColorPrimary AccentColor = "primary"
AccentColorBlue AccentColor = "blue"
AccentColorGreen AccentColor = "green"
AccentColorOrange AccentColor = "orange"
AccentColorPurple AccentColor = "purple"
)

View File

@ -150,3 +150,14 @@ func ToSortOrder(s *types.SortOrder) types.SortOrder {
} }
return *s return *s
} }
func AccentColor(s types.AccentColor) *types.AccentColor {
return &s
}
func ToAccentColor(s *types.AccentColor) types.AccentColor {
if s == nil {
return ""
}
return *s
}