rumble-lib-go/chat.go

282 lines
7 KiB
Go
Raw Permalink Normal View History

2024-06-14 17:13:49 +00:00
package rumble
import (
"context"
"encoding/json"
"github.com/r3labs/sse"
)
const (
ChatBadgeRecurringSubscription = "recurring_subscription"
ChatBadgeLocalsSupporter = "locals_supporter"
ChatTypeInit = "init"
ChatTypeMessages = "messages"
ChatTypeMuteUsers = "mute_users"
ChatTypeDeleteMessages = "delete_messages"
ChatTypeSubscriber = "locals_supporter"
ChatTypeRaiding = "raid_confirmed"
ChatTypePinMessage = "pin_message"
ChatTypeUnpinMessage = "unpin_message"
)
type ChatEventChannels struct {
ErrorCh chan error
}
type RegisterChatEventsOptions struct {
}
// TODO: for every true bool, create channel, otherwise nil.
// TODO: always create error channel
func RegisterChatEvents(opts RegisterChatEventsOptions) *ChatEventChannels {
}
type chatClient struct {
cancel context.CancelFunc
sseCancel context.CancelFunc
sseCl *sse.Client
sseEvent chan *sse.Event
}
type RawChatEventChannel struct {
ID string `json:"id"`
Image1 string `json:"image.1"`
Link string `json:"link"`
Username string `json:"username"`
}
type RawChatEventBlockData struct {
Text string `json:"text"`
}
type RawChatEventBlock struct {
Data RawChatEventBlockData `json:"data"`
Type string `json:"type"`
}
type RawChatEventNotification struct {
Badge string `json:"badge"`
Text string `json:"text"`
}
type RawChatEventRaidNotification struct {
StartTs int64 `json:"start_ts"`
}
type RawChatEventRant struct {
Duration int `json:"duration"`
ExpiresOn string `json:"expires_on"`
PriceCents int `json:"price_cents"`
}
type RawChatEventMessage struct {
Blocks []RawChatEventBlock `json:"blocks"`
ChannelID *int64 `json:"channel_id"`
ID string `json:"id"`
Notification *RawChatEventNotification `json:"notification"`
RaidNotification *RawChatEventRaidNotification `json:"raid_notification"`
Rant *RawChatEventRant `json:"rant"`
Text string `json:"text"`
Time string `json:"time"`
UserID string `json:"user_id"`
}
type RawChatEventUser struct {
Badges []string `json:"badges"`
Color string `json:"color"`
ID string `json:"id"`
Image1 string `json:"image.1"`
IsFollower bool `json:"is_follower"`
Link string `json:"link"`
Username string `json:"username"`
}
type RawChatEventData struct {
Channels []RawChatEventChannel `json:"channels"`
Messages []RawChatEventMessage `json:"messages"`
Users []RawChatEventUser `json:"users"`
}
type RawChatEvent struct {
Data RawChatEventData `json:"data"`
RequestID string `json:"request_id"`
Type string `json:"type"`
}
type RawChatEventAny struct {
Data any `json:"data"`
Type string `json:"type"`
}
type RawChatEventDataNoChannels struct {
// Channels [][]string `json:"channels"`
Channels [][]any `json:"channels"`
Messages []RawChatEventMessage `json:"messages"`
Users []RawChatEventUser `json:"users"`
}
type RawChatEventNoChannels struct {
Data RawChatEventDataNoChannels `json:"data"`
RequestID string `json:"request_id"`
Type string `json:"type"`
}
type ChatBase struct {
Data any `json:"data"`
Type string `json:"type"`
}
func (rce RawChatEvent) users() map[string]RawChatEventUser {
uMap := map[string]RawChatEventUser{}
for _, user := range rce.Data.Users {
uMap[user.ID] = user
}
return uMap
}
func (rce RawChatEvent) channels() map[string]RawChatEventChannel {
cMap := map[string]RawChatEventChannel{}
for _, channel := range rce.Data.Channels {
cMap[channel.ID] = channel
}
return cMap
}
// func (rce RawChatEvent) parse() ([]ChatEvent, error) {
// events := []ChatEvent{}
// users := rce.users()
// channels := rce.channels()
// for _, message := range rce.Data.Messages {
// var event ChatEvent
// user, exists := users[message.UserID]
// if !exists {
// return nil, fmt.Errorf("missing user information for user ID: %s", message.UserID)
// }
// event.Badges = user.Badges
// event.Color = user.Color
// event.ImageUrl = user.Image1
// event.IsFollower = user.IsFollower
// if message.RaidNotification != nil {
// event.Raid = true
// }
// if message.Rant != nil {
// event.Rant = message.Rant.PriceCents
// }
// if message.Notification != nil {
// if message.Notification.Badge == ChatBadgeRecurringSubscription {
// event.Sub = true
// }
// }
// event.Text = message.Text
// t, err := time.Parse(time.RFC3339, message.Time)
// if err != nil {
// return nil, fmt.Errorf("error parsing message time: %v", err)
// }
// event.Time = t
// event.Type = rce.Type
// event.Username = user.Username
// if message.ChannelID != nil {
// cid := strconv.Itoa(int(*message.ChannelID))
// channel, exists := channels[cid]
// if !exists {
// return nil, fmt.Errorf("missing channel information for channel ID: %s", cid)
// }
// event.ImageUrl = channel.Image1
// event.ChannelName = channel.Username
// }
// events = append(events, event)
// }
// return events, nil
// }
// type ChatEvent struct {
// Badges []string
// ChannelName string
// Color string
// ImageUrl string
// Init bool
// IsFollower bool
// Raid bool
// Rant int
// Sub bool
// Text string
// Time time.Time
// Type string
// Username string
// }
func (cl *chatClient) start(ctx context.Context, eventCh chan *sse.Event) {
for {
select {
case <-ctx.Done():
cl.sseCancel()
return
case event := <-eventCh:
if event == nil {
// handleError(fmt.Errorf("received nil event"))
} else {
cl.handleEvent(event)
// chats, err := parseEvent(event.Data)
// if err != nil {
// handleError(err)
// } else {
// for _, chat := range chats {
// handle(chat)
// }
// }
}
}
}
}
func (cl *chatClient) handleEvent(e *sse.Event) {
var base ChatBase
err := json.Unmarshal(e, &base)
if err != nil {
// send error
return
}
}
// func parseEvent(event []byte) ([]ChatEvent, error) {
// var rce RawChatEvent
// err := json.Unmarshal(event, &rce)
// if err != nil {
// var rcenc RawChatEventNoChannels
// errnc := json.Unmarshal(event, &rcenc)
// if errnc != nil {
// var rcea RawChatEventAny
// errany := json.Unmarshal(event, &rcea)
// if errany != nil {
// return nil, fmt.Errorf("error un-marshaling event: %v", err)
// }
// // ChatEvent type not supported, return empty events
// return []ChatEvent{}, nil
// }
// rce.Data.Messages = rcenc.Data.Messages
// rce.Data.Users = rcenc.Data.Users
// rce.RequestID = rcenc.RequestID
// rce.Type = rcenc.Type
// }
// events, err := rce.parse()
// if err != nil {
// return nil, fmt.Errorf("error parsing raw chat event: %v", err)
// }
// return events, nil
// }