mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
Applied codestyle to all .cs files
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -37,4 +37,4 @@ public class LevelStats
|
||||
LevelXp = xp - totalXp;
|
||||
RequiredXp = required;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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());
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,4 +13,4 @@ public class UserCacheItem
|
||||
|
||||
public override bool Equals(object obj)
|
||||
=> obj is UserCacheItem uci && uci.User == User;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user