StreamGremlin’s code
StreamGremlin is free and open source under the Apache License 2.0. Its Go module is named code.streamgremlin.com/streamgremlin, so the name stays the same wherever the code is kept. Today it’s on GitHub.
-
Get the code
git clone https://github.com/shawnbutts/StreamGremlin.gitCONTRIBUTING.md says what to install and how to build the app.
make verifyruns every check. -
The command line
go install code.streamgremlin.com/streamgremlin/cmd/streamgremlin@latestNeeds Go 1.27 or newer. It talks to the StreamGremlin app running on the same computer; the app itself comes from the download page.
-
Help make it better
Report a bug or an idea in GitHub’s issues, and a security problem privately. Every commit is signed off under the Developer Certificate of Origin.
Programs
What’s built from this code. The desktop app is a module of its own, code.streamgremlin.com/streamgremlin/cmd/desktop.
| Import path | What it is |
|---|---|
cmd/desktop | Command desktop is the StreamGremlin desktop app: the engine plus a window. |
cmd/mockdiscord | Command mockdiscord runs a stand-in for Discord's webhooks, to try StreamGremlin's Discord posts without Discord. |
cmd/mockobs | Command mockobs runs a stand-in for OBS's WebSocket server, to try StreamGremlin without OBS. |
cmd/mocktwitch | Command mocktwitch runs a stand-in for Twitch's sign-in server, to try StreamGremlin without a registered Twitch app. |
cmd/mockyoutube | Command mockyoutube runs a stand-in for Google's sign-in and YouTube's Data API, to try StreamGremlin's YouTube sign-in without Google. |
cmd/notices | Command notices writes THIRD-PARTY-LICENSES.txt: the licence of every Go module built into the app or the command line, on macOS, Windows or Linux. |
cmd/release | Command release makes the pieces of StreamGremlin's installers that need code, for make release (D-084). |
cmd/screenshots | Command screenshots photographs the desktop app for the website and its Help (M9 slice 4, D-112). |
cmd/site | Command site builds StreamGremlin's website into a folder the user hosts (M9 slice 4, D-112). |
cmd/streamgremlin | Command streamgremlin is StreamGremlin's command line. |
Packages
StreamGremlin’s own parts, under internal/: Go lets only StreamGremlin import them. ARCHITECTURE.md says how they fit together.
| Import path | What it is |
|---|---|
internal/actions | Package actions registers the steps workflows can use, on top of the Twitch and OBS services. |
internal/ads | Package ads asks Twitch for ad breaks and snoozes, and records what it asked and what Twitch said happened, apart (docs/adr/0024-ads.md). |
internal/api | Package api is the authenticated local API. |
internal/audience | Package audience says who's around while you're live (M6 slice 7, D-102): every few minutes, the people who spoke in chat lately, on Twitch and YouTube ("active chatters"), and each minute Twitch's viewer count when it changes enough. |
internal/backup | Package backup makes, checks and restores backups of the data folder (docs/adr/0012-backups-and-retention.md). |
internal/banlists | Package banlists keeps the streamer's own ban lists and applies them to Twitch (M8 slice 2, D-106, docs/adr/0049-ban-lists.md). |
internal/brand | Package brand holds the product name and every name derived from it. |
internal/buildinfo | Package buildinfo reports the version the binary was built as. |
internal/buttons | Package buttons keeps the streamer's buttons (M7, D-075): the Live screen shows them, and later the Stream Deck presses them. |
internal/chat | Package chat holds what chat means on every platform, starting with recognising a command such as "!so @friend". |
internal/chatsend | Package chatsend sends one chat message to Twitch, YouTube or both (M6 slice 3, D-098): the send box on Live, workflows' "Send a chat message" and the API all use it. |
internal/client | Package client calls the local API from the command line. |
internal/clients | Package clients pairs outside programs with the engine and gives each its own API token (M7 slice 4; docs/adr/0042-paired-clients.md). |
internal/commands | Package commands keeps one answer per chat command (docs/adr/0011-command-ownership.md). |
internal/datadir | Package datadir finds, creates and locks the data folder: the one place StreamGremlin keeps its database, API token, logs and backups. |
internal/desktop | Package desktop is the desktop app's side of the engine: it serves the UI and hands the UI's /v1/* requests to the API in-process, adding the token. |
internal/discord | Package discord posts to Discord channels through webhooks (D-089): a link Discord makes for one channel, which needs no bot account. |
internal/earning | Package earning pays points for taking part (docs/adr/0033-earning-rules.md): chatting (with a wait between awards per viewer), a first follow (once per viewer, ever), subscribing and resubscribing by tier, gifting subs (to the gifter), and cheering bits. |
internal/events | Package events is the event inbox: every outside or simulated event is checked, stored once in arrival order, and readable from any position (docs/adr/0004-events.md). |
internal/filters | Package filters catches spam in chat and acts on it as the streamer (D-085): links, capitals, symbols, emotes, repeats and the streamer's own words. |
internal/firstwords | Package firstwords finds each viewer's first chat message of a stream and adds a chat.first_words.received event for it (docs/adr/0021-first-words.md). |
internal/followbots | Package followbots finds follows that look like follow bots, for the streamer to review (M8 slice 5, D-109): Twitch follows from accounts made only days before they followed, that never chatted, especially when several came within minutes. |
internal/giveaways | Package giveaways runs chat giveaways (docs/adr/0025-giveaways.md): viewers enter with a chat command, every entry has the same chance (unless subscribers were given more, said in chat), the entry list is fingerprinted when entries close, and each winner is drawn with crypto/rand and recorded so anyone can check the draw. |
internal/gives | Package gives gives points to everyone in a group at once (docs/adr/0035-giving-to-everyone.md): everyone in chat (Twitch's chatter list), everyone who chatted in the last N minutes, or subscribers (Twitch's subscriber list). |
internal/host | Package host starts and stops the engine: data folder lock, database, services and the local API. |
internal/links | Package links joins a Twitch viewer and a YouTube viewer who are one person (M6 slice 6, D-101, docs/adr/0048-viewer-links.md). |
internal/logging | Package logging sets up structured logs to stderr and to a file in the data folder. |
internal/lua | Package lua runs streamers' Lua scripts in separate worker processes, with time and memory limits (docs/adr/0037-lua-scripts.md). |
internal/maintenance | Package maintenance keeps the data folder tidy while the engine runs (docs/adr/0012-backups-and-retention.md): a backup every day, keeping the newest few, and a sweep of old events and finished runs. |
internal/mockdiscord | Package mockdiscord is a stand-in for Discord's webhook endpoints (D-089): Get Webhook with Token and Execute Webhook, as Discord's reference documents them, for tests and for trying StreamGremlin without Discord. |
internal/mockobs | Package mockobs is a stand-in for OBS's obs-websocket 5 server, for tests and for trying StreamGremlin without OBS. |
internal/mocktwitch | Package mocktwitch is a stand-in for Twitch's OAuth server (id.twitch.tv), for tests and for trying the app without a real Twitch app. |
internal/mockyoutube | Package mockyoutube is a stand-in for Google's sign-in and the parts of YouTube's Data API StreamGremlin uses, for tests and to try StreamGremlin without Google (M6, D-096). |
internal/moderation | Package moderation sends the streamer's moderating requests to Twitch or YouTube and records each one with the platform's answer (M7 slice 3, M6 slice 5; docs/adr/0041-moderation-record.md). |
internal/notices | Package notices collects the licences of the Go modules built into StreamGremlin's programs, for THIRD-PARTY-LICENSES.txt, and checks that THIRD-PARTY-NOTICES.md names each of them. |
internal/obs | Package obs connects to OBS Studio over obs-websocket 5: scenes, sources, filters, audio, text, media, recording, the replay buffer and screenshots, plus scene snapshots that switch back only while StreamGremlin still owns the scene (docs/adr/0007-obs.md). |
internal/overlays | Package overlays serves OBS browser sources (docs/adr/0017-alert-overlays.md). |
internal/overlays/themesounds | Package themesounds makes the built-in wheel looks' sounds (docs/adr/0036-packages-plugins-and-themes.md, D-065). |
internal/overview | Package overview works out what Home shows (D-018 in docs/DECISIONS.md): the Get set up checklist, ticked from real state and never from what the streamer clicked, and what needs the streamer now. |
internal/packages | Package packages installs, lists and removes packages: overlay themes now, Lua plugins later (docs/adr/0036-packages-plugins-and-themes.md). |
internal/plugins | Package plugins runs installed Lua plugins (docs/adr/0038-lua-plugins.md): their steps in workflows, one worker for each that's on, restarting one that dies, doing what each asks within its approved permissions, and recording every call it makes. |
internal/points | Package points keeps the points ledger (docs/adr/0032-viewers-and-points.md): append-only and double-entry. |
internal/quotes | Package quotes keeps numbered quotes from the stream (docs/adr/0014-quotes.md), as Streamer.bot's Quotes: add, show one at random or by number, edit and delete. |
internal/raidguard | Package raidguard notices a hate raid as it starts (M8 slice 3, D-107): a burst of chatters StreamGremlin has never seen, or of Twitch accounts made only days ago, within a short time, watched more closely for a while after a raid arrives. |
internal/release | Package release makes the pieces of StreamGremlin's installers that need code: the Windows icon file, the macOS app's Info.plist, and the version in the forms each system wants (D-084). |
internal/rounds | Package rounds keeps plugins' rounds (docs/adr/0039-points-for-plugins.md): viewers' stakes held for a game, paid out or refunded, exactly once. |
internal/secrets | Package secrets keeps sign-in tokens and passwords out of the database, logs and API answers (docs/adr/0003-secrets.md). |
internal/settings | Package settings stores small, typed settings documents in the settings table. |
internal/sounds | Package sounds keeps the sound library and asks the desktop app to play sounds (docs/adr/0016-sounds.md). |
internal/storage | Package storage opens the SQLite database and applies its schema. |
internal/templates | Package templates holds the ready-made workflows the gallery offers (D-019 in docs/DECISIONS.md). |
internal/timers | Package timers runs Streamer.bot-style timed actions (docs/adr/0013-timers.md): a timer goes off every so often, or on a cron schedule, and records a timers.timer.fired event that workflows match by timer_id. |
internal/twitch | Package twitch connects to Twitch: sign-in with the device code flow for the streamer's account and an optional bot account, keeping tokens fresh and valid (docs/adr/0005-twitch-sign-in.md). |
internal/variables | Package variables keeps the values workflows save between runs and restarts (docs/adr/0009-variables.md). |
internal/viewers | Package viewers keeps a record per platform account that has taken part (docs/adr/0032-viewers-and-points.md): their names, when they were first and last seen, and how much they've chatted. |
internal/wheels | Package wheels spins wheels of weighted choices (docs/adr/0030-wheels.md): the next game, a challenge, a mystery pick. |
internal/workflow | Package workflow runs streamers' automations: when an event matches a trigger, run steps (docs/adr/0008-workflows.md). |
internal/youtube | Package youtube connects to YouTube (M6, D-095, D-096): Google's sign-in for desktop apps for the streamer's channel and an optional bot channel, keeping tokens fresh, and counting the Data API's daily quota (docs/adr/0046-youtube-sign-in.md). |
internal/youtube/livechat | Package livechat is the wire format of YouTube's live chat stream, liveChatMessages.streamList over gRPC (M6 slice 2, D-097, docs/adr/0047-youtube-chat-stream.md). |