# [1.8.0](http://forgejo:3000/ircforever/managebot/compare/v1.7.1...v1.8.0) (2026-06-17) ### Features * add !help IRC command ([ |
||
|---|---|---|
| .forgejo/workflows | ||
| cmd | ||
| config | ||
| db | ||
| internal | ||
| test/integration | ||
| web | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .releaserc.json | ||
| CHANGELOG.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| Makefile | ||
| README.md | ||
managebot
An IRC bot that automates IRCNow bouncer (BNC) approvals. It replaces the manual
!bnc approve workflow with two questions answered automatically:
- Is this a real person? — email verification (click a link or
!verify <code>), plus MX/disposable-domain checks and IRC client signals (TLS, CTCP). - Is this someone farming multiple accounts? — correlation across IP,
subnet (/24 & /64), normalized email (catches
j.o.h.n+x@gmail), and similar nicks, plus DNSBL / Tor-exit / hosting-ASN reputation on the connecting IP.
Each request gets an additive risk score. Below CHECK_APPROVE_THRESHOLD it
is auto-approved; at/above CHECK_REJECT_THRESHOLD it is auto-rejected; in
between it is escalated to staff in the team channel with the evidence and
!approve / !reject buttons.
The only thing kept compatible with the old system is the ZNC control
convention: accounts are created via *controlpanel AddUser, gated with
*blockuser block (created blocked), approval = unblock, rejection = DelUser.
Architecture
Layered (per team Go standards): cmd → commands → services → repositories → db.
Repositories are only used by services; everything is interface-driven and wired
by DI in internal/commands/serve.go.
cmd/main.go entry point
config/ env-driven config (configor)
db/ embedded migrations (golang-migrate)
internal/
commands/ cobra CLI: serve, migrate up|down
db/ gorm connection + repositories (request, sighting, decision)
checks/ signal detectors: ip (DNSBL/Tor/ASN), email (MX/disposable/normalize), similarity
services/risk/ aggregates checks + correlation -> verdict
services/approval/ lifecycle orchestrator (intake -> verify -> assess -> act)
znc/ ZNC control-module driver
irc/ girc client: command routing + WHOIS enrichment
http/ click-to-verify web endpoint + healthz
mail/ SMTP verification emails
Verification (either method works)
On !bnc <username> <email> the bot creates the account blocked, emails a
code, and waits. The user activates with either:
- clicking
HTTP_BASE_URL/verify?token=...from the email, or - typing
!verify <code>on IRC.
Only after verification does the risk engine run.
Running
# Local dev
cp .env.example .env # fill in IRC_PASSWORD etc.
make setup # starts postgres (compose) + runs migrations
make run # go run cmd/main.go serve
# Docker (production)
docker compose up -d # postgres + managebot
docker compose run --rm migrate # apply migrations (profile: tools)
Note:
docker-compose.ymlpublishes Postgres on5432. If that port is busy, change the published port or run migrations through themigrateservice which talks to the container directly.
Configuration
All via environment variables — see .env.example and config/config.go. Key knobs:
| Var | Default | Purpose |
|---|---|---|
IRC_SERVER / IRC_PORT / IRC_PASSWORD |
— | ZNC/IRC login (user/network:pass) |
IRC_STAFF |
— | comma-separated nicks allowed !approve/!reject |
HTTP_BASE_URL |
http://localhost:8080 |
origin used in verification links |
SMTP_* |
mail.ircforever.org:25 |
verification email delivery |
CHECK_APPROVE_THRESHOLD |
20 |
auto-approve at/below |
CHECK_REJECT_THRESHOLD |
60 |
auto-reject at/above |
CHECK_FLAGGED_ASNS |
— | hosting/VPN AS numbers to penalize |
CHECK_DNSBLS |
spamhaus,barracuda,dronebl | DNS blocklists |
Tests
make test # unit tests
go test -race ./... # unit tests, race detector
# Integration (build-tagged `integration`):
go test -tags=integration ./test/integration/...
- Unit: pure check logic (normalize/disposable/similarity/subnet), the ZNC command contract, the risk verdict thresholds + dedupe signals (mocked detectors), and the full approval lifecycle (in-memory fakes).
- Integration:
postgres_test.go— real Postgres via env (DBHOST/DBPORT/...), runs migrations and exercises every repository. Skips if the DB is unreachable.irc_znc_test.go— spins up an in-process IRC server, connects a real girc client, injects a!bnc, and asserts the bot WHOISes the user and emits the correct*controlpanel/*blockusercontrol commands end to end.
Commands (IRC)
| Command | Who | Effect |
|---|---|---|
!bnc <username> <email> |
anyone | request a bouncer; creates blocked account + sends verification |
!verify <code> |
requester | confirm email, triggers checks |
!approve <username> |
staff | override-approve (unblock) |
!reject <username> |
staff | override-reject (deluser) |