Commit Graph
9 Commits
Author SHA1 Message Date
jaredandClaude Opus 5 fb933b0b13 feat(matrixbot): remove the auto-invite welcome flow entirely
Lint / JS (eslint) (push) Successful in 1m16s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 1m1s
Lint / Secret scan (gitleaks) (push) Successful in 7s
Lint / Shell (shellcheck) (push) Successful in 16s
Joining the Lotus Guild Space (join_rule: public) triggered a welcome DM;
reacting to it made the bot invite that user into a fixed room list. Now
that #general is published to the public room directory, any stranger can
join the Space and trigger this.

The room list excluded the invite-only rooms, but it included Voice, whose
join rule is `knock`. An invite bypasses a knock gate, so a stranger could
skip the approval step that rule exists to enforce.

Removes welcome.py, the Space-join watcher in Callbacks.member, both
welcome-reaction hooks, and the admin `cleanwelcome` command. The bot no
longer issues invites automatically anywhere. The PL50+ `invite` and
`inviteall` commands are untouched: those are deliberate admin actions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 15:46:36 -04:00
jaredandClaude Opus 5 9e5d3ec83d feat(matrixbot): stop auto-joining invites, restrict commands to two rooms
Lint / JS (eslint) (push) Successful in 40s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 1m44s
Lint / Secret scan (gitleaks) (push) Successful in 33s
Lint / Shell (shellcheck) (push) Successful in 11s
#general is now published to the public room directory, so the bot is
reachable by strangers. Two hardening changes:

- Invites are only accepted from INVITE_ALLOWED_USERS (defaults to
  ADMIN_USERS). Anything else is declined via room_leave so hostile
  invites do not accumulate as pending. Previously any invite from
  anyone was auto-joined.
- Commands and the passive scramble/riddle answer checks only run in
  COMMAND_ROOMS (#commands and #management). The gate sits early in
  Callbacks.message, so the bot stays silent everywhere else, including
  #general. Set COMMAND_ROOMS="*" to restore the old behaviour.

Reaction handlers are deliberately left ungated so the welcome flow
keeps working; game votes elsewhere cannot match an active game.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 01:37:45 -04:00
jaredandClaude Sonnet 4.6 54c73535b8 feat: add 9 new games and update help/README
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Failing after 5s
Lint / Python deps (pip-audit) (push) Successful in 41s
Lint / Secret scan (gitleaks) (push) Successful in 5s
New commands: numguess/ng, wordchain/wc/endwc, acronym/ac,
20q/q/answer, nhie, hottake, ttt/move, blackjack/hit/stand,
triviaduel/da. All per-room with AI-generated content where
applicable. callbacks.py wired up for new reaction handlers
(acronym votes, nhie, hottake). Help and README updated with
full command reference.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:29:23 -04:00
jaredandClaude Sonnet 4.6 80d77a8a0f fix: wyr votes never counted — reactions arrive as ReactionEvent not UnknownEvent
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 11s
Lint / Python deps (pip-audit) (push) Successful in 49s
Lint / Secret scan (gitleaks) (push) Successful in 5s
nio has a dedicated ReactionEvent type with .reacts_to and .key attributes.
The callback was registered for UnknownEvent so reaction events were silently
dropped. Register for ReactionEvent and use its native attributes; keep the
UnknownEvent fallback for edge cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 14:00:03 -04:00
jaredandClaude Sonnet 4.6 126979f5cb hangman: edit board in place + fix ASCII art rendering; wyr: debug reaction logging
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 44s
Lint / Secret scan (gitleaks) (push) Successful in 6s
- Add edit_html() to utils using m.replace so messages can be updated
- Hangman board now edits in place on every guess — shows progressing
  ASCII figure as wrong guesses accumulate instead of spamming new messages
- Extract _hangman_board_html() helper for consistent board rendering
- wyr: add INFO-level logging to reaction callback to diagnose vote tracking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 13:30:46 -04:00
jaredandClaude Sonnet 4.6 c9d9febbe0 wyr: track real reaction votes and announce winner with counts
Lint / Shell (shellcheck) (push) Successful in 27s
Lint / JS (eslint) (push) Successful in 14s
Lint / Python (ruff) (push) Successful in 11s
Lint / Python deps (pip-audit) (push) Successful in 45s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Add _WYR_POLLS dict keyed by poll event_id to accumulate votes
- record_wyr_vote() called from callbacks.reaction() on every reaction
- reveal() reads actual vote counts and announces winner with percentage
- Handles tie and zero-vote cases
- Remove the useless 'check the reactions above' message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 01:02:25 -04:00
jared 973e422678 feat: add 7 new commands — hangman, scramble, wyr, riddle, roast, story, debate
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Failing after 5s
Lint / Python deps (pip-audit) (push) Successful in 1m16s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- !hangman: AI picks a 5-8 letter word with hint; players !guess letters/words, 6 wrong = dead
- !scramble: AI picks a word, scrambles it; first correct answer in chat wins (45s timeout)
- !wyr: AI generates Would You Rather with 🅰️/🅱️ reaction voting, 30s reveal
- !riddle: AI generates riddle monitored for 60s, substring match in chat wins
- !roast: AI roasts a target using BALL_MODEL with special Jared/Wynter lore
- !story: collaborative story with !story add <line> and !story end (AI conclusion, max 10 lines)
- !debate: AI writes FOR/AGAINST arguments for any topic using ASK_MODEL
- callbacks.py: route all non-command messages through scramble/riddle answer checkers
- help: updated categories to include all new commands
2026-04-22 00:35:19 -04:00
jaredandClaude Sonnet 4.6 86cb78d74d Fix ruff lint errors across matrixbot (F401, F841, E402)
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 10s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 1m10s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Remove unused imports: logging from bot.py and config.py, RoomMessageText/
UnknownEvent from callbacks.py, functools.partial and MAX_INPUT_LENGTH from
commands.py. Rename unused local variables to _ (resp in cmd_ping, symbols in
render_keyboard_plain, guesses_left in two wordle functions). Move wordle import
to top of commands.py to fix E402.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:54:55 -04:00
jaredandClaude Sonnet 4.6 52c4781e64 Add matrixbot source to repo
All bot source files from LXC 151 (/opt/matrixbot) are now tracked here.
Secrets (.env, credentials.json), venv dirs, and runtime state files
(nio_store, welcome_state.json, wordle_stats.json) are excluded via .gitignore.
Includes deploy.sh to sync files to /opt/matrixbot and restart the service.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:16:38 -04:00