mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-21 22:33:54 -07:00
Add Discord account registration monitor (#7013)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
A read-only cron script that posts new Servatrice account registrations to a Discord channel via webhook. Dedups by an auto-increment id high-water-mark (single-integer state, no duplicates, nothing missed across downtime). Reads DB credentials and the webhook from a servatrice-style ini via --config.
This commit is contained in:
parent
e99a55ccab
commit
80426d77bc
4 changed files with 519 additions and 0 deletions
163
servatrice/scripts/account_monitor/README.md
Normal file
163
servatrice/scripts/account_monitor/README.md
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
# Account registration monitor
|
||||
|
||||
Posts a Discord message whenever a new account is registered in Servatrice
|
||||
(`cockatrice_users`). Each message includes the username, real name (if set),
|
||||
email, and registration time.
|
||||
|
||||
It runs as a periodic read-only query against the production database. It does
|
||||
not modify the database and does not touch the running Servatrice process.
|
||||
|
||||
## How it decides what is "new"
|
||||
|
||||
Accounts get an auto-increment `id`, so "new since last time" is just
|
||||
`id > last_seen_id`. The monitor stores that single high-water-mark id in its
|
||||
state file. Each run it posts every account above the mark, oldest first, then
|
||||
advances the mark to the highest id it posted.
|
||||
|
||||
Because the mark only moves forward and an id is posted exactly once, there are
|
||||
no duplicate messages and nothing is missed, even if the monitor is down for a
|
||||
while. The state file holds a single number, so it never grows.
|
||||
|
||||
The first run (when no state file exists yet) records the current maximum id as
|
||||
the baseline and posts nothing. This prevents the entire existing user base from
|
||||
being dumped into the channel. Only accounts registered after that baseline are
|
||||
posted.
|
||||
|
||||
If a post to Discord fails, the monitor stops there without advancing the mark
|
||||
past it, so that account and everything after it are retried on the next run.
|
||||
|
||||
## Privacy note
|
||||
|
||||
Messages contain personal data (real name and email). Discord stores message
|
||||
content on their servers, so post only to a private channel that the right
|
||||
people can see, and treat the webhook URL as a secret. It lives in the config
|
||||
ini alongside the database password, so keep that file readable only by the user
|
||||
that runs the monitor.
|
||||
|
||||
## Setup
|
||||
|
||||
The monitor reads its database credentials and the webhook from a
|
||||
servatrice-style ini file passed with `--config` (or the `CONFIG_FILE` env var).
|
||||
You can point it at your existing `servatrice.ini`, or keep a small separate ini
|
||||
just for the monitor.
|
||||
|
||||
### 1. Create a read-only database user
|
||||
|
||||
Run as a DB admin. Adjust the host (`'%'` allows any host; restrict it to the
|
||||
machine running the monitor if you can) and the table prefix if yours is not the
|
||||
default `cockatrice`.
|
||||
|
||||
```sql
|
||||
CREATE USER 'account_monitor'@'%' IDENTIFIED BY 'a-strong-password';
|
||||
GRANT SELECT (id, name, realname, email, registrationDate)
|
||||
ON servatrice.cockatrice_users TO 'account_monitor'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
Using a read-only user is recommended over pointing `--config` at the real
|
||||
`servatrice.ini`, because Servatrice's own DB account usually has write access
|
||||
the monitor does not need.
|
||||
|
||||
### 2. Create the Discord webhook and add it to the config
|
||||
|
||||
In Discord: open the target channel, then Edit Channel -> Integrations ->
|
||||
Webhooks -> New Webhook. Name it, pick the channel, and copy the webhook URL.
|
||||
|
||||
Add a `[discord]` section with the URL to the ini you will pass to `--config`.
|
||||
If you want the read-only user above, set the `[database]` section to use it. A
|
||||
small dedicated `monitor.ini` looks like this:
|
||||
|
||||
```ini
|
||||
[database]
|
||||
hostname=127.0.0.1
|
||||
database=servatrice
|
||||
user=account_monitor
|
||||
password=a-strong-password
|
||||
prefix=cockatrice
|
||||
|
||||
[discord]
|
||||
new_user_activation_webhook=https://discord.com/api/webhooks/XXXX/YYYY
|
||||
```
|
||||
|
||||
If you would rather use one file, add the `[discord]` section to the real
|
||||
`servatrice.ini` instead. Servatrice ignores sections it does not use. Note that
|
||||
Servatrice (a Qt app) rewrites ini values it touches in quoted, backslash-escaped
|
||||
form, for example `"https\://..."`. The monitor strips that encoding from the
|
||||
webhook automatically, so either the plain or the escaped form works.
|
||||
|
||||
### 3. Install
|
||||
|
||||
```bash
|
||||
cd servatrice/scripts/account_monitor
|
||||
python3 -m venv venv
|
||||
./venv/bin/pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 4. Verify before scheduling
|
||||
|
||||
```bash
|
||||
# Confirm the webhook works (sends one test message to the channel)
|
||||
./venv/bin/python ./account_monitor.py --config /path/to/monitor.ini --test-webhook
|
||||
|
||||
# Confirm DB access and see what it would do, without posting or writing state
|
||||
./venv/bin/python ./account_monitor.py --config /path/to/monitor.ini --dry-run --verbose
|
||||
```
|
||||
|
||||
The first real run seeds the baseline and posts nothing:
|
||||
|
||||
```bash
|
||||
./venv/bin/python ./account_monitor.py --config /path/to/monitor.ini
|
||||
```
|
||||
|
||||
After that, test it end to end by registering a throwaway account and confirming
|
||||
a message appears on the next run.
|
||||
|
||||
## Run it every 2 minutes with cron
|
||||
|
||||
Edit the crontab of the user that owns the script directory (`crontab -e`) and
|
||||
add one line. This runs the monitor every 2 minutes, using the venv's Python and
|
||||
your config ini, and appends output to a log:
|
||||
|
||||
```cron
|
||||
*/2 * * * * cd /opt/cockatrice/servatrice/scripts/account_monitor && ./venv/bin/python ./account_monitor.py --config /etc/servatrice/servatrice.ini >> /var/log/account_monitor.log 2>&1
|
||||
```
|
||||
|
||||
Adjust the three paths to your install: the script directory after `cd`, and the
|
||||
`--config` and log paths. The `*/2` field is what makes it run every 2 minutes;
|
||||
change it to `*/5` for every 5, and so on.
|
||||
|
||||
By default the high-water-mark is stored in `state.json` next to the script, so
|
||||
the directory must be writable by the cron user. To put it elsewhere, set
|
||||
`STATE_FILE`:
|
||||
|
||||
```cron
|
||||
*/2 * * * * STATE_FILE=/var/lib/account_monitor/state.json cd /opt/cockatrice/servatrice/scripts/account_monitor && ./venv/bin/python ./account_monitor.py --config /etc/servatrice/servatrice.ini >> /var/log/account_monitor.log 2>&1
|
||||
```
|
||||
|
||||
The interval only controls how often it checks; it is not a lookback window, so
|
||||
a longer interval never causes missed accounts. The query is cheap: an indexed
|
||||
range scan on the primary key for `id > last_seen`.
|
||||
|
||||
## Options
|
||||
|
||||
- `--config PATH` / `-c PATH` — read DB settings from `[database]` and the webhook from `[discord] new_user_activation_webhook` of a servatrice-style ini (falls back to the `CONFIG_FILE` env var).
|
||||
- `--dry-run` — query and log what would be posted; no Discord posts, no state write.
|
||||
- `--test-webhook` — send one test message to the webhook and exit (does not need DB credentials).
|
||||
- `--verbose` — debug logging.
|
||||
|
||||
## Configuration reference
|
||||
|
||||
Settings come from the `--config` ini, with environment variables available as
|
||||
overrides if you need them (env takes precedence over the ini).
|
||||
|
||||
| Setting | ini (`--config`) | Environment override |
|
||||
| --- | --- | --- |
|
||||
| DB host | `[database] hostname` | `DB_HOST` |
|
||||
| DB port | `[database] port` (optional) | `DB_PORT` |
|
||||
| DB name | `[database] database` | `DB_NAME` |
|
||||
| DB user | `[database] user` | `DB_USER` |
|
||||
| DB password | `[database] password` | `DB_PASSWORD` |
|
||||
| Table prefix | `[database] prefix` | `DB_TABLE_PREFIX` |
|
||||
| Webhook URL | `[discord] new_user_activation_webhook` | `DISCORD_WEBHOOK_URL` |
|
||||
| DB TLS | — | `DB_SSL` / `DB_SSL_CA` |
|
||||
| State file path | — | `STATE_FILE` (default: `state.json` next to the script) |
|
||||
Loading…
Add table
Add a link
Reference in a new issue