mirror of
				https://gitlab.com/Kwoth/nadekobot.git
				synced 2025-11-04 00:34:26 -05:00 
			
		
		
		
	fix: xplb and xpglb pagination fixed, closes #430
fix: Page number when there is an unknown number of items while paginating is now correct fix: .stm and .stma fixed and can now mention everyone as long as the user executing the command also can dev: Cleaned up/improved some code
This commit is contained in:
		@@ -20,48 +20,48 @@ public static class DiscordUserExtensions
 | 
			
		||||
        string discrim,
 | 
			
		||||
        string avatarId)
 | 
			
		||||
        => ctx.GetTable<DiscordUser>()
 | 
			
		||||
            .InsertOrUpdate(
 | 
			
		||||
                () => new()
 | 
			
		||||
                {
 | 
			
		||||
                    UserId = userId,
 | 
			
		||||
                    Username = username,
 | 
			
		||||
                    Discriminator = discrim,
 | 
			
		||||
                    AvatarId = avatarId,
 | 
			
		||||
                    TotalXp = 0,
 | 
			
		||||
                    CurrencyAmount = 0
 | 
			
		||||
                },
 | 
			
		||||
                old => new()
 | 
			
		||||
                {
 | 
			
		||||
                    Username = username,
 | 
			
		||||
                    Discriminator = discrim,
 | 
			
		||||
                    AvatarId = avatarId
 | 
			
		||||
                },
 | 
			
		||||
                () => new()
 | 
			
		||||
                {
 | 
			
		||||
                    UserId = userId
 | 
			
		||||
                });
 | 
			
		||||
              .InsertOrUpdate(
 | 
			
		||||
                  () => new()
 | 
			
		||||
                  {
 | 
			
		||||
                      UserId = userId,
 | 
			
		||||
                      Username = username,
 | 
			
		||||
                      Discriminator = discrim,
 | 
			
		||||
                      AvatarId = avatarId,
 | 
			
		||||
                      TotalXp = 0,
 | 
			
		||||
                      CurrencyAmount = 0
 | 
			
		||||
                  },
 | 
			
		||||
                  old => new()
 | 
			
		||||
                  {
 | 
			
		||||
                      Username = username,
 | 
			
		||||
                      Discriminator = discrim,
 | 
			
		||||
                      AvatarId = avatarId
 | 
			
		||||
                  },
 | 
			
		||||
                  () => new()
 | 
			
		||||
                  {
 | 
			
		||||
                      UserId = userId
 | 
			
		||||
                  });
 | 
			
		||||
 | 
			
		||||
    public static Task EnsureUserCreatedAsync(
 | 
			
		||||
        this DbContext ctx,
 | 
			
		||||
        ulong userId)
 | 
			
		||||
        => ctx.GetTable<DiscordUser>()
 | 
			
		||||
            .InsertOrUpdateAsync(
 | 
			
		||||
                () => new()
 | 
			
		||||
                {
 | 
			
		||||
                    UserId = userId,
 | 
			
		||||
                    Username = "Unknown",
 | 
			
		||||
                    Discriminator = "????",
 | 
			
		||||
                    AvatarId = string.Empty,
 | 
			
		||||
                    TotalXp = 0,
 | 
			
		||||
                    CurrencyAmount = 0
 | 
			
		||||
                },
 | 
			
		||||
                old => new()
 | 
			
		||||
                {
 | 
			
		||||
                },
 | 
			
		||||
                () => new()
 | 
			
		||||
                {
 | 
			
		||||
                    UserId = userId
 | 
			
		||||
                });
 | 
			
		||||
              .InsertOrUpdateAsync(
 | 
			
		||||
                  () => new()
 | 
			
		||||
                  {
 | 
			
		||||
                      UserId = userId,
 | 
			
		||||
                      Username = "Unknown",
 | 
			
		||||
                      Discriminator = "????",
 | 
			
		||||
                      AvatarId = string.Empty,
 | 
			
		||||
                      TotalXp = 0,
 | 
			
		||||
                      CurrencyAmount = 0
 | 
			
		||||
                  },
 | 
			
		||||
                  old => new()
 | 
			
		||||
                  {
 | 
			
		||||
                  },
 | 
			
		||||
                  () => new()
 | 
			
		||||
                  {
 | 
			
		||||
                      UserId = userId
 | 
			
		||||
                  });
 | 
			
		||||
 | 
			
		||||
    //temp is only used in updatecurrencystate, so that i don't overwrite real usernames/discrims with Unknown
 | 
			
		||||
    public static DiscordUser GetOrCreateUser(
 | 
			
		||||
@@ -83,25 +83,29 @@ public static class DiscordUserExtensions
 | 
			
		||||
 | 
			
		||||
    public static int GetUserGlobalRank(this DbSet<DiscordUser> users, ulong id)
 | 
			
		||||
        => users.AsQueryable()
 | 
			
		||||
               .Where(x => x.TotalXp
 | 
			
		||||
                           > users.AsQueryable().Where(y => y.UserId == id).Select(y => y.TotalXp).FirstOrDefault())
 | 
			
		||||
               .Count()
 | 
			
		||||
                .Where(x => x.TotalXp
 | 
			
		||||
                            > users.AsQueryable().Where(y => y.UserId == id).Select(y => y.TotalXp).FirstOrDefault())
 | 
			
		||||
                .Count()
 | 
			
		||||
           + 1;
 | 
			
		||||
 | 
			
		||||
    public static DiscordUser[] GetUsersXpLeaderboardFor(this DbSet<DiscordUser> users, int page, int perPage)
 | 
			
		||||
        => users.AsQueryable().OrderByDescending(x => x.TotalXp).Skip(page * perPage).Take(perPage).AsEnumerable()
 | 
			
		||||
            .ToArray();
 | 
			
		||||
    public static async Task<IReadOnlyCollection<DiscordUser>> GetUsersXpLeaderboardFor(this DbSet<DiscordUser> users, int page, int perPage)
 | 
			
		||||
        => await users.ToLinqToDBTable()
 | 
			
		||||
                      .OrderByDescending(x => x.TotalXp)
 | 
			
		||||
                      .Skip(page * perPage)
 | 
			
		||||
                      .Take(perPage)
 | 
			
		||||
                      .ToArrayAsyncLinqToDB();
 | 
			
		||||
 | 
			
		||||
    public static Task<List<DiscordUser>> GetTopRichest(
 | 
			
		||||
        this DbSet<DiscordUser> users,
 | 
			
		||||
        ulong botId,
 | 
			
		||||
        int page = 0, int perPage = 9)
 | 
			
		||||
        int page = 0,
 | 
			
		||||
        int perPage = 9)
 | 
			
		||||
        => users.AsQueryable()
 | 
			
		||||
            .Where(c => c.CurrencyAmount > 0 && botId != c.UserId)
 | 
			
		||||
            .OrderByDescending(c => c.CurrencyAmount)
 | 
			
		||||
            .Skip(page * perPage)
 | 
			
		||||
            .Take(perPage)
 | 
			
		||||
            .ToListAsyncLinqToDB();
 | 
			
		||||
                .Where(c => c.CurrencyAmount > 0 && botId != c.UserId)
 | 
			
		||||
                .OrderByDescending(c => c.CurrencyAmount)
 | 
			
		||||
                .Skip(page * perPage)
 | 
			
		||||
                .Take(perPage)
 | 
			
		||||
                .ToListAsyncLinqToDB();
 | 
			
		||||
 | 
			
		||||
    public static async Task<long> GetUserCurrencyAsync(this DbSet<DiscordUser> users, ulong userId)
 | 
			
		||||
        => (await users.FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId))?.CurrencyAmount ?? 0;
 | 
			
		||||
