diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/alfred.md | 132 | ||||
| -rw-r--r-- | docs/contessa.md | 59 | ||||
| -rw-r--r-- | docs/daffy.md | 55 | ||||
| -rw-r--r-- | docs/daft.md | 39 | ||||
| -rw-r--r-- | docs/herald.md | 63 | ||||
| -rw-r--r-- | docs/jeeves.md | 122 | ||||
| -rw-r--r-- | docs/osterman.md | 134 | ||||
| -rw-r--r-- | docs/salvador.md | 30 | ||||
| -rw-r--r-- | docs/shireen.md | 88 |
9 files changed, 722 insertions, 0 deletions
diff --git a/docs/alfred.md b/docs/alfred.md new file mode 100644 index 0000000..c2e6a7d --- /dev/null +++ b/docs/alfred.md @@ -0,0 +1,132 @@ +# alfred + +Server management bot. All commands are owner-only and work in channel or PM. + +## Dependencies + +``` +pip install requests +``` + +## Help system + +``` +!help list topics +!help <topic> list commands for a topic +!help <topic> <cmd> description and usage for a command +``` + +All help responses are sent as IRC NOTICE to the requester, not said publicly in channel. + +Running any command with no arguments shows the same output as `!help <topic>`. + +## Commands + +### Bot management + +``` +!bot list show all managed bots and their running state +!bot all start|stop|restart control all bots at once +!bot <name> start|stop|restart control a bot +!bot <name> status check if a bot is running +``` + +Bots are discovered automatically from `~/.config/sopel/*.cfg`. + +### Server stats + +``` +!srv uptime uptime and load averages +!srv disk disk usage for / [raw df output - needs formatting] +!srv mem RAM and swap usage [raw free output - needs formatting] +!srv load load averages and process count +!srv status [service] rc-service status, all or one +!srv net [iface] RX TX bytes for an interface +!srv top [n] top n processes by CPU (default 5) +!srv topmem [n] top n processes by memory (default 5) +!srv io disk read write stats +!srv conns TCP connection summary [raw ss -s output - needs formatting] +!srv who logged-in users [raw who output - needs formatting] +!srv logs <service> [n] last n log lines for a service (default 10) +``` + +`!server` is an alias for `!srv`. + +### Soju bouncer + +``` +!irc user list list all bouncer users [raw sojuctl output - needs formatting] +!irc user add <nick> <pass> create a new user [raw sojuctl output - needs formatting] +!irc user remove <nick> delete a user [raw sojuctl output - needs formatting] +!irc user passwd <nick> <pass> change a user's password [raw sojuctl output - needs formatting] +!irc user enable <nick> re-enable a disabled user [raw sojuctl output - needs formatting] +!irc user disable <nick> disable a user [raw sojuctl output - needs formatting] +!irc net list <user> list networks for a user [raw sojuctl output - needs formatting] +!irc net status <user> show network connection status [raw sojuctl output - needs formatting] +!irc net add <user> <name> [addr] add a network (preset or custom) [raw sojuctl output - needs formatting] +!irc net remove <user> <name> remove a network [raw sojuctl output - needs formatting] +!irc net quote <user> <net> <cmd> send a raw IRC command to a network [raw sojuctl output - needs formatting] +!irc net presets show available network presets +!irc bouncer bouncer-wide stats [raw sojuctl output - needs formatting] +!irc notice <message> broadcast a notice to all users [raw sojuctl output - needs formatting] +``` + +### File hosting (0x0) + +``` +!files stats file count and total size +!files list [n] last n uploads (default 5) +!files shorten <url> [wkfo|gumx] shorten a URL +!files mirror <url> [wkfo|gumx] mirror a remote URL +!files prune delete expired files from disk [raw flask output - needs formatting] +!files vscan run ClamAV scan on stored files [raw flask output - needs formatting] +!files remove <filename> permanently remove a file +``` + +### Coffee tracker + +``` +!coffee stats today count, week bar graph, streak, all-time average +!coffee +<n> add n cups to today +!coffee -<n> remove n cups from today +!coffee <n> set today's count to n +!coffee +<n> yyyy-mm-dd add n cups to a past date +!coffee <n> yyyy-mm-dd set a past date to n cups +!coffee yes confirm a pending action +!coffee no cancel a pending action +``` + +### WireGuard VPN + +``` +!vpn pubkey print server public key +!vpn list list peers: name, IP, pubkey (first 24 chars) +!vpn add <name> <pubkey> add peer, returns assigned IP and client config URL +!vpn remove <name> remove peer live and from wg0.conf +``` + +`!vpn add` assigns the next free `10.0.0.x`, calls `wg set wg0 peer` live (no restart needed), rewrites `wg0.conf`, uploads a ready-to-use client `.conf` to wk.fo, and replies with the IP and URL. + +### Mailing list + +``` +!list members show all subscribers +!list subscribe <email> subscribe an address +!list unsubscribe <email> unsubscribe an address +!list send <message> send a message to the list +``` + +Manages the mlmmj list at `list@gumx.cc`. Web archive at `mail.gumx.cc/list/archive/`. + +## Config keys + +| Key | Description | +|-----|-------------| +| `[coffee] data_path` | Path to coffee data JSON | +| `[coffee] timezone` | Timezone for date calculations (default UTC) | +| `[soju] config_path` | Path to soju config file | +| `[files] url` | 0x0 API URL | +| `[files] default_domain` | Default short domain (wkfo or gumx) | +| `[files] db_path` | Path to 0x0 SQLite database | +| `[files] data_path` | Path to 0x0 file storage directory | +| `[files] app_path` | Path to 0x0 Flask app directory | diff --git a/docs/contessa.md b/docs/contessa.md new file mode 100644 index 0000000..b1d2e27 --- /dev/null +++ b/docs/contessa.md @@ -0,0 +1,59 @@ +# contessa + +Recipe suggestion bot. Suggests random recipes by meal type, lists available +dishes per category, and gives full step-by-step recipes on request. + +## Dependencies + +No external libraries required. + +## Commands + +All commands require channel context (`@plugin.require_chanmsg`). + +| Command | Description | +|---------|-------------| +| `!breakfast [list]` | Random breakfast suggestion, or list all breakfast dishes | +| `!lunch [list]` | Random lunch suggestion, or list all lunch dishes | +| `!dinner [list]` | Random dinner suggestion, or list all dinner dishes | +| `!snack [list]` | Random snack suggestion, or list all snacks | +| `!recipe <name>` | Full recipe: description, ingredients, steps (3 lines) | + +### Admin (owner) +| Command | Description | +|---------|-------------| +| `!join #channel` | Join a channel | +| `!part [#channel]` | Leave a channel | +| `!chans` | List channels | +| `!help` | Show usage (PM) | + +## Recipe data + +Recipes are loaded from a JSON file at startup. Format: + +```json +{ + "breakfast": [ + { + "name": "Dish Name", + "description": "One-line description.", + "ingredients": ["item 1", "item 2"], + "steps": ["Step one.", "Step two.", "Step three."] + } + ], + "lunch": [...], + "dinner": [...], + "snack": [...] +} +``` + +The included `recipes.json` has 24 recipes per category (96 total), covering +both Egyptian/Middle Eastern and Western/European dishes. + +`!recipe` matches by exact name first, then by substring across all categories. + +## Config keys + +| Key | Default | Description | +|-----|---------|-------------| +| `[contessa] recipes_path` | `/var/contessa/recipes.json` | Path to recipes JSON file | diff --git a/docs/daffy.md b/docs/daffy.md new file mode 100644 index 0000000..d9a8311 --- /dev/null +++ b/docs/daffy.md @@ -0,0 +1,55 @@ +# daffy + +Duck hunting game bot. Ducks appear at random intervals; players race to shoot +them. Scores are stored in SQLite. The hunt auto-stops after a configurable +number of rounds with no participants. + +## Dependencies + +No external libraries required. + +## Commands + +### Game (anyone in channel) +| Command | Description | +|---------|-------------| +| `!bang` | Fire at the current duck | +| `!reload` | Refill ammo (3-second cooldown) | +| `!score` | Top 5 players for this channel | +| `!score clear` | Clear scores for this channel (owner/op) | + +Owner can also use `!score clear all` or `!score clear #channel` from PM. + +### Hunt control (owner / op) +| Command | Description | +|---------|-------------| +| `!hunt` | Show hunt state (on/off/active, idle counter) | +| `!hunt start` | Start the hunt | +| `!hunt stop` | Stop the hunt | +| `!hunt idle <N>` | Set empty-round auto-stop threshold (0 = never); takes effect immediately if threshold is already met | + +### Admin (owner) +| Command | Description | +|---------|-------------| +| `!join #channel` | Join a channel | +| `!part [#channel]` | Leave a channel | +| `!chans` | List channels | +| `!help` | Show usage (PM) | + +## How it works + +- A duck spawns every `spawn_min` to `spawn_max` seconds (random, default 1-5 minutes). +- First player to `!bang` scores a point. Each player has one shell; use `!reload` to reload. +- `!bang` and `!reload` are ignored while the hunt is off. +- If no one shoots within `flee_time` seconds (default 45), the duck flees and the round is marked empty. +- After `idle_rounds` consecutive empty rounds the hunt auto-stops. + +## Config keys + +| Key | Default | Description | +|-----|---------|-------------| +| `[daffy] db_path` | `~/daffy_scores.db` | Path to SQLite scores database | +| `[daffy] idle_rounds` | 3 | Empty rounds before auto-stop (0 = never) | +| `[daffy] spawn_min` | 60 | Minimum seconds between duck spawns | +| `[daffy] spawn_max` | 300 | Maximum seconds between duck spawns | +| `[daffy] flee_time` | 45 | Seconds before an unshot duck flees | diff --git a/docs/daft.md b/docs/daft.md new file mode 100644 index 0000000..f3595ee --- /dev/null +++ b/docs/daft.md @@ -0,0 +1,39 @@ +# daft + +YouTube playlist manager. Anyone can queue tracks; ops control playback. +Tracks are played via an external player (managed outside the bot). + +## Dependencies + +No external libraries required. + +## Commands + +### Queue (anyone in channel) +| Command | Description | +|---------|-------------| +| `!dj <youtube-url>` | Add a YouTube video to the queue | +| `!np` | Show the currently playing track | +| `!queue` | Show upcoming tracks | + +Accepted URL formats: `youtube.com/watch?v=...`, `youtu.be/...`. +Shorts, embeds, and live streams are rejected. +Queue cap: 50 tracks. + +### Playback (owner / op) +| Command | Description | +|---------|-------------| +| `!play` | Start or resume playback | +| `!stop` | Pause playback | +| `!skip` | Skip to the next track | +| `!remove` | Remove the current track from the queue | +| `!loop on\|off` | Toggle circular queue looping | +| `!clear` | Clear queue and stop playback | + +### Admin (owner) +| Command | Description | +|---------|-------------| +| `!join #channel` | Join a channel | +| `!part [#channel]` | Leave a channel | +| `!chans` | List channels | +| `!help` | Show usage (PM) | diff --git a/docs/herald.md b/docs/herald.md new file mode 100644 index 0000000..d651d4f --- /dev/null +++ b/docs/herald.md @@ -0,0 +1,63 @@ +# herald + +Owner-follow bot with a configurable keyword responder. + +Herald tracks the owner's IRC presence and mirrors their channel movements. +It can also respond to keywords in channel messages with random replies. + +## Dependencies + +No external libraries required. + +## Plugins + +| File | Role | +|------|------| +| `commands.py` | Follow logic and admin commands | +| `respond.py` | Keyword-based auto-responder | + +## Commands (owner only) + +| Command | Description | +|---------|-------------| +| `!pause` | Pause keyword responses | +| `!resume` | Resume keyword responses | +| `!follow on` | Start tracking owner's channels (checks every 30s via WHOIS) | +| `!follow off` | Stop tracking | +| `!unfollow` | Immediately leave all follow-joined channels | +| `!join #channel` | Join a channel manually | +| `!part [#channel]` | Leave a channel | +| `!chans` | List channels | +| `!help` | Show usage (PM) | + +## Automatic behaviour + +- When the owner PARTs a channel, herald leaves too (unless it's a preconfigured channel). +- When the owner QUITs, herald leaves all non-preconfigured channels. +- With `!follow on`, herald also joins any channel the owner is in that herald isn't. + +Preconfigured channels are the ones listed under `channels` in the config. + +## Keyword responder (`respond.py`) + +Configure in `[respond]`: + +```ini +[respond] +keywords = + hello + hi there +responses = + Hey! + What's up? +``` + +When any `keyword` appears (case-insensitive) in a channel message, herald +replies with a randomly chosen response. + +## Config keys + +| Key | Description | +|-----|-------------| +| `[respond] keywords` | Newline-separated list of trigger words | +| `[respond] responses` | Newline-separated list of possible replies | diff --git a/docs/jeeves.md b/docs/jeeves.md new file mode 100644 index 0000000..77bd5e7 --- /dev/null +++ b/docs/jeeves.md @@ -0,0 +1,122 @@ +# jeeves + +Combined-features IRC bot. Brings together DJ queue management, duck hunting, +recipes, news and weather, quote bank, image rendering, and keyword responses +in a single bot with a shared runtime-configurable settings store. + +## Dependencies + +- Sopel IRC framework +- Pillow (`pip install Pillow`) - only needed for `!draw`; all other features + work without it + +## Commands + +### DJ (anyone / op for controls) +| Command | Description | +|---------|-------------| +| `!dj <url>` | Queue a YouTube URL (shorts, embeds, live not accepted) | +| `!np` | Show currently playing track | +| `!queue` | List up to 4 upcoming tracks | +| `!loop` | Show loop state | +| `!play` | Start or resume playback (op) | +| `!stop` | Pause playback (op) | +| `!skip` | Skip to next track (op) | +| `!remove` | Remove current track from queue (op) | +| `!loop <on\|off>` | Toggle queue looping (op) | +| `!clear` | Clear queue and stop playback (op) | + +### Duck hunting (anyone in channel / op for control) +| Command | Description | +|---------|-------------| +| `!bang` | Fire at the current duck | +| `!reload` | Refill ammo (3-second cooldown) | +| `!score` | Top 5 players for this channel | +| `!score clear` | Clear scores for this channel (op/owner) | +| `!hunt` | Show hunt state (includes current spawn/flee times) | +| `!hunt start` | Start the hunt (op/owner) | +| `!hunt stop` | Stop the hunt (op/owner) | + +### Recipes (anyone in channel) +| Command | Description | +|---------|-------------| +| `!breakfast [list]` | Random breakfast suggestion, or list all | +| `!lunch [list]` | Random lunch suggestion, or list all | +| `!dinner [list]` | Random dinner suggestion, or list all | +| `!snack [list]` | Random snack suggestion, or list all | +| `!recipe <name>` | Full recipe: name, ingredients, steps | + +### News and weather (anyone) +| Command | Description | +|---------|-------------| +| `!weather <city>` | Current weather conditions | +| `!forecast <city>` | 3-day weather forecast | +| `!headlines [global\|mena\|egypt] [count]` | Latest RSS headlines | +| `!news` | Show auto-broadcast state | +| `!news on\|off` | Enable/disable auto-broadcast (op/owner) | + +### Quotes (anyone / op for management) +| Command | Description | +|---------|-------------| +| `!quote` | Post a random quote | +| `!quote add <text>` | Add a quote (op/owner) | +| `!quote del <N>` | Delete quote by index (op/owner) | +| `!quote list` | Show total quote count | +| `!quotes` | Show auto-post state | +| `!quotes on\|off` | Enable/disable auto-posting (op/owner) | + +### Art (anyone in channel) +| Command | Description | +|---------|-------------| +| `!draw [<lines>] <url>` | Render image as mIRC colour art (lines 4-12) | + +### Config (owner / op) +| Command | Description | +|---------|-------------| +| `!set <key> <value>` | Set a config value (in channel: per-channel; in PM: global, owner only) | +| `!config [#channel]` | Show all config values for a channel | + +### Admin (owner) +| Command | Description | +|---------|-------------| +| `!join #channel` | Join a channel | +| `!part [#channel]` | Leave a channel | +| `!chans` | List joined channels | +| `!pause` | Pause keyword responses | +| `!resume` | Resume keyword responses | + +### Help +| Command | Description | +|---------|-------------| +| `!help` | Topics overview | +| `!help <topic>` | Commands in that topic | +| `!help <cmd>` | Command description | + +## Runtime config keys + +All keys are set via `!set <key> <value>`. Per-channel keys can be set in a +channel (affecting that channel only) or in PM (setting the global default). +Global-only keys must be set in PM by the owner. + +| Key | Default | Scope | Description | +|-----|---------|-------|-------------| +| `dj_track_duration` | 120 | global | Seconds per track before auto-advance | +| `dj_queue_cap` | 50 | global | Max tracks in queue | +| `art_height` | 6 | global | Default lines for `!draw` (4-12) | +| `duck_spawn_min` | 60 | per-channel | Min seconds between duck spawns | +| `duck_spawn_max` | 300 | per-channel | Max seconds between duck spawns | +| `duck_flee_time` | 45 | per-channel | Seconds before duck flees | +| `duck_idle_rounds` | 3 | per-channel | Empty rounds before auto-stop (0=off) | +| `news_interval` | 90 | per-channel | Minutes between news broadcasts | +| `news_count` | 1 | per-channel | Headlines per broadcast cycle | +| `quotes_interval` | 60 | per-channel | Minutes between quote auto-posts | + +## Config file keys + +| Key | Description | +|-----|-------------| +| `[jeeves] db_path` | Path to main JSON database | +| `[jeeves] duck_db_path` | Path to duck scores SQLite database | +| `[jeeves] recipes_path` | Path to recipes JSON file | +| `[respond] keywords` | Newline-separated trigger words for keyword responses | +| `[respond] responses` | Newline-separated response lines (random choice) | diff --git a/docs/osterman.md b/docs/osterman.md new file mode 100644 index 0000000..2e81629 --- /dev/null +++ b/docs/osterman.md @@ -0,0 +1,134 @@ +# osterman + +Channel moderation bot. Manages bans, kicks, mutes, auto-modes, content filters, +and idle tracking. + +## Dependencies + +No external libraries required. + +## Plugins + +| File | Role | +|------|------| +| `protect.py` | Setup, passive protection: flood, caps, repeat, badword, clone, join flood | +| `commands.py` | All user-facing moderation and config commands | +| `tracking.py` | SQLite event log, greeting, `!seen`, `!info`, `!log` | +| `idle.py` | Idle detection tick, `!afk`, `!idle` | +| `help.py` | Three-level help system | + +## Message routing + +| Output type | Delivery | +|-------------|----------| +| `!seen`, `!idle <nick>` results | Channel message | +| `!info`, `!log` results | PM to nick | +| `!ban list`, `!config`, `!filter list`, `!badword list` | PM to nick | +| All other command feedback (errors, confirmations) | IRC NOTICE to nick | +| Greetings, idle warns, bad word warn | IRC NOTICE to nick | + +## Help system + +``` +!help list topics +!help <topic> list commands for a topic +!help <topic> <cmd> description and usage for a command +!help <cmd> description and usage (topic not required) +``` + +Topics: `mod`, `config`, `track`, `idle`, `admin` + +## Commands + +### Moderation (owner / ACL / op) + +| Command | Short | Description | +|---------|-------|-------------| +| `!kick <nick> [reason]` | `!k` | Kick | +| `!ban <nick\|mask> [reason]` | `!b` | Ban + kick | +| `!ban list` | `!b list` | View channel ban list (PM) | +| `!bankick <nick\|mask> [reason]` | `!bk` | Ban + kick (explicit) | +| `!unban <nick\|mask>` | `!ub` | Remove ban | +| `!tempban <nick\|mask> <min> [reason]` | `!tb` | Timed ban (auto-lifts) | +| `!mute <nick\|mask>` | `!mu` | Quiet (+q) | +| `!unmute <nick\|mask>` | `!umu` | Unquiet (-q) | +| `!voice <nick>` | `!v` | Give voice (+v) | +| `!devoice <nick>` | `!dv` | Remove voice | +| `!op <nick>` | `!o` | Give op (+o) | +| `!deop <nick>` | `!do` | Remove op | +| `!halfop <nick>` | `!hop` | Give halfop (+h) | +| `!dehalfop <nick>` | `!dhop` | Remove halfop | +| `!lock [m\|i]` | `!lk` | Lock channel (+mi, +m, or +i) | +| `!unlock [m\|i]` | `!ulk` | Unlock channel | + +### Auto-modes (owner / ACL / op, per channel) + +| Command | Short | Description | +|---------|-------|-------------| +| `!autoop <add\|del\|list> [nick\|mask]` | `!ao` | Auto +o on join | +| `!autovoice <add\|del\|list> [nick\|mask]` | `!av` | Auto +v on join | +| `!autohalfop <add\|del\|list> [nick\|mask]` | `!ahop` | Auto +h on join | + +### Config / lists (owner / ACL) + +| Command | Short | Description | +|---------|-------|-------------| +| `!blacklist <add\|del\|list> [mask]` | `!bl` | Global ban list (all channels) | +| `!whitelist <add\|del\|list> [mask]` | `!wl` | Global bypass list | +| `!except <add\|del\|list> [mask]` | `!ex` | Per-channel bypass list | +| `!acl <add\|del\|list> [nick]` | (none) | Trusted nicks (can use mod commands) | +| `!filter <add\|del\|list> [pattern]` | `!f` | Per-channel regex content filter | +| `!badword <add\|del\|list> [word]` | `!bw` | Per-channel word block list | +| `!set <key> <value>` | `!s` | Set a config value (in channel: per-channel; in PM: global) | +| `!config [#channel]` | `!cfg` | Show channel config (PM) | +| `!idle <on\|off>` | `!id` | Toggle idle detection | + +### Tracking + +| Command | Auth | Description | +|---------|------|-------------| +| `!seen <nick>` | anyone | Last time nick was seen in this channel. Responds in channel. Owner/ACL may call from PM for cross-channel lookup. | +| `!info <nick>` | anyone | Nick summary scoped to this channel (PM). Owner/ACL may call from PM for global lookup. | +| `!idle <nick>` | anyone | How long nick has been idle in this channel. Responds in channel. | +| `!log <nick> [n]` | owner / ACL | Full event log for nick (PM) | +| `!afk` | anyone | Reset your idle timer | + +### Admin (owner) + +| Command | Short | Description | +|---------|-------|-------------| +| `!join <#channel>` | `!j` | Join a channel | +| `!part [#channel]` | `!p` | Leave a channel | +| `!chans` | `!c` | List channels | + +## Configurable settings (`!set <key> <value>`) + +| Key | Default | Description | +|-----|---------|-------------| +| `flood_threshold` | 5 | Messages before flood action | +| `flood_window_sec` | 10 | Flood detection window (seconds) | +| `caps_filter` | 1 | Enable caps filter (0/1) | +| `caps_percent` | 70 | Caps percentage threshold | +| `caps_min_len` | 10 | Minimum message length to check | +| `repeat_filter` | 1 | Enable repeat filter (0/1) | +| `repeat_threshold` | 3 | Repeated messages before action | +| `repeat_window_sec` | 30 | Repeat detection window (seconds) | +| `clone_limit` | 2 | Max connections from same host | +| `join_flood_filter` | 1 | Enable join flood filter (0/1) | +| `join_flood_count` | 5 | Joins before action | +| `join_flood_window` | 10 | Join flood window (seconds) | +| `nick_flood_filter` | 1 | Enable nick flood filter (0/1) | +| `nick_flood_count` | 3 | Nick changes before action | +| `nick_flood_window` | 60 | Nick flood window (seconds) | +| `badword_action` | kick | Action on badword: `kick` or `warn` | +| `tempban_max_min` | 60 | Max duration for `!tempban` (minutes) | +| `idle_warn_min` | 45 | Minutes idle before warning | +| `idle_kick_min` | 60 | Minutes idle before kick | +| `log_limit` | 6 | Default number of events shown by `!log` | +| `greet` | 1 | Send join greeting (0/1) | + +## Config keys + +| Key | Description | +|-----|-------------| +| `[osterman] db_path` | Path to JSON database file | diff --git a/docs/salvador.md b/docs/salvador.md new file mode 100644 index 0000000..c1206b0 --- /dev/null +++ b/docs/salvador.md @@ -0,0 +1,30 @@ +# salvador + +Image-to-IRC art bot. Converts an image URL into mIRC colour art using +half-block characters and Floyd-Steinberg dithering against the 99-colour +mIRC palette. + +## Dependencies + +``` +pip install Pillow +``` + +## Commands + +| Command | Description | +|---------|-------------| +| `!draw <url>` | Render image at default height (6 lines) | +| `!draw <lines> <url>` | Render at custom height (4-12 lines) | + +The image is fetched, resized to fit within 60 chars wide, dithered to the +mIRC palette, and output line by line with a 0.4s flood delay between lines. +Images up to 5 MB are accepted; the Content-Type must be `image/*`. + +### Admin (owner) +| Command | Description | +|---------|-------------| +| `!join #channel` | Join a channel | +| `!part [#channel]` | Leave a channel | +| `!chans` | List channels | +| `!help` | Show usage (PM) | diff --git a/docs/shireen.md b/docs/shireen.md new file mode 100644 index 0000000..71cbaf7 --- /dev/null +++ b/docs/shireen.md @@ -0,0 +1,88 @@ +# shireen + +News and weather bot. Fetches current weather and forecasts from wttr.in, +and streams headlines from configurable RSS feeds. Posts fresh headlines +automatically at a per-channel interval and deduplicates across restarts. + +## Dependencies + +No external libraries required (uses `urllib` and `xml.etree.ElementTree`). + +## Commands + +| Command | Description | +|---------|-------------| +| `!weather <city>` | Current weather conditions | +| `!forecast <city>` | Brief forecast (today + next 2 days) | +| `!headlines [global\|mena\|egypt] [n]` | Fresh headlines, optionally filtered by label or count | +| `!news` | Show auto-broadcast state for this channel | +| `!news on` | Enable auto-broadcast (owner/op) | +| `!news off` | Disable auto-broadcast (owner/op) | +| `!news interval <min>` | Set broadcast interval in minutes (owner/op) | +| `!news count <n>` | Set headlines per broadcast cycle (owner/op) | + +### Admin (owner) +| Command | Description | +|---------|-------------| +| `!join #channel` | Join a channel | +| `!part [#channel]` | Leave a channel | +| `!chans` | List channels | +| `!help` | Show usage (PM) | + +## Auto-broadcast + +Every 90 minutes (default, per channel) shireen posts 1 headline (default) it +hasn't posted before. GUIDs are persisted to the data JSON so the same article +is never repeated across restarts. The cap is 1000 seen GUIDs (oldest pruned). +Interval and count are configurable per channel with `!news interval` and `!news count`. + +## URL cleaning + +All query strings and fragments are stripped from feed links before posting. +News article URLs are fully identified by their path; query parameters from +feeds are always tracking noise. + +## Default RSS feeds + +| ID | Name | Label | +|----|------|-------| +| `bbc_world` | BBC World | global | +| `reuters_world` | Reuters World | global | +| `ap_world` | AP News | global | +| `guardian_world` | The Guardian | global | +| `arab_news` | Arab News | mena | +| `aljazeera` | Al Jazeera | mena | +| `al_monitor` | Al-Monitor | mena | +| `egypt_indep` | Egypt Independent | egypt | +| `daily_news_egypt` | Daily News Egypt | egypt | + +Feeds can be modified directly in the data JSON (`feeds` array) while the bot +is stopped. Each feed has: `id`, `name`, `url`, `label`, `enabled`. + +## Data file format + +Created automatically at `data_path` on first run: + +```json +{ + "channels": { + "#example": { + "news_enabled": true, + "broadcast_interval": 90, + "broadcast_count": 1, + "last_broadcast": 0 + } + }, + "feeds": [...], + "seen": ["guid1", "guid2"] +} +``` + +## Config keys + +| Key | Default | Description | +|-----|---------|-------------| +| `[shireen] data_path` | `/var/shireen/data.json` | Path to state/config JSON (auto-created) | +| `[shireen] broadcast_interval` | `90` | Default minutes between auto-broadcast cycles | +| `[shireen] broadcast_count` | `1` | Default headlines posted per broadcast cycle | +| `[shireen] headlines_count` | `1` | Default headlines returned by `!headlines` | |
