Repository navigation
Clear the Discord Banned role when a ban ends - #31
Conversation
The ban mirror never ran: it listened for Essentials' BanStatusChangeEvent, which EssentialsX 2.22 does not have, so every startup logged "ban mirror disabled". Staff added the Banned role by hand with /minecraftban and nothing ever took it off, so players stayed muted on Discord after their ban ended. Poll the server's player ban list instead (where /ban, /tempban and /unban all write) and post the differences to the moderation outbox. New entries post a ban; removed entries post an unban; timed bans post an unban once their expiry passes, labelled "Ban expired". The bot already removes the role on unban. Mirrored bans are kept in ban-mirror.yml so restarts do not resend them. On the first run the current list is adopted without notifying anyone. Reasons and names are cleaned to what the API accepts, since reasons such as "(3.1) | Griefing" were rejected. Failed posts are retried every poll, with one warning per player. ban-mirror.enabled and ban-mirror.poll-seconds (default 30) control it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (12)
💤 Files with no reviewable changes (3)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review. 📝 SummarySummary by CodeRabbit
WalkthroughThe plugin replaces Essentials ban-event handling with polling of the profile ban list. It sends detected bans, unbans and expired timed bans to ProvinceSystem. Configuration controls the polling interval and whether mirroring is enabled. ChangesBan-list moderation mirroring
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant BanMirrorPoller
participant ProfileBanList
participant LinkCache
participant ProvinceSystemClient
participant BanMirrorFile
BanMirrorPoller->>ProfileBanList: Read current profile bans
ProfileBanList-->>BanMirrorPoller: Return ban records
BanMirrorPoller->>LinkCache: Check for a cached player identity
LinkCache-->>BanMirrorPoller: Return cached identity when available
BanMirrorPoller->>ProvinceSystemClient: Resolve identity or post moderation event
ProvinceSystemClient-->>BanMirrorPoller: Return identity or API result
BanMirrorPoller->>BanMirrorFile: Save known ban state
Suggested reviewers: Merge Risk: ⚪ Minimal · up to No actionable issue is established that would prevent merging after normal checks. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to The change improves ban-expiry synchronization, but a failed state save can leave Discord moderation out of sync after a restart. Account-link reconciliation and duplicate-delivery behavior also depend on guarantees not available for review. Retained concerns
Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
Comment |
A 2 minute ban seen 18 s later on Dev was sent as "1m"; a 7 day ban would have shown "6 days". Measure from the ban's created time. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Dev test (TFMCDev01, dev API on :18001)Tested with a linked test account. Dev's outbox is not polled by the live bot. The test rows were marked delivered afterwards.
The 2 m ban was first reported as 🤖 Generated with Claude Code |
|
@coderabbitai review |
|
Fixes the bug report "banned people on Discord keep the role after their ban is lifted".
Cause
The in-game → Discord ban mirror never ran. It listened for Essentials'
BanStatusChangeEvent, which EssentialsX 2.22 does not have, so every startup on Main logged:The ProvinceSystem moderation outbox has never held a ban or unban row. Staff added the Banned role by hand with
/minecraftban, and nothing ever removed it. Timed bans also expire without any event, so they could not have cleared the role even if the listener had registered.Change
EssentialsBanListenerwithBanMirrorPoller. It reads the server's profile ban list every 30 s (/ban,/tempban,/unbanand/pardonall write to it) and posts the differences to/skins/moderation/ban-events:ban, with the reason, duration and source (the bot sends the DM and adds the role)unbanunbanwith issuer "Ban expired". The entry may stay inbanned-players.jsonuntil the player logs in, but it is treated as ended.plugins/TFMCWeb/ban-mirror.yml, so restarts don't resend them. On the first run the current list is adopted without notifying anyone, so there is no flood of DMs when this is deployed.|become spaces. Reasons already on Main, likeNot using RP chats correctly (3.1) | Gri…, would otherwise be rejected with a 400.ban-mirror.enabled(defaulttrue) andban-mirror.poll-seconds(default30). If the keys are missing, these defaults apply, so existing live configs need no edit.No bot or ProvinceSystem changes are needed: the bot already removes the Banned role on
unban.Not covered
/minecraftbanfor someone who was never banned in-game is not tracked.Testing
mvn clean verify: 107 tests pass and the 100% line coverage gate is met. NewBanMirrorPollerTestcovers first-run adoption, restart persistence, ban/unban/expiry/re-ban, API failure retry, overlapping ticks, ban-list errors and text cleaning.🤖 Generated with Claude Code