backend for twitch chat widgets
This commit is contained in:
parent
09c11f11a1
commit
28b9492cb3
11 changed files with 725 additions and 94 deletions
|
|
@ -38,6 +38,26 @@ type (
|
|||
LatestSubscriber *twitchLabel
|
||||
LatestCheer *twitchLabel
|
||||
}
|
||||
|
||||
ChatMessageModifier string
|
||||
chatMessage struct {
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Colour string `json:"colour,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Fragments []api.ChatMessageFragment `json:"fragments,omitempty"`
|
||||
Modifier ChatMessageModifier `json:"modifier,omitempty"`
|
||||
AnnouncementColour string `json:"announcement_colour,omitempty"`
|
||||
}
|
||||
SystemChatMessageType string
|
||||
systemChatMessage struct {
|
||||
Text string `json:"text,omitempty"`
|
||||
Type SystemChatMessageType `json:"type,omitempty"`
|
||||
}
|
||||
deleteChatMessage struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
MessageID string `json:"message_id,omitempty"`
|
||||
}
|
||||
|
||||
ServiceOptions struct {
|
||||
Host string
|
||||
|
|
@ -63,6 +83,13 @@ type (
|
|||
|
||||
eventSubSession *api.EventSubSession
|
||||
labels *twitchLabels
|
||||
|
||||
ChatC chan *chatMessage
|
||||
ChatBroadcast broadcast.BroadcastChannel[*chatMessage]
|
||||
SystemChatC chan *systemChatMessage
|
||||
SystemChatBroadcast broadcast.BroadcastChannel[*systemChatMessage]
|
||||
DeleteChatC chan *deleteChatMessage
|
||||
DeleteChatBroadcast broadcast.BroadcastChannel[*deleteChatMessage]
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -70,6 +97,20 @@ const (
|
|||
LABEL_LATEST_FOLLOWER string = "latest-follower"
|
||||
LABEL_LATEST_SUBSCRIBER string = "latest-subscriber"
|
||||
LABEL_LATEST_CHEER string = "latest-cheer"
|
||||
|
||||
CHAT_MODIFIER_NONE ChatMessageModifier = ""
|
||||
CHAT_MODIFIER_SUBSCRIBE ChatMessageModifier = "subscribe"
|
||||
CHAT_MODIFIER_CHEER ChatMessageModifier = "cheer"
|
||||
CHAT_MODIFIER_HIGHLIGHT ChatMessageModifier = "highlight"
|
||||
CHAT_MODIFIER_ANNOUNCEMENT ChatMessageModifier = "announcement"
|
||||
|
||||
SYSTEM_CHAT_FOLLOW SystemChatMessageType = "follow"
|
||||
SYSTEM_CHAT_SUBSCRIBE SystemChatMessageType = "subscribe"
|
||||
SYSTEM_CHAT_CHEER SystemChatMessageType = "cheer"
|
||||
SYSTEM_CHAT_RAID SystemChatMessageType = "raid"
|
||||
SYSTEM_CHAT_POLL SystemChatMessageType = "poll"
|
||||
SYSTEM_CHAT_SHOUTOUT SystemChatMessageType = "shoutout"
|
||||
SYSTEM_CHAT_POINT_REDEEM SystemChatMessageType = "point-redeem"
|
||||
)
|
||||
|
||||
var DATA_PATH string = path.Join(config.CONFIG_DIR, "twitch")
|
||||
|
|
@ -98,6 +139,16 @@ func New(ctx context.Context, opts ServiceOptions) (*Service, error) {
|
|||
latestCheerC := make(chan string)
|
||||
latestCheerBroadcast := broadcast.NewBroadcastChannel(
|
||||
ctx, latestCheerC)
|
||||
|
||||
chatC := make(chan *chatMessage)
|
||||
chatBroadcast := broadcast.NewBroadcastChannel(
|
||||
ctx, chatC)
|
||||
systemChatC := make(chan *systemChatMessage)
|
||||
systemChatBroadcast := broadcast.NewBroadcastChannel(
|
||||
ctx, systemChatC)
|
||||
deleteChatC := make(chan *deleteChatMessage)
|
||||
deleteChatBroadcast := broadcast.NewBroadcastChannel(
|
||||
ctx, deleteChatC)
|
||||
|
||||
srv := &Service{
|
||||
host: opts.Host,
|
||||
|
|
@ -138,6 +189,13 @@ func New(ctx context.Context, opts ServiceOptions) (*Service, error) {
|
|||
},
|
||||
RedirectURL: fmt.Sprintf("http://%s:%d/twitch/auth", opts.Host, opts.Port),
|
||||
},
|
||||
|
||||
ChatC: chatC,
|
||||
ChatBroadcast: chatBroadcast,
|
||||
SystemChatC: systemChatC,
|
||||
SystemChatBroadcast: systemChatBroadcast,
|
||||
DeleteChatC: deleteChatC,
|
||||
DeleteChatBroadcast: deleteChatBroadcast,
|
||||
}
|
||||
|
||||
if authFile, err := os.OpenFile(AUTH_FILEPATH, os.O_RDONLY, 0600); err != nil {
|
||||
|
|
@ -203,7 +261,7 @@ func (srv *Service) BindRoutes(group *gin.RouterGroup) {
|
|||
go srv.start(ctx)
|
||||
})
|
||||
|
||||
group.GET("/sse/:label", func(ctx *gin.Context) {
|
||||
group.GET("/sse/label/:label", func(ctx *gin.Context) {
|
||||
ctx.Header("connection", "keep-alive")
|
||||
|
||||
labelParam := ctx.Param("label")
|
||||
|
|
@ -250,6 +308,35 @@ func (srv *Service) BindRoutes(group *gin.RouterGroup) {
|
|||
|
||||
http.ServeFileFS(ctx.Writer, ctx.Request, pagesFS, "pages/labels.html")
|
||||
})
|
||||
|
||||
group.GET("/sse/chat", func(ctx *gin.Context) {
|
||||
ctx.Header("connection", "keep-alive")
|
||||
|
||||
chatUpdate := srv.ChatBroadcast.Subscribe()
|
||||
defer srv.ChatBroadcast.Cancel(chatUpdate)
|
||||
systemChatUpdate := srv.SystemChatBroadcast.Subscribe()
|
||||
defer srv.SystemChatBroadcast.Cancel(systemChatUpdate)
|
||||
deleteChatUpdate := srv.DeleteChatBroadcast.Subscribe()
|
||||
defer srv.DeleteChatBroadcast.Cancel(deleteChatUpdate)
|
||||
|
||||
ticker := time.NewTicker(10 * time.Millisecond)
|
||||
ctx.Stream(func(w io.Writer) bool {
|
||||
select {
|
||||
case update := <-chatUpdate:
|
||||
ctx.SSEvent("chat", update)
|
||||
case update := <-systemChatUpdate:
|
||||
ctx.SSEvent("system", update)
|
||||
case update := <-deleteChatUpdate:
|
||||
ctx.SSEvent("delete", update)
|
||||
case <-ticker.C:
|
||||
}
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
group.GET("/chat", func(ctx *gin.Context) {
|
||||
http.ServeFileFS(ctx.Writer, ctx.Request, pagesFS, "pages/chat.html")
|
||||
})
|
||||
}
|
||||
|
||||
func (srv *Service) Run(ctx context.Context) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue