282 lines
7 KiB
Go
282 lines
7 KiB
Go
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
|
|
// }
|