mirror of
				https://gitlab.com/Kwoth/nadekobot.git
				synced 2025-11-04 00:34:26 -05:00 
			
		
		
		
	Started rewriting all paginted responses into the new system
This commit is contained in:
		@@ -32,13 +32,15 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
 | 
			
		||||
 | 
			
		||||
        var ex = await _service.AddAsync(ctx.Guild?.Id, key, message);
 | 
			
		||||
 | 
			
		||||
        await Response().Embed(new EmbedBuilder()
 | 
			
		||||
                            .WithOkColor()
 | 
			
		||||
                            .WithTitle(GetText(strs.expr_new))
 | 
			
		||||
                            .WithDescription($"#{new kwum(ex.Id)}")
 | 
			
		||||
                            .AddField(GetText(strs.trigger), key)
 | 
			
		||||
                            .AddField(GetText(strs.response),
 | 
			
		||||
                                message.Length > 1024 ? GetText(strs.redacted_too_long) : message)).SendAsync();
 | 
			
		||||
        await Response()
 | 
			
		||||
              .Embed(new EmbedBuilder()
 | 
			
		||||
                     .WithOkColor()
 | 
			
		||||
                     .WithTitle(GetText(strs.expr_new))
 | 
			
		||||
                     .WithDescription($"#{new kwum(ex.Id)}")
 | 
			
		||||
                     .AddField(GetText(strs.trigger), key)
 | 
			
		||||
                     .AddField(GetText(strs.response),
 | 
			
		||||
                         message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
 | 
			
		||||
              .SendAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Cmd]
 | 
			
		||||
@@ -101,12 +103,12 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
 | 
			
		||||
        if (ex is not null)
 | 
			
		||||
        {
 | 
			
		||||
            await ctx.Channel.EmbedAsync(new EmbedBuilder()
 | 
			
		||||
                                            .WithOkColor()
 | 
			
		||||
                                            .WithTitle(GetText(strs.expr_edited))
 | 
			
		||||
                                            .WithDescription($"#{id}")
 | 
			
		||||
                                            .AddField(GetText(strs.trigger), ex.Trigger)
 | 
			
		||||
                                            .AddField(GetText(strs.response),
 | 
			
		||||
                                                message.Length > 1024 ? GetText(strs.redacted_too_long) : message));
 | 
			
		||||
                                         .WithOkColor()
 | 
			
		||||
                                         .WithTitle(GetText(strs.expr_edited))
 | 
			
		||||
                                         .WithDescription($"#{id}")
 | 
			
		||||
                                         .AddField(GetText(strs.trigger), ex.Trigger)
 | 
			
		||||
                                         .AddField(GetText(strs.response),
 | 
			
		||||
                                             message.Length > 1024 ? GetText(strs.redacted_too_long) : message));
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@@ -123,33 +125,36 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var expressions = _service.GetExpressionsFor(ctx.Guild?.Id);
 | 
			
		||||
        var allExpressions = _service.GetExpressionsFor(ctx.Guild?.Id)
 | 
			
		||||
                                     .OrderBy(x => x.Trigger)
 | 
			
		||||
                                     .ToArray();
 | 
			
		||||
 | 
			
		||||
        if (expressions is null || !expressions.Any())
 | 
			
		||||
        if (allExpressions is null || !allExpressions.Any())
 | 
			
		||||
        {
 | 
			
		||||
            await Response().Error(strs.expr_no_found).SendAsync();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await ctx.SendPaginatedConfirmAsync(page,
 | 
			
		||||
            curPage =>
 | 
			
		||||
            {
 | 
			
		||||
                var desc = expressions.OrderBy(ex => ex.Trigger)
 | 
			
		||||
                                      .Skip(curPage * 20)
 | 
			
		||||
                                      .Take(20)
 | 
			
		||||
                                      .Select(ex => $"{(ex.ContainsAnywhere ? "🗯" : "◾")}"
 | 
			
		||||
                                                    + $"{(ex.DmResponse ? "✉" : "◾")}"
 | 
			
		||||
                                                    + $"{(ex.AutoDeleteTrigger ? "❌" : "◾")}"
 | 
			
		||||
                                                    + $"`{(kwum)ex.Id}` {ex.Trigger}"
 | 
			
		||||
                                                    + (string.IsNullOrWhiteSpace(ex.Reactions)
 | 
			
		||||
                                                        ? string.Empty
 | 
			
		||||
                                                        : " // " + string.Join(" ", ex.GetReactions())))
 | 
			
		||||
                                      .Join('\n');
 | 
			
		||||
        await Response()
 | 
			
		||||
              .Paginated()
 | 
			
		||||
              .Items(allExpressions)
 | 
			
		||||
              .PageSize(20)
 | 
			
		||||
              .CurrentPage(page)
 | 
			
		||||
              .Page((exprs, _) =>
 | 
			
		||||
              {
 | 
			
		||||
                  var desc = exprs
 | 
			
		||||
                             .Select(ex => $"{(ex.ContainsAnywhere ? "🗯" : "◾")}"
 | 
			
		||||
                                           + $"{(ex.DmResponse ? "✉" : "◾")}"
 | 
			
		||||
                                           + $"{(ex.AutoDeleteTrigger ? "❌" : "◾")}"
 | 
			
		||||
                                           + $"`{(kwum)ex.Id}` {ex.Trigger}"
 | 
			
		||||
                                           + (string.IsNullOrWhiteSpace(ex.Reactions)
 | 
			
		||||
                                               ? string.Empty
 | 
			
		||||
                                               : " // " + string.Join(" ", ex.GetReactions())))
 | 
			
		||||
                             .Join('\n');
 | 
			
		||||
 | 
			
		||||
                return new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc);
 | 
			
		||||
            },
 | 
			
		||||
            expressions.Length,
 | 
			
		||||
            20);
 | 
			
		||||
                  return new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc);
 | 
			
		||||
              })
 | 
			
		||||
              .SendAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Cmd]
 | 
			
		||||
