diff --git a/Boyfriend.cs b/Boyfriend.cs index 2c2c07a..ce75cf2 100644 --- a/Boyfriend.cs +++ b/Boyfriend.cs @@ -78,7 +78,8 @@ public class Boyfriend { .WithCommandGroup() .WithCommandGroup() .WithCommandGroup() - .WithCommandGroup(); + .WithCommandGroup() + .WithCommandGroup(); var responderTypes = typeof(Boyfriend).Assembly .GetExportedTypes() .Where(t => t.IsResponder()); diff --git a/Commands/PingCommandGroup.cs b/Commands/PingCommandGroup.cs new file mode 100644 index 0000000..2db7dfe --- /dev/null +++ b/Commands/PingCommandGroup.cs @@ -0,0 +1,79 @@ +using System.ComponentModel; +using Boyfriend.Services.Data; +using Remora.Commands.Attributes; +using Remora.Commands.Groups; +using Remora.Discord.API.Abstractions.Rest; +using Remora.Discord.Commands.Contexts; +using Remora.Discord.Commands.Feedback.Services; +using Remora.Discord.Extensions.Embeds; +using Remora.Discord.Gateway; +using Remora.Results; + +// ReSharper disable ClassNeverInstantiated.Global +// ReSharper disable UnusedMember.Global + +namespace Boyfriend.Commands; + +/// +/// Handles the command to get the time taken for the gateway to respond to the last heartbeat: /ping +/// +public class PingCommandGroup : CommandGroup { + private readonly IDiscordRestChannelAPI _channelApi; + private readonly DiscordGatewayClient _client; + private readonly ICommandContext _context; + private readonly GuildDataService _dataService; + private readonly FeedbackService _feedbackService; + private readonly IDiscordRestUserAPI _userApi; + + public PingCommandGroup( + IDiscordRestChannelAPI channelApi, ICommandContext context, DiscordGatewayClient client, + GuildDataService dataService, FeedbackService feedbackService, IDiscordRestUserAPI userApi) { + _channelApi = channelApi; + _context = context; + _client = client; + _dataService = dataService; + _feedbackService = feedbackService; + _userApi = userApi; + } + + [Command("ping", "пинг")] + [Description("получает задержку")] + public async Task GetPingAsync() { + if (!_context.TryGetContextIDs(out var guildId, out var channelId, out _)) + return Result.FromError( + new ArgumentNullError(nameof(_context), "Unable to retrieve necessary IDs from command context")); + + var currentUserResult = await _userApi.GetCurrentUserAsync(CancellationToken); + if (!currentUserResult.IsDefined(out var currentUser)) + return Result.FromError(currentUserResult); + + var cfg = await _dataService.GetConfiguration(guildId.Value); + Messages.Culture = cfg.GetCulture(); + + var latency = _client.Latency.TotalMilliseconds; + if (latency is 0) { + // No heartbeat has occurred, estimate latency from local time and "Boyfriend is thinking..." message + var lastMessageResult = await _channelApi.GetChannelMessagesAsync( + channelId.Value, limit: 1, ct: CancellationToken); + if (!lastMessageResult.IsDefined(out var lastMessage)) + return Result.FromError(lastMessageResult); + latency = DateTimeOffset.UtcNow.Subtract(lastMessage.Single().Timestamp).TotalMilliseconds; + } + + // var embed = new EmbedBuilder().WithTitle($"Beep{Random.Shared.Next(1, 4)}".Localized()) + // .WithDescription($"{latency:F0}{Messages.Milliseconds}") + // .WithColour(ColorsList.Green) + // .WithUserFooter(currentUser) + // .WithCurrentTimestamp() + // .Build(); + var embed = new EmbedBuilder().WithSmallTitle(currentUser.GetTag(), currentUser) + .WithTitle($"Beep{Random.Shared.Next(1, 4)}".Localized()) + .WithDescription($"{latency:F0}{Messages.Milliseconds}") + .WithColour(latency < 250 ? ColorsList.Green : latency < 500 ? ColorsList.Yellow : ColorsList.Red) + .WithCurrentTimestamp() + .Build(); + if (!embed.IsDefined(out var built)) return Result.FromError(embed); + + return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken); + } +} diff --git a/EventResponders.cs b/EventResponders.cs index 8f6eed3..52c22af 100644 --- a/EventResponders.cs +++ b/EventResponders.cs @@ -54,10 +54,9 @@ public class GuildCreateResponder : IResponder { Messages.Culture = guildConfig.GetCulture(); var i = Random.Shared.Next(1, 4); - var embed = new EmbedBuilder() + var embed = new EmbedBuilder().WithSmallTitle(currentUser.GetTag(), currentUser) .WithTitle($"Beep{i}".Localized()) .WithDescription(Messages.Ready) - .WithUserFooter(currentUser) .WithCurrentTimestamp() .WithColour(ColorsList.Blue) .Build(); diff --git a/Services/GuildUpdateService.cs b/Services/GuildUpdateService.cs index b1eb010..cf3fef8 100644 --- a/Services/GuildUpdateService.cs +++ b/Services/GuildUpdateService.cs @@ -1,6 +1,5 @@ using Boyfriend.Data; using Boyfriend.Services.Data; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Remora.Discord.API.Abstractions.Objects; @@ -34,26 +33,27 @@ public class GuildUpdateService : BackgroundService { private readonly List _activityList = new(1) { new Activity("with Remora.Discord", ActivityType.Game) }; private readonly IDiscordRestChannelAPI _channelApi; + private readonly DiscordGatewayClient _client; private readonly GuildDataService _dataService; private readonly IDiscordRestGuildScheduledEventAPI _eventApi; private readonly IDiscordRestGuildAPI _guildApi; private readonly ILogger _logger; - private readonly IServiceProvider _provider; private readonly IDiscordRestUserAPI _userApi; private readonly UtilityService _utility; - private DateTimeOffset _nextSongAt = DateTimeOffset.MinValue; - private uint _nextSongIndex; + + private DateTimeOffset _nextSongAt = DateTimeOffset.MinValue; + private uint _nextSongIndex; public GuildUpdateService( - IDiscordRestChannelAPI channelApi, GuildDataService dataService, IDiscordRestGuildScheduledEventAPI eventApi, - IDiscordRestGuildAPI guildApi, ILogger logger, IServiceProvider provider, - IDiscordRestUserAPI userApi, UtilityService utility) { + IDiscordRestChannelAPI channelApi, DiscordGatewayClient client, GuildDataService dataService, + IDiscordRestGuildScheduledEventAPI eventApi, IDiscordRestGuildAPI guildApi, ILogger logger, + IDiscordRestUserAPI userApi, UtilityService utility) { _channelApi = channelApi; + _client = client; _dataService = dataService; _eventApi = eventApi; _guildApi = guildApi; _logger = logger; - _provider = provider; _userApi = userApi; _utility = utility; } @@ -73,8 +73,7 @@ public class GuildUpdateService : BackgroundService { if (guildIds.Count > 0 && DateTimeOffset.UtcNow >= _nextSongAt) { var nextSong = SongList[_nextSongIndex]; _activityList[0] = new Activity(nextSong.Name, ActivityType.Listening); - var client = _provider.GetRequiredService(); - client.SubmitCommand( + _client.SubmitCommand( new UpdatePresence( UserStatus.Online, false, DateTimeOffset.UtcNow, _activityList)); _nextSongAt = DateTimeOffset.UtcNow.Add(nextSong.Duration);