91 lines
2.6 KiB
Go
91 lines
2.6 KiB
Go
package chat
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"net/http"
|
||
|
||
"go.fifitido.net/twitch/api/endpoint"
|
||
)
|
||
|
||
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. Don’t 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 broadcaster’s 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) {
|
||
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.Make(c.baseUrl, "chat/messages"), r)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
res, err := c.client.Do(req)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer res.Body.Close()
|
||
|
||
statusOK := res.StatusCode >= 200 && res.StatusCode < 300
|
||
if !statusOK {
|
||
return nil, fmt.Errorf("failed to send chat message (%d)", res.StatusCode)
|
||
}
|
||
|
||
var data SendChatMessageResponse
|
||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &data, nil
|
||
}
|