Documentation ¶
Overview ¶
Package eventsub implements a http.Handler for processing Twitch EventSub notifications and validation requests (Handler) and provides a client for interacting with the EventSub API (Client).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var (
ErrEmptySubscriptionVersion = errors.New("empty subscription version")
)
Functions ¶
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func NewClient ¶
func NewClient(credentials Credentials) *Client
NewClient creates a new Client with the given Credentials provider.
func NewClientHTTP ¶
func NewClientHTTP(credentials Credentials, client *http.Client) *Client
NewClientHTTP creates a new Client with the given Credentials provider and http.Client instance.
func (*Client) GetSubscriptions ¶
func (s *Client) GetSubscriptions(ctx context.Context, statusFilter Status) (*bindings.RequestStatus, error)
GetSubscriptions returns all EventSub subscriptions. If statusFilter != StatusAny, it will apply the filter to the query.
func (*Client) Subscribe ¶
func (s *Client) Subscribe(ctx context.Context, srq *SubRequest) (*bindings.RequestStatus, error)
Subscribe creates a new Webhook subscription.
type Credentials ¶
type Credentials interface { ClientID(ctx context.Context) (string, error) AppToken(ctx context.Context) (string, error) }
Credentials represents a method of obtaining Twitch API client credentials
func NewStaticCredentials ¶
func NewStaticCredentials(clientID string, appToken string) Credentials
NewStaticCredentials creates a Credentials instance with a fixed ClientID string and AppToken string.
This Credentials implementation should only be used for development as the app token will eventually expire and API calls will subsequently fail.
type EventHandler ¶
type EventHandler[EventMessage any] func(headers bindings.NotificationHeaders, sub bindings.Subscription, event EventMessage)
EventHandler is an event callback to process a notification from EventSub.
type Handler ¶
type Handler struct { // VerifyChallenge is called to determine whether a subscription challenge // should be accepted. VerifyChallenge func(context.Context, *bindings.NotificationHeaders, *bindings.SubscriptionChallenge) bool // IDTracker used to deduplicate notifications. IDTracker IDTracker // OnDuplicateNotification is called when the provided IDTracker rejects a // EventSub notification as duplicate. Completes before returning a response // to Twitch, so this function should not take too long to execute. OnDuplicateNotification func(context.Context, *bindings.NotificationHeaders) // BeforeHandleEvent is called with the request context, the notification // headers, raw event notification body. Completes before executing the event // handler. BeforeHandleEvent func(context.Context, *bindings.NotificationHeaders, *bindings.EventNotification) HandleChannelUpdate EventHandler[bindings.EventChannelUpdate] `eventsub-type:"channel.update" eventsub-version:"2"` HandleChannelFollow EventHandler[bindings.EventChannelFollow] `eventsub-type:"channel.follow" eventsub-version:"2"` HandleChannelSubscribe EventHandler[bindings.EventChannelSubscribe] `eventsub-type:"channel.subscribe" eventsub-version:"1"` HandleChannelSubscriptionEnd EventHandler[bindings.EventChannelSubscriptionEnd] `eventsub-type:"channel.subscription.end" eventsub-version:"1"` HandleChannelSubscriptionGift EventHandler[bindings.EventChannelSubscriptionGift] `eventsub-type:"channel.subscription.gift" eventsub-version:"1"` HandleChannelSubscriptionMessage EventHandler[bindings.EventChannelSubscriptionMessage] `eventsub-type:"channel.subscription.message" eventsub-version:"1"` HandleChannelCheer EventHandler[bindings.EventChannelCheer] `eventsub-type:"channel.cheer" eventsub-version:"1"` HandleChannelRaid EventHandler[bindings.EventChannelRaid] `eventsub-type:"channel.raid" eventsub-version:"1"` HandleChannelBan EventHandler[bindings.EventChannelBan] `eventsub-type:"channel.ban" eventsub-version:"1"` HandleChannelUnban EventHandler[bindings.EventChannelUnban] `eventsub-type:"channel.unban" eventsub-version:"1"` HandleChannelModeratorAdd EventHandler[bindings.EventChannelModeratorAdd] `eventsub-type:"channel.moderator.add" eventsub-version:"1"` HandleChannelModeratorRemove EventHandler[bindings.EventChannelModeratorRemove] `eventsub-type:"channel.moderator.remove" eventsub-version:"1"` HandleChannelPointsRewardAdd EventHandler[bindings.EventChannelPointsRewardAdd] `eventsub-type:"channel.channel_points_custom_reward.add" eventsub-version:"1"` HandleChannelPointsRewardUpdate EventHandler[bindings.EventChannelPointsRewardUpdate] `eventsub-type:"channel.channel_points_custom_reward.update" eventsub-version:"1"` HandleChannelPointsRewardRemove EventHandler[bindings.EventChannelPointsRewardRemove] `eventsub-type:"channel.channel_points_custom_reward.remove" eventsub-version:"1"` HandleChannelPointsRewardRedemptionAdd EventHandler[bindings.EventChannelPointsRewardRedemptionAdd] `eventsub-type:"channel.channel_points_custom_reward_redemption.add" eventsub-version:"1"` HandleChannelPointsRewardRedemptionUpdate EventHandler[bindings.EventChannelPointsRewardRedemptionUpdate] `eventsub-type:"channel.channel_points_custom_reward_redemption.update" eventsub-version:"1"` HandleChannelPollBegin EventHandler[bindings.EventChannelPollBegin] `eventsub-type:"channel.poll.begin" eventsub-version:"1"` HandleChannelPollProgress EventHandler[bindings.EventChannelPollProgress] `eventsub-type:"channel.poll.progress" eventsub-version:"1"` HandleChannelPollEnd EventHandler[bindings.EventChannelPollEnd] `eventsub-type:"channel.poll.end" eventsub-version:"1"` HandleChannelPredictionBegin EventHandler[bindings.EventChannelPredictionBegin] `eventsub-type:"channel.prediction.begin" eventsub-version:"1"` HandleChannelPredictionProgress EventHandler[bindings.EventChannelPredictionProgress] `eventsub-type:"channel.prediction.progress" eventsub-version:"1"` HandleChannelPredictionLock EventHandler[bindings.EventChannelPredictionLock] `eventsub-type:"channel.prediction.lock" eventsub-version:"1"` HandleChannelPredictionEnd EventHandler[bindings.EventChannelPredictionEnd] `eventsub-type:"channel.prediction.end" eventsub-version:"1"` HandleDropEntitlementGrant EventHandler[bindings.EventDropEntitlementGrant] `eventsub-type:"drop.entitlement.grant" eventsub-version:"1"` HandleExtensionBitsTransactionCreate EventHandler[bindings.EventBitsTransactionCreate] `eventsub-type:"extension.bits_transaction.create" eventsub-version:"1"` HandleGoalBegin EventHandler[bindings.EventGoals] `eventsub-type:"channel.goal.begin" eventsub-version:"1"` HandleGoalProgress EventHandler[bindings.EventGoals] `eventsub-type:"channel.goal.progress" eventsub-version:"1"` HandleGoalEnd EventHandler[bindings.EventGoals] `eventsub-type:"channel.goal.end" eventsub-version:"1"` HandleHypeTrainBegin EventHandler[bindings.EventHypeTrainBegin] `eventsub-type:"channel.hype_train.begin" eventsub-version:"1"` HandleHypeTrainProgress EventHandler[bindings.EventHypeTrainProgress] `eventsub-type:"channel.hype_train.progress" eventsub-version:"1"` HandleHypeTrainEnd EventHandler[bindings.EventHypeTrainEnd] `eventsub-type:"channel.hype_train.end" eventsub-version:"1"` HandleStreamOnline EventHandler[bindings.EventStreamOnline] `eventsub-type:"stream.online" eventsub-version:"1"` HandleStreamOffline EventHandler[bindings.EventStreamOffline] `eventsub-type:"stream.offline" eventsub-version:"1"` HandleUserUpdate EventHandler[bindings.EventUserUpdate] `eventsub-type:"user.update" eventsub-version:"1"` HandleUserAuthorizationGrant EventHandler[bindings.EventUserAuthorizationGrant] `eventsub-type:"user.authorization.grant" eventsub-version:"1"` HandleUserAuthorizationRevoke EventHandler[bindings.EventUserAuthorizationRevoke] `eventsub-type:"user.authorization.revoke" eventsub-version:"1"` HandleChannelChatMessage EventHandler[bindings.EventChannelChatMessage] `eventsub-type:"channel.chat.message" eventsub-version:"1"` HandleChannelChatClear EventHandler[bindings.EventChannelChatClear] `eventsub-type:"channel.chat.clear" eventsub-version:"1"` HandleChannelChatClearUserMessages EventHandler[bindings.EventChannelChatClearUserMessages] `eventsub-type:"channel.chat.clear_user_messages" eventsub-version:"1"` HandleChannelChatMessageDelete EventHandler[bindings.EventChannelChatMessageDelete] `eventsub-type:"channel.chat.message_delete" eventsub-version:"1"` HandleChannelChatNotification EventHandler[bindings.EventChannelChatNotification] `eventsub-type:"channel.chat.notification" eventsub-version:"1"` // ====================================================== // NOTE: Beta handlers, may break backwards-compatibility // ====================================================== HandleChannelUnbanRequestCreate EventHandler[beta.EventChannelUnbanRequestCreate] `eventsub-type:"channel.unban_request.create" eventsub-version:"beta"` HandleChannelUnbanRequestResolve EventHandler[beta.EventChannelUnbanRequestResolve] `eventsub-type:"channel.unban_request.resolve" eventsub-version:"beta"` // contains filtered or unexported fields }
Handler implements http.Handler to receive Twitch EventSub webhook requests.
Handler handles both verification of new subscriptions and dispatching of event notifications. To handle a specific event, set the corresponding HandleXXX struct field. When a notification is received and validated, the handler function will be invoked in a new goroutine.
To conditionally verify challenges, set the VerifyChallenge function.
To deduplicate EventSub notifications sent by Twitch (highly recommended), set IDTracker to proper implementation of the IDTracker interface. Set OnDuplicateNotification to perform some custom logic when a duplicate notification is detected by the set IDTracker.
To perform some logic before processing every request (e.g. log something, metrics, tracing), set BeforeHandleEvent.
func NewHandler ¶
NewHandler creates a new, empty EventSub handler. It implements http.Handler.
When passed a non-nil secret, validation of notification events will be enabled and computed using the secret.
type IDTracker ¶
type IDTracker interface { // AddAndCheckIfDuplicate returns if the ID is a duplicate and an error. AddAndCheckIfDuplicate(ctx context.Context, id string) (bool, error) }
IDTracker keeps track of EventSub Message IDs that have already been processed.
type MapTracker ¶
type MapTracker struct {
// contains filtered or unexported fields
}
MapTracker uses an in-memory map to check if a notification ID is a duplicate.
func NewMapTracker ¶
func NewMapTracker() *MapTracker
NewMapTracker creates a new MapTracker instance which uses an in-memory map to check if a notification ID is a duplicate.
func (*MapTracker) AddAndCheckIfDuplicate ¶
type Status ¶
type Status string
const ( StatusAny Status = "" // StatusEnabled indicates Twitch has verified your callback and is able to // send you notifications. StatusEnabled Status = "enabled" // StatusVerificationPending indicates Twitch is verifying that you own the // callback specified in the create subscription request. StatusVerificationPending Status = "webhook_callback_verification_pending" // StatusVerificationFailed indicates Twitch failed to verify that you own // the callback specified in the create subscription request. StatusVerificationFailed Status = "webhook_callback_verification_failed" // StatusFailuresExceeded indicates Twitch revoked your subscription because // the notification delivery failure rate was too high. StatusFailuresExceeded Status = "notification_failures_exceeded" // StatusAuthorizationRevoked indicates Twitch revoked your subscription // because the users in the condition object revoked their authorization // letting you get events on their behalf, or changed their password. StatusAuthorizationRevoked Status = "authorization_revoked" // StatusModeratorRemoved indicates The moderator that authorized the // subscription is no longer one of the broadcaster’s moderators. StatusModeratorRemoved Status = "moderator_removed" // StatusUserRemoved indicates Twitch revoked your subscription because // the users in the condition object are no longer Twitch users. StatusUserRemoved Status = "user_removed" // StatusVersionRemoved indicates Twitch revoked your subscription because // the subscription to subscription type and version is no longer supported StatusVersionRemoved Status = "version_removed" // StatusBetaMaintenance indicates Twitch revoked your subscription because // the beta subscription type was undergoing maintenance. StatusBetaMaintenance Status = "beta_maintenance" )
type SubRequest ¶
type SubRequest struct { // The type of event being subscribed to. Type string // The subscription type version. Version string // The parameters under which the event will be fired. Condition interface{} // The Webhook HTTP callback address. Callback string // The HMAC secret used to verify the event data. Secret string }
type TrackerFunc ¶
TrackerFunc is a functional adapter for the IDTracker interface.
func (TrackerFunc) AddAndCheckIfDuplicate ¶
type TwitchError ¶
type TwitchError struct { ErrorText string `json:"error"` Status int `json:"status"` Message string `json:"message"` }
TwitchError describes an error from the Twitch API.
For example:
{ "error": "Unauthorized", "status": 401, "message": "Invalid OAuth token" }
func (*TwitchError) Error ¶
func (t *TwitchError) Error() string