@@ -118,8 +122,8 @@ public static class DiscordUserExtensions
 | 
			
		||||
 | 
			
		||||
    public static decimal GetTopOnePercentCurrency(this DbSet<DiscordUser> users, ulong botId)
 | 
			
		||||
        => users.AsQueryable()
 | 
			
		||||
            .Where(x => x.UserId != botId)
 | 
			
		||||
            .OrderByDescending(x => x.CurrencyAmount)
 | 
			
		||||
            .Take(users.Count() / 100 == 0 ? 1 : users.Count() / 100)
 | 
			
		||||
            .Sum(x => x.CurrencyAmount);
 | 
			
		||||
                .Where(x => x.UserId != botId)
 | 
			
		||||
                .OrderByDescending(x => x.CurrencyAmount)
 | 
			
		||||
                .Take(users.Count() / 100 == 0 ? 1 : users.Count() / 100)
 | 
			
		||||
                .Sum(x => x.CurrencyAmount);
 | 
			
		||||
}
 | 
			
		||||
@@ -2,7 +2,6 @@
 | 
			
		||||
using LinqToDB;
 | 
			
		||||
using LinqToDB.EntityFrameworkCore;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
 | 
			
		||||
using NadekoBot.Db.Models;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Db;
 | 
			
		||||
@@ -27,33 +26,33 @@ public static class UserXpExtensions
 | 
			
		||||
        return usr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<UserXpStats> GetUsersFor(this DbSet<UserXpStats> xps, ulong guildId, int page)
 | 
			
		||||
        => xps.AsQueryable()
 | 
			
		||||
              .AsNoTracking()
 | 
			
		||||
              .Where(x => x.GuildId == guildId)
 | 
			
		||||
              .OrderByDescending(x => x.Xp + x.AwardedXp)
 | 
			
		||||
              .Skip(page * 9)
 | 
			
		||||
              .Take(9)
 | 
			
		||||
              .ToList();
 | 
			
		||||
    public static async Task<IReadOnlyCollection<UserXpStats>> GetUsersFor(
 | 
			
		||||
        this DbSet<UserXpStats> xps,
 | 
			
		||||
        ulong guildId,
 | 
			
		||||
        int page)
 | 
			
		||||
        => await xps.ToLinqToDBTable()
 | 
			
		||||
                    .Where(x => x.GuildId == guildId)
 | 
			
		||||
                    .OrderByDescending(x => x.Xp + x.AwardedXp)
 | 
			
		||||
                    .Skip(page * 9)
 | 
			
		||||
                    .Take(9)
 | 
			
		||||
                    .ToArrayAsyncLinqToDB();
 | 
			
		||||
 | 
			
		||||
    public static List<UserXpStats> GetTopUserXps(this DbSet<UserXpStats> xps, ulong guildId, int count)
 | 
			
		||||
        => xps.AsQueryable()
 | 
			
		||||
              .AsNoTracking()
 | 
			
		||||
              .Where(x => x.GuildId == guildId)
 | 
			
		||||
              .OrderByDescending(x => x.Xp + x.AwardedXp)
 | 
			
		||||
              .Take(count)
 | 
			
		||||
              .ToList();
 | 
			
		||||
    public static async Task<List<UserXpStats>> GetTopUserXps(this DbSet<UserXpStats> xps, ulong guildId, int count)
 | 
			
		||||
        => await xps.ToLinqToDBTable()
 | 
			
		||||
                    .Where(x => x.GuildId == guildId)
 | 
			
		||||
                    .OrderByDescending(x => x.Xp + x.AwardedXp)
 | 
			
		||||
                    .Take(count)
 | 
			
		||||
                    .ToListAsyncLinqToDB();
 | 
			
		||||
 | 
			
		||||
    public static int GetUserGuildRanking(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
 | 
			
		||||
        => xps.AsQueryable()
 | 
			
		||||
              .AsNoTracking()
 | 
			
		||||
              .Where(x => x.GuildId == guildId
 | 
			
		||||
                          && x.Xp + x.AwardedXp
 | 
			
		||||
                          > xps.AsQueryable()
 | 
			
		||||
                               .Where(y => y.UserId == userId && y.GuildId == guildId)
 | 
			
		||||
                               .Select(y => y.Xp + y.AwardedXp)
 | 
			
		||||
                               .FirstOrDefault())
 | 
			
		||||
              .Count()
 | 
			
		||||
    public static async Task<int> GetUserGuildRanking(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
 | 
			
		||||
        => await xps.ToLinqToDBTable()
 | 
			
		||||
                    .Where(x => x.GuildId == guildId
 | 
			
		||||
                                && x.Xp + x.AwardedXp
 | 
			
		||||
                                > xps.AsQueryable()
 | 
			
		||||
                                     .Where(y => y.UserId == userId && y.GuildId == guildId)
 | 
			
		||||
                                     .Select(y => y.Xp + y.AwardedXp)
 | 
			
		||||
                                     .FirstOrDefault())
 | 
			
		||||
                    .CountAsyncLinqToDB()
 | 
			
		||||
           + 1;
 | 
			
		||||
 | 
			
		||||
    public static void ResetGuildUserXp(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
 | 
			
		||||
@@ -61,12 +60,11 @@ public static class UserXpExtensions
 | 
			
		||||
 | 
			
		||||
    public static void ResetGuildXp(this DbSet<UserXpStats> xps, ulong guildId)
 | 
			
		||||
        => xps.Delete(x => x.GuildId == guildId);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public static async Task<LevelStats> GetLevelDataFor(this ITable<UserXpStats> userXp, ulong guildId, ulong userId)
 | 
			
		||||
            => await userXp
 | 
			
		||||
                     .Where(x => x.GuildId == guildId && x.UserId == userId)
 | 
			
		||||
                     .FirstOrDefaultAsyncLinqToDB() is UserXpStats uxs
 | 
			
		||||
                ? new(uxs.Xp + uxs.AwardedXp)
 | 
			
		||||
                : new(0);
 | 
			
		||||
    
 | 
			
		||||
        => await userXp
 | 
			
		||||
                 .Where(x => x.GuildId == guildId && x.UserId == userId)
 | 
			
		||||
                 .FirstOrDefaultAsyncLinqToDB() is UserXpStats uxs
 | 
			
		||||
            ? new(uxs.Xp + uxs.AwardedXp)
 | 
			
		||||
            : new(0);
 | 
			
		||||
}
 | 
			
		||||
@@ -3,6 +3,7 @@ namespace NadekoBot.Db.Models;
 | 
			
		||||
 | 
			
		||||
public class GuildConfig : DbEntity
 | 
			
		||||
{
 | 
			
		||||
    // public bool Keep { get; set; }
 | 
			
		||||
    public ulong GuildId { get; set; }
 | 
			
		||||
 | 
			
		||||
    public string Prefix { get; set; }
 | 
			
		||||
 
 | 
			
		||||
@@ -766,7 +766,7 @@ public partial class Gambling : GamblingModule<GamblingService>
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        async Task<IEnumerable<DiscordUser>> GetTopRichest(int curPage)
 | 
			
		||||
        async Task<IReadOnlyCollection<DiscordUser>> GetTopRichest(int curPage)
 | 
			
		||||
        {
 | 
			
		||||
            if (opts.Clean)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -143,6 +143,10 @@ public partial class Searches
 | 
			
		||||
            if (--index < 0)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var canMentionEveryone = (ctx.User as IGuildUser)?.GuildPermissions.MentionEveryone ?? true;
 | 
			
		||||
            if (!canMentionEveryone)
 | 
			
		||||
                message = message?.SanitizeAllMentions();
 | 
			
		||||
 | 
			
		||||
            if (!_service.SetStreamMessage(ctx.Guild.Id, index, message, out var fs))
 | 
			
		||||
            {
 | 
			
		||||
                await Response().Confirm(strs.stream_not_following).SendAsync();
 | 
			
		||||
@@ -160,6 +164,10 @@ public partial class Searches
 | 
			
		||||
        [UserPerm(GuildPerm.ManageMessages)]
 | 
			
		||||
        public async Task StreamMessageAll([Leftover] string message)
 | 
			
		||||
        {
 | 
			
		||||
            var canMentionEveryone = (ctx.User as IGuildUser)?.GuildPermissions.MentionEveryone ?? true;
 | 
			
		||||
            if (!canMentionEveryone)
 | 
			
		||||
                message = message?.SanitizeAllMentions();
 | 
			
		||||
            
 | 
			
		||||
            var count = _service.SetStreamMessageForAll(ctx.Guild.Id, message);
 | 
			
		||||
 | 
			
		||||
            if (count == 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -294,6 +294,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
 | 
			
		||||
                                            var msg = await _sender.Response(textChannel)
 | 
			
		||||
                                                                   .Embed(GetEmbed(fs.GuildId, stream, false))
 | 
			
		||||
                                                                   .Text(message)
 | 
			
		||||
                                                                   .Sanitize(false)
 | 
			
		||||
                                                                   .SendAsync();
 | 
			
		||||
 | 
			
		||||
                                            // only cache the ids of channel/message pairs 
 | 
			
		||||
@@ -615,7 +616,9 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
 | 
			
		||||
    {
 | 
			
		||||
        using var uow = _db.GetDbContext();
 | 
			
		||||
 | 
			
		||||
        var all = uow.Set<FollowedStream>().ToList();
 | 
			
		||||
        var all = uow.Set<FollowedStream>()
 | 
			
		||||
                     .Where(x => x.GuildId == guildId)
 | 
			
		||||
                     .ToList();
 | 
			
		||||
 | 
			
		||||
        if (all.Count == 0)
 | 
			
		||||
            return 0;
 | 
			
		||||
@@ -623,6 +626,19 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
 | 
			
		||||
        all.ForEach(x => x.Message = message);
 | 
			
		||||
 | 
			
		||||
        uow.SaveChanges();
 | 
			
		||||
        
 | 
			
		||||
        lock (_shardLock)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var fs in all)
 | 
			
		||||
            {
 | 
			
		||||
                var streams = GetLocalGuildStreams(fs.CreateKey(), guildId);
 | 
			
		||||
 | 
			
		||||
                // message doesn't participate in equality checking
 | 
			
		||||
                // removing and adding = update
 | 
			
		||||
                streams.Remove(fs);
 | 
			
		||||
                streams.Add(fs);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return all.Count;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
#nullable disable warnings
 | 
			
		||||
using NadekoBot.Modules.Xp.Services;
 | 
			
		||||
using NadekoBot.Db.Models;
 | 
			
		||||
using NadekoBot.Db;
 | 
			
		||||
using NadekoBot.Modules.Patronage;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Xp;
 | 
			
		||||
@@ -191,21 +190,22 @@ public partial class Xp : NadekoModule<XpService>
 | 
			
		||||
            await ctx.Channel.TriggerTypingAsync();
 | 
			
		||||
            await _tracker.EnsureUsersDownloadedAsync(ctx.Guild);
 | 
			
		||||
 | 
			
		||||
            allCleanUsers = _service.GetTopUserXps(ctx.Guild.Id, 1000)
 | 
			
		||||
                                    .Where(user => socketGuild.GetUser(user.UserId) is not null)
 | 
			
		||||
                                    .ToList();
 | 
			
		||||
            allCleanUsers = (await _service.GetTopUserXps(ctx.Guild.Id, 1000))
 | 
			
		||||
                            .Where(user => socketGuild.GetUser(user.UserId) is not null)
 | 
			
		||||
                            .ToList();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await Response()
 | 
			
		||||
        var res = opts.Clean
 | 
			
		||||
            ? Response()
 | 
			
		||||
              .Paginated()
 | 
			
		||||
              .PageItems<UserXpStats>(opts.Clean
 | 
			
		||||
                  ? (curPage) => Task.FromResult<IEnumerable<UserXpStats>>(allCleanUsers.Skip(curPage * 9)
 | 
			
		||||
                      .Take(9)
 | 
			
		||||
                      .ToList())
 | 
			
		||||
                  : (curPage) => Task.FromResult<IEnumerable<UserXpStats>>(_service.GetUserXps(ctx.Guild.Id, curPage)))
 | 
			
		||||
              .Items(allCleanUsers)
 | 
			
		||||
            : Response()
 | 
			
		||||
              .Paginated()
 | 
			
		||||
              .PageItems((curPage) => _service.GetUserXps(ctx.Guild.Id, curPage));
 | 
			
		||||
 | 
			
		||||
        await res
 | 
			
		||||
              .PageSize(9)
 | 
			
		||||
              .CurrentPage(page)
 | 
			
		||||
              .AddFooter(false)
 | 
			
		||||
              .Page((users, curPage) =>
 | 
			
		||||
              {
 | 
			
		||||
                  var embed = _sender.CreateEmbed().WithTitle(GetText(strs.server_leaderboard)).WithOkColor();
 | 
			
		||||
@@ -241,23 +241,33 @@ public partial class Xp : NadekoModule<XpService>
 | 
			
		||||
    {
 | 
			
		||||
        if (--page < 0 || page > 99)
 | 
			
		||||
            return;
 | 
			
		||||
        var users = _service.GetUserXps(page);
 | 
			
		||||
 | 
			
		||||
        var embed = _sender.CreateEmbed().WithTitle(GetText(strs.global_leaderboard)).WithOkColor();
 | 
			
		||||
        await Response()
 | 
			
		||||
              .Paginated()
 | 
			
		||||
              .PageItems(async curPage => await _service.GetUserXps(curPage))
 | 
			
		||||
              .PageSize(9)
 | 
			
		||||
              .Page((users, curPage) =>
 | 
			
		||||
              {
 | 
			
		||||
                  var embed = _sender.CreateEmbed()
 | 
			
		||||
                                     .WithOkColor()
 | 
			
		||||
                                     .WithTitle(GetText(strs.global_leaderboard));
 | 
			
		||||
 | 
			
		||||
        if (!users.Any())
 | 
			
		||||
            embed.WithDescription("-");
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            for (var i = 0; i < users.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var user = users[i];
 | 
			
		||||
                embed.AddField($"#{i + 1 + (page * 9)} {user.ToString()}",
 | 
			
		||||
                    $"{GetText(strs.level_x(new LevelStats(users[i].TotalXp).Level))} - {users[i].TotalXp}xp");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
                  if (!users.Any())
 | 
			
		||||
                  {
 | 
			
		||||
                      embed.WithDescription("-");
 | 
			
		||||
                      return embed;
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
        await Response().Embed(embed).SendAsync();
 | 
			
		||||
                  for (var i = 0; i < users.Count; i++)
 | 
			
		||||
                  {
 | 
			
		||||
                      var user = users[i];
 | 
			
		||||
                      embed.AddField($"#{i + 1 + (curPage * 9)} {user}",
 | 
			
		||||
                          $"{GetText(strs.level_x(new LevelStats(users[i].TotalXp).Level))} - {users[i].TotalXp}xp");
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  return embed;
 | 
			
		||||
              })
 | 
			
		||||
              .SendAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Cmd]
 | 
			
		||||
 
 | 
			
		||||
@@ -563,22 +563,23 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
 | 
			
		||||
        uow.SaveChanges();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<UserXpStats> GetUserXps(ulong guildId, int page)
 | 
			
		||||
    public async Task<IReadOnlyCollection<UserXpStats>> GetUserXps(ulong guildId, int page)
 | 
			
		||||
    {
 | 
			
		||||
        using var uow = _db.GetDbContext();
 | 
			
		||||
        return uow.Set<UserXpStats>().GetUsersFor(guildId, page);
 | 
			
		||||
        await using var uow = _db.GetDbContext();
 | 
			
		||||
        return await uow.Set<UserXpStats>().GetUsersFor(guildId, page);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<UserXpStats> GetTopUserXps(ulong guildId, int count)
 | 
			
		||||
    public async Task<IReadOnlyCollection<UserXpStats>> GetTopUserXps(ulong guildId, int count)
 | 
			
		||||
    {
 | 
			
		||||
        using var uow = _db.GetDbContext();
 | 
			
		||||
        return uow.Set<UserXpStats>().GetTopUserXps(guildId, count);
 | 
			
		||||
        await using var uow = _db.GetDbContext();
 | 
			
		||||
        return await uow.Set<UserXpStats>().GetTopUserXps(guildId, count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public DiscordUser[] GetUserXps(int page, int perPage = 9)
 | 
			
		||||
    public Task<IReadOnlyCollection<DiscordUser>> GetUserXps(int page, int perPage = 9)
 | 
			
		||||
    {
 | 
			
		||||
        using var uow = _db.GetDbContext();
 | 
			
		||||
        return uow.Set<DiscordUser>().GetUsersXpLeaderboardFor(page, perPage);
 | 
			
		||||
        return uow.Set<DiscordUser>()
 | 
			
		||||
                  .GetUsersXpLeaderboardFor(page, perPage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task ChangeNotificationType(ulong userId, ulong guildId, XpNotificationLocation type)
 | 
			
		||||
@@ -884,7 +885,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
 | 
			
		||||
        var du = uow.GetOrCreateUser(user, set => set.Include(x => x.Club));
 | 
			
		||||
        var totalXp = du.TotalXp;
 | 
			
		||||
        var globalRank = uow.Set<DiscordUser>().GetUserGlobalRank(user.Id);
 | 
			
		||||
        var guildRank = uow.Set<UserXpStats>().GetUserGuildRanking(user.Id, user.GuildId);
 | 
			
		||||
        var guildRank = await uow.Set<UserXpStats>().GetUserGuildRanking(user.Id, user.GuildId);
 | 
			
		||||
        var stats = uow.GetOrCreateUserXpStats(user.GuildId, user.Id);
 | 
			
		||||
        await uow.SaveChangesAsync();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
        <Nullable>enable</Nullable>
 | 
			
		||||
        <ImplicitUsings>true</ImplicitUsings>
 | 
			
		||||
        <SatelliteResourceLanguages>en</SatelliteResourceLanguages>
 | 
			
		||||
        <Version>5.0.6</Version>
 | 
			
		||||
        <Version>5.0.7</Version>
 | 
			
		||||
 | 
			
		||||
        <!-- Output/build -->
 | 
			
		||||
        <RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ public partial class ResponseBuilder
 | 
			
		||||
                cb.WithButton(new ButtonBuilder()
 | 
			
		||||
                              .WithStyle(ButtonStyle.Primary)
 | 
			
		||||
                              .WithCustomId(BUTTON_RIGHT)
 | 
			
		||||
                              .WithDisabled(lastPage == 0 || currentPage >= lastPage)
 | 
			
		||||
                              .WithDisabled(lastPage is not null && (lastPage == 0 || currentPage >= lastPage))
 | 
			
		||||
                              .WithEmote(InteractionHelpers.ArrowRight));
 | 
			
		||||
 | 
			
		||||
                return cb;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using NadekoBot.Common.Configs;
 | 
			
		||||
using NadekoBot.Db.Models;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Extensions;
 | 
			
		||||
 | 
			
		||||
@@ -357,10 +358,9 @@ public sealed partial class ResponseBuilder
 | 
			
		||||
        fileName = name;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public PaginatedResponseBuilder Paginated()
 | 
			
		||||
        => new(this);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public class PaginatedResponseBuilder
 | 
			
		||||
@@ -376,7 +376,7 @@ public class PaginatedResponseBuilder
 | 
			
		||||
        => new SourcedPaginatedResponseBuilder<T>(_builder)
 | 
			
		||||
            .Items(items);
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> PageItems<T>(Func<int, Task<IEnumerable<T>>> items)
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> PageItems<T>(Func<int, Task<IReadOnlyCollection<T>>> items)
 | 
			
		||||
        => new SourcedPaginatedResponseBuilder<T>(_builder)
 | 
			
		||||
            .PageItems(items);
 | 
			
		||||
}
 | 
			
		||||
@@ -390,14 +390,14 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
 | 
			
		||||
        return Task.FromResult<EmbedBuilder>(new());
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public Func<int, Task<IEnumerable<T>>> ItemsFunc { get; set; } = static delegate
 | 
			
		||||
    public Func<int, Task<IReadOnlyCollection<T>>> ItemsFunc { get; set; } = static delegate
 | 
			
		||||
    {
 | 
			
		||||
        return Task.FromResult(Enumerable.Empty<T>());
 | 
			
		||||
        return Task.FromResult<IReadOnlyCollection<T>>(ReadOnlyCollection<T>.Empty);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public Func<int, Task<SimpleInteractionBase>>? InteractionFunc { get; private set; }
 | 
			
		||||
 | 
			
		||||
    public int Elems { get; private set; } = 1;
 | 
			
		||||
    public int? Elems { get; private set; } = 1;
 | 
			
		||||
    public int ItemsPerPage { get; private set; } = 9;
 | 
			
		||||
    public bool AddPaginatedFooter { get; private set; } = true;
 | 
			
		||||
    public bool IsEphemeral { get; private set; }
 | 
			
		||||
@@ -413,18 +413,19 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
 | 
			
		||||
    {
 | 
			
		||||
        items = col;
 | 
			
		||||
        Elems = col.Count;
 | 
			
		||||
        ItemsFunc = (i) => Task.FromResult(items.Skip(i * ItemsPerPage).Take(ItemsPerPage));
 | 
			
		||||
        ItemsFunc = (i) => Task.FromResult(items.Skip(i * ItemsPerPage).Take(ItemsPerPage).ToArray() as IReadOnlyCollection<T>);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> TotalElements(int i)
 | 
			
		||||
    {
 | 
			
		||||
        Elems = i;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> PageItems(Func<int, Task<IEnumerable<T>>> func)
 | 
			
		||||
    public SourcedPaginatedResponseBuilder<T> PageItems(Func<int, Task<IReadOnlyCollection<T>>> func)
 | 
			
		||||
    {
 | 
			
		||||
        Elems = null;
 | 
			
		||||
        ItemsFunc = func;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -167,7 +167,8 @@ public static class Extensions
 | 
			
		||||
    {
 | 
			
		||||
        if (lastPage is not null)
 | 
			
		||||
            return embed.WithFooter($"{curPage + 1} / {lastPage + 1}");
 | 
			
		||||
        return embed.WithFooter(curPage.ToString());
 | 
			
		||||
        
 | 
			
		||||
        return embed.WithFooter((curPage + 1).ToString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // public static EmbedBuilder WithOkColor(this EmbedBuilder eb)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user