Defer JOIN until NickServ login confirmed (fixes +r channel 477)

This commit is contained in:
megaproxy 2026-06-04 17:25:18 +01:00
parent 841a152436
commit 52e579e364
2 changed files with 39 additions and 7 deletions

29
bot.py
View file

@ -173,8 +173,13 @@ class IRCBot:
time.sleep(backoff)
backoff = min(backoff * 2, 300)
def _join_channel(self):
log.info("Joining %s", CHANNEL)
self._send_raw(f"JOIN {CHANNEL}")
def _event_loop(self):
registered = False
joined = False
for line in self._read_lines():
log.debug("<< %s", line)
prefix, command, params = parse_message(line)
@ -183,15 +188,33 @@ class IRCBot:
self._send_raw(f"PONG :{params[-1] if params else ''}")
continue
# 376 = end of MOTD, 422 = no MOTD; either means we can join.
# 376 = end of MOTD, 422 = no MOTD; either means we're registered.
if command in ("376", "422") and not registered:
registered = True
if NICKSERV_PASS:
# Identify first, then wait for the login confirmation
# below before joining. +r channels reject us until the
# NickServ login has actually landed, so joining now races.
self.send_privmsg("NickServ", f"IDENTIFY {NICKSERV_PASS}")
log.info("Joining %s", CHANNEL)
self._send_raw(f"JOIN {CHANNEL}")
log.info("Identifying with NickServ; join deferred until login")
else:
self._join_channel()
joined = True
continue
# 900 RPL_LOGGEDIN, or the NickServ "now identified" notice —
# either confirms login is complete, so it's safe to join +r chans.
if not joined and registered and NICKSERV_PASS:
identified = command == "900" or (
command == "NOTICE"
and prefix.lower().startswith("nickserv!")
and "now identified" in (params[-1].lower() if params else "")
)
if identified:
self._join_channel()
joined = True
continue
# Nick already in use — try a variant so we still connect.
if command == "433":
global NICK

View file

@ -17,11 +17,16 @@ Durable memory for this project. Read at session start, update before session en
## Open questions / TODOs
- [ ] Live-test against Libera (join `#r.trees`, exercise commands). Not yet run.
- [ ] Exercise the `!` commands live in-channel (connect + join verified; command
round-trip not yet tested with a second client).
- [ ] Decide whether `!delquote` should be restricted to ops/admins (currently
anyone can delete). Fine for a trusted channel; revisit if abused.
- [ ] Consider registering the `treesquotes` nick with NickServ if the channel
blocks unregistered users.
## Resolved
- `#r.trees` is `+r` (registered-nicks-only). Nick `treesquotes` is registered &
NickServ-verified under megaproxy@gmail.com. Password lives in gitignored
`config.env` (`IRC_NICKSERV_PASS`). Bot identifies and joins successfully.
## Session log
@ -30,7 +35,11 @@ Durable memory for this project. Read at session start, update before session en
- Wrote `bot.py`: stdlib IRC client (TLS, PING/PONG, reconnect, nick fallback),
`QuoteStore` SQLite wrapper, and `!` command handlers.
- Added `README.md`, `config.example.env`; gitignored `quotes.db`/`config.env`.
- Syntax-checked with `py_compile` (Python 3.12.3). Not yet live-tested on IRC.
- Syntax-checked with `py_compile` (Python 3.12.3).
- Live-tested against Libera: discovered `#r.trees` is `+r`. Registered/verified
the `treesquotes` nick. Fixed a join race — bot was sending JOIN before the
NickServ login landed and getting bounced (477); now defers JOIN until the
`900`/"now identified" confirmation. Verified join succeeds (got 353/366).
## External references