using JetBrains.Annotations; using Microsoft.Extensions.Logging; using Remora.Discord.API.Abstractions.Gateway.Events; using Remora.Discord.API.Abstractions.Objects; using Remora.Discord.API.Abstractions.Rest; using Remora.Discord.API.Gateway.Events; using Remora.Discord.API.Objects; using Remora.Discord.Extensions.Embeds; using Remora.Discord.Gateway.Responders; using Remora.Results; using TeamOctolings.Octobot.Data; using TeamOctolings.Octobot.Extensions; using TeamOctolings.Octobot.Services; namespace TeamOctolings.Octobot.Responders; /// /// Handles sending a message to a guild that has just initialized if that guild /// has enabled /// [UsedImplicitly] public class GuildLoadedResponder : IResponder { private readonly IDiscordRestChannelAPI _channelApi; private readonly GuildDataService _guildData; private readonly ILogger _logger; private readonly IDiscordRestUserAPI _userApi; private readonly Utility _utility; public GuildLoadedResponder( IDiscordRestChannelAPI channelApi, GuildDataService guildData, ILogger logger, IDiscordRestUserAPI userApi, Utility utility) { _channelApi = channelApi; _guildData = guildData; _logger = logger; _userApi = userApi; _utility = utility; } public async Task RespondAsync(IGuildCreate gatewayEvent, CancellationToken ct = default) { if (!gatewayEvent.Guild.IsT0) // Guild is not IAvailableGuild { return Result.Success; } var guild = gatewayEvent.Guild.AsT0; var data = await _guildData.GetData(guild.ID, ct); var cfg = data.Settings; foreach (var member in guild.Members.Where(m => m.User.HasValue)) { data.GetOrCreateMemberData(member.User.Value.ID); } var botResult = await _userApi.GetCurrentUserAsync(ct); if (!botResult.IsDefined(out var bot)) { return ResultExtensions.FromError(botResult); } if (data.DataLoadFailed) { return await SendDataLoadFailed(guild, data, bot, ct); } var ownerResult = await _userApi.GetUserAsync(guild.OwnerID, ct); if (!ownerResult.IsDefined(out var owner)) { return ResultExtensions.FromError(ownerResult); } _logger.LogInformation("Loaded guild \"{Name}\" ({ID}) owned by {Owner} ({OwnerID}) with {MemberCount} members", guild.Name, guild.ID, owner.GetTag(), owner.ID, guild.MemberCount); if (GuildSettings.PrivateFeedbackChannel.Get(cfg).Empty() || !GuildSettings.ReceiveStartupMessages.Get(cfg)) { return Result.Success; } Messages.Culture = GuildSettings.Language.Get(cfg); var i = Random.Shared.Next(1, 4); var embed = new EmbedBuilder().WithSmallTitle(bot.GetTag(), bot) .WithTitle($"Generic{i}".Localized()) .WithDescription(Messages.Ready) .WithCurrentTimestamp() .WithColour(ColorsList.Blue) .Build(); return await _channelApi.CreateMessageWithEmbedResultAsync( GuildSettings.PrivateFeedbackChannel.Get(cfg), embedResult: embed, ct: ct); } private async Task SendDataLoadFailed(IGuild guild, GuildData data, IUser bot, CancellationToken ct) { var channelResult = await _utility.GetEmergencyFeedbackChannel(guild, data, ct); if (!channelResult.IsDefined(out var channel)) { return ResultExtensions.FromError(channelResult); } var errorEmbed = new EmbedBuilder() .WithSmallTitle(Messages.DataLoadFailedTitle, bot) .WithDescription(Messages.DataLoadFailedDescription) .WithFooter(Messages.ContactDevelopers) .WithColour(ColorsList.Red) .Build(); var issuesButton = new ButtonComponent( ButtonComponentStyle.Link, BuildInfo.IsDirty ? Messages.ButtonDirty : Messages.ButtonReportIssue, new PartialEmoji(Name: "\u26a0\ufe0f"), // 'WARNING SIGN' (U+26A0) URL: BuildInfo.IssuesUrl, IsDisabled: BuildInfo.IsDirty ); return await _channelApi.CreateMessageWithEmbedResultAsync(channel, embedResult: errorEmbed, components: new[] { new ActionRowComponent(new[] { issuesButton }) }, ct: ct); } }