[eventsub] Add poll_begin, poll_end, poll_progress events

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2023-05-21 14:59:06 +02:00
parent 1ba6c0f116
commit 04648a22e0
Signed by: luzifer
GPG key ID: D91C3E91E4CAD6F5
5 changed files with 101 additions and 0 deletions

View file

@ -29,6 +29,9 @@ var (
eventTypeOutboundRaid = ptrStr("outbound_raid")
eventTypePart = ptrStr("part")
eventTypePermit = ptrStr("permit")
eventTypePollBegin = ptrStr("poll_begin")
eventTypePollEnd = ptrStr("poll_end")
eventTypePollProgress = ptrStr("poll_progress")
eventTypeRaid = ptrStr("raid")
eventTypeResub = ptrStr("resub")
eventTypeShoutoutCreated = ptrStr("shoutout_created")
@ -58,6 +61,9 @@ var (
eventTypeOutboundRaid,
eventTypePart,
eventTypePermit,
eventTypePollBegin,
eventTypePollEnd,
eventTypePollProgress,
eventTypeRaid,
eventTypeResub,
eventTypeShoutoutReceived,

View file

@ -22,6 +22,9 @@ const (
EventSubEventTypeChannelShoutoutCreate = "channel.shoutout.create"
EventSubEventTypeChannelShoutoutReceive = "channel.shoutout.receive"
EventSubEventTypeChannelUpdate = "channel.update"
EventSubEventTypeChannelPollBegin = "channel.poll.begin"
EventSubEventTypeChannelPollEnd = "channel.poll.end"
EventSubEventTypeChannelPollProgress = "channel.poll.progress"
EventSubEventTypeStreamOffline = "stream.offline"
EventSubEventTypeStreamOnline = "stream.online"
EventSubEventTypeUserAuthorizationRevoke = "user.authorization.revoke"
@ -86,6 +89,29 @@ type (
FollowedAt time.Time `json:"followed_at"`
}
EventSubEventPoll struct {
ID string `json:"id"`
BroadcasterUserID string `json:"broadcaster_user_id"`
BroadcasterUserLogin string `json:"broadcaster_user_login"`
BroadcasterUserName string `json:"broadcaster_user_name"`
Title string `json:"title"`
Choices []struct {
ID string `json:"id"`
Title string `json:"title"`
ChannelPointsVotes int `json:"channel_points_votes"`
Votes int `json:"votes"`
} `json:"choices"`
ChannelPointsVoting struct {
IsEnabled bool `json:"is_enabled"`
AmountPerVote int `json:"amount_per_vote"`
} `json:"channel_points_voting"`
StartedAt time.Time `json:"started_at"` // begin, progress, end
EndsAt time.Time `json:"ends_at,omitempty"` // begin, progress
Status string `json:"status,omitempty"` // end -- enum(completed, archived, terminated)
EndedAt time.Time `json:"ended_at,omitempty"` // end
}
EventSubEventRaid struct {
FromBroadcasterUserID string `json:"from_broadcaster_user_id"`
FromBroadcasterUserLogin string `json:"from_broadcaster_user_login"`

View file

@ -11,6 +11,7 @@ const (
ScopeChannelManageRedemptions = "channel:manage:redemptions"
ScopeChannelManageVIPS = "channel:manage:vips"
ScopeChannelManageWhispers = "user:manage:whispers"
ScopeChannelReadPolls = "channel:read:polls"
ScopeChannelReadRedemptions = "channel:read:redemptions"
ScopeChannelReadSubscriptions = "channel:read:subscriptions"
ScopeModeratorManageAnnoucements = "moderator:manage:announcements"

View file

@ -149,6 +149,27 @@ func (t *twitchWatcher) getTopicRegistrations(userID string) []topicRegistration
AnyScope: true,
Hook: t.handleEventSubChannelPointCustomRewardRedemptionAdd,
},
{
Topic: twitch.EventSubEventTypeChannelPollBegin,
Condition: twitch.EventSubCondition{BroadcasterUserID: userID},
RequiredScopes: []string{twitch.ScopeChannelReadPolls, twitch.ScopeChannelManagePolls},
AnyScope: true,
Hook: t.handleEventSubChannelPollChange(eventTypePollBegin),
},
{
Topic: twitch.EventSubEventTypeChannelPollEnd,
Condition: twitch.EventSubCondition{BroadcasterUserID: userID},
RequiredScopes: []string{twitch.ScopeChannelReadPolls, twitch.ScopeChannelManagePolls},
AnyScope: true,
Hook: t.handleEventSubChannelPollChange(eventTypePollEnd),
},
{
Topic: twitch.EventSubEventTypeChannelPollProgress,
Condition: twitch.EventSubCondition{BroadcasterUserID: userID},
RequiredScopes: []string{twitch.ScopeChannelReadPolls, twitch.ScopeChannelManagePolls},
AnyScope: true,
Hook: t.handleEventSubChannelPollChange(eventTypePollProgress),
},
{
Topic: twitch.EventSubEventTypeChannelShoutoutCreate,
Condition: twitch.EventSubCondition{BroadcasterUserID: userID, ModeratorUserID: userID},
@ -238,6 +259,42 @@ func (t *twitchWatcher) handleEventSubChannelUpdate(m json.RawMessage) error {
return nil
}
func (t *twitchWatcher) handleEventSubChannelPollChange(event *string) func(json.RawMessage) error {
return func(m json.RawMessage) error {
var payload twitch.EventSubEventPoll
if err := json.Unmarshal(m, &payload); err != nil {
return errors.Wrap(err, "unmarshalling event")
}
fields := plugins.FieldCollectionFromData(map[string]any{
"channel": "#" + payload.BroadcasterUserLogin,
"hasChannelPointVoting": payload.ChannelPointsVoting.IsEnabled,
"title": payload.Title,
})
logger := log.WithFields(log.Fields(fields.Data()))
switch event {
case eventTypePollBegin:
logger.Info("Poll started")
case eventTypePollEnd:
logger.WithField("status", payload.Status).Info("Poll ended")
case eventTypePollProgress:
// Lets not spam the info-level-log with every single vote but
// provide them for bots with debug-level-logging
logger.Debug("Poll changed")
}
// Set after logging not to spam logs with full payload
fields.Set("poll", payload)
go handleMessage(ircHdl.Client(), nil, event, fields)
return nil
}
}
func (t *twitchWatcher) handleEventSubShoutoutCreated(m json.RawMessage) error {
var payload twitch.EventSubEventShoutoutCreated
if err := json.Unmarshal(m, &payload); err != nil {

View file

@ -128,6 +128,17 @@ Fields:
- `user` - The login-name of the user who **gave** the permit
- `to` - The username who got the permit
## `poll_begin` / `poll_end` / `poll_progress`
A poll was started / was ended / had changes in the given channel.
Fields:
- `channel` - The channel the event occurred in
- `poll` - The poll object describing the poll, see schema in [`pkg/twitch/eventsub.go#L92`](https://github.com/Luzifer/twitch-bot/blob/master/pkg/twitch/eventsub.go#L92)
- `status` - The status of the poll (one of `completed`, `terminated` or `archived`) - only available in `poll_end`
- `title` - The title of the poll the event was generated for
## `raid`
The channel was raided by another user.