mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-21 22:33:54 -07:00
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.
163 lines
6.6 KiB
Markdown
163 lines
6.6 KiB
Markdown
# 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) |
|