No description
Find a file
forgejo-actions 46eb648c44 chore(release): 1.8.0 [skip ci]
# [1.8.0](http://forgejo:3000/ircforever/managebot/compare/v1.7.1...v1.8.0) (2026-06-17)

### Features

* add !help IRC command ([d7d7aab](d7d7aabe2b))
2026-06-17 18:59:36 +00:00
.forgejo/workflows feat: self-update from releases + publish OpenBSD binary, version stamping 2026-06-17 12:29:22 -04:00
cmd Initial commit: managebot — IRCNow BNC auto-approval bot 2026-06-16 10:05:21 -04:00
config feat: gate activation behind email verification 2026-06-17 14:34:39 -04:00
db feat: gate activation behind email verification 2026-06-17 14:34:39 -04:00
internal feat: add !help IRC command 2026-06-17 14:55:05 -04:00
test/integration Initial commit: managebot — IRCNow BNC auto-approval bot 2026-06-16 10:05:21 -04:00
web feat: oper-based real-IP capture, reevaluate action, dashboard pagination 2026-06-17 13:34:17 -04:00
.dockerignore Add Logto-OIDC dashboard, management console, and activity log 2026-06-17 08:37:03 -04:00
.env.example Add Logto-OIDC dashboard, management console, and activity log 2026-06-17 08:37:03 -04:00
.gitignore Add Logto-OIDC dashboard, management console, and activity log 2026-06-17 08:37:03 -04:00
.releaserc.json feat: self-update from releases + publish OpenBSD binary, version stamping 2026-06-17 12:29:22 -04:00
CHANGELOG.md chore(release): 1.8.0 [skip ci] 2026-06-17 18:59:36 +00:00
docker-compose.yml Initial commit: managebot — IRCNow BNC auto-approval bot 2026-06-16 10:05:21 -04:00
Dockerfile Add Logto-OIDC dashboard, management console, and activity log 2026-06-17 08:37:03 -04:00
go.mod Add Logto-OIDC dashboard, management console, and activity log 2026-06-17 08:37:03 -04:00
go.sum Add Logto-OIDC dashboard, management console, and activity log 2026-06-17 08:37:03 -04:00
Makefile Initial commit: managebot — IRCNow BNC auto-approval bot 2026-06-16 10:05:21 -04:00
README.md Initial commit: managebot — IRCNow BNC auto-approval bot 2026-06-16 10:05:21 -04:00

managebot

An IRC bot that automates IRCNow bouncer (BNC) approvals. It replaces the manual !bnc approve workflow with two questions answered automatically:

  1. Is this a real person? — email verification (click a link or !verify <code>), plus MX/disposable-domain checks and IRC client signals (TLS, CTCP).
  2. 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.yml publishes Postgres on 5432. If that port is busy, change the published port or run migrations through the migrate service 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/*blockuser control 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)