mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
- Use IEmbedBuilderService to create embed builders - Wrapped embed builder and using IEmbedBuilder
433 lines
15 KiB
C#
433 lines
15 KiB
C#
using Discord;
|
|
using Discord.Commands;
|
|
using Discord.WebSocket;
|
|
using NadekoBot.Common.Attributes;
|
|
using NadekoBot.Common;
|
|
using NadekoBot.Services.Database.Models;
|
|
using NadekoBot.Extensions;
|
|
using NadekoBot.Modules.Xp.Services;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using NadekoBot.Modules.Gambling.Services;
|
|
|
|
namespace NadekoBot.Modules.Xp
|
|
{
|
|
public partial class Xp : NadekoModule<XpService>
|
|
{
|
|
private readonly DownloadTracker _tracker;
|
|
private readonly GamblingConfigService _gss;
|
|
|
|
public Xp(DownloadTracker tracker, GamblingConfigService gss)
|
|
{
|
|
_tracker = tracker;
|
|
_gss = gss;
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task Experience([Leftover] IUser user = null)
|
|
{
|
|
user = user ?? ctx.User;
|
|
await ctx.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
|
var (img, fmt) = await _service.GenerateXpImageAsync((IGuildUser)user).ConfigureAwait(false);
|
|
using (img)
|
|
{
|
|
await ctx.Channel.SendFileAsync(img, $"{ctx.Guild.Id}_{user.Id}_xp.{fmt.FileExtensions.FirstOrDefault()}")
|
|
.ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
public async Task XpRewsReset()
|
|
{
|
|
var reply = await PromptUserConfirmAsync(_eb.Create()
|
|
.WithPendingColor()
|
|
.WithDescription(GetText("xprewsreset_confirm")));
|
|
|
|
if (!reply)
|
|
return;
|
|
|
|
await _service.ResetXpRewards(ctx.Guild.Id);
|
|
await ctx.OkAsync();
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
public Task XpLevelUpRewards(int page = 1)
|
|
{
|
|
page--;
|
|
|
|
if (page < 0 || page > 100)
|
|
return Task.CompletedTask;
|
|
|
|
var allRewards = _service.GetRoleRewards(ctx.Guild.Id)
|
|
.OrderBy(x => x.Level)
|
|
.Select(x =>
|
|
{
|
|
var sign = !x.Remove
|
|
? @"✅ "
|
|
: @"❌ ";
|
|
|
|
var str = ctx.Guild.GetRole(x.RoleId)?.ToString();
|
|
|
|
if (str is null)
|
|
str = GetText("role_not_found", Format.Code(x.RoleId.ToString()));
|
|
else
|
|
{
|
|
if (!x.Remove)
|
|
str = GetText("xp_receive_role", Format.Bold(str));
|
|
else
|
|
str = GetText("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 embed = _eb.Create()
|
|
.WithTitle(GetText("level_up_rewards"))
|
|
.WithOkColor();
|
|
|
|
var localRewards = allRewards
|
|
.Skip(cur * 9)
|
|
.Take(9)
|
|
.ToList();
|
|
|
|
if (!localRewards.Any())
|
|
return embed.WithDescription(GetText("no_level_up_rewards"));
|
|
|
|
foreach (var reward in localRewards)
|
|
{
|
|
embed.AddField(GetText("level_x", reward.Key),
|
|
string.Join("\n", reward.Select(y => y.Item2)));
|
|
}
|
|
|
|
return embed;
|
|
}, allRewards.Count, 9);
|
|
}
|
|
|
|
public enum AddRemove
|
|
{
|
|
Add = 0,
|
|
Remove = 1,
|
|
Rm = 1,
|
|
Rem = 1,
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
[RequireContext(ContextType.Guild)]
|
|
[Priority(2)]
|
|
public async Task XpRoleReward(int level)
|
|
{
|
|
_service.ResetRoleReward(ctx.Guild.Id, level);
|
|
await ReplyConfirmLocalizedAsync("xp_role_reward_cleared", level).ConfigureAwait(false);
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
[RequireContext(ContextType.Guild)]
|
|
[Priority(1)]
|
|
public async Task XpRoleReward(int level, AddRemove action, [Leftover] IRole role)
|
|
{
|
|
if (level < 1)
|
|
return;
|
|
|
|
_service.SetRoleReward(ctx.Guild.Id, level, role.Id, action == AddRemove.Remove);
|
|
if (action == AddRemove.Add)
|
|
await ReplyConfirmLocalizedAsync("xp_role_reward_add_role",
|
|
level,
|
|
Format.Bold(role.ToString()));
|
|
else
|
|
await ReplyConfirmLocalizedAsync("xp_role_reward_remove_role",
|
|
Format.Bold(level.ToString()),
|
|
Format.Bold(role.ToString()));
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
[OwnerOnly]
|
|
public async Task XpCurrencyReward(int level, int amount = 0)
|
|
{
|
|
if (level < 1 || amount < 0)
|
|
return;
|
|
|
|
_service.SetCurrencyReward(ctx.Guild.Id, level, amount);
|
|
var config = _gss.Data;
|
|
|
|
if (amount == 0)
|
|
await ReplyConfirmLocalizedAsync("cur_reward_cleared", level, config.Currency.Sign)
|
|
.ConfigureAwait(false);
|
|
else
|
|
await ReplyConfirmLocalizedAsync("cur_reward_added",
|
|
level, Format.Bold(amount + config.Currency.Sign))
|
|
.ConfigureAwait(false);
|
|
}
|
|
|
|
public enum NotifyPlace
|
|
{
|
|
Server = 0,
|
|
Guild = 0,
|
|
Global = 1,
|
|
}
|
|
|
|
private string GetNotifLocationString(XpNotificationLocation loc)
|
|
{
|
|
if (loc == XpNotificationLocation.Channel)
|
|
{
|
|
return GetText("xpn_notif_channel");
|
|
}
|
|
|
|
if (loc == XpNotificationLocation.Dm)
|
|
{
|
|
return GetText("xpn_notif_dm");
|
|
}
|
|
|
|
return GetText("xpn_notif_disabled");
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task XpNotify()
|
|
{
|
|
var globalSetting = _service.GetNotificationType(ctx.User);
|
|
var serverSetting = _service.GetNotificationType(ctx.User.Id, ctx.Guild.Id);
|
|
|
|
var embed = _eb.Create()
|
|
.WithOkColor()
|
|
.AddField(GetText("xpn_setting_global"), GetNotifLocationString(globalSetting))
|
|
.AddField(GetText("xpn_setting_server"), GetNotifLocationString(serverSetting));
|
|
|
|
await Context.Channel.EmbedAsync(embed);
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task XpNotify(NotifyPlace place, XpNotificationLocation type)
|
|
{
|
|
if (place == NotifyPlace.Guild)
|
|
await _service.ChangeNotificationType(ctx.User.Id, ctx.Guild.Id, type).ConfigureAwait(false);
|
|
else
|
|
await _service.ChangeNotificationType(ctx.User, type).ConfigureAwait(false);
|
|
|
|
await ctx.OkAsync().ConfigureAwait(false);
|
|
}
|
|
|
|
public enum Server { Server };
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
public async Task XpExclude(Server _)
|
|
{
|
|
var ex = _service.ToggleExcludeServer(ctx.Guild.Id);
|
|
|
|
await ReplyConfirmLocalizedAsync((ex ? "excluded" : "not_excluded"), Format.Bold(ctx.Guild.ToString())).ConfigureAwait(false);
|
|
}
|
|
|
|
public enum Role { Role };
|
|
|
|
[NadekoCommand, Aliases]
|
|
[UserPerm(GuildPerm.ManageRoles)]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task XpExclude(Role _, [Leftover] IRole role)
|
|
{
|
|
var ex = _service.ToggleExcludeRole(ctx.Guild.Id, role.Id);
|
|
|
|
await ReplyConfirmLocalizedAsync((ex ? "excluded" : "not_excluded"), Format.Bold(role.ToString())).ConfigureAwait(false);
|
|
}
|
|
|
|
public enum Channel { Channel };
|
|
|
|
[NadekoCommand, Aliases]
|
|
[UserPerm(GuildPerm.ManageChannels)]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task XpExclude(Channel _, [Leftover] IChannel channel = null)
|
|
{
|
|
if (channel is null)
|
|
channel = ctx.Channel;
|
|
|
|
var ex = _service.ToggleExcludeChannel(ctx.Guild.Id, channel.Id);
|
|
|
|
await ReplyConfirmLocalizedAsync((ex ? "excluded" : "not_excluded"), Format.Bold(channel.ToString())).ConfigureAwait(false);
|
|
}
|
|
|
|
[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();
|
|
|
|
var chans = (await Task.WhenAll(_service.GetExcludedChannels(ctx.Guild.Id)
|
|
.Select(x => ctx.Guild.GetChannelAsync(x)))
|
|
.ConfigureAwait(false))
|
|
.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;
|
|
var desc = Format.Code(serverExcluded
|
|
? GetText("server_is_excluded")
|
|
: GetText("server_is_not_excluded"));
|
|
|
|
desc += "\n\n" + rolesStr + chansStr;
|
|
|
|
var lines = desc.Split('\n');
|
|
await ctx.SendPaginatedConfirmAsync(0, curpage =>
|
|
{
|
|
var embed = _eb.Create()
|
|
.WithTitle(GetText("exclusion_list"))
|
|
.WithDescription(string.Join('\n', lines.Skip(15 * curpage).Take(15)))
|
|
.WithOkColor();
|
|
|
|
return embed;
|
|
}, lines.Length, 15);
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[NadekoOptions(typeof(LbOpts))]
|
|
[Priority(0)]
|
|
[RequireContext(ContextType.Guild)]
|
|
public Task XpLeaderboard(params string[] args)
|
|
=> XpLeaderboard(1, args);
|
|
|
|
[NadekoCommand, Aliases]
|
|
[NadekoOptions(typeof(LbOpts))]
|
|
[Priority(1)]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task XpLeaderboard(int page = 1, params string[] args)
|
|
{
|
|
if (--page < 0 || page > 100)
|
|
return;
|
|
|
|
var (opts, _) = OptionsParser.ParseFrom(new LbOpts(), args);
|
|
|
|
await Context.Channel.TriggerTypingAsync();
|
|
|
|
var socketGuild = ((SocketGuild)ctx.Guild);
|
|
List<UserXpStats> allUsers = new List<UserXpStats>();
|
|
if (opts.Clean)
|
|
{
|
|
await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
|
await _tracker.EnsureUsersDownloadedAsync(ctx.Guild).ConfigureAwait(false);
|
|
|
|
allUsers = _service.GetTopUserXps(ctx.Guild.Id, 1000)
|
|
.Where(user => !(socketGuild.GetUser(user.UserId) is null))
|
|
.ToList();
|
|
}
|
|
|
|
await ctx.SendPaginatedConfirmAsync(page, (curPage) =>
|
|
{
|
|
var embed = _eb.Create()
|
|
.WithTitle(GetText("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);
|
|
}
|
|
|
|
if (!users.Any())
|
|
return embed.WithDescription("-");
|
|
else
|
|
{
|
|
for (int i = 0; i < users.Count; i++)
|
|
{
|
|
var levelStats = new LevelStats(users[i].Xp + users[i].AwardedXp);
|
|
var user = ((SocketGuild)ctx.Guild).GetUser(users[i].UserId);
|
|
|
|
var userXpData = users[i];
|
|
|
|
var awardStr = "";
|
|
if (userXpData.AwardedXp > 0)
|
|
awardStr = $"(+{userXpData.AwardedXp})";
|
|
else if (userXpData.AwardedXp < 0)
|
|
awardStr = $"({userXpData.AwardedXp})";
|
|
|
|
embed.AddField(
|
|
$"#{(i + 1 + curPage * 9)} {(user?.ToString() ?? users[i].UserId.ToString())}",
|
|
$"{GetText("level_x", levelStats.Level)} - {levelStats.TotalXp}xp {awardStr}");
|
|
}
|
|
return embed;
|
|
}
|
|
}, 900, 9, addPaginatedFooter: false);
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task XpGlobalLeaderboard(int page = 1)
|
|
{
|
|
if (--page < 0 || page > 99)
|
|
return;
|
|
var users = _service.GetUserXps(page);
|
|
|
|
var embed = _eb.Create()
|
|
.WithTitle(GetText("global_leaderboard"))
|
|
.WithOkColor();
|
|
|
|
if (!users.Any())
|
|
embed.WithDescription("-");
|
|
else
|
|
{
|
|
for (int i = 0; i < users.Length; i++)
|
|
{
|
|
var user = users[i];
|
|
embed.AddField(
|
|
$"#{i + 1 + page * 9} {(user.ToString())}",
|
|
$"{GetText("level_x", new LevelStats(users[i].TotalXp).Level)} - {users[i].TotalXp}xp");
|
|
}
|
|
}
|
|
|
|
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
public async Task XpAdd(int amount, ulong userId)
|
|
{
|
|
if (amount == 0)
|
|
return;
|
|
|
|
_service.AddXp(userId, ctx.Guild.Id, amount);
|
|
var usr = ((SocketGuild)ctx.Guild).GetUser(userId)?.ToString()
|
|
?? userId.ToString();
|
|
await ReplyConfirmLocalizedAsync("modified", Format.Bold(usr), Format.Bold(amount.ToString())).ConfigureAwait(false);
|
|
}
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
public Task XpAdd(int amount, [Leftover] IGuildUser user)
|
|
=> XpAdd(amount, user.Id);
|
|
|
|
[NadekoCommand, Aliases]
|
|
[RequireContext(ContextType.Guild)]
|
|
[OwnerOnly]
|
|
public async Task XpTemplateReload()
|
|
{
|
|
_service.ReloadXpTemplate();
|
|
await Task.Delay(1000).ConfigureAwait(false);
|
|
await ReplyConfirmLocalizedAsync("template_reloaded").ConfigureAwait(false);
|
|
}
|
|
}
|
|
}
|