@@ -164,11 +169,11 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await ctx.Channel.EmbedAsync(new EmbedBuilder()
 | 
			
		||||
                                        .WithOkColor()
 | 
			
		||||
                                        .WithDescription($"#{id}")
 | 
			
		||||
                                        .AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
 | 
			
		||||
                                        .AddField(GetText(strs.response),
 | 
			
		||||
                                            found.Response.TrimTo(1000).Replace("](", "]\\(")));
 | 
			
		||||
                                     .WithOkColor()
 | 
			
		||||
                                     .WithDescription($"#{id}")
 | 
			
		||||
                                     .AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
 | 
			
		||||
                                     .AddField(GetText(strs.response),
 | 
			
		||||
                                         found.Response.TrimTo(1000).Replace("](", "]\\(")));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task ExprDeleteInternalAsync(kwum id)
 | 
			
		||||
@@ -178,11 +183,11 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
 | 
			
		||||
        if (ex is not null)
 | 
			
		||||
        {
 | 
			
		||||
            await ctx.Channel.EmbedAsync(new EmbedBuilder()
 | 
			
		||||
                                            .WithOkColor()
 | 
			
		||||
                                            .WithTitle(GetText(strs.expr_deleted))
 | 
			
		||||
                                            .WithDescription($"#{id}")
 | 
			
		||||
                                            .AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
 | 
			
		||||
                                            .AddField(GetText(strs.response), ex.Response.TrimTo(1024)));
 | 
			
		||||
                                         .WithOkColor()
 | 
			
		||||
                                         .WithTitle(GetText(strs.expr_deleted))
 | 
			
		||||
                                         .WithDescription($"#{id}")
 | 
			
		||||
                                         .AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
 | 
			
		||||
                                         .AddField(GetText(strs.response), ex.Response.TrimTo(1024)));
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@@ -328,8 +333,8 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
 | 
			
		||||
    public async Task ExprClear()
 | 
			
		||||
    {
 | 
			
		||||
        if (await PromptUserConfirmAsync(new EmbedBuilder()
 | 
			
		||||
                                            .WithTitle("Expression clear")
 | 
			
		||||
                                            .WithDescription("This will delete all expressions on this server.")))
 | 
			
		||||
                                         .WithTitle("Expression clear")
 | 
			
		||||
                                         .WithDescription("This will delete all expressions on this server.")))
 | 
			
		||||
        {
 | 
			
		||||
            var count = _service.DeleteAllExpressions(ctx.Guild.Id);
 | 
			
		||||
            await Response().Confirm(strs.exprs_cleared(count)).SendAsync();
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ public partial class Permissions
 | 
			
		||||
                throw new ArgumentOutOfRangeException(nameof(page));
 | 
			
		||||
 | 
			
		||||
            var list = _service.GetBlacklist();
 | 
			
		||||
            var items = await list.Where(x => x.Type == type)
 | 
			
		||||
            var allItems = await list.Where(x => x.Type == type)
 | 
			
		||||
                                  .Select(async i =>
 | 
			
		||||
                                  {
 | 
			
		||||
                                      try
 | 
			
		||||
@@ -52,18 +52,25 @@ public partial class Permissions
 | 
			
		||||
                                  })
 | 
			
		||||
                                  .WhenAll();
 | 
			
		||||
 | 
			
		||||
            await ctx.SendPaginatedConfirmAsync(page,
 | 
			
		||||
                curPage =>
 | 
			
		||||
                {
 | 
			
		||||
                    var pageItems = items.Skip(10 * curPage).Take(10).ToList();
 | 
			
		||||
            await Response()
 | 
			
		||||
                  .Paginated()
 | 
			
		||||
                  .Items(allItems)
 | 
			
		||||
                  .PageSize(10)
 | 
			
		||||
                  .CurrentPage(page)
 | 
			
		||||
                  .Page((pageItems, _) =>
 | 
			
		||||
                  {
 | 
			
		||||
                      if (pageItems.Count == 0)
 | 
			
		||||
                          return new EmbedBuilder()
 | 
			
		||||
                                 .WithOkColor()
 | 
			
		||||
                                 .WithTitle(title)
 | 
			
		||||
                                 .WithDescription(GetText(strs.empty_page));
 | 
			
		||||
 | 
			
		||||
                    if (pageItems.Count == 0)
 | 
			
		||||
                        return new EmbedBuilder().WithOkColor().WithTitle(title).WithDescription(GetText(strs.empty_page));
 | 
			
		||||
 | 
			
		||||
                    return new EmbedBuilder().WithTitle(title).WithDescription(pageItems.Join('\n')).WithOkColor();
 | 
			
		||||
                },
 | 
			
		||||
                items.Length,
 | 
			
		||||
                10);
 | 
			
		||||
                      return new EmbedBuilder()
 | 
			
		||||
                             .WithTitle(title)
 | 
			
		||||
                             .WithDescription(allItems.Join('\n'))
 | 
			
		||||
                             .WithOkColor();
 | 
			
		||||
                  })
 | 
			
		||||
                  .SendAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Cmd]
 | 
			
		||||
