feat: persist invite-joined channels for auto-rejoin on connect
When the bot accepts an admin INVITE, the channel is stored in bot.state under chanmgmt/autojoin:<channel>. On reconnect, persisted channels are rejoined alongside configured ones. If the bot is kicked, the channel is removed from the auto-rejoin list. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -103,7 +103,8 @@ IRC operators are auto-detected via WHO on connect and on user JOIN
|
||||
!mode +o nick # Give ops
|
||||
```
|
||||
|
||||
Auto-joins channels when invited by an admin/ircop.
|
||||
Auto-joins channels when invited by an admin/ircop. Persists across restarts.
|
||||
Removed from auto-rejoin list if bot is kicked.
|
||||
|
||||
## State Store (admin)
|
||||
|
||||
|
||||
@@ -302,7 +302,10 @@ The bot must have channel operator status for these commands to take effect.
|
||||
### Invite Auto-Join
|
||||
|
||||
When an admin or IRC operator sends an `INVITE`, the bot automatically joins
|
||||
the target channel. Non-admin invites are silently ignored.
|
||||
the target channel and persists it for auto-rejoin on reconnect. Non-admin
|
||||
invites are silently ignored. If the bot is kicked from a persisted channel,
|
||||
it is removed from the auto-rejoin list. Channels already in the config
|
||||
`[bot] channels` are skipped (they rejoin via the normal path).
|
||||
|
||||
## Plugin State Persistence
|
||||
|
||||
|
||||
@@ -85,6 +85,23 @@ async def cmd_mode(bot, message):
|
||||
await bot.mode(message.target, mode_str, *args)
|
||||
|
||||
|
||||
@event("001")
|
||||
async def on_connect(bot, message):
|
||||
"""Rejoin channels persisted from previous invite-joins."""
|
||||
from derp.irc import format_msg
|
||||
|
||||
configured = set(bot.config["bot"]["channels"])
|
||||
for key in bot.state.keys("chanmgmt"):
|
||||
if not key.startswith("autojoin:"):
|
||||
continue
|
||||
channel = key[len("autojoin:"):]
|
||||
if channel in configured:
|
||||
continue
|
||||
log.info("rejoining %s (autojoin)", channel)
|
||||
await bot.join(channel)
|
||||
await bot.conn.send(format_msg("WHO", channel))
|
||||
|
||||
|
||||
@event("INVITE")
|
||||
async def on_invite(bot, message):
|
||||
"""Join a channel when invited by an admin or IRC operator."""
|
||||
@@ -96,3 +113,17 @@ async def on_invite(bot, message):
|
||||
return
|
||||
log.info("accepting invite to %s from %s", channel, message.nick)
|
||||
await bot.join(channel)
|
||||
bot.state.set("chanmgmt", f"autojoin:{channel}", message.nick)
|
||||
|
||||
|
||||
@event("KICK")
|
||||
async def on_kick(bot, message):
|
||||
"""Remove autojoin if the bot is kicked from a channel."""
|
||||
if len(message.params) < 2:
|
||||
return
|
||||
kicked = message.params[1]
|
||||
if kicked != bot.nick:
|
||||
return
|
||||
channel = message.target
|
||||
if bot.state.delete("chanmgmt", f"autojoin:{channel}"):
|
||||
log.info("removed autojoin for %s (kicked)", channel)
|
||||
|
||||
Reference in New Issue
Block a user