feat: merge discord bot into Notifierr, drop RabbitMQ#91
Draft
Pouleyy wants to merge 7 commits into
Draft
Conversation
Folds the standalone PlexNotifierrDiscord repo into this solution as a new project hosted by the API process, so the system deploys as a single pod with no RabbitMQ broker between the worker and the bot. - New PlexNotifierr.Discord project: hosted service that owns the DiscordShardedClient, command handler, !subscribe/!unsubscribe/!help modules, and a DiscordNotificationSender that implements INotificationSender by DM-ing the user directly via Discord.Net. - New PlexNotifierr.Core.SubscriptionService: shared subscribe/ unsubscribe logic backed by IDbContextFactory so it can live as a singleton and be injected straight into the Discord module without a manual scope. - API host: registers the Discord bot, swaps AddDbContext for AddDbContextFactory + a scoped DbContext that resolves through it, drops the now-empty MVC/Scalar/Auth pipeline (only the Hangfire dashboard remains). - Removed RabbitMQ.Client + the old NotificationSender, RabbitMqConfig, PublicationExtensions, /subscription controller and its request models. docker-compose loses the rabbitmq service. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ob coverage Add xUnit + NSubstitute + Shouldly test projects: - PlexNotifierr.TestSupport: shared SQLite in-memory IDbContextFactory helper - PlexNotifierr.Core.Tests: SubscriptionService branch coverage - PlexNotifierr.Worker.Tests: GetRecentlyAddedJob behavior coverage Wire all three into the solution and run them in CI via `dotnet test`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PlexAccount members are non-virtual, so build a real PlexAccount over substituted Plex clients and stub GetFriendsAsync (what Friends() delegates to). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sode) Drives the paging loop with a single sub-limit page and asserts HistoryPosition advances to guard against the job's catch-all swallowing a misconfigured mock. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The old catch-all wrapped the whole page loop and only logged e.Message. When GetPlayHistory threw, isLastPage stayed false and offset never advanced, so the loop spun forever against a down Plex server. Restructure the error boundaries: - page fetch failure -> log with context + break (cursor untouched, next run retries) - per-show failure -> log + skip that show so the rest of the page still processes - save failure -> log + break Add regression tests for the fetch-failure (single call, no retry) and per-show-failure (skip one, process the rest, advance cursor) paths. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ender DiscordShardedClient and RestUser are concrete Discord.Net types with non-virtual members, so the sender could not be unit-tested. Extract a thin IDiscordUserGateway/IDiscordDmRecipient seam (production adapter forwards to the live client) so all notification logic stays in DiscordNotificationSender and becomes testable. Behavior is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New PlexNotifierr.Discord.Tests project (xUnit + NSubstitute + Shouldly): invalid id short-circuits the lookup, user-not-found and send-failure return false, and the happy path builds the templated text + embed (title/description/ image/colour) with the Plex link field toggled by config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
babariviere
approved these changes
May 29, 2026
babariviere
force-pushed
the
feat/merge-discord-bot
branch
from
June 5, 2026 06:15
9fc280e to
77deeca
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PlexNotifierrDiscordrepo into this solution as a newPlexNotifierr.Discordproject, hosted in-process by the API. The system now deploys as a single pod with no RabbitMQ broker between the worker and the bot.DiscordNotificationSenderimplementsINotificationSenderby DM-ing the user directly via Discord.Net, replacing the old RabbitMQ publish + separate consumer pod with one in-process call.PlexNotifierr.Core.SubscriptionService(backed byIDbContextFactory, singleton) holds the subscribe/unsubscribe logic so the Discord module can inject it via plain DI — no manual scope, no HTTP round trip.AddDbContextforAddDbContextFactory+ a scopedDbContextthat resolves through it, drops the now-empty MVC/Scalar/Auth pipeline (Hangfire dashboard at/dashboardis all that's left).RabbitMQ.Client, the oldNotificationSender,RabbitMqConfig,PublicationExtensions, the/subscriptioncontroller and its request models.docker-compose.yamlloses therabbitmqservice.Test plan
dotnet buildclean (5 projects, 0 errors)/dashboardreturns HTTP 200 with<title>Overview – Notifierr Dashboard</title>, clean SIGINT shutdown!help,!subscribe,!unsubscriberound tripGetRecentlyAddedJob🤖 Generated with Claude Code