From 6bbdb8c600aa4faf602b79233938a1a365eeac9a Mon Sep 17 00:00:00 2001 From: Satont Date: Sun, 26 Nov 2023 10:20:31 +0300 Subject: [PATCH 1/5] feat: add clear and notification events --- go.mod | 2 + go.sum | 2 - handler.go | 148 ++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 126 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index 77a2051..e7b54ac 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/dnsge/twitch-eventsub-framework go 1.17 +replace github.com/dnsge/twitch-eventsub-bindings => ../twitch-eventsub-bindings + require ( github.com/dnsge/twitch-eventsub-bindings v1.1.0 github.com/mozillazg/go-httpheader v0.3.0 diff --git a/go.sum b/go.sum index d3e7758..7aaf911 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnsge/twitch-eventsub-bindings v1.1.0 h1:11MBREP4tdcxfGNxDRSu86ASxlnMsSCo0YnLV01T0Ws= -github.com/dnsge/twitch-eventsub-bindings v1.1.0/go.mod h1:Zbj+TpgcdNu4Gj6+6KG/+A7EvWMDbzQ+UGm35P918pc= github.com/mozillazg/go-httpheader v0.3.0 h1:3brX5z8HTH+0RrNA1362Rc3HsaxyWEKtGY45YrhuINM= github.com/mozillazg/go-httpheader v0.3.0/go.mod h1:PuT8h0pw6efvp8ZeUec1Rs7dwjK08bt6gKSReGMqtdA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/handler.go b/handler.go index 5c6eac3..bdcd5f5 100644 --- a/handler.go +++ b/handler.go @@ -2,10 +2,11 @@ package eventsub_framework import ( "encoding/json" - esb "github.com/dnsge/twitch-eventsub-bindings" - "github.com/mozillazg/go-httpheader" "io" "net/http" + + esb "github.com/dnsge/twitch-eventsub-bindings" + "github.com/mozillazg/go-httpheader" ) const ( @@ -35,35 +36,74 @@ type SubHandler struct { HandleChannelFollow func(h *esb.ResponseHeaders, event *esb.EventChannelFollow) HandleUserUpdate func(h *esb.ResponseHeaders, event *esb.EventUserUpdate) - HandleChannelSubscribe func(h *esb.ResponseHeaders, event *esb.EventChannelSubscribe) - HandleChannelSubscriptionEnd func(h *esb.ResponseHeaders, event *esb.EventChannelSubscriptionEnd) - HandleChannelSubscriptionGift func(h *esb.ResponseHeaders, event *esb.EventChannelSubscriptionGift) - HandleChannelSubscriptionMessage func(h *esb.ResponseHeaders, event *esb.EventChannelSubscriptionMessage) - HandleChannelCheer func(h *esb.ResponseHeaders, event *esb.EventChannelCheer) - HandleChannelRaid func(h *esb.ResponseHeaders, event *esb.EventChannelRaid) + HandleChannelSubscribe func(h *esb.ResponseHeaders, event *esb.EventChannelSubscribe) + HandleChannelSubscriptionEnd func( + h *esb.ResponseHeaders, + event *esb.EventChannelSubscriptionEnd, + ) + HandleChannelSubscriptionGift func( + h *esb.ResponseHeaders, + event *esb.EventChannelSubscriptionGift, + ) + HandleChannelSubscriptionMessage func( + h *esb.ResponseHeaders, + event *esb.EventChannelSubscriptionMessage, + ) + HandleChannelCheer func(h *esb.ResponseHeaders, event *esb.EventChannelCheer) + HandleChannelRaid func(h *esb.ResponseHeaders, event *esb.EventChannelRaid) HandleChannelBan func(h *esb.ResponseHeaders, event *esb.EventChannelBan) HandleChannelUnban func(h *esb.ResponseHeaders, event *esb.EventChannelUnban) HandleChannelModeratorAdd func(h *esb.ResponseHeaders, event *esb.EventChannelModeratorAdd) HandleChannelModeratorRemove func(h *esb.ResponseHeaders, event *esb.EventChannelModeratorRemove) - HandleChannelPointsRewardAdd func(h *esb.ResponseHeaders, event *esb.EventChannelPointsRewardAdd) - HandleChannelPointsRewardUpdate func(h *esb.ResponseHeaders, event *esb.EventChannelPointsRewardUpdate) - HandleChannelPointsRewardRemove func(h *esb.ResponseHeaders, event *esb.EventChannelPointsRewardRemove) - HandleChannelPointsRewardRedemptionAdd func(h *esb.ResponseHeaders, event *esb.EventChannelPointsRewardRedemptionAdd) - HandleChannelPointsRewardRedemptionUpdate func(h *esb.ResponseHeaders, event *esb.EventChannelPointsRewardRedemptionUpdate) + HandleChannelPointsRewardAdd func( + h *esb.ResponseHeaders, + event *esb.EventChannelPointsRewardAdd, + ) + HandleChannelPointsRewardUpdate func( + h *esb.ResponseHeaders, + event *esb.EventChannelPointsRewardUpdate, + ) + HandleChannelPointsRewardRemove func( + h *esb.ResponseHeaders, + event *esb.EventChannelPointsRewardRemove, + ) + HandleChannelPointsRewardRedemptionAdd func( + h *esb.ResponseHeaders, + event *esb.EventChannelPointsRewardRedemptionAdd, + ) + HandleChannelPointsRewardRedemptionUpdate func( + h *esb.ResponseHeaders, + event *esb.EventChannelPointsRewardRedemptionUpdate, + ) HandleChannelPollBegin func(h *esb.ResponseHeaders, event *esb.EventChannelPollBegin) HandleChannelPollProgress func(h *esb.ResponseHeaders, event *esb.EventChannelPollProgress) HandleChannelPollEnd func(h *esb.ResponseHeaders, event *esb.EventChannelPollEnd) - HandleChannelPredictionBegin func(h *esb.ResponseHeaders, event *esb.EventChannelPredictionBegin) - HandleChannelPredictionProgress func(h *esb.ResponseHeaders, event *esb.EventChannelPredictionProgress) - HandleChannelPredictionLock func(h *esb.ResponseHeaders, event *esb.EventChannelPredictionLock) - HandleChannelPredictionEnd func(h *esb.ResponseHeaders, event *esb.EventChannelPredictionEnd) - - HandleDropEntitlementGrant func(h *esb.ResponseHeaders, event *esb.EventDropEntitlementGrant) - HandleExtensionBitsTransactionCreate func(h *esb.ResponseHeaders, event *esb.EventBitsTransactionCreate) + HandleChannelPredictionBegin func( + h *esb.ResponseHeaders, + event *esb.EventChannelPredictionBegin, + ) + HandleChannelPredictionProgress func( + h *esb.ResponseHeaders, + event *esb.EventChannelPredictionProgress, + ) + HandleChannelPredictionLock func( + h *esb.ResponseHeaders, + event *esb.EventChannelPredictionLock, + ) + HandleChannelPredictionEnd func(h *esb.ResponseHeaders, event *esb.EventChannelPredictionEnd) + + HandleDropEntitlementGrant func( + h *esb.ResponseHeaders, + event *esb.EventDropEntitlementGrant, + ) + HandleExtensionBitsTransactionCreate func( + h *esb.ResponseHeaders, + event *esb.EventBitsTransactionCreate, + ) HandleGoalBegin func(h *esb.ResponseHeaders, event *esb.EventGoals) HandleGoalProgress func(h *esb.ResponseHeaders, event *esb.EventGoals) @@ -77,7 +117,25 @@ type SubHandler struct { HandleStreamOffline func(h *esb.ResponseHeaders, event *esb.EventStreamOffline) HandleUserAuthorizationGrant func(h *esb.ResponseHeaders, event *esb.EventUserAuthorizationGrant) - HandleUserAuthorizationRevoke func(h *esb.ResponseHeaders, event *esb.EventUserAuthorizationRevoke) + HandleUserAuthorizationRevoke func( + h *esb.ResponseHeaders, + event *esb.EventUserAuthorizationRevoke, + ) + + HandleChannelChatClear func(h *esb.ResponseHeaders, event *esb.EventChannelChatClear) + HandleChannelChatClearUserMessages func( + h *esb.ResponseHeaders, + event *esb.EventChannelChatClearUserMessages, + ) + HandleChannelChatMessageDelete func( + h *esb.ResponseHeaders, + event *esb.EventChannelChatMessageDelete, + ) + + HandleChannelChatNotification func( + h *esb.ResponseHeaders, + event *esb.EventChannelChatNotification, + ) } func NewSubHandler(doSignatureVerification bool, secret []byte) *SubHandler { @@ -147,7 +205,11 @@ func (s *SubHandler) handlePost(w http.ResponseWriter, r *http.Request) { // checkIfDuplicate returns whether the IDTracker reports this notification is // a duplicate. If it is a duplicate, it writes a 2xx response and returns true. // Otherwise, it returns false. -func (s *SubHandler) checkIfDuplicate(w http.ResponseWriter, r *http.Request, h *esb.ResponseHeaders) (bool, error) { +func (s *SubHandler) checkIfDuplicate( + w http.ResponseWriter, + r *http.Request, + h *esb.ResponseHeaders, +) (bool, error) { if s.IDTracker != nil { duplicate, err := s.IDTracker.AddAndCheckIfDuplicate(r.Context(), h.MessageID) if err != nil { @@ -166,7 +228,11 @@ func (s *SubHandler) checkIfDuplicate(w http.ResponseWriter, r *http.Request, h return false, nil } -func (s *SubHandler) handleVerification(w http.ResponseWriter, bodyBytes []byte, headers *esb.ResponseHeaders) { +func (s *SubHandler) handleVerification( + w http.ResponseWriter, + bodyBytes []byte, + headers *esb.ResponseHeaders, +) { var data esb.SubscriptionChallenge if err := json.Unmarshal(bodyBytes, &data); err != nil { http.Error(w, "Invalid JSON body", http.StatusBadRequest) @@ -182,7 +248,11 @@ func (s *SubHandler) handleVerification(w http.ResponseWriter, bodyBytes []byte, } } -func (s *SubHandler) handleNotification(w http.ResponseWriter, bodyBytes []byte, h *esb.ResponseHeaders) { +func (s *SubHandler) handleNotification( + w http.ResponseWriter, + bodyBytes []byte, + h *esb.ResponseHeaders, +) { var notification esb.EventNotification if err := json.Unmarshal(bodyBytes, ¬ification); err != nil { http.Error(w, "Invalid JSON body", http.StatusBadRequest) @@ -524,6 +594,36 @@ func (s *SubHandler) handleNotification(w http.ResponseWriter, bodyBytes []byte, if s.HandleUserUpdate != nil { go s.HandleUserUpdate(h, &data) } + case "channel.chat.clear": + var data esb.EventChannelChatClear + if err := json.Unmarshal(event, &data); err != nil { + http.Error(w, "Invalid JSON body", http.StatusBadRequest) + return + } + if s.HandleChannelChatClear != nil { + go s.HandleChannelChatClear(h, &data) + } + case "channel.chat.clear_user_messages": + var data esb.EventChannelChatClearUserMessages + if err := json.Unmarshal(event, &data); err != nil { + http.Error(w, "Invalid JSON body", http.StatusBadRequest) + return + } + if s.HandleChannelChatClearUserMessages != nil { + go s.HandleChannelChatClearUserMessages(h, &data) + } + case "channel.chat.message_delete": + var data esb.EventChannelChatMessageDelete + if err := json.Unmarshal(event, &data); err != nil { + http.Error(w, "Invalid JSON body", http.StatusBadRequest) + return + } + if s.HandleChannelChatMessageDelete != nil { + go s.HandleChannelChatMessageDelete(h, &data) + } + case "channel.chat.notification": + var data esb.EventChannelChatNotification + default: http.Error(w, "Unknown notification type", http.StatusBadRequest) return From 9c5aca874cd8e698e6d2d9524cc7e09d4184d540 Mon Sep 17 00:00:00 2001 From: Satont Date: Sun, 26 Nov 2023 10:25:50 +0300 Subject: [PATCH 2/5] chore: remove local bindings replace --- go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.mod b/go.mod index e7b54ac..77a2051 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/dnsge/twitch-eventsub-framework go 1.17 -replace github.com/dnsge/twitch-eventsub-bindings => ../twitch-eventsub-bindings - require ( github.com/dnsge/twitch-eventsub-bindings v1.1.0 github.com/mozillazg/go-httpheader v0.3.0 From 59b0b1bff8a0ab326564a8a74f929a2972072c0a Mon Sep 17 00:00:00 2001 From: Satont Date: Sun, 26 Nov 2023 11:37:30 +0300 Subject: [PATCH 3/5] feat: add channel notification handler --- handler.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/handler.go b/handler.go index bdcd5f5..56368d2 100644 --- a/handler.go +++ b/handler.go @@ -623,7 +623,13 @@ func (s *SubHandler) handleNotification( } case "channel.chat.notification": var data esb.EventChannelChatNotification - + if err := json.Unmarshal(event, &data); err != nil { + http.Error(w, "Invalid JSON body", http.StatusBadRequest) + return + } + if s.HandleChannelChatNotification != nil { + go s.HandleChannelChatNotification(h, &data) + } default: http.Error(w, "Unknown notification type", http.StatusBadRequest) return From e03880fb3633bbaaf74f262381b2932dcfab8ea5 Mon Sep 17 00:00:00 2001 From: Satont Date: Sun, 26 Nov 2023 12:46:50 +0300 Subject: [PATCH 4/5] feat: use new eventsub events instead of listen from chat --- go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.mod b/go.mod index 77a2051..e7b54ac 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/dnsge/twitch-eventsub-framework go 1.17 +replace github.com/dnsge/twitch-eventsub-bindings => ../twitch-eventsub-bindings + require ( github.com/dnsge/twitch-eventsub-bindings v1.1.0 github.com/mozillazg/go-httpheader v0.3.0 From e81b26fc3ce9315019e973df29595dbf921b671a Mon Sep 17 00:00:00 2001 From: Satont Date: Sun, 26 Nov 2023 13:18:46 +0300 Subject: [PATCH 5/5] chore: remove replace --- go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.mod b/go.mod index e7b54ac..77a2051 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/dnsge/twitch-eventsub-framework go 1.17 -replace github.com/dnsge/twitch-eventsub-bindings => ../twitch-eventsub-bindings - require ( github.com/dnsge/twitch-eventsub-bindings v1.1.0 github.com/mozillazg/go-httpheader v0.3.0