示例#1
0
        public async Task InteractiveSetupCommandAsync(CommandContext ctx)
        {
            // Check for donor rank updates
            // then display welcome message
            // along with donor features this server gets
            // or an advert for unlocking the donor features
            // (check, cross, and lock symbols next to features for avalible, used, and need to buy stuff)
            // have setup requirements displayed
            // and options to setup parts of the message
            // along with a toggle option, once everything is setup
            // once setup is closed, save new data.

            GuildBan?ban;

            if ((ban = await this._ban.GetBanAsync(ctx.Guild.Id)) is not null ||
                (ban = await this._ban.GetBanAsync(ctx.Guild.OwnerId)) is not null)
            {
                await RespondError($"Your server is banned due to: {ban.Reason}\n\n" +
                                   $"Contact a staff member on the [support server](https://discord.gg/3SCTnhCMam) to learn more.");

                await ctx.Guild.LeaveAsync();

                return;
            }

            using var scope = this._services.CreateScope();
            var     db      = scope.ServiceProvider.GetRequiredService <PartnerDatabaseContext>();
            Partner?partner = await db.Partners.AsNoTracking().FirstOrDefaultAsync(x => x.GuildId == ctx.Guild.Id);

            if (partner is null)
            {
                partner = new()
                {
                    GuildId = ctx.Guild.Id,
                };

                await db.AddAsync(partner);

                await db.SaveChangesAsync();
            }

            partner.OwnerId   = ctx.Guild.OwnerId;
            partner.GuildName = ctx.Guild.Name;
            partner.GuildIcon = ctx.Guild.IconUrl;
            partner.UserCount = ctx.Guild.MemberCount;
            partner.DonorRank = await this._donor.GetDonorRankAsync(partner.OwnerId);

            await db.SaveChangesAsync();

            partner.ModifyToDonorRank();

            DiscordChannel?channel      = null;
            ulong          oldChannelId = 0;
            DiscordWebhook?hook         = null;

            if (!string.IsNullOrWhiteSpace(partner.WebhookToken))
            {
                try
                {
                    hook = await ctx.Client.GetWebhookAsync(partner.WebhookId);

                    channel = await ctx.Client.GetChannelAsync(hook.ChannelId);

                    oldChannelId = channel.Id;
                }
                catch
                {
                    hook         = null;
                    oldChannelId = 0;
                    channel      = null;
                }
            }

            DSharpPlus.Interactivity.InteractivityExtension?interact = ctx.Client.GetInteractivity();
            bool             done                = false;
            bool             isChanged           = false;
            string?          errorMessage        = null;
            DiscordMessage?  requirementsMessage = null;
            HashSet <string>?tagUpdate           = null;
            ComponentInteractionCreateEventArgs?lastButtonEvent = null;

            do
            {
                if (lastButtonEvent is null)
                {
                    var messageBuilder = await GetMessageBuilder(partner, isChanged, channel);

                    if (requirementsMessage is null)
                    {
                        requirementsMessage = await messageBuilder.SendAsync(ctx.Channel);
                    }
                    else
                    {
                        await requirementsMessage.ModifyAsync(messageBuilder);
                    }
                }
                else
                {
                    await lastButtonEvent.Interaction.EditOriginalResponseAsync(
                        await GetInteractionEditAsync(partner, isChanged, channel, errorMessage)
                        );

                    requirementsMessage = lastButtonEvent.Message;
                }

                var response = await GetButtonPressAsync(interact, requirementsMessage);

                if (!response.Item2)
                {
                    return;
                }

                lastButtonEvent = response.Item1;
                await lastButtonEvent.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage,
                                                                      await GetInteractionResponseAsync(partner, isChanged, channel, errorMessage));

                errorMessage = null;

                switch (lastButtonEvent.Id)
                {
                // Exit calls.
                case "exit":
                    await RespondError("Aborting...");

                    return;

                case "save":
                    done = true;
                    break;

                // Primary Settings.
                case "channel":
                    ((DiscordChannel, DiscordWebhook, string)?, string?, bool)chanRes = await GetNewPartnerChannelAsync(partner, lastButtonEvent);

                    if (chanRes.Item3)
                    {
                        return;
                    }

                    if (chanRes.Item1 is null)
                    {
                        await RespondError(chanRes.Item2 ?? "An unknown error occurred.");

                        return;
                    }

                    channel              = chanRes.Item1.Value.Item1;
                    partner.WebhookId    = chanRes.Item1.Value.Item2.Id;
                    partner.WebhookToken = chanRes.Item1.Value.Item2.Token;
                    partner.Invite       = chanRes.Item1.Value.Item3;
                    break;

                case "message":
                    (string?, string?, bool)messageRes = await GetNewMessage(partner, lastButtonEvent, partner.Message.GetUrls().Count);

                    if (messageRes.Item3)
                    {
                        return;
                    }

                    if (messageRes.Item1 is null)
                    {
                        await RespondError(messageRes.Item2 ?? "An unknown error occurred.");

                        return;
                    }

                    partner.Message = messageRes.Item1;
                    break;

                case "toggle":
                    var setup = partner.IsSetup();
                    if (partner.Active)
                    {
                        partner.Active = false;
                    }
                    else if (!partner.Active && setup.Item1)
                    {
                        partner.Active = true;
                    }
                    else
                    {
                        errorMessage = $"**Core setup is not complete. Please complete the required settings before toggling Partner Bot**\n\n" +
                                       $"**Setup Erroed because:** `{setup.Item2}`";
                    }
                    break;

                // Secondary Settings.
                case "add-embed":
                    if (partner.DonorRank < DonorService.EMBED_LIMIT)
                    {
                        errorMessage = $"**You need to be a Tripple Partner to use custom embeds! Consider [donating](https://www.patreon.com/cessumdevelopment?fan_landing=true) to get access to embeds.**";
                    }
                    else if (partner.DonorRank >= DonorService.HIGHEST_RANK
                            ? partner.MessageEmbeds.Count >= DonorService.QUADRUPLE_EMBEDS
                            : partner.MessageEmbeds.Count >= DonorService.TRIPPLE_EMBEDS)
                    {
                        errorMessage = $"**You have used up all your embeds! You can edit a existing one, or remove an old one and add a new one.**";
                    }
                    else
                    {
                        var statusEmbed = new DiscordEmbedBuilder()
                                          .WithDescription($"**Please enter the title for your new embed:**")
                                          .WithColor(Color_PartnerBotMagenta);

                        var builder = new DiscordMessageBuilder()
                                      .WithEmbed(statusEmbed);

                        var statusMessage = await builder.SendAsync(lastButtonEvent.Channel);

                        (DSharpPlus.Interactivity.InteractivityResult <DiscordMessage>, bool)editStart = await GetFollowupMessageAsync(interact);

                        if (!editStart.Item2)
                        {
                            return;
                        }

                        DSharpPlus.Interactivity.InteractivityResult <DiscordMessage> startRes = editStart.Item1;

                        string?title = startRes.Result.Content.Trim();

                        if (title.Length > 256)
                        {
                            errorMessage = $"**The embed title cannot be longer than 256 characters. Returning to main menu.**";
                        }
                        else
                        {
                            (DiscordEmbedBuilder?, string?, bool)addEnd = await GetCustomDiscordEmbedAsync(partner, lastButtonEvent, title);

                            if (addEnd.Item3)
                            {
                                return;
                            }

                            if (addEnd.Item1 is null)
                            {
                                await RespondError(addEnd.Item2 ?? "An unknown error occurred.");

                                return;
                            }

                            partner.MessageEmbeds.Add(addEnd.Item1);
                        }

                        await statusMessage.DeleteAsync();
                    }
                    break;

                case "edit-embed":
                    if (partner.DonorRank < DonorService.EMBED_LIMIT)
                    {
                        errorMessage = $"**You need to be a Tripple Partner to use custom embeds! Consider [donating](https://www.patreon.com/cessumdevelopment?fan_landing=true) to get access to embeds.**";
                    }
                    else if (partner.MessageEmbeds.Count <= 0)
                    {
                        errorMessage = $"**There are no embeds to edit!**";
                    }
                    else
                    {
                        string        desc    = $"Please select an embed to edit:\n\n";
                        List <string> items   = new();
                        int           c       = 1;
                        var           buttons = new List <DiscordButtonComponent>();
                        foreach (DiscordEmbed f in partner.MessageEmbeds)
                        {
                            items.Add($"`{c}` - {f.Title}");
                            buttons.Add(new(ButtonStyle.Primary, c.ToString(), c.ToString()));
                            c++;
                        }

                        var statusEmbed = new DiscordEmbedBuilder()
                                          .WithDescription($"{desc}{string.Join("\n", items)}")
                                          .WithColor(DiscordColor.Gold);

                        var builder = new DiscordMessageBuilder()
                                      .WithEmbed(statusEmbed)
                                      .AddComponents(buttons);

                        var statusMessage = await builder.SendAsync(lastButtonEvent.Channel);

                        var addStart = await GetButtonPressAsync(interact, statusMessage);

                        if (!addStart.Item2)
                        {
                            return;
                        }

                        var startRes = addStart.Item1;
                        await startRes.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);

                        if (!int.TryParse(startRes.Id, out int index))
                        {
                            errorMessage = $"**The value provided was not a number! Returning to main menu.**";
                        }
                        else if (index > partner.MessageEmbeds.Count || index < 0)
                        {
                            errorMessage = $"**The value provided was not a valid embed! Returning to main menu.**";
                        }
                        else
                        {
                            DiscordEmbed?oldEmbed = partner.MessageEmbeds[index - 1];

                            (DiscordEmbedBuilder?, string?, bool)editEnd = await GetCustomDiscordEmbedAsync(partner, lastButtonEvent, oldEmbed.Title, new(oldEmbed));

                            if (editEnd.Item3)
                            {
                                return;
                            }

                            if (editEnd.Item1 is null)
                            {
                                await RespondError(editEnd.Item2 ?? "An unknown error occurred.");

                                return;
                            }

                            partner.MessageEmbeds[index - 1] = editEnd.Item1;
                        }

                        await statusMessage.DeleteAsync();
                    }
                    break;

                case "remove-embed":
                    if (partner.DonorRank < DonorService.EMBED_LIMIT)
                    {
                        errorMessage = $"**You need to be a Tripple Partner to use custom embeds! Consider [donating](https://www.patreon.com/cessumdevelopment?fan_landing=true) to get access to embeds.**";
                    }
                    else if (partner.MessageEmbeds.Count <= 0)
                    {
                        errorMessage = $"**There are no embeds to remove!**";
                    }
                    else
                    {
                        string        desc    = $"Please select an embed to delete:\n\n";
                        List <string> items   = new();
                        int           c       = 1;
                        var           buttons = new List <DiscordButtonComponent>();
                        foreach (DiscordEmbed f in partner.MessageEmbeds)
                        {
                            items.Add($"`{c}` - {f.Title}");
                            buttons.Add(new(ButtonStyle.Primary, c.ToString(), c.ToString()));
                            c++;
                        }

                        var statusEmbed = new DiscordEmbedBuilder()
                                          .WithDescription($"{desc}{string.Join("\n", items)}")
                                          .WithColor(DiscordColor.Gold);

                        var builder = new DiscordMessageBuilder()
                                      .WithEmbed(statusEmbed)
                                      .AddComponents(buttons);

                        var statusMessage = await builder.SendAsync(lastButtonEvent.Channel);

                        var addStart = await GetButtonPressAsync(interact, statusMessage);

                        if (!addStart.Item2)
                        {
                            return;
                        }

                        var startRes = addStart.Item1;

                        if (!int.TryParse(startRes.Id, out int index))
                        {
                            errorMessage = $"**The value provided was not a number! Returning to main menu.**";
                            await startRes.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
                        }
                        else if (index > partner.MessageEmbeds.Count || index < 0)
                        {
                            errorMessage = $"**The value provided was not a valid embed! Returning to main menu.**";
                            await startRes.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
                        }
                        else
                        {
                            await startRes.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage,
                                                                           new DiscordInteractionResponseBuilder()
                                                                           .AddEmbed(statusEmbed
                                                                                     .WithTitle("Partner Bot Setup - Main")
                                                                                     .WithDescription($"**Embed removed.**")));

                            partner.MessageEmbeds.RemoveAt(index - 1);

                            await Task.Delay(TimeSpan.FromSeconds(2));
                        }

                        await statusMessage.DeleteAsync();
                    }
                    break;

                case "banner":
                    (Uri?, string?, bool)bannerRes = await GetNewPartnerBanner(lastButtonEvent);

                    if (bannerRes.Item3)
                    {
                        return;
                    }

                    if (bannerRes.Item1 is null)
                    {
                        await RespondError(bannerRes.Item2 ?? "An unknown error occurred.");

                        return;
                    }

                    partner.Banner = bannerRes.Item1.AbsoluteUri;
                    break;

                case "color":
                case "colour":
                    (DiscordColor?, string?, bool)colorRes = await GetCustomEmbedColorAsync(partner, lastButtonEvent);

                    if (colorRes.Item3)
                    {
                        return;
                    }

                    if (colorRes.Item1 is null)
                    {
                        await RespondError(colorRes.Item2 ?? "An unknown error occurred.");

                        return;
                    }

                    partner.BaseColor = colorRes.Item1.Value;
                    break;

                case "tag":
                case "tags":
                    (HashSet <string>?, string?, bool)tagRes = await UpdateTagsAsync(partner, lastButtonEvent);

                    if (tagRes.Item3)
                    {
                        return;
                    }

                    if (tagRes.Item1 is null)
                    {
                        await RespondError(tagRes.Item2 ?? "An unknown error occurred.");

                        return;
                    }

                    tagUpdate = tagRes.Item1;
                    break;

                case "vanity":
                    if (partner.DonorRank >= DonorService.VANITY_LIMIT)
                    {
                        if (partner.VanityInvite is not null)
                        {
                            await lastButtonEvent.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage,
                                                                                  new DiscordInteractionResponseBuilder()
                                                                                  .AddEmbed(new DiscordEmbedBuilder()
                                                                                            .WithDescription($"**Vanity Invite disabled!**")));

                            await Task.Delay(TimeSpan.FromSeconds(2));
                        }
                        else
                        {
                            DiscordInvite?vanity;
                            try
                            {
                                vanity = await this.Context.Guild.GetVanityInviteAsync();
                            }
                            catch { vanity = null; }

                            if (vanity is not null)
                            {
                                await lastButtonEvent.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage,
                                                                                      new DiscordInteractionResponseBuilder()
                                                                                      .AddEmbed(new DiscordEmbedBuilder()
                                                                                                .WithDescription($"**Vanity Invite enabled!**")));

                                await Task.Delay(TimeSpan.FromSeconds(2));
                            }
                            else
                            {
                                errorMessage = $"**You do not have a vanity invite for your server!**";
                            }
                        }
                    }
                    else
                    {
                        errorMessage = $"**You do not have a high enough donor rank to use vanity invites." +
                                       $" Consider [donating](https://www.patreon.com/cessumdevelopment?fan_landing=true)" +
                                       $" to use your vanity invite!**";
                    }
                    break;

                case "get-nsfw":
                    if (!partner.NSFW)
                    {
                        partner.ReceiveNSFW = !partner.ReceiveNSFW;
                    }
                    else
                    {
                        errorMessage = $"**If your server is marked NSFW you must be allwoed to receive other NSFW server advertisments." +
                                       $" Make your advertisment *not* NSFW, then use `set-nsfw` again before turning this option off with" +
                                       $" `get-nsfw`.**";
                    }
                    break;

                case "set-nsfw":
                    partner.NSFW = !partner.NSFW;
                    if (partner.NSFW)
                    {
                        partner.ReceiveNSFW = true;
                    }
                    break;

                default:
                    break;
                }

                isChanged = true;
            } while (!done);

            (Partner?, string)updateRes = await this._partners.UpdateOrAddPartnerAsync(ctx.Guild.Id, () =>
            {
                var update = PartnerUpdater.BuildFromPartner(partner);

                if (channel is not null)
                {
                    update.ChannelId = channel.Id;
                }

                if (tagUpdate is not null)
                {
                    update.TagOverride = tagUpdate;
                }

                return(update);
            });

            if (updateRes.Item1 is not null)
            {
                await lastButtonEvent.Interaction.EditOriginalResponseAsync(
                    new DiscordWebhookBuilder()
                    .AddEmbed(new DiscordEmbedBuilder()
                              .WithTitle("Partner Bot Setup - Main")
                              .WithColor(DiscordColor.Green)
                              .WithDescription("Partner Setup Saved!")));
            }
            else
            {
                await lastButtonEvent.Interaction.EditOriginalResponseAsync(
                    new DiscordWebhookBuilder()
                    .AddEmbed(new DiscordEmbedBuilder()
                              .WithTitle("Partner Bot Setup - Main")
                              .WithDescription("An error occurred while saving:\n\n```\n" +
                                               $"{updateRes.Item2}" +
                                               $"\n```")
                              .WithColor(DiscordColor.DarkRed)));

                ;
            }
        }
示例#2
0
        public async Task PurgeCommandAsync(CommandContext ctx)
        {
            DSharpPlus.Interactivity.InteractivityExtension?interact = ctx.Client.GetInteractivity();

            await ctx.RespondAsync("**Purging your data will delete all saved partner information then remove the bot from your server. Are you sure" +
                                   " you want to proceed? Type `yes` to purge data. Type anything else to cancel this operation.**");

            DSharpPlus.Interactivity.InteractivityResult <DSharpPlus.Entities.DiscordMessage> res = await interact.WaitForMessageAsync(x => x.Author.Id == ctx.User.Id);

            if (res.TimedOut)
            {
                await RespondError("Time out.");
            }
            else
            {
                if (res.Result.Content.Trim().ToLower().Equals("yes"))
                {
                    await this._partners.RemovePartnerAsync(ctx.Guild.Id);

                    using var scope = this._services.CreateScope();
                    var db = scope.ServiceProvider.GetRequiredService <PartnerDatabaseContext>();

                    await RespondSuccess("Partner config purged, leaving guild.\n\n" +
                                         "Thanks for using Partner Bot!");

                    DiscordGuildConfiguration?guild = await db.FindAsync <DiscordGuildConfiguration>(ctx.Guild.Id);

                    db.Remove(guild);

                    await db.SaveChangesAsync();

                    await ctx.Guild.LeaveAsync();
                }
                else
                {
                    await RespondError("Aborting...");
                }
            }
        }
        public async Task SetupTestServers(CommandContext ctx, params DiscordGuild[] guilds)
        {
            List <string> names = new();

            foreach (DiscordGuild?g in guilds)
            {
                names.Add(g.Name);
            }

            DSharpPlus.Interactivity.InteractivityExtension?interact = ctx.Client.GetInteractivity();

            DiscordEmbedBuilder?embed = new DiscordEmbedBuilder()
                                        .WithColor(DiscordColor.Red)
                                        .WithTitle("Partner Test Server Setup")
                                        .WithDescription("Setting up Partner Bot Test Server. Please ensure the bot has admin on all servers. Type `continue` to start.\n\n" +
                                                         "**THIS WILL DELETE ALL CONTENT FROM THE FOLLOWING GUILDS:**")
                                        .AddField("Guilds: ", string.Join(",", names));

            DiscordMessage?message = await ctx.RespondAsync(embed);

            DSharpPlus.Interactivity.InteractivityResult <DiscordMessage> response = await interact.WaitForMessageAsync(x => x.Channel.Id == ctx.Channel.Id && x.Author.Id == ctx.Member.Id);

            if (response.TimedOut)
            {
                await InteractTimeout();

                return;
            }
            else if (!response.Result.Content.ToLower().Equals("continue"))
            {
                await RespondError("Aborting...");

                return;
            }

            var queue = new Queue <DiscordGuild>(guilds);

            List <DevelopmentStressTestChannel>?data = await DevelopmentStressTestDataManager.GetDataAsync();

            if (data is null)
            {
                data = new();
            }

            DiscordMessage?msg = null;

            while (queue.TryDequeue(out DiscordGuild? guild))
            {
                int channelStage = 0;
                int webhookStage = 0;
                msg = await Update(ctx, guild, queue, true, channelStage, webhookStage, msg);

                await CleanupGuild(guild);

                var baseChan = new DevelopmentStressTestChannel()
                {
                    GuildId   = guild.Id,
                    GuildName = Names[ThreadSafeRandom.Next(0, Names.Count)]
                };

                await guild.ModifyAsync(x => x.Name = $"Test Server {baseChan.GuildName}");

                msg = await Update(ctx, guild, queue, false, channelStage, webhookStage, msg);

                List <DevelopmentStressTestChannel> createdChannels = new();
                List <DiscordChannel> rawChannels = new();
                // build new channels
                int x = 1;
                for (int i = 0; i < 50; i++)
                {
                    if (x % 5 == 0)
                    {
                        msg = await Update(ctx, guild, queue, false, ++channelStage, webhookStage, msg);
                    }

                    (DevelopmentStressTestChannel, DiscordChannel)chan = await BuildChannel(guild, baseChan);

                    createdChannels.Add(chan.Item1);
                    rawChannels.Add(chan.Item2);

                    x++;

                    await Task.Delay(TimeSpan.FromSeconds(.5));
                }

                msg = await Update(ctx, guild, queue, false, channelStage, webhookStage, msg);

                // build new webhooks
                x = 1;
                int rc = 0;
                foreach (DevelopmentStressTestChannel?c in createdChannels)
                {
                    if (x % 5 == 0)
                    {
                        msg = await Update(ctx, guild, queue, false, channelStage, ++webhookStage, msg);
                    }

                    await ApplyWebhookData(c, rawChannels[rc++]);

                    x++;

                    await Task.Delay(TimeSpan.FromSeconds(.5));
                }

                // save data
                data.AddRange(createdChannels);
            }

            await msg.ModifyAsync(embed : new DiscordEmbedBuilder()
                                  .WithColor(DiscordColor.Orange)
                                  .WithTitle("Partner Test Server Cleanup")
                                  .WithDescription("Cleaning up test server data...")
                                  .Build());

            data.RemoveAll(x =>
            {
                bool found = false;
                foreach (DiscordClient?shard in this._client.ShardClients.Values)
                {
                    if (shard.Guilds.ContainsKey(x.GuildId))
                    {
                        found = true;
                        break;
                    }
                }

                return(!found);
            });

            await DevelopmentStressTestDataManager.SaveDataAsync(data);

            await RespondSuccess("Setup Complete.");
        }