twitchgo

package module
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 26, 2025 License: MIT Imports: 26 Imported by: 0

README

twitchgo

twitchgo is an event-driven Twitch EventSub bot framework built on Go, providing a structured HTTP server, OAuth2 authentication flow, signature-verified webhook handling, and a pluggable event engine. The framework manages configuration, logging, deduplication of Twitch messages, and graceful shutdown routines.

This project exposes an internal OAuth login flow, accessible at /auth/login, which generates a bot access token based on your configured scopes.

Features

  • Event-driven architecture via a user-defined EventEngine
  • Webhook processing for Twitch EventSub (signature verification, HMAC validation, replay protection)
  • OAuth2 authorization flow for acquiring bot tokens
  • Configurable HTTP server with TLS support
  • Structured logging using zerolog
  • Dedupe cache for EventSub message IDs
  • Automatic configuration file creation on first run
  • Extensible routing via Chi

Installation

go get github.com/Etwodev/twitchgo

Quick Start

1. Implement an EventEngine

Your engine must implement the required callbacks—for example:

type MyEngine struct{}

func (e *MyEngine) OnChannelChatMessage(ctx context.Context, h *helix.Client, event twitchgo.Response[helix.EventSubChannelChatMessageEvent, helix.EventSubCondition]) {
    // handle chat message event
}
2. Initialize and start the bot
engine := &MyEngine{}
bot := twitchgo.New(engine)
bot.Start()

OAuth Flow

twitchgo exposes these endpoints:

GET /auth/login

Redirects the user to Twitch OAuth using:

  • Client ID from config
  • Scopes defined in config (scopes)
  • Redirect URI from config (redirectUri)
GET /auth/callback

Twitch redirects back to this endpoint after the user grants permissions.

This endpoint is protected by Basic Auth, requiring:

  • CALLBACK_USER
  • CALLBACK_PASS

The callback handler exchanges the authorization code for an access token and stores it in your engine or environment as needed.

Webhook Handling

All EventSub notifications are sent to:

POST /webhook/callback

This handler performs:

  • Required header validation
  • Timestamp freshness check
  • HMAC signature verification (CLIENT_SECRET)
  • Duplicate message detection
  • Challenge handling
  • Dispatch of notifications to your configured EventEngine

Supported events include:

  • channel.chat.message (v1) Additional types may require extending processNotification with more mappings.

Health Check

GET /healthcheck

Returns a simple HTTP 200 response for readiness/liveness checks.

Configuration

twitchgo loads configuration from:

./twitchgo.config.json

This file is created automatically on first run if not present.

Example default config
{
  "port": "7000",
  "address": "0.0.0.0",
  "experimental": false,
  "readTimeout": 15,
  "writeTimeout": 15,
  "idleTimeout": 60,
  "logLevel": "info",
  "maxHeaderBytes": 1048576,
  "enableTLS": false,
  "tlsCertFile": "",
  "tlsKeyFile": "",
  "shutdownTimeout": 15,
  "enableCORS": false,
  "allowedOrigins": [],
  "enableRequestLogging": false,
  "scopes": ["channel:moderate"],
  "redirectUri": "https://example.com",
  "clientId": "unknown"
}
Config fields
Field Description
port HTTP server port
address Bind address
experimental Enables experimental middleware/endpoints
readTimeout / writeTimeout / idleTimeout Request timeouts (seconds)
logLevel Logging level (debug, info, etc.)
maxHeaderBytes Maximum request header size
enableTLS Enables HTTPS server
tlsCertFile / tlsKeyFile Certificate and key paths
shutdownTimeout Graceful shutdown timeout (seconds)
enableCORS Enables CORS middleware
allowedOrigins Allowed CORS origins
enableRequestLogging Enables request logging middleware
scopes Twitch OAuth scopes
redirectUri OAuth redirect URL
clientId Twitch client ID

Required Environment Variables

Variable Purpose
CLIENT_SECRET Twitch application client secret used for OAuth and HMAC validation
CALLBACK_USER Username for callback Basic Auth
CALLBACK_PASS Password for callback Basic Auth

All OAuth and signature verification processes depend on these being set.

Running the Server

Local
export CLIENT_SECRET="your_twitch_secret"
export CALLBACK_USER="admin"
export CALLBACK_PASS="supersecret"

