Pin co-op invite posts; unpin on lock/cancel

Adds Base.PinEvent / Base.UnpinEvent helpers (m.room.pinned_events state)
that read-modify-write the existing pin list — idempotent on both sides.
The bot needs power level for state events; failures are logged but not
fatal.

Schema: add coop_dungeon_runs.invite_post_id to remember which event to
unpin. Migration entry included.

Wired:
- !coop start: pin the invite post in the games room
- !coop cancel: unpin before posting cancellation
- coopProcessLocks (auto-lock or auto-cancel): unpin before lock/expiry post

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-04-26 10:24:21 -07:00
parent 91af4f1e83
commit f3d1e65bf1
5 changed files with 86 additions and 3 deletions

View File

@@ -68,6 +68,9 @@ func (p *AdventurePlugin) coopProcessLocks() {
_ = setCoopRunStatus(run.ID, "cancelled")
gr := gamesRoom()
if gr != "" {
if run.InvitePostID != "" {
_ = p.UnpinEvent(gr, run.InvitePostID)
}
_ = p.SendMessage(gr, fmt.Sprintf("⚔️ Tier %d Co-op #%d expired with no party. Cancelled.", run.Tier, run.ID))
}
_ = p.SendDM(run.LeaderID, fmt.Sprintf("Co-op #%d expired before anyone joined. No party, no run.", run.ID))
@@ -94,6 +97,9 @@ func (p *AdventurePlugin) coopProcessLocks() {
fresh, _ := loadCoopRun(run.ID)
gr := gamesRoom()
if gr != "" {
if run.InvitePostID != "" {
_ = p.UnpinEvent(gr, run.InvitePostID)
}
_ = p.SendMessage(gr, renderCoopLock(fresh, members, p))
}
// Per-player DM with funding instructions.