forked from EllieBotDevs/elliebot
970 lines
No EOL
35 KiB
C#
970 lines
No EOL
35 KiB
C#
#nullable disable
|
|
using CommandLine;
|
|
using EllieBot.Common.TypeReaders.Models;
|
|
using EllieBot.Modules.Administration.Services;
|
|
using EllieBot.Db.Models;
|
|
|
|
namespace EllieBot.Modules.Administration;
|
|
|
|
public partial class Administration
|
|
{
|
|
[Group]
|
|
public partial class UserPunishCommands : EllieModule<UserPunishService>
|
|
{
|
|
public enum AddRole
|
|
{
|
|
AddRole
|
|
}
|
|
|
|
private readonly MuteService _mute;
|
|
|
|
public UserPunishCommands(MuteService mute)
|
|
{
|
|
_mute = mute;
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
public Task Warn(IGuildUser user, [Leftover] string reason = null)
|
|
=> Warn(1, user, reason);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
public async Task Warn(int weight, IGuildUser user, [Leftover] string reason = null)
|
|
{
|
|
if (weight <= 0)
|
|
return;
|
|
|
|
if (!await CheckRoleHierarchy(user))
|
|
return;
|
|
|
|
var dmFailed = false;
|
|
try
|
|
{
|
|
await _sender.Response(user)
|
|
.Embed(CreateEmbed()
|
|
.WithErrorColor()
|
|
.WithDescription(GetText(strs.warned_on(ctx.Guild.ToString())))
|
|
.AddField(GetText(strs.moderator), ctx.User.ToString())
|
|
.AddField(GetText(strs.reason), reason ?? "-"))
|
|
.SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
dmFailed = true;
|
|
}
|
|
|
|
WarningPunishment punishment;
|
|
try
|
|
{
|
|
punishment = await _service.Warn(ctx.Guild, user.Id, ctx.User, weight, reason);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Warning(ex, "Exception occured while warning a user");
|
|
var errorEmbed = CreateEmbed()
|
|
.WithErrorColor()
|
|
.WithDescription(GetText(strs.cant_apply_punishment));
|
|
|
|
if (dmFailed)
|
|
errorEmbed.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
|
|
|
|
await Response().Embed(errorEmbed).SendAsync();
|
|
return;
|
|
}
|
|
|
|
var embed = CreateEmbed().WithOkColor();
|
|
if (punishment is null)
|
|
embed.WithDescription(GetText(strs.user_warned(Format.Bold(user.ToString()))));
|
|
else
|
|
{
|
|
embed.WithDescription(GetText(strs.user_warned_and_punished(Format.Bold(user.ToString()),
|
|
Format.Bold(punishment.Punishment.ToString()))));
|
|
}
|
|
|
|
if (dmFailed)
|
|
embed.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
|
|
|
|
await Response().Embed(embed).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
[EllieOptions<WarnExpireOptions>]
|
|
[Priority(1)]
|
|
public async Task WarnExpire()
|
|
{
|
|
var (expireDays, _) = await _service.GetWarnExpire(ctx.Guild.Id);
|
|
|
|
if (expireDays == 0)
|
|
await Response().Confirm(strs.warns_dont_expire).SendAsync();
|
|
else
|
|
await Response().Error(strs.warns_expire_in(expireDays)).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
[EllieOptions<WarnExpireOptions>]
|
|
[Priority(2)]
|
|
public async Task WarnExpire(int days, params string[] args)
|
|
{
|
|
if (days is < 0 or > 366)
|
|
return;
|
|
|
|
var opts = OptionsParser.ParseFrom<WarnExpireOptions>(args);
|
|
|
|
await ctx.Channel.TriggerTypingAsync();
|
|
|
|
await _service.WarnExpireAsync(ctx.Guild.Id, days, opts.Delete);
|
|
if (days == 0)
|
|
{
|
|
await Response().Confirm(strs.warn_expire_reset).SendAsync();
|
|
return;
|
|
}
|
|
|
|
if (opts.Delete)
|
|
await Response().Confirm(strs.warn_expire_set_delete(Format.Bold(days.ToString()))).SendAsync();
|
|
else
|
|
await Response().Confirm(strs.warn_expire_set_clear(Format.Bold(days.ToString()))).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[Priority(2)]
|
|
public Task Warnlog(int page, [Leftover] IGuildUser user = null)
|
|
{
|
|
user ??= (IGuildUser)ctx.User;
|
|
|
|
return Warnlog(page, user.Id);
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[Priority(3)]
|
|
public Task Warnlog(IGuildUser user = null)
|
|
{
|
|
user ??= (IGuildUser)ctx.User;
|
|
|
|
return ctx.User.Id == user.Id || ((IGuildUser)ctx.User).GuildPermissions.BanMembers
|
|
? Warnlog(user.Id)
|
|
: Task.CompletedTask;
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[Priority(0)]
|
|
public Task Warnlog(int page, ulong userId)
|
|
=> InternalWarnlog(userId, page - 1);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[Priority(1)]
|
|
public Task Warnlog(ulong userId)
|
|
=> InternalWarnlog(userId, 0);
|
|
|
|
private async Task InternalWarnlog(ulong userId, int inputPage)
|
|
{
|
|
if (inputPage < 0)
|
|
return;
|
|
|
|
var allWarnings = _service.UserWarnings(ctx.Guild.Id, userId);
|
|
|
|
await Response()
|
|
.Paginated()
|
|
.Items(allWarnings)
|
|
.PageSize(9)
|
|
.CurrentPage(inputPage)
|
|
.Page((warnings, page) =>
|
|
{
|
|
var user = (ctx.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString();
|
|
var embed = CreateEmbed().WithOkColor().WithTitle(GetText(strs.warnlog_for(user)));
|
|
|
|
if (!warnings.Any())
|
|
embed.WithDescription(GetText(strs.warnings_none));
|
|
else
|
|
{
|
|
var descText = GetText(strs.warn_count(
|
|
Format.Bold(warnings.Where(x => !x.Forgiven).Sum(x => x.Weight).ToString()),
|
|
Format.Bold(warnings.Sum(x => x.Weight).ToString())));
|
|
|
|
embed.WithDescription(descText);
|
|
|
|
var i = page * 9;
|
|
foreach (var w in warnings)
|
|
{
|
|
i++;
|
|
var name = GetText(strs.warned_on_by(w.DateAdded?.ToString("dd.MM.yyy"),
|
|
w.DateAdded?.ToString("HH:mm"),
|
|
w.Moderator));
|
|
|
|
if (w.Forgiven)
|
|
name = $"{Format.Strikethrough(name)} {GetText(strs.warn_cleared_by(w.ForgivenBy))}";
|
|
|
|
|
|
embed.AddField($"#`{i}` " + name,
|
|
Format.Code(GetText(strs.warn_weight(w.Weight))) + '\n' + w.Reason.TrimTo(1000));
|
|
}
|
|
}
|
|
|
|
return embed;
|
|
})
|
|
.SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
public async Task WarnlogAll(int page = 1)
|
|
{
|
|
if (--page < 0)
|
|
return;
|
|
var allWarnings = _service.WarnlogAll(ctx.Guild.Id);
|
|
|
|
await Response()
|
|
.Paginated()
|
|
.Items(allWarnings)
|
|
.PageSize(15)
|
|
.CurrentPage(page)
|
|
.Page((warnings, _) =>
|
|
{
|
|
var ws = warnings
|
|
.Select(x =>
|
|
{
|
|
var all = x.Count();
|
|
var forgiven = x.Count(y => y.Forgiven);
|
|
var total = all - forgiven;
|
|
var usr = ((SocketGuild)ctx.Guild).GetUser(x.Key);
|
|
return (usr?.ToString() ?? x.Key.ToString())
|
|
+ $" | {total} ({all} - {forgiven})";
|
|
});
|
|
|
|
return CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle(GetText(strs.warnings_list))
|
|
.WithDescription(string.Join("\n", ws));
|
|
})
|
|
.SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
public Task WarnDelete(IGuildUser user, int index)
|
|
=> WarnDelete(user.Id, index);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.Administrator)]
|
|
public async Task WarnDelete(ulong userId, int index)
|
|
{
|
|
if (--index < 0)
|
|
return;
|
|
|
|
var warn = await _service.WarnDelete(ctx.Guild.Id, userId, index);
|
|
|
|
if (warn is null)
|
|
{
|
|
await Response().Error(strs.warning_not_found).SendAsync();
|
|
return;
|
|
}
|
|
|
|
await Response().Confirm(strs.warning_deleted(Format.Bold(index.ToString()))).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
public Task Warnclear(IGuildUser user, int index = 0)
|
|
=> Warnclear(user.Id, index);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
public async Task Warnclear(ulong userId, int index = 0)
|
|
{
|
|
if (index < 0)
|
|
return;
|
|
|
|
var success = await _service.WarnClearAsync(ctx.Guild.Id, userId, index, ctx.User.ToString());
|
|
var userStr = Format.Bold((ctx.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString());
|
|
if (index == 0)
|
|
await Response().Error(strs.warnings_cleared(userStr)).SendAsync();
|
|
else
|
|
{
|
|
if (success)
|
|
await Response().Confirm(strs.warning_cleared(Format.Bold(index.ToString()), userStr)).SendAsync();
|
|
else
|
|
await Response().Error(strs.warning_clear_fail).SendAsync();
|
|
}
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[Priority(1)]
|
|
public async Task WarnPunish(
|
|
int number,
|
|
AddRole _,
|
|
IRole role,
|
|
StoopidTime time = null)
|
|
{
|
|
var punish = PunishmentAction.AddRole;
|
|
|
|
if (ctx.Guild.OwnerId != ctx.User.Id
|
|
&& role.Position >= ((IGuildUser)ctx.User).GetRoles().Max(x => x.Position))
|
|
{
|
|
await Response().Error(strs.role_too_high).SendAsync();
|
|
return;
|
|
}
|
|
|
|
var success = await _service.WarnPunish(ctx.Guild.Id, number, punish, time, role);
|
|
|
|
if (!success)
|
|
return;
|
|
|
|
if (time is null)
|
|
{
|
|
await Response()
|
|
.Confirm(strs.warn_punish_set(Format.Bold(punish.ToString()),
|
|
Format.Bold(number.ToString())))
|
|
.SendAsync();
|
|
}
|
|
else
|
|
{
|
|
await Response()
|
|
.Confirm(strs.warn_punish_set_timed(Format.Bold(punish.ToString()),
|
|
Format.Bold(number.ToString()),
|
|
Format.Bold(time.Input)))
|
|
.SendAsync();
|
|
}
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
public async Task WarnPunish(int number, PunishmentAction punish, StoopidTime time = null)
|
|
{
|
|
// this should never happen. Addrole has its own method with higher priority
|
|
// also disallow warn punishment for getting warned
|
|
if (punish is PunishmentAction.AddRole or PunishmentAction.Warn)
|
|
return;
|
|
|
|
// you must specify the time for timeout
|
|
if (punish is PunishmentAction.TimeOut && time is null)
|
|
return;
|
|
|
|
var success = await _service.WarnPunish(ctx.Guild.Id, number, punish, time);
|
|
|
|
if (!success)
|
|
return;
|
|
|
|
if (time is null)
|
|
{
|
|
await Response()
|
|
.Confirm(strs.warn_punish_set(Format.Bold(punish.ToString()),
|
|
Format.Bold(number.ToString())))
|
|
.SendAsync();
|
|
}
|
|
else
|
|
{
|
|
await Response()
|
|
.Confirm(strs.warn_punish_set_timed(Format.Bold(punish.ToString()),
|
|
Format.Bold(number.ToString()),
|
|
Format.Bold(time.Input)))
|
|
.SendAsync();
|
|
}
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
public async Task WarnPunish(int number)
|
|
{
|
|
if (!await _service.WarnPunishRemove(ctx.Guild.Id, number))
|
|
return;
|
|
|
|
await Response().Confirm(strs.warn_punish_rem(Format.Bold(number.ToString()))).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task WarnPunishList()
|
|
{
|
|
var ps = await _service.WarnPunishList(ctx.Guild.Id);
|
|
|
|
string list;
|
|
if (ps.Any())
|
|
{
|
|
list = string.Join("\n",
|
|
ps.Select(x
|
|
=> $"{x.Count} -> {x.Punishment} {(x.Punishment == PunishmentAction.AddRole ? $"<@&{x.RoleId}>" : "")} {(x.Time <= 0 ? "" : x.Time + "m")} "));
|
|
}
|
|
else
|
|
list = GetText(strs.warnpl_none);
|
|
|
|
await Response().Confirm(GetText(strs.warn_punish_list), list).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[Priority(1)]
|
|
public Task Ban(StoopidTime time, IUser user, [Leftover] string msg = null)
|
|
=> Ban(time, user.Id, msg);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[Priority(0)]
|
|
public async Task Ban(StoopidTime time, ulong userId, [Leftover] string msg = null)
|
|
{
|
|
if (time.Time > TimeSpan.FromDays(49))
|
|
return;
|
|
|
|
var guildUser = await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id, userId);
|
|
|
|
|
|
if (guildUser is not null && !await CheckRoleHierarchy(guildUser))
|
|
return;
|
|
|
|
var dmFailed = false;
|
|
|
|
if (guildUser is not null)
|
|
{
|
|
try
|
|
{
|
|
var defaultMessage = GetText(strs.bandm(Format.Bold(ctx.Guild.Name), msg));
|
|
var smartText =
|
|
await _service.GetBanUserDmEmbed(Context, guildUser, defaultMessage, msg, time.Time);
|
|
if (smartText is not null)
|
|
await Response().User(guildUser).Text(smartText).SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
dmFailed = true;
|
|
}
|
|
}
|
|
|
|
var user = await ctx.Client.GetUserAsync(userId);
|
|
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
|
await _mute.TimedBan(ctx.Guild, userId, time.Time, (ctx.User + " | " + msg).TrimTo(512), banPrune);
|
|
var toSend = CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle("⛔️ " + GetText(strs.banned_user))
|
|
.AddField(GetText(strs.username), user?.ToString() ?? userId.ToString(), true)
|
|
.AddField("ID", userId.ToString(), true)
|
|
.AddField(GetText(strs.duration),
|
|
time.Time.ToPrettyStringHm(),
|
|
true);
|
|
|
|
if (dmFailed)
|
|
toSend.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
|
|
|
|
await Response().Embed(toSend).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[Priority(0)]
|
|
public async Task Ban(ulong userId, [Leftover] string msg = null)
|
|
{
|
|
var user = await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id, userId);
|
|
if (user is null)
|
|
{
|
|
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
|
await ctx.Guild.AddBanAsync(userId, banPrune, (ctx.User + " | " + msg).TrimTo(512));
|
|
|
|
await Response()
|
|
.Embed(CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle("⛔️ " + GetText(strs.banned_user))
|
|
.AddField("ID", userId.ToString(), true))
|
|
.SendAsync();
|
|
}
|
|
else
|
|
await Ban(user, msg);
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[Priority(2)]
|
|
public async Task Ban(IGuildUser user, [Leftover] string msg = null)
|
|
{
|
|
if (!await CheckRoleHierarchy(user))
|
|
return;
|
|
|
|
var dmFailed = false;
|
|
|
|
try
|
|
{
|
|
var defaultMessage = GetText(strs.bandm(Format.Bold(ctx.Guild.Name), msg));
|
|
var embed = await _service.GetBanUserDmEmbed(Context, user, defaultMessage, msg, null);
|
|
if (embed is not null)
|
|
await Response().User(user).Text(embed).SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
dmFailed = true;
|
|
}
|
|
|
|
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
|
await ctx.Guild.AddBanAsync(user, banPrune, (ctx.User + " | " + msg).TrimTo(512));
|
|
|
|
var toSend = CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle("⛔️ " + GetText(strs.banned_user))
|
|
.AddField(GetText(strs.username), user.ToString(), true)
|
|
.AddField("ID", user.Id.ToString(), true);
|
|
|
|
if (dmFailed)
|
|
toSend.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
|
|
|
|
await Response().Embed(toSend).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
public async Task BanPrune(int days)
|
|
{
|
|
if (days < 0 || days > 7)
|
|
{
|
|
await Response().Error(strs.invalid_input).SendAsync();
|
|
return;
|
|
}
|
|
|
|
await _service.SetBanPruneAsync(ctx.Guild.Id, days);
|
|
|
|
if (days == 0)
|
|
await Response().Confirm(strs.ban_prune_disabled).SendAsync();
|
|
else
|
|
await Response().Confirm(strs.ban_prune(days)).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
public async Task BanMessage([Leftover] string message = null)
|
|
{
|
|
if (message is null)
|
|
{
|
|
var template = _service.GetBanTemplate(ctx.Guild.Id);
|
|
if (template is null)
|
|
{
|
|
await Response().Confirm(strs.banmsg_default).SendAsync();
|
|
return;
|
|
}
|
|
|
|
await Response().Confirm(template).SendAsync();
|
|
return;
|
|
}
|
|
|
|
_service.SetBanTemplate(ctx.Guild.Id, message);
|
|
await ctx.OkAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
public async Task BanMsgReset()
|
|
{
|
|
_service.SetBanTemplate(ctx.Guild.Id, null);
|
|
await ctx.OkAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[Priority(0)]
|
|
public Task BanMessageTest([Leftover] string reason = null)
|
|
=> InternalBanMessageTest(reason, null);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[Priority(1)]
|
|
public Task BanMessageTest(StoopidTime duration, [Leftover] string reason = null)
|
|
=> InternalBanMessageTest(reason, duration.Time);
|
|
|
|
private async Task InternalBanMessageTest(string reason, TimeSpan? duration)
|
|
{
|
|
var defaultMessage = GetText(strs.bandm(Format.Bold(ctx.Guild.Name), reason));
|
|
var smartText = await _service.GetBanUserDmEmbed(Context,
|
|
(IGuildUser)ctx.User,
|
|
defaultMessage,
|
|
reason,
|
|
duration);
|
|
|
|
if (smartText is null)
|
|
await Response().Confirm(strs.banmsg_disabled).SendAsync();
|
|
else
|
|
{
|
|
try
|
|
{
|
|
await Response().User(ctx.User).Text(smartText).SendAsync();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
await Response().Error(strs.unable_to_dm_user).SendAsync();
|
|
return;
|
|
}
|
|
|
|
await ctx.OkAsync();
|
|
}
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
public async Task Unban([Leftover] string user)
|
|
{
|
|
var bans = await ctx.Guild.GetBansAsync().FlattenAsync();
|
|
|
|
var bun = bans.FirstOrDefault(x => x.User.ToString()!.ToLowerInvariant() == user.ToLowerInvariant());
|
|
|
|
if (bun is null)
|
|
{
|
|
await Response().Error(strs.user_not_found).SendAsync();
|
|
return;
|
|
}
|
|
|
|
await UnbanInternal(bun.User);
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
public async Task Unban(ulong userId)
|
|
{
|
|
var bun = await ctx.Guild.GetBanAsync(userId);
|
|
|
|
if (bun is null)
|
|
{
|
|
await Response().Error(strs.user_not_found).SendAsync();
|
|
return;
|
|
}
|
|
|
|
await UnbanInternal(bun.User);
|
|
}
|
|
|
|
private async Task UnbanInternal(IUser user)
|
|
{
|
|
await ctx.Guild.RemoveBanAsync(user);
|
|
|
|
await Response().Confirm(strs.unbanned_user(Format.Bold(user.ToString()))).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.KickMembers | GuildPerm.ManageMessages)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
public Task Softban(IGuildUser user, [Leftover] string msg = null)
|
|
=> SoftbanInternal(user, msg);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.KickMembers | GuildPerm.ManageMessages)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
public async Task Softban(ulong userId, [Leftover] string msg = null)
|
|
{
|
|
var user = await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id, userId);
|
|
if (user is null)
|
|
return;
|
|
|
|
await SoftbanInternal(user, msg);
|
|
}
|
|
|
|
private async Task SoftbanInternal(IGuildUser user, [Leftover] string msg = null)
|
|
{
|
|
if (!await CheckRoleHierarchy(user))
|
|
return;
|
|
|
|
var dmFailed = false;
|
|
|
|
try
|
|
{
|
|
await Response()
|
|
.Channel(await user.CreateDMChannelAsync())
|
|
.Error(strs.sbdm(Format.Bold(ctx.Guild.Name), msg))
|
|
.SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
dmFailed = true;
|
|
}
|
|
|
|
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
|
await ctx.Guild.AddBanAsync(user, banPrune, ("Softban | " + ctx.User + " | " + msg).TrimTo(512));
|
|
try
|
|
{ await ctx.Guild.RemoveBanAsync(user); }
|
|
catch { await ctx.Guild.RemoveBanAsync(user); }
|
|
|
|
var toSend = CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle("☣ " + GetText(strs.sb_user))
|
|
.AddField(GetText(strs.username), user.ToString(), true)
|
|
.AddField("ID", user.Id.ToString(), true);
|
|
|
|
if (dmFailed)
|
|
toSend.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
|
|
|
|
await Response().Embed(toSend).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.KickMembers)]
|
|
[BotPerm(GuildPerm.KickMembers)]
|
|
[Priority(1)]
|
|
public Task Kick(IGuildUser user, [Leftover] string msg = null)
|
|
=> KickInternal(user, msg);
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.KickMembers)]
|
|
[BotPerm(GuildPerm.KickMembers)]
|
|
[Priority(0)]
|
|
public async Task Kick(ulong userId, [Leftover] string msg = null)
|
|
{
|
|
var user = await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id, userId);
|
|
if (user is null)
|
|
return;
|
|
|
|
await KickInternal(user, msg);
|
|
}
|
|
|
|
private async Task KickInternal(IGuildUser user, string msg = null)
|
|
{
|
|
if (!await CheckRoleHierarchy(user))
|
|
return;
|
|
|
|
var dmFailed = false;
|
|
|
|
try
|
|
{
|
|
await Response()
|
|
.Channel(await user.CreateDMChannelAsync())
|
|
.Error(GetText(strs.kickdm(Format.Bold(ctx.Guild.Name), msg)))
|
|
.SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
dmFailed = true;
|
|
}
|
|
|
|
await user.KickAsync((ctx.User + " | " + msg).TrimTo(512));
|
|
|
|
var toSend = CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle(GetText(strs.kicked_user))
|
|
.AddField(GetText(strs.username), user.ToString(), true)
|
|
.AddField("ID", user.Id.ToString(), true);
|
|
|
|
if (dmFailed)
|
|
toSend.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
|
|
|
|
await Response().Embed(toSend).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.ModerateMembers)]
|
|
[BotPerm(GuildPerm.ModerateMembers)]
|
|
[Priority(2)]
|
|
public async Task Timeout(IUser globalUser, StoopidTime time, [Leftover] string msg = null)
|
|
{
|
|
var user = await ctx.Guild.GetUserAsync(globalUser.Id);
|
|
|
|
if (user is null)
|
|
return;
|
|
|
|
if (!await CheckRoleHierarchy(user))
|
|
return;
|
|
|
|
var dmFailed = false;
|
|
|
|
try
|
|
{
|
|
var dmMessage = GetText(strs.timeoutdm(Format.Bold(ctx.Guild.Name), msg));
|
|
await _sender.Response(user)
|
|
.Embed(CreateEmbed()
|
|
.WithPendingColor()
|
|
.WithDescription(dmMessage))
|
|
.SendAsync();
|
|
}
|
|
catch
|
|
{
|
|
dmFailed = true;
|
|
}
|
|
|
|
await user.SetTimeOutAsync(time.Time);
|
|
|
|
var toSend = CreateEmbed()
|
|
.WithOkColor()
|
|
.WithTitle("⏳ " + GetText(strs.timedout_user))
|
|
.AddField(GetText(strs.username), user.ToString(), true)
|
|
.AddField("ID", user.Id.ToString(), true);
|
|
|
|
if (dmFailed)
|
|
toSend.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
|
|
|
|
await Response().Embed(toSend).SendAsync();
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[Ratelimit(30)]
|
|
public async Task MassBan(params string[] userStrings)
|
|
{
|
|
if (userStrings.Length == 0)
|
|
return;
|
|
|
|
var missing = new List<string>();
|
|
var banning = new HashSet<IUser>();
|
|
|
|
await ctx.Channel.TriggerTypingAsync();
|
|
foreach (var userStr in userStrings)
|
|
{
|
|
if (ulong.TryParse(userStr, out var userId))
|
|
{
|
|
IUser user = await ctx.Guild.GetUserAsync(userId)
|
|
?? await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id,
|
|
userId);
|
|
|
|
if (user is null)
|
|
{
|
|
// if IGuildUser is null, try to get IUser
|
|
user = await ((DiscordSocketClient)Context.Client).Rest.GetUserAsync(userId);
|
|
|
|
// only add to missing if *still* null
|
|
if (user is null)
|
|
{
|
|
missing.Add(userStr);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//Hierachy checks only if the user is in the guild
|
|
if (user is IGuildUser gu && !await CheckRoleHierarchy(gu))
|
|
return;
|
|
|
|
banning.Add(user);
|
|
}
|
|
else
|
|
missing.Add(userStr);
|
|
}
|
|
|
|
var missStr = string.Join("\n", missing);
|
|
if (string.IsNullOrWhiteSpace(missStr))
|
|
missStr = "-";
|
|
|
|
var toSend = CreateEmbed()
|
|
.WithDescription(GetText(strs.mass_ban_in_progress(banning.Count)))
|
|
.AddField(GetText(strs.invalid(missing.Count)), missStr)
|
|
.WithPendingColor();
|
|
|
|
var banningMessage = await Response().Embed(toSend).SendAsync();
|
|
|
|
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
|
foreach (var toBan in banning)
|
|
{
|
|
try
|
|
{
|
|
await ctx.Guild.AddBanAsync(toBan.Id, banPrune, $"{ctx.User} | Massban");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Warning(ex, "Error banning {User} user in {GuildId} server", toBan.Id, ctx.Guild.Id);
|
|
}
|
|
}
|
|
|
|
await banningMessage.ModifyAsync(x => x.Embed = CreateEmbed()
|
|
.WithDescription(
|
|
GetText(strs.mass_ban_completed(
|
|
banning.Count())))
|
|
.AddField(GetText(strs.invalid(missing.Count)),
|
|
missStr)
|
|
.WithOkColor()
|
|
.Build());
|
|
}
|
|
|
|
[Cmd]
|
|
[RequireContext(ContextType.Guild)]
|
|
[UserPerm(GuildPerm.BanMembers)]
|
|
[BotPerm(GuildPerm.BanMembers)]
|
|
[OwnerOnly]
|
|
public async Task MassKill([Leftover] string people)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(people))
|
|
return;
|
|
|
|
var (bans, missing) = _service.MassKill((SocketGuild)ctx.Guild, people);
|
|
|
|
var missStr = string.Join("\n", missing);
|
|
if (string.IsNullOrWhiteSpace(missStr))
|
|
missStr = "-";
|
|
|
|
//send a message but don't wait for it
|
|
var banningMessageTask = Response()
|
|
.Embed(CreateEmbed()
|
|
.WithDescription(
|
|
GetText(strs.mass_kill_in_progress(bans.Count())))
|
|
.AddField(GetText(strs.invalid(missing)), missStr)
|
|
.WithPendingColor())
|
|
.SendAsync();
|
|
|
|
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
|
//do the banning
|
|
await Task.WhenAll(bans.Where(x => x.Id.HasValue)
|
|
.Select(x => ctx.Guild.AddBanAsync(x.Id.Value,
|
|
banPrune,
|
|
x.Reason,
|
|
new()
|
|
{
|
|
RetryMode = RetryMode.AlwaysRetry
|
|
})));
|
|
|
|
//wait for the message and edit it
|
|
var banningMessage = await banningMessageTask;
|
|
|
|
await banningMessage.ModifyAsync(x => x.Embed = CreateEmbed()
|
|
.WithDescription(
|
|
GetText(strs.mass_kill_completed(bans.Count())))
|
|
.AddField(GetText(strs.invalid(missing)), missStr)
|
|
.WithOkColor()
|
|
.Build());
|
|
}
|
|
|
|
public class WarnExpireOptions : IEllieCommandOptions
|
|
{
|
|
[Option('d', "delete", Default = false, HelpText = "Delete warnings instead of clearing them.")]
|
|
public bool Delete { get; set; } = false;
|
|
|
|
public void NormalizeOptions()
|
|
{
|
|
}
|
|
}
|
|
}
|
|
} |