diff --git a/README.md b/README.md new file mode 100644 index 0000000..94b989b --- /dev/null +++ b/README.md @@ -0,0 +1,196 @@ +# anope21-contrib + +Custom third-party modules for [Anope IRC Services **2.1**](https://www.anope.org/) by +Jean "reverse" Chevronnet. + +| Module | Purpose | +| ------ | ------- | +| [`m_apiauth`](#m_apiauth) | Authenticate users against an external HTTP API instead of the internal Anope database, with optional SASL SCRAM-SHA-256/512 support. | +| [`m_nickserv_oauth`](#m_nickserv_oauth) | Adds `NickServ IDENTIFYOAUTH` for JWT/OAuth token login (used by web chat clients). | +| [`m_youtube`](#m_youtube) | BotServ reads YouTube links posted in channels and replies with video details. | + +> These are **contrib** modules — they are not part of the Anope core and are +> not supported by the Anope team. Test on a staging network before deploying. + +--- + +## Building & installing + +Anope 2.1 builds third-party modules from `modules/third/`. Drop the `.cpp` +files there (or symlink this repo), then configure and build: + +```bash +# from your Anope source tree +cp /path/to/anope21-contrib/*.cpp modules/third/ +./Config # regenerate the build +cd build +make -j$(nproc) +make install +``` + +Each module declares its own build/link requirements at the top of the source +file (parsed by Anope's CMake glue). Install the dependencies below **before** +building, or the affected module will be skipped: + +| Module | Build dependencies | +| ------ | ------------------ | +| `m_apiauth` | OpenSSL (`libssl`/`libcrypto`), libcurl, [`nlohmann/json`](https://github.com/nlohmann/json), [`jwt-cpp`](https://github.com/Thalhammer/jwt-cpp) | +| `m_nickserv_oauth` | OpenSSL (`libssl`/`libcrypto`), [`jwt-cpp`](https://github.com/Thalhammer/jwt-cpp) | +| `m_youtube` | libcurl, OpenSSL, [`yyjson`](https://github.com/ibireme/yyjson) | + +On Debian/Ubuntu the system packages are roughly: + +```bash +sudo apt install libssl-dev libcurl4-openssl-dev nlohmann-json3-dev +# jwt-cpp and yyjson are header/lib-only; install from source or your package manager +``` + +After installing, load and configure each module in your Anope configuration +(typically `modules.conf` / your services config). Every example below is a +`module { ... }` block — add it and `/msg OperServ RELOAD` (or restart) to apply. + +--- + +## m_apiauth + +Delegates NickServ authentication to an external HTTP API. When a user +identifies, Anope POSTs (or GETs) the credentials to your endpoint; a `2xx` +response authenticates the user. Optionally validates JWTs returned by the API +and provides SASL **SCRAM-SHA-256** / **SCRAM-SHA-512** mechanisms. + +```ini +module +{ + name = "m_apiauth" + + # ── External auth endpoint ─────────────────────────────── + api_url = "https://accounts.example.com/api/login_token/" + api_method = "POST" # POST (default) or GET + api_username_param = "username" # form field carrying the nick + api_password_param = "password" # form field carrying the password + api_email_field = "email" # JSON field to read the email back from + api_key = "changeme-shared-secret" # sent to the API; keep secret + + # ── TLS verification for the API call ──────────────────── + verify_ssl = "true" # "true"/"false" + #capath = "/etc/ssl/certs" # optional CA directory + #cainfo = "/etc/ssl/cert.pem" # optional CA bundle file + + # ── Optional JWT validation of the API response ────────── + # Leave jwt_secret empty to skip signature verification. + jwt_secret = "your-hmac-signing-secret" + jwt_issuer = "accounts.example.com" + + # ── User-facing URLs shown in replies ──────────────────── + profile_url = "https://accounts.example.com/profile/%s/" # %s = account + register_url = "https://accounts.example.com/register/" + + # ── Redirect built-in commands to the web app (optional) ─ + # If set, these NickServ commands are blocked with the given reason. + disable_reason = "Please register on the website: https://accounts.example.com/register/" + disable_email_reason = "Change your email address on the website instead." + + # ── Optional group/role sync endpoint ──────────────────── + #group_api_url = "https://accounts.example.com/api/groups/" + + # ── SASL SCRAM mechanisms (optional) ───────────────────── + enable_sasl_scram_sha256 = "yes" # advertise SCRAM-SHA-256 (default yes) + enable_sasl_scram_sha512 = "no" # advertise SCRAM-SHA-512 (default no) + scram_iterations = "4096" # PBKDF2 iteration count + scram_saltlen = "16" # salt length in bytes + #scram_debug = "no" # verbose SASL logging + #scram_attr_b64_nopad = "no" # base64 without padding for SCRAM attrs +} +``` + +**Notes** +- `api_key` and `jwt_secret` are secrets — do not commit real values. +- The API must accept the configured `api_method` and return `2xx` on success. +- `%s` in `profile_url` is replaced with the account name. +- SCRAM verifiers are stored per-account; enabling SCRAM requires the API/flow + to provision them. + +--- + +## m_nickserv_oauth + +Adds the `IDENTIFYOAUTH` command to NickServ, letting a user identify with a +JWT bearer token instead of a password. Intended to be driven automatically by +a web chat client after the user logs into your web app. + +```ini +module +{ + name = "m_nickserv_oauth" + + # HMAC secret used to verify the JWT signature (HS256). + # If left empty, signature verification is DISABLED (not recommended). + jwt_secret = "your-hmac-signing-secret" + + # Expected "iss" claim. Only enforced when both this and the token set it. + jwt_issuer = "accounts.example.com" +} +``` + +**Usage** + +``` +/msg NickServ IDENTIFYOAUTH YourNick eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +The token's `sub` / `name` / `username` claim must match the requested account, +and the token must not be expired (`exp`). Tip: share the same `jwt_secret` and +`jwt_issuer` here and in `m_apiauth` so one signing key covers both flows. + +--- + +## m_youtube + +A BotServ add-on: when a channel bot sees a YouTube link, it fetches the video +details from the YouTube Data API v3 and posts a formatted reply. Includes an +anti-spam throttle and a persistent cache. + +```ini +module +{ + name = "m_youtube" + + # YouTube Data API v3 key (required). + youtube_api_key = "AIza...your-key..." + + # ── Reply formatting ───────────────────────────────────── + prefix = "\x02\x03""01,00You\x03""00,04Tube\x0F\x02" # colored "YouTube" tag + duration_text = "Duration: " + seen_text = "Seen: " + times_text = " times." + #response_format = "" # optional custom format string + + # ── Anti-spam (per channel) ────────────────────────────── + spam_limit = "3" # max links... + spam_window = "60" # ...per this many seconds + spam_kick = "yes" # kick offenders? + spam_kick_reason = "YouTube link spam" + cache_ttl = "300" # video-info cache lifetime (seconds) +} +``` + +**Commands** (require the `SAY` channel privilege or `botserv/administration`): + +| Command | Description | +| ------- | ----------- | +| `BotServ youtube` | Handle/announce a YouTube link. | +| `BotServ ytstats` | Show module usage statistics. | + +**Notes** +- Get an API key from the [Google Cloud Console](https://console.cloud.google.com/) + with the **YouTube Data API v3** enabled. +- The cache is persisted to `m_youtube.module.json` in the Anope data directory. +- Assign the BotServ bot to a channel (`/msg BotServ ASSIGN #chan Bot`) for link + detection to work there. + +--- + +## License + +Unless a source file states otherwise, these modules are distributed under the +**GNU General Public License**. See the header of each `.cpp` file for details.