@@ -130,13 +137,17 @@ public partial class Permissions
 | 
			
		||||
 | 
			
		||||
            if (action == AddRemove.Add)
 | 
			
		||||
            {
 | 
			
		||||
                await Response().Confirm(strs.blacklisted(Format.Code(type.ToString()),
 | 
			
		||||
                    Format.Code(id.ToString()))).SendAsync();
 | 
			
		||||
                await Response()
 | 
			
		||||
                      .Confirm(strs.blacklisted(Format.Code(type.ToString()),
 | 
			
		||||
                          Format.Code(id.ToString())))
 | 
			
		||||
                      .SendAsync();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                await Response().Confirm(strs.unblacklisted(Format.Code(type.ToString()),
 | 
			
		||||
                    Format.Code(id.ToString()))).SendAsync();
 | 
			
		||||
                await Response()
 | 
			
		||||
                      .Confirm(strs.unblacklisted(Format.Code(type.ToString()),
 | 
			
		||||
                          Format.Code(id.ToString())))
 | 
			
		||||
                      .SendAsync();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -120,7 +120,7 @@ public partial class Searches
 | 
			
		||||
                await Response().Embed(new EmbedBuilder().WithOkColor().WithDescription(GetText(strs.feed_no_feed))).SendAsync();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
            await ctx.SendPaginatedConfirmAsync(0,
 | 
			
		||||
                cur =>
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ public partial class Searches
 | 
			
		||||
            if (page-- < 1)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var streams = new List<FollowedStream>();
 | 
			
		||||
            var allStreams = new List<FollowedStream>();
 | 
			
		||||
            await using (var uow = _db.GetDbContext())
 | 
			
		||||
            {
 | 
			
		||||
                var all = uow.GuildConfigsForId(ctx.Guild.Id, set => set.Include(gc => gc.FollowedStreams))
 | 
			
		||||
@@ -83,34 +83,32 @@ public partial class Searches
 | 
			
		||||
                    if (((SocketGuild)ctx.Guild).GetTextChannel(fs.ChannelId) is null)
 | 
			
		||||
                        await _service.UnfollowStreamAsync(fs.GuildId, index);
 | 
			
		||||
                    else
 | 
			
		||||
                        streams.Insert(0, fs);
 | 
			
		||||
                        allStreams.Insert(0, fs);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await ctx.SendPaginatedConfirmAsync(page,
 | 
			
		||||
                cur =>
 | 
			
		||||
                {
 | 
			
		||||
                    var elements = streams
 | 
			
		||||
                                   .Skip(cur * 12)
 | 
			
		||||
                                   .Take(12)
 | 
			
		||||
                                   .ToList();
 | 
			
		||||
            await Response()
 | 
			
		||||
                  .Paginated()
 | 
			
		||||
                  .Items(allStreams)
 | 
			
		||||
                  .PageSize(12)
 | 
			
		||||
                  .CurrentPage(page)
 | 
			
		||||
                  .Page((elements, cur) =>
 | 
			
		||||
                  {
 | 
			
		||||
                      if (elements.Count == 0)
 | 
			
		||||
                          return new EmbedBuilder().WithDescription(GetText(strs.streams_none)).WithErrorColor();
 | 
			
		||||
 | 
			
		||||
                    if (elements.Count == 0)
 | 
			
		||||
                        return new EmbedBuilder().WithDescription(GetText(strs.streams_none)).WithErrorColor();
 | 
			
		||||
                      var eb = new EmbedBuilder().WithTitle(GetText(strs.streams_follow_title)).WithOkColor();
 | 
			
		||||
                      for (var index = 0; index < elements.Count; index++)
 | 
			
		||||
                      {
 | 
			
		||||
                          var elem = elements[index];
 | 
			
		||||
                          eb.AddField($"**#{index + 1 + (12 * cur)}** {elem.Username.ToLower()}",
 | 
			
		||||
                              $"【{elem.Type}】\n<#{elem.ChannelId}>\n{elem.Message?.TrimTo(50)}",
 | 
			
		||||
                              true);
 | 
			
		||||
                      }
 | 
			
		||||
 | 
			
		||||
                    var eb = new EmbedBuilder().WithTitle(GetText(strs.streams_follow_title)).WithOkColor();
 | 
			
		||||
                    for (var index = 0; index < elements.Count; index++)
 | 
			
		||||
                    {
 | 
			
		||||
                        var elem = elements[index];
 | 
			
		||||
                        eb.AddField($"**#{index + 1 + (12 * cur)}** {elem.Username.ToLower()}",
 | 
			
		||||
                            $"【{elem.Type}】\n<#{elem.ChannelId}>\n{elem.Message?.TrimTo(50)}",
 | 
			
		||||
                            true);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return eb;
 | 
			
		||||
                },
 | 
			
		||||
                streams.Count,
 | 
			
		||||
                12);
 | 
			
		||||
                      return eb;
 | 
			
		||||
                  })
 | 
			
		||||
                  .SendAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Cmd]
 | 
			
		||||
 
 | 
			
		||||
@@ -37,36 +37,39 @@ public partial class Utility
 | 
			
		||||
 | 
			
		||||
            var invites = await channel.GetInvitesAsync();
 | 
			
		||||
 | 
			
		||||
            await ctx.SendPaginatedConfirmAsync(page,
 | 
			
		||||
                cur =>
 | 
			
		||||
                {
 | 
			
		||||
                    var i = 1;
 | 
			
		||||
                    var invs = invites.Skip(cur * 9).Take(9).ToList();
 | 
			
		||||
 | 
			
		||||
                    if (!invs.Any())
 | 
			
		||||
                        return new EmbedBuilder().WithErrorColor().WithDescription(GetText(strs.no_invites));
 | 
			
		||||
            await Response()
 | 
			
		||||
                  .Paginated()
 | 
			
		||||
                  .Items(invites)
 | 
			
		||||
                  .PageSize(9)
 | 
			
		||||
                  .Page((invs, _) =>
 | 
			
		||||
                  {
 | 
			
		||||
                      var i = 1;
 | 
			
		||||
 | 
			
		||||
                    var embed = new EmbedBuilder().WithOkColor();
 | 
			
		||||
                    foreach (var inv in invites)
 | 
			
		||||
                    {
 | 
			
		||||
                        var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null
 | 
			
		||||
                            ? "∞"
 | 
			
		||||
                            : (inv.CreatedAt.Value.AddSeconds(inv.MaxAge.Value).UtcDateTime - DateTime.UtcNow).ToString(
 | 
			
		||||
                                """d\.hh\:mm\:ss""");
 | 
			
		||||
                        var creator = inv.Inviter.ToString().TrimTo(25);
 | 
			
		||||
                        var usesString = $"{inv.Uses} / {(inv.MaxUses == 0 ? "∞" : inv.MaxUses?.ToString())}";
 | 
			
		||||
                      if (!invs.Any())
 | 
			
		||||
                          return new EmbedBuilder().WithErrorColor().WithDescription(GetText(strs.no_invites));
 | 
			
		||||
 | 
			
		||||
                        var desc = $@"`{GetText(strs.inv_uses)}` **{usesString}**
 | 
			
		||||
                      var embed = new EmbedBuilder().WithOkColor();
 | 
			
		||||
                      foreach (var inv in invs)
 | 
			
		||||
                      {
 | 
			
		||||
                          var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null
 | 
			
		||||
                              ? "∞"
 | 
			
		||||
                              : (inv.CreatedAt.Value.AddSeconds(inv.MaxAge.Value).UtcDateTime - DateTime.UtcNow)
 | 
			
		||||
                              .ToString(
 | 
			
		||||
                                  """d\.hh\:mm\:ss""");
 | 
			
		||||
                          var creator = inv.Inviter.ToString().TrimTo(25);
 | 
			
		||||
                          var usesString = $"{inv.Uses} / {(inv.MaxUses == 0 ? "∞" : inv.MaxUses?.ToString())}";
 | 
			
		||||
 | 
			
		||||
                          var desc = $@"`{GetText(strs.inv_uses)}` **{usesString}**
 | 
			
		||||
`{GetText(strs.inv_expire)}` **{expiryString}**
 | 
			
		||||
 | 
			
		||||
                        
 | 
			
		||||
{inv.Url} ";
 | 
			
		||||
                        embed.AddField($"#{i++} {creator}", desc);
 | 
			
		||||
                    }
 | 
			
		||||
                          embed.AddField($"#{i++} {creator}", desc);
 | 
			
		||||
                      }
 | 
			
		||||
 | 
			
		||||
                    return embed;
 | 
			
		||||
                },
 | 
			
		||||
                invites.Count,
 | 
			
		||||
                9);
 | 
			
		||||
                      return embed;
 | 
			
		||||
                  })
 | 
			
		||||
                  .SendAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Cmd]
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,14 @@ public partial class Xp
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                await Response().Confirm(
 | 
			
		||||
                    strs.club_transfered(
 | 
			
		||||
                        Format.Bold(club.Name),
 | 
			
		||||
                        Format.Bold(newOwner.ToString())
 | 
			
		||||
                    )
 | 
			
		||||
                ).SendAsync();
 | 
			
		||||
                await Response()
 | 
			
		||||
                      .Confirm(
 | 
			
		||||
                          strs.club_transfered(
 | 
			
		||||
                              Format.Bold(club.Name),
 | 
			
		||||
                              Format.Bold(newOwner.ToString())
 | 
			
		||||
                          )
 | 
			
		||||
                      )
 | 
			
		||||
                      .SendAsync();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -65,7 +67,7 @@ public partial class Xp
 | 
			
		||||
                await Response().Error(strs.club_name_too_long).SendAsync();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            if (result == ClubCreateResult.NameTaken)
 | 
			
		||||
            {
 | 
			
		||||
                await Response().Error(strs.club_name_taken).SendAsync();
 | 
			
		||||
@@ -110,49 +112,52 @@ public partial class Xp
 | 
			
		||||
        private async Task InternalClubInfoAsync(ClubInfo club)
 | 
			
		||||
        {
 | 
			
		||||
            var lvl = new LevelStats(club.Xp);
 | 
			
		||||
            var users = club.Members.OrderByDescending(x =>
 | 
			
		||||
            {
 | 
			
		||||
                var l = new LevelStats(x.TotalXp).Level;
 | 
			
		||||
                if (club.OwnerId == x.Id)
 | 
			
		||||
                    return int.MaxValue;
 | 
			
		||||
                if (x.IsClubAdmin)
 | 
			
		||||
                    return (int.MaxValue / 2) + l;
 | 
			
		||||
                return l;
 | 
			
		||||
            });
 | 
			
		||||
            var allUsers = club.Members.OrderByDescending(x =>
 | 
			
		||||
                               {
 | 
			
		||||
                                   var l = new LevelStats(x.TotalXp).Level;
 | 
			
		||||
                                   if (club.OwnerId == x.Id)
 | 
			
		||||
                                       return int.MaxValue;
 | 
			
		||||
                                   if (x.IsClubAdmin)
 | 
			
		||||
                                       return (int.MaxValue / 2) + l;
 | 
			
		||||
                                   return l;
 | 
			
		||||
                               })
 | 
			
		||||
                               .ToList();
 | 
			
		||||
 | 
			
		||||
            await ctx.SendPaginatedConfirmAsync(0,
 | 
			
		||||
                page =>
 | 
			
		||||
                {
 | 
			
		||||
                    var embed = new EmbedBuilder()
 | 
			
		||||
                        .WithOkColor()
 | 
			
		||||
                        .WithTitle($"{club}")
 | 
			
		||||
                        .WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)")))
 | 
			
		||||
                        .AddField(GetText(strs.desc),
 | 
			
		||||
                            string.IsNullOrWhiteSpace(club.Description) ? "-" : club.Description)
 | 
			
		||||
                        .AddField(GetText(strs.owner), club.Owner.ToString(), true)
 | 
			
		||||
                        // .AddField(GetText(strs.level_req), club.MinimumLevelReq.ToString(), true)
 | 
			
		||||
                        .AddField(GetText(strs.members),
 | 
			
		||||
                            string.Join("\n",
 | 
			
		||||
                                users.Skip(page * 10)
 | 
			
		||||
                                    .Take(10)
 | 
			
		||||
                                    .Select(x =>
 | 
			
		||||
                                    {
 | 
			
		||||
                                        var l = new LevelStats(x.TotalXp);
 | 
			
		||||
                                        var lvlStr = Format.Bold($" ⟪{l.Level}⟫");
 | 
			
		||||
                                        if (club.OwnerId == x.Id)
 | 
			
		||||
                                            return x + "🌟" + lvlStr;
 | 
			
		||||
                                        if (x.IsClubAdmin)
 | 
			
		||||
                                            return x + "⭐" + lvlStr;
 | 
			
		||||
                                        return x + lvlStr;
 | 
			
		||||
                                    })));
 | 
			
		||||
            await Response()
 | 
			
		||||
                  .Paginated()
 | 
			
		||||
                  .Items(allUsers)
 | 
			
		||||
                  .PageSize(10)
 | 
			
		||||
                  .CurrentPage(0)
 | 
			
		||||
                  .Page((users, _) =>
 | 
			
		||||
                  {
 | 
			
		||||
                      var embed = new EmbedBuilder()
 | 
			
		||||
                                  .WithOkColor()
 | 
			
		||||
                                  .WithTitle($"{club}")
 | 
			
		||||
                                  .WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)")))
 | 
			
		||||
                                  .AddField(GetText(strs.desc),
 | 
			
		||||
                                      string.IsNullOrWhiteSpace(club.Description) ? "-" : club.Description)
 | 
			
		||||
                                  .AddField(GetText(strs.owner), club.Owner.ToString(), true)
 | 
			
		||||
                                  // .AddField(GetText(strs.level_req), club.MinimumLevelReq.ToString(), true)
 | 
			
		||||
                                  .AddField(GetText(strs.members),
 | 
			
		||||
                                      string.Join("\n",
 | 
			
		||||
                                          users
 | 
			
		||||
                                              .Select(x =>
 | 
			
		||||
                                              {
 | 
			
		||||
                                                  var l = new LevelStats(x.TotalXp);
 | 
			
		||||
                                                  var lvlStr = Format.Bold($" ⟪{l.Level}⟫");
 | 
			
		||||
                                                  if (club.OwnerId == x.Id)
 | 
			
		||||
                                                      return x + "🌟" + lvlStr;
 | 
			
		||||
                                                  if (x.IsClubAdmin)
 | 
			
		||||
                                                      return x + "⭐" + lvlStr;
 | 
			
		||||
                                                  return x + lvlStr;
 | 
			
		||||
                                              })));
 | 
			
		||||
 | 
			
		||||
                    if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
 | 
			
		||||
                        return embed.WithThumbnailUrl(club.ImageUrl);
 | 
			
		||||
                      if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
 | 
			
		||||
                          return embed.WithThumbnailUrl(club.ImageUrl);
 | 
			
		||||
 | 
			
		||||
                    return embed;
 | 
			
		||||
                },
 | 
			
		||||
                club.Members.Count,
 | 
			
		||||
                10);
 | 
			
		||||
                      return embed;
 | 
			
		||||
                  })
 | 
			
		||||
                  .SendAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Cmd]
 | 
			
		||||
@@ -204,14 +209,16 @@ public partial class Xp
 | 
			
		||||
            return ctx.SendPaginatedConfirmAsync(page,
 | 
			
		||||
                _ =>
 | 
			
		||||
                {
 | 
			
		||||
                    var toShow = string.Join("\n", bans
 | 
			
		||||
                        .Skip(page * 10).Take(10)
 | 
			
		||||
                        .Select(x => x.ToString()));
 | 
			
		||||
                    var toShow = string.Join("\n",
 | 
			
		||||
                        bans
 | 
			
		||||
                            .Skip(page * 10)
 | 
			
		||||
                            .Take(10)
 | 
			
		||||
                            .Select(x => x.ToString()));
 | 
			
		||||
 | 
			
		||||
                    return new EmbedBuilder()
 | 
			
		||||
                        .WithTitle(GetText(strs.club_bans_for(club.ToString())))
 | 
			
		||||
                        .WithDescription(toShow)
 | 
			
		||||
                        .WithOkColor();
 | 
			
		||||
                           .WithTitle(GetText(strs.club_bans_for(club.ToString())))
 | 
			
		||||
                           .WithDescription(toShow)
 | 
			
		||||
                           .WithOkColor();
 | 
			
		||||
                },
 | 
			
		||||
                bans.Length,
 | 
			
		||||
                10);
 | 
			
		||||
@@ -235,9 +242,9 @@ public partial class Xp
 | 
			
		||||
                    var toShow = string.Join("\n", apps.Skip(page * 10).Take(10).Select(x => x.ToString()));
 | 
			
		||||
 | 
			
		||||
                    return new EmbedBuilder()
 | 
			
		||||
                        .WithTitle(GetText(strs.club_apps_for(club.ToString())))
 | 
			
		||||
                        .WithDescription(toShow)
 | 
			
		||||
                        .WithOkColor();
 | 
			
		||||
                           .WithTitle(GetText(strs.club_apps_for(club.ToString())))
 | 
			
		||||
                           .WithDescription(toShow)
 | 
			
		||||
                           .WithOkColor();
 | 
			
		||||
                },
 | 
			
		||||
                apps.Length,
 | 
			
		||||
                10);
 | 
			
		||||
