Skip to content

Add server wipe detection#53

Merged
HandyS11 merged 15 commits into
developfrom
feat/wipe-detection
Jul 15, 2026
Merged

Add server wipe detection#53
HandyS11 merged 15 commits into
developfrom
feat/wipe-detection

Conversation

@HandyS11

Copy link
Copy Markdown
Owner

Summary

Adds server wipe detection to RustPlusBot. When the Rust server wipes, the bot now detects it on reconnect, announces it in the per-server #events channel, and purges all paired smart devices so no stale devices or dead alarm notifications survive the wipe.

Design spec: docs/superpowers/specs/2026-07-15-wipe-detection-design.md

What it does

  • Detection — a new RustPlusBot.Features.Wipes project checks each reconnect transition (ConnectionStatusChangedEvent with IsConnected && !WasConnected), diffing live wipe time / map seed / map size against a baseline persisted on the RustServer row (new WipeDetection migration adds LastWipeTimeUtc, LastMapSeed, LastMapSize). A wipe fires when the wipe time advances beyond a 60s jitter tolerance, or the seed/size changes — so wipes that happen while the bot is offline are still caught on the next connect. The first observation after deploy backfills the baseline silently (no false announcement on upgrade).
  • Announcement — a localized (en/fr) embed in #events: wiped-at relative timestamp, new map size + seed, and a re-pair reminder.
  • @everyone ping — a new toggle button in the global #settings message (PingEveryoneOnWipe, default off).
  • Device purge — Alarms, Switches, and StorageMonitors each subscribe to ServerWipedEvent and delete their DB rows first (the stale-notification guarantee — a late trigger for a dead entity finds no row and is dropped), then best-effort delete their Discord embeds. Idempotent; missing channel/message tolerated.
  • The map needs no handling — RustMaps generation already keys on (size, seed), so the new seed regenerates it automatically.

Testing

  • Full solution build clean (39 projects, -warnaserror).
  • 1028 passed / 1 skipped across 18 test assemblies (36 new tests).
  • No EF model drift; jb cleanupcode gate clean.

Notes

  • Detection is event-driven (reacts to the existing connection-status event); ConnectionSupervisor is untouched.
  • Spec deviation (documented in the plan): the PairedEntity purge was dropped — nothing in production writes that table.
  • dotnet ef in this repo must use --startup-project src/RustPlusBot.Persistence (Host fails on a pre-existing packaging quirk).

🤖 Generated with Claude Code

HandyS11 and others added 14 commits July 15, 2026 20:09
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 15, 2026 21:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “server wipe detection” feature to RustPlusBot that detects wipe signals on reconnect, announces the wipe in the per-server #events channel (optionally pinging @everyone), and purges paired smart-device state so stale entities/notifications don’t survive a wipe.

Changes:

  • Introduces RustPlusBot.Features.Wipes (detector + hosted service + announcer + embed renderer + Discord poster) and the ServerWipedEvent abstraction event.
  • Persists a per-server wipe baseline (LastWipeTimeUtc, LastMapSeed, LastMapSize) and adds a guild toggle (PingEveryoneOnWipe) with a new #settings UI button.
  • Adds wipe purge handlers for Alarms, Switches, and StorageMonitors (DB rows removed first, then best-effort Discord message deletes), plus extensive test coverage.

Reviewed changes

Copilot reviewed 64 out of 66 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/RustPlusBot.Persistence.Tests/Workspace/WorkspaceStoreWipePingTests.cs Verifies PingEveryoneOnWipe default + upsert/round-trip behavior in WorkspaceStore.
tests/RustPlusBot.Persistence.Tests/Wipes/WipeBaselineStoreTests.cs Unit tests for reading/writing wipe baseline via IWipeBaselineStore.
tests/RustPlusBot.Persistence.Tests/Servers/RustServerWipeColumnsTests.cs Migration/schema round-trip test for wipe baseline columns + guild ping default.
tests/RustPlusBot.Localization.Tests/StringsResourceParityTests.cs Updates expected localization key count for added wipe/settings strings.
tests/RustPlusBot.Features.Workspace.Tests/Messages/SettingsMessageRendererWipePingTests.cs Validates the settings message wipe-ping toggle button rendering.
tests/RustPlusBot.Features.Workspace.Tests/Messages/RendererTests.cs Adjusts renderer wiring to provide an IWorkspaceStore to settings renderer.
tests/RustPlusBot.Features.Workspace.Tests/Fakes/FakeWorkspaceStore.cs Extends fake workspace store with wipe-ping flag storage.
tests/RustPlusBot.Features.Wipes.Tests/WipeRegistrationTests.cs Ensures AddWipes() registers and resolves required services.
tests/RustPlusBot.Features.Wipes.Tests/WipeEmbedRendererTests.cs Verifies wipe announcement embed structure and localization.
tests/RustPlusBot.Features.Wipes.Tests/WipeDetectorTests.cs Covers wipe detection diff rules, tolerance, and backfill/noop behavior.
tests/RustPlusBot.Features.Wipes.Tests/WipeAnnouncerTests.cs Tests posting behavior including optional @everyone and culture selection.
tests/RustPlusBot.Features.Wipes.Tests/RustPlusBot.Features.Wipes.Tests.csproj Adds a dedicated test project for the new wipes feature.
tests/RustPlusBot.Features.Wipes.Tests/Hosting/WipesHostedServiceTests.cs Validates hosted service routes bus events to detector/announcer.
tests/RustPlusBot.Features.Switches.Tests/SwitchWipePurgerTests.cs Tests switch purge handler: remove rows + best-effort message deletes.
tests/RustPlusBot.Features.Switches.Tests/Hosting/SwitchesHostedServiceTests.cs Updates Switches hosted service tests for injected wipe purger.
tests/RustPlusBot.Features.StorageMonitors.Tests/StorageMonitorWipePurgerTests.cs Tests storage monitor purge handler behavior.
tests/RustPlusBot.Features.StorageMonitors.Tests/Hosting/StorageMonitorsHostedServiceTests.cs Updates StorageMonitors hosted service tests for injected wipe purger.
tests/RustPlusBot.Features.Alarms.Tests/Hosting/AlarmsHostedServiceTests.cs Updates Alarms hosted service tests for injected wipe purger.
tests/RustPlusBot.Features.Alarms.Tests/AlarmWipePurgerTests.cs Tests alarm purge handler behavior.
src/RustPlusBot.Persistence/Workspace/WorkspaceStore.cs Adds persistence accessors/mutator for GuildSettings.PingEveryoneOnWipe.
src/RustPlusBot.Persistence/Workspace/IWorkspaceStore.cs Extends workspace store contract with wipe-ping flag operations.
src/RustPlusBot.Persistence/Wipes/WipeBaselineStore.cs Implements baseline store over RustServer wipe baseline columns.
src/RustPlusBot.Persistence/Wipes/WipeBaseline.cs Defines WipeBaseline record (wipe time, seed, size).
src/RustPlusBot.Persistence/Wipes/IWipeBaselineStore.cs Adds interface for reading/writing wipe baseline.
src/RustPlusBot.Persistence/PersistenceServiceCollectionExtensions.cs Registers IWipeBaselineStore in persistence DI.
src/RustPlusBot.Persistence/Migrations/BotDbContextModelSnapshot.cs Updates EF snapshot with new guild/server wipe-related columns.
src/RustPlusBot.Persistence/Migrations/20260715195556_WipeDetection.Designer.cs EF migration designer for wipe detection schema changes.
src/RustPlusBot.Persistence/Migrations/20260715195556_WipeDetection.cs Migration adding wipe baseline columns + PingEveryoneOnWipe default false.
src/RustPlusBot.Persistence/Configurations/RustServerConfiguration.cs Configures conversions for new uint? seed/size columns to SQLite-friendly types.
src/RustPlusBot.Localization/Strings.resx Adds English strings for wipe embed + settings wipe-ping toggle labels.
src/RustPlusBot.Localization/Strings.fr.resx Adds French strings for wipe embed + settings wipe-ping toggle labels.
src/RustPlusBot.Host/RustPlusBot.Host.csproj References the new wipes feature project from the host.
src/RustPlusBot.Host/Program.cs Registers wipes feature via builder.Services.AddWipes().
src/RustPlusBot.Features.Workspace/Modules/SettingsComponentModule.cs Adds interaction handler to toggle wipe-ping flag and re-render settings.
src/RustPlusBot.Features.Workspace/Messages/SettingsMessageRenderer.cs Renders wipe-ping toggle button in global settings message.
src/RustPlusBot.Features.Wipes/WipeServiceCollectionExtensions.cs Adds DI setup for wipes feature components and hosted service.
src/RustPlusBot.Features.Wipes/RustPlusBot.Features.Wipes.csproj New wipes feature project definition and references.
src/RustPlusBot.Features.Wipes/Rendering/WipeEmbedRenderer.cs Renders localized wipe announcement embed.
src/RustPlusBot.Features.Wipes/Posting/IWipeChannelPoster.cs Defines posting abstraction for wipe announcements.
src/RustPlusBot.Features.Wipes/Posting/DiscordWipeChannelPoster.cs Posts wipe announcements to Discord via gateway client.
src/RustPlusBot.Features.Wipes/Hosting/WipesHostedService.cs Subscribes to connection-status and wipe events to trigger detection/announce.
src/RustPlusBot.Features.Wipes/Detection/WipeDetector.cs Implements diff rules against persisted baseline and publishes ServerWipedEvent.
src/RustPlusBot.Features.Wipes/Detection/IWipeDetector.cs Defines wipe detector contract.
src/RustPlusBot.Features.Wipes/Announcing/WipeAnnouncer.cs Locates #events, resolves culture + ping flag, and posts wipe embed.
src/RustPlusBot.Features.Wipes/Announcing/IWipeAnnouncer.cs Defines wipe announcer contract.
src/RustPlusBot.Features.Switches/SwitchServiceCollectionExtensions.cs Registers switch wipe purger for event-driven purge.
src/RustPlusBot.Features.Switches/Relaying/SwitchWipePurger.cs Purges switches (DB first, then message deletes) on ServerWipedEvent.
src/RustPlusBot.Features.Switches/Posting/ISwitchChannelPoster.cs Extends poster contract to support message deletion.
src/RustPlusBot.Features.Switches/Posting/DiscordSwitchChannelPoster.cs Implements best-effort raw message deletes via gateway client.
src/RustPlusBot.Features.Switches/Hosting/SwitchesHostedService.cs Adds ServerWipedEvent subscription loop to invoke switch purge.
src/RustPlusBot.Features.StorageMonitors/StorageMonitorServiceCollectionExtensions.cs Registers storage monitor wipe purger.
src/RustPlusBot.Features.StorageMonitors/Relaying/StorageMonitorWipePurger.cs Purges storage monitors on wipe event.
src/RustPlusBot.Features.StorageMonitors/Posting/IStorageMonitorChannelPoster.cs Extends poster contract to support message deletion.
src/RustPlusBot.Features.StorageMonitors/Posting/DiscordStorageMonitorChannelPoster.cs Implements storage monitor message deletes via gateway client.
src/RustPlusBot.Features.StorageMonitors/Hosting/StorageMonitorsHostedService.cs Adds wipe-purge event loop for storage monitors.
src/RustPlusBot.Features.Alarms/Relaying/AlarmWipePurger.cs Purges alarms on wipe event.
src/RustPlusBot.Features.Alarms/Posting/IAlarmChannelPoster.cs Extends alarm poster contract to support message deletion.
src/RustPlusBot.Features.Alarms/Posting/DiscordAlarmChannelPoster.cs Adds alarm message deletion implementation.
src/RustPlusBot.Features.Alarms/Hosting/AlarmsHostedService.cs Adds wipe-purge loop subscription for alarms.
src/RustPlusBot.Features.Alarms/AlarmServiceCollectionExtensions.cs Registers alarm wipe purger in DI.
src/RustPlusBot.Domain/Servers/RustServer.cs Adds persisted wipe baseline properties to the server entity.
src/RustPlusBot.Domain/Guilds/GuildSettings.cs Adds PingEveryoneOnWipe flag to guild settings.
src/RustPlusBot.Abstractions/Events/ServerWipedEvent.cs Introduces cross-feature wipe event contract.
RustPlusBot.slnx Adds wipes feature and test projects to the solution.
docs/superpowers/specs/2026-07-15-wipe-detection-design.md Adds the design spec documenting wipe detection approach and decisions.
Files not reviewed (1)
  • src/RustPlusBot.Persistence/Migrations/20260715195556_WipeDetection.Designer.cs: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +29 to +34
await channel.SendMessageAsync(
content,
embed: embed,
options: options,
allowedMentions: AllowedMentions.All)
.ConfigureAwait(false);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in 249beb1. PostAsync now passes AllowedMentions.None for embed-only posts (content is null) and keeps AllowedMentions.All only when explicit ping content is present, so incidental mention-like text in the localized embed can never ping. Ping behavior on the @everyone path is unchanged.

Only pass AllowedMentions.All when ping content is present; use
AllowedMentions.None for embed-only posts so incidental mention-like
text in the localized embed cannot ping users or roles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@HandyS11
HandyS11 merged commit 54263a4 into develop Jul 15, 2026
3 checks passed
@HandyS11
HandyS11 deleted the feat/wipe-detection branch July 15, 2026 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants