From dfd5b7a8231de0b8922606467bcaf253a2aa038d Mon Sep 17 00:00:00 2001
From: Toastie <toastie@toastiet0ast.com>
Date: Sun, 1 Dec 2024 00:43:53 +1300
Subject: [PATCH] .setstream and .setactivity will now pause .ropl

---
 .../PlayingRotate/PlayingRotateCommands.cs    |   2 +-
 .../BotActivityService.cs}                    | 154 ++++++++++++------
 .../Self/IBotActivityService.cs               |  14 ++
 .../Administration/Self/SelfCommands.cs       |   9 +-
 .../Administration/Self/SelfService.cs        |  47 ------
 5 files changed, 122 insertions(+), 104 deletions(-)
 rename src/EllieBot/Modules/Administration/{PlayingRotate/PlayingRotateService.cs => Self/BotActivityService.cs} (59%)
 create mode 100644 src/EllieBot/Modules/Administration/Self/IBotActivityService.cs

diff --git a/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs b/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs
index 16120f2..e7f1d0f 100644
--- a/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs
+++ b/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs
@@ -6,7 +6,7 @@ namespace EllieBot.Modules.Administration;
 public partial class Administration
 {
     [Group]
-    public partial class PlayingRotateCommands : EllieModule<PlayingRotateService>
+    public partial class PlayingRotateCommands : EllieModule<IBotActivityService>
     {
         [Cmd]
         [OwnerOnly]
diff --git a/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateService.cs b/src/EllieBot/Modules/Administration/Self/BotActivityService.cs
similarity index 59%
rename from src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateService.cs
rename to src/EllieBot/Modules/Administration/Self/BotActivityService.cs
index 6a0f2bf..6933da8 100644
--- a/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateService.cs
+++ b/src/EllieBot/Modules/Administration/Self/BotActivityService.cs
@@ -5,67 +5,28 @@ using EllieBot.Db.Models;
 
 namespace EllieBot.Modules.Administration.Services;
 
-public sealed class PlayingRotateService : IEService, IReadyExecutor
+public sealed class BotActivityService : IBotActivityService, IReadyExecutor, IEService
 {
-    private readonly BotConfigService _bss;
-    private readonly SelfService _selfService;
+    private readonly TypedKey<ActivityPubData> _activitySetKey = new("activity.set");
 
-    private readonly IReplacementService _repService;
-
-    // private readonly Replacer _rep;
-    private readonly DbService _db;
+    private readonly IPubSub _pubSub;
     private readonly DiscordSocketClient _client;
+    private readonly DbService _db;
+    private readonly IReplacementService _rep;
+    private readonly BotConfigService _bss;
 
-    public PlayingRotateService(
+    public BotActivityService(
+        IPubSub pubSub,
         DiscordSocketClient client,
         DbService db,
-        BotConfigService bss,
-        IEnumerable<IPlaceholderProvider> phProviders,
-        SelfService selfService,
-        IReplacementService repService)
+        IReplacementService rep,
+        BotConfigService bss)
     {
-        _db = db;
-        _bss = bss;
-        _selfService = selfService;
-        _repService = repService;
+        _pubSub = pubSub;
         _client = client;
-    }
-
-    public async Task OnReadyAsync()
-    {
-        if (_client.ShardId != 0)
-            return;
-
-        using var timer = new PeriodicTimer(TimeSpan.FromMinutes(1));
-        var index = 0;
-        while (await timer.WaitForNextTickAsync())
-        {
-            try
-            {
-                if (!_bss.Data.RotateStatuses)
-                    continue;
-
-                IReadOnlyList<RotatingPlayingStatus> rotatingStatuses;
-                await using (var uow = _db.GetDbContext())
-                {
-                    rotatingStatuses = uow.Set<RotatingPlayingStatus>().AsNoTracking().OrderBy(x => x.Id).ToList();
-                }
-
-                if (rotatingStatuses.Count == 0)
-                    continue;
-
-                var playingStatus = index >= rotatingStatuses.Count
-                    ? rotatingStatuses[index = 0]
-                    : rotatingStatuses[index++];
-
-                var statusText = await _repService.ReplaceAsync(playingStatus.Status, new(client: _client));
-                await _selfService.SetActivityAsync(statusText, (ActivityType)playingStatus.Type);
-            }
-            catch (Exception ex)
-            {
-                Log.Warning(ex, "Rotating playing status errored: {ErrorMessage}", ex.Message);
-            }
-        }
+        _db = db;
+        _rep = rep;
+        _bss = bss;
     }
 
     public async Task<string> RemovePlayingAsync(int index)
@@ -116,4 +77,91 @@ public sealed class PlayingRotateService : IEService, IReadyExecutor
         using var uow = _db.GetDbContext();
         return uow.Set<RotatingPlayingStatus>().AsNoTracking().ToList();
     }
+
+    public Task SetActivityAsync(string game, ActivityType? type)
+        => _pubSub.Pub(_activitySetKey,
+            new()
+            {
+                Name = game,
+                Link = null,
+                Type = type
+            });
+
+    public Task SetStreamAsync(string name, string link)
+        => _pubSub.Pub(_activitySetKey,
+            new()
+            {
+                Name = name,
+                Link = link,
+                Type = ActivityType.Streaming
+            });
+
+    private sealed class ActivityPubData
+    {
+        public string Name { get; init; }
+        public string Link { get; init; }
+        public ActivityType? Type { get; init; }
+    }
+
+    public async Task OnReadyAsync()
+    {
+        await _pubSub.Sub(_activitySetKey,
+            async data =>
+            {
+                if (_client.ShardId == 0)
+                {
+                    DisableRotatePlaying();
+                }
+
+                try
+                {
+                    if (data.Type is { } activityType)
+                    {
+                        await _client.SetGameAsync(data.Name, data.Link, activityType);
+                    }
+                    else
+                    {
+                        await _client.SetCustomStatusAsync(data.Name);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Log.Warning(ex, "Error setting activity");
+                }
+            });
+
+        if (_client.ShardId != 0)
+            return;
+
+        using var timer = new PeriodicTimer(TimeSpan.FromMinutes(1));
+        var index = 0;
+        while (await timer.WaitForNextTickAsync())
+        {
+            try
+            {
+                if (!_bss.Data.RotateStatuses)
+                    continue;
+
+                IReadOnlyList<RotatingPlayingStatus> rotatingStatuses;
+                await using (var uow = _db.GetDbContext())
+                {
+                    rotatingStatuses = uow.Set<RotatingPlayingStatus>().AsNoTracking().OrderBy(x => x.Id).ToList();
+                }
+
+                if (rotatingStatuses.Count == 0)
+                    continue;
+
+                var playingStatus = index >= rotatingStatuses.Count
+                    ? rotatingStatuses[index = 0]
+                    : rotatingStatuses[index++];
+
+                var statusText = await _rep.ReplaceAsync(playingStatus.Status, new(client: _client));
+                await SetActivityAsync(statusText, (ActivityType)playingStatus.Type);
+            }
+            catch (Exception ex)
+            {
+                Log.Warning(ex, "Rotating playing status errored: {ErrorMessage}", ex.Message);
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/EllieBot/Modules/Administration/Self/IBotActivityService.cs b/src/EllieBot/Modules/Administration/Self/IBotActivityService.cs
new file mode 100644
index 0000000..bd737d4
--- /dev/null
+++ b/src/EllieBot/Modules/Administration/Self/IBotActivityService.cs
@@ -0,0 +1,14 @@
+#nullable disable
+using EllieBot.Db.Models;
+
+namespace EllieBot.Modules.Administration.Services;
+
+public interface IBotActivityService
+{
+    Task SetActivityAsync(string game, ActivityType? type);
+    Task SetStreamAsync(string name, string link);
+    bool ToggleRotatePlaying();
+    Task AddPlaying(ActivityType statusType, string status);
+    Task<string> RemovePlayingAsync(int index);
+    IReadOnlyList<RotatingPlayingStatus> GetRotatingStatuses();
+}
\ No newline at end of file
diff --git a/src/EllieBot/Modules/Administration/Self/SelfCommands.cs b/src/EllieBot/Modules/Administration/Self/SelfCommands.cs
index e5196d5..440bd25 100644
--- a/src/EllieBot/Modules/Administration/Self/SelfCommands.cs
+++ b/src/EllieBot/Modules/Administration/Self/SelfCommands.cs
@@ -24,19 +24,22 @@ public partial class Administration
         private readonly IMarmaladeLoaderService _marmaladeLoader;
         private readonly ICoordinator _coord;
         private readonly DbService _db;
+        private readonly IBotActivityService _bas;
 
         public SelfCommands(
             DiscordSocketClient client,
             DbService db,
             IBotStrings strings,
             ICoordinator coord,
-            IMarmaladeLoaderService marmaladeLoader)
+            IMarmaladeLoaderService marmaladeLoader,
+            IBotActivityService bas)
         {
             _client = client;
             _db = db;
             _strings = strings;
             _coord = coord;
             _marmaladeLoader = marmaladeLoader;
+            _bas = bas;
         }
 
 
@@ -496,7 +499,7 @@ public partial class Administration
             // var rep = new ReplacementBuilder().WithDefault(Context).Build();
 
             var repCtx = new ReplacementContext(ctx);
-            await _service.SetActivityAsync(game is null ? game : await repSvc.ReplaceAsync(game, repCtx), type);
+            await _bas.SetActivityAsync(game is null ? game : await repSvc.ReplaceAsync(game, repCtx), type);
 
             await Response().Confirm(strs.set_activity).SendAsync();
         }
@@ -518,7 +521,7 @@ public partial class Administration
         {
             name ??= "";
 
-            await _service.SetStreamAsync(name, url);
+            await _bas.SetStreamAsync(name, url);
 
             await Response().Confirm(strs.set_stream).SendAsync();
         }
diff --git a/src/EllieBot/Modules/Administration/Self/SelfService.cs b/src/EllieBot/Modules/Administration/Self/SelfService.cs
index c07c16e..b9829ce 100644
--- a/src/EllieBot/Modules/Administration/Self/SelfService.cs
+++ b/src/EllieBot/Modules/Administration/Self/SelfService.cs
@@ -28,7 +28,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
     private readonly IMessageSenderService _sender;
 
     //keys
-    private readonly TypedKey<ActivityPubData> _activitySetKey;
     private readonly TypedKey<string> _guildLeaveKey;
 
     public SelfService(
@@ -51,11 +50,8 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
         _bss = bss;
         _pubSub = pubSub;
         _sender = sender;
-        _activitySetKey = new("activity.set");
         _guildLeaveKey = new("guild.leave");
 
-        HandleStatusChanges();
-
         _pubSub.Sub(_guildLeaveKey,
             async input =>
             {
@@ -394,49 +390,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
         return channelId is not null;
     }
 
-    private void HandleStatusChanges()
-        => _pubSub.Sub(_activitySetKey,
-            async data =>
-            {
-                try
-                {
-                    if (data.Type is { } activityType)
-                        await _client.SetGameAsync(data.Name, data.Link, activityType);
-                    else
-                        await _client.SetCustomStatusAsync(data.Name);
-                }
-                catch (Exception ex)
-                {
-                    Log.Warning(ex, "Error setting activity");
-                }
-            });
-
-    public Task SetActivityAsync(string game, ActivityType? type)
-        => _pubSub.Pub(_activitySetKey,
-            new()
-            {
-                Name = game,
-                Link = null,
-                Type = type
-            });
-
-    public Task SetStreamAsync(string name, string link)
-        => _pubSub.Pub(_activitySetKey,
-            new()
-            {
-                Name = name,
-                Link = link,
-                Type = ActivityType.Streaming
-            });
-
-    private sealed class ActivityPubData
-    {
-        public string Name { get; init; }
-        public string Link { get; init; }
-        public ActivityType? Type { get; init; }
-    }
-
-
     /// <summary>
     /// Adds the specified <paramref name="users"/> to the database. If a database user with placeholder name
     /// and discriminator is present in <paramref name="users"/>, their name and discriminator get updated accordingly.