Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# sp0rkle Agent Guide: Instructions for Developers and AI Agents

Welcome to the sp0rkle development guide. This document is designed to help you navigate the codebase, understand its unique architecture, and follow the established coding conventions.

## 1. Architecture Overview

sp0rkle is a modular IRC bot with a driver-based architecture.

- **`bot/`**: The core logic. Manages the IRC connection, command dispatching, rewriters, and pollers.
- **`db/`**: The database abstraction layer. Currently handles the dual-writing logic for the MongoDB to BoltDB migration.
- **`drivers/`**: Modular features (e.g., `factdriver`, `quotedriver`). Each driver is self-contained and registers its functionality with the core bot.
- **`collections/`**: Data access objects for specific features (e.g., `collections/karma`). These sit between the drivers and the `db/` package.
- **`util/`**: General-purpose utilities, including complex lexing (`util/datetime`, `util/lexer.go`).
- **`main.go`**: The entry point. It initializes databases and manually registers drivers.

## 2. Coding Style & "sp0rkle-isms"

This project uses Go 1.22 and follows some non-standard patterns that you must respect:

- **The Global `bot` Singleton**: The `bot` package uses a global singleton to manage state. While not "modern Go," it is the established pattern here. Use `bot.Command`, `bot.Handle`, etc., to register functionality.
- **Manual Registration**: Drivers must be imported in `main.go` and their `Init()` function called explicitly. There is no auto-discovery.
- **Driver Globals**: It is common for drivers to maintain their own package-level state (e.g., collection handles, rate limit maps).
- **Concurrency**: IRC handlers are executed in concurrent goroutines. Shared state in drivers **must** be protected by `sync.Mutex` or `sync.RWMutex`.
- **Go 1.22 Conventions**: Use `interface{}` (not `any`), `math/rand` (seeded in `main.go`), and `io/ioutil` (though `os` is preferred where applicable).
- **Tabs for Indentation**: Use standard `gofmt` with tabs.

## 3. Events and Handlers

sp0rkle uses an event-based system built on top of `goirc`.

- **Handler Signature**: `type HandlerFunc func(*bot.Context)`
- **`bot.Handle(fn, events...)`**: Registers a `HandlerFunc` for specific IRC events (e.g., `client.PRIVMSG`, `client.JOIN`).
- **`bot.HandleBG(fn, events...)`**: Same as `Handle`, but runs the handler in its own goroutine. Useful for long-running tasks like migrations.
- **`bot.Context`**: The primary object passed to handlers. It encapsulates the IRC line, the connection, and provides helper methods:
- `ctx.Text()`: Message body with bot name/command prefix stripped.
- `ctx.ReplyN(format, args...)`: Reply with "Nick: " prefix.
- `ctx.Storable()`: Returns sender nick and channel.

## 4. Plugins

The Factoid driver supports "plugins" which allow other drivers to perform transformations on factoid values.
- **Implementation**: A driver provides a `RegisterPlugins` method (if using the older pattern) or simply registers functions that the factoid driver calls.
- **Factoid Syntax**: Triggered via `<plugin=name args>` in a factoid value.
- **Identifier Replacement**: Common identifiers like `$nick`, `$chan`, `$date`, and `$time` are handled by a standard replacer in `factdriver/plugins.go`.

## 5. The "Long Slog" Migration (Mongo to BoltDB)

We are in the middle of a migration from MongoDB to BoltDB.

- **`db.Both`**: Most collections use `db.Both`, which writes to both databases simultaneously and compares reads.
- **`db.K`**: Keys are constructed using a custom key builder:
```go
key := db.K{db.S{"nick", "fluffle"}, db.I{"count", 42}}
```
- **BoltDB Structure**: Successive key elements create nested BoltDB buckets, with the final element as the key.

## 6. Extending the Bot

### Drivers
To add a new feature, create a new package in `drivers/`. It must have an `Init()` function:
```go
func Init() {
// Register a command: !myfeat <args>
bot.Command(myHandler, "myfeat", "myfeat <args> -- descriptive help")

// Register a raw IRC handler
bot.Handle(rawHandler, client.PRIVMSG)
}
```

### Pollers
For periodic tasks, implement `bot.Poller` (`Start`, `Stop`, `Poll`, `Tick`) and register with `bot.Poll(myPoller)`.

## 7. Testing

- Tests live in `_test.go` files.
- Use `bot.Context` mocking for handler tests.
- Reference `collections/` tests for database interaction testing.

## 8. Tips for AI Agents

- **Trace to Source**: Many files in `util/` (like `datetime/y.go`) are generated from `.y` or `.rl` files.
- **Check `main.go`**: Manual registration is required for all drivers.
- **Logging**: Use `github.com/fluffle/golog/logging`.

Happy Hacking!
8 changes: 8 additions & 0 deletions docs/drivers/decision.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Decision Driver

Make choices based on random numbers.

## Usage
- `!decide <option1> or <option2> or ...` - The bot will pick one for you.
- `!choose <option1> or <option2> or ...` - Same as `!decide`.
- `!rand <range>` - Pick a random number in the given range.
28 changes: 28 additions & 0 deletions docs/drivers/factoid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Factoid Driver

Factoids allow the bot to remember and recall information.

## Adding Factoids
There are two ways to teach the bot something (must address the bot by nick):
- `botNick: <key> := <value>` - Stores `<value>` for `<key>`.
- `botNick: <key> :is <value>` - Stores `<key> is <value>` for `<key>`.

## Retrieving Factoids
- Simply type the `<key>` in the channel, and the bot will respond with a random value associated with that key.
- `botNick: literal <key>` - Prints all known values for a key. If there are many, the bot will ask you to do this in a private message.

## Managing Factoids
These commands operate on the **last factoid triggered** in the channel:
- `botNick: forget that` or `delete that` - Deletes the last triggered value.
- `botNick: replace that with <new value>` - Replaces the last value.
- `botNick: that =~ /regex/replacement/` - Edit the last factoid value using regex.
- `botNick: chance of that is <N>%` - Sets the probability (0-100%) that the bot will respond to this key.
- `botNick: fact info` - Displays metadata about the last factoid (creator, time, etc.).
- `botNick: fact search <regex>` - Search for factoid keys matching a regex.

## Factoid Variables
You can use variables in factoid values:
- `$nick`: The nick of the person who triggered the factoid.
- `$chan`: The channel it was triggered in.
- `$date` / `$time`: Current date or time.
- `$user` / `$host`: Ident or host of the triggerer.
8 changes: 8 additions & 0 deletions docs/drivers/github.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# GitHub Integration

File and update issues directly from IRC.

## Usage
- `!file bug: <title>` - Create a new issue.
- `!report bug <title>` - Same as `!file bug:`.
- `!update bug #<number> <comment>` - Add a comment to an existing issue.
9 changes: 9 additions & 0 deletions docs/drivers/karma.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Karma Driver

Karma tracks the "score" of things or people.

## Usage
- `<thing>++` - Increases the karma of `<thing>`.
- `<thing>--` - Decreases the karma of `<thing>`.
- `(a thing with spaces)++` - Use parentheses for things with spaces.
- `!karma <thing>` - Retrieve the karma score of `<thing>`.
10 changes: 10 additions & 0 deletions docs/drivers/management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Bot Management

Commands for bot administrators.

## Usage
- `!ignore <nick>` - Make the bot ignore a user.
- `!unignore <nick>` - Make the bot stop ignoring a user.
- `!rebuild` - Trigger a rebuild and restart (authorized users only).
- `!shutdown` - Shutdown the bot (authorized users only).
- `!migrate <state>` - Change database migration state.
10 changes: 10 additions & 0 deletions docs/drivers/markov.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Markov and Insults

Random sentence generation and friendly insults.

## Usage
- `!markov [nick]` - Generate a random sentence.
- `!markov me` - Opt-in to Markov learning.
- `!don't markov me` - Opt-out of Markov learning.
- `!insult <nick>` - Insult a user at random.
- `!learn <tag> <sentence>` - Teach the bot a new sentence for a tag.
6 changes: 6 additions & 0 deletions docs/drivers/minecraft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Minecraft Integration

Minecraft server integration.

## Usage
- `!mc set <key> <value>` - Set configuration for Minecraft integration.
10 changes: 10 additions & 0 deletions docs/drivers/push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Push Notifications

Integration with Pushbullet.

## Usage
- `!push enable` - Enable push notifications.
- `!push disable` - Disable push notifications.
- `!push auth <pin>` - Authenticate with Pushbullet.
- `!push add alias` - Add an alias for push notifications.
- `!push del alias` - Delete an alias.
30 changes: 30 additions & 0 deletions docs/drivers/quote.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Quote Driver

The quote driver implements quote storage and retrieval.

## Adding quotes
Quotes can be added in three ways (must address the bot by nick):
- `botNick: qadd <quote>`
- `botNick: quote add <quote>`
- `botNick: add quote <quote>`

## Removing quotes
Quotes are deleted by quote ID (must address the bot by nick):
- `botNick: qdel <qid>`
- `botNick: quote del <qid>`
- `botNick: del quote <qid>`

## Retrieving quotes by ID
A specific quote may be looked up by its ID:
- `botNick: quote #<qid>`

## Retrieving quotes
Quotes may also be retrieved at random, with an optional case-insensitive regular expression:
- `botNick: quote <regex>`
- `botNick: quote`

## Plugin Syntax
The quote driver provides plugin functionality for the factoid driver, allowing you to embed quotes in factoid results. Add a factoid containing a `<plugin=quote>` directive:
- `botNick: quote fact := <plugin=quote>`
- `botNick: quote fact := <plugin=quote #quote ID>`
- `botNick: quote fact := <plugin=quote regex>`
18 changes: 18 additions & 0 deletions docs/drivers/reminders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Reminders and Tells

sp0rkle can remind you of things later or leave messages for absent users.

## Reminders
- `!remind <nick> <message> in <duration>` (e.g., `!remind me coffee in 10m`).
- `!remind <nick> <message> at <time>` (e.g., `!remind me meeting at 2pm`).
- `!remind list` - Lists reminders set by or for your nick.
- `!remind del <N>` - Deletes (previously listed) reminder N.
- `!snooze [duration]` - Resets the previously-triggered reminder.

## Tells
- `!tell <nick> <msg>` - Stores a message for the (absent) nick.
- `!ask <nick> <msg>` - Same as `!tell`.

## Timezones
- `!my timezone is <zone>` - Sets a local timezone for your nick.
- `!forget my timezone` - Unsets your local timezone.
26 changes: 26 additions & 0 deletions docs/drivers/utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Utilities

Various small utility commands.

## Calculator and Date
- `!calc <expression>` - Does maths for you.
- `!date <time/date> [in <zone>]` - Parse and format dates/times.

## Conversions
- `!base <from>to<to> <num>` - Base conversion (e.g., `!base 10to16 255`).
- `!length <string>` - Returns the length of a string.
- `!chr <int>` - Get character from integer.
- `!ord <char>` - Get integer from character.
- `!netmask <ip/cidr>|<ip> <mask>` - Netmask calculator.

## Web Tools
- `!ud <term>` - Urban Dictionary lookup.
- `!urlfind <regex>` - Search for URLs previously seen in the channel.
- `!randurl` / `!random url` - Show a random URL.
- `!shorten <url>` - Shortens a URL.
- `!cache <url>` / `!save <url>` - Caches a URL.

## Stats and Seen
- `!seen <nick>` - Check when a user was last seen.
- `!stats [nick]` / `!lines [nick]` - Line count statistics.
- `!topten` / `!top10` - Show top 10 most active users.
23 changes: 23 additions & 0 deletions docs/guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# sp0rkle User Guide: How to use the Bot

This guide provides an overview of the commands and features available to users of the sp0rkle IRC bot.

## Core Features

- [Factoids](drivers/factoid.md) - Teach the bot new things.
- [Karma](drivers/karma.md) - Track the "score" of things or people.
- [Quotes](drivers/quote.md) - Store and retrieve funny or memorable lines.
- [Reminders and Tells](drivers/reminders.md) - Set reminders for yourself or leave messages for others.
- [Decisions](drivers/decision.md) - Let the bot help you make choices.

## Utilities and Integrations

- [Utilities](drivers/utils.md) - Calculator, date parsing, base conversion, etc.
- [GitHub](drivers/github.md) - File and update issues directly from IRC.
- [Push Notifications](drivers/push.md) - Integration with Pushbullet.
- [Minecraft](drivers/minecraft.md) - Minecraft server integration.
- [Markov and Insults](drivers/markov.md) - Random sentence generation and friendly insults.

## Bot Management

- [Bot Management](drivers/management.md) - Commands for bot administrators.