Add welcomebot-signups CLI to inspect signup-IP classification history
This commit is contained in:
@@ -99,11 +99,31 @@ admin.yttrx.com (source: `bin/welcomebot-logs` in this repo). It wraps
|
|||||||
ssh admin.yttrx.com welcomebot-logs # last 200 lines
|
ssh admin.yttrx.com welcomebot-logs # last 200 lines
|
||||||
ssh admin.yttrx.com welcomebot-logs -f --abuse # follow abuse activity only
|
ssh admin.yttrx.com welcomebot-logs -f --abuse # follow abuse activity only
|
||||||
ssh admin.yttrx.com welcomebot-logs -n 1000 --since 24h
|
ssh admin.yttrx.com welcomebot-logs -n 1000 --since 24h
|
||||||
|
ssh admin.yttrx.com welcomebot-logs --ip --since 24h # signup-IP scrutiny decisions
|
||||||
ssh admin.yttrx.com 'welcomebot-logs --help'
|
ssh admin.yttrx.com 'welcomebot-logs --help'
|
||||||
```
|
```
|
||||||
|
|
||||||
To reinstall after editing `bin/welcomebot-logs`:
|
### Inspecting signup-IP classification history
|
||||||
`scp bin/welcomebot-logs admin.yttrx.com:/tmp/ && ssh admin.yttrx.com 'install -m755 /tmp/welcomebot-logs /usr/local/bin/'`
|
|
||||||
|
`welcomebot-signups` (also `/usr/local/bin/welcomebot-signups`, source
|
||||||
|
`bin/welcomebot-signups`) reads the persistent `signup_ip` sqlite table
|
||||||
|
directly — a permanent record of every classification decision, independent
|
||||||
|
of log retention:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh admin.yttrx.com welcomebot-signups # last 20 decisions
|
||||||
|
ssh admin.yttrx.com welcomebot-signups --flagged # only datacenter-flagged signups
|
||||||
|
ssh admin.yttrx.com welcomebot-signups -a someuser
|
||||||
|
ssh admin.yttrx.com welcomebot-signups -n all
|
||||||
|
```
|
||||||
|
|
||||||
|
Both CLIs are just files tracked in this repo now — after editing either one,
|
||||||
|
reinstall with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh admin.yttrx.com 'cd /root/yttrx-welcomebot && git pull origin main && \
|
||||||
|
install -m755 bin/welcomebot-logs bin/welcomebot-signups /usr/local/bin/'
|
||||||
|
```
|
||||||
|
|
||||||
### Rollback
|
### Rollback
|
||||||
|
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ test toot.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
welcomebot-logs -f --abuse # convenience CLI on admin (see bin/welcomebot-logs)
|
welcomebot-logs -f --abuse # convenience CLI on admin (see bin/welcomebot-logs)
|
||||||
|
welcomebot-signups --flagged # signup-IP classification history (see bin/welcomebot-signups)
|
||||||
docker compose logs -f welcomebot # watch deliveries
|
docker compose logs -f welcomebot # watch deliveries
|
||||||
docker compose restart welcomebot # after editing .env
|
docker compose restart welcomebot # after editing .env
|
||||||
docker compose down && docker compose up -d --build # redeploy after code change
|
docker compose down && docker compose up -d --build # redeploy after code change
|
||||||
|
|||||||
Executable
+87
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# welcomebot-signups — inspect the signup-IP classification history for yttrx-welcomebot.
|
||||||
|
#
|
||||||
|
# Installed at /usr/local/bin/welcomebot-signups on admin.yttrx.com.
|
||||||
|
# Source of truth: ~/yttrx-welcomebot/bin/welcomebot-signups (workstation).
|
||||||
|
# Reads the persistent `signup_ip` sqlite table (survives log rotation) —
|
||||||
|
# see app/main.py's record_signup_ip / IP-based signup scrutiny.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CONTAINER="${WELCOMEBOT_CONTAINER:-yttrx-welcomebot}"
|
||||||
|
limit=20
|
||||||
|
flagged_only=0
|
||||||
|
acct_filter=""
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: welcomebot-signups [options]
|
||||||
|
|
||||||
|
Print signup-IP classification records (acct, ip, org, classification,
|
||||||
|
flagged, ip_block status, timestamp) from the welcomebot's persistent
|
||||||
|
sqlite store, newest first.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-n, --limit N Show the last N rows (default: $limit; 'all' for everything).
|
||||||
|
--flagged Only flagged (datacenter) signups.
|
||||||
|
-a, --acct ACCT Only rows for this acct (exact match).
|
||||||
|
-h, --help Show this help.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
welcomebot-signups # last $limit classification decisions
|
||||||
|
welcomebot-signups --flagged # only datacenter-flagged signups
|
||||||
|
welcomebot-signups -n all
|
||||||
|
welcomebot-signups -a someuser
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-n|--limit) shift; limit="${1:?--limit needs a value}" ;;
|
||||||
|
--flagged) flagged_only=1 ;;
|
||||||
|
-a|--acct) shift; acct_filter="${1:?--acct needs a value}" ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) echo "welcomebot-signups: unknown option: $1" >&2; usage >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
echo "welcomebot-signups: docker not found in PATH" >&2; exit 1
|
||||||
|
fi
|
||||||
|
if ! docker inspect "$CONTAINER" >/dev/null 2>&1; then
|
||||||
|
echo "welcomebot-signups: container '$CONTAINER' not found (is it deployed/running?)" >&2; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker exec \
|
||||||
|
-e SIG_LIMIT="$limit" \
|
||||||
|
-e SIG_FLAGGED_ONLY="$flagged_only" \
|
||||||
|
-e SIG_ACCT="$acct_filter" \
|
||||||
|
"$CONTAINER" python3 -c '
|
||||||
|
import os
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
conn = sqlite3.connect("/data/welcomed.db")
|
||||||
|
where, params = [], []
|
||||||
|
if os.environ.get("SIG_FLAGGED_ONLY") == "1":
|
||||||
|
where.append("flagged = 1")
|
||||||
|
if os.environ.get("SIG_ACCT"):
|
||||||
|
where.append("acct = ?")
|
||||||
|
params.append(os.environ["SIG_ACCT"])
|
||||||
|
|
||||||
|
sql = "SELECT acct, ip, classification, org, flagged, ipblock_registered, classified_at FROM signup_ip"
|
||||||
|
if where:
|
||||||
|
sql += " WHERE " + " AND ".join(where)
|
||||||
|
sql += " ORDER BY classified_at DESC"
|
||||||
|
|
||||||
|
limit = os.environ.get("SIG_LIMIT", "20")
|
||||||
|
if limit != "all":
|
||||||
|
sql += f" LIMIT {int(limit)}"
|
||||||
|
|
||||||
|
rows = conn.execute(sql, params).fetchall()
|
||||||
|
if not rows:
|
||||||
|
print("(no matching signup records)")
|
||||||
|
for acct, ip, classification, org, flagged, ipblock, ts in rows:
|
||||||
|
flag = "FLAGGED" if flagged else "-"
|
||||||
|
ipb = "ipblock=yes" if ipblock else "ipblock=no"
|
||||||
|
print(f"{ts} {acct or \"\":20s} {ip or \"\":16s} {classification or \"\":12s} {flag:8s} {ipb:12s} {org or \"\"}")
|
||||||
|
'
|
||||||
Reference in New Issue
Block a user