@@ -283,7 +290,7 @@ public partial class Xp
 | 
			
		||||
            else if (result == ClubAcceptResult.NotOwnerOrAdmin)
 | 
			
		||||
                await Response().Error(strs.club_admin_perms).SendAsync();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        [Cmd]
 | 
			
		||||
        [Priority(1)]
 | 
			
		||||
        public Task ClubReject(IUser user)
 | 
			
		||||
@@ -296,9 +303,9 @@ public partial class Xp
 | 
			
		||||
            var result = _service.RejectApplication(ctx.User.Id, userName, out var discordUser);
 | 
			
		||||
            if (result == ClubDenyResult.Rejected)
 | 
			
		||||
                await Response().Confirm(strs.club_rejected(Format.Bold(discordUser.ToString()))).SendAsync();
 | 
			
		||||
            else if(result == ClubDenyResult.NoSuchApplicant)
 | 
			
		||||
            else if (result == ClubDenyResult.NoSuchApplicant)
 | 
			
		||||
                await Response().Error(strs.club_accept_invalid_applicant).SendAsync();
 | 
			
		||||
            else if(result == ClubDenyResult.NotOwnerOrAdmin)
 | 
			
		||||
            else if (result == ClubDenyResult.NotOwnerOrAdmin)
 | 
			
		||||
                await Response().Error(strs.club_admin_perms).SendAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -327,8 +334,10 @@ public partial class Xp
 | 
			
		||||
            var result = _service.Kick(ctx.User.Id, userName, out var club);
 | 
			
		||||
            if (result == ClubKickResult.Success)
 | 
			
		||||
            {
 | 
			
		||||
                return Response().Confirm(strs.club_user_kick(Format.Bold(userName),
 | 
			
		||||
                    Format.Bold(club.ToString()))).SendAsync();
 | 
			
		||||
                return Response()
 | 
			
		||||
                       .Confirm(strs.club_user_kick(Format.Bold(userName),
 | 
			
		||||
                           Format.Bold(club.ToString())))
 | 
			
		||||
                       .SendAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (result == ClubKickResult.Hierarchy)
 | 
			
		||||
@@ -352,8 +361,10 @@ public partial class Xp
 | 
			
		||||
            var result = _service.Ban(ctx.User.Id, userName, out var club);
 | 
			
		||||
            if (result == ClubBanResult.Success)
 | 
			
		||||
            {
 | 
			
		||||
                return Response().Confirm(strs.club_user_banned(Format.Bold(userName),
 | 
			
		||||
                    Format.Bold(club.ToString()))).SendAsync();
 | 
			
		||||
                return Response()
 | 
			
		||||
                       .Confirm(strs.club_user_banned(Format.Bold(userName),
 | 
			
		||||
                           Format.Bold(club.ToString())))
 | 
			
		||||
                       .SendAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (result == ClubBanResult.Unbannable)
 | 
			
		||||
@@ -378,8 +389,10 @@ public partial class Xp
 | 
			
		||||
 | 
			
		||||
            if (result == ClubUnbanResult.Success)
 | 
			
		||||
            {
 | 
			
		||||
                return Response().Confirm(strs.club_user_unbanned(Format.Bold(userName),
 | 
			
		||||
                    Format.Bold(club.ToString()))).SendAsync();
 | 
			
		||||
                return Response()
 | 
			
		||||
                       .Confirm(strs.club_user_unbanned(Format.Bold(userName),
 | 
			
		||||
                           Format.Bold(club.ToString())))
 | 
			
		||||
                       .SendAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (result == ClubUnbanResult.WrongUser)
 | 
			
		||||
@@ -400,10 +413,10 @@ public partial class Xp
 | 
			
		||||
                    : desc;
 | 
			
		||||
 | 
			
		||||
                var eb = new EmbedBuilder()
 | 
			
		||||
                    .WithAuthor(ctx.User)
 | 
			
		||||
                    .WithTitle(GetText(strs.club_desc_update))
 | 
			
		||||
                    .WithOkColor()
 | 
			
		||||
                    .WithDescription(desc);
 | 
			
		||||
                         .WithAuthor(ctx.User)
 | 
			
		||||
                         .WithTitle(GetText(strs.club_desc_update))
 | 
			
		||||
                         .WithOkColor()
 | 
			
		||||
                         .WithDescription(desc);
 | 
			
		||||
 | 
			
		||||
                await Response().Embed(eb).SendAsync();
 | 
			
		||||
            }
 | 
			
		||||
@@ -450,11 +463,11 @@ public partial class Xp
 | 
			
		||||
                    await Response().Error(strs.club_name_too_long).SendAsync();
 | 
			
		||||
                    return;
 | 
			
		||||
                case ClubRenameResult.Success:
 | 
			
		||||
                {
 | 
			
		||||
                    var embed = new EmbedBuilder().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor();
 | 
			
		||||
                    await Response().Embed(embed).SendAsync();
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                    {
 | 
			
		||||
                        var embed = new EmbedBuilder().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor();
 | 
			
		||||
                        await Response().Embed(embed).SendAsync();
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                case ClubRenameResult.NameTaken:
 | 
			
		||||
                    await Response().Error(strs.club_name_taken).SendAsync();
 | 
			
		||||
                    return;
 | 
			
		||||
 
 | 
			
		||||
@@ -96,7 +96,7 @@ public static class MessageChannelExtensions
 | 
			
		||||
            embed: embed?.Build(),
 | 
			
		||||
            embeds: embeds?.Map(x => x.Build()),
 | 
			
		||||
            replyTo: replyTo);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // embed title and optional footer overloads
 | 
			
		||||
 | 
			
		||||
    public static Task SendPaginatedConfirmAsync(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										155
									
								
								src/NadekoBot/_common/Sender/ResponseBuilder.PaginationSender.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								src/NadekoBot/_common/Sender/ResponseBuilder.PaginationSender.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,155 @@
 | 
			
		||||
namespace NadekoBot.Extensions;
 | 
			
		||||
 | 
			
		||||
public partial class ResponseBuilder
 | 
			
		||||
{
 | 
			
		||||
    public class PaginationSender<T>
 | 
			
		||||
    {
 | 
			
		||||
        private const string BUTTON_LEFT = "BUTTON_LEFT";
 | 
			
		||||
        private const string BUTTON_RIGHT = "BUTTON_RIGHT";
 | 
			
		||||
 | 
			
		||||
        private static readonly IEmote _arrowLeft = Emote.Parse("<:x:1232256519844790302>");
 | 
			
		||||
        private static readonly IEmote _arrowRight = Emote.Parse("<:x:1232256515298295838>");
 | 
			
		||||
 | 
			
		||||
        private readonly SourcedPaginatedResponseBuilder<T> _paginationBuilder;
 | 
			
		||||
        private readonly ResponseBuilder builder;
 | 
			
		||||
        private readonly DiscordSocketClient client;
 | 
			
		||||
        private int currentPage;
 | 
			
		||||
 | 
			
		||||
        public PaginationSender(
 | 
			
		||||
            SourcedPaginatedResponseBuilder<T> paginationBuilder,
 | 
			
		||||
            ResponseBuilder builder
 | 
			
		||||
        )
 | 
			
		||||
        {
 | 
			
		||||
            this._paginationBuilder = paginationBuilder;
 | 
			
		||||
            this.builder = builder;
 | 
			
		||||
 | 
			
		||||
            client = (DiscordSocketClient)builder.ctx.Client;
 | 
			
		||||
            currentPage = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task SendAsync(bool ephemeral = false)
 | 
			
		||||
        {
 | 
			
		||||
            var lastPage = (_paginationBuilder.TotalElements - 1)
 | 
			
		||||
                           / _paginationBuilder.ItemsPerPage;
 | 
			
		||||
 | 
			
		||||
            var items = (await _paginationBuilder.ItemsFunc(currentPage)).ToArray();
 | 
			
		||||
            var embed = await _paginationBuilder.PageFunc(items, currentPage);
 | 
			
		||||
 | 
			
		||||
            if (_paginationBuilder.AddPaginatedFooter)
 | 
			
		||||
                embed.AddPaginatedFooter(currentPage, lastPage);
 | 
			
		||||
 | 
			
		||||
            SimpleInteraction<T>? maybeInter = null;
 | 
			
		||||
 | 
			
		||||
            async Task<ComponentBuilder> GetComponentBuilder()
 | 
			
		||||
            {
 | 
			
		||||
                var cb = new ComponentBuilder();
 | 
			
		||||
 | 
			
		||||
                cb.WithButton(new ButtonBuilder()
 | 
			
		||||
                              .WithStyle(ButtonStyle.Primary)
 | 
			
		||||
                              .WithCustomId(BUTTON_LEFT)
 | 
			
		||||
                              .WithDisabled(lastPage == 0)
 | 
			
		||||
                              .WithEmote(_arrowLeft)
 | 
			
		||||
                              .WithDisabled(currentPage <= 0));
 | 
			
		||||
                // todo
 | 
			
		||||
                // if (interFactory is not null)
 | 
			
		||||
                // {
 | 
			
		||||
                //     maybeInter = await interFactory(currentPage);
 | 
			
		||||
                //
 | 
			
		||||
                //     if (maybeInter is not null)
 | 
			
		||||
                //         cb.WithButton(maybeInter.Button);
 | 
			
		||||
                // }
 | 
			
		||||
 | 
			
		||||
                cb.WithButton(new ButtonBuilder()
 | 
			
		||||
                              .WithStyle(ButtonStyle.Primary)
 | 
			
		||||
                              .WithCustomId(BUTTON_RIGHT)
 | 
			
		||||
                              .WithDisabled(lastPage == 0 || currentPage >= lastPage)
 | 
			
		||||
                              .WithEmote(_arrowRight));
 | 
			
		||||
 | 
			
		||||
                return cb;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            async Task UpdatePageAsync(SocketMessageComponent smc)
 | 
			
		||||
            {
 | 
			
		||||
                var pageItems = (await _paginationBuilder.ItemsFunc(currentPage)).ToArray();
 | 
			
		||||
                var toSend = await _paginationBuilder.PageFunc(pageItems, currentPage);
 | 
			
		||||
                if (_paginationBuilder.AddPaginatedFooter)
 | 
			
		||||
                    toSend.AddPaginatedFooter(currentPage, lastPage);
 | 
			
		||||
 | 
			
		||||
                var component = (await GetComponentBuilder()).Build();
 | 
			
		||||
 | 
			
		||||
                await smc.ModifyOriginalResponseAsync(x =>
 | 
			
		||||
                {
 | 
			
		||||
                    x.Embed = toSend.Build();
 | 
			
		||||
                    x.Components = component;
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var model = builder.Build(ephemeral);
 | 
			
		||||
 | 
			
		||||
            var component = (await GetComponentBuilder()).Build();
 | 
			
		||||
            var msg = await model.TargetChannel
 | 
			
		||||
                                 .SendMessageAsync(model.Text,
 | 
			
		||||
                                     embed: embed.Build(),
 | 
			
		||||
                                     components: component,
 | 
			
		||||
                                     messageReference: model.MessageReference);
 | 
			
		||||
 | 
			
		||||
            async Task OnInteractionAsync(SocketInteraction si)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if (si is not SocketMessageComponent smc)
 | 
			
		||||
                        return;
 | 
			
		||||
 | 
			
		||||
                    if (smc.Message.Id != msg.Id)
 | 
			
		||||
                        return;
 | 
			
		||||
 | 
			
		||||
                    await si.DeferAsync();
 | 
			
		||||
                    if (smc.User.Id != model.User.Id)
 | 
			
		||||
                        return;
 | 
			
		||||
 | 
			
		||||
                    if (smc.Data.CustomId == BUTTON_LEFT)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (currentPage == 0)
 | 
			
		||||
                            return;
 | 
			
		||||
 | 
			
		||||
                        --currentPage;
 | 
			
		||||
                        _ = UpdatePageAsync(smc);
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (smc.Data.CustomId == BUTTON_RIGHT)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (currentPage >= lastPage)
 | 
			
		||||
                            return;
 | 
			
		||||
 | 
			
		||||
                        ++currentPage;
 | 
			
		||||
                        _ = UpdatePageAsync(smc);
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (maybeInter is { } inter && inter.Button.CustomId == smc.Data.CustomId)
 | 
			
		||||
                    {
 | 
			
		||||
                        await inter.TriggerAsync(smc);
 | 
			
		||||
                        _ = UpdatePageAsync(smc);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // todo re-add
 | 
			
		||||
            // if (lastPage == 0 && interFactory is null)
 | 
			
		||||
            //     return;
 | 
			
		||||
 | 
			
		||||
            if (lastPage == 0)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var client = this.client;
 | 
			
		||||
 | 
			
		||||
            client.InteractionCreated += OnInteractionAsync;
 | 
			
		||||
 | 
			
		||||
            await Task.Delay(30_000);
 | 
			
		||||
 | 
			
		||||
            client.InteractionCreated -= OnInteractionAsync;
 | 
			
		||||
 | 
			
		||||
            await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
namespace NadekoBot.Extensions;
 | 
			
		||||
 | 
			
		||||
public sealed class ResponseBuilder
 | 
			
		||||
public sealed partial class ResponseBuilder
 | 
			
		||||
{
 | 
			
		||||
    private ICommandContext? ctx = null;
 | 
			
		||||
    private IMessageChannel? channel = null;
 | 
			
		||||
@@ -44,33 +44,53 @@ public sealed class ResponseBuilder
 | 
			
		||||
            failIfNotExists: false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<IUserMessage> SendAsync(bool ephemeral = false)
 | 
			
		||||
    public ResponseMessageModel Build(bool ephemeral = false)
 | 
			
		||||
    {
 | 
			
		||||
        // todo use ephemeral in interactions
 | 
			
		||||
        var targetChannel = InternalResolveChannel() ?? throw new ArgumentNullException(nameof(channel));
 | 
			
		||||
        var msgReference = CreateMessageReference(targetChannel);
 | 
			
		||||
 | 
			
		||||
        var txt = GetText(locTxt);
 | 
			
		||||
        // todo check message  sanitization
 | 
			
		||||
 | 
			
		||||
        if (sanitizeMentions)
 | 
			
		||||
            txt = txt?.SanitizeMentions(true);
 | 
			
		||||
        var buildModel = new ResponseMessageModel()
 | 
			
		||||
        {
 | 
			
		||||
            TargetChannel = targetChannel,
 | 
			
		||||
            MessageReference = msgReference,
 | 
			
		||||
            Text = txt,
 | 
			
		||||
            User = ctx?.User,
 | 
			
		||||
            Embed = embed ?? embedBuilder?.Build(),
 | 
			
		||||
            Embeds = embeds?.Map(x => x.Build()),
 | 
			
		||||
            SanitizeMentions = sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return buildModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Task<IUserMessage> SendAsync(bool ephemeral = false)
 | 
			
		||||
    {
 | 
			
		||||
        var model = Build(ephemeral);
 | 
			
		||||
        return SendAsync(model);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<IUserMessage> SendAsync(ResponseMessageModel model)
 | 
			
		||||
    {
 | 
			
		||||
        if (this.fileStream is Stream stream)
 | 
			
		||||
            return await targetChannel.SendFileAsync(stream,
 | 
			
		||||
            return await model.TargetChannel.SendFileAsync(stream,
 | 
			
		||||
                filename: fileName,
 | 
			
		||||
                txt,
 | 
			
		||||
                embed: embed ?? embedBuilder?.Build(),
 | 
			
		||||
                model.Text,
 | 
			
		||||
                embed: model.Embed,
 | 
			
		||||
                components: null,
 | 
			
		||||
                allowedMentions: sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All,
 | 
			
		||||
                messageReference: msgReference);
 | 
			
		||||
                allowedMentions: model.SanitizeMentions,
 | 
			
		||||
                messageReference: model.MessageReference);
 | 
			
		||||
 | 
			
		||||
        return await targetChannel.SendMessageAsync(
 | 
			
		||||
            txt,
 | 
			
		||||
            embed: embed ?? embedBuilder?.Build(),
 | 
			
		||||
            embeds: embeds?.Map(x => x.Build()),
 | 
			
		||||
        return await model.TargetChannel.SendMessageAsync(
 | 
			
		||||
            model.Text,
 | 
			
		||||
            embed: model.Embed,
 | 
			
		||||
            embeds: model.Embeds,
 | 
			
		||||
            components: null,
 | 
			
		||||
            allowedMentions: sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All,
 | 
			
		||||
            messageReference: msgReference);
 | 
			
		||||
            allowedMentions: model.SanitizeMentions,
 | 
			
		||||
            messageReference: model.MessageReference);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ulong? InternalResolveGuildId(IMessageChannel? targetChannel)
 | 
			
		||||
@@ -263,4 +283,94 @@ public sealed class ResponseBuilder
 | 
			
		||||
        this.fileName = fileName;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public PaginatedResponseBuilder Paginated()
 | 
			
		||||
        => new(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public class PaginatedResponseBuilder
 | 
			
		||||
{
 | 
			
		||||
    protected readonly ResponseBuilder _builder;
 | 
			
		||||
 | 
			
		||||
    public PaginatedResponseBuilder(ResponseBuilder builder)
 | 
			
		||||
    {
 | 
			
		||||
        _builder = builder;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> Items<T>(IReadOnlyCollection<T> items)
 | 
			
		||||
        => new SourcedPaginatedResponseBuilder<T>(_builder)
 | 
			
		||||
            .Items(items);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilder
 | 
			
		||||
{
 | 
			
		||||
    private IReadOnlyCollection<T>? items;
 | 
			
		||||
    public Func<IReadOnlyList<T>, int, Task<EmbedBuilder>> PageFunc { get; private set; }
 | 
			
		||||
    public Func<int, Task<IEnumerable<T>>> ItemsFunc { get; set; }
 | 
			
		||||
    public int TotalElements { get; private set; } = 1;
 | 
			
		||||
    public int ItemsPerPage { get; private set; } = 9;
 | 
			
		||||
    public bool AddPaginatedFooter { get; private set; } = true;
 | 
			
		||||
    public bool IsEphemeral { get; private set; }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder(ResponseBuilder builder)
 | 
			
		||||
        : base(builder)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> Items(IReadOnlyCollection<T> items)
 | 
			
		||||
    {
 | 
			
		||||
        this.items = items;
 | 
			
		||||
        ItemsFunc = (i) => Task.FromResult(this.items.Skip(i * ItemsPerPage).Take(ItemsPerPage));
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> PageSize(int i)
 | 
			
		||||
    {
 | 
			
		||||
        ItemsPerPage = i;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> CurrentPage(int i)
 | 
			
		||||
    {
 | 
			
		||||
        InitialPage = i;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // todo use it
 | 
			
		||||
    public int InitialPage { get; set; }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> Page(Func<IReadOnlyList<T>, int, EmbedBuilder> pageFunc)
 | 
			
		||||
    {
 | 
			
		||||
        this.PageFunc = (xs, x) => Task.FromResult(pageFunc(xs, x));
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> Page(Func<IReadOnlyList<T>, int, Task<EmbedBuilder>> pageFunc)
 | 
			
		||||
    {
 | 
			
		||||
        this.PageFunc = pageFunc;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> AddFooter()
 | 
			
		||||
    {
 | 
			
		||||
        AddPaginatedFooter = true;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> Ephemeral()
 | 
			
		||||
    {
 | 
			
		||||
        IsEphemeral = true;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public Task SendAsync()
 | 
			
		||||
    {
 | 
			
		||||
        var paginationSender = new ResponseBuilder.PaginationSender<T>(
 | 
			
		||||
            this,
 | 
			
		||||
            _builder);
 | 
			
		||||
 | 
			
		||||
        return paginationSender.SendAsync(IsEphemeral);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/NadekoBot/_common/Sender/ResponseMessageModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/NadekoBot/_common/Sender/ResponseMessageModel.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
public class ResponseMessageModel
 | 
			
		||||
{
 | 
			
		||||
    public IMessageChannel TargetChannel { get; set; }
 | 
			
		||||
    public MessageReference MessageReference { get; set; }
 | 
			
		||||
    public string Text { get; set; }
 | 
			
		||||
    public Embed Embed { get; set; }
 | 
			
		||||
    public Embed[] Embeds { get; set; }
 | 
			
		||||
    public AllowedMentions SanitizeMentions { get; set; }
 | 
			
		||||
    public IUser User { get; set; }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user