Applied codestyle to all .cs files

This commit is contained in:
Kwoth
2021-12-29 06:07:16 +01:00
parent 723447c7d4
commit 82000c97a4
543 changed files with 13221 additions and 14059 deletions

View File

@@ -13,20 +13,21 @@ public partial class Xp
public Club(XpService xps)
=> _xps = xps;
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubTransfer([Leftover] IUser newOwner)
{
var club = _service.TransferClub(ctx.User, newOwner);
if (club != null)
await ReplyConfirmLocalizedAsync(strs.club_transfered(
Format.Bold(club.Name),
await ReplyConfirmLocalizedAsync(strs.club_transfered(Format.Bold(club.Name),
Format.Bold(newOwner.ToString())));
else
await ReplyErrorLocalizedAsync(strs.club_transfer_failed);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubAdmin([Leftover] IUser toAdmin)
{
bool admin;
@@ -46,7 +47,8 @@ public partial class Xp
await ReplyConfirmLocalizedAsync(strs.club_admin_remove(Format.Bold(toAdmin.ToString())));
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubCreate([Leftover] string clubName)
{
if (string.IsNullOrWhiteSpace(clubName) || clubName.Length > 20)
@@ -64,7 +66,8 @@ public partial class Xp
await ReplyConfirmLocalizedAsync(strs.club_created(Format.Bold(club.ToString())));
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubIcon([Leftover] string url = null)
{
if ((!Uri.IsWellFormedUriString(url, UriKind.Absolute) && url != null)
@@ -77,7 +80,8 @@ public partial class Xp
await ReplyConfirmLocalizedAsync(strs.club_icon_set);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(1)]
public async Task ClubInformation(IUser user = null)
{
@@ -92,7 +96,8 @@ public partial class Xp
await ClubInformation(club.ToString());
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(0)]
public async Task ClubInformation([Leftover] string clubName = null)
{
@@ -109,50 +114,53 @@ public partial class Xp
}
var lvl = new LevelStats(club.Xp);
var users = club.Users
.OrderByDescending(x =>
{
var l = new LevelStats(x.TotalXp).Level;
if (club.OwnerId == x.Id)
return int.MaxValue;
else if (x.IsClubAdmin)
return (int.MaxValue / 2) + l;
else
return l;
});
await ctx.SendPaginatedConfirmAsync(0, page =>
var users = club.Users.OrderByDescending(x =>
{
var embed = _eb.Create()
.WithOkColor()
.WithTitle($"{club.ToString()}")
.WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)")))
.AddField(GetText(strs.desc), string.IsNullOrWhiteSpace(club.Description) ? "-" : club.Description,
false)
.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.ToString() + "🌟" + lvlStr;
else if (x.IsClubAdmin)
return x.ToString() + "⭐" + lvlStr;
return x.ToString() + lvlStr;
})), false);
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;
});
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
return embed.WithThumbnailUrl(club.ImageUrl);
await ctx.SendPaginatedConfirmAsync(0,
page =>
{
var embed = _eb.Create()
.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;
})));
return embed;
}, club.Users.Count, 10);
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
return embed.WithThumbnailUrl(club.ImageUrl);
return embed;
},
club.Users.Count,
10);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public Task ClubBans(int page = 1)
{
if (--page < 0)
@@ -162,28 +170,25 @@ public partial class Xp
if (club is null)
return ReplyErrorLocalizedAsync(strs.club_not_exists_owner);
var bans = club
.Bans
.Select(x => x.User)
.ToArray();
var bans = club.Bans.Select(x => x.User).ToArray();
return ctx.SendPaginatedConfirmAsync(page,
curPage =>
{
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 _eb.Create()
.WithTitle(GetText(strs.club_bans_for(club.ToString())))
.WithDescription(toShow)
.WithOkColor();
}, bans.Length, 10);
.WithTitle(GetText(strs.club_bans_for(club.ToString())))
.WithDescription(toShow)
.WithOkColor();
},
bans.Length,
10);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public Task ClubApps(int page = 1)
{
if (--page < 0)
@@ -193,27 +198,24 @@ public partial class Xp
if (club is null)
return ReplyErrorLocalizedAsync(strs.club_not_exists_owner);
var apps = club
.Applicants
.Select(x => x.User)
.ToArray();
var apps = club.Applicants.Select(x => x.User).ToArray();
return ctx.SendPaginatedConfirmAsync(page,
curPage =>
{
var toShow = string.Join("\n", apps
.Skip(page * 10)
.Take(10)
.Select(x => x.ToString()));
var toShow = string.Join("\n", apps.Skip(page * 10).Take(10).Select(x => x.ToString()));
return _eb.Create()
.WithTitle(GetText(strs.club_apps_for(club.ToString())))
.WithDescription(toShow)
.WithOkColor();
}, apps.Length, 10);
.WithTitle(GetText(strs.club_apps_for(club.ToString())))
.WithDescription(toShow)
.WithOkColor();
},
apps.Length,
10);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubApply([Leftover] string clubName)
{
if (string.IsNullOrWhiteSpace(clubName))
@@ -226,33 +228,30 @@ public partial class Xp
}
if (_service.ApplyToClub(ctx.User, club))
{
await ReplyConfirmLocalizedAsync(strs.club_applied(Format.Bold(club.ToString())));
}
else
{
await ReplyErrorLocalizedAsync(strs.club_apply_error);
}
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(1)]
public Task ClubAccept(IUser user)
=> ClubAccept(user.ToString());
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(0)]
public async Task ClubAccept([Leftover] string userName)
{
if (_service.AcceptApplication(ctx.User.Id, userName, out var discordUser))
{
await ReplyConfirmLocalizedAsync(strs.club_accepted(Format.Bold(discordUser.ToString())));
}
else
await ReplyErrorLocalizedAsync(strs.club_accept_error);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task Clubleave()
{
if (_service.LeaveClub(ctx.User))
@@ -261,94 +260,89 @@ public partial class Xp
await ReplyErrorLocalizedAsync(strs.club_not_in_club);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(1)]
public Task ClubKick([Leftover] IUser user)
=> ClubKick(user.ToString());
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(0)]
public Task ClubKick([Leftover] string userName)
{
if (_service.Kick(ctx.User.Id, userName, out var club))
return ReplyConfirmLocalizedAsync(strs.club_user_kick(Format.Bold(userName),
Format.Bold(club.ToString())));
else
return ReplyErrorLocalizedAsync(strs.club_user_kick_fail);
return ReplyErrorLocalizedAsync(strs.club_user_kick_fail);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(1)]
public Task ClubBan([Leftover] IUser user)
=> ClubBan(user.ToString());
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(0)]
public Task ClubBan([Leftover] string userName)
{
if (_service.Ban(ctx.User.Id, userName, out var club))
return ReplyConfirmLocalizedAsync(strs.club_user_banned(Format.Bold(userName),
Format.Bold(club.ToString())));
else
return ReplyErrorLocalizedAsync(strs.club_user_ban_fail);
return ReplyErrorLocalizedAsync(strs.club_user_ban_fail);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(1)]
public Task ClubUnBan([Leftover] IUser user)
=> ClubUnBan(user.ToString());
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[Priority(0)]
public Task ClubUnBan([Leftover] string userName)
{
if (_service.UnBan(ctx.User.Id, userName, out var club))
return ReplyConfirmLocalizedAsync(strs.club_user_unbanned(Format.Bold(userName),
Format.Bold(club.ToString())));
else
return ReplyErrorLocalizedAsync(strs.club_user_unban_fail);
return ReplyErrorLocalizedAsync(strs.club_user_unban_fail);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubLevelReq(int level)
{
if (_service.ChangeClubLevelReq(ctx.User.Id, level))
{
await ReplyConfirmLocalizedAsync(strs.club_level_req_changed(Format.Bold(level.ToString())));
}
else
{
await ReplyErrorLocalizedAsync(strs.club_level_req_change_error);
}
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubDescription([Leftover] string desc = null)
{
if (_service.ChangeClubDescription(ctx.User.Id, desc))
{
await ReplyConfirmLocalizedAsync(strs.club_desc_updated(Format.Bold(desc ?? "-")));
}
else
{
await ReplyErrorLocalizedAsync(strs.club_desc_update_failed);
}
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public async Task ClubDisband()
{
if (_service.Disband(ctx.User.Id, out var club))
{
await ReplyConfirmLocalizedAsync(strs.club_disbanded(Format.Bold(club.ToString())));
}
else
{
await ReplyErrorLocalizedAsync(strs.club_disband_error);
}
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
public Task ClubLeaderboard(int page = 1)
{
if (--page < 0)
@@ -356,17 +350,12 @@ public partial class Xp
var clubs = _service.GetClubLeaderboardPage(page);
var embed = _eb.Create()
.WithTitle(GetText(strs.club_leaderboard(page + 1)))
.WithOkColor();
var embed = _eb.Create().WithTitle(GetText(strs.club_leaderboard(page + 1))).WithOkColor();
var i = page * 9;
foreach (var club in clubs)
{
embed.AddField($"#{++i} " + club.ToString(), club.Xp.ToString() + " xp", false);
}
foreach (var club in clubs) embed.AddField($"#{++i} " + club, club.Xp + " xp");
return ctx.Channel.EmbedAsync(embed);
}
}
}
}

View File

@@ -1,6 +1,6 @@
#nullable disable
using NadekoBot.Services.Database.Models;
using NadekoBot.Db.Models;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Xp;
@@ -13,8 +13,13 @@ public class FullUserStats
public int GlobalRanking { get; }
public int GuildRanking { get; }
public FullUserStats(DiscordUser usr, UserXpStats fullGuildStats, LevelStats global,
LevelStats guild, int globalRanking, int guildRanking)
public FullUserStats(
DiscordUser usr,
UserXpStats fullGuildStats,
LevelStats global,
LevelStats guild,
int globalRanking,
int guildRanking)
{
User = usr;
Global = global;
@@ -23,4 +28,4 @@ public class FullUserStats
GuildRanking = guildRanking;
FullGuildStats = fullGuildStats;
}
}
}

View File

@@ -37,4 +37,4 @@ public class LevelStats
LevelXp = xp - totalXp;
RequiredXp = required;
}
}
}

View File

@@ -7,7 +7,7 @@ namespace NadekoBot.Modules.Xp;
[Cloneable]
public sealed partial class XpConfig : ICloneable<XpConfig>
{
[Comment(@"DO NOT CHANGE")]
[Comment(@"DO NOT CHANGE")]
public int Version { get; set; } = 2;
[Comment(@"How much XP will the users receive per message")]
@@ -24,4 +24,4 @@ public sealed partial class XpConfig : ICloneable<XpConfig>
[Comment(@"The maximum amount of minutes the bot will keep track of a user in a voice channel")]
public int VoiceMaxMinutes { get; set; } = 720;
}
}

View File

@@ -1,107 +1,30 @@
#nullable disable
using Newtonsoft.Json;
using SixLabors.ImageSharp.PixelFormats;
using Color = SixLabors.ImageSharp.Color;
namespace NadekoBot.Modules.Xp;
public class XpTemplate
{
[JsonProperty("output_size")]
public XpTemplatePos OutputSize { get; set; } = new()
{
X = 450,
Y = 220,
};
public XpTemplatePos OutputSize { get; set; } = new() { X = 450, Y = 220 };
public XpTemplateUser User { get; set; } = new()
{
Name = new()
{
FontSize = 50,
Show = true,
Pos = new()
Name = new() { FontSize = 50, Show = true, Pos = new() { X = 130, Y = 17 } },
Icon = new() { Show = true, Pos = new() { X = 32, Y = 10 }, Size = new() { X = 69, Y = 70 } },
GuildLevel = new() { Show = true, FontSize = 45, Pos = new() { X = 47, Y = 297 } },
GlobalLevel = new() { Show = true, FontSize = 45, Pos = new() { X = 47, Y = 149 } },
GuildRank = new() { Show = true, FontSize = 30, Pos = new() { X = 148, Y = 326 } },
GlobalRank = new() { Show = true, FontSize = 30, Pos = new() { X = 148, Y = 179 } },
TimeOnLevel =
new()
{
X = 130,
Y = 17,
}
},
Icon = new()
{
Show = true,
Pos = new()
{
X = 32,
Y = 10,
Format = "{0}d{1}h{2}m",
Global = new() { FontSize = 20, Show = true, Pos = new() { X = 50, Y = 204 } },
Guild = new() { FontSize = 20, Show = true, Pos = new() { X = 50, Y = 351 } }
},
Size = new()
{
X = 69,
Y = 70,
}
},
GuildLevel = new()
{
Show = true,
FontSize = 45,
Pos = new()
{
X = 47,
Y = 297,
}
},
GlobalLevel = new()
{
Show = true,
FontSize = 45,
Pos = new()
{
X = 47,
Y = 149,
}
},
GuildRank = new()
{
Show = true,
FontSize = 30,
Pos = new()
{
X = 148,
Y = 326,
}
},
GlobalRank = new()
{
Show = true,
FontSize = 30,
Pos = new()
{
X = 148,
Y = 179,
}
},
TimeOnLevel = new()
{
Format = "{0}d{1}h{2}m",
Global = new()
{
FontSize = 20,
Show = true,
Pos = new()
{
X = 50,
Y = 204
}
},
Guild = new()
{
FontSize = 20,
Show = true,
Pos = new()
{
X = 50,
Y = 351
}
}
},
Xp = new()
{
Bar = new()
@@ -112,92 +35,28 @@ public class XpTemplate
Direction = XpTemplateDirection.Right,
Length = 450,
Color = new(0, 0, 0, 0.4f),
PointA = new()
{
X = 321,
Y = 104
},
PointB = new()
{
X = 286,
Y = 235
}
PointA = new() { X = 321, Y = 104 },
PointB = new() { X = 286, Y = 235 }
},
Guild = new()
{
Direction = XpTemplateDirection.Right,
Length = 450,
Color = new(0, 0, 0, 0.4f),
PointA = new()
{
X = 282,
Y = 248
},
PointB = new()
{
X = 247,
Y = 379
}
PointA = new() { X = 282, Y = 248 },
PointB = new() { X = 247, Y = 379 }
}
},
Global = new()
{
Show = true,
FontSize = 50,
Pos = new()
{
X = 430,
Y = 142
}
},
Guild = new()
{
Show = true,
FontSize = 50,
Pos = new()
{
X = 400,
Y = 282
}
},
Awarded = new()
{
Show = true,
FontSize = 25,
Pos = new()
{
X = 445,
Y = 347
}
}
Global = new() { Show = true, FontSize = 50, Pos = new() { X = 430, Y = 142 } },
Guild = new() { Show = true, FontSize = 50, Pos = new() { X = 400, Y = 282 } },
Awarded = new() { Show = true, FontSize = 25, Pos = new() { X = 445, Y = 347 } }
}
};
public XpTemplateClub Club { get; set; } = new()
{
Icon = new()
{
Show = true,
Pos = new()
{
X = 722,
Y = 25,
},
Size = new()
{
X = 45,
Y = 45,
}
},
Name = new()
{
FontSize = 35,
Pos = new()
{
X = 650,
Y = 49
},
Show = true,
}
Icon = new() { Show = true, Pos = new() { X = 722, Y = 25 }, Size = new() { X = 45, Y = 45 } },
Name = new() { FontSize = 35, Pos = new() { X = 650, Y = 49 }, Show = true }
};
}
@@ -243,6 +102,7 @@ public class XpTemplateText
{
[JsonConverter(typeof(XpRgba32Converter))]
public Rgba32 Color { get; set; } = SixLabors.ImageSharp.Color.White;
public bool Show { get; set; }
public int FontSize { get; set; }
public XpTemplatePos Pos { get; set; }
@@ -267,6 +127,7 @@ public class XpBar
{
[JsonConverter(typeof(XpRgba32Converter))]
public Rgba32 Color { get; set; }
public XpTemplatePos PointA { get; set; }
public XpTemplatePos PointB { get; set; }
public int Length { get; set; }
@@ -283,9 +144,14 @@ public enum XpTemplateDirection
public class XpRgba32Converter : JsonConverter<Rgba32>
{
public override Rgba32 ReadJson(JsonReader reader, Type objectType, Rgba32 existingValue, bool hasExistingValue, JsonSerializer serializer)
=> SixLabors.ImageSharp.Color.ParseHex(reader.Value?.ToString());
public override Rgba32 ReadJson(
JsonReader reader,
Type objectType,
Rgba32 existingValue,
bool hasExistingValue,
JsonSerializer serializer)
=> Color.ParseHex(reader.Value?.ToString());
public override void WriteJson(JsonWriter writer, Rgba32 value, JsonSerializer serializer)
=> writer.WriteValue(value.ToHex().ToLowerInvariant());
}
}

View File

@@ -9,7 +9,7 @@ public static class Extensions
public static (int Level, int LevelXp, int LevelRequiredXp) GetLevelData(this UserXpStats stats)
{
var baseXp = XpService.XP_REQUIRED_LVL_1;
var required = baseXp;
var totalXp = 0;
var lvl = 1;
@@ -26,4 +26,4 @@ public static class Extensions
return (lvl - 1, stats.Xp - totalXp, required);
}
}
}

View File

@@ -7,21 +7,20 @@ public partial class Xp
{
public class ResetCommands : NadekoSubmodule<XpService>
{
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public Task XpReset(IGuildUser user)
=> XpReset(user.Id);
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public async Task XpReset(ulong userId)
{
var embed = _eb.Create()
.WithTitle(GetText(strs.reset))
.WithDescription(GetText(strs.reset_user_confirm));
var embed = _eb.Create().WithTitle(GetText(strs.reset)).WithDescription(GetText(strs.reset_user_confirm));
if (!await PromptUserConfirmAsync(embed))
return;
@@ -31,14 +30,13 @@ public partial class Xp
await ReplyConfirmLocalizedAsync(strs.reset_user(userId));
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public async Task XpReset()
{
var embed = _eb.Create()
.WithTitle(GetText(strs.reset))
.WithDescription(GetText(strs.reset_server_confirm));
var embed = _eb.Create().WithTitle(GetText(strs.reset)).WithDescription(GetText(strs.reset_server_confirm));
if (!await PromptUserConfirmAsync(embed))
return;
@@ -48,4 +46,4 @@ public partial class Xp
await ReplyConfirmLocalizedAsync(strs.reset_server);
}
}
}
}

View File

@@ -1,6 +1,6 @@
#nullable disable
using NadekoBot.Db.Models;
using NadekoBot.Db;
using NadekoBot.Db.Models;
namespace NadekoBot.Modules.Xp.Services;
@@ -28,22 +28,16 @@ public class ClubService : INService
if (xp.Level >= 5 && du.Club is null)
{
du.IsClubAdmin = true;
du.Club = new()
{
Name = clubName,
Discrim = uow.Clubs.GetNextDiscrim(clubName),
Owner = du,
};
du.Club = new() { Name = clubName, Discrim = uow.Clubs.GetNextDiscrim(clubName), Owner = du };
uow.Clubs.Add(du.Club);
uow.SaveChanges();
}
else
{
return false;
}
uow.Set<ClubApplicants>()
.RemoveRange(uow.Set<ClubApplicants>()
.AsQueryable()
.Where(x => x.UserId == du.Id));
uow.Set<ClubApplicants>().RemoveRange(uow.Set<ClubApplicants>().AsQueryable().Where(x => x.UserId == du.Id));
club = du.Club;
uow.SaveChanges();
@@ -54,12 +48,10 @@ public class ClubService : INService
{
ClubInfo club;
using var uow = _db.GetDbContext();
club = uow.Clubs.GetByOwner(@from.Id);
club = uow.Clubs.GetByOwner(from.Id);
var newOwnerUser = uow.GetOrCreateUser(newOwner);
if (club is null ||
club.Owner.UserId != @from.Id ||
!club.Users.Contains(newOwnerUser))
if (club is null || club.Owner.UserId != from.Id || !club.Users.Contains(newOwnerUser))
return null;
club.Owner.IsClubAdmin = true; // old owner will stay as admin
@@ -76,8 +68,7 @@ public class ClubService : INService
var club = uow.Clubs.GetByOwner(owner.Id);
var adminUser = uow.GetOrCreateUser(toAdmin);
if (club is null || club.Owner.UserId != owner.Id ||
!club.Users.Contains(adminUser))
if (club is null || club.Owner.UserId != owner.Id || !club.Users.Contains(adminUser))
throw new InvalidOperationException();
if (club.OwnerId == adminUser.Id)
@@ -134,8 +125,7 @@ public class ClubService : INService
club = uow.Clubs.GetByName(name, discrim);
if (club is null)
return false;
else
return true;
return true;
}
public bool ApplyToClub(IUser user, ClubInfo club)
@@ -148,17 +138,11 @@ public class ClubService : INService
|| new LevelStats(du.TotalXp).Level < club.MinimumLevelReq
|| club.Bans.Any(x => x.UserId == du.Id)
|| club.Applicants.Any(x => x.UserId == du.Id))
{
//user banned or a member of a club, or already applied,
// or doesn't min minumum level requirement, can't apply
return false;
}
var app = new ClubApplicants
{
ClubId = club.Id,
UserId = du.Id,
};
var app = new ClubApplicants { ClubId = club.Id, UserId = du.Id };
uow.Set<ClubApplicants>().Add(app);
@@ -174,7 +158,8 @@ public class ClubService : INService
if (club is null)
return false;
var applicant = club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
var applicant =
club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
if (applicant is null)
return false;
@@ -184,9 +169,7 @@ public class ClubService : INService
//remove that user's all other applications
uow.Set<ClubApplicants>()
.RemoveRange(uow.Set<ClubApplicants>()
.AsQueryable()
.Where(x => x.UserId == applicant.User.Id));
.RemoveRange(uow.Set<ClubApplicants>().AsQueryable().Where(x => x.UserId == applicant.User.Id));
discordUser = applicant.User;
uow.SaveChanges();
@@ -261,18 +244,17 @@ public class ClubService : INService
return false;
var usr = club.Users.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant())
?? club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant())?.User;
?? club.Applicants
.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant())
?.User;
if (usr is null)
return false;
if (club.OwnerId == usr.Id || (usr.IsClubAdmin && club.Owner.UserId != bannerId)) // can't ban the owner kek, whew
if (club.OwnerId == usr.Id
|| (usr.IsClubAdmin && club.Owner.UserId != bannerId)) // can't ban the owner kek, whew
return false;
club.Bans.Add(new()
{
Club = club,
User = usr,
});
club.Bans.Add(new() { Club = club, User = usr });
club.Users.Remove(usr);
var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id);
@@ -332,4 +314,4 @@ public class ClubService : INService
using var uow = _db.GetDbContext();
return uow.Clubs.GetClubLeaderboardPage(page);
}
}
}

View File

@@ -13,4 +13,4 @@ public class UserCacheItem
public override bool Equals(object obj)
=> obj is UserCacheItem uci && uci.User == User;
}
}

View File

@@ -5,24 +5,31 @@ namespace NadekoBot.Modules.Xp.Services;
public sealed class XpConfigService : ConfigServiceBase<XpConfig>
{
public override string Name { get; } = "xp";
private const string FilePath = "data/xp.yml";
private static readonly TypedKey<XpConfig> changeKey = new("config.xp.updated");
public override string Name { get; } = "xp";
public XpConfigService(IConfigSeria serializer, IPubSub pubSub)
public XpConfigService(IConfigSeria serializer, IPubSub pubSub)
: base(FilePath, serializer, pubSub, changeKey)
{
AddParsedProp("txt.cooldown", conf => conf.MessageXpCooldown, int.TryParse,
ConfigPrinters.ToString, x => x > 0);
AddParsedProp("txt.per_msg", conf => conf.XpPerMessage, int.TryParse,
ConfigPrinters.ToString, x => x >= 0);
AddParsedProp("txt.per_image", conf => conf.XpFromImage, int.TryParse,
ConfigPrinters.ToString, x => x > 0);
AddParsedProp("voice.per_minute", conf => conf.VoiceXpPerMinute, double.TryParse,
ConfigPrinters.ToString, x => x >= 0);
AddParsedProp("voice.max_minutes", conf => conf.VoiceMaxMinutes, int.TryParse,
ConfigPrinters.ToString, x => x > 0);
AddParsedProp("txt.cooldown",
conf => conf.MessageXpCooldown,
int.TryParse,
ConfigPrinters.ToString,
x => x > 0);
AddParsedProp("txt.per_msg", conf => conf.XpPerMessage, int.TryParse, ConfigPrinters.ToString, x => x >= 0);
AddParsedProp("txt.per_image", conf => conf.XpFromImage, int.TryParse, ConfigPrinters.ToString, x => x > 0);
AddParsedProp("voice.per_minute",
conf => conf.VoiceXpPerMinute,
double.TryParse,
ConfigPrinters.ToString,
x => x >= 0);
AddParsedProp("voice.max_minutes",
conf => conf.VoiceMaxMinutes,
int.TryParse,
ConfigPrinters.ToString,
x => x > 0);
Migrate();
}
@@ -30,12 +37,10 @@ public sealed class XpConfigService : ConfigServiceBase<XpConfig>
private void Migrate()
{
if (data.Version < 2)
{
ModifyConfig(c =>
{
c.Version = 2;
c.XpFromImage = 0;
});
}
}
}
}

View File

@@ -1,5 +1,8 @@
#nullable disable
using Microsoft.EntityFrameworkCore;
using NadekoBot.Db;
using NadekoBot.Db.Models;
using NadekoBot.Services.Database.Models;
using Newtonsoft.Json;
using SixLabors.Fonts;
using SixLabors.ImageSharp;
@@ -7,10 +10,8 @@ using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Services.Database.Models;
using NadekoBot.Db;
using StackExchange.Redis;
using Color = SixLabors.ImageSharp.Color;
using Image = SixLabors.ImageSharp.Image;
namespace NadekoBot.Modules.Xp.Services;
@@ -18,11 +19,7 @@ namespace NadekoBot.Modules.Xp.Services;
// todo improve xp with linqtodb
public class XpService : INService
{
private enum NotifOf
{
Server,
Global
} // is it a server level-up or global level-up notification
public const int XP_REQUIRED_LVL_1 = 36;
private readonly DbService _db;
private readonly CommandHandler _cmd;
@@ -38,8 +35,6 @@ public class XpService : INService
private readonly IPubSub _pubSub;
private readonly IEmbedBuilderService _eb;
public const int XP_REQUIRED_LVL_1 = 36;
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedRoles;
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedChannels;
@@ -87,54 +82,41 @@ public class XpService : INService
InternalReloadXpTemplate();
if (client.ShardId == 0)
{
_pubSub.Sub(_xpTemplateReloadKey, _ =>
{
InternalReloadXpTemplate();
return default;
});
}
_pubSub.Sub(_xpTemplateReloadKey,
_ =>
{
InternalReloadXpTemplate();
return default;
});
//load settings
var allGuildConfigs = bot.AllGuildConfigs
.Where(x => x.XpSettings != null)
.ToList();
_excludedChannels = allGuildConfigs
.ToDictionary(
x => x.GuildId,
x => new ConcurrentHashSet<ulong>(x.XpSettings
.ExclusionList
.Where(ex => ex.ItemType == ExcludedItemType.Channel)
.Select(ex => ex.ItemId)
.Distinct()))
.ToConcurrent();
var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null).ToList();
_excludedRoles = allGuildConfigs
.ToDictionary(
x => x.GuildId,
x => new ConcurrentHashSet<ulong>(x.XpSettings
.ExclusionList
.Where(ex => ex.ItemType == ExcludedItemType.Role)
.Select(ex => ex.ItemId)
.Distinct()))
.ToConcurrent();
_excludedChannels = allGuildConfigs.ToDictionary(x => x.GuildId,
x => new ConcurrentHashSet<ulong>(x.XpSettings.ExclusionList
.Where(ex => ex.ItemType == ExcludedItemType.Channel)
.Select(ex => ex.ItemId)
.Distinct()))
.ToConcurrent();
_excludedServers = new(
allGuildConfigs.Where(x => x.XpSettings.ServerExcluded)
.Select(x => x.GuildId));
_excludedRoles = allGuildConfigs.ToDictionary(x => x.GuildId,
x => new ConcurrentHashSet<ulong>(x.XpSettings.ExclusionList
.Where(ex => ex.ItemType
== ExcludedItemType.Role)
.Select(ex => ex.ItemId)
.Distinct()))
.ToConcurrent();
_excludedServers = new(allGuildConfigs.Where(x => x.XpSettings.ServerExcluded).Select(x => x.GuildId));
_cmd.OnMessageNoTrigger += Cmd_OnMessageNoTrigger;
#if !GLOBAL_NADEKO
_client.UserVoiceStateUpdated += Client_OnUserVoiceStateUpdated;
// Scan guilds on startup.
_client.GuildAvailable += Client_OnGuildAvailable;
foreach (var guild in _client.Guilds)
{
Client_OnGuildAvailable(guild);
}
foreach (var guild in _client.Guilds) Client_OnGuildAvailable(guild);
#endif
_updateXpTask = Task.Run(UpdateLoop);
}
@@ -218,23 +200,17 @@ public class XpService : INService
if (role is not null)
{
if (rrew.Remove)
{
_ = first.User.RemoveRoleAsync(role);
}
else
{
_ = first.User.AddRoleAsync(role);
}
}
}
//get currency reward for this level
var crew = crews.FirstOrDefault(x => x.Level == i);
if (crew != null)
{
//give the user the reward if it exists
await _cs.AddAsync(item.Key.User.Id, "Level-up Reward", crew.Amount);
}
}
}
}
@@ -243,45 +219,36 @@ public class XpService : INService
}
await toNotify.Select(async x =>
{
if (x.NotifOf == NotifOf.Server)
{
if (x.NotifyType == XpNotificationLocation.Dm)
{
await x.User.SendConfirmAsync(_eb,
_strings.GetText(strs.level_up_dm(
x.User.Mention, Format.Bold(x.Level.ToString()),
Format.Bold(x.Guild.ToString() ?? "-")),
x.Guild.Id));
}
else if (x.MessageChannel != null) // channel
{
await x.MessageChannel.SendConfirmAsync(_eb,
_strings.GetText(strs.level_up_channel(
x.User.Mention,
Format.Bold(x.Level.ToString())),
x.Guild.Id));
}
}
else
{
IMessageChannel chan;
if (x.NotifyType == XpNotificationLocation.Dm)
{
chan = await x.User.CreateDMChannelAsync();
}
else // channel
{
chan = x.MessageChannel;
}
{
if (x.NotifOf == NotifOf.Server)
{
if (x.NotifyType == XpNotificationLocation.Dm)
await x.User.SendConfirmAsync(_eb,
_strings.GetText(strs.level_up_dm(x.User.Mention,
Format.Bold(x.Level.ToString()),
Format.Bold(x.Guild.ToString() ?? "-")),
x.Guild.Id));
else if (x.MessageChannel != null) // channel
await x.MessageChannel.SendConfirmAsync(_eb,
_strings.GetText(strs.level_up_channel(x.User.Mention,
Format.Bold(x.Level.ToString())),
x.Guild.Id));
}
else
{
IMessageChannel chan;
if (x.NotifyType == XpNotificationLocation.Dm)
chan = await x.User.CreateDMChannelAsync();
else // channel
chan = x.MessageChannel;
await chan.SendConfirmAsync(_eb,
_strings.GetText(strs.level_up_global(
x.User.Mention,
Format.Bold(x.Level.ToString())),
x.Guild.Id));
}
}).WhenAll();
await chan.SendConfirmAsync(_eb,
_strings.GetText(strs.level_up_global(x.User.Mention,
Format.Bold(x.Level.ToString())),
x.Guild.Id));
}
})
.WhenAll();
}
catch (Exception ex)
{
@@ -289,7 +256,7 @@ public class XpService : INService
}
}
}
private void InternalReloadXpTemplate()
{
@@ -299,8 +266,8 @@ public class XpService : INService
{
ContractResolver = new RequireObjectPropertiesContractResolver()
};
_template = JsonConvert.DeserializeObject<XpTemplate>(
File.ReadAllText("./data/xp_template.json"), settings);
_template = JsonConvert.DeserializeObject<XpTemplate>(File.ReadAllText("./data/xp_template.json"),
settings);
}
catch (Exception ex)
{
@@ -335,11 +302,7 @@ public class XpService : INService
if (rew != null)
rew.Amount = amount;
else
settings.CurrencyRewards.Add(new()
{
Level = level,
Amount = amount,
});
settings.CurrencyRewards.Add(new() { Level = level, Amount = amount });
}
uow.SaveChanges();
@@ -348,24 +311,20 @@ public class XpService : INService
public IEnumerable<XpCurrencyReward> GetCurrencyRewards(ulong id)
{
using var uow = _db.GetDbContext();
return uow.XpSettingsFor(id)
.CurrencyRewards
.ToArray();
return uow.XpSettingsFor(id).CurrencyRewards.ToArray();
}
public IEnumerable<XpRoleReward> GetRoleRewards(ulong id)
{
using var uow = _db.GetDbContext();
return uow.XpSettingsFor(id)
.RoleRewards
.ToArray();
return uow.XpSettingsFor(id).RoleRewards.ToArray();
}
public void ResetRoleReward(ulong guildId, int level)
{
using var uow = _db.GetDbContext();
var settings = uow.XpSettingsFor(guildId);
var toRemove = settings.RoleRewards.FirstOrDefault(x => x.Level == level);
if (toRemove != null)
{
@@ -375,13 +334,17 @@ public class XpService : INService
uow.SaveChanges();
}
public void SetRoleReward(ulong guildId, int level, ulong roleId, bool remove)
public void SetRoleReward(
ulong guildId,
int level,
ulong roleId,
bool remove)
{
using var uow = _db.GetDbContext();
var settings = uow.XpSettingsFor(guildId);
var rew = settings.RoleRewards.FirstOrDefault(x => x.Level == level);
if (rew != null)
@@ -391,12 +354,7 @@ public class XpService : INService
}
else
{
settings.RoleRewards.Add(new()
{
Level = level,
RoleId = roleId,
Remove = remove,
});
settings.RoleRewards.Add(new() { Level = level, RoleId = roleId, Remove = remove });
}
uow.SaveChanges();
@@ -427,7 +385,7 @@ public class XpService : INService
user.NotifyOnLevelUp = type;
await uow.SaveChangesAsync();
}
public XpNotificationLocation GetNotificationType(ulong userId, ulong guildId)
{
using var uow = _db.GetDbContext();
@@ -453,15 +411,12 @@ public class XpService : INService
{
Task.Run(() =>
{
foreach (var channel in guild.VoiceChannels)
{
ScanChannelForVoiceXp(channel);
}
foreach (var channel in guild.VoiceChannels) ScanChannelForVoiceXp(channel);
});
return Task.CompletedTask;
}
private Task Client_OnUserVoiceStateUpdated(SocketUser socketUser, SocketVoiceState before, SocketVoiceState after)
{
if (socketUser is not SocketGuildUser user || user.IsBot)
@@ -469,59 +424,40 @@ public class XpService : INService
var _ = Task.Run(() =>
{
if (before.VoiceChannel != null)
{
ScanChannelForVoiceXp(before.VoiceChannel);
}
if (before.VoiceChannel != null) ScanChannelForVoiceXp(before.VoiceChannel);
if (after.VoiceChannel != null && after.VoiceChannel != before.VoiceChannel)
{
ScanChannelForVoiceXp(after.VoiceChannel);
}
else if (after.VoiceChannel is null)
{
// In this case, the user left the channel and the previous for loops didn't catch
// it because it wasn't in any new channel. So we need to get rid of it.
UserLeftVoiceChannel(user, before.VoiceChannel);
}
});
return Task.CompletedTask;
}
private void ScanChannelForVoiceXp(SocketVoiceChannel channel)
{
if (ShouldTrackVoiceChannel(channel))
{
foreach (var user in channel.Users)
{
ScanUserForVoiceXp(user, channel);
}
}
else
{
foreach (var user in channel.Users)
{
UserLeftVoiceChannel(user, channel);
}
}
}
/// <summary>
/// Assumes that the channel itself is valid and adding xp.
/// Assumes that the channel itself is valid and adding xp.
/// </summary>
/// <param name="user"></param>
/// <param name="channel"></param>
private void ScanUserForVoiceXp(SocketGuildUser user, SocketVoiceChannel channel)
{
if (UserParticipatingInVoiceChannel(user) && ShouldTrackXp(user, channel.Id))
{
UserJoinedVoiceChannel(user);
}
else
{
UserLeftVoiceChannel(user, channel);
}
}
private bool ShouldTrackVoiceChannel(SocketVoiceChannel channel)
@@ -535,7 +471,8 @@ public class XpService : INService
var key = $"{_creds.RedisKey()}_user_xp_vc_join_{user.Id}";
var value = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
_cache.Redis.GetDatabase().StringSet(key, value, TimeSpan.FromMinutes(_xpConfig.Data.VoiceMaxMinutes), When.NotExists);
_cache.Redis.GetDatabase()
.StringSet(key, value, TimeSpan.FromMinutes(_xpConfig.Data.VoiceMaxMinutes), When.NotExists);
}
private void UserLeftVoiceChannel(SocketGuildUser user, SocketVoiceChannel channel)
@@ -543,44 +480,35 @@ public class XpService : INService
var key = $"{_creds.RedisKey()}_user_xp_vc_join_{user.Id}";
var value = _cache.Redis.GetDatabase().StringGet(key);
_cache.Redis.GetDatabase().KeyDelete(key);
// Allow for if this function gets called multiple times when a user leaves a channel.
if (value.IsNull) return;
if (!value.TryParse(out long startUnixTime))
return;
var dateStart = DateTimeOffset.FromUnixTimeSeconds(startUnixTime);
var dateEnd = DateTimeOffset.UtcNow;
var minutes = (dateEnd - dateStart).TotalMinutes;
var xp = _xpConfig.Data.VoiceXpPerMinute * minutes;
var actualXp = (int) Math.Floor(xp);
var actualXp = (int)Math.Floor(xp);
if (actualXp > 0)
{
_addMessageXp.Enqueue(new()
{
Guild = channel.Guild,
User = user,
XpAmount = actualXp
});
}
_addMessageXp.Enqueue(new() { Guild = channel.Guild, User = user, XpAmount = actualXp });
}
private bool ShouldTrackXp(SocketGuildUser user, ulong channelId)
{
if (_excludedChannels.TryGetValue(user.Guild.Id, out var chans) &&
chans.Contains(channelId)) return false;
if (_excludedChannels.TryGetValue(user.Guild.Id, out var chans) && chans.Contains(channelId)) return false;
if (_excludedServers.Contains(user.Guild.Id)) return false;
if (_excludedRoles.TryGetValue(user.Guild.Id, out var roles) &&
user.Roles.Any(x => roles.Contains(x.Id)))
if (_excludedRoles.TryGetValue(user.Guild.Id, out var roles) && user.Roles.Any(x => roles.Contains(x.Id)))
return false;
return true;
}
private Task Cmd_OnMessageNoTrigger(IUserMessage arg)
{
if (arg.Author is not SocketGuildUser user || user.IsBot)
@@ -593,15 +521,9 @@ public class XpService : INService
var xpConf = _xpConfig.Data;
var xp = 0;
if (arg.Attachments.Any(a => a.Height >= 128 && a.Width >= 128))
{
xp = xpConf.XpFromImage;
}
if (arg.Content.Contains(' ') || arg.Content.Length >= 5)
{
xp = Math.Max(xp, xpConf.XpPerMessage);
}
if (arg.Attachments.Any(a => a.Height >= 128 && a.Width >= 128)) xp = xpConf.XpFromImage;
if (arg.Content.Contains(' ') || arg.Content.Length >= 5) xp = Math.Max(xp, xpConf.XpPerMessage);
if (xp <= 0)
return;
@@ -609,13 +531,7 @@ public class XpService : INService
if (!SetUserRewarded(user.Id))
return;
_addMessageXp.Enqueue(new()
{
Guild = user.Guild,
Channel = arg.Channel,
User = user,
XpAmount = xp
});
_addMessageXp.Enqueue(new() { Guild = user.Guild, Channel = arg.Channel, User = user, XpAmount = xp });
});
return Task.CompletedTask;
}
@@ -623,16 +539,10 @@ public class XpService : INService
public void AddXpDirectly(IGuildUser user, IMessageChannel channel, int amount)
{
if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount));
_addMessageXp.Enqueue(new()
{
Guild = user.Guild,
Channel = channel,
User = user,
XpAmount = amount
});
_addMessageXp.Enqueue(new() { Guild = user.Guild, Channel = channel, User = user, XpAmount = amount });
}
public void AddXp(ulong userId, ulong guildId, int amount)
{
using var uow = _db.GetDbContext();
@@ -667,10 +577,7 @@ public class XpService : INService
var r = _cache.Redis.GetDatabase();
var key = $"{_creds.RedisKey()}_user_xp_gain_{userId}";
return r.StringSet(key,
true,
TimeSpan.FromMinutes(_xpConfig.Data.MessageXpCooldown),
StackExchange.Redis.When.NotExists);
return r.StringSet(key, true, TimeSpan.FromMinutes(_xpConfig.Data.MessageXpCooldown), When.NotExists);
}
public async Task<FullUserStats> GetUserStatsAsync(IGuildUser user)
@@ -690,12 +597,7 @@ public class XpService : INService
await uow.SaveChangesAsync();
}
return new(du,
stats,
new(totalXp),
new(stats.Xp + stats.AwardedXp),
globalRank,
guildRank);
return new(du, stats, new(totalXp), new(stats.Xp + stats.AwardedXp), globalRank, guildRank);
}
public bool ToggleExcludeServer(ulong id)
@@ -720,34 +622,25 @@ public class XpService : INService
var roles = _excludedRoles.GetOrAdd(guildId, _ => new());
using var uow = _db.GetDbContext();
var xpSetting = uow.XpSettingsFor(guildId);
var excludeObj = new ExcludedItem
{
ItemId = rId,
ItemType = ExcludedItemType.Role,
};
var excludeObj = new ExcludedItem { ItemId = rId, ItemType = ExcludedItemType.Role };
if (roles.Add(rId))
{
if (xpSetting.ExclusionList.Add(excludeObj))
{
uow.SaveChanges();
}
if (xpSetting.ExclusionList.Add(excludeObj)) uow.SaveChanges();
return true;
}
else
roles.TryRemove(rId);
var toDelete = xpSetting.ExclusionList.FirstOrDefault(x => x.Equals(excludeObj));
if (toDelete != null)
{
roles.TryRemove(rId);
var toDelete = xpSetting.ExclusionList.FirstOrDefault(x => x.Equals(excludeObj));
if (toDelete != null)
{
uow.Remove(toDelete);
uow.SaveChanges();
}
return false;
uow.Remove(toDelete);
uow.SaveChanges();
}
return false;
}
public bool ToggleExcludeChannel(ulong guildId, ulong chId)
@@ -755,32 +648,20 @@ public class XpService : INService
var channels = _excludedChannels.GetOrAdd(guildId, _ => new());
using var uow = _db.GetDbContext();
var xpSetting = uow.XpSettingsFor(guildId);
var excludeObj = new ExcludedItem
{
ItemId = chId,
ItemType = ExcludedItemType.Channel,
};
var excludeObj = new ExcludedItem { ItemId = chId, ItemType = ExcludedItemType.Channel };
if (channels.Add(chId))
{
if (xpSetting.ExclusionList.Add(excludeObj))
{
uow.SaveChanges();
}
if (xpSetting.ExclusionList.Add(excludeObj)) uow.SaveChanges();
return true;
}
else
{
channels.TryRemove(chId);
if (xpSetting.ExclusionList.Remove(excludeObj))
{
uow.SaveChanges();
}
channels.TryRemove(chId);
return false;
}
if (xpSetting.ExclusionList.Remove(excludeObj)) uow.SaveChanges();
return false;
}
public async Task<(Stream Image, IImageFormat Format)> GenerateXpImageAsync(IGuildUser user)
@@ -790,24 +671,22 @@ public class XpService : INService
}
public Task<(Stream Image, IImageFormat Format)> GenerateXpImageAsync(FullUserStats stats) => Task.Run(
async () =>
public Task<(Stream Image, IImageFormat Format)> GenerateXpImageAsync(FullUserStats stats)
=> Task.Run(async () =>
{
var usernameTextOptions = new TextGraphicsOptions()
var usernameTextOptions = new TextGraphicsOptions
{
TextOptions = new()
{
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center
}
}.WithFallbackFonts(_fonts.FallBackFonts);
var clubTextOptions = new TextGraphicsOptions()
var clubTextOptions = new TextGraphicsOptions
{
TextOptions = new()
{
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top
}
}.WithFallbackFonts(_fonts.FallBackFonts);
@@ -816,16 +695,12 @@ public class XpService : INService
{
var fontSize = (int)(_template.User.Name.FontSize * 0.9);
var username = stats.User.ToString();
var usernameFont = _fonts.NotoSans
.CreateFont(fontSize, FontStyle.Bold);
var usernameFont = _fonts.NotoSans.CreateFont(fontSize, FontStyle.Bold);
var size = TextMeasurer.Measure($"@{username}", new(usernameFont));
var scale = 400f / size.Width;
if (scale < 1)
{
usernameFont = _fonts.NotoSans
.CreateFont(_template.User.Name.FontSize * scale, FontStyle.Bold);
}
usernameFont = _fonts.NotoSans.CreateFont(_template.User.Name.FontSize * scale, FontStyle.Bold);
img.Mutate(x =>
{
@@ -843,45 +718,35 @@ public class XpService : INService
{
var clubName = stats.User.Club?.ToString() ?? "-";
var clubFont = _fonts.NotoSans
.CreateFont(_template.Club.Name.FontSize, FontStyle.Regular);
var clubFont = _fonts.NotoSans.CreateFont(_template.Club.Name.FontSize, FontStyle.Regular);
img.Mutate(x => x.DrawText(clubTextOptions,
clubName,
clubFont,
_template.Club.Name.Color,
new(_template.Club.Name.Pos.X + 50, _template.Club.Name.Pos.Y - 8))
);
new(_template.Club.Name.Pos.X + 50, _template.Club.Name.Pos.Y - 8)));
}
if (_template.User.GlobalLevel.Show)
{
img.Mutate(x =>
{
x.DrawText(
stats.Global.Level.ToString(),
x.DrawText(stats.Global.Level.ToString(),
_fonts.NotoSans.CreateFont(_template.User.GlobalLevel.FontSize, FontStyle.Bold),
_template.User.GlobalLevel.Color,
new(_template.User.GlobalLevel.Pos.X, _template.User.GlobalLevel.Pos.Y)
); //level
new(_template.User.GlobalLevel.Pos.X, _template.User.GlobalLevel.Pos.Y)); //level
});
}
if (_template.User.GuildLevel.Show)
{
img.Mutate(x =>
{
x.DrawText(
stats.Guild.Level.ToString(),
x.DrawText(stats.Guild.Level.ToString(),
_fonts.NotoSans.CreateFont(_template.User.GuildLevel.FontSize, FontStyle.Bold),
_template.User.GuildLevel.Color,
new(_template.User.GuildLevel.Pos.X, _template.User.GuildLevel.Pos.Y)
);
new(_template.User.GuildLevel.Pos.X, _template.User.GuildLevel.Pos.Y));
});
}
var pen = new Pen(SixLabors.ImageSharp.Color.Black, 1);
var pen = new Pen(Color.Black, 1);
var global = stats.Global;
var guild = stats.Guild;
@@ -889,37 +754,31 @@ public class XpService : INService
//xp bar
if (_template.User.Xp.Bar.Show)
{
var xpPercent = global.LevelXp / (float) global.RequiredXp;
var xpPercent = global.LevelXp / (float)global.RequiredXp;
DrawXpBar(xpPercent, _template.User.Xp.Bar.Global, img);
xpPercent = guild.LevelXp / (float) guild.RequiredXp;
xpPercent = guild.LevelXp / (float)guild.RequiredXp;
DrawXpBar(xpPercent, _template.User.Xp.Bar.Guild, img);
}
if (_template.User.Xp.Global.Show)
{
img.Mutate(x => x.DrawText($"{global.LevelXp}/{global.RequiredXp}",
_fonts.NotoSans.CreateFont(_template.User.Xp.Global.FontSize, FontStyle.Bold),
Brushes.Solid(_template.User.Xp.Global.Color),
pen,
new(_template.User.Xp.Global.Pos.X, _template.User.Xp.Global.Pos.Y)));
}
if (_template.User.Xp.Guild.Show)
{
img.Mutate(x => x.DrawText($"{guild.LevelXp}/{guild.RequiredXp}",
_fonts.NotoSans.CreateFont(_template.User.Xp.Guild.FontSize, FontStyle.Bold),
Brushes.Solid(_template.User.Xp.Guild.Color),
pen,
new(_template.User.Xp.Guild.Pos.X, _template.User.Xp.Guild.Pos.Y)));
}
if (stats.FullGuildStats.AwardedXp != 0 && _template.User.Xp.Awarded.Show)
{
var sign = stats.FullGuildStats.AwardedXp > 0
? "+ "
: "";
var awX = _template.User.Xp.Awarded.Pos.X -
(Math.Max(0, stats.FullGuildStats.AwardedXp.ToString().Length - 2) * 5);
var sign = stats.FullGuildStats.AwardedXp > 0 ? "+ " : "";
var awX = _template.User.Xp.Awarded.Pos.X
- (Math.Max(0, stats.FullGuildStats.AwardedXp.ToString().Length - 2) * 5);
var awY = _template.User.Xp.Awarded.Pos.Y;
img.Mutate(x => x.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})",
_fonts.NotoSans.CreateFont(_template.User.Xp.Awarded.FontSize, FontStyle.Bold),
@@ -930,20 +789,16 @@ public class XpService : INService
//ranking
if (_template.User.GlobalRank.Show)
{
img.Mutate(x => x.DrawText(stats.GlobalRanking.ToString(),
_fonts.UniSans.CreateFont(_template.User.GlobalRank.FontSize, FontStyle.Bold),
_template.User.GlobalRank.Color,
new(_template.User.GlobalRank.Pos.X, _template.User.GlobalRank.Pos.Y)));
}
if (_template.User.GuildRank.Show)
{
img.Mutate(x => x.DrawText(stats.GuildRanking.ToString(),
_fonts.UniSans.CreateFont(_template.User.GuildRank.FontSize, FontStyle.Bold),
_template.User.GuildRank.Color,
new(_template.User.GuildRank.Pos.X, _template.User.GuildRank.Pos.Y)));
}
//time on this level
@@ -954,29 +809,20 @@ public class XpService : INService
}
if (_template.User.TimeOnLevel.Global.Show)
{
img.Mutate(x =>
x.DrawText(GetTimeSpent(stats.User.LastLevelUp, _template.User.TimeOnLevel.Format),
_fonts.NotoSans.CreateFont(_template.User.TimeOnLevel.Global.FontSize, FontStyle.Bold),
_template.User.TimeOnLevel.Global.Color,
new(_template.User.TimeOnLevel.Global.Pos.X,
_template.User.TimeOnLevel.Global.Pos.Y)));
}
img.Mutate(x => x.DrawText(GetTimeSpent(stats.User.LastLevelUp, _template.User.TimeOnLevel.Format),
_fonts.NotoSans.CreateFont(_template.User.TimeOnLevel.Global.FontSize, FontStyle.Bold),
_template.User.TimeOnLevel.Global.Color,
new(_template.User.TimeOnLevel.Global.Pos.X, _template.User.TimeOnLevel.Global.Pos.Y)));
if (_template.User.TimeOnLevel.Guild.Show)
{
img.Mutate(x =>
x.DrawText(
GetTimeSpent(stats.FullGuildStats.LastLevelUp, _template.User.TimeOnLevel.Format),
img.Mutate(x
=> x.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp, _template.User.TimeOnLevel.Format),
_fonts.NotoSans.CreateFont(_template.User.TimeOnLevel.Guild.FontSize, FontStyle.Bold),
_template.User.TimeOnLevel.Guild.Color,
new(_template.User.TimeOnLevel.Guild.Pos.X,
_template.User.TimeOnLevel.Guild.Pos.Y)));
}
new(_template.User.TimeOnLevel.Guild.Pos.X, _template.User.TimeOnLevel.Guild.Pos.Y)));
//avatar
if (stats.User.AvatarId != null && _template.User.Icon.Show)
{
try
{
var avatarUrl = stats.User.RealAvatarUrl();
@@ -990,9 +836,10 @@ public class XpService : INService
using (var tempDraw = Image.Load(avatarData))
{
tempDraw.Mutate(x => x
.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y)
.ApplyRoundedCorners(
Math.Max(_template.User.Icon.Size.X, _template.User.Icon.Size.Y) / 2));
.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y)
.ApplyRoundedCorners(Math.Max(_template.User.Icon.Size.X,
_template.User.Icon.Size.Y)
/ 2));
await using (var stream = tempDraw.ToStream())
{
data = stream.ToArray();
@@ -1005,28 +852,22 @@ public class XpService : INService
using var toDraw = Image.Load(data);
if (toDraw.Size() != new Size(_template.User.Icon.Size.X, _template.User.Icon.Size.Y))
{
toDraw.Mutate(x =>
x.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y));
}
toDraw.Mutate(x => x.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y));
img.Mutate(x => x.DrawImage(toDraw,
new Point(_template.User.Icon.Pos.X, _template.User.Icon.Pos.Y), 1));
new Point(_template.User.Icon.Pos.X, _template.User.Icon.Pos.Y),
1));
}
catch (Exception ex)
{
Log.Warning(ex, "Error drawing avatar image");
}
}
//club image
if (_template.Club.Icon.Show)
{
await DrawClubImage(img, stats);
}
if (_template.Club.Icon.Show) await DrawClubImage(img, stats);
img.Mutate(x => x.Resize(_template.OutputSize.X, _template.OutputSize.Y));
return ((Stream) img.ToStream(imageFormat), imageFormat);
return ((Stream)img.ToStream(imageFormat), imageFormat);
});
private void DrawXpBar(float percent, XpBar info, Image<Rgba32> img)
@@ -1071,19 +912,15 @@ public class XpService : INService
}
img.Mutate(x => x.FillPolygon(info.Color,
new[]
{
new PointF(x1, y1),
new PointF(x3, y3),
new PointF(x4, y4),
new PointF(x2, y2),
}));
new PointF(x1, y1),
new PointF(x3, y3),
new PointF(x4, y4),
new PointF(x2, y2)));
}
private async Task DrawClubImage(Image<Rgba32> img, FullUserStats stats)
{
if (!string.IsNullOrWhiteSpace(stats.User.Club?.ImageUrl))
{
try
{
var imgUrl = new Uri(stats.User.Club.ImageUrl);
@@ -1099,9 +936,10 @@ public class XpService : INService
using (var tempDraw = Image.Load(imgData))
{
tempDraw.Mutate(x => x
.Resize(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y)
.ApplyRoundedCorners(
Math.Max(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y) / 2.0f));
.Resize(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y)
.ApplyRoundedCorners(Math.Max(_template.Club.Icon.Size.X,
_template.Club.Icon.Size.Y)
/ 2.0f));
;
await using (var tds = tempDraw.ToStream())
{
@@ -1115,9 +953,7 @@ public class XpService : INService
using var toDraw = Image.Load(data);
if (toDraw.Size() != new Size(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y))
{
toDraw.Mutate(x => x.Resize(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y));
}
img.Mutate(x => x.DrawImage(
toDraw,
@@ -1128,7 +964,6 @@ public class XpService : INService
{
Log.Warning(ex, "Error drawing club image");
}
}
}
public void XpReset(ulong guildId, ulong userId)
@@ -1148,15 +983,20 @@ public class XpService : INService
public async Task ResetXpRewards(ulong guildId)
{
await using var uow = _db.GetDbContext();
var guildConfig = uow.GuildConfigsForId(guildId,
set => set
.Include(x => x.XpSettings)
.ThenInclude(x => x.CurrencyRewards)
.Include(x => x.XpSettings)
.ThenInclude(x => x.RoleRewards));
var guildConfig = uow.GuildConfigsForId(guildId,
set => set.Include(x => x.XpSettings)
.ThenInclude(x => x.CurrencyRewards)
.Include(x => x.XpSettings)
.ThenInclude(x => x.RoleRewards));
uow.RemoveRange(guildConfig.XpSettings.RoleRewards);
uow.RemoveRange(guildConfig.XpSettings.CurrencyRewards);
await uow.SaveChangesAsync();
}
}
private enum NotifOf
{
Server,
Global
} // is it a server level-up or global level-up notification
}

View File

@@ -1,12 +1,25 @@
#nullable disable
using NadekoBot.Services.Database.Models;
using NadekoBot.Modules.Xp.Services;
using NadekoBot.Modules.Gambling.Services;
using NadekoBot.Modules.Xp.Services;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Xp;
public partial class Xp : NadekoModule<XpService>
{
public enum Channel { Channel }
public enum NotifyPlace
{
Server = 0,
Guild = 0,
Global = 1
}
public enum Role { Role }
public enum Server { Server }
private readonly DownloadTracker _tracker;
private readonly GamblingConfigService _gss;
@@ -16,7 +29,8 @@ public partial class Xp : NadekoModule<XpService>
_gss = gss;
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
public async Task Experience([Leftover] IUser user = null)
{
@@ -29,14 +43,15 @@ public partial class Xp : NadekoModule<XpService>
}
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public async Task XpRewsReset()
{
var reply = await PromptUserConfirmAsync(_eb.Create()
.WithPendingColor()
.WithDescription(GetText(strs.xprewsreset_confirm)));
.WithPendingColor()
.WithDescription(GetText(strs.xprewsreset_confirm)));
if (!reply)
return;
@@ -44,8 +59,9 @@ public partial class Xp : NadekoModule<XpService>
await _service.ResetXpRewards(ctx.Guild.Id);
await ctx.OkAsync();
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
public Task XpLevelUpRewards(int page = 1)
{
@@ -55,58 +71,56 @@ public partial class Xp : NadekoModule<XpService>
return Task.CompletedTask;
var allRewards = _service.GetRoleRewards(ctx.Guild.Id)
.OrderBy(x => x.Level)
.Select(x =>
.OrderBy(x => x.Level)
.Select(x =>
{
var sign = !x.Remove ? @"✅ " : @"❌ ";
var str = ctx.Guild.GetRole(x.RoleId)?.ToString();
if (str is null)
{
str = GetText(strs.role_not_found(Format.Code(x.RoleId.ToString())));
}
else
{
if (!x.Remove)
str = GetText(strs.xp_receive_role(Format.Bold(str)));
else
str = GetText(strs.xp_lose_role(Format.Bold(str)));
}
return (x.Level, Text: sign + str);
})
.Concat(_service.GetCurrencyRewards(ctx.Guild.Id)
.OrderBy(x => x.Level)
.Select(x => (x.Level,
Format.Bold(x.Amount + _gss.Data.Currency.Sign))))
.GroupBy(x => x.Level)
.OrderBy(x => x.Key)
.ToList();
return Context.SendPaginatedConfirmAsync(page,
cur =>
{
var sign = !x.Remove
? @"✅ "
: @"❌ ";
var str = ctx.Guild.GetRole(x.RoleId)?.ToString();
if (str is null)
str = GetText(strs.role_not_found(Format.Code(x.RoleId.ToString())));
else
{
if (!x.Remove)
str = GetText(strs.xp_receive_role(Format.Bold(str)));
else
str = GetText(strs.xp_lose_role(Format.Bold(str)));
}
return (x.Level, Text: sign + str);
})
.Concat(_service.GetCurrencyRewards(ctx.Guild.Id)
.OrderBy(x => x.Level)
.Select(x => (x.Level, Format.Bold(x.Amount + _gss.Data.Currency.Sign))))
.GroupBy(x => x.Level)
.OrderBy(x => x.Key)
.ToList();
var embed = _eb.Create().WithTitle(GetText(strs.level_up_rewards)).WithOkColor();
return Context.SendPaginatedConfirmAsync(page, cur =>
{
var embed = _eb.Create()
.WithTitle(GetText(strs.level_up_rewards))
.WithOkColor();
var localRewards = allRewards
.Skip(cur * 9)
.Take(9)
.ToList();
var localRewards = allRewards.Skip(cur * 9).Take(9).ToList();
if (!localRewards.Any())
return embed.WithDescription(GetText(strs.no_level_up_rewards));
if (!localRewards.Any())
return embed.WithDescription(GetText(strs.no_level_up_rewards));
foreach (var reward in localRewards)
{
embed.AddField(GetText(strs.level_x(reward.Key)),
string.Join("\n", reward.Select(y => y.Item2)));
}
return embed;
}, allRewards.Count, 9);
foreach (var reward in localRewards)
embed.AddField(GetText(strs.level_x(reward.Key)), string.Join("\n", reward.Select(y => y.Item2)));
return embed;
},
allRewards.Count,
9);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[UserPerm(GuildPerm.Administrator)]
[BotPerm(GuildPerm.ManageRoles)]
[RequireContext(ContextType.Guild)]
@@ -116,8 +130,9 @@ public partial class Xp : NadekoModule<XpService>
_service.ResetRoleReward(ctx.Guild.Id, level);
await ReplyConfirmLocalizedAsync(strs.xp_role_reward_cleared(level));
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[UserPerm(GuildPerm.Administrator)]
[BotPerm(GuildPerm.ManageRoles)]
[RequireContext(ContextType.Guild)]
@@ -129,16 +144,14 @@ public partial class Xp : NadekoModule<XpService>
_service.SetRoleReward(ctx.Guild.Id, level, role.Id, action == AddRemove.Remove);
if (action == AddRemove.Add)
await ReplyConfirmLocalizedAsync(strs.xp_role_reward_add_role(
level,
Format.Bold(role.ToString())));
await ReplyConfirmLocalizedAsync(strs.xp_role_reward_add_role(level, Format.Bold(role.ToString())));
else
await ReplyConfirmLocalizedAsync(strs.xp_role_reward_remove_role(
Format.Bold(level.ToString()),
await ReplyConfirmLocalizedAsync(strs.xp_role_reward_remove_role(Format.Bold(level.ToString()),
Format.Bold(role.ToString())));
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task XpCurrencyReward(int level, int amount = 0)
@@ -152,33 +165,20 @@ public partial class Xp : NadekoModule<XpService>
if (amount == 0)
await ReplyConfirmLocalizedAsync(strs.cur_reward_cleared(level, config.Currency.Sign));
else
await ReplyConfirmLocalizedAsync(strs.cur_reward_added(
level, Format.Bold(amount + config.Currency.Sign)));
}
public enum NotifyPlace
{
Server = 0,
Guild = 0,
Global = 1,
await ReplyConfirmLocalizedAsync(strs.cur_reward_added(level, Format.Bold(amount + config.Currency.Sign)));
}
private string GetNotifLocationString(XpNotificationLocation loc)
{
if (loc == XpNotificationLocation.Channel)
{
return GetText(strs.xpn_notif_channel);
}
if (loc == XpNotificationLocation.Channel) return GetText(strs.xpn_notif_channel);
if (loc == XpNotificationLocation.Dm)
{
return GetText(strs.xpn_notif_dm);
}
if (loc == XpNotificationLocation.Dm) return GetText(strs.xpn_notif_dm);
return GetText(strs.xpn_notif_disabled);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
public async Task XpNotify()
{
@@ -186,14 +186,15 @@ public partial class Xp : NadekoModule<XpService>
var serverSetting = _service.GetNotificationType(ctx.User.Id, ctx.Guild.Id);
var embed = _eb.Create()
.WithOkColor()
.AddField(GetText(strs.xpn_setting_global), GetNotifLocationString(globalSetting))
.AddField(GetText(strs.xpn_setting_server), GetNotifLocationString(serverSetting));
.WithOkColor()
.AddField(GetText(strs.xpn_setting_global), GetNotifLocationString(globalSetting))
.AddField(GetText(strs.xpn_setting_server), GetNotifLocationString(serverSetting));
await ctx.Channel.EmbedAsync(embed);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
public async Task XpNotify(NotifyPlace place, XpNotificationLocation type)
{
@@ -201,13 +202,12 @@ public partial class Xp : NadekoModule<XpService>
await _service.ChangeNotificationType(ctx.User.Id, ctx.Guild.Id, type);
else
await _service.ChangeNotificationType(ctx.User, type);
await ctx.OkAsync();
}
public enum Server { Server };
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public async Task XpExclude(Server _)
@@ -215,18 +215,13 @@ public partial class Xp : NadekoModule<XpService>
var ex = _service.ToggleExcludeServer(ctx.Guild.Id);
if (ex)
{
await ReplyConfirmLocalizedAsync(strs.excluded(Format.Bold(ctx.Guild.ToString())));
}
else
{
await ReplyConfirmLocalizedAsync(strs.not_excluded(Format.Bold(ctx.Guild.ToString())));
}
}
public enum Role { Role };
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[UserPerm(GuildPerm.ManageRoles)]
[RequireContext(ContextType.Guild)]
public async Task XpExclude(Role _, [Leftover] IRole role)
@@ -234,18 +229,13 @@ public partial class Xp : NadekoModule<XpService>
var ex = _service.ToggleExcludeRole(ctx.Guild.Id, role.Id);
if (ex)
{
await ReplyConfirmLocalizedAsync(strs.excluded(Format.Bold(role.ToString())));
}
else
{
await ReplyConfirmLocalizedAsync(strs.not_excluded(Format.Bold(role.ToString())));
}
}
public enum Channel { Channel };
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[UserPerm(GuildPerm.ManageChannels)]
[RequireContext(ContextType.Guild)]
public async Task XpExclude(Channel _, [Leftover] IChannel channel = null)
@@ -256,31 +246,28 @@ public partial class Xp : NadekoModule<XpService>
var ex = _service.ToggleExcludeChannel(ctx.Guild.Id, channel.Id);
if (ex)
{
await ReplyConfirmLocalizedAsync(strs.excluded(Format.Bold(channel.ToString())));
}
else
{
await ReplyConfirmLocalizedAsync(strs.not_excluded(Format.Bold(channel.ToString())));
}
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
public async Task XpExclusionList()
{
var serverExcluded = _service.IsServerExcluded(ctx.Guild.Id);
var roles = _service.GetExcludedRoles(ctx.Guild.Id)
.Select(x => ctx.Guild.GetRole(x))
.Where(x => x != null)
.Select(x => $"`role` {x.Mention}")
.ToList();
.Select(x => ctx.Guild.GetRole(x))
.Where(x => x != null)
.Select(x => $"`role` {x.Mention}")
.ToList();
var chans = (await _service.GetExcludedChannels(ctx.Guild.Id)
.Select(x => ctx.Guild.GetChannelAsync(x))
.WhenAll()).Where(x => x != null)
.Select(x => $"`channel` <#{x.Id}>")
.ToList();
.Select(x => ctx.Guild.GetChannelAsync(x))
.WhenAll()).Where(x => x != null)
.Select(x => $"`channel` <#{x.Id}>")
.ToList();
var rolesStr = roles.Any() ? string.Join("\n", roles) + "\n" : string.Empty;
var chansStr = chans.Count > 0 ? string.Join("\n", chans) + "\n" : string.Empty;
@@ -291,25 +278,30 @@ public partial class Xp : NadekoModule<XpService>
desc += "\n\n" + rolesStr + chansStr;
var lines = desc.Split('\n');
await ctx.SendPaginatedConfirmAsync(0, curpage =>
{
var embed = _eb.Create()
.WithTitle(GetText(strs.exclusion_list))
.WithDescription(string.Join('\n', lines.Skip(15 * curpage).Take(15)))
.WithOkColor();
await ctx.SendPaginatedConfirmAsync(0,
curpage =>
{
var embed = _eb.Create()
.WithTitle(GetText(strs.exclusion_list))
.WithDescription(string.Join('\n', lines.Skip(15 * curpage).Take(15)))
.WithOkColor();
return embed;
}, lines.Length, 15);
return embed;
},
lines.Length,
15);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[NadekoOptions(typeof(LbOpts))]
[Priority(0)]
[RequireContext(ContextType.Guild)]
public Task XpLeaderboard(params string[] args)
=> XpLeaderboard(1, args);
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[NadekoOptions(typeof(LbOpts))]
[Priority(1)]
[RequireContext(ContextType.Guild)]
@@ -328,32 +320,25 @@ public partial class Xp : NadekoModule<XpService>
{
await ctx.Channel.TriggerTypingAsync();
await _tracker.EnsureUsersDownloadedAsync(ctx.Guild);
allUsers = _service.GetTopUserXps(ctx.Guild.Id, 1000)
.Where(user => socketGuild.GetUser(user.UserId) is not null)
.ToList();
.Where(user => socketGuild.GetUser(user.UserId) is not null)
.ToList();
}
await ctx.SendPaginatedConfirmAsync(page, curPage =>
{
var embed = _eb.Create()
.WithTitle(GetText(strs.server_leaderboard))
.WithOkColor();
await ctx.SendPaginatedConfirmAsync(page,
curPage =>
{
var embed = _eb.Create().WithTitle(GetText(strs.server_leaderboard)).WithOkColor();
List<UserXpStats> users;
if (opts.Clean)
{
users = allUsers.Skip(curPage * 9).Take(9).ToList();
}
else
{
users = _service.GetUserXps(ctx.Guild.Id, curPage);
}
List<UserXpStats> users;
if (opts.Clean)
users = allUsers.Skip(curPage * 9).Take(9).ToList();
else
users = _service.GetUserXps(ctx.Guild.Id, curPage);
if (!users.Any()) return embed.WithDescription("-");
if (!users.Any())
return embed.WithDescription("-");
else
{
for (var i = 0; i < users.Count; i++)
{
var levelStats = new LevelStats(users[i].Xp + users[i].AwardedXp);
@@ -367,16 +352,19 @@ public partial class Xp : NadekoModule<XpService>
else if (userXpData.AwardedXp < 0)
awardStr = $"({userXpData.AwardedXp})";
embed.AddField(
$"#{i + 1 + (curPage * 9)} {user?.ToString() ?? users[i].UserId.ToString()}",
embed.AddField($"#{i + 1 + (curPage * 9)} {user?.ToString() ?? users[i].UserId.ToString()}",
$"{GetText(strs.level_x(levelStats.Level))} - {levelStats.TotalXp}xp {awardStr}");
}
return embed;
}
}, 900, 9, addPaginatedFooter: false);
},
900,
9,
false);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
public async Task XpGlobalLeaderboard(int page = 1)
{
@@ -384,27 +372,23 @@ public partial class Xp : NadekoModule<XpService>
return;
var users = _service.GetUserXps(page);
var embed = _eb.Create()
.WithTitle(GetText(strs.global_leaderboard))
.WithOkColor();
var embed = _eb.Create().WithTitle(GetText(strs.global_leaderboard)).WithOkColor();
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()}",
embed.AddField($"#{i + 1 + (page * 9)} {user.ToString()}",
$"{GetText(strs.level_x(new LevelStats(users[i].TotalXp).Level))} - {users[i].TotalXp}xp");
}
}
await ctx.Channel.EmbedAsync(embed);
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public async Task XpAdd(int amount, ulong userId)
@@ -413,18 +397,19 @@ public partial class Xp : NadekoModule<XpService>
return;
_service.AddXp(userId, ctx.Guild.Id, amount);
var usr = ((SocketGuild)ctx.Guild).GetUser(userId)?.ToString()
?? userId.ToString();
var usr = ((SocketGuild)ctx.Guild).GetUser(userId)?.ToString() ?? userId.ToString();
await ReplyConfirmLocalizedAsync(strs.modified(Format.Bold(usr), Format.Bold(amount.ToString())));
}
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public Task XpAdd(int amount, [Leftover] IGuildUser user)
=> XpAdd(amount, user.Id);
[NadekoCommand, Aliases]
[NadekoCommand]
[Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task XpTemplateReload()
@@ -433,4 +418,4 @@ public partial class Xp : NadekoModule<XpService>
await Task.Delay(1000);
await ReplyConfirmLocalizedAsync(strs.template_reloaded);
}
}
}