go run main.go

Server starts at:

http://0.0.0.0:7000
With TLS

Enable TLS in config:

"enableTLS": true,
"tlsCertFile": "cert.pem",
"tlsKeyFile": "key.pem"

Event Subscription

Subscriptions are created externally using the Twitch Helix API. You may use the built-in helix.Client provided via:

bot.Helix()

Ensure your EventSub transport points to:

https://<your-domain>/webhook/callback

Extending Event Types

To support additional Twitch EventSub notifications:

  1. Add your type mapping inside processNotification
  2. Unmarshal into a Response[...]
  3. Dispatch to your engine:
go b.engine.OnYourEvent(ctx, b.helix, event)

Graceful Shutdown

The bot listens for os.Interrupt and shuts down the server cleanly, respecting the configured shutdownTimeout.

Logging

twitchgo uses zerolog with a console-friendly writer. Global log level is set via configuration.

License

MIT (recommended to update with your own license if applicable).

Documentation

Index

Constants

View Source
const (
	Webhook   Method = "webhook"
	Websocket Method = "websocket"

	Enabled  Status = "enabled"
	Disabled Status = "disabled"
)

Variables

View Source
var FULL_AUTH_SCOPES = []string{
	"analytics:read:extensions",
	"analytics:read:games",
	"bits:read",
	"channel:bot",
	"channel:manage:ads",
	"channel:read:ads",
	"channel:manage:broadcast",
	"channel:read:charity",
	"channel:manage:clips",
	"channel:edit:commercial",
	"channel:read:editors",
	"channel:manage:extensions",
	"channel:read:goals",
	"channel:read:guest_star",
	"channel:manage:guest_star",
	"channel:read:hype_train",
	"channel:manage:moderators",
	"channel:read:polls",
	"channel:manage:polls",
	"channel:read:predictions",
	"channel:manage:predictions",
	"channel:manage:raids",
	"channel:read:redemptions",
	"channel:manage:redemptions",
	"channel:manage:schedule",
	"channel:read:stream_key",
	"channel:read:subscriptions",
	"channel:manage:videos",
	"channel:read:vips",
	"channel:manage:vips",
	"channel:moderate",
	"clips:edit",
	"editor:manage:clips",
	"moderation:read",
	"moderator:manage:banned_users",
	"moderator:read:blocked_terms",
	"moderator:read:chat_messages",
	"moderator:manage:blocked_terms",
	"moderator:manage:chat_messages",
	"moderator:read:chat_settings",
	"moderator:manage:chat_settings",
	"moderator:read:chatters",
	"moderator:read:followers",
	"moderator:read:guest_star",
	"moderator:manage:guest_star",
	"moderator:read:shield_mode",
	"moderator:manage:shield_mode",
	"moderator:read:shoutouts",
	"moderator:manage:shoutouts",
	"moderator:read:suspicious_users",
	"moderator:read:unban_requests",
	"moderator:manage:unban_requests",
	"moderator:read:vips",
	"moderator:read:warnings",
	"moderator:manage:warnings",
	"user:bot",
	"user:edit",
	"user:edit:broadcast",
	"user:read:blocked_users",
	"user:manage:blocked_users",
	"user:read:broadcast",
	"user:read:chat",
	"user:manage:chat_color",
	"user:read:email",
	"user:read:emotes",
	"user:read:follows",
	"user:read:moderated_channels",
	"user:read:subscriptions",
	"user:read:whispers",
	"user:manage:whispers",
	"user:write:chat",
	"chat:edit",
	"chat:read",
	"whispers:read",
}

Functions

func BuildHMACMessage added in v1.1.0

func BuildHMACMessage(messageID, timestamp string, body []byte) []byte

BuildHMACMessage constructs the message string used to compute the HMAC.

func ComputeHMAC added in v1.1.0

func ComputeHMAC(secret []byte, message []byte) string

ComputeHMAC returns the HMAC SHA-256 hex digest for the provided secret and message.

func HandleHealthCheck added in v1.1.0

func HandleHealthCheck(w http.ResponseWriter, r *http.Request)

func HandleLogin added in v1.1.0

func HandleLogin(w http.ResponseWriter, r *http.Request)

func VerifyHMAC added in v1.1.0

func VerifyHMAC(computedHex, receivedHeader string) bool

VerifyHMAC performs a constant-time comparison between the computed HMAC and the provided signature.

Types

type Bot

type Bot struct {
	// contains filtered or unexported fields
}

configuration, middleware, routers, and structured logging.

func New

func New(engine EventEngine) *Bot

New creates a new Bot instance with configuration loaded and a logger initialized.

It will fatal exit if configuration loading failb.

Example:

bot := twitchgo.New()

func (*Bot) Handle added in v1.1.0

func (b *Bot) Handle(w http.ResponseWriter, r *http.Request)

func (*Bot) HandleCallback added in v1.1.1

func (b *Bot) HandleCallback(w http.ResponseWriter, r *http.Request)

func (*Bot) Helix added in v1.1.0

func (b *Bot) Helix() *helix.Client

Helix returns the helix instance used by the bot.

Example:

helix := bot.Helix()
helix.GetUser...

func (*Bot) LoadMiddleware added in v1.1.4

func (b *Bot) LoadMiddleware(middlewares []middleware.Middleware)

LoadMiddleware appends one or more middleware instances to the server's middleware chain.

Middleware registered here will be applied globally to all routers.

Example:

srv.LoadMiddleware([]middleware.Middleware{corsMw, loggingMw})

func (*Bot) LoadRouter added in v1.1.4

func (b *Bot) LoadRouter(routers []router.Router)

LoadRouter appends one or more routers to the server's router list.

Example:

srv.LoadRouter([]router.Router{myRouter1, myRouter2})

func (*Bot) Logger

func (b *Bot) Logger() log.Logger

Logger returns the logger instance used by the bot.

Example:

logger := bot.Logger()
logger.Info().Msg("Bot logger retrieved")

func (*Bot) Routes added in v1.1.0

func (b *Bot) Routes(m *chi.Mux)

func (*Bot) Start

func (b *Bot) Start()

Start launches the HTTP server, applying configured middleware and routers, and listens for termination signals for graceful shutdown.

It blocks until the server is shut down.

Example:

bot.Start()

type ChallengeRequest added in v1.1.0

type ChallengeRequest struct {
	Challenge string `json:"challenge"`
}

type EventEngine added in v1.1.0

type EventEngine interface {
	// OnBotStart is called when the bot starts.
	// Useful for initializing connections, registering event subscriptions, or performing startup routines.
	OnBotStart(ctx context.Context, api *helix.Client)

	// OnClientLogin is called when a user logs into the client.
	// At this point, access and refresh tokens are set, allowing API calls on behalf of the user.
	OnClientLogin(ctx context.Context, api *helix.Client)

	// OnClientRefresh is called whenever an access token is refreshed.
	// This ensures the bot continues to operate with a valid token without interruption.
	OnClientRefresh(ctx context.Context, api *helix.Client)

	OnChannelChatMessage(ctx context.Context, api *helix.Client, response Response[helix.EventSubChannelChatMessageEvent, helix.EventSubCondition])
}

EventEngine defines an interface for handling various Twitch bot events.

type HelixRefreshTransport added in v1.3.0

type HelixRefreshTransport struct {
	Base   http.RoundTripper
	Client *helix.Client
	Event  EventEngine
}

func (*HelixRefreshTransport) RoundTrip added in v1.3.0

func (t *HelixRefreshTransport) RoundTrip(r *http.Request) (*http.Response, error)

type Method added in v1.1.0

type Method string

type Response added in v1.1.0

type Response[T interface{}, U interface{}] struct {
	Event        T               `json:"event"`
	Subscription Subscription[U] `json:"subscription"`
}

Request represents an EventSub subscription response.

See: https://dev.twitch.tv/docs/eventsub/eventsub-reference for more information.

type Status added in v1.1.0

type Status string

type Subscription added in v1.1.0

type Subscription[T interface{}] struct {
	ID        string    `json:"id"`
	Type      string    `json:"type"`
	Version   string    `json:"version"`
	Status    Status    `json:"status"`
	Cost      int       `json:"cost"`
	Condition T         `json:"condition"`
	CreatedAt time.Time `json:"created_at"`
}

type SubscriptionType added in v1.1.0

type SubscriptionType string
const (
	ChannelChatMessage SubscriptionType = "channel.chat.message.v1"
)

Directories

Path Synopsis
pkg
log

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL