Plugins are enabled or disabled under plugins..enabled in config.yaml. !help prints a compact one-line index; use !help for details. !alias prints aliases without flooding the channel.
- correction: IRC-style spelling corrections
- banter: optional replies when GoBot is directly addressed
- welcome: optional, probability-based join greetings with a per-channel cooldown
- urltitle: page titles and YouTube metadata
- weather: Open-Meteo weather, no key required
- news: NewsAPI headlines and search
- ask: source-grounded questions with optional AI rewriting
- wikipedia: English Wikipedia summaries
- horoscope: daily zodiac horoscopes
- urban: Urban Dictionary definitions
- reddit: compact Reddit post metadata
- foods: local food, cuisine, beer, coffee, tea, and wine suggestions
- sports: broad local sports suggestions
- car: broad local make, model, and production-span suggestions
- define: short English dictionary definitions
- calc: safe local arithmetic and unit conversion
- github: compact public GitHub repository, issue, release, user, commit, and search lookups
- grab: save, replay, search, and randomly show memorable channel lines
- linux: current Linux kernel release lines from kernel.org
- weapons: high-level local firearm and weapons-name catalog
- status: local connection, uptime, and counter status
- xkcd: latest or numbered XKCD comics
- lastfm: current or recently played Last.fm tracks
- cats: short cat facts
- eightball: customizable Magic 8-Ball answers
- fun: local yo-momma jokes, one-liners, puns, and wisdom
- attack: playful target-based actions and messages
- cheer: family-friendly cheers
- seen, tell, karma, and dice: channel utilities
- quote, choose, and time: lightweight utilities
- channelstats: persistent per-channel statistics
- help and alias: command discovery
- blackjack, pool, poll, remind, and duckhunt: games and activities
Most command responses are rate-limited. See Configuration.
With banter enabled, address the bot in a channel:
GoBot hello, how are you?
@GoBot hello
Banter is intentionally random and will not respond to every message. Commands can be sent in a channel or by direct message where supported:
!help
!weather Seattle
!quote
!tell username hello
!tell queues a message for the next time the addressed nickname speaks:
!tell GoBot you are awesome
GoBot confirms that it will tell GoBot the next time they speak. When GoBot next sends a message, the pending message is delivered in that channel or conversation. Pending messages are stored in BoltDB and survive restarts.
If the addressed nickname is GoBot's own configured nickname, it replies with a short humorous message instead of queueing a message for itself. A queued tell is delivered when that nickname next sends either a channel message or a private message to GoBot.
The optional welcome plugin posts a short, playful line when another user
joins a channel. It is disabled by default. Enable it in config.yaml:
plugins:
welcome:
enabled: true
probability: 0.15
cooldown_seconds: 120
messages_file: "data/welcome.txt"probability is the chance that an individual join produces a greeting. The
cooldown is tracked separately for each channel, so a busy channel cannot be
flooded by a greeting for every arrival. The catalog contains short original
lines and supports the {nick} placeholder:
The Evil Has Landed.
A wild Pzycho appeared!
There is no command to enable it at runtime. Once enabled, it applies to channels where GoBot is present. The bot's own join is ignored, and the normal post-join warmup also suppresses replayed events during startup.
Use familiar IRC correction syntax immediately after the message to correct:
I need a wiiifee
s/wiiifee/wife/
Add /g for every matching occurrence:
s/wiiifee/wife/g
The correction history is kept in memory and controlled by history_size.
When someone posts an HTTP or HTTPS URL, GoBot fetches a title. It prefers Open Graph and Twitter metadata, then falls back to the HTML title element. YouTube links are formatted with title, channel, and duration when available:
[YouTube] Video title | Channel: Example Channel | 1m 37s
An optional YouTube Data API v3 key gives the most reliable title, channel, and duration data. Without it, GoBot uses public oEmbed, player metadata, and HTML fallbacks; restricted or dynamically rendered videos may not expose duration. Sites that block automated requests may not provide a title. Access-denied and error titles are suppressed rather than posted.
Keep the key out of Git:
BOT_YOUTUBE_API_KEY=your-youtube-data-api-keyThe key needs YouTube Data API v3 enabled. GoBot requests only snippet and contentDetails for the linked video.
Weather uses Open-Meteo and does not require an API key:
!weather Seattle
!wx Seattle
!forecast Seattle
!temp Seattle
Set default_units to metric or imperial.
Fetch today's horoscope by zodiac sign. The sign is saved for your nickname:
!horoscope aries
!horoscope
!zodiac
The public daily horoscope API requires no key. GoBot keeps the response to one
compact IRC message and allows a fuller paragraph when it fits the configured
preview length. If the paragraph is longer, it is shortened and gets a
readable Read more link for the sign's daily horoscope page. The preview
length defaults to 360 characters and can be changed with
plugins.horoscope.max_summary_length (120–400 characters). For example, a
Virgo response links to the Virgo daily horoscope
page.
Look up a slang term. Add a result number for another definition:
!urban yeet
!u yeet 2
!ud doomscrolling
GoBot returns one shortened definition and permalink. User-submitted text is
treated as untrusted: IRC control characters are stripped and output length
is bounded. The 1/10 notation means the first definition out of ten returned
by Urban Dictionary; it is not random. Add a number to select another result,
such as !urban yeet 2.
!xkcd
!xkcd latest
!xkcd 353
GoBot uses XKCD's official JSON interface and returns the number, title, date, and link. The interface supports latest and numbered comics, not full-text search.
Last.fm requires a free API key:
plugins:
lastfm:
enabled: true
api_key: ""Use a Last.fm username once; GoBot remembers it for your nickname:
!lastfm username
!lastfm
!np
The response reports the current track or the most recently played track. GoBot does not collect passwords or OAuth credentials.
!cats
!cat
The Cats plugin uses the public catfact.ninja endpoint, requires no key, returns one cleaned and length-limited message, and does not download images.
These commands use only GoBot's local state and do not call an external service:
!status
!uptime
!ping
The response includes connection state, process uptime, configured network, and message/command counters. It is useful for a quick IRC-side health check.
Look up one English word using the public Free Dictionary API:
!define resilient
!def resilient
!dictionary resilient
GoBot returns the first concise definition and part of speech in one bounded message. No API key is required. The lookup is English-only and third-party text is cleaned before it is sent to IRC.
Calculator expressions are evaluated locally with a small parser; GoBot never executes shell commands or arbitrary code:
!calc 2*(3+4)
!math 100 / 4
!convert 10 km to mi
!convert 32 f to c
Supported conversions include temperature, length, mass, and volume. Keep
expressions short and use +, -, *, /, and parentheses.
Posting a Reddit URL still uses the automatic URL-title plugin. Use !reddit
when you want Reddit-specific metadata for a particular post or one current
post from a subreddit:
!reddit https://www.reddit.com/r/golang/comments/example/post-title/
!r https://www.reddit.com/r/golang/comments/example/post-title/
!reddit r/linux
!reddit https://www.reddit.com/r/linux/
!r r/golang
The response contains the post title, author, subreddit, score, comment count,
and canonical Reddit URL in one compact message. Both r/subreddit and full
Reddit subreddit URLs are accepted. GoBot prefers Reddit's public JSON
endpoint, then falls back to the corresponding public RSS feed when JSON is
temporarily blocked or throttled. RSS does not reliably include scores or
comment counts, so those fields are omitted rather than shown as false zeroes.
For individual posts, a final oEmbed title fallback can still provide the
title when Reddit rate-limits both metadata endpoints.
Only recognized Reddit hosts and paths are accepted; arbitrary URL fetching is
not performed by this command.
The GitHub plugin uses the public GitHub REST API and keeps every response to one bounded IRC message. It accepts repository names, GitHub URLs, issues, pull requests, releases, commits, users, and repository searches:
!github variablenix/GoBot
!gh https://github.com/variablenix/GoBot/issues/1
!github variablenix/GoBot#12
!github variablenix/GoBot releases
!github user octocat
!github search go irc bot
Repository responses include a short description, stars, forks, open issues, language, and a link. Issue and pull-request responses include the title, state, author, comments, and link. Search returns up to three compact repository matches. Invalid hosts and malformed references are rejected locally; GitHub response text is cleaned before it reaches IRC.
Authentication is optional. A token can increase the public API rate limit,
but GoBot only performs read-only lookups and never needs repository write
permissions. Keep the token out of config.yaml in deployments:
BOT_GITHUB_TOKEN=your-optional-read-only-tokenThe token is sent only to api.github.com over HTTPS. Leave it empty when the
anonymous public API limit is sufficient.
The grab plugin lets users save memorable lines without keeping a complete
transcript of the channel in memory. GoBot remembers only the latest message
from each nickname in the current channel; a line is written to BoltDB only
when someone explicitly grabs it:
!grab Alice
!lgrab Alice
!grabr
!grabr Alice
!grabs deployment
!grab <nick> saves that nickname's latest message. !lgrab repeats their
most recently saved line, !grabr shows a random saved line, and !grabs
searches saved nicknames and text. Search results are limited to three compact
matches so the plugin cannot flood a channel. Duplicate lines are ignored and
each nickname is limited to the configured number of saved lines. The plugin
supports ordinary messages and /me actions, strips IRC control characters,
and adds a zero-width separator after the first nickname character to avoid
unwanted highlights.
plugins:
grab:
enabled: true
max_length: 320
max_quotes_per_user: 20The saved lines are scoped by network and channel and survive restarts. The plugin does not expose a command to dump the entire database.
!linux and !kernel fetch the current release-line summary from
kernel.org and return it as one bounded IRC message:
!linux
!kernel
The lookup is read-only, has a short timeout, limits the response body, and does not accept arbitrary URLs. It requires no API key:
plugins:
linux:
enabled: true
timeout_seconds: 8
max_length: 260Foods is a local, data-driven suggestion plugin. It does not call a food API or send user input to a third-party service. Each request produces one short IRC message:
!food
!food ramen
!food pork
!food steak
!beer guinness
!beer
!korean
!japanese
!sushi
!ramen
!chinese
!cantonese
!mandarin
!sichuan
!hunan
!shanghai
!beijing
!dongbei
!yunnan
!xinjiang
!burrito
!vietnamese
!filipino
!french
!spanish
!turkish
!middle-eastern
!german
!british
!irish
!polish
!portuguese
!greek
!soda
!juice
!water
!smoothie
!mocktail
!pizza
!tea nickname
The built-in lists include a broad food collection, beer styles from pale
ales and IPAs through lagers, stouts, sours, Belgian, farmhouse, and historical
styles, plus Korean, Japanese, sushi, ramen, Chinese, Indian, Thai, Mexican,
Italian, Mediterranean, American, pizza, taco, burrito, burger, pasta, dessert,
snack, coffee, tea, wine, Vietnamese, Filipino, French, Spanish, Turkish,
Ethiopian, Brazilian, Caribbean, Indonesian, Persian, and Middle Eastern
categories. European lists include German, British, Irish, Scottish, Welsh,
Portuguese, Greek, Polish, Ukrainian, Russian, Swedish, Norwegian, Danish,
Finnish, Dutch, Belgian, Austrian, Swiss, Czech, Hungarian, Romanian, and
Georgian dishes. The catalog also includes Moroccan, Nigerian, South African,
Peruvian, Argentinian, Chilean, Colombian, Venezuelan, Cuban, Canadian,
Australian, New Zealand, Malaysian, Pakistani, Bangladeshi, Sri Lankan, and
Nepalese dishes. Chinese regional lists include Cantonese, Northern Chinese
(available as !mandarin), Sichuan, Hunan, Shanghai, Beijing, Dongbei,
Yunnan, and Xinjiang dishes. !foods is an alias for !food; country and regional aliases
such as !de, !uk, !ie, !pt, !gr, !pl, !ua, !ru, !se, !no,
!dk, !fi, !nl, !be, !at, !ch, !cz, !hu, !ro, !br, !pe,
!ar, !cl, !co, !ve, and !nz are also available.
The cuisine lists are intentionally broad and easy to extend. They include
common dishes, regional specialties, street food, desserts, and familiar
variants such as double cheeseburger, triple cheeseburger, and several
burrito styles. Add one dish per line to a list in data/foods/; changes are
loaded when GoBot starts.
Drink lists are local and include everyday beverages as well as international
styles. Use !drinks for a general suggestion or a focused command such as
!soda, !juice, !water, !smoothie, !milkshake, !lemonade,
!mocktail, !energy-drink, !sports-drink, !hot-chocolate, !kombucha,
or !bubble-tea. Coffee and tea remain available through !coffee and
!tea, while alcoholic suggestions remain under !beer and !wine.
Each drink list is one item per line under data/foods/, and the output is
bounded to one IRC message just like the cuisine lists.
!food accepts a search term as well as a category. For example, !food pork
searches the complete catalog for matching dishes, while !beer guinness
searches only the beer list. Matching is case-insensitive and supports
multi-word terms. If no item matches, the command keeps its friendly random
suggestion behavior and treats the text as an optional nickname.
!sports returns one random sport from the local catalog. !sport is a short
alias, and an optional nickname makes the response more personal:
!sports
!sport Alex
The catalog covers team sports, individual and racket sports, combat sports,
water and winter sports, motorsports, strength sports, adaptive sports, and
esports. Add one sport per line to data/sports.txt; the file is loaded when
GoBot starts. Every response is bounded to one IRC message.
!car returns one random entry from the local car catalog; !cars is an
alias. Entries cover affordable daily drivers, trucks, SUVs, EVs, luxury cars,
classics, and sports and supercars. Each entry includes an approximate
production span. The bundled catalog includes hundreds of entries from brands
such as Bugatti, Ferrari, Lamborghini, McLaren, Pagani, Porsche, Rolls-Royce,
Koenigsegg, Rimac, Lucid, and major international manufacturers:
!car
!cars Alex
The catalog is intentionally local and easy to extend rather than pretending
to be a perfect worldwide vehicle registry. Add one make/model entry per line
to data/cars.txt; entries can include a year range such as
Toyota Corolla (1966-present). The optional configuration is:
plugins:
car:
enabled: true
data_file: "data/cars.txt"
max_length: 240Lists are plain text, one item per line, under data/foods/. Operators can
extend or replace them without changing Go code:
plugins:
foods:
enabled: true
data_dir: "data/foods"
max_length: 240An optional nickname after a category produces a single targeted suggestion,
such as Tea pick for Sam: genmaicha. The plugin is bounded to one response
and local list lookups, so it does not create an external-request or flooding
hotspot.
!8ball Will this deploy cleanly?
!8 Should I order pizza?
!eightball Is the channel ready?
Responses come from quotes/eightball.txt, one per line. Prefix a response with green|, yellow|, or red| to control its IRC color. Unprefixed responses remain readable without color. Each request produces one bounded message.
Pool's separate 8-ball mode uses !pool 8 <nick>, !pool8 <nick>, or
!8pool <nick>; !8ball is reserved for questions to the magic 8-ball.
The fun plugin provides local text without making an external request. Each
command returns one randomly selected, bounded line. The yo-momma catalog is
organized around classic joke categories such as size, age, smell, silliness,
work, food, technology, and everyday mishaps. It is playful and non-targeted:
operators should remove any entries that do not fit their channel's tone.
!yomomma
!yo
!oneliner
!one
!pun
!puns
!wisdom
!wise
The catalogs are stored under data/fun/:
yo_momma.txt: categorized yo-momma jokes, including fat, skinny, tall, short, old, smelly, stupid/silly, loud, broke, clumsy, food, technology, school, sports, and other classic joke themesone_liners.txt: short original one-linerspuns.txt: short original punswisdom.txt: original/adapted wisdom lines without questionable attribution
They are intentionally curated rather than presented as an exhaustive list of every joke or quotation. Add one line per entry; GoBot loads the files when it starts. The plugin is configured as follows:
plugins:
fun:
enabled: true
data_dir: "data/fun"
max_length: 240The catalogs are local and editable, so operators can remove a line or adapt the tone of a channel without changing Go code.
The attack plugin provides short, playful target-based actions and messages:
!attack slap Alice
!slap Alice
!hug Alice
!flirt Alice
!compliment Alice
!high5 Alice
!gift Alice
!spank Alice
!attack pokemon Alice
!strax
The canonical form is !attack <style> [nick]; most styles require a nickname.
Aliases include !bite,
!fight, !glomp, !insult, !kill, !lart, !present, !spank,
!stab, !bdsm, !clinton, !trump, !lurve, and !pokemon, plus
CloudBot-style aliases such as !end, !sexup, !jackmeoff, !dominate,
!spar, !challenge, !luff, and !luv. !strax, !nk, and !westworld
also work without a target. Action styles use standard IRC CTCP ACTION
formatting, so clients usually render them like /me messages; compliment,
flirt, insult, lurve, pokemon, strax, nk, and westworld use ordinary messages.
Targets must be a single IRC-style nickname. Targeting GoBot or self makes
GoBot perform the playful action toward the sender. Templates are built in,
capped to short safe text, and contain no real-world instructions.
The weapons plugin is a lightweight reference/randomizer for firearm and
weapons terminology. It returns names and broad categories only; it does not
provide instructions, construction details, acquisition advice, or tactical
guidance. Generic commands choose from the whole catalog, while category
aliases narrow the result:
!firearm
!guns pistol
!rifle
!shotgun
!smg
!grenade
!explosives
The catalog includes civilian, historical, sporting, military, launcher,
grenade, and high-level explosive terms. Keep the default output limit in
place to ensure one short IRC response. Operators can edit data/weapons.txt
or disable the plugin with plugins.weapons.enabled: false.
plugins:
weapons:
enabled: true
data_file: "data/weapons.txt"
max_length: 240!cheer
!yay
GoBot also responds to a message containing \o/, with a per-channel cooldown:
plugins:
cheer:
enabled: true
cheers_file: "quotes/cheers.txt"
automatic_cooldown_seconds: 15Responses come from quotes/cheers.txt, one family-friendly response per line.
Ask GoBot a general question with any of these aliases:
!ask how dangerous is extreme dehydration?
!question what is the Linux kernel?
!q what does TLS protect?
GoBot first looks for a concise English Wikipedia summary and can fall back to
DuckDuckGo's public Instant Answer data. The default source-only mode needs no
API key. It replies in one compact IRC message and includes a Read more link
when the source provides one. A sender-specific cooldown prevents repeated
lookups from becoming a flood source.
The plugin is configured under plugins.ask:
plugins:
ask:
enabled: true
wikipedia_first: true
duckduckgo_fallback: true
ai_rewrite: false
provider: none # none, openrouter, openai, gemini, ollama
max_length: 360
max_response_chars: 240
timeout_seconds: 12
cooldown_seconds: 15ai_rewrite is optional. When enabled, GoBot gives the selected provider the
retrieved source and asks it to turn that source into a concise, factual,
single-paragraph answer. It does not use an AI provider when provider: none
is selected, and it falls back to the source summary if the provider is
unavailable. BOT_ASK_PROVIDER and BOT_ASK_AI_REWRITE override the
corresponding nested config values; this means provider: none and
ai_rewrite: false can remain in the tracked example while a deployment
enables rewriting through .env. Keep provider credentials out of
config.yaml:
BOT_ASK_PROVIDER=openrouter
BOT_ASK_AI_REWRITE=true
BOT_OPENROUTER_API_KEY=...
# A specific instruction-tuned free model is more consistent than a random
# free-model router for this short source-rewrite task.
BOT_OPENROUTER_MODEL=google/gemma-4-31b-it:freeOpenAI uses BOT_OPENAI_API_KEY and BOT_OPENAI_MODEL; Gemini uses
BOT_GEMINI_API_KEY and BOT_GEMINI_MODEL. For a local Ollama instance, use
BOT_ASK_PROVIDER=ollama, BOT_OLLAMA_URL, and BOT_OLLAMA_MODEL. The output
limits still apply regardless of provider. If a provider returns meta-text
such as “the user asks” or “the source does not”, GoBot makes one stricter
correction request within the original timeout. If that still fails, or the
provider returns INSUFFICIENT_SOURCE, GoBot rejects it and keeps the
source-grounded answer instead. The question and retrieved source are treated
as untrusted data in the rewrite prompt; instructions contained in them are
not followed.
To verify that the key is actually being used, check the service log after one
fresh !ask request:
ask AI rewrite requested ... provider=openrouter ... api_key_configured=true
ask AI rewrite used ... provider=openrouter ...
If the provider call fails, GoBot logs ask AI rewrite unavailable; using source summary and still returns the source answer. The API key is never written to
the log. A source-only response is usually faster; an AI rewrite adds one
external request, and free models may take longer when they are cold or busy.
Use BOT_ASK_AI_REWRITE=false to compare source-only behavior.
The daily plugin adds a persistent !daily command:
plugins:
daily: {enabled: true, bonus_xp: 25}Each authenticated account can claim once per UTC calendar day, regardless of channel or network. Users without an authenticated account are limited by network and nickname. Different users may claim independently; this is not a single shared server-wide claim. The reward is added to the Duck Hunt XP profile for the channel where the claim is made, so Duck Hunt must be enabled globally and in that channel. Claims survive restarts through the configured Bolt database. Daily tracks the consecutive UTC-day claim streak separately from Duck Hunt's XP and level progression.
After changing config.yaml, an owner can send GoBot a private reload
message to apply reloadable plugin settings without reconnecting. Changes to
.env still require a service restart because systemd reads that file when the
process starts.
Search English Wikipedia with either alias:
!wiki Linux
!wikipedia FreeBSD
GoBot tries an exact article title, then searches Wikipedia if needed. max_summary_length controls response length.
!seen nickname
!tell nickname message for them
!karma project
project++
project--
!roll d20
!roll 2d6
!quote
!choose pizza | tacos | burgers
!time America/Los_Angeles
!time Seoul
!time Bangkok
!car
!stats
!chanstats
!channelstats
!status
!define resilient
!calc 2+2
!convert 10 km to mi
!reddit https://www.reddit.com/r/example/comments/abc123/post/
- seen reports where and when a nickname last spoke. Records are stored in BoltDB.
- tell queues a message and delivers it when the addressed nickname next speaks.
- karma tracks case-insensitive thing++ and thing-- changes.
- thing++ and thing-- also work as standalone ordinary chat messages. GoBot
confirms each update in one compact line, replacing
<nickname>with the actual nickname being changed, such as🆙 Karma boost! KnownSyntax gained 1 karma ✨ (🎯 1 in #chat | 🌐 2 global); command messages are not treated as karma changes. - In a channel, Karma reports the channel total and the global total, for
example
🎯 9 in #chat | 🌐 19 global; private messages report global Karma. - Positive karma milestones at +10, +25, +50, and +100 add a highlighted trophy notice when the total crosses the threshold.
- dice accepts NdN notation or a single number such as !roll 20, meaning 1d20. It allows up to 100 dice and 10,000 sides per die and uses secure random values.
- quote reads the configured quote sources; see Banter and fortune.
- choose randomly selects between two to twenty pipe- or comma-separated options.
- time accepts full IANA timezone names and common city shortcuts such as
Seoul,Bangkok,Tokyo,London, andNew York; full names such asAsia/Seoulremain supported. Weather already accepts city names through Open-Meteo geocoding. - channelstats reports message totals, distinct users, and the top five users for the current channel. It is persisted in BoltDB.
!help
!help weather
!help blackjack
!alias
!alias wiki
!help shows the compact plugin index. !help gives detailed usage, and !alias [command] lists aliases without scanning a long response.