Added many more braces for multiline if's, Improved .crypto command quite a bit and applied locale-specific format

This commit is contained in:
Kwoth
2022-02-04 06:00:17 +01:00
parent f77f2f433f
commit eda38e64d1
129 changed files with 635 additions and 233 deletions

View File

@@ -314,9 +314,7 @@ public partial class Administration : NadekoModule<AdministrationService>
}
if (time is null)
{
await msg.DeleteAsync();
}
else if (time.Time <= TimeSpan.FromDays(7))
{
_ = Task.Run(async () =>

View File

@@ -115,13 +115,9 @@ public class AdministrationService : INService
{
}
else if (newState == Administration.State.Enable)
{
DeleteMessagesOnCommandChannels[chId] = true;
}
else
{
DeleteMessagesOnCommandChannels.TryRemove(chId, out _);
}
}
public async Task DeafenUsers(bool value, params IGuildUser[] users)

View File

@@ -25,9 +25,7 @@ public partial class Administration
var id = _service.ToggleGameVoiceChannel(ctx.Guild.Id, vch.Id);
if (id is null)
{
await ReplyConfirmLocalizedAsync(strs.gvc_disabled);
}
else
{
_service.GameVoiceChannels.Add(vch.Id);

View File

@@ -42,8 +42,10 @@ public class GameVoiceChannelService : INService
{
if (activity is { Type: ActivityType.Playing })
//trigger gvc
{
if (await TriggerGvc(newUser, activity.Name))
return;
}
}
}
catch (Exception ex)

View File

@@ -141,9 +141,7 @@ public class GreetService : INService, IReadyExecutor
}
}
else
{
await ByeUsers(conf, channel, new[] { user });
}
}
catch
{
@@ -255,10 +253,12 @@ public class GreetService : INService, IReadyExecutor
text = rep.Replace(text);
if (text is SmartPlainText pt)
{
text = new SmartEmbedText()
{
PlainText = pt.Text
};
}
((SmartEmbedText)text).Footer = new()
{
@@ -308,9 +308,7 @@ public class GreetService : INService, IReadyExecutor
}
}
else
{
await GreetUsers(conf, channel, new[] { user });
}
}
}

View File

@@ -75,9 +75,7 @@ public sealed class ImageOnlyChannelService : IEarlyBehavior
var newState = false;
using var uow = _db.GetDbContext();
if (forceDisable || (_enabledOn.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId)))
{
uow.ImageOnlyChannels.Delete(x => x.ChannelId == channelId);
}
else
{
uow.ImageOnlyChannels.Add(new()

View File

@@ -66,9 +66,7 @@ public class MuteService : INService
{
TimeSpan after;
if (x.UnmuteAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
{
after = TimeSpan.FromMinutes(2);
}
else
{
var unmute = x.UnmuteAt - DateTime.UtcNow;
@@ -82,9 +80,7 @@ public class MuteService : INService
{
TimeSpan after;
if (x.UnbanAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
{
after = TimeSpan.FromMinutes(2);
}
else
{
var unban = x.UnbanAt - DateTime.UtcNow;
@@ -98,9 +94,7 @@ public class MuteService : INService
{
TimeSpan after;
if (x.UnbanAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
{
after = TimeSpan.FromMinutes(2);
}
else
{
var unban = x.UnbanAt - DateTime.UtcNow;
@@ -306,6 +300,7 @@ public class MuteService : INService
var muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName);
if (muteRole is null)
//if it doesn't exist, create it
{
try { muteRole = await guild.CreateRoleAsync(muteRoleName, isMentionable: false); }
catch
{
@@ -313,6 +308,7 @@ public class MuteService : INService
muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName)
?? await guild.CreateRoleAsync(defaultMuteRoleName, isMentionable: false);
}
}
foreach (var toOverwrite in await guild.GetTextChannelsAsync())
{
@@ -414,6 +410,7 @@ public class MuteService : INService
var toAdd = new Timer(async _ =>
{
if (type == TimerType.Ban)
{
try
{
RemoveTimerFromDb(guildId, userId, type);
@@ -426,7 +423,9 @@ public class MuteService : INService
{
Log.Warning(ex, "Couldn't unban user {UserId} in guild {GuildId}", userId, guildId);
}
}
else if (type == TimerType.AddRole)
{
try
{
if (roleId is null)
@@ -444,7 +443,9 @@ public class MuteService : INService
{
Log.Warning(ex, "Couldn't remove role from user {UserId} in guild {GuildId}", userId, guildId);
}
}
else
{
try
{
// unmute the user, this will also remove the timer from the db
@@ -455,6 +456,7 @@ public class MuteService : INService
RemoveTimerFromDb(guildId, userId, type); // if unmute errored, just remove unmute from db
Log.Warning(ex, "Couldn't unmute user {UserId} in guild {GuildId}", userId, guildId);
}
}
},
null,
after,

View File

@@ -67,8 +67,10 @@ public partial class Administration
if (thisPageOverrides.Count == 0)
eb.WithDescription(GetText(strs.perm_override_page_none));
else
{
eb.WithDescription(thisPageOverrides.Select(ov => $"{ov.Command} => {ov.Perm.ToString()}")
.Join("\n"));
}
return eb;
},

View File

@@ -56,6 +56,7 @@ public class DiscordPermOverrideService : INService, ILateBlocker
.FirstOrDefaultAsync(x => x.GuildId == guildId && commandName == x.Command);
if (over is null)
{
uow.Set<DiscordPermOverride>()
.Add(over = new()
{
@@ -63,6 +64,7 @@ public class DiscordPermOverrideService : INService, ILateBlocker
Perm = perm,
GuildId = guildId
});
}
else
over.Perm = perm;

View File

@@ -34,9 +34,7 @@ public partial class Administration
var statuses = _service.GetRotatingStatuses();
if (!statuses.Any())
{
await ReplyErrorLocalizedAsync(strs.ropl_not_set);
}
else
{
var i = 1;

View File

@@ -114,8 +114,10 @@ public partial class Administration
}
if (punishTime is not null)
{
if (!_service.IsDurationAllowed(action))
await ReplyErrorLocalizedAsync(strs.prot_cant_use_time);
}
var time = (int?)punishTime?.Time.TotalMinutes ?? 0;
if (time is < 0 or > 60 * 24)
@@ -176,8 +178,10 @@ public partial class Administration
return;
if (timeData is not null)
{
if (!_service.IsDurationAllowed(action))
await ReplyErrorLocalizedAsync(strs.prot_cant_use_time);
}
var time = (int?)timeData?.Time.TotalMinutes ?? 0;
if (time is < 0 or > 60 * 24)

View File

@@ -136,10 +136,12 @@ public class ProtectionService : INService
}
if (spam is not null)
{
_antiSpamGuilds[gc.GuildId] = new()
{
AntiSpamSettings = spam
};
}
var alt = gc.AntiAltSetting;
if (alt is not null)
@@ -160,6 +162,7 @@ public class ProtectionService : INService
_ = Task.Run(async () =>
{
if (maybeAlts is { } alts)
{
if (user.CreatedAt != default)
{
var diff = DateTime.UtcNow - user.CreatedAt.UtcDateTime;
@@ -176,6 +179,7 @@ public class ProtectionService : INService
return;
}
}
}
try
{
@@ -234,6 +238,7 @@ public class ProtectionService : INService
});
if (stats.Count >= spamSettings.AntiSpamSettings.MessageThreshold)
{
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
{
var settings = spamSettings.AntiSpamSettings;
@@ -243,6 +248,7 @@ public class ProtectionService : INService
settings.RoleId,
(IGuildUser)msg.Author);
}
}
}
catch
{
@@ -392,9 +398,7 @@ public class ProtectionService : INService
gc.AntiSpamSetting.RoleId = stats.AntiSpamSettings.RoleId;
}
else
{
gc.AntiSpamSetting = stats.AntiSpamSettings;
}
await uow.SaveChangesAsync();
return stats;

View File

@@ -71,13 +71,17 @@ public partial class Administration
count = 1000;
if (parameter is "-s" or "--safe")
{
await _service.PruneWhere((ITextChannel)ctx.Channel,
count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks && !m.IsPinned);
}
else
{
await _service.PruneWhere((ITextChannel)ctx.Channel,
count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks);
}
}
}
}

View File

@@ -52,10 +52,12 @@ public class PruneService : INService
//100 messages, Maybe this needs to be reduced by msgs.Length instead of 100
amount -= 50;
if (amount > 0)
{
msgs = (await channel.GetMessagesAsync(lastMessage, Direction.Before, 50).FlattenAsync())
.Where(predicate)
.Take(amount)
.ToArray();
}
}
}
catch

View File

@@ -143,9 +143,7 @@ public partial class Administration
{
var embed = _eb.Create().WithOkColor();
if (!_service.Get(ctx.Guild.Id, out var rrs) || !rrs.Any())
{
embed.WithDescription(GetText(strs.no_reaction_roles));
}
else
{
var g = (SocketGuild)ctx.Guild;

View File

@@ -101,9 +101,7 @@ public partial class Administration
var scmds = _service.GetStartupCommands().Skip(page * 5).Take(5).ToList();
if (scmds.Count == 0)
{
await ReplyErrorLocalizedAsync(strs.startcmdlist_none);
}
else
{
var i = 0;
@@ -128,9 +126,7 @@ public partial class Administration
var scmds = _service.GetAutoCommands().Skip(page * 5).Take(5).ToList();
if (!scmds.Any())
{
await ReplyErrorLocalizedAsync(strs.autocmdlist_none);
}
else
{
var i = 0;

View File

@@ -190,12 +190,16 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
.ToImmutableDictionary();
if (!ownerChannels.Any())
{
Log.Warning(
"No owner channels created! Make sure you've specified the correct OwnerId in the creds.yml file and invited the bot to a Discord server");
}
else
{
Log.Information("Created {OwnerChannelCount} out of {TotalOwnerChannelCount} owner message channels",
ownerChannels.Count,
_creds.OwnerIds.Count);
}
}
public Task LeaveGuild(string guildStr)
@@ -214,8 +218,10 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
var toSend = msg.Content;
if (msg.Attachments.Count > 0)
{
toSend += $"\n\n{Format.Code(attachamentsTxt)}:\n"
+ string.Join("\n", msg.Attachments.Select(a => a.ProxyUrl));
}
if (bs.ForwardToAllOwners)
{
@@ -237,6 +243,7 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
{
var firstOwnerChannel = ownerChannels.Values.First();
if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
{
try
{
await firstOwnerChannel.SendConfirmAsync(_eb, title, toSend);
@@ -245,6 +252,7 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
{
// ignored
}
}
}
}
}
@@ -273,8 +281,11 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
{
uow.Remove(cmd);
if (autoCommands.TryGetValue(cmd.GuildId, out var autos))
{
if (autos.TryRemove(cmd.Id, out var timer))
timer.Change(Timeout.Infinite, Timeout.Infinite);
}
uow.SaveChanges();
return true;
}

View File

@@ -45,8 +45,10 @@ public partial class Administration
var succ = _service.AddNew(ctx.Guild.Id, role, group);
if (succ)
{
await ReplyConfirmLocalizedAsync(strs.role_added(Format.Bold(role.Name),
Format.Bold(group.ToString())));
Format.Bold(@group.ToString())));
}
else
await ReplyErrorLocalizedAsync(strs.role_in_list(Format.Bold(role.Name)));
}
@@ -61,8 +63,10 @@ public partial class Administration
var set = await _service.SetNameAsync(ctx.Guild.Id, group, name);
if (set)
{
await ReplyConfirmLocalizedAsync(
strs.group_name_added(Format.Bold(group.ToString()), Format.Bold(name)));
strs.group_name_added(Format.Bold(@group.ToString()), Format.Bold(name)));
}
else
await ReplyConfirmLocalizedAsync(strs.group_name_removed(Format.Bold(group.ToString())));
}

View File

@@ -85,6 +85,7 @@ public class SelfAssignedRolesService : INService
{
var sameRole = guildUser.Guild.GetRole(roleId);
if (sameRole is not null)
{
try
{
await guildUser.RemoveRoleAsync(sameRole);
@@ -94,6 +95,7 @@ public class SelfAssignedRolesService : INService
{
// ignored
}
}
}
}
@@ -192,9 +194,7 @@ public class SelfAssignedRolesService : INService
uow.SaveChanges();
}
else
{
return false;
}
return true;
}

View File

@@ -21,7 +21,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private readonly GuildTimezoneService _tz;
private readonly IEmbedBuilderService _eb;
private readonly IMemoryCache _memoryCache;
private readonly ConcurrentHashSet<ulong> _ignoreMessageIds = new();
public LogCommandService(
@@ -89,9 +89,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
{
using var timer = new PeriodicTimer(TimeSpan.FromHours(1));
while (await timer.WaitForNextTickAsync())
{
_ignoreMessageIds.Clear();
}
}
private async Task PresenceUpdateTask()
@@ -108,7 +106,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
{
if (!((SocketGuild)key.Guild).CurrentUser.GetPermissions(key).SendMessages)
return Task.CompletedTask;
if (PresenceUpdates.TryRemove(key, out var msgs))
{
var title = GetText(key.Guild, strs.presence_updates);
@@ -234,9 +232,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
embed.WithImageUrl(aav.ToString());
}
else
{
return;
}
await logChannel.EmbedAsync(embed);
}
@@ -656,14 +652,18 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
var afterTextChannel = cafter as ITextChannel;
if (before.Name != after.Name)
{
embed.WithTitle(" " + GetText(logChannel.Guild, strs.ch_name_change))
.WithDescription($"{after} | {after.Id}")
.AddField(GetText(logChannel.Guild, strs.ch_old_name), before.Name);
}
else if (beforeTextChannel?.Topic != afterTextChannel?.Topic)
{
embed.WithTitle(" " + GetText(logChannel.Guild, strs.ch_topic_change))
.WithDescription($"{after} | {after.Id}")
.AddField(GetText(logChannel.Guild, strs.old_topic), beforeTextChannel?.Topic ?? "-")
.AddField(GetText(logChannel.Guild, strs.new_topic), afterTextChannel?.Topic ?? "-");
}
else
return;
@@ -778,26 +778,33 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
var str = string.Empty;
if (beforeVch?.Guild == afterVch?.Guild)
{
str = "🎙"
+ Format.Code(PrettyCurrentTime(usr.Guild))
+ GetText(logChannel.Guild,
strs.user_vmoved("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
Format.Bold(beforeVch?.Name ?? ""),
Format.Bold(afterVch?.Name ?? "")));
}
else if (beforeVch is null)
{
str = "🎙"
+ Format.Code(PrettyCurrentTime(usr.Guild))
+ GetText(logChannel.Guild,
strs.user_vjoined("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
Format.Bold(afterVch?.Name ?? "")));
}
else if (afterVch is null)
{
str = "🎙"
+ Format.Code(PrettyCurrentTime(usr.Guild))
+ GetText(logChannel.Guild,
strs.user_vleft("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
Format.Bold(beforeVch.Name ?? "")));
}
if (!string.IsNullOrWhiteSpace(str))
{
PresenceUpdates.AddOrUpdate(logChannel,
new List<string>
{
@@ -808,6 +815,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
list.Add(str);
return list;
});
}
}
catch
{
@@ -1001,8 +1009,10 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
.AddField("Id", msg.Id.ToString())
.WithFooter(CurrentTime(channel.Guild));
if (msg.Attachments.Any())
{
embed.AddField(GetText(logChannel.Guild, strs.attachments),
string.Join(", ", msg.Attachments.Select(a => a.Url)));
}
await logChannel.EmbedAsync(embed);
}

View File

@@ -58,11 +58,15 @@ public partial class Administration
var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.Channel);
if (!removed)
{
await ReplyConfirmLocalizedAsync(
strs.log_ignore_chan(Format.Bold(target.Mention + "(" + target.Id + ")")));
}
else
{
await ReplyConfirmLocalizedAsync(
strs.log_not_ignore_chan(Format.Bold(target.Mention + "(" + target.Id + ")")));
}
}
[Cmd]
@@ -74,11 +78,15 @@ public partial class Administration
var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.User);
if (!removed)
{
await ReplyConfirmLocalizedAsync(
strs.log_ignore_user(Format.Bold(target.Mention + "(" + target.Id + ")")));
}
else
{
await ReplyConfirmLocalizedAsync(
strs.log_not_ignore_user(Format.Bold(target.Mention + "(" + target.Id + ")")));
}
}
[Cmd]

View File

@@ -100,8 +100,10 @@ public partial class Administration
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));
@@ -204,9 +206,7 @@ public partial class Administration
var embed = _eb.Create().WithOkColor().WithTitle(GetText(strs.warnlog_for(user)));
if (!warnings.Any())
{
embed.WithDescription(GetText(strs.warnings_none));
}
else
{
var descText = GetText(strs.warn_count(
@@ -288,9 +288,7 @@ public partial class Administration
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 ReplyErrorLocalizedAsync(strs.warnings_cleared(userStr));
}
else
{
if (success)
@@ -325,12 +323,16 @@ public partial class Administration
return;
if (time is null)
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set(Format.Bold(punish.ToString()),
Format.Bold(number.ToString())));
}
else
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set_timed(Format.Bold(punish.ToString()),
Format.Bold(number.ToString()),
Format.Bold(time.Input)));
}
}
[Cmd]
@@ -348,12 +350,16 @@ public partial class Administration
return;
if (time is null)
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set(Format.Bold(punish.ToString()),
Format.Bold(number.ToString())));
}
else
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set_timed(Format.Bold(punish.ToString()),
Format.Bold(number.ToString()),
Format.Bold(time.Input)));
}
}
[Cmd]
@@ -375,11 +381,14 @@ public partial class Administration
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 SendConfirmAsync(GetText(strs.warn_punish_list), list);
}
@@ -401,6 +410,7 @@ public partial class Administration
var dmFailed = false;
if (guildUser is not null)
{
try
{
var defaultMessage = GetText(strs.bandm(Format.Bold(ctx.Guild.Name), msg));
@@ -412,6 +422,7 @@ public partial class Administration
{
dmFailed = true;
}
}
await _mute.TimedBan(ctx.Guild, user, time.Time, (ctx.User + " | " + msg).TrimTo(512));
var toSend = _eb.Create()
@@ -447,9 +458,7 @@ public partial class Administration
.AddField("ID", userId.ToString(), true));
}
else
{
await Ban(user, msg);
}
}
[Cmd]
@@ -545,9 +554,7 @@ public partial class Administration
var embed = _service.GetBanUserDmEmbed(Context, (IGuildUser)ctx.User, defaultMessage, reason, duration);
if (embed is null)
{
await ConfirmLocalizedAsync(strs.banmsg_disabled);
}
else
{
try
@@ -755,9 +762,7 @@ public partial class Administration
banning.Add(user);
}
else
{
missing.Add(userStr);
}
}
var missStr = string.Join("\n", missing);

View File

@@ -233,9 +233,11 @@ WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND
AND DateAdded < datetime('now', (SELECT '-' || WarnExpireHours || ' hours' FROM GuildConfigs as gc WHERE gc.GuildId = Warnings.GuildId));");
if (cleared > 0 || deleted > 0)
{
Log.Information("Cleared {ClearedWarnings} warnings and deleted {DeletedWarnings} warnings due to expiry",
cleared,
deleted);
}
}
public async Task CheckWarnExpiresAsync(ulong guildId)
@@ -248,16 +250,20 @@ WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND
var hours = $"{-config.WarnExpireHours} hours";
if (config.WarnExpireAction == WarnExpireAction.Clear)
{
await uow.Database.ExecuteSqlInterpolatedAsync($@"UPDATE warnings
SET Forgiven = 1,
ForgivenBy = 'Expiry'
WHERE GuildId={guildId}
AND Forgiven = 0
AND DateAdded < datetime('now', {hours})");
}
else if (config.WarnExpireAction == WarnExpireAction.Delete)
{
await uow.Database.ExecuteSqlInterpolatedAsync($@"DELETE FROM warnings
WHERE GuildId={guildId}
AND DateAdded < datetime('now', {hours})");
}
await uow.SaveChangesAsync();
}
@@ -436,9 +442,7 @@ WHERE GuildId={guildId}
});
}
else
{
template.Text = text;
}
uow.SaveChanges();
}
@@ -487,22 +491,26 @@ WHERE GuildId={guildId}
// if template isn't set, use the old message style
if (string.IsNullOrWhiteSpace(template))
{
template = JsonConvert.SerializeObject(new
{
color = _bcs.Data.Color.Error.PackedValue >> 8,
description = defaultMessage
});
}
// if template is set to "-" do not dm the user
else if (template == "-")
return default;
// if template is an embed, send that embed with replacements
// otherwise, treat template as a regular string with replacements
else if (!SmartText.CreateFrom(template).IsEmbed)
{
template = JsonConvert.SerializeObject(new
{
color = _bcs.Data.Color.Error.PackedValue >> 8,
description = template
});
}
var output = SmartText.CreateFrom(template);
return replacer.Replace(output);

View File

@@ -59,14 +59,14 @@ public partial class Administration
if (!roles.Any())
text = GetText(strs.no_vcroles);
else
{
text = string.Join("\n",
roles.Select(x
=> $"{Format.Bold(guild.GetVoiceChannel(x.Key)?.Name ?? x.Key.ToString())} => {x.Value}"));
}
}
else
{
text = GetText(strs.no_vcroles);
}
await ctx.Channel.EmbedAsync(_eb.Create()
.WithOkColor()