Initial scaffold: Discord subreddit-announcer bot
This commit is contained in:
commit
705c6ba9f7
8 changed files with 1715 additions and 0 deletions
77
README.md
Normal file
77
README.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# subreddit-announcer
|
||||
|
||||
A Discord bot that watches subreddits and posts an embed to a Discord channel
|
||||
whenever a new submission appears. Built with [discord.py] and [asyncpraw];
|
||||
state is a local SQLite DB. One long-running process polls Reddit on an
|
||||
interval — no webhooks, no external scheduler.
|
||||
|
||||
## How it works
|
||||
|
||||
- A background loop polls each watched subreddit's `/new` every
|
||||
`ANNOUNCER_POLL_INTERVAL` seconds (default 60).
|
||||
- The first time a subreddit is watched it's **bootstrapped silently**: the
|
||||
posts already on `/new` are recorded as "seen" without being announced, so
|
||||
adding a busy subreddit doesn't dump its backlog into the channel. Only posts
|
||||
created afterwards are announced.
|
||||
- Seen submission ids are stored in SQLite for dedup and pruned to the most
|
||||
recent 500 per subreddit.
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Discord application
|
||||
|
||||
1. Create an app at <https://discord.com/developers/applications>.
|
||||
2. **Bot** tab → reset/copy the token → put it in `config.env` as `DISCORD_TOKEN`.
|
||||
3. Invite the bot to your server with the **`bot`** and **`applications.commands`**
|
||||
scopes, and the **Send Messages** + **Embed Links** permissions.
|
||||
No privileged intents are required (the bot never reads message content).
|
||||
|
||||
### 2. Reddit app (read-only)
|
||||
|
||||
1. Go to <https://www.reddit.com/prefs/apps> → **create another app**.
|
||||
2. Choose type **script**. The client id is the string shown under the app
|
||||
name; the secret is labelled **secret**.
|
||||
3. Put both into `config.env` (`REDDIT_CLIENT_ID`, `REDDIT_CLIENT_SECRET`).
|
||||
|
||||
### 3. Config + run
|
||||
|
||||
```bash
|
||||
cp config.example.env config.env
|
||||
$EDITOR config.env # fill in the tokens
|
||||
|
||||
# uv handles the venv + deps from pyproject.toml
|
||||
set -a; source config.env; set +a
|
||||
uv run bot.py
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
Slash commands (server-only; replies are ephemeral):
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| `/watch <subreddit> [channel]` | Announce a subreddit's new posts in a channel (defaults to the current one). |
|
||||
| `/unwatch <subreddit>` | Stop announcing that subreddit in this server. |
|
||||
| `/watching` | List the subreddits announced in this server. |
|
||||
| `/setinterval <seconds>` | Change the global poll interval (min 15s). |
|
||||
|
||||
## Running it persistently
|
||||
|
||||
It's a single foreground process; keep it alive however you like — `systemd`,
|
||||
`tmux`, `pm2`, or a container. A minimal systemd unit:
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
WorkingDirectory=/home/megaproxy/claude/projects/subreddit-announcer
|
||||
EnvironmentFile=/home/megaproxy/claude/projects/subreddit-announcer/config.env
|
||||
ExecStart=/home/megaproxy/.local/bin/uv run bot.py
|
||||
Restart=always
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- `config.env` and `announcer.db` are gitignored — secrets and state stay local.
|
||||
- Syntax check: `uv run python -m py_compile bot.py`.
|
||||
|
||||
[discord.py]: https://discordpy.readthedocs.io/
|
||||
[asyncpraw]: https://asyncpraw.readthedocs.io/
|
||||
Loading…
Add table
Add a link
Reference in a new issue