mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-10 19:37:03 +01:00
./web.sh serves health, the configuration and the photo album on 127.0.0.1:8140 -- the port tool/tagger.py vacates. React 19, Vite 8, TypeScript 6.0.3, ESLint 10 with strictTypeChecked + stylisticTypeChecked + unicorn + sonarjs + perfectionist, Vitest 4 at 100% on all four metrics. No coverage exclude list, including for main.tsx. This repository treats a coverage omit as a suppression, and "the DOM bootstrap is awkward to assert" is the same sentence as "this code is untested" -- so the bootstrap is a shim thin enough to test in jsdom, and the album view holds its file list apart from the album so the update path stopped carrying a "what if it is null" branch that cannot happen. An untestable branch is an untested one. TypeScript stays at 6.0.3: typescript-eslint 8.68.0 declares typescript >=4.8.4 <6.1.0, and the fleet-wide allowlist entry says the compiler waits for the linter. The freshness gate then caught two pins the reference repo was carrying stale -- eslint-plugin-unicorn 73 -> 74 and a floating node-version: "24" in CI -- both bumped rather than allowlisted. Traps the gates found, all of them real: - .gitignore has a bare lib/, which matches at any depth, so web/src/lib/ would have been silently untracked. The source lives in src/api/. - CI's shellcheck glob was `run.sh scripts/*.sh`, so tag.sh was unlinted in CI for its whole life and web.sh would have inherited that. Now ./*.sh. - tsconfig.json is strict JSON, not JSONC: check-json is generic and tsconfig being commentable is a convention, not a requirement. - The personal-data gate refused an invented phone number in a test, which is exactly what it is for. The album's warning that names a command moved with the command, and every path that pointed at tool/tagger.py now points at ./web.sh. The historical mentions stay: they explain why the code is shaped as it is. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01416TegJ3sa8xL5qGGgrygP
123 lines
5.4 KiB
Plaintext
123 lines
5.4 KiB
Plaintext
# Copy to .env and fill in. Every value here is read by signal_bot/config.py.
|
|
# The bot refuses to start if any REQUIRED value is missing or blank.
|
|
|
|
# REQUIRED. The account signal-cli is linked to, in +E.164 form.
|
|
PHONE_NUMBER=
|
|
|
|
# OPTIONAL, and normally left empty. Comma-separated group ids.
|
|
#
|
|
# Empty means "every group this account is a member of", discovered at
|
|
# runtime: adding the bot to a group is then the whole procedure, with no
|
|
# edit here and no restart. That is safe when the bot has its OWN number,
|
|
# because such an account has no other chats.
|
|
#
|
|
# Set it when the bot runs as a LINKED DEVICE on a personal account, where
|
|
# it would otherwise see every group on that account. scripts/live_smoke.sh
|
|
# writes it for you in that case; scripts/register_bot.sh deliberately does
|
|
# not. Startup fails if a listed group is not one the bot has joined.
|
|
#
|
|
# Find the ids with: curl -s localhost:9922/v1/groups/$PHONE_NUMBER | jq
|
|
#
|
|
# Replies, rate limits and the daily tally are per group either way: a
|
|
# command is answered in the group that asked and nowhere else, so there is
|
|
# no send target to configure. GROUP_ID is still accepted as the one-group
|
|
# spelling; GROUP_ID_SEND was removed and now fails startup if set.
|
|
GROUP_IDS=
|
|
|
|
# Optional. The signal-cli-rest-api container. Point this at the fake server
|
|
# to run entirely offline. Default: http://localhost:9922
|
|
API_BASE_URL=
|
|
|
|
# Optional. Tally database. Survives restarts. Default: signal_bot.sqlite3
|
|
DATABASE_PATH=
|
|
|
|
# Optional. When the daily tally is posted. Default: 21:37
|
|
REPORT_HOUR=
|
|
REPORT_MINUTE=
|
|
|
|
# Optional. Per-user, per-command cooldown in seconds. Default: 10
|
|
COOLDOWN_SECONDS=
|
|
|
|
# Optional but recommended. Comma-separated +E.164 numbers -- or member
|
|
# UUIDs, which is how /v1/groups spells anybody the account has never
|
|
# messaged -- allowed to add this bot to a group.
|
|
#
|
|
# Empty means anyone who knows the number can pull the bot into a group and
|
|
# have it answer there. With it set, "add the bot" is still the whole setup
|
|
# for you, and a stranger's group is refused with one WARNING naming that
|
|
# group's members, so you can see exactly which string to add here.
|
|
TRUSTED_INVITERS=
|
|
|
|
# Optional. How long the bot may hear nothing at all -- no message, no
|
|
# receipt, no typing indicator -- before it probes /v1/devices to find out
|
|
# whether it has gone deaf. Three failed probes and /healthz turns 503.
|
|
# Default: 120. scripts/e2e.sh sets it to 0 to prove the gate really fires.
|
|
SILENCE_SECONDS=
|
|
|
|
# Optional. Image APIs. Overridden by scripts/e2e.sh to serve local fixtures.
|
|
CAT_API_URL=
|
|
DOG_API_URL=
|
|
GECKO_API_URL=
|
|
COMMONS_API_URL=
|
|
|
|
# Optional. Where !papież keeps the 267 papal portraits it has downloaded.
|
|
# Default: $CACHE_DIRECTORY/portraits under systemd (the unit sets
|
|
# CacheDirectory=signal-bot), otherwise $XDG_CACHE_HOME/signal-bot/portraits.
|
|
PORTRAIT_CACHE_DIR=
|
|
|
|
# Optional. Groups scripts/selftest.sh may make the bot post into. Empty by
|
|
# default, which makes POST /_selftest refuse everything -- Signal never
|
|
# delivers an account its own sends, so this is the only way to exercise a
|
|
# command without a second account, and it posts for real.
|
|
SELFTEST_GROUPS=
|
|
|
|
# Optional, and private. The album the per-person photo commands draw
|
|
# from: a directory holding people.json, tags.json and media/. Everything
|
|
# identifying lives in there and nothing about it is in this repository --
|
|
# see DOCS-photo-pack.md, and ./web.sh for how it gets filled in.
|
|
#
|
|
# Leave it empty and the bot looks in $STATE_DIRECTORY/pack (systemd) and
|
|
# then $XDG_DATA_HOME/signal-bot/pack. Not finding one is normal: the
|
|
# commands simply do not exist. Naming one that is not there, or one whose
|
|
# manifest cannot be honoured, fails startup rather than every command.
|
|
PHOTO_PACK_DIR=
|
|
|
|
# Optional. Where the /healthz readiness probe binds.
|
|
# Default: 127.0.0.1:8137 -- deliberately not 8000, which unrelated dev
|
|
# servers grab, and below the ephemeral range so the kernel cannot take it.
|
|
BIND_HOST=
|
|
BIND_PORT=
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# scripts/signal_api_watchdog.sh -- the two-minute timer that restarts the
|
|
# container when signal-cli can no longer reach Signal. Every value here is
|
|
# optional; the defaults are what the timer has always used.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# What reaches the DESKTOP. journald gets every message either way, twice --
|
|
# `journalctl --user -t signal-api-watchdog` and `-u signal-api-watchdog`.
|
|
# escalation only the give-up message pops, and only once per window
|
|
# always every transition pops, reusing one replaceable slot
|
|
# never nothing pops
|
|
# Default: escalation. The routine restart/recovery pair is the noise this
|
|
# exists to stop -- it used to pop on every firing, with critical urgency and
|
|
# no replace id, so one outage left a screen of boxes to dismiss by hand.
|
|
WATCHDOG_NOTIFY=
|
|
|
|
# How long a popup stays up, in milliseconds. Default: 20000.
|
|
WATCHDOG_NOTIFY_EXPIRE_MS=
|
|
|
|
# Consecutive failed probes before the container is restarted. Default: 2.
|
|
FAILURES_BEFORE_RESTART=
|
|
|
|
# Restarts allowed inside RESTART_WINDOW before it gives up and escalates
|
|
# instead. A deregistered account is not fixable by restarting, and a
|
|
# forever-loop would hide that. Defaults: 3 restarts, 21600 seconds (6h).
|
|
MAX_RESTARTS=
|
|
RESTART_WINDOW=
|
|
|
|
# Seconds to wait after a restart before deciding whether it helped, and the
|
|
# per-probe curl timeout. Defaults: 45 and 15.
|
|
SETTLE_SECONDS=
|
|
PROBE_TIMEOUT=
|