From c6e4c862b85f162a4331698eb5ce2d798501a97a Mon Sep 17 00:00:00 2001 From: spiral Date: Thu, 20 Jan 2022 05:52:40 -0500 Subject: [PATCH] feat: update Discord status only on identify See We still update status when restarting cluster, because it doesn't really matter if the session dies in that case (we're already restarting / going to reidentify) --- Myriad/Gateway/Cluster.cs | 4 +- Myriad/Gateway/Shard.cs | 8 +++- PluralKit.Bot/Bot.cs | 82 +++++++++++---------------------------- 3 files changed, 31 insertions(+), 63 deletions(-) diff --git a/Myriad/Gateway/Cluster.cs b/Myriad/Gateway/Cluster.cs index 42916f7d..be5640a5 100644 --- a/Myriad/Gateway/Cluster.cs +++ b/Myriad/Gateway/Cluster.cs @@ -16,6 +16,8 @@ public class Cluster private readonly ConcurrentDictionary _shards = new(); private IGatewayRatelimiter? _ratelimiter; + public GatewayStatusUpdate DiscordPresence { get; set; } + public Cluster(GatewaySettings gatewaySettings, ILogger logger) { _gatewaySettings = gatewaySettings; @@ -54,7 +56,7 @@ public class Cluster private void CreateAndAddShard(string url, ShardInfo shardInfo) { - var shard = new Shard(_gatewaySettings, shardInfo, _ratelimiter!, url, _logger); + var shard = new Shard(_gatewaySettings, shardInfo, _ratelimiter!, url, _logger, DiscordPresence); shard.OnEventReceived += evt => OnShardEventReceived(shard, evt); _shards[shardInfo.ShardId] = shard; diff --git a/Myriad/Gateway/Shard.cs b/Myriad/Gateway/Shard.cs index b4804585..ed7a3005 100644 --- a/Myriad/Gateway/Shard.cs +++ b/Myriad/Gateway/Shard.cs @@ -41,12 +41,15 @@ public class Shard private TimeSpan _reconnectDelay = TimeSpan.Zero; private Task? _worker; - public Shard(GatewaySettings settings, ShardInfo info, IGatewayRatelimiter ratelimiter, string url, ILogger logger) + private GatewayStatusUpdate? _presence { get; init; } + + public Shard(GatewaySettings settings, ShardInfo info, IGatewayRatelimiter ratelimiter, string url, ILogger logger, GatewayStatusUpdate? presence = null) { _jsonSerializerOptions = new JsonSerializerOptions().ConfigureForMyriad(); _settings = settings; _info = info; + _presence = presence; _ratelimiter = ratelimiter; _url = url; _logger = logger.ForContext().ForContext("ShardId", info.ShardId); @@ -164,7 +167,8 @@ public class Shard }, Shard = _info, Token = _settings.Token, - LargeThreshold = 50 + LargeThreshold = 50, + Presence = _presence, } }); diff --git a/PluralKit.Bot/Bot.cs b/PluralKit.Bot/Bot.cs index 89b2abad..0466fbb6 100644 --- a/PluralKit.Bot/Bot.cs +++ b/PluralKit.Bot/Bot.cs @@ -34,7 +34,6 @@ public class Bot private readonly DiscordApiClient _rest; private readonly ILifetimeScope _services; - private bool _hasReceivedReady; private Timer _periodicTask; // Never read, just kept here for GC reasons public Bot(ILifetimeScope services, ILogger logger, PeriodicStatCollector collector, IMetrics metrics, @@ -54,9 +53,23 @@ public class Bot _cache = cache; } + private string BotStatus => $"{(_config.Prefixes ?? BotConfig.DefaultPrefixes)[0]}help"; + public void Init() { _cluster.EventReceived += (shard, evt) => OnEventReceived(shard.ShardId, evt); + _cluster.DiscordPresence = new GatewayStatusUpdate + { + Status = GatewayStatusUpdate.UserStatus.Online, + Activities = new[] + { + new Activity + { + Type = ActivityType.Game, + Name = BotStatus + } + } + }; // Init the shard stuff _services.Resolve().Init(); @@ -95,20 +108,6 @@ public class Bot await HandleEvent(shardId, mra); if (evt is InteractionCreateEvent ic) await HandleEvent(shardId, ic); - - // Update shard status for shards immediately on connect - if (evt is ReadyEvent re) - await HandleReady(shardId, re); - if (evt is ResumedEvent) - await HandleResumed(shardId); - } - - private Task HandleResumed(int shardId) => UpdateBotStatus(shardId); - - private Task HandleReady(int shardId, ReadyEvent _) - { - _hasReceivedReady = true; - return UpdateBotStatus(shardId); } public async Task Shutdown() @@ -119,16 +118,15 @@ public class Bot // Send users a lil status message // We're not actually properly disconnecting from the gateway (lol) so it'll linger for a few minutes // Should be plenty of time for the bot to connect again next startup and set the real status - if (_hasReceivedReady) - await Task.WhenAll(_cluster.Shards.Values.Select(shard => - shard.UpdateStatus(new GatewayStatusUpdate + await Task.WhenAll(_cluster.Shards.Values.Select(shard => + shard.UpdateStatus(new GatewayStatusUpdate + { + Activities = new[] { - Activities = new[] - { - new Activity {Name = "Restarting... (please wait)", Type = ActivityType.Game} - }, - Status = GatewayStatusUpdate.UserStatus.Idle - }))); + new Activity {Name = "Restarting... (please wait)", Type = ActivityType.Game} + }, + Status = GatewayStatusUpdate.UserStatus.Idle + }))); } private Task HandleEvent(int shardId, T evt) where T : IGatewayEvent @@ -238,45 +236,9 @@ public class Bot { _logger.Debug("Running once-per-minute scheduled tasks"); - await UpdateBotStatus(); - // Collect some stats, submit them to the metrics backend await _collector.CollectStats(); await Task.WhenAll(((IMetricsRoot)_metrics).ReportRunner.RunAllAsync()); _logger.Debug("Submitted metrics to backend"); } - - private async Task UpdateBotStatus(int? specificShardId = null) - { - // If we're not on any shards, don't bother (this happens if the periodic timer fires before the first Ready) - if (!_hasReceivedReady) return; - - var totalGuilds = await _cache.GetAllGuilds().CountAsync(); - - try // DiscordClient may throw an exception if the socket is closed (e.g just after OP 7 received) - { - Task UpdateStatus(Shard shard) => - shard.UpdateStatus(new GatewayStatusUpdate - { - Activities = new[] - { - new Activity - { - Name = $"{(_config.Prefixes ?? BotConfig.DefaultPrefixes)[0]}help | in {totalGuilds:N0} servers | shard #{shard.ShardId}", - Type = ActivityType.Game, - Url = "https://pluralkit.me/" - } - } - }); - - if (specificShardId != null) - await UpdateStatus(_cluster.Shards[specificShardId.Value]); - else // Run shard updates concurrently - await Task.WhenAll(_cluster.Shards.Values.Select(UpdateStatus)); - } - catch (WebSocketException) - { - // TODO: this still thrown? - } - } } \ No newline at end of file