mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
Finished new response system
This commit is contained in:
@@ -32,6 +32,7 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
|
||||
- Added `.clubrename` command to uh rename your club
|
||||
- For self-hosters:
|
||||
- Added `.sqlselectcsv` which will return results in a csv file instead of an embed.
|
||||
- Added a page parameter to `.feedlist`
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -46,6 +47,7 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
|
||||
|
||||
- `.feed` should now correctly accept (and show) the message which can be passed as the third parameter
|
||||
- `.say` will now correctly report errors if the user or the bot don't have sufficent perms to send a message in the targeted channel
|
||||
- Fixed a bug in .invitelist not paginating correctly
|
||||
|
||||
### Removed
|
||||
|
||||
|
@@ -58,7 +58,7 @@ namespace NadekoBot.Tests
|
||||
aliasesPath);
|
||||
|
||||
var methodNames = GetCommandMethodNames();
|
||||
|
||||
|
||||
var isSuccess = true;
|
||||
foreach (var methodName in methodNames)
|
||||
{
|
||||
|
@@ -95,7 +95,7 @@ public partial class Administration : NadekoModule<AdministrationService>
|
||||
var guild = (SocketGuild)ctx.Guild;
|
||||
var (enabled, channels) = _service.GetDelMsgOnCmdData(ctx.Guild.Id);
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.server_delmsgoncmd))
|
||||
.WithDescription(enabled ? "✅" : "❌");
|
||||
|
@@ -35,22 +35,22 @@ public partial class Administration
|
||||
{
|
||||
var result = _ds.SelectSql(sql);
|
||||
|
||||
return ctx.SendPaginatedConfirmAsync(0,
|
||||
cur =>
|
||||
{
|
||||
var items = result.Results.Skip(cur * 20).Take(20).ToList();
|
||||
return Response()
|
||||
.Paginated()
|
||||
.Items(result.Results)
|
||||
.PageSize(20)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
if (!items.Any())
|
||||
return _sender.CreateEmbed().WithErrorColor().WithFooter(sql).WithDescription("-");
|
||||
|
||||
if (!items.Any())
|
||||
return new EmbedBuilder().WithErrorColor().WithFooter(sql).WithDescription("-");
|
||||
|
||||
return new EmbedBuilder()
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithFooter(sql)
|
||||
.WithTitle(string.Join(" ║ ", result.ColumnNames))
|
||||
.WithDescription(string.Join('\n', items.Select(x => string.Join(" ║ ", x))));
|
||||
},
|
||||
result.Results.Count,
|
||||
20);
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -99,9 +99,9 @@ public partial class Administration
|
||||
{
|
||||
try
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.sql_confirm_exec))
|
||||
.WithDescription(Format.Code(sql));
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.sql_confirm_exec))
|
||||
.WithDescription(Format.Code(sql));
|
||||
|
||||
if (!await PromptUserConfirmAsync(embed))
|
||||
return;
|
||||
@@ -119,8 +119,8 @@ public partial class Administration
|
||||
[OwnerOnly]
|
||||
public async Task PurgeUser(ulong userId)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithDescription(GetText(strs.purge_user_confirm(Format.Bold(userId.ToString()))));
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithDescription(GetText(strs.purge_user_confirm(Format.Bold(userId.ToString()))));
|
||||
|
||||
if (!await PromptUserConfirmAsync(embed))
|
||||
return;
|
||||
|
@@ -97,7 +97,7 @@ public class GreetService : INService, IReadyExecutor
|
||||
{
|
||||
var newContent = await _repSvc.ReplaceAsync(toSend,
|
||||
new(client: _client, guild: user.Guild, channel: channel, users: user));
|
||||
var toDelete = await channel.SendAsync(newContent);
|
||||
var toDelete = await _sender.Response(channel).Text(newContent).SendAsync();
|
||||
if (conf.BoostMessageDeleteAfter > 0)
|
||||
toDelete.DeleteAfter(conf.BoostMessageDeleteAfter);
|
||||
|
||||
@@ -217,12 +217,12 @@ public class GreetService : INService, IReadyExecutor
|
||||
text = await _repSvc.ReplaceAsync(text, repCtx);
|
||||
try
|
||||
{
|
||||
var toDelete = await channel.SendAsync(text);
|
||||
var toDelete = await _sender.Response(channel).Text(text).SendAsync();
|
||||
if (conf.AutoDeleteByeMessagesTimer > 0)
|
||||
toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer);
|
||||
}
|
||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions ||
|
||||
ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions
|
||||
|| ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
||||
{
|
||||
Log.Warning(ex,
|
||||
"Missing permissions to send a bye message, the bye message will be disabled on server: {GuildId}",
|
||||
@@ -258,12 +258,12 @@ public class GreetService : INService, IReadyExecutor
|
||||
text = await _repSvc.ReplaceAsync(text, repCtx);
|
||||
try
|
||||
{
|
||||
var toDelete = await channel.SendAsync(text);
|
||||
var toDelete = await _sender.Response(channel).Text(text).SendAsync();
|
||||
if (conf.AutoDeleteGreetMessagesTimer > 0)
|
||||
toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer);
|
||||
}
|
||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions ||
|
||||
ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions
|
||||
|| ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
||||
{
|
||||
Log.Warning(ex,
|
||||
"Missing permissions to send a bye message, the greet message will be disabled on server: {GuildId}",
|
||||
@@ -352,9 +352,10 @@ public class GreetService : INService, IReadyExecutor
|
||||
{
|
||||
// if there is less than 10 embeds, add an embed with footer only
|
||||
seta.Embeds = seta.Embeds.Append(new SmartEmbedArrayElementText()
|
||||
{
|
||||
Footer = CreateFooterSource(user)
|
||||
}).ToArray();
|
||||
{
|
||||
Footer = CreateFooterSource(user)
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -112,7 +112,7 @@ public partial class Administration
|
||||
|
||||
[Cmd]
|
||||
public async Task LanguagesList()
|
||||
=> await Response().Embed(new EmbedBuilder()
|
||||
=> await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.lang_list))
|
||||
.WithDescription(string.Join("\n",
|
||||
|
@@ -123,7 +123,7 @@ public class MuteService : INService
|
||||
return;
|
||||
|
||||
_ = Task.Run(() => _sender.Response(user)
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithDescription($"You've been muted in {user.Guild} server")
|
||||
.AddField("Mute Type", type.ToString())
|
||||
.AddField("Moderator", mod.ToString())
|
||||
@@ -141,7 +141,7 @@ public class MuteService : INService
|
||||
return;
|
||||
|
||||
_ = Task.Run(() => _sender.Response(user)
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithDescription($"You've been unmuted in {user.Guild} server")
|
||||
.AddField("Unmute Type", type.ToString())
|
||||
.AddField("Moderator", mod.ToString())
|
||||
|
@@ -25,8 +25,10 @@ public partial class Administration
|
||||
var aggregatePerms = perms.Aggregate((acc, seed) => seed | acc);
|
||||
await _service.AddOverride(ctx.Guild.Id, cmd.Name, aggregatePerms);
|
||||
|
||||
await Response().Confirm(strs.perm_override(Format.Bold(aggregatePerms.ToString()),
|
||||
Format.Code(cmd.Name))).SendAsync();
|
||||
await Response()
|
||||
.Confirm(strs.perm_override(Format.Bold(aggregatePerms.ToString()),
|
||||
Format.Code(cmd.Name)))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -34,9 +36,9 @@ public partial class Administration
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task DiscordPermOverrideReset()
|
||||
{
|
||||
var result = await PromptUserConfirmAsync(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithDescription(GetText(strs.perm_override_all_confirm)));
|
||||
var result = await PromptUserConfirmAsync(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(GetText(strs.perm_override_all_confirm)));
|
||||
|
||||
if (!result)
|
||||
return;
|
||||
@@ -54,27 +56,28 @@ public partial class Administration
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
var overrides = await _service.GetAllOverrides(ctx.Guild.Id);
|
||||
var allOverrides = await _service.GetAllOverrides(ctx.Guild.Id);
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var eb = new EmbedBuilder().WithTitle(GetText(strs.perm_overrides)).WithOkColor();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allOverrides)
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var eb = _sender.CreateEmbed().WithTitle(GetText(strs.perm_overrides)).WithOkColor();
|
||||
|
||||
var thisPageOverrides = overrides.Skip(9 * curPage).Take(9).ToList();
|
||||
if (items.Count == 0)
|
||||
eb.WithDescription(GetText(strs.perm_override_page_none));
|
||||
else
|
||||
{
|
||||
eb.WithDescription(items.Select(ov => $"{ov.Command} => {ov.Perm.ToString()}")
|
||||
.Join("\n"));
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
overrides.Count,
|
||||
9);
|
||||
return eb;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -241,7 +241,7 @@ public partial class Administration
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.prot_active));
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.prot_active));
|
||||
|
||||
if (spam is not null)
|
||||
embed.AddField("Anti-Spam", GetAntiSpamString(spam).TrimTo(1024), true);
|
||||
|
@@ -12,7 +12,7 @@ public partial class Administration
|
||||
{
|
||||
_rero = rero;
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
@@ -29,15 +29,16 @@ public partial class Administration
|
||||
|
||||
if (levelReq < 0)
|
||||
return;
|
||||
|
||||
|
||||
var msg = await ctx.Channel.GetMessageAsync(messageId);
|
||||
if (msg is null)
|
||||
{
|
||||
await Response().Error(strs.not_found).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.User.Id != ctx.Guild.OwnerId && ((IGuildUser)ctx.User).GetRoles().Max(x => x.Position) <= role.Position)
|
||||
|
||||
if (ctx.User.Id != ctx.Guild.OwnerId
|
||||
&& ((IGuildUser)ctx.User).GetRoles().Max(x => x.Position) <= role.Position)
|
||||
{
|
||||
await Response().Error(strs.hierarchy).SendAsync();
|
||||
return;
|
||||
@@ -71,48 +72,52 @@ public partial class Administration
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
var reros = await _rero.GetReactionRolesAsync(ctx.Guild.Id);
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page, curPage =>
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor();
|
||||
var allReros = await _rero.GetReactionRolesAsync(ctx.Guild.Id);
|
||||
|
||||
var content = string.Empty;
|
||||
foreach (var g in reros.OrderBy(x => x.Group)
|
||||
.Skip(curPage * 10)
|
||||
.GroupBy(x => x.MessageId)
|
||||
.OrderBy(x => x.Key))
|
||||
{
|
||||
var messageId = g.Key;
|
||||
content +=
|
||||
$"[{messageId}](https://discord.com/channels/{ctx.Guild.Id}/{g.First().ChannelId}/{g.Key})\n";
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allReros.OrderBy(x => x.Group).ToList())
|
||||
.PageSize(10)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor();
|
||||
|
||||
var groupGroups = g.GroupBy(x => x.Group);
|
||||
var content = string.Empty;
|
||||
foreach (var g in items
|
||||
.GroupBy(x => x.MessageId)
|
||||
.OrderBy(x => x.Key))
|
||||
{
|
||||
var messageId = g.Key;
|
||||
content +=
|
||||
$"[{messageId}](https://discord.com/channels/{ctx.Guild.Id}/{g.First().ChannelId}/{g.Key})\n";
|
||||
|
||||
foreach (var ggs in groupGroups)
|
||||
{
|
||||
content += $"`< {(g.Key == 0 ? ("Not Exclusive (Group 0)") : ($"Group {ggs.Key}"))} >`\n";
|
||||
var groupGroups = g.GroupBy(x => x.Group);
|
||||
|
||||
foreach (var rero in ggs)
|
||||
{
|
||||
content +=
|
||||
$"\t{rero.Emote} -> {(ctx.Guild.GetRole(rero.RoleId)?.Mention ?? "<missing role>")}";
|
||||
if (rero.LevelReq > 0)
|
||||
content += $" (lvl {rero.LevelReq}+)";
|
||||
content += '\n';
|
||||
}
|
||||
}
|
||||
foreach (var ggs in groupGroups)
|
||||
{
|
||||
content += $"`< {(g.Key == 0 ? ("Not Exclusive (Group 0)") : ($"Group {ggs.Key}"))} >`\n";
|
||||
|
||||
}
|
||||
foreach (var rero in ggs)
|
||||
{
|
||||
content +=
|
||||
$"\t{rero.Emote} -> {(ctx.Guild.GetRole(rero.RoleId)?.Mention ?? "<missing role>")}";
|
||||
if (rero.LevelReq > 0)
|
||||
content += $" (lvl {rero.LevelReq}+)";
|
||||
content += '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
embed.WithDescription(string.IsNullOrWhiteSpace(content)
|
||||
? "There are no reaction roles on this server"
|
||||
: content);
|
||||
embed.WithDescription(string.IsNullOrWhiteSpace(content)
|
||||
? "There are no reaction roles on this server"
|
||||
: content);
|
||||
|
||||
return embed;
|
||||
}, reros.Count, 10);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -78,7 +78,7 @@ public sealed class CheckForUpdatesService : INService, IReadyExecutor
|
||||
if (user is null)
|
||||
return;
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor($"NadekoBot v{latestVersion} Released!")
|
||||
.WithTitle("Changelog")
|
||||
|
@@ -51,7 +51,6 @@ public partial class Administration
|
||||
{
|
||||
var downloadUsersTask = guild.DownloadUsersAsync();
|
||||
var message = await Response().Pending(strs.cache_users_pending).SendAsync();
|
||||
using var dbContext = _db.GetDbContext();
|
||||
|
||||
await downloadUsersTask;
|
||||
|
||||
@@ -62,10 +61,10 @@ public partial class Administration
|
||||
var (added, updated) = await _service.RefreshUsersAsync(users);
|
||||
|
||||
await message.ModifyAsync(x =>
|
||||
x.Embed = new EmbedBuilder()
|
||||
.WithDescription(GetText(strs.cache_users_done(added, updated)))
|
||||
.WithOkColor()
|
||||
.Build()
|
||||
x.Embed = _sender.CreateEmbed()
|
||||
.WithDescription(GetText(strs.cache_users_done(added, updated)))
|
||||
.WithOkColor()
|
||||
.Build()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,6 +80,7 @@ public partial class Administration
|
||||
&& ctx.Message is SocketUserMessage msg)
|
||||
{
|
||||
var fakeMessage = new DoAsUserMessage(msg, user, message);
|
||||
|
||||
|
||||
await _cmdHandler.TryRunCommand(sg, ch, fakeMessage);
|
||||
}
|
||||
@@ -113,14 +113,16 @@ public partial class Administration
|
||||
};
|
||||
_service.AddNewAutoCommand(cmd);
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.scadd))
|
||||
.AddField(GetText(strs.server),
|
||||
cmd.GuildId is null ? "-" : $"{cmd.GuildName}/{cmd.GuildId}",
|
||||
true)
|
||||
.AddField(GetText(strs.channel), $"{cmd.ChannelName}/{cmd.ChannelId}", true)
|
||||
.AddField(GetText(strs.command_text), cmdText)).SendAsync();
|
||||
await Response()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.scadd))
|
||||
.AddField(GetText(strs.server),
|
||||
cmd.GuildId is null ? "-" : $"{cmd.GuildName}/{cmd.GuildId}",
|
||||
true)
|
||||
.AddField(GetText(strs.channel), $"{cmd.ChannelName}/{cmd.ChannelId}", true)
|
||||
.AddField(GetText(strs.command_text), cmdText))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -328,18 +330,21 @@ public partial class Administration
|
||||
+ $"| {st.GuildCount.ToString().PadBoth(maxGuildCountLength)} `";
|
||||
})
|
||||
.ToArray();
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var str = string.Join("\n", allShardStrings.Skip(25 * curPage).Take(25));
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allShardStrings)
|
||||
.PageSize(25)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var str = string.Join("\n", items);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(str))
|
||||
str = GetText(strs.no_shards_on_page);
|
||||
if (string.IsNullOrWhiteSpace(str))
|
||||
str = GetText(strs.no_shards_on_page);
|
||||
|
||||
return new EmbedBuilder().WithOkColor().WithDescription($"{status}\n\n{str}");
|
||||
},
|
||||
allShardStrings.Length,
|
||||
25);
|
||||
return _sender.CreateEmbed().WithOkColor().WithDescription($"{status}\n\n{str}");
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
private static string ConnectionStateToEmoji(ShardStatus status)
|
||||
@@ -566,7 +571,7 @@ public partial class Administration
|
||||
return;
|
||||
|
||||
text = await repSvc.ReplaceAsync(text, repCtx);
|
||||
await ch.SendAsync(text);
|
||||
await Response().Channel(ch).Text(text).SendAsync();
|
||||
}
|
||||
else if (ids[1].ToUpperInvariant().StartsWith("U:", StringComparison.InvariantCulture))
|
||||
{
|
||||
@@ -577,7 +582,7 @@ public partial class Administration
|
||||
|
||||
var ch = await user.CreateDMChannelAsync();
|
||||
text = await repSvc.ReplaceAsync(text, repCtx);
|
||||
await ch.SendAsync(text);
|
||||
await Response().Channel(ch).Text(text).SendAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -98,53 +98,54 @@ public partial class Administration
|
||||
|
||||
var (exclusive, roles, groups) = _service.GetRoles(ctx.Guild);
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var rolesStr = new StringBuilder();
|
||||
var roleGroups = roles.OrderBy(x => x.Model.Group)
|
||||
.Skip(cur * 20)
|
||||
.Take(20)
|
||||
.GroupBy(x => x.Model.Group)
|
||||
.OrderBy(x => x.Key);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(roles.OrderBy(x => x.Model.Group).ToList())
|
||||
.PageSize(20)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var rolesStr = new StringBuilder();
|
||||
var roleGroups = items
|
||||
.GroupBy(x => x.Model.Group)
|
||||
.OrderBy(x => x.Key);
|
||||
|
||||
foreach (var kvp in roleGroups)
|
||||
{
|
||||
string groupNameText;
|
||||
if (!groups.TryGetValue(kvp.Key, out var name))
|
||||
groupNameText = Format.Bold(GetText(strs.self_assign_group(kvp.Key)));
|
||||
else
|
||||
groupNameText = Format.Bold($"{kvp.Key} - {name.TrimTo(25, true)}");
|
||||
foreach (var kvp in roleGroups)
|
||||
{
|
||||
string groupNameText;
|
||||
if (!groups.TryGetValue(kvp.Key, out var name))
|
||||
groupNameText = Format.Bold(GetText(strs.self_assign_group(kvp.Key)));
|
||||
else
|
||||
groupNameText = Format.Bold($"{kvp.Key} - {name.TrimTo(25, true)}");
|
||||
|
||||
rolesStr.AppendLine("\t\t\t\t ⟪" + groupNameText + "⟫");
|
||||
foreach (var (model, role) in kvp.AsEnumerable())
|
||||
{
|
||||
if (role is null)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
// first character is invisible space
|
||||
if (model.LevelRequirement == 0)
|
||||
rolesStr.AppendLine(" " + role.Name);
|
||||
else
|
||||
rolesStr.AppendLine(" " + role.Name + $" (lvl {model.LevelRequirement}+)");
|
||||
}
|
||||
}
|
||||
rolesStr.AppendLine("\t\t\t\t ⟪" + groupNameText + "⟫");
|
||||
foreach (var (model, role) in kvp.AsEnumerable())
|
||||
{
|
||||
if (role is null)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
// first character is invisible space
|
||||
if (model.LevelRequirement == 0)
|
||||
rolesStr.AppendLine(" " + role.Name);
|
||||
else
|
||||
rolesStr.AppendLine(" " + role.Name + $" (lvl {model.LevelRequirement}+)");
|
||||
}
|
||||
}
|
||||
|
||||
rolesStr.AppendLine();
|
||||
}
|
||||
rolesStr.AppendLine();
|
||||
}
|
||||
|
||||
return new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(Format.Bold(GetText(strs.self_assign_list(roles.Count()))))
|
||||
.WithDescription(rolesStr.ToString())
|
||||
.WithFooter(exclusive
|
||||
? GetText(strs.self_assign_are_exclusive)
|
||||
: GetText(strs.self_assign_are_not_exclusive));
|
||||
},
|
||||
roles.Count(),
|
||||
20);
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(Format.Bold(GetText(strs.self_assign_list(roles.Count()))))
|
||||
.WithDescription(rolesStr.ToString())
|
||||
.WithFooter(exclusive
|
||||
? GetText(strs.self_assign_are_exclusive)
|
||||
: GetText(strs.self_assign_are_not_exclusive));
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -164,7 +164,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
|
||||
var title = GetText(logChannel.Guild, strs.thread_deleted);
|
||||
|
||||
await _sender.Response(logChannel).Embed(new EmbedBuilder()
|
||||
await _sender.Response(logChannel).Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("🗑 " + title)
|
||||
.WithDescription($"{ch.Name} | {ch.Id}")
|
||||
@@ -194,7 +194,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
|
||||
var title = GetText(logChannel.Guild, strs.thread_created);
|
||||
|
||||
await _sender.Response(logChannel).Embed(new EmbedBuilder()
|
||||
await _sender.Response(logChannel).Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("🆕 " + title)
|
||||
.WithDescription($"{ch.Name} | {ch.Id}")
|
||||
@@ -327,7 +327,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
if ((logChannel = await TryGetLogChannel(g, logSetting, LogType.UserWarned)) is null)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle($"⚠️ User Warned")
|
||||
.WithDescription($"<@{arg.UserId}> | {arg.UserId}")
|
||||
@@ -356,7 +356,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
if ((logChannel = await TryGetLogChannel(g, logSetting, LogType.UserUpdated)) is null)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder();
|
||||
var embed = _sender.CreateEmbed();
|
||||
|
||||
if (before.Username != after.Username)
|
||||
{
|
||||
@@ -495,7 +495,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
break;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor(mutes)
|
||||
.WithTitle($"{usr.Username}#{usr.Discriminator} | {usr.Id}")
|
||||
.WithFooter(CurrentTime(usr.Guild))
|
||||
@@ -542,7 +542,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
break;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor(mutes)
|
||||
.WithTitle($"{usr.Username}#{usr.Discriminator} | {usr.Id}")
|
||||
.WithFooter($"{CurrentTime(usr.Guild)}")
|
||||
@@ -596,7 +596,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
break;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor($"🛡 Anti-{protection}")
|
||||
.WithTitle(GetText(logChannel.Guild, strs.users) + " " + punishment)
|
||||
.WithDescription(string.Join("\n", users.Select(u => u.ToString())))
|
||||
@@ -649,7 +649,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
if (logSetting.UserUpdatedId is not null
|
||||
&& (logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) is not null)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithFooter(CurrentTime(before.Guild))
|
||||
.WithTitle($"{before.Username}#{before.Discriminator} | {before.Id}");
|
||||
@@ -720,7 +720,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) is null)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor().WithFooter(CurrentTime(before.Guild));
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithFooter(CurrentTime(before.Guild));
|
||||
|
||||
var beforeTextChannel = cbefore as ITextChannel;
|
||||
var afterTextChannel = cafter as ITextChannel;
|
||||
@@ -776,7 +776,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
else
|
||||
title = GetText(logChannel.Guild, strs.text_chan_destroyed);
|
||||
|
||||
await _sender.Response(logChannel).Embed(new EmbedBuilder()
|
||||
await _sender.Response(logChannel).Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("🆕 " + title)
|
||||
.WithDescription($"{ch.Name} | {ch.Id}")
|
||||
@@ -812,7 +812,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
else
|
||||
title = GetText(logChannel.Guild, strs.text_chan_created);
|
||||
|
||||
await _sender.Response(logChannel).Embed(new EmbedBuilder()
|
||||
await _sender.Response(logChannel).Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("🆕 " + title)
|
||||
.WithDescription($"{ch.Name} | {ch.Id}")
|
||||
@@ -915,7 +915,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
ITextChannel? logChannel;
|
||||
if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserLeft)) is null)
|
||||
return;
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("❌ " + GetText(logChannel.Guild, strs.user_left))
|
||||
.WithDescription(usr.ToString())
|
||||
@@ -948,7 +948,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) is null)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("✅ " + GetText(logChannel.Guild, strs.user_joined))
|
||||
.WithDescription($"{usr.Mention} `{usr}`")
|
||||
@@ -989,7 +989,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
ITextChannel? logChannel;
|
||||
if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) is null)
|
||||
return;
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("♻️ " + GetText(logChannel.Guild, strs.user_unbanned))
|
||||
.WithDescription(usr.ToString()!)
|
||||
@@ -1036,7 +1036,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
{
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("🚫 " + GetText(logChannel.Guild, strs.user_banned))
|
||||
.WithDescription(usr.ToString()!)
|
||||
@@ -1087,7 +1087,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
return;
|
||||
|
||||
var resolvedMessage = msg.Resolve(TagHandling.FullName);
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("🗑 "
|
||||
+ GetText(logChannel.Guild, strs.msg_del(((ITextChannel)msg.Channel).Name)))
|
||||
@@ -1147,7 +1147,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
||||
|| logChannel.Id == after.Channel.Id)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("📝 "
|
||||
+ GetText(logChannel.Guild,
|
||||
|
@@ -35,7 +35,7 @@ public partial class Administration
|
||||
var usrs = settings?.LogIgnores.Where(x => x.ItemType == IgnoredItemType.User).ToList()
|
||||
?? new List<IgnoredLogItem>();
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField(GetText(strs.log_ignored_channels),
|
||||
chs.Count == 0
|
||||
|
@@ -33,17 +33,20 @@ public partial class Administration
|
||||
if (flip)
|
||||
return $"{offset} {Format.Code(nameStr)}";
|
||||
return $"{Format.Code(offset)} {nameStr}";
|
||||
});
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage => new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.timezones_available))
|
||||
.WithDescription(string.Join("\n",
|
||||
timezoneStrings.Skip(curPage * timezonesPerPage).Take(timezonesPerPage))),
|
||||
timezones.Length,
|
||||
timezonesPerPage);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(timezoneStrings)
|
||||
.PageSize(timezonesPerPage)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) => _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.timezones_available))
|
||||
.WithDescription(string.Join("\n", items)))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -66,7 +66,7 @@ public partial class Administration
|
||||
try
|
||||
{
|
||||
await _sender.Response(user)
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithErrorColor()
|
||||
.WithDescription(GetText(strs.warned_on(ctx.Guild.ToString())))
|
||||
.AddField(GetText(strs.moderator), ctx.User.ToString())
|
||||
@@ -86,7 +86,7 @@ public partial class Administration
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Exception occured while warning a user");
|
||||
var errorEmbed = new EmbedBuilder().WithErrorColor()
|
||||
var errorEmbed = _sender.CreateEmbed().WithErrorColor()
|
||||
.WithDescription(GetText(strs.cant_apply_punishment));
|
||||
|
||||
if (dmFailed)
|
||||
@@ -96,7 +96,7 @@ public partial class Administration
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
if (punishment is null)
|
||||
embed.WithDescription(GetText(strs.user_warned(Format.Bold(user.ToString()))));
|
||||
else
|
||||
@@ -197,45 +197,46 @@ public partial class Administration
|
||||
|
||||
var allWarnings = _service.UserWarnings(ctx.Guild.Id, userId);
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(inputPage,
|
||||
page =>
|
||||
{
|
||||
var warnings = allWarnings.Skip(page * 9).Take(9).ToArray();
|
||||
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 = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.warnlog_for(user)));
|
||||
|
||||
var user = (ctx.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString();
|
||||
var embed = new EmbedBuilder().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())));
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
|
||||
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))}";
|
||||
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));
|
||||
}
|
||||
}
|
||||
embed.AddField($"#`{i}` " + name,
|
||||
Format.Code(GetText(strs.warn_weight(w.Weight))) + '\n' + w.Reason.TrimTo(1000));
|
||||
}
|
||||
}
|
||||
|
||||
return embed;
|
||||
},
|
||||
allWarnings.Length,
|
||||
9);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -245,31 +246,32 @@ public partial class Administration
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
var warnings = _service.WarnlogAll(ctx.Guild.Id);
|
||||
var allWarnings = _service.WarnlogAll(ctx.Guild.Id);
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var ws = warnings.Skip(curPage * 15)
|
||||
.Take(15)
|
||||
.ToArray()
|
||||
.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})";
|
||||
});
|
||||
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 new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.warnings_list))
|
||||
.WithDescription(string.Join("\n", ws));
|
||||
},
|
||||
warnings.Length,
|
||||
15);
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.warnings_list))
|
||||
.WithDescription(string.Join("\n", ws));
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -450,7 +452,7 @@ public partial class Administration
|
||||
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 = new EmbedBuilder()
|
||||
var toSend = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("⛔️ " + GetText(strs.banned_user))
|
||||
.AddField(GetText(strs.username), user?.ToString() ?? userId.ToString(), true)
|
||||
@@ -478,10 +480,11 @@ public partial class Administration
|
||||
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
||||
await ctx.Guild.AddBanAsync(userId, banPrune, (ctx.User + " | " + msg).TrimTo(512));
|
||||
|
||||
await ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("⛔️ " + GetText(strs.banned_user))
|
||||
.AddField("ID", userId.ToString(), true));
|
||||
.AddField("ID", userId.ToString(), true))
|
||||
.SendAsync();
|
||||
}
|
||||
else
|
||||
await Ban(user, msg);
|
||||
@@ -514,7 +517,7 @@ public partial class Administration
|
||||
var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7;
|
||||
await ctx.Guild.AddBanAsync(user, banPrune, (ctx.User + " | " + msg).TrimTo(512));
|
||||
|
||||
var toSend = new EmbedBuilder()
|
||||
var toSend = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("⛔️ " + GetText(strs.banned_user))
|
||||
.AddField(GetText(strs.username), user.ToString(), true)
|
||||
@@ -709,7 +712,7 @@ public partial class Administration
|
||||
try { await ctx.Guild.RemoveBanAsync(user); }
|
||||
catch { await ctx.Guild.RemoveBanAsync(user); }
|
||||
|
||||
var toSend = new EmbedBuilder()
|
||||
var toSend = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("☣ " + GetText(strs.sb_user))
|
||||
.AddField(GetText(strs.username), user.ToString(), true)
|
||||
@@ -764,7 +767,7 @@ public partial class Administration
|
||||
|
||||
await user.KickAsync((ctx.User + " | " + msg).TrimTo(512));
|
||||
|
||||
var toSend = new EmbedBuilder()
|
||||
var toSend = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.kicked_user))
|
||||
.AddField(GetText(strs.username), user.ToString(), true)
|
||||
@@ -797,7 +800,7 @@ public partial class Administration
|
||||
{
|
||||
var dmMessage = GetText(strs.timeoutdm(Format.Bold(ctx.Guild.Name), msg));
|
||||
await _sender.Response(user)
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithPendingColor()
|
||||
.WithDescription(dmMessage))
|
||||
.SendAsync();
|
||||
@@ -809,7 +812,7 @@ public partial class Administration
|
||||
|
||||
await user.SetTimeOutAsync(time.Time);
|
||||
|
||||
var toSend = new EmbedBuilder()
|
||||
var toSend = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("⏳ " + GetText(strs.timedout_user))
|
||||
.AddField(GetText(strs.username), user.ToString(), true)
|
||||
@@ -870,7 +873,7 @@ public partial class Administration
|
||||
if (string.IsNullOrWhiteSpace(missStr))
|
||||
missStr = "-";
|
||||
|
||||
var toSend = new EmbedBuilder()
|
||||
var toSend = _sender.CreateEmbed()
|
||||
.WithDescription(GetText(strs.mass_ban_in_progress(banning.Count)))
|
||||
.AddField(GetText(strs.invalid(missing.Count)), missStr)
|
||||
.WithPendingColor();
|
||||
@@ -890,7 +893,7 @@ public partial class Administration
|
||||
}
|
||||
}
|
||||
|
||||
await banningMessage.ModifyAsync(x => x.Embed = new EmbedBuilder()
|
||||
await banningMessage.ModifyAsync(x => x.Embed = _sender.CreateEmbed()
|
||||
.WithDescription(
|
||||
GetText(strs.mass_ban_completed(banning.Count())))
|
||||
.AddField(GetText(strs.invalid(missing.Count)), missStr)
|
||||
@@ -915,11 +918,13 @@ public partial class Administration
|
||||
missStr = "-";
|
||||
|
||||
//send a message but don't wait for it
|
||||
var banningMessageTask = ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
.WithDescription(
|
||||
GetText(strs.mass_kill_in_progress(bans.Count())))
|
||||
.AddField(GetText(strs.invalid(missing)), missStr)
|
||||
.WithPendingColor());
|
||||
var banningMessageTask = Response()
|
||||
.Embed(_sender.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
|
||||
@@ -935,7 +940,7 @@ public partial class Administration
|
||||
//wait for the message and edit it
|
||||
var banningMessage = await banningMessageTask;
|
||||
|
||||
await banningMessage.ModifyAsync(x => x.Embed = new EmbedBuilder()
|
||||
await banningMessage.ModifyAsync(x => x.Embed = _sender.CreateEmbed()
|
||||
.WithDescription(
|
||||
GetText(strs.mass_kill_completed(bans.Count())))
|
||||
.AddField(GetText(strs.invalid(missing)), missStr)
|
||||
|
@@ -68,7 +68,7 @@ public partial class Administration
|
||||
else
|
||||
text = GetText(strs.no_vcroles);
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.vc_role_list))
|
||||
.WithDescription(text)).SendAsync();
|
||||
|
@@ -14,7 +14,7 @@ public static class NadekoExpressionExtensions
|
||||
IUserMessage ctx,
|
||||
IReplacementService repSvc,
|
||||
DiscordSocketClient client,
|
||||
bool sanitize)
|
||||
IMessageSenderService sender)
|
||||
{
|
||||
var channel = cr.DmResponse ? await ctx.Author.CreateDMChannelAsync() : ctx.Channel;
|
||||
|
||||
@@ -46,7 +46,7 @@ public static class NadekoExpressionExtensions
|
||||
var text = SmartText.CreateFrom(cr.Response);
|
||||
text = await repSvc.ReplaceAsync(text, repCtx);
|
||||
|
||||
return await channel.SendAsync(text, sanitize);
|
||||
return await sender.Response(channel).Text(text).Sanitize(false).SendAsync();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
@@ -33,7 +33,7 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
var ex = await _service.AddAsync(ctx.Guild?.Id, key, message);
|
||||
|
||||
await Response()
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_new))
|
||||
.WithDescription($"#{new kwum(ex.Id)}")
|
||||
@@ -66,6 +66,7 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
await ExprAddInternalAsync(key, message);
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
public async Task ExprAdd(string key, [Leftover] string message)
|
||||
{
|
||||
@@ -102,13 +103,15 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
var ex = await _service.EditAsync(ctx.Guild?.Id, id, message);
|
||||
if (ex is not null)
|
||||
{
|
||||
await ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_edited))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger)
|
||||
.AddField(GetText(strs.response),
|
||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message));
|
||||
await Response()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_edited))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger)
|
||||
.AddField(GetText(strs.response),
|
||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
|
||||
.SendAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -152,7 +155,7 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
: " // " + string.Join(" ", ex.GetReactions())))
|
||||
.Join('\n');
|
||||
|
||||
return new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc);
|
||||
return _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc);
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
@@ -168,12 +171,14 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response),
|
||||
found.Response.TrimTo(1000).Replace("](", "]\\(")));
|
||||
await Response()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response),
|
||||
found.Response.TrimTo(1000).Replace("](", "]\\(")))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
public async Task ExprDeleteInternalAsync(kwum id)
|
||||
@@ -182,12 +187,14 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
|
||||
if (ex is not null)
|
||||
{
|
||||
await ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_deleted))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response), ex.Response.TrimTo(1024)));
|
||||
await Response()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_deleted))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response), ex.Response.TrimTo(1024)))
|
||||
.SendAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -332,7 +339,7 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task ExprClear()
|
||||
{
|
||||
if (await PromptUserConfirmAsync(new EmbedBuilder()
|
||||
if (await PromptUserConfirmAsync(_sender.CreateEmbed()
|
||||
.WithTitle("Expression clear")
|
||||
.WithDescription("This will delete all expressions on this server.")))
|
||||
{
|
||||
|
@@ -280,7 +280,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
|
||||
}
|
||||
}
|
||||
|
||||
var sentMsg = await expr.Send(msg, _repSvc, _client, false);
|
||||
var sentMsg = await expr.Send(msg, _repSvc, _client, _sender);
|
||||
|
||||
var reactions = expr.GetReactions();
|
||||
foreach (var reaction in reactions)
|
||||
|
@@ -128,7 +128,7 @@ public partial class Gambling
|
||||
raceMessage = await Response().Confirm(text).SendAsync();
|
||||
else
|
||||
{
|
||||
await msg.ModifyAsync(x => x.Embed = new EmbedBuilder()
|
||||
await msg.ModifyAsync(x => x.Embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.animal_race))
|
||||
.WithDescription(text)
|
||||
.WithOkColor()
|
||||
|
@@ -59,7 +59,7 @@ public partial class Gambling
|
||||
{
|
||||
var bal = await _bank.GetBalanceAsync(ctx.User.Id);
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(GetText(strs.bank_balance(N(bal))));
|
||||
|
||||
|
@@ -95,7 +95,7 @@ public partial class Gambling
|
||||
|
||||
var cStr = string.Concat(c.Select(x => x[..^1] + " "));
|
||||
cStr += "\n" + string.Concat(c.Select(x => x.Last() + " "));
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("BlackJack")
|
||||
.AddField($"{dealerIcon} Dealer's Hand | Value: {bj.Dealer.GetHandValue()}", cStr);
|
||||
|
@@ -150,7 +150,7 @@ public partial class Gambling
|
||||
else
|
||||
title = GetText(strs.connect4_draw);
|
||||
|
||||
return msg.ModifyAsync(x => x.Embed = new EmbedBuilder()
|
||||
return msg.ModifyAsync(x => x.Embed = _sender.CreateEmbed()
|
||||
.WithTitle(title)
|
||||
.WithDescription(GetGameStateText(game))
|
||||
.WithOkColor()
|
||||
@@ -160,7 +160,7 @@ public partial class Gambling
|
||||
|
||||
private async Task Game_OnGameStateUpdated(Connect4Game game)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle($"{game.CurrentPlayer.Username} vs {game.OtherPlayer.Username}")
|
||||
.WithDescription(GetGameStateText(game))
|
||||
.WithOkColor();
|
||||
|
@@ -38,7 +38,7 @@ public partial class Gambling
|
||||
|
||||
var fileName = $"dice.{format.FileExtensions.First()}";
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.AddField(GetText(strs.roll2), gen)
|
||||
@@ -115,7 +115,7 @@ public partial class Gambling
|
||||
d.Dispose();
|
||||
|
||||
var imageName = $"dice.{format.FileExtensions.First()}";
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.AddField(GetText(strs.rolls), values.Select(x => Format.Code(x.ToString())).Join(' '), true)
|
||||
@@ -141,7 +141,7 @@ public partial class Gambling
|
||||
|
||||
for (var i = 0; i < n1; i++)
|
||||
rolls.Add(_fateRolls[rng.Next(0, _fateRolls.Length)]);
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithDescription(GetText(strs.dice_rolled_num(Format.Bold(n1.ToString()))))
|
||||
@@ -170,7 +170,7 @@ public partial class Gambling
|
||||
arr[i] = rng.Next(1, n2 + 1);
|
||||
|
||||
var sum = arr.Sum();
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithDescription(GetText(strs.dice_rolled_num(n1 + $"`1 - {n2}`")))
|
||||
|
@@ -55,7 +55,7 @@ public partial class Gambling
|
||||
foreach (var i in images)
|
||||
i.Dispose();
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor();
|
||||
|
||||
var toSend = string.Empty;
|
||||
@@ -160,7 +160,7 @@ public partial class Gambling
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithDescription(result.Card.GetEmoji())
|
||||
|
@@ -30,12 +30,12 @@ public partial class Gambling
|
||||
private EmbedBuilder GetEmbed(CurrencyEvent.Type type, EventOptions opts, long currentPot)
|
||||
=> type switch
|
||||
{
|
||||
CurrencyEvent.Type.Reaction => new EmbedBuilder()
|
||||
CurrencyEvent.Type.Reaction => _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.event_title(type.ToString())))
|
||||
.WithDescription(GetReactionDescription(opts.Amount, currentPot))
|
||||
.WithFooter(GetText(strs.event_duration_footer(opts.Hours))),
|
||||
CurrencyEvent.Type.GameStatus => new EmbedBuilder()
|
||||
CurrencyEvent.Type.GameStatus => _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.event_title(type.ToString())))
|
||||
.WithDescription(GetGameStatusDescription(opts.Amount, currentPot))
|
||||
|
@@ -84,7 +84,7 @@ public partial class Gambling
|
||||
? Format.Bold(GetText(strs.heads))
|
||||
: Format.Bold(GetText(strs.tails))));
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithDescription(msg)
|
||||
@@ -130,7 +130,7 @@ public partial class Gambling
|
||||
str = Format.Bold(GetText(strs.better_luck));
|
||||
}
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithDescription(str)
|
||||
.WithOkColor()
|
||||
|
@@ -73,7 +73,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
{
|
||||
var stats = await _gamblingTxTracker.GetAllAsync();
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor();
|
||||
|
||||
var str = "` Feature `|` Bet `|`Paid Out`|` RoI `\n";
|
||||
@@ -118,7 +118,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
}
|
||||
|
||||
// [21:03] Bob Page: Kinda remids me of US economy
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.economy_state))
|
||||
.AddField(GetText(strs.currency_owned), N(ec.Cash - ec.Bot))
|
||||
.AddField(GetText(strs.currency_one_percent), (onePercent * 100).ToString("F2") + "%")
|
||||
@@ -310,7 +310,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
trs = await uow.Set<CurrencyTransaction>().GetPageFor(userId, page);
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.transactions(((SocketGuild)ctx.Guild)?.GetUser(userId)?.ToString()
|
||||
?? $"{userId}")))
|
||||
.WithOkColor();
|
||||
@@ -360,7 +360,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder().WithOkColor();
|
||||
var eb = _sender.CreateEmbed().WithOkColor();
|
||||
|
||||
eb.WithAuthor(ctx.User);
|
||||
eb.WithTitle(GetText(strs.transaction));
|
||||
@@ -624,7 +624,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.roll_duel));
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.roll_duel));
|
||||
|
||||
var description = string.Empty;
|
||||
|
||||
@@ -731,7 +731,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
str = GetText(strs.better_luck);
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithDescription(Format.Bold(str))
|
||||
.AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture))
|
||||
@@ -758,68 +758,64 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
|
||||
var (opts, _) = OptionsParser.ParseFrom(new LbOpts(), args);
|
||||
|
||||
List<DiscordUser> cleanRichest;
|
||||
// List<DiscordUser> cleanRichest;
|
||||
// it's pointless to have clean on dm context
|
||||
if (ctx.Guild is null)
|
||||
{
|
||||
opts.Clean = false;
|
||||
}
|
||||
|
||||
if (opts.Clean)
|
||||
|
||||
async Task<IEnumerable<DiscordUser>> GetTopRichest(int curPage)
|
||||
{
|
||||
await using (var uow = _db.GetDbContext())
|
||||
if (opts.Clean)
|
||||
{
|
||||
cleanRichest = await uow.Set<DiscordUser>().GetTopRichest(_client.CurrentUser.Id, 0, 10_000);
|
||||
await ctx.Channel.TriggerTypingAsync();
|
||||
await _tracker.EnsureUsersDownloadedAsync(ctx.Guild);
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
|
||||
var cleanRichest = await uow.Set<DiscordUser>()
|
||||
.GetTopRichest(_client.CurrentUser.Id, 0, 10_000);
|
||||
|
||||
var sg = (SocketGuild)ctx.Guild!;
|
||||
return cleanRichest.Where(x => sg.GetUser(x.UserId) is not null).ToList();
|
||||
}
|
||||
|
||||
await ctx.Channel.TriggerTypingAsync();
|
||||
await _tracker.EnsureUsersDownloadedAsync(ctx.Guild);
|
||||
|
||||
var sg = (SocketGuild)ctx.Guild!;
|
||||
cleanRichest = cleanRichest.Where(x => sg.GetUser(x.UserId) is not null).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
cleanRichest = await uow.Set<DiscordUser>().GetTopRichest(_client.CurrentUser.Id, page);
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
async curPage =>
|
||||
else
|
||||
{
|
||||
var embed = new EmbedBuilder().WithOkColor().WithTitle(CurrencySign + " " + GetText(strs.leaderboard));
|
||||
await using var uow = _db.GetDbContext();
|
||||
return await uow.Set<DiscordUser>().GetTopRichest(_client.CurrentUser.Id, curPage);
|
||||
}
|
||||
}
|
||||
|
||||
List<DiscordUser> toSend;
|
||||
if (!opts.Clean)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
toSend = await uow.Set<DiscordUser>().GetTopRichest(_client.CurrentUser.Id, curPage);
|
||||
}
|
||||
else
|
||||
{
|
||||
toSend = cleanRichest.Skip(curPage * 9).Take(9).ToList();
|
||||
}
|
||||
await Response()
|
||||
.Paginated()
|
||||
.PageItems(GetTopRichest)
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((toSend, curPage) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed().WithOkColor()
|
||||
.WithTitle(CurrencySign + " " + GetText(strs.leaderboard));
|
||||
|
||||
if (!toSend.Any())
|
||||
{
|
||||
embed.WithDescription(GetText(strs.no_user_on_this_page));
|
||||
return embed;
|
||||
}
|
||||
if (!toSend.Any())
|
||||
{
|
||||
embed.WithDescription(GetText(strs.no_user_on_this_page));
|
||||
return Task.FromResult(embed);
|
||||
}
|
||||
|
||||
for (var i = 0; i < toSend.Count; i++)
|
||||
{
|
||||
var x = toSend[i];
|
||||
var usrStr = x.ToString().TrimTo(20, true);
|
||||
for (var i = 0; i < toSend.Count; i++)
|
||||
{
|
||||
var x = toSend[i];
|
||||
var usrStr = x.ToString().TrimTo(20, true);
|
||||
|
||||
var j = i;
|
||||
embed.AddField("#" + ((9 * curPage) + j + 1) + " " + usrStr, N(x.CurrencyAmount), true);
|
||||
}
|
||||
var j = i;
|
||||
embed.AddField("#" + ((9 * curPage) + j + 1) + " " + usrStr, N(x.CurrencyAmount), true);
|
||||
}
|
||||
|
||||
return embed;
|
||||
},
|
||||
opts.Clean ? cleanRichest.Count() : 9000,
|
||||
9,
|
||||
opts.Clean);
|
||||
return Task.FromResult(embed);
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
public enum InputRpsPick : byte
|
||||
@@ -861,7 +857,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder();
|
||||
var embed = _sender.CreateEmbed();
|
||||
|
||||
string msg;
|
||||
if (result.Result == RpsResultType.Draw)
|
||||
@@ -922,7 +918,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(sb.ToString())
|
||||
.AddField(GetText(strs.multiplier), $"{result.Multiplier:0.##}x", true)
|
||||
|
@@ -92,21 +92,23 @@ public partial class Gambling
|
||||
{
|
||||
if (--page < 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var enabledIn = _service.GetAllGeneratingChannels();
|
||||
|
||||
return ctx.SendPaginatedConfirmAsync(page,
|
||||
_ =>
|
||||
{
|
||||
var items = enabledIn.Skip(page * 9).Take(9).ToList();
|
||||
return Response()
|
||||
.Paginated()
|
||||
.Items(enabledIn.ToList())
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
if (!items.Any())
|
||||
return _sender.CreateEmbed().WithErrorColor().WithDescription("-");
|
||||
|
||||
if (!items.Any())
|
||||
return new EmbedBuilder().WithErrorColor().WithDescription("-");
|
||||
|
||||
return items.Aggregate(new EmbedBuilder().WithOkColor(),
|
||||
(eb, i) => eb.AddField(i.GuildId.ToString(), i.ChannelId));
|
||||
},
|
||||
enabledIn.Count(),
|
||||
9);
|
||||
return items.Aggregate(_sender.CreateEmbed().WithOkColor(),
|
||||
(eb, i) => eb.AddField(i.GuildId.ToString(), i.ChannelId));
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -48,27 +48,29 @@ public partial class Gambling
|
||||
var entries = uow.GuildConfigsForId(ctx.Guild.Id,
|
||||
set => set.Include(x => x.ShopEntries).ThenInclude(x => x.Items))
|
||||
.ShopEntries.ToIndexed();
|
||||
return ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var theseEntries = entries.Skip(curPage * 9).Take(9).ToArray();
|
||||
|
||||
if (!theseEntries.Any())
|
||||
return new EmbedBuilder().WithErrorColor().WithDescription(GetText(strs.shop_none));
|
||||
var embed = new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.shop));
|
||||
return Response()
|
||||
.Paginated()
|
||||
.Items(entries.ToList())
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, curPage) =>
|
||||
{
|
||||
if (!items.Any())
|
||||
return _sender.CreateEmbed().WithErrorColor().WithDescription(GetText(strs.shop_none));
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.shop));
|
||||
|
||||
for (var i = 0; i < theseEntries.Length; i++)
|
||||
{
|
||||
var entry = theseEntries[i];
|
||||
embed.AddField($"#{(curPage * 9) + i + 1} - {N(entry.Price)}",
|
||||
EntryToString(entry),
|
||||
true);
|
||||
}
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
var entry = items[i];
|
||||
embed.AddField($"#{(curPage * 9) + i + 1} - {N(entry.Price)}",
|
||||
EntryToString(entry),
|
||||
true);
|
||||
}
|
||||
|
||||
return embed;
|
||||
},
|
||||
entries.Count,
|
||||
9);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -187,7 +189,7 @@ public partial class Gambling
|
||||
{
|
||||
await Response()
|
||||
.User(ctx.User)
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.shop_purchase(ctx.Guild.Name)))
|
||||
.AddField(GetText(strs.item), item.Text)
|
||||
@@ -246,7 +248,7 @@ public partial class Gambling
|
||||
else
|
||||
{
|
||||
var cmd = entry.Command.Replace("%you%", ctx.User.Id.ToString());
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithPendingColor()
|
||||
.WithTitle("Executing shop command")
|
||||
.WithDescription(cmd);
|
||||
@@ -268,10 +270,11 @@ public partial class Gambling
|
||||
try
|
||||
{
|
||||
var pendingMsg = await msgTask;
|
||||
await pendingMsg.EditAsync(SmartEmbedText.FromEmbed(eb
|
||||
.WithOkColor()
|
||||
.WithTitle("Shop command executed")
|
||||
.Build()));
|
||||
await pendingMsg.EditAsync(
|
||||
SmartEmbedText.FromEmbed(eb
|
||||
.WithOkColor()
|
||||
.WithTitle("Shop command executed")
|
||||
.Build()));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -531,7 +534,7 @@ public partial class Gambling
|
||||
|
||||
public EmbedBuilder EntryToEmbed(ShopEntry entry)
|
||||
{
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
|
||||
if (entry.Type == ShopEntryType.Role)
|
||||
{
|
||||
|
@@ -69,7 +69,7 @@ public partial class Gambling
|
||||
await using var imgStream = await image.ToStreamAsync();
|
||||
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithDescription(Format.Bold(text))
|
||||
.WithImageUrl($"attachment://result.png")
|
||||
|
@@ -20,9 +20,9 @@ public partial class Gambling
|
||||
public async Task WaifuReset()
|
||||
{
|
||||
var price = _service.GetResetPrice(ctx.User);
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.waifu_reset_confirm))
|
||||
.WithDescription(GetText(strs.waifu_reset_price(Format.Bold(N(price)))));
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.waifu_reset_confirm))
|
||||
.WithDescription(GetText(strs.waifu_reset_price(Format.Bold(N(price)))));
|
||||
|
||||
if (!await PromptUserConfirmAsync(embed))
|
||||
return;
|
||||
@@ -222,7 +222,7 @@ public partial class Gambling
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.waifus_top_waifus)).WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.waifus_top_waifus)).WithOkColor();
|
||||
|
||||
var i = 0;
|
||||
foreach (var w in waifus)
|
||||
@@ -306,25 +306,25 @@ public partial class Gambling
|
||||
if (string.IsNullOrWhiteSpace(fansStr))
|
||||
fansStr = "-";
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.waifu)
|
||||
+ " "
|
||||
+ (wi.FullName ?? name ?? targetId.ToString())
|
||||
+ " - \"the "
|
||||
+ _service.GetClaimTitle(wi.ClaimCount)
|
||||
+ "\"")
|
||||
.AddField(GetText(strs.price), N(wi.Price), true)
|
||||
.AddField(GetText(strs.claimed_by), wi.ClaimerName ?? nobody, true)
|
||||
.AddField(GetText(strs.likes), wi.AffinityName ?? nobody, true)
|
||||
.AddField(GetText(strs.changes_of_heart), $"{wi.AffinityCount} - \"the {affInfo}\"", true)
|
||||
.AddField(GetText(strs.divorces), wi.DivorceCount.ToString(), true)
|
||||
.AddField("\u200B", "\u200B", true)
|
||||
.AddField(GetText(strs.fans(fansList.Count)), fansStr, true)
|
||||
.AddField($"Waifus ({wi.ClaimCount})",
|
||||
wi.ClaimCount == 0 ? nobody : claimsStr,
|
||||
true)
|
||||
.AddField(GetText(strs.gifts), itemsStr, true);
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.waifu)
|
||||
+ " "
|
||||
+ (wi.FullName ?? name ?? targetId.ToString())
|
||||
+ " - \"the "
|
||||
+ _service.GetClaimTitle(wi.ClaimCount)
|
||||
+ "\"")
|
||||
.AddField(GetText(strs.price), N(wi.Price), true)
|
||||
.AddField(GetText(strs.claimed_by), wi.ClaimerName ?? nobody, true)
|
||||
.AddField(GetText(strs.likes), wi.AffinityName ?? nobody, true)
|
||||
.AddField(GetText(strs.changes_of_heart), $"{wi.AffinityCount} - \"the {affInfo}\"", true)
|
||||
.AddField(GetText(strs.divorces), wi.DivorceCount.ToString(), true)
|
||||
.AddField("\u200B", "\u200B", true)
|
||||
.AddField(GetText(strs.fans(fansList.Count)), fansStr, true)
|
||||
.AddField($"Waifus ({wi.ClaimCount})",
|
||||
wi.ClaimCount == 0 ? nobody : claimsStr,
|
||||
true)
|
||||
.AddField(GetText(strs.gifts), itemsStr, true);
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
@@ -338,25 +338,27 @@ public partial class Gambling
|
||||
return;
|
||||
|
||||
var waifuItems = _service.GetWaifuItems();
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.waifu_gift_shop)).WithOkColor();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(waifuItems.OrderBy(x => x.Negative)
|
||||
.ThenBy(x => x.Price)
|
||||
.ToList())
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.waifu_gift_shop)).WithOkColor();
|
||||
|
||||
items
|
||||
.ToList()
|
||||
.ForEach(x => embed.AddField(
|
||||
$"{(!x.Negative ? string.Empty : "\\💔")} {x.ItemEmoji} {x.Name}",
|
||||
Format.Bold(N(x.Price)),
|
||||
true));
|
||||
|
||||
waifuItems.OrderBy(x => x.Negative)
|
||||
.ThenBy(x => x.Price)
|
||||
.Skip(9 * cur)
|
||||
.Take(9)
|
||||
.ToList()
|
||||
.ForEach(x => embed.AddField(
|
||||
$"{(!x.Negative ? string.Empty : "\\💔")} {x.ItemEmoji} {x.Name}",
|
||||
Format.Bold(N(x.Price)),
|
||||
true));
|
||||
|
||||
return embed;
|
||||
},
|
||||
waifuItems.Count,
|
||||
9);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -67,7 +67,7 @@ public partial class Games
|
||||
|
||||
private Task Game_OnStarted(AcrophobiaGame game)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.acrophobia))
|
||||
.WithDescription(
|
||||
@@ -92,7 +92,7 @@ public partial class Games
|
||||
|
||||
if (submissions.Length == 1)
|
||||
{
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(GetText(
|
||||
strs.acro_winner_only(
|
||||
@@ -103,7 +103,7 @@ public partial class Games
|
||||
|
||||
|
||||
var i = 0;
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.acrophobia) + " - " + GetText(strs.submissions_closed))
|
||||
.WithDescription(GetText(strs.acro_nym_was(
|
||||
@@ -127,7 +127,7 @@ public partial class Games
|
||||
|
||||
var table = votes.OrderByDescending(v => v.Value);
|
||||
var winner = table.First();
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.acrophobia))
|
||||
.WithDescription(GetText(strs.acro_winner(Format.Bold(winner.Key.UserName),
|
||||
|
@@ -38,7 +38,7 @@ public partial class Games : NadekoModule<GamesService>
|
||||
return;
|
||||
|
||||
var res = _service.GetEightballResponse(ctx.User.Id, question);
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(ctx.User.ToString())
|
||||
.AddField("❓ " + GetText(strs.question), question)
|
||||
|
@@ -23,11 +23,11 @@ public partial class Games
|
||||
/-\
|
||||
""";
|
||||
|
||||
public static EmbedBuilder GetEmbed(HangmanGame.State state)
|
||||
public static EmbedBuilder GetEmbed(IMessageSenderService sender, HangmanGame.State state)
|
||||
{
|
||||
if (state.Phase == HangmanGame.Phase.Running)
|
||||
{
|
||||
return new EmbedBuilder()
|
||||
return sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField("Hangman", Draw(state))
|
||||
.AddField("Guess", Format.Code(state.Word))
|
||||
@@ -36,14 +36,14 @@ public partial class Games
|
||||
|
||||
if (state.Phase == HangmanGame.Phase.Ended && state.Failed)
|
||||
{
|
||||
return new EmbedBuilder()
|
||||
return sender.CreateEmbed()
|
||||
.WithErrorColor()
|
||||
.AddField("Hangman", Draw(state))
|
||||
.AddField("Guess", Format.Code(state.Word))
|
||||
.WithFooter(state.MissedLetters.Join(' '));
|
||||
}
|
||||
|
||||
return new EmbedBuilder()
|
||||
return sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField("Hangman", Draw(state))
|
||||
.AddField("Guess", Format.Code(state.Word))
|
||||
@@ -60,7 +60,7 @@ public partial class Games
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = GetEmbed(hangman);
|
||||
var eb = GetEmbed(_sender, hangman);
|
||||
eb.WithDescription(GetText(strs.hangman_game_started));
|
||||
await Response().Embed(eb).SendAsync();
|
||||
}
|
||||
|
@@ -116,7 +116,7 @@ public sealed class HangmanService : IHangmanService, IExecNoCommand
|
||||
string content,
|
||||
HangmanGame.State state)
|
||||
{
|
||||
var embed = Games.HangmanCommands.GetEmbed(state);
|
||||
var embed = Games.HangmanCommands.GetEmbed(_sender, state);
|
||||
if (state.GuessResult == HangmanGame.GuessResult.Guess)
|
||||
embed.WithDescription($"{user} guessed the letter {content}!").WithOkColor();
|
||||
else if (state.GuessResult == HangmanGame.GuessResult.Incorrect && state.Failed)
|
||||
|
@@ -94,7 +94,7 @@ public partial class Games
|
||||
if (removed is null)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle($"Removed typing article #{index + 1}")
|
||||
.WithDescription(removed.Text.TrimTo(50))
|
||||
.WithOkColor();
|
||||
|
@@ -82,7 +82,6 @@ public class TypingGame
|
||||
|
||||
do
|
||||
{
|
||||
// todo fix all modifies
|
||||
await Task.Delay(2000);
|
||||
time -= 2;
|
||||
try { await msg.ModifyAsync(m => m.Content = $"Starting new typing contest in **{time}**.."); }
|
||||
@@ -145,7 +144,7 @@ public class TypingGame
|
||||
var wpm = CurrentSentence.Length / WORD_VALUE / elapsed.TotalSeconds * 60;
|
||||
_finishedUserIds.Add(msg.Author.Id);
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle($"{msg.Author} finished the race!")
|
||||
.AddField("Place", $"#{_finishedUserIds.Count}", true)
|
||||
|
@@ -73,7 +73,7 @@ public class TicTacToe
|
||||
|
||||
public EmbedBuilder GetEmbed(string title = null)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(Environment.NewLine + GetState())
|
||||
.WithAuthor(GetText(strs.vs(_users[0], _users[1])));
|
||||
|
@@ -160,7 +160,7 @@ public partial class Games
|
||||
{
|
||||
try
|
||||
{
|
||||
questionEmbed = new EmbedBuilder()
|
||||
questionEmbed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.trivia_game))
|
||||
.AddField(GetText(strs.category), question.Category)
|
||||
@@ -189,7 +189,7 @@ public partial class Games
|
||||
{
|
||||
try
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithErrorColor()
|
||||
.WithTitle(GetText(strs.trivia_game))
|
||||
.WithDescription(GetText(strs.trivia_times_up(Format.Bold(question.Answer))));
|
||||
@@ -221,7 +221,7 @@ public partial class Games
|
||||
{
|
||||
try
|
||||
{
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(strs.trivia_ended))
|
||||
.WithTitle(GetText(strs.leaderboard))
|
||||
@@ -247,7 +247,7 @@ public partial class Games
|
||||
{
|
||||
try
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.trivia_game))
|
||||
.WithDescription(GetText(strs.trivia_win(user.Name,
|
||||
|
@@ -84,32 +84,32 @@ public sealed class Help : NadekoModule<HelpService>
|
||||
topLevelModules.Add(m);
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var embed = new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.list_of_modules));
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(topLevelModules)
|
||||
.CurrentPage(page)
|
||||
.AddFooter(false)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.list_of_modules));
|
||||
|
||||
var localModules = topLevelModules.Skip(12 * cur).Take(12).ToList();
|
||||
if (!items.Any())
|
||||
{
|
||||
embed = embed.WithOkColor().WithDescription(GetText(strs.module_page_empty));
|
||||
return embed;
|
||||
}
|
||||
|
||||
if (!localModules.Any())
|
||||
{
|
||||
embed = embed.WithOkColor().WithDescription(GetText(strs.module_page_empty));
|
||||
return embed;
|
||||
}
|
||||
items.OrderBy(module => module.Name)
|
||||
.ToList()
|
||||
.ForEach(module => embed.AddField($"{GetModuleEmoji(module.Name)} {module.Name}",
|
||||
GetModuleDescription(module.Name)
|
||||
+ "\n"
|
||||
+ Format.Code(GetText(strs.module_footer(prefix, module.Name.ToLowerInvariant()))),
|
||||
true));
|
||||
|
||||
localModules.OrderBy(module => module.Name)
|
||||
.ToList()
|
||||
.ForEach(module => embed.AddField($"{GetModuleEmoji(module.Name)} {module.Name}",
|
||||
GetModuleDescription(module.Name)
|
||||
+ "\n"
|
||||
+ Format.Code(GetText(strs.module_footer(prefix, module.Name.ToLowerInvariant()))),
|
||||
true));
|
||||
|
||||
return embed;
|
||||
},
|
||||
topLevelModules.Count(),
|
||||
12,
|
||||
false);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
private string GetModuleDescription(string moduleName)
|
||||
@@ -271,7 +271,7 @@ public sealed class Help : NadekoModule<HelpService>
|
||||
|
||||
var cnt = 0;
|
||||
var groups = cmdsWithGroup.GroupBy(_ => cnt++ / 48).ToArray();
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
foreach (var g in groups)
|
||||
{
|
||||
var last = g.Count();
|
||||
@@ -303,9 +303,9 @@ public sealed class Help : NadekoModule<HelpService>
|
||||
|
||||
private async Task Group(ModuleInfo group)
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.cmd_group_commands(group.Name)))
|
||||
.WithOkColor();
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.cmd_group_commands(group.Name)))
|
||||
.WithOkColor();
|
||||
|
||||
foreach (var cmd in group.Commands.DistinctBy(x => x.Aliases[0]))
|
||||
{
|
||||
@@ -358,7 +358,8 @@ public sealed class Help : NadekoModule<HelpService>
|
||||
var data = await GetHelpString();
|
||||
if (data == default)
|
||||
return;
|
||||
await ch.SendAsync(data);
|
||||
|
||||
await Response().Text(data).SendAsync();
|
||||
try
|
||||
{
|
||||
await ctx.OkAsync();
|
||||
@@ -534,9 +535,9 @@ public sealed class Help : NadekoModule<HelpService>
|
||||
label: "Selfhosting"),
|
||||
SelfhostAction));
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle("Thank you for considering to donate to the NadekoBot project!");
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("Thank you for considering to donate to the NadekoBot project!");
|
||||
|
||||
eb
|
||||
.WithDescription("NadekoBot relies on donations to keep the servers, services and APIs running.\n"
|
||||
@@ -575,7 +576,12 @@ Nadeko will DM you the welcome instructions, and you may start using the patron-
|
||||
|
||||
try
|
||||
{
|
||||
await (await ctx.User.CreateDMChannelAsync()).EmbedAsync(eb, inter: selfhostInter);
|
||||
await Response()
|
||||
.Channel(await ctx.User.CreateDMChannelAsync())
|
||||
.Embed(eb)
|
||||
.Interaction(selfhostInter)
|
||||
.SendAsync();
|
||||
|
||||
_ = ctx.OkAsync();
|
||||
}
|
||||
catch
|
||||
|
@@ -2,11 +2,22 @@ using NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
namespace NadekoBot.Modules.Help.Services;
|
||||
|
||||
public class HelpService(BotConfigService bss, IReplacementService repSvc) : IExecNoCommand, INService
|
||||
public class HelpService : IExecNoCommand, INService
|
||||
{
|
||||
private readonly BotConfigService _bss;
|
||||
private readonly IReplacementService _rs;
|
||||
private readonly IMessageSenderService _sender;
|
||||
|
||||
public HelpService(BotConfigService bss, IReplacementService repSvc, IMessageSenderService sender)
|
||||
{
|
||||
_bss = bss;
|
||||
_rs = repSvc;
|
||||
_sender = sender;
|
||||
}
|
||||
|
||||
public async Task ExecOnNoCommandAsync(IGuild? guild, IUserMessage msg)
|
||||
{
|
||||
var settings = bss.Data;
|
||||
var settings = _bss.Data;
|
||||
if (guild is null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(settings.DmHelpText) || settings.DmHelpText == "-")
|
||||
@@ -14,20 +25,20 @@ public class HelpService(BotConfigService bss, IReplacementService repSvc) : IEx
|
||||
|
||||
// only send dm help text if it contains one of the keywords, if they're specified
|
||||
// if they're not, then reply to every DM
|
||||
if (settings.DmHelpTextKeywords is not null &&
|
||||
!settings.DmHelpTextKeywords.Any(k => msg.Content.Contains(k)))
|
||||
if (settings.DmHelpTextKeywords is not null
|
||||
&& !settings.DmHelpTextKeywords.Any(k => msg.Content.Contains(k)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var repCtx = new ReplacementContext(guild: guild, channel: msg.Channel, users: msg.Author)
|
||||
.WithOverride("%prefix%", () => bss.Data.Prefix)
|
||||
.WithOverride("%bot.prefix%", () => bss.Data.Prefix);
|
||||
.WithOverride("%prefix%", () => _bss.Data.Prefix)
|
||||
.WithOverride("%bot.prefix%", () => _bss.Data.Prefix);
|
||||
|
||||
var text = SmartText.CreateFrom(settings.DmHelpText);
|
||||
text = await repSvc.ReplaceAsync(text, repCtx);
|
||||
text = await _rs.ReplaceAsync(text, repCtx);
|
||||
|
||||
await msg.Channel.SendAsync(text);
|
||||
await _sender.Response(msg.Channel).Text(text).SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,7 +11,7 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
{
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
public async Task MedusaLoad(string? name = null)
|
||||
@@ -21,11 +21,11 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
var loaded = _service.GetLoadedMedusae()
|
||||
.Select(x => x.Name)
|
||||
.ToHashSet();
|
||||
|
||||
|
||||
var unloaded = _service.GetAllMedusae()
|
||||
.Where(x => !loaded.Contains(x))
|
||||
.Select(x => Format.Code(x.ToString()))
|
||||
.ToArray();
|
||||
.Where(x => !loaded.Contains(x))
|
||||
.Select(x => Format.Code(x.ToString()))
|
||||
.ToArray();
|
||||
|
||||
if (unloaded.Length == 0)
|
||||
{
|
||||
@@ -33,16 +33,18 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
page =>
|
||||
{
|
||||
return new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.list_of_unloaded))
|
||||
.WithDescription(unloaded.Skip(10 * page).Take(10).Join('\n'));
|
||||
},
|
||||
unloaded.Length,
|
||||
10);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(unloaded)
|
||||
.PageSize(10)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.list_of_unloaded))
|
||||
.WithDescription(items.Join('\n'));
|
||||
})
|
||||
.SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
await Response().Error(locStr).SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
public async Task MedusaUnload(string? name = null)
|
||||
@@ -77,15 +79,17 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
return;
|
||||
}
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.loaded_medusae))
|
||||
.WithDescription(loaded.Select(x => x.Name)
|
||||
.Join("\n"))).SendAsync();
|
||||
|
||||
await Response()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.loaded_medusae))
|
||||
.WithDescription(loaded.Select(x => x.Name)
|
||||
.Join("\n")))
|
||||
.SendAsync();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var res = await _service.UnloadMedusaAsync(name);
|
||||
if (res == MedusaUnloadResult.Success)
|
||||
await Response().Confirm(strs.medusa_unloaded(Format.Code(name))).SendAsync();
|
||||
@@ -113,27 +117,29 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
await Response().Pending(strs.no_medusa_available).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var loaded = _service.GetLoadedMedusae()
|
||||
.Select(x => x.Name)
|
||||
.ToHashSet();
|
||||
|
||||
var output = all
|
||||
.Select(m =>
|
||||
{
|
||||
var emoji = loaded.Contains(m) ? "`✅`" : "`🔴`";
|
||||
return $"{emoji} `{m}`";
|
||||
})
|
||||
.ToArray();
|
||||
.Select(m =>
|
||||
{
|
||||
var emoji = loaded.Contains(m) ? "`✅`" : "`🔴`";
|
||||
return $"{emoji} `{m}`";
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
page => new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.list_of_medusae))
|
||||
.WithDescription(output.Skip(page * 10).Take(10).Join('\n')),
|
||||
output.Length,
|
||||
10);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(output)
|
||||
.PageSize(10)
|
||||
.Page((items, _) => _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.list_of_medusae))
|
||||
.WithDescription(items.Join('\n')))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -147,7 +153,7 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
var found = medusae.FirstOrDefault(x => string.Equals(x.Name,
|
||||
name,
|
||||
StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
|
||||
if (found is null)
|
||||
{
|
||||
await Response().Error(strs.medusa_name_not_found).SendAsync();
|
||||
@@ -156,26 +162,26 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
|
||||
var cmdCount = found.Sneks.Sum(x => x.Commands.Count);
|
||||
var cmdNames = found.Sneks
|
||||
.SelectMany(x => Format.Code(string.IsNullOrWhiteSpace(x.Prefix)
|
||||
? x.Name
|
||||
: $"{x.Prefix} {x.Name}"))
|
||||
.Join("\n");
|
||||
.SelectMany(x => Format.Code(string.IsNullOrWhiteSpace(x.Prefix)
|
||||
? x.Name
|
||||
: $"{x.Prefix} {x.Name}"))
|
||||
.Join("\n");
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(strs.medusa_info))
|
||||
.WithTitle(found.Name)
|
||||
.WithDescription(found.Description)
|
||||
.AddField(GetText(strs.sneks_count(found.Sneks.Count)),
|
||||
found.Sneks.Count == 0
|
||||
? "-"
|
||||
: found.Sneks.Select(x => x.Name).Join('\n'),
|
||||
true)
|
||||
.AddField(GetText(strs.commands_count(cmdCount)),
|
||||
string.IsNullOrWhiteSpace(cmdNames)
|
||||
? "-"
|
||||
: cmdNames,
|
||||
true);
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(strs.medusa_info))
|
||||
.WithTitle(found.Name)
|
||||
.WithDescription(found.Description)
|
||||
.AddField(GetText(strs.sneks_count(found.Sneks.Count)),
|
||||
found.Sneks.Count == 0
|
||||
? "-"
|
||||
: found.Sneks.Select(x => x.Name).Join('\n'),
|
||||
true)
|
||||
.AddField(GetText(strs.commands_count(cmdCount)),
|
||||
string.IsNullOrWhiteSpace(cmdNames)
|
||||
? "-"
|
||||
: cmdNames,
|
||||
true);
|
||||
|
||||
await Response().Embed(eb).SendAsync();
|
||||
return;
|
||||
@@ -186,42 +192,49 @@ public partial class Medusa : NadekoModule<IMedusaLoaderService>
|
||||
await Response().Pending(strs.no_medusa_loaded).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
page =>
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor();
|
||||
|
||||
foreach (var medusa in medusae.Skip(page * 9).Take(9))
|
||||
{
|
||||
eb.AddField(medusa.Name,
|
||||
$"""
|
||||
`Sneks:` {medusa.Sneks.Count}
|
||||
`Commands:` {medusa.Sneks.Sum(x => x.Commands.Count)}
|
||||
--
|
||||
{medusa.Description}
|
||||
""");
|
||||
}
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(medusae)
|
||||
.PageSize(9)
|
||||
.CurrentPage(0)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor();
|
||||
|
||||
return eb;
|
||||
}, medusae.Count, 9);
|
||||
foreach (var medusa in items)
|
||||
{
|
||||
eb.AddField(medusa.Name,
|
||||
$"""
|
||||
`Sneks:` {medusa.Sneks.Count}
|
||||
`Commands:` {medusa.Sneks.Sum(x => x.Commands.Count)}
|
||||
--
|
||||
{medusa.Description}
|
||||
""");
|
||||
}
|
||||
|
||||
return eb;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
public async Task MedusaSearch()
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.list_of_medusae))
|
||||
.WithOkColor();
|
||||
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.list_of_medusae))
|
||||
.WithOkColor();
|
||||
|
||||
foreach (var item in await _repo.GetModuleItemsAsync())
|
||||
{
|
||||
eb.AddField(item.Name, $"""
|
||||
{item.Description}
|
||||
`{item.Command}`
|
||||
""", true);
|
||||
eb.AddField(item.Name,
|
||||
$"""
|
||||
{item.Description}
|
||||
`{item.Command}`
|
||||
""",
|
||||
true);
|
||||
}
|
||||
|
||||
await Response().Embed(eb).SendAsync();
|
||||
|
@@ -109,11 +109,11 @@ public sealed partial class Music : NadekoModule<IMusicService>
|
||||
|
||||
try
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(strs.queued_track) + " #" + (index + 1), MUSIC_ICON_URL)
|
||||
.WithDescription($"{trackInfo.PrettyName()}\n{GetText(strs.queue)} ")
|
||||
.WithFooter(trackInfo.Platform.ToString());
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(strs.queued_track) + " #" + (index + 1), MUSIC_ICON_URL)
|
||||
.WithDescription($"{trackInfo.PrettyName()}\n{GetText(strs.queue)} ")
|
||||
.WithFooter(trackInfo.Platform.ToString());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trackInfo.Thumbnail))
|
||||
embed.WithThumbnailUrl(trackInfo.Thumbnail);
|
||||
@@ -273,7 +273,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder PrintAction(int curPage)
|
||||
EmbedBuilder PrintAction(IReadOnlyList<IQueuedTrackInfo> tracks, int curPage)
|
||||
{
|
||||
var desc = string.Empty;
|
||||
var current = mp.GetCurrentTrack(out var currentIndex);
|
||||
@@ -300,32 +300,38 @@ public sealed partial class Music : NadekoModule<IMusicService>
|
||||
}
|
||||
|
||||
|
||||
desc += tracks.Skip(LQ_ITEMS_PER_PAGE * curPage)
|
||||
.Take(LQ_ITEMS_PER_PAGE)
|
||||
.Select((v, index) =>
|
||||
{
|
||||
index += LQ_ITEMS_PER_PAGE * curPage;
|
||||
if (index == currentIndex)
|
||||
return $"**⇒**`{index + 1}.` {v.PrettyFullName()}";
|
||||
desc += tracks
|
||||
.Select((v, index) =>
|
||||
{
|
||||
index += LQ_ITEMS_PER_PAGE * curPage;
|
||||
if (index == currentIndex)
|
||||
return $"**⇒**`{index + 1}.` {v.PrettyFullName()}";
|
||||
|
||||
return $"`{index + 1}.` {v.PrettyFullName()}";
|
||||
})
|
||||
.Join('\n');
|
||||
return $"`{index + 1}.` {v.PrettyFullName()}";
|
||||
})
|
||||
.Join('\n');
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(add))
|
||||
desc = add + "\n" + desc;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor(GetText(strs.player_queue(curPage + 1, (tracks.Count / LQ_ITEMS_PER_PAGE) + 1)),
|
||||
MUSIC_ICON_URL)
|
||||
.WithDescription(desc)
|
||||
.WithFooter($" {mp.PrettyVolume()} | 🎶 {tracks.Count} | ⌛ {mp.PrettyTotalTime()} ")
|
||||
.WithOkColor();
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor(GetText(strs.player_queue(curPage + 1, (tracks.Count / LQ_ITEMS_PER_PAGE) + 1)),
|
||||
MUSIC_ICON_URL)
|
||||
.WithDescription(desc)
|
||||
.WithFooter($" {mp.PrettyVolume()} | 🎶 {tracks.Count} | ⌛ {mp.PrettyTotalTime()} ")
|
||||
.WithOkColor();
|
||||
|
||||
return embed;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page, PrintAction, tracks.Count, LQ_ITEMS_PER_PAGE, false);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(tracks)
|
||||
.PageSize(LQ_ITEMS_PER_PAGE)
|
||||
.CurrentPage(page)
|
||||
.AddFooter(false)
|
||||
.Page(PrintAction)
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
// search
|
||||
@@ -408,11 +414,11 @@ public sealed partial class Music : NadekoModule<IMusicService>
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor(GetText(strs.removed_track) + " #" + index, MUSIC_ICON_URL)
|
||||
.WithDescription(track.PrettyName())
|
||||
.WithFooter(track.PrettyInfo())
|
||||
.WithErrorColor();
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor(GetText(strs.removed_track) + " #" + index, MUSIC_ICON_URL)
|
||||
.WithDescription(track.PrettyName())
|
||||
.WithFooter(track.PrettyInfo())
|
||||
.WithErrorColor();
|
||||
|
||||
await _service.SendToOutputAsync(ctx.Guild.Id, embed);
|
||||
}
|
||||
@@ -576,12 +582,12 @@ public sealed partial class Music : NadekoModule<IMusicService>
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle(track.Title.TrimTo(65))
|
||||
.WithAuthor(GetText(strs.track_moved), MUSIC_ICON_URL)
|
||||
.AddField(GetText(strs.from_position), $"#{from + 1}", true)
|
||||
.AddField(GetText(strs.to_position), $"#{to + 1}", true)
|
||||
.WithOkColor();
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(track.Title.TrimTo(65))
|
||||
.WithAuthor(GetText(strs.track_moved), MUSIC_ICON_URL)
|
||||
.AddField(GetText(strs.from_position), $"#{from + 1}", true)
|
||||
.AddField(GetText(strs.to_position), $"#{to + 1}", true)
|
||||
.WithOkColor();
|
||||
|
||||
if (Uri.IsWellFormedUriString(track.Url, UriKind.Absolute))
|
||||
embed.WithUrl(track.Url);
|
||||
@@ -635,13 +641,13 @@ public sealed partial class Music : NadekoModule<IMusicService>
|
||||
if (currentTrack is null)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(strs.now_playing), MUSIC_ICON_URL)
|
||||
.WithDescription(currentTrack.PrettyName())
|
||||
.WithThumbnailUrl(currentTrack.Thumbnail)
|
||||
.WithFooter(
|
||||
$"{mp.PrettyVolume()} | {mp.PrettyTotalTime()} | {currentTrack.Platform} | {currentTrack.Queuer}");
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(strs.now_playing), MUSIC_ICON_URL)
|
||||
.WithDescription(currentTrack.PrettyName())
|
||||
.WithThumbnailUrl(currentTrack.Thumbnail)
|
||||
.WithFooter(
|
||||
$"{mp.PrettyVolume()} | {mp.PrettyTotalTime()} | {currentTrack.Platform} | {currentTrack.Queuer}");
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ public sealed partial class Music
|
||||
playlists = uow.Set<MusicPlaylist>().GetPlaylistsOnPage(num);
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor(GetText(strs.playlists_page(num)), MUSIC_ICON_URL)
|
||||
.WithDescription(string.Join("\n",
|
||||
playlists.Select(r => GetText(strs.playlists(r.Id, r.Name, r.Author, r.Songs.Count)))))
|
||||
@@ -103,20 +103,22 @@ public sealed partial class Music
|
||||
mpl = uow.Set<MusicPlaylist>().GetWithSongs(id);
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var i = 0;
|
||||
var str = string.Join("\n",
|
||||
mpl.Songs.Skip(cur * 20)
|
||||
.Take(20)
|
||||
.Select(x => $"`{++i}.` [{x.Title.TrimTo(45)}]({x.Query}) `{x.Provider}`"));
|
||||
return new EmbedBuilder().WithTitle($"\"{mpl.Name}\" by {mpl.Author}")
|
||||
.WithOkColor()
|
||||
.WithDescription(str);
|
||||
},
|
||||
mpl.Songs.Count,
|
||||
20);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(mpl.Songs)
|
||||
.PageSize(20)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var i = 0;
|
||||
var str = string.Join("\n",
|
||||
items
|
||||
.Select(x => $"`{++i}.` [{x.Title.TrimTo(45)}]({x.Query}) `{x.Provider}`"));
|
||||
return _sender.CreateEmbed().WithTitle($"\"{mpl.Name}\" by {mpl.Author}")
|
||||
.WithOkColor()
|
||||
.WithDescription(str);
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -154,7 +156,7 @@ public sealed partial class Music
|
||||
}
|
||||
|
||||
await Response()
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.playlist_saved))
|
||||
.AddField(GetText(strs.name), name)
|
||||
|
@@ -163,7 +163,9 @@ public sealed class MusicService : IMusicService
|
||||
{
|
||||
if (_outputChannels.TryGetValue(guildId, out var chan))
|
||||
{
|
||||
var msg = await (chan.Override ?? chan.Default).EmbedAsync(embed);
|
||||
var msg = await _sender.Response(chan.Override ?? chan.Default)
|
||||
.Embed(embed)
|
||||
.SendAsync();
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -176,11 +178,11 @@ public sealed class MusicService : IMusicService
|
||||
return async (mp, trackInfo) =>
|
||||
{
|
||||
_ = lastFinishedMessage?.DeleteAsync();
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(guildId, strs.finished_track), Music.MUSIC_ICON_URL)
|
||||
.WithDescription(trackInfo.PrettyName())
|
||||
.WithFooter(trackInfo.PrettyTotalTime());
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(guildId, strs.finished_track), Music.MUSIC_ICON_URL)
|
||||
.WithDescription(trackInfo.PrettyName())
|
||||
.WithFooter(trackInfo.PrettyTotalTime());
|
||||
|
||||
lastFinishedMessage = await SendToOutputAsync(guildId, embed);
|
||||
};
|
||||
@@ -192,11 +194,11 @@ public sealed class MusicService : IMusicService
|
||||
return async (mp, trackInfo, index) =>
|
||||
{
|
||||
_ = lastPlayingMessage?.DeleteAsync();
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(guildId, strs.playing_track(index + 1)), Music.MUSIC_ICON_URL)
|
||||
.WithDescription(trackInfo.PrettyName())
|
||||
.WithFooter($"{mp.PrettyVolume()} | {trackInfo.PrettyInfo()}");
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(GetText(guildId, strs.playing_track(index + 1)), Music.MUSIC_ICON_URL)
|
||||
.WithDescription(trackInfo.PrettyName())
|
||||
.WithFooter($"{mp.PrettyVolume()} | {trackInfo.PrettyInfo()}");
|
||||
|
||||
lastPlayingMessage = await SendToOutputAsync(guildId, embed);
|
||||
};
|
||||
@@ -279,9 +281,9 @@ public sealed class MusicService : IMusicService
|
||||
yield return ("%music.playing%", () =>
|
||||
{
|
||||
var randomPlayingTrack = _players.Select(x => x.Value.GetCurrentTrack(out _))
|
||||
.Where(x => x is not null)
|
||||
.Shuffle()
|
||||
.FirstOrDefault();
|
||||
.Where(x => x is not null)
|
||||
.Shuffle()
|
||||
.FirstOrDefault();
|
||||
|
||||
if (randomPlayingTrack is null)
|
||||
return "-";
|
||||
|
@@ -171,7 +171,7 @@ public sealed class CurrencyRewardService : INService, IDisposable
|
||||
if (user is null)
|
||||
return;
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(message);
|
||||
|
||||
|
@@ -49,7 +49,7 @@ public partial class Patronage : NadekoModule
|
||||
//
|
||||
// var patron = _service.GiftPatronAsync(user, amount);
|
||||
//
|
||||
// var eb = new EmbedBuilder();
|
||||
// var eb = _sender.CreateEmbed();
|
||||
//
|
||||
// await Response().Embed(eb.WithDescription($"Added **{days}** days of Patron benefits to {user.Mention}!")
|
||||
// .AddField("Tier", Format.Bold(patron.Tier.ToString()), true)
|
||||
@@ -70,7 +70,7 @@ public partial class Patronage : NadekoModule
|
||||
var patron = await _service.GetPatronAsync(user.Id);
|
||||
var quotaStats = await _service.GetUserQuotaStatistic(user.Id);
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithAuthor(user)
|
||||
.WithTitle(GetText(strs.patron_info))
|
||||
.WithOkColor();
|
||||
|
@@ -306,7 +306,7 @@ public sealed class PatronageService
|
||||
_ => false,
|
||||
ins =>
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithPendingColor()
|
||||
.WithTitle("Insufficient Patron Tier")
|
||||
.AddField("For", $"{ins.FeatureType}: `{ins.Feature}`", true)
|
||||
@@ -336,7 +336,7 @@ public sealed class PatronageService
|
||||
},
|
||||
quota =>
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithPendingColor()
|
||||
.WithTitle("Quota Limit Reached");
|
||||
|
||||
@@ -778,7 +778,7 @@ public sealed class PatronageService
|
||||
if (user is null)
|
||||
return;
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("❤️ Thank you for supporting NadekoBot! ❤️")
|
||||
.WithDescription(
|
||||
|
@@ -60,12 +60,12 @@ public partial class Permissions
|
||||
.Page((pageItems, _) =>
|
||||
{
|
||||
if (pageItems.Count == 0)
|
||||
return new EmbedBuilder()
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(title)
|
||||
.WithDescription(GetText(strs.empty_page));
|
||||
|
||||
return new EmbedBuilder()
|
||||
return _sender.CreateEmbed()
|
||||
.WithTitle(title)
|
||||
.WithDescription(allItems.Join('\n'))
|
||||
.WithOkColor();
|
||||
|
@@ -61,7 +61,7 @@ public partial class Permissions
|
||||
else
|
||||
await Response().Confirm(strs.cmdcd_add(Format.Bold(name), Format.Bold(secs.ToString()))).SendAsync();
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[Priority(0)]
|
||||
@@ -80,7 +80,7 @@ public partial class Permissions
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
var localSet = _service.GetCommandCooldowns(ctx.Guild.Id);
|
||||
|
||||
@@ -88,17 +88,21 @@ public partial class Permissions
|
||||
await Response().Confirm(strs.cmdcd_none).SendAsync();
|
||||
else
|
||||
{
|
||||
await ctx.SendPaginatedConfirmAsync(page, curPage =>
|
||||
{
|
||||
var items = localSet.Skip(curPage * 15)
|
||||
.Take(15)
|
||||
.Select(x => $"{Format.Code(x.CommandName)}: {x.Seconds.Seconds().Humanize(maxUnit: TimeUnit.Second, culture: Culture)}");
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(localSet)
|
||||
.PageSize(15)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var output = items.Select(x =>
|
||||
$"{Format.Code(x.CommandName)}: {x.Seconds.Seconds().Humanize(maxUnit: TimeUnit.Second, culture: Culture)}");
|
||||
|
||||
return new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithDescription(items.Join("\n"));
|
||||
|
||||
}, localSet.Count, 15);
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(output.Join("\n"));
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,9 +29,9 @@ public partial class Permissions
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task FilterList()
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle("Server filter settings");
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("Server filter settings");
|
||||
|
||||
var config = await _service.GetFilterSettings(ctx.Guild.Id);
|
||||
|
||||
@@ -41,14 +41,14 @@ public partial class Permissions
|
||||
async Task<string> GetChannelListAsync(IReadOnlyCollection<ulong> channels)
|
||||
{
|
||||
var toReturn = (await channels
|
||||
.Select(async cid =>
|
||||
{
|
||||
var ch = await ctx.Guild.GetChannelAsync(cid);
|
||||
return ch is null
|
||||
? $"{cid} *missing*"
|
||||
: $"<#{cid}>";
|
||||
})
|
||||
.WhenAll())
|
||||
.Select(async cid =>
|
||||
{
|
||||
var ch = await ctx.Guild.GetChannelAsync(cid);
|
||||
return ch is null
|
||||
? $"{cid} *missing*"
|
||||
: $"<#{cid}>";
|
||||
})
|
||||
.WhenAll())
|
||||
.Join('\n');
|
||||
|
||||
if (string.IsNullOrWhiteSpace(toReturn))
|
||||
@@ -312,13 +312,16 @@ public partial class Permissions
|
||||
|
||||
var fws = fwHash.ToArray();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage => new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.filter_word_list))
|
||||
.WithDescription(string.Join("\n", fws.Skip(curPage * 10).Take(10)))
|
||||
.WithOkColor(),
|
||||
fws.Length,
|
||||
10);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(fws)
|
||||
.PageSize(10)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) => _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.filter_word_list))
|
||||
.WithDescription(string.Join("\n", items))
|
||||
.WithOkColor())
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -30,7 +30,7 @@ public partial class Permissions
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
|
||||
if (blockedModule.Any())
|
||||
embed.AddField(GetText(strs.blocked_modules), string.Join("\n", _service.BlockedModules));
|
||||
|
@@ -24,7 +24,7 @@ public partial class Searches
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var embed = new EmbedBuilder()
|
||||
// var embed = _sender.CreateEmbed()
|
||||
// .WithOkColor()
|
||||
// .WithDescription(novelData.Description.Replace("<br>", Environment.NewLine, StringComparison.InvariantCulture))
|
||||
// .WithTitle(novelData.Title)
|
||||
@@ -86,7 +86,7 @@ public partial class Searches
|
||||
.Select(x => x.TextContent.Split(':').Select(y => y.Trim()).ToArray())
|
||||
.ToArray();
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.mal_profile(name)))
|
||||
.AddField("💚 " + GetText(strs.watching), stats[0], true)
|
||||
@@ -151,7 +151,7 @@ public partial class Searches
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(animeData.Synopsis.Replace("<br>",
|
||||
Environment.NewLine,
|
||||
@@ -183,7 +183,7 @@ public partial class Searches
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(mangaData.Synopsis.Replace("<br>",
|
||||
Environment.NewLine,
|
||||
|
@@ -35,7 +35,7 @@ public partial class Searches
|
||||
}
|
||||
|
||||
var symbol = symbols.First();
|
||||
var promptEmbed = new EmbedBuilder()
|
||||
var promptEmbed = _sender.CreateEmbed()
|
||||
.WithDescription(symbol.Description)
|
||||
.WithTitle(GetText(strs.did_you_mean(symbol.Symbol)));
|
||||
|
||||
@@ -79,7 +79,7 @@ public partial class Searches
|
||||
|
||||
var price = stock.Price.ToString("C2", localCulture);
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(stock.Symbol)
|
||||
.WithUrl($"https://www.tradingview.com/chart/?symbol={stock.Symbol}")
|
||||
@@ -127,7 +127,7 @@ public partial class Searches
|
||||
|
||||
if (nearest is not null)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.crypto_not_found))
|
||||
.WithDescription(
|
||||
GetText(strs.did_you_mean(Format.Bold($"{nearest.Name} ({nearest.Symbol})"))));
|
||||
@@ -160,7 +160,7 @@ public partial class Searches
|
||||
await using var sparkline = await _service.GetSparklineAsync(crypto.Id, usd.PercentChange7d >= 0);
|
||||
var fileName = $"{crypto.Slug}_7d.png";
|
||||
|
||||
var toSend = new EmbedBuilder()
|
||||
var toSend = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor($"#{crypto.CmcRank}")
|
||||
.WithTitle($"{crypto.Name} ({crypto.Symbol})")
|
||||
|
@@ -111,28 +111,36 @@ public partial class Searches
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageMessages)]
|
||||
public async Task FeedList()
|
||||
public async Task FeedList(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
var feeds = _service.GetFeeds(ctx.Guild.Id);
|
||||
|
||||
if (!feeds.Any())
|
||||
{
|
||||
await Response().Embed(new EmbedBuilder().WithOkColor().WithDescription(GetText(strs.feed_no_feed))).SendAsync();
|
||||
await Response()
|
||||
.Embed(_sender.CreateEmbed().WithOkColor().WithDescription(GetText(strs.feed_no_feed)))
|
||||
.SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
cur =>
|
||||
{
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var i = 0;
|
||||
var fs = string.Join("\n",
|
||||
feeds.Skip(cur * 10).Take(10).Select(x => $"`{(cur * 10) + ++i}.` <#{x.ChannelId}> {x.Url}"));
|
||||
|
||||
return embed.WithDescription(fs);
|
||||
},
|
||||
feeds.Count,
|
||||
10);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(feeds)
|
||||
.PageSize(10)
|
||||
.CurrentPage(page)
|
||||
.Page((items, cur) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
var i = 0;
|
||||
var fs = string.Join("\n",
|
||||
items.Select(x => $"`{(cur * 10) + ++i}.` <#{x.ChannelId}> {x.Url}"));
|
||||
|
||||
return embed.WithDescription(fs);
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,14 +31,14 @@ public class FeedsService : INService
|
||||
{
|
||||
var guildConfigIds = bot.AllGuildConfigs.Select(x => x.Id).ToList();
|
||||
_subs = uow.Set<GuildConfig>()
|
||||
.AsQueryable()
|
||||
.Where(x => guildConfigIds.Contains(x.Id))
|
||||
.Include(x => x.FeedSubs)
|
||||
.ToList()
|
||||
.SelectMany(x => x.FeedSubs)
|
||||
.GroupBy(x => x.Url.ToLower())
|
||||
.ToDictionary(x => x.Key, x => x.ToList())
|
||||
.ToConcurrent();
|
||||
.AsQueryable()
|
||||
.Where(x => guildConfigIds.Contains(x.Id))
|
||||
.Include(x => x.FeedSubs)
|
||||
.ToList()
|
||||
.SelectMany(x => x.FeedSubs)
|
||||
.GroupBy(x => x.Url.ToLower())
|
||||
.ToDictionary(x => x.Key, x => x.ToList())
|
||||
.ToConcurrent();
|
||||
}
|
||||
|
||||
_client = client;
|
||||
@@ -61,7 +61,7 @@ public class FeedsService : INService
|
||||
// remove from db
|
||||
await using var ctx = _db.GetDbContext();
|
||||
await ctx.GetTable<FeedSub>()
|
||||
.DeleteAsync(x => ids.Contains(x.Id));
|
||||
.DeleteAsync(x => ids.Contains(x.Id));
|
||||
|
||||
// remove from the local cache
|
||||
_subs.TryRemove(url, out _);
|
||||
@@ -95,14 +95,14 @@ public class FeedsService : INService
|
||||
var feed = await FeedReader.ReadAsync(rssUrl);
|
||||
|
||||
var items = feed
|
||||
.Items.Select(item => (Item: item,
|
||||
LastUpdate: item.PublishingDate?.ToUniversalTime()
|
||||
?? (item.SpecificItem as AtomFeedItem)?.UpdatedDate?.ToUniversalTime()))
|
||||
.Where(data => data.LastUpdate is not null)
|
||||
.Select(data => (data.Item, LastUpdate: (DateTime)data.LastUpdate))
|
||||
.OrderByDescending(data => data.LastUpdate)
|
||||
.Reverse() // start from the oldest
|
||||
.ToList();
|
||||
.Items.Select(item => (Item: item,
|
||||
LastUpdate: item.PublishingDate?.ToUniversalTime()
|
||||
?? (item.SpecificItem as AtomFeedItem)?.UpdatedDate?.ToUniversalTime()))
|
||||
.Where(data => data.LastUpdate is not null)
|
||||
.Select(data => (data.Item, LastUpdate: (DateTime)data.LastUpdate))
|
||||
.OrderByDescending(data => data.LastUpdate)
|
||||
.Reverse() // start from the oldest
|
||||
.ToList();
|
||||
|
||||
if (!_lastPosts.TryGetValue(kvp.Key, out var lastFeedUpdate))
|
||||
{
|
||||
@@ -115,7 +115,7 @@ public class FeedsService : INService
|
||||
if (itemUpdateDate <= lastFeedUpdate)
|
||||
continue;
|
||||
|
||||
var embed = new EmbedBuilder().WithFooter(rssUrl);
|
||||
var embed = _sender.CreateEmbed().WithFooter(rssUrl);
|
||||
|
||||
_lastPosts[kvp.Key] = itemUpdateDate;
|
||||
|
||||
@@ -141,12 +141,12 @@ public class FeedsService : INService
|
||||
if (!gotImage && feedItem.SpecificItem is AtomFeedItem afi)
|
||||
{
|
||||
var previewElement = afi.Element.Elements()
|
||||
.FirstOrDefault(x => x.Name.LocalName == "preview");
|
||||
.FirstOrDefault(x => x.Name.LocalName == "preview");
|
||||
|
||||
if (previewElement is null)
|
||||
{
|
||||
previewElement = afi.Element.Elements()
|
||||
.FirstOrDefault(x => x.Name.LocalName == "thumbnail");
|
||||
.FirstOrDefault(x => x.Name.LocalName == "thumbnail");
|
||||
}
|
||||
|
||||
if (previewElement is not null)
|
||||
@@ -170,11 +170,23 @@ public class FeedsService : INService
|
||||
|
||||
//send the created embed to all subscribed channels
|
||||
var feedSendTasks = kvp.Value
|
||||
.Where(x => x.GuildConfig is not null)
|
||||
.Select(x => _client.GetGuild(x.GuildConfig.GuildId)
|
||||
?.GetTextChannel(x.ChannelId)
|
||||
?.EmbedAsync(embed, string.IsNullOrWhiteSpace(x.Message) ? "" : x.Message))
|
||||
.Where(x => x is not null);
|
||||
.Where(x => x.GuildConfig is not null)
|
||||
.Select(x =>
|
||||
{
|
||||
var ch = _client.GetGuild(x.GuildConfig.GuildId)
|
||||
?.GetTextChannel(x.ChannelId);
|
||||
|
||||
if (ch is null)
|
||||
return null;
|
||||
|
||||
return _sender.Response(ch)
|
||||
.Embed(embed)
|
||||
.Text(string.IsNullOrWhiteSpace(x.Message)
|
||||
? string.Empty
|
||||
: x.Message)
|
||||
.SendAsync();
|
||||
})
|
||||
.Where(x => x is not null);
|
||||
|
||||
allSendTasks.Add(feedSendTasks.WhenAll());
|
||||
|
||||
@@ -202,11 +214,15 @@ public class FeedsService : INService
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
return uow.GuildConfigsForId(guildId, set => set.Include(x => x.FeedSubs))
|
||||
.FeedSubs.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
.FeedSubs.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public FeedAddResult AddFeed(ulong guildId, ulong channelId, string rssFeed, string message)
|
||||
public FeedAddResult AddFeed(
|
||||
ulong guildId,
|
||||
ulong channelId,
|
||||
string rssFeed,
|
||||
string message)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(rssFeed, nameof(rssFeed));
|
||||
|
||||
@@ -252,8 +268,8 @@ public class FeedsService : INService
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var items = uow.GuildConfigsForId(guildId, set => set.Include(x => x.FeedSubs))
|
||||
.FeedSubs.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
.FeedSubs.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
|
||||
if (items.Count <= index)
|
||||
return false;
|
||||
|
@@ -40,18 +40,21 @@ public partial class Searches
|
||||
|
||||
var data = JsonConvert.DeserializeObject<List<MemegenTemplate>>(rawJson)!;
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var templates = string.Empty;
|
||||
foreach (var template in data.Skip(curPage * 15).Take(15))
|
||||
templates += $"**{template.Name}:**\n key: `{template.Id}`\n";
|
||||
var embed = new EmbedBuilder().WithOkColor().WithDescription(templates);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(data)
|
||||
.PageSize(15)
|
||||
.CurrentPage(page)
|
||||
.Page((items, curPage) =>
|
||||
{
|
||||
var templates = string.Empty;
|
||||
foreach (var template in items)
|
||||
templates += $"**{template.Name}:**\n key: `{template.Id}`\n";
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithDescription(templates);
|
||||
|
||||
return embed;
|
||||
},
|
||||
data.Count,
|
||||
15);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -49,7 +49,7 @@ public partial class Searches
|
||||
var obj = objs[0];
|
||||
var userId = obj.UserId;
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle($"osu! {smode} profile for {user}")
|
||||
.WithThumbnailUrl($"https://a.ppy.sh/{userId}")
|
||||
@@ -95,7 +95,7 @@ public partial class Searches
|
||||
var userData = JsonConvert.DeserializeObject<GatariUserResponse>(usrResString).Users[0];
|
||||
var userStats = statsResponse.Stats;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle($"osu!Gatari {modeStr} profile for {user}")
|
||||
.WithThumbnailUrl($"https://a.gatari.pw/{userStats.Id}")
|
||||
@@ -166,7 +166,7 @@ public partial class Searches
|
||||
return (title, desc);
|
||||
});
|
||||
|
||||
var eb = new EmbedBuilder().WithOkColor().WithTitle($"Top 5 plays for {user}");
|
||||
var eb = _sender.CreateEmbed().WithOkColor().WithTitle($"Top 5 plays for {user}");
|
||||
|
||||
var mapData = await mapTasks.WhenAll();
|
||||
foreach (var (title, desc) in mapData.Where(x => x != default))
|
||||
|
@@ -135,7 +135,7 @@ public partial class Searches
|
||||
}
|
||||
catch
|
||||
{
|
||||
var embed = new EmbedBuilder().WithDescription(GetText(strs.account_not_found)).WithErrorColor();
|
||||
var embed = _sender.CreateEmbed().WithDescription(GetText(strs.account_not_found)).WithErrorColor();
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
return;
|
||||
@@ -144,37 +144,38 @@ public partial class Searches
|
||||
if (!string.IsNullOrWhiteSpace(league))
|
||||
characters.RemoveAll(c => c.League != league);
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor($"Characters on {usr}'s account",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
$"{PROFILE_URL}{usr}")
|
||||
.WithOkColor();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(characters)
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, curPage) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor($"Characters on {usr}'s account",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
$"{PROFILE_URL}{usr}")
|
||||
.WithOkColor();
|
||||
|
||||
var tempList = characters.Skip(curPage * 9).Take(9).ToList();
|
||||
if (characters.Count == 0)
|
||||
return embed.WithDescription("This account has no characters.");
|
||||
|
||||
if (characters.Count == 0)
|
||||
return embed.WithDescription("This account has no characters.");
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"```{"#",-5}{"Character Name",-23}{"League",-10}{"Class",-13}{"Level",-3}");
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
var character = items[i];
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"```{"#",-5}{"Character Name",-23}{"League",-10}{"Class",-13}{"Level",-3}");
|
||||
for (var i = 0; i < tempList.Count; i++)
|
||||
{
|
||||
var character = tempList[i];
|
||||
sb.AppendLine(
|
||||
$"#{i + 1 + (curPage * 9),-4}{character.Name,-23}{ShortLeagueName(character.League),-10}{character.Class,-13}{character.Level,-3}");
|
||||
}
|
||||
|
||||
sb.AppendLine(
|
||||
$"#{i + 1 + (curPage * 9),-4}{character.Name,-23}{ShortLeagueName(character.League),-10}{character.Class,-13}{character.Level,-3}");
|
||||
}
|
||||
sb.AppendLine("```");
|
||||
embed.WithDescription(sb.ToString());
|
||||
|
||||
sb.AppendLine("```");
|
||||
embed.WithDescription(sb.ToString());
|
||||
|
||||
return embed;
|
||||
},
|
||||
characters.Count,
|
||||
9);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -190,17 +191,17 @@ public partial class Searches
|
||||
}
|
||||
catch
|
||||
{
|
||||
var eembed = new EmbedBuilder().WithDescription(GetText(strs.leagues_not_found)).WithErrorColor();
|
||||
var eembed = _sender.CreateEmbed().WithDescription(GetText(strs.leagues_not_found)).WithErrorColor();
|
||||
|
||||
await Response().Embed(eembed).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor("Path of Exile Leagues",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
"https://www.pathofexile.com")
|
||||
.WithOkColor();
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor("Path of Exile Leagues",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
"https://www.pathofexile.com")
|
||||
.WithOkColor();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"```{"#",-5}{"League Name",-23}");
|
||||
@@ -273,19 +274,19 @@ public partial class Searches
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor($"{leagueName} Currency Exchange",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
"http://poe.ninja")
|
||||
.AddField("Currency Type", cleanCurrency, true)
|
||||
.AddField($"{cleanConvert} Equivalent", chaosEquivalent / conversionEquivalent, true)
|
||||
.WithOkColor();
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor($"{leagueName} Currency Exchange",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
"http://poe.ninja")
|
||||
.AddField("Currency Type", cleanCurrency, true)
|
||||
.AddField($"{cleanConvert} Equivalent", chaosEquivalent / conversionEquivalent, true)
|
||||
.WithOkColor();
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
var embed = new EmbedBuilder().WithDescription(GetText(strs.ninja_not_found)).WithErrorColor();
|
||||
var embed = _sender.CreateEmbed().WithDescription(GetText(strs.ninja_not_found)).WithErrorColor();
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ public partial class Searches
|
||||
if (kvp.Key.ToUpperInvariant() == pokemon.ToUpperInvariant())
|
||||
{
|
||||
var p = kvp.Value;
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(kvp.Key.ToTitleCase())
|
||||
.WithDescription(p.BaseStats.ToString())
|
||||
@@ -55,7 +55,7 @@ public partial class Searches
|
||||
{
|
||||
if (kvp.Key.ToUpperInvariant() == ability)
|
||||
{
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(kvp.Value.Name)
|
||||
.WithDescription(string.IsNullOrWhiteSpace(kvp.Value.Desc)
|
||||
|
@@ -59,7 +59,7 @@ public partial class Searches
|
||||
|
||||
descStr = descStr.TrimTo(4096);
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithTitle(query.TrimTo(64)!)
|
||||
@@ -98,7 +98,7 @@ public partial class Searches
|
||||
|
||||
EmbedBuilder CreateEmbed(IImageSearchResultEntry entry)
|
||||
{
|
||||
return new EmbedBuilder()
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithTitle(query)
|
||||
@@ -190,7 +190,7 @@ public partial class Searches
|
||||
//
|
||||
// var descStr = string.Join("\n\n", desc);
|
||||
//
|
||||
// var embed = new EmbedBuilder()
|
||||
// var embed = _sender.CreateEmbed()
|
||||
// .WithAuthor(ctx.User.ToString(),
|
||||
// "https://upload.wikimedia.org/wikipedia/en/9/90/The_DuckDuckGo_Duck.png")
|
||||
// .WithDescription($"{GetText(strs.search_for)} **{query}**\n\n" + descStr)
|
||||
|
@@ -54,7 +54,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
if (!await ValidateQuery(query))
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder();
|
||||
var embed = _sender.CreateEmbed();
|
||||
var data = await _service.GetWeatherDataAsync(query);
|
||||
|
||||
if (data is null)
|
||||
@@ -134,7 +134,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.time_new))
|
||||
.WithDescription(Format.Code(data.Time.ToString(Culture)))
|
||||
@@ -160,7 +160,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
}
|
||||
|
||||
await Response()
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(movie.Title)
|
||||
.WithUrl($"https://www.imdb.com/title/{movie.ImdbId}/")
|
||||
@@ -191,7 +191,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
private Task InternalRandomImage(SearchesService.ImageTag tag)
|
||||
{
|
||||
var url = _service.GetRandomImageUrl(tag);
|
||||
return Response().Embed(new EmbedBuilder().WithOkColor().WithImageUrl(url)).SendAsync();
|
||||
return Response().Embed(_sender.CreateEmbed().WithOkColor().WithImageUrl(url)).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -242,7 +242,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
}
|
||||
|
||||
await Response()
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField(GetText(strs.original_url), $"<{query}>")
|
||||
.AddField(GetText(strs.short_url), $"<{shortLink}>"))
|
||||
@@ -264,7 +264,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(card.Name)
|
||||
.WithDescription(card.Description)
|
||||
@@ -297,7 +297,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor().WithImageUrl(card.Img);
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithImageUrl(card.Img);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(card.Flavor))
|
||||
embed.WithDescription(card.Flavor);
|
||||
@@ -318,21 +318,24 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
$"https://api.urbandictionary.com/v0/define?term={Uri.EscapeDataString(query)}");
|
||||
try
|
||||
{
|
||||
var items = JsonConvert.DeserializeObject<UrbanResponse>(res).List;
|
||||
if (items.Any())
|
||||
var allItems = JsonConvert.DeserializeObject<UrbanResponse>(res).List;
|
||||
if (allItems.Any())
|
||||
{
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
p =>
|
||||
{
|
||||
var item = items[p];
|
||||
return new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithUrl(item.Permalink)
|
||||
.WithTitle(item.Word)
|
||||
.WithDescription(item.Definition);
|
||||
},
|
||||
items.Length,
|
||||
1);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allItems)
|
||||
.PageSize(1)
|
||||
.CurrentPage(0)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var item = items[0];
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithUrl(item.Permalink)
|
||||
.WithTitle(item.Word)
|
||||
.WithDescription(item.Definition);
|
||||
})
|
||||
.SendAsync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -362,52 +365,54 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
+ WebUtility.UrlEncode(word));
|
||||
});
|
||||
|
||||
var data = JsonConvert.DeserializeObject<DefineModel>(res);
|
||||
var responseModel = JsonConvert.DeserializeObject<DefineModel>(res);
|
||||
|
||||
var datas = data.Results
|
||||
.Where(x => x.Senses is not null
|
||||
&& x.Senses.Count > 0
|
||||
&& x.Senses[0].Definition is not null)
|
||||
.Select(x => (Sense: x.Senses[0], x.PartOfSpeech))
|
||||
.ToList();
|
||||
var data = responseModel.Results
|
||||
.Where(x => x.Senses is not null
|
||||
&& x.Senses.Count > 0
|
||||
&& x.Senses[0].Definition is not null)
|
||||
.Select(x => (Sense: x.Senses[0], x.PartOfSpeech))
|
||||
.ToList();
|
||||
|
||||
if (!datas.Any())
|
||||
if (!data.Any())
|
||||
{
|
||||
Log.Warning("Definition not found: {Word}", word);
|
||||
await Response().Error(strs.define_unknown).SendAsync();
|
||||
}
|
||||
|
||||
|
||||
var col = datas.Select(x => (
|
||||
Definition: x.Sense.Definition is string
|
||||
? x.Sense.Definition.ToString()
|
||||
: ((JArray)JToken.Parse(x.Sense.Definition.ToString())).First.ToString(),
|
||||
Example: x.Sense.Examples is null || x.Sense.Examples.Count == 0
|
||||
? string.Empty
|
||||
: x.Sense.Examples[0].Text, Word: word,
|
||||
WordType: string.IsNullOrWhiteSpace(x.PartOfSpeech) ? "-" : x.PartOfSpeech))
|
||||
.ToList();
|
||||
var col = data.Select(x => (
|
||||
Definition: x.Sense.Definition is string
|
||||
? x.Sense.Definition.ToString()
|
||||
: ((JArray)JToken.Parse(x.Sense.Definition.ToString())).First.ToString(),
|
||||
Example: x.Sense.Examples is null || x.Sense.Examples.Count == 0
|
||||
? string.Empty
|
||||
: x.Sense.Examples[0].Text, Word: word,
|
||||
WordType: string.IsNullOrWhiteSpace(x.PartOfSpeech) ? "-" : x.PartOfSpeech))
|
||||
.ToList();
|
||||
|
||||
Log.Information("Sending {Count} definition for: {Word}", col.Count, word);
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
page =>
|
||||
{
|
||||
var model = col.Skip(page).First();
|
||||
var embed = new EmbedBuilder()
|
||||
.WithDescription(ctx.User.Mention)
|
||||
.AddField(GetText(strs.word), model.Word, true)
|
||||
.AddField(GetText(strs._class), model.WordType, true)
|
||||
.AddField(GetText(strs.definition), model.Definition)
|
||||
.WithOkColor();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(col)
|
||||
.PageSize(1)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var model = items.First();
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithDescription(ctx.User.Mention)
|
||||
.AddField(GetText(strs.word), model.Word, true)
|
||||
.AddField(GetText(strs._class), model.WordType, true)
|
||||
.AddField(GetText(strs.definition), model.Definition)
|
||||
.WithOkColor();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(model.Example))
|
||||
embed.AddField(GetText(strs.example), model.Example);
|
||||
if (!string.IsNullOrWhiteSpace(model.Example))
|
||||
embed.AddField(GetText(strs.example), model.Example);
|
||||
|
||||
return embed;
|
||||
},
|
||||
col.Count,
|
||||
1);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -474,7 +479,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
|
||||
await Response()
|
||||
.Embed(
|
||||
new EmbedBuilder()
|
||||
_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField("Username", usr.ToString())
|
||||
.AddField("Avatar Url", avatarUrl)
|
||||
@@ -542,7 +547,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
{
|
||||
var v = obj.Verses[0];
|
||||
await Response()
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle($"{v.BookName} {v.Chapter}:{v.Verse}")
|
||||
.WithDescription(v.Text))
|
||||
@@ -565,7 +570,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
return;
|
||||
}
|
||||
|
||||
//var embed = new EmbedBuilder()
|
||||
//var embed = _sender.CreateEmbed()
|
||||
// .WithOkColor()
|
||||
// .WithDescription(gameData.ShortDescription)
|
||||
// .WithTitle(gameData.Name)
|
||||
|
@@ -95,9 +95,9 @@ public partial class Searches
|
||||
.Page((elements, cur) =>
|
||||
{
|
||||
if (elements.Count == 0)
|
||||
return new EmbedBuilder().WithDescription(GetText(strs.streams_none)).WithErrorColor();
|
||||
return _sender.CreateEmbed().WithDescription(GetText(strs.streams_none)).WithErrorColor();
|
||||
|
||||
var eb = new EmbedBuilder().WithTitle(GetText(strs.streams_follow_title)).WithOkColor();
|
||||
var eb = _sender.CreateEmbed().WithTitle(GetText(strs.streams_follow_title)).WithOkColor();
|
||||
for (var index = 0; index < elements.Count; index++)
|
||||
{
|
||||
var elem = elements[index];
|
||||
|
@@ -73,34 +73,34 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
{
|
||||
var ids = client.GetGuildIds();
|
||||
var guildConfigs = uow.Set<GuildConfig>()
|
||||
.AsQueryable()
|
||||
.Include(x => x.FollowedStreams)
|
||||
.Where(x => ids.Contains(x.GuildId))
|
||||
.ToList();
|
||||
.AsQueryable()
|
||||
.Include(x => x.FollowedStreams)
|
||||
.Where(x => ids.Contains(x.GuildId))
|
||||
.ToList();
|
||||
|
||||
_offlineNotificationServers = new(guildConfigs
|
||||
.Where(gc => gc.NotifyStreamOffline)
|
||||
.Select(x => x.GuildId)
|
||||
.ToList());
|
||||
.Where(gc => gc.NotifyStreamOffline)
|
||||
.Select(x => x.GuildId)
|
||||
.ToList());
|
||||
|
||||
_deleteOnOfflineServers = new(guildConfigs
|
||||
.Where(gc => gc.DeleteStreamOnlineMessage)
|
||||
.Select(x => x.GuildId)
|
||||
.ToList());
|
||||
.Where(gc => gc.DeleteStreamOnlineMessage)
|
||||
.Select(x => x.GuildId)
|
||||
.ToList());
|
||||
|
||||
var followedStreams = guildConfigs.SelectMany(x => x.FollowedStreams).ToList();
|
||||
|
||||
_shardTrackedStreams = followedStreams.GroupBy(x => new
|
||||
{
|
||||
x.Type,
|
||||
Name = x.Username.ToLower()
|
||||
})
|
||||
.ToList()
|
||||
.ToDictionary(
|
||||
x => new StreamDataKey(x.Key.Type, x.Key.Name.ToLower()),
|
||||
x => x.GroupBy(y => y.GuildId)
|
||||
.ToDictionary(y => y.Key,
|
||||
y => y.AsEnumerable().ToHashSet()));
|
||||
{
|
||||
x.Type,
|
||||
Name = x.Username.ToLower()
|
||||
})
|
||||
.ToList()
|
||||
.ToDictionary(
|
||||
x => new StreamDataKey(x.Key.Type, x.Key.Name.ToLower()),
|
||||
x => x.GroupBy(y => y.GuildId)
|
||||
.ToDictionary(y => y.Key,
|
||||
y => y.AsEnumerable().ToHashSet()));
|
||||
|
||||
// shard 0 will keep track of when there are no more guilds which track a stream
|
||||
if (client.ShardId == 0)
|
||||
@@ -111,12 +111,12 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
_streamTracker.AddLastData(fs.CreateKey(), null, false);
|
||||
|
||||
_trackCounter = allFollowedStreams.GroupBy(x => new
|
||||
{
|
||||
x.Type,
|
||||
Name = x.Username.ToLower()
|
||||
})
|
||||
.ToDictionary(x => new StreamDataKey(x.Key.Type, x.Key.Name),
|
||||
x => x.Select(fs => fs.GuildId).ToHashSet());
|
||||
{
|
||||
x.Type,
|
||||
Name = x.Username.ToLower()
|
||||
})
|
||||
.ToDictionary(x => new StreamDataKey(x.Key.Type, x.Key.Name),
|
||||
x => x.Select(fs => fs.GuildId).ToHashSet());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
continue;
|
||||
|
||||
var deleteGroups = failingStreams.GroupBy(x => x.Type)
|
||||
.ToDictionary(x => x.Key, x => x.Select(y => y.Name).ToList());
|
||||
.ToDictionary(x => x.Key, x => x.Select(y => y.Name).ToList());
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
foreach (var kvp in deleteGroups)
|
||||
@@ -169,9 +169,9 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
string.Join(", ", kvp.Value));
|
||||
|
||||
var toDelete = uow.Set<FollowedStream>()
|
||||
.AsQueryable()
|
||||
.Where(x => x.Type == kvp.Key && kvp.Value.Contains(x.Username))
|
||||
.ToList();
|
||||
.AsQueryable()
|
||||
.Where(x => x.Type == kvp.Key && kvp.Value.Contains(x.Username))
|
||||
.ToList();
|
||||
|
||||
uow.RemoveRange(toDelete);
|
||||
await uow.SaveChangesAsync();
|
||||
@@ -250,13 +250,20 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
if (_shardTrackedStreams.TryGetValue(key, out var fss))
|
||||
{
|
||||
await fss
|
||||
// send offline stream notifications only to guilds which enable it with .stoff
|
||||
.SelectMany(x => x.Value)
|
||||
.Where(x => _offlineNotificationServers.Contains(x.GuildId))
|
||||
.Select(fs => _client.GetGuild(fs.GuildId)
|
||||
?.GetTextChannel(fs.ChannelId)
|
||||
?.EmbedAsync(GetEmbed(fs.GuildId, stream)))
|
||||
.WhenAll();
|
||||
// send offline stream notifications only to guilds which enable it with .stoff
|
||||
.SelectMany(x => x.Value)
|
||||
.Where(x => _offlineNotificationServers.Contains(x.GuildId))
|
||||
.Select(fs =>
|
||||
{
|
||||
var ch = _client.GetGuild(fs.GuildId)
|
||||
?.GetTextChannel(fs.ChannelId);
|
||||
|
||||
if (ch is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return _sender.Response(ch).Embed(GetEmbed(fs.GuildId, stream)).SendAsync();
|
||||
})
|
||||
.WhenAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,33 +277,35 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
if (_shardTrackedStreams.TryGetValue(key, out var fss))
|
||||
{
|
||||
var messages = await fss.SelectMany(x => x.Value)
|
||||
.Select(async fs =>
|
||||
{
|
||||
var textChannel = _client.GetGuild(fs.GuildId)?.GetTextChannel(fs.ChannelId);
|
||||
.Select(async fs =>
|
||||
{
|
||||
var textChannel = _client.GetGuild(fs.GuildId)
|
||||
?.GetTextChannel(fs.ChannelId);
|
||||
|
||||
if (textChannel is null)
|
||||
return default;
|
||||
if (textChannel is null)
|
||||
return default;
|
||||
|
||||
var repCtx = new ReplacementContext(guild: textChannel.Guild, client: _client)
|
||||
.WithOverride("%platform%", () => fs.Type.ToString());
|
||||
var repCtx = new ReplacementContext(guild: textChannel.Guild,
|
||||
client: _client)
|
||||
.WithOverride("%platform%", () => fs.Type.ToString());
|
||||
|
||||
|
||||
var message = string.IsNullOrWhiteSpace(fs.Message)
|
||||
? ""
|
||||
: await _repSvc.ReplaceAsync(fs.Message, repCtx);
|
||||
var message = string.IsNullOrWhiteSpace(fs.Message)
|
||||
? ""
|
||||
: await _repSvc.ReplaceAsync(fs.Message, repCtx);
|
||||
|
||||
var msg = await _sender.Response(textChannel)
|
||||
.Embed(GetEmbed(fs.GuildId, stream, false))
|
||||
.Text(message)
|
||||
.SendAsync();
|
||||
var msg = await _sender.Response(textChannel)
|
||||
.Embed(GetEmbed(fs.GuildId, stream, false))
|
||||
.Text(message)
|
||||
.SendAsync();
|
||||
|
||||
// only cache the ids of channel/message pairs
|
||||
if (_deleteOnOfflineServers.Contains(fs.GuildId))
|
||||
return (textChannel.Id, msg.Id);
|
||||
else
|
||||
return default;
|
||||
})
|
||||
.WhenAll();
|
||||
// only cache the ids of channel/message pairs
|
||||
if (_deleteOnOfflineServers.Contains(fs.GuildId))
|
||||
return (textChannel.Id, msg.Id);
|
||||
else
|
||||
return default;
|
||||
})
|
||||
.WhenAll();
|
||||
|
||||
|
||||
// push online stream messages to redis
|
||||
@@ -306,9 +315,9 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
try
|
||||
{
|
||||
var pairs = messages
|
||||
.Where(x => x != default)
|
||||
.Select(x => (x.Item1, x.Item2))
|
||||
.ToList();
|
||||
.Where(x => x != default)
|
||||
.Select(x => (x.Item1, x.Item2))
|
||||
.ToList();
|
||||
|
||||
if (pairs.Count > 0)
|
||||
await OnlineMessagesSent(key.Type, key.Name, pairs);
|
||||
@@ -330,9 +339,10 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var gc = uow.Set<GuildConfig>().AsQueryable()
|
||||
.Include(x => x.FollowedStreams)
|
||||
.FirstOrDefault(x => x.GuildId == guildConfig.GuildId);
|
||||
var gc = uow.Set<GuildConfig>()
|
||||
.AsQueryable()
|
||||
.Include(x => x.FollowedStreams)
|
||||
.FirstOrDefault(x => x.GuildId == guildConfig.GuildId);
|
||||
|
||||
if (gc is null)
|
||||
return Task.CompletedTask;
|
||||
@@ -392,10 +402,10 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var fss = uow.Set<FollowedStream>()
|
||||
.AsQueryable()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
.AsQueryable()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
|
||||
// out of range
|
||||
if (fss.Count <= index)
|
||||
@@ -484,11 +494,11 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
|
||||
public EmbedBuilder GetEmbed(ulong guildId, StreamData status, bool showViewers = true)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle(status.Name)
|
||||
.WithUrl(status.StreamUrl)
|
||||
.WithDescription(status.StreamUrl)
|
||||
.AddField(GetText(guildId, strs.status), status.IsLive ? "🟢 Online" : "🔴 Offline", true);
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(status.Name)
|
||||
.WithUrl(status.StreamUrl)
|
||||
.WithDescription(status.StreamUrl)
|
||||
.AddField(GetText(guildId, strs.status), status.IsLive ? "🟢 Online" : "🔴 Offline", true);
|
||||
|
||||
if (showViewers)
|
||||
{
|
||||
|
@@ -69,7 +69,7 @@ public sealed class TranslateService : ITranslateService, IExecNoCommand, IReady
|
||||
|| msg.Content.Equals(output, StringComparison.InvariantCultureIgnoreCase))
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
|
||||
if (autoDelete)
|
||||
{
|
||||
|
@@ -20,7 +20,7 @@ public partial class Searches
|
||||
await ctx.Channel.TriggerTypingAsync();
|
||||
var translation = await _service.Translate(from, to, text);
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor().AddField(from, text).AddField(to, translation);
|
||||
var embed = _sender.CreateEmbed().WithOkColor().AddField(from, text).AddField(to, translation);
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
@@ -80,7 +80,7 @@ public partial class Searches
|
||||
{
|
||||
var langs = _service.GetLanguages().ToList();
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.supported_languages))
|
||||
.WithOkColor();
|
||||
|
||||
|
@@ -25,7 +25,7 @@ public partial class Searches
|
||||
using var http = _httpFactory.CreateClient();
|
||||
var res = await http.GetStringAsync($"{XKCD_URL}/info.0.json");
|
||||
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithImageUrl(comic.ImageLink)
|
||||
.WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{XKCD_URL}/{comic.Num}")
|
||||
@@ -60,7 +60,7 @@ public partial class Searches
|
||||
var res = await http.GetStringAsync($"{XKCD_URL}/{num}/info.0.json");
|
||||
|
||||
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithImageUrl(comic.ImageLink)
|
||||
.WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{XKCD_URL}/{num}")
|
||||
|
@@ -121,17 +121,19 @@ public partial class Utility
|
||||
|
||||
var arr = maps.ToArray();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
return new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.alias_list))
|
||||
.WithDescription(string.Join("\n",
|
||||
arr.Skip(curPage * 10).Take(10).Select(x => $"`{x.Key}` => `{x.Value}`")));
|
||||
},
|
||||
arr.Length,
|
||||
10);
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(arr)
|
||||
.PageSize(10)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.alias_list))
|
||||
.WithDescription(string.Join("\n", items.Select(x => $"`{x.Key}` => `{x.Value}`")));
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -20,7 +20,7 @@ public partial class Utility
|
||||
if (setting is null)
|
||||
{
|
||||
var configNames = _settingServices.Select(x => x.Name);
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithErrorColor()
|
||||
.WithDescription(GetText(strs.config_not_found(Format.Code(name))))
|
||||
.AddField(GetText(strs.config_list), string.Join("\n", configNames));
|
||||
@@ -43,7 +43,7 @@ public partial class Utility
|
||||
name = name?.ToLowerInvariant();
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.config_list))
|
||||
.WithDescription(string.Join("\n", configNames));
|
||||
@@ -58,7 +58,7 @@ public partial class Utility
|
||||
// if config name is not found, print error and the list of configs
|
||||
if (setting is null)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithErrorColor()
|
||||
.WithDescription(GetText(strs.config_not_found(Format.Code(name))))
|
||||
.AddField(GetText(strs.config_list), string.Join("\n", configNames));
|
||||
@@ -75,7 +75,7 @@ public partial class Utility
|
||||
if (string.IsNullOrWhiteSpace(prop))
|
||||
{
|
||||
var propStrings = GetPropsAndValuesString(setting, propNames);
|
||||
var embed = new EmbedBuilder().WithOkColor().WithTitle($"⚙️ {setting.Name}").WithDescription(propStrings);
|
||||
var embed = _sender.CreateEmbed().WithOkColor().WithTitle($"⚙️ {setting.Name}").WithDescription(propStrings);
|
||||
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
@@ -88,7 +88,7 @@ public partial class Utility
|
||||
if (!exists)
|
||||
{
|
||||
var propStrings = GetPropsAndValuesString(setting, propNames);
|
||||
var propErrorEmbed = new EmbedBuilder()
|
||||
var propErrorEmbed = _sender.CreateEmbed()
|
||||
.WithErrorColor()
|
||||
.WithDescription(GetText(
|
||||
strs.config_prop_not_found(Format.Code(prop), Format.Code(name))))
|
||||
@@ -110,7 +110,7 @@ public partial class Utility
|
||||
if (prop != "currency.sign")
|
||||
value = Format.Code(Format.Sanitize(value.TrimTo(1000)), "json");
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField("Config", Format.Code(setting.Name), true)
|
||||
.AddField("Prop", Format.Code(prop), true)
|
||||
|
@@ -17,7 +17,7 @@ public partial class Utility
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithPendingColor()
|
||||
.WithTitle(GetText(strs.giveaway_starting))
|
||||
.WithDescription(message);
|
||||
@@ -103,7 +103,7 @@ public partial class Utility
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.giveaway_list))
|
||||
.WithOkColor();
|
||||
|
||||
|
@@ -317,7 +317,7 @@ public sealed class GiveawayService : INService, IReadyExecutor
|
||||
{Format.Code(winner.UserId.ToString())}
|
||||
""";
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.giveaway_ended))
|
||||
.WithDescription(ga.Message)
|
||||
|
@@ -54,7 +54,7 @@ public partial class Utility
|
||||
if (string.IsNullOrWhiteSpace(features))
|
||||
features = "-";
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor(GetText(strs.server_info))
|
||||
.WithTitle(guild.Name)
|
||||
.AddField(GetText(strs.id), guild.Id.ToString(), true)
|
||||
@@ -87,7 +87,7 @@ public partial class Utility
|
||||
return;
|
||||
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ch.Id >> 22);
|
||||
var usercount = (await ch.GetUsersAsync().FlattenAsync()).Count();
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(ch.Name)
|
||||
.WithDescription(ch.Topic?.SanitizeMentions(true))
|
||||
.AddField(GetText(strs.id), ch.Id.ToString(), true)
|
||||
@@ -107,7 +107,7 @@ public partial class Utility
|
||||
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
|
||||
.AddMilliseconds(role.Id >> 22);
|
||||
var usercount = role.Members.LongCount();
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(role.Name.TrimTo(128))
|
||||
.WithDescription(role.Permissions.ToList().Join(" | "))
|
||||
.AddField(GetText(strs.id), role.Id.ToString(), true)
|
||||
@@ -133,7 +133,7 @@ public partial class Utility
|
||||
if (user is null)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder().AddField(GetText(strs.name), $"**{user.Username}**#{user.Discriminator}", true);
|
||||
var embed = _sender.CreateEmbed().AddField(GetText(strs.name), $"**{user.Username}**#{user.Discriminator}", true);
|
||||
if (!string.IsNullOrWhiteSpace(user.Nickname))
|
||||
embed.AddField(GetText(strs.nickname), user.Nickname, true);
|
||||
|
||||
@@ -204,7 +204,7 @@ public partial class Utility
|
||||
kvp.Value)));
|
||||
}
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.activity_page(page + 1)))
|
||||
.WithOkColor()
|
||||
.WithFooter(GetText(
|
||||
|
@@ -47,9 +47,9 @@ public partial class Utility
|
||||
var i = 1;
|
||||
|
||||
if (!invs.Any())
|
||||
return new EmbedBuilder().WithErrorColor().WithDescription(GetText(strs.no_invites));
|
||||
return _sender.CreateEmbed().WithErrorColor().WithDescription(GetText(strs.no_invites));
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
foreach (var inv in invs)
|
||||
{
|
||||
var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null
|
||||
|
@@ -106,7 +106,10 @@ public partial class Utility
|
||||
var text = SmartText.CreateFrom(quote.Text);
|
||||
text = await repSvc.ReplaceAsync(text, repCtx);
|
||||
|
||||
await ctx.Channel.SendAsync($"`#{quote.Id}` 📣 " + text, true, replyTo: ctx.Message);
|
||||
await Response()
|
||||
.Text($"`#{quote.Id}` 📣 " + text)
|
||||
.Sanitize()
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -132,13 +135,13 @@ public partial class Utility
|
||||
|
||||
private async Task ShowQuoteData(Quote data)
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle($"{GetText(strs.quote_id($"#{data.Id}"))} | {GetText(strs.response)}:")
|
||||
.WithDescription(Format.Sanitize(data.Text).Replace("](", "]\\(").TrimTo(4096))
|
||||
.AddField(GetText(strs.trigger), data.Keyword)
|
||||
.WithFooter(
|
||||
GetText(strs.created_by($"{data.AuthorName} ({data.AuthorId})")));
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle($"{GetText(strs.quote_id($"#{data.Id}"))} | {GetText(strs.response)}:")
|
||||
.WithDescription(Format.Sanitize(data.Text).Replace("](", "]\\(").TrimTo(4096))
|
||||
.AddField(GetText(strs.trigger), data.Keyword)
|
||||
.WithFooter(
|
||||
GetText(strs.created_by($"{data.AuthorName} ({data.AuthorId})")));
|
||||
|
||||
if (!(data.Text.Length > 4096))
|
||||
{
|
||||
@@ -146,10 +149,12 @@ public partial class Utility
|
||||
return;
|
||||
}
|
||||
|
||||
// todo all send files should go through response system too
|
||||
await ctx.Channel.SendFileAsync(
|
||||
attachment: new FileAttachment(await data.Text.ToStream(), "quote.txt"),
|
||||
embed: eb.Build());
|
||||
await using var textStream = await data.Text.ToStream();
|
||||
|
||||
await Response()
|
||||
.Embed(eb)
|
||||
.File(textStream, "quote.txt")
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
private async Task QuoteSearchinternalAsync(string? keyword, string textOrAuthor)
|
||||
@@ -217,7 +222,10 @@ public partial class Utility
|
||||
|
||||
var text = SmartText.CreateFrom(quote.Text);
|
||||
text = await repSvc.ReplaceAsync(text, repCtx);
|
||||
await ctx.Channel.SendAsync(infoText + text, true, replyTo: ctx.Message);
|
||||
await Response()
|
||||
.Text(infoText + text)
|
||||
.Sanitize()
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -96,7 +96,7 @@ public partial class Utility
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(isServer ? strs.reminder_server_list : strs.reminder_list));
|
||||
|
||||
|
@@ -208,7 +208,7 @@ public class RemindService : INService, IReadyExecutor, IRemindService
|
||||
else
|
||||
{
|
||||
await _sender.Response(ch)
|
||||
.Embed(new EmbedBuilder()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle("Reminder")
|
||||
.AddField("Created At",
|
||||
|
@@ -64,7 +64,7 @@ public partial class Utility
|
||||
}
|
||||
|
||||
var description = GetRepeaterInfoString(removed);
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.repeater_removed(index + 1)))
|
||||
.WithDescription(description)).SendAsync();
|
||||
@@ -187,7 +187,7 @@ public partial class Utility
|
||||
}
|
||||
|
||||
var description = GetRepeaterInfoString(runner);
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
await Response().Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.repeater_created))
|
||||
.WithDescription(description)).SendAsync();
|
||||
@@ -205,7 +205,7 @@ public partial class Utility
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.list_of_repeaters)).WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.list_of_repeaters)).WithOkColor();
|
||||
|
||||
var i = 0;
|
||||
foreach (var runner in repeaters.OrderBy(r => r.Repeater.Id))
|
||||
|
@@ -19,24 +19,27 @@ public sealed class RepeaterService : IReadyExecutor, INService
|
||||
private readonly ConcurrentHashSet<int> _skipNext = new();
|
||||
|
||||
private readonly object _queueLocker = new();
|
||||
private readonly IMessageSenderService _sender;
|
||||
|
||||
public RepeaterService(
|
||||
DiscordSocketClient client,
|
||||
DbService db,
|
||||
IReplacementService repSvc,
|
||||
IBotCredentials creds)
|
||||
IBotCredentials creds,
|
||||
IMessageSenderService sender)
|
||||
{
|
||||
_db = db;
|
||||
_repSvc = repSvc;
|
||||
_creds = creds;
|
||||
_client = client;
|
||||
_sender = sender;
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var shardRepeaters = uow.Set<Repeater>()
|
||||
.Where(x => (int)(x.GuildId / Math.Pow(2, 22)) % _creds.TotalShards
|
||||
== _client.ShardId)
|
||||
.AsNoTracking()
|
||||
.ToList();
|
||||
.Where(x => (int)(x.GuildId / Math.Pow(2, 22)) % _creds.TotalShards
|
||||
== _client.ShardId)
|
||||
.AsNoTracking()
|
||||
.ToList();
|
||||
|
||||
_noRedundant = new(shardRepeaters.Where(x => x.NoRedundant).Select(x => x.Id));
|
||||
|
||||
@@ -125,10 +128,11 @@ public sealed class RepeaterService : IReadyExecutor, INService
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
|
||||
var toTrigger = await uow.Set<Repeater>().AsNoTracking()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
var toTrigger = await uow.Set<Repeater>()
|
||||
.AsNoTracking()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
|
||||
if (toTrigger is null)
|
||||
return false;
|
||||
@@ -265,7 +269,7 @@ public sealed class RepeaterService : IReadyExecutor, INService
|
||||
var text = SmartText.CreateFrom(repeater.Message);
|
||||
text = await _repSvc.ReplaceAsync(text, repCtx);
|
||||
|
||||
var newMsg = await channel.SendAsync(text);
|
||||
var newMsg = await _sender.Response(channel).Text(text).SendAsync();
|
||||
_ = newMsg.AddReactionAsync(new Emoji("🔄"));
|
||||
|
||||
if (_noRedundant.Contains(repeater.Id))
|
||||
@@ -308,12 +312,13 @@ public sealed class RepeaterService : IReadyExecutor, INService
|
||||
private async Task SetRepeaterLastMessageInternal(int repeaterId, ulong lastMsgId)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
await uow.Set<Repeater>().AsQueryable()
|
||||
.Where(x => x.Id == repeaterId)
|
||||
.UpdateAsync(rep => new()
|
||||
{
|
||||
LastMessageId = lastMsgId
|
||||
});
|
||||
await uow.Set<Repeater>()
|
||||
.AsQueryable()
|
||||
.Where(x => x.Id == repeaterId)
|
||||
.UpdateAsync(rep => new()
|
||||
{
|
||||
LastMessageId = lastMsgId
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<RunningRepeater?> AddRepeaterAsync(
|
||||
@@ -358,10 +363,11 @@ public sealed class RepeaterService : IReadyExecutor, INService
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
var toRemove = await uow.Set<Repeater>().AsNoTracking()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
var toRemove = await uow.Set<Repeater>()
|
||||
.AsNoTracking()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
|
||||
if (toRemove is null)
|
||||
return null;
|
||||
@@ -389,10 +395,11 @@ public sealed class RepeaterService : IReadyExecutor, INService
|
||||
public async Task<bool?> ToggleRedundantAsync(ulong guildId, int index)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var toToggle = await uow.Set<Repeater>().AsQueryable()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
var toToggle = await uow.Set<Repeater>()
|
||||
.AsQueryable()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
|
||||
if (toToggle is null)
|
||||
return null;
|
||||
@@ -411,9 +418,9 @@ public sealed class RepeaterService : IReadyExecutor, INService
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
var toSkip = await ctx.Set<Repeater>()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.Skip(index)
|
||||
.FirstOrDefaultAsyncEF();
|
||||
|
||||
if (toSkip is null)
|
||||
return null;
|
||||
|
@@ -81,27 +81,27 @@ public partial class Utility
|
||||
}
|
||||
|
||||
|
||||
private async Task ShowTodosAsync(TodoModel[] todos)
|
||||
{
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
(curPage) =>
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.todo_list));
|
||||
private Task ShowTodosAsync(TodoModel[] todos)
|
||||
=> Response()
|
||||
.Paginated()
|
||||
.Items(todos)
|
||||
.PageSize(9)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.todo_list));
|
||||
|
||||
ShowTodoItem(todos, curPage, eb);
|
||||
ShowTodoItem(items, eb);
|
||||
|
||||
return eb;
|
||||
},
|
||||
todos.Length,
|
||||
9);
|
||||
}
|
||||
return eb;
|
||||
})
|
||||
.SendAsync();
|
||||
|
||||
private static void ShowTodoItem(IReadOnlyCollection<TodoModel> todos, int curPage, EmbedBuilder eb)
|
||||
private static void ShowTodoItem(IReadOnlyCollection<TodoModel> todos, EmbedBuilder eb)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var todo in todos.Skip(curPage * 9).Take(9))
|
||||
foreach (var todo in todos)
|
||||
{
|
||||
sb.AppendLine($"{(todo.IsDone ? "✔" : "□")} {Format.Code(new kwum(todo.Id).ToString())} {todo.Todo}");
|
||||
|
||||
@@ -147,23 +147,25 @@ public partial class Utility
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
(curPage) =>
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.todo_archive_list))
|
||||
.WithOkColor();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(archivedTodoLists)
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.todo_archive_list))
|
||||
.WithOkColor();
|
||||
|
||||
foreach (var archivedList in archivedTodoLists.Skip(curPage * 9).Take(9))
|
||||
{
|
||||
eb.AddField($"id: {archivedList.Id.ToString()}", archivedList.Name, true);
|
||||
}
|
||||
foreach (var archivedList in items)
|
||||
{
|
||||
eb.AddField($"id: {archivedList.Id.ToString()}", archivedList.Name, true);
|
||||
}
|
||||
|
||||
return eb;
|
||||
},
|
||||
archivedTodoLists.Count,
|
||||
9,
|
||||
true);
|
||||
return eb;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -176,19 +178,21 @@ public partial class Utility
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
(curPage) =>
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.todo_list));
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(list.Items)
|
||||
.PageSize(9)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.todo_list));
|
||||
|
||||
ShowTodoItem(list.Items, curPage, eb);
|
||||
ShowTodoItem(items, eb);
|
||||
|
||||
return eb;
|
||||
},
|
||||
list.Items.Count,
|
||||
9);
|
||||
return eb;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -13,7 +13,7 @@ public partial class Utility
|
||||
{
|
||||
var units = await _service.GetUnitsAsync();
|
||||
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.convertlist)).WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.convertlist)).WithOkColor();
|
||||
|
||||
|
||||
foreach (var g in units.GroupBy(x => x.UnitType))
|
||||
|
@@ -83,9 +83,10 @@ public partial class Utility : NadekoModule
|
||||
var repCtx = new ReplacementContext(Context);
|
||||
message = await repSvc.ReplaceAsync(message, repCtx);
|
||||
|
||||
await channel.SendAsync(message,
|
||||
!((IGuildUser)ctx.User).GuildPermissions.MentionEveryone,
|
||||
replyTo: ctx.Message);
|
||||
await Response()
|
||||
.Text(message)
|
||||
.UserBasedMentions()
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -154,21 +155,22 @@ public partial class Utility : NadekoModule
|
||||
.Select(u => $"`{u.Id,18}` {u}")
|
||||
.ToArray();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var pageUsers = roleUsers.Skip(cur * 20).Take(20).ToList();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(roleUsers)
|
||||
.PageSize(20)
|
||||
.CurrentPage(page)
|
||||
.Page((pageUsers, _) =>
|
||||
{
|
||||
if (pageUsers.Count == 0)
|
||||
return _sender.CreateEmbed().WithOkColor().WithDescription(GetText(strs.no_user_on_this_page));
|
||||
|
||||
if (pageUsers.Count == 0)
|
||||
return new EmbedBuilder().WithOkColor().WithDescription(GetText(strs.no_user_on_this_page));
|
||||
|
||||
return new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.inrole_list(Format.Bold(role?.Name ?? "No Role"), roleUsers.Length)))
|
||||
.WithDescription(string.Join("\n", pageUsers));
|
||||
},
|
||||
roleUsers.Length,
|
||||
20);
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.inrole_list(Format.Bold(role?.Name ?? "No Role"), roleUsers.Length)))
|
||||
.WithDescription(string.Join("\n", pageUsers));
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -301,30 +303,32 @@ public partial class Utility : NadekoModule
|
||||
if (string.IsNullOrWhiteSpace(ownerIds))
|
||||
ownerIds = "-";
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithAuthor($"NadekoBot v{StatsService.BotVersion}",
|
||||
"https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/avatar.png",
|
||||
"https://nadekobot.readthedocs.io/en/latest/")
|
||||
.AddField(GetText(strs.author), _stats.Author, true)
|
||||
.AddField(GetText(strs.botid), _client.CurrentUser.Id.ToString(), true)
|
||||
.AddField(GetText(strs.shard),
|
||||
$"#{_client.ShardId} / {_creds.TotalShards}",
|
||||
true)
|
||||
.AddField(GetText(strs.commands_ran), _stats.CommandsRan.ToString(), true)
|
||||
.AddField(GetText(strs.messages),
|
||||
$"{_stats.MessageCounter} ({_stats.MessagesPerSecond:F2}/sec)",
|
||||
true)
|
||||
.AddField(GetText(strs.memory),
|
||||
FormattableString.Invariant($"{_stats.GetPrivateMemoryMegabytes():F2} MB"),
|
||||
true)
|
||||
.AddField(GetText(strs.owner_ids), ownerIds, true)
|
||||
.AddField(GetText(strs.uptime), _stats.GetUptimeString("\n"), true)
|
||||
.AddField(GetText(strs.presence),
|
||||
GetText(strs.presence_txt(_coord.GetGuildCount(),
|
||||
_stats.TextChannels,
|
||||
_stats.VoiceChannels)),
|
||||
true)).SendAsync();
|
||||
await Response()
|
||||
.Embed(_sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor($"NadekoBot v{StatsService.BotVersion}",
|
||||
"https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/avatar.png",
|
||||
"https://nadekobot.readthedocs.io/en/latest/")
|
||||
.AddField(GetText(strs.author), _stats.Author, true)
|
||||
.AddField(GetText(strs.botid), _client.CurrentUser.Id.ToString(), true)
|
||||
.AddField(GetText(strs.shard),
|
||||
$"#{_client.ShardId} / {_creds.TotalShards}",
|
||||
true)
|
||||
.AddField(GetText(strs.commands_ran), _stats.CommandsRan.ToString(), true)
|
||||
.AddField(GetText(strs.messages),
|
||||
$"{_stats.MessageCounter} ({_stats.MessagesPerSecond:F2}/sec)",
|
||||
true)
|
||||
.AddField(GetText(strs.memory),
|
||||
FormattableString.Invariant($"{_stats.GetPrivateMemoryMegabytes():F2} MB"),
|
||||
true)
|
||||
.AddField(GetText(strs.owner_ids), ownerIds, true)
|
||||
.AddField(GetText(strs.uptime), _stats.GetUptimeString("\n"), true)
|
||||
.AddField(GetText(strs.presence),
|
||||
GetText(strs.presence_txt(_coord.GetGuildCount(),
|
||||
_stats.TextChannels,
|
||||
_stats.VoiceChannels)),
|
||||
true))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -517,7 +521,7 @@ public partial class Utility : NadekoModule
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithOkColor();
|
||||
foreach (var guild in guilds)
|
||||
embed.AddField(guild.Name, GetText(strs.listservers(guild.Id, guild.MemberCount, guild.OwnerId)));
|
||||
|
||||
@@ -660,6 +664,7 @@ public partial class Utility : NadekoModule
|
||||
.WithReferences(this.GetType().Assembly)
|
||||
.WithImports(
|
||||
"System",
|
||||
"System.Linq",
|
||||
"NadekoBot",
|
||||
"NadekoBot.Extensions",
|
||||
"Microsoft.Extensions.DependencyInjection",
|
||||
@@ -683,10 +688,10 @@ public partial class Utility : NadekoModule
|
||||
var output = result.ReturnValue?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.AddField("Code", scriptText)
|
||||
.AddField("Output", output.TrimTo(512)!);
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField("Code", scriptText)
|
||||
.AddField("Output", output.TrimTo(512)!);
|
||||
|
||||
_ = Response().Embed(eb).SendAsync();
|
||||
}
|
||||
|
@@ -127,10 +127,9 @@ public partial class Xp
|
||||
.Paginated()
|
||||
.Items(allUsers)
|
||||
.PageSize(10)
|
||||
.CurrentPage(0)
|
||||
.Page((users, _) =>
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle($"{club}")
|
||||
.WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)")))
|
||||
@@ -206,22 +205,21 @@ public partial class Xp
|
||||
|
||||
var bans = club.Bans.Select(x => x.User).ToArray();
|
||||
|
||||
return ctx.SendPaginatedConfirmAsync(page,
|
||||
_ =>
|
||||
{
|
||||
var toShow = string.Join("\n",
|
||||
bans
|
||||
.Skip(page * 10)
|
||||
.Take(10)
|
||||
.Select(x => x.ToString()));
|
||||
return Response()
|
||||
.Paginated()
|
||||
.Items(bans)
|
||||
.PageSize(10)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var toShow = string.Join("\n", items.Select(x => x.ToString()));
|
||||
|
||||
return new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.club_bans_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
},
|
||||
bans.Length,
|
||||
10);
|
||||
return _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.club_bans_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -236,18 +234,21 @@ public partial class Xp
|
||||
|
||||
var apps = club.Applicants.Select(x => x.User).ToArray();
|
||||
|
||||
return ctx.SendPaginatedConfirmAsync(page,
|
||||
_ =>
|
||||
{
|
||||
var toShow = string.Join("\n", apps.Skip(page * 10).Take(10).Select(x => x.ToString()));
|
||||
return Response()
|
||||
.Paginated()
|
||||
.Items(apps)
|
||||
.PageSize(10)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var toShow = string.Join("\n", items.Select(x => x.ToString()));
|
||||
|
||||
return new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.club_apps_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
},
|
||||
apps.Length,
|
||||
10);
|
||||
return _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.club_apps_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -412,7 +413,7 @@ public partial class Xp
|
||||
? "-"
|
||||
: desc;
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithTitle(GetText(strs.club_desc_update))
|
||||
.WithOkColor()
|
||||
@@ -443,7 +444,7 @@ public partial class Xp
|
||||
|
||||
var clubs = _service.GetClubLeaderboardPage(page);
|
||||
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.club_leaderboard(page + 1))).WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.club_leaderboard(page + 1))).WithOkColor();
|
||||
|
||||
var i = page * 9;
|
||||
foreach (var club in clubs)
|
||||
@@ -464,7 +465,7 @@ public partial class Xp
|
||||
return;
|
||||
case ClubRenameResult.Success:
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor();
|
||||
await Response().Embed(embed).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
@@ -59,10 +59,10 @@ public partial class Xp : NadekoModule<XpService>
|
||||
var globalSetting = _service.GetNotificationType(ctx.User);
|
||||
var serverSetting = _service.GetNotificationType(ctx.User.Id, ctx.Guild.Id);
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.AddField(GetText(strs.xpn_setting_global), GetNotifLocationString(globalSetting))
|
||||
.AddField(GetText(strs.xpn_setting_server), GetNotifLocationString(serverSetting));
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.AddField(GetText(strs.xpn_setting_global), GetNotifLocationString(globalSetting))
|
||||
.AddField(GetText(strs.xpn_setting_server), GetNotifLocationString(serverSetting));
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
@@ -147,18 +147,21 @@ public partial class Xp : NadekoModule<XpService>
|
||||
desc += "\n\n" + rolesStr + chansStr;
|
||||
|
||||
var lines = desc.Split('\n');
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
curpage =>
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.exclusion_list))
|
||||
.WithDescription(string.Join('\n', lines.Skip(15 * curpage).Take(15)))
|
||||
.WithOkColor();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(lines)
|
||||
.PageSize(15)
|
||||
.CurrentPage(0)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.exclusion_list))
|
||||
.WithDescription(string.Join('\n', items))
|
||||
.WithOkColor();
|
||||
|
||||
return embed;
|
||||
},
|
||||
lines.Length,
|
||||
15);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -182,53 +185,54 @@ public partial class Xp : NadekoModule<XpService>
|
||||
await ctx.Channel.TriggerTypingAsync();
|
||||
|
||||
var socketGuild = (SocketGuild)ctx.Guild;
|
||||
var allUsers = new List<UserXpStats>();
|
||||
var allCleanUsers = new List<UserXpStats>();
|
||||
if (opts.Clean)
|
||||
{
|
||||
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();
|
||||
allCleanUsers = _service.GetTopUserXps(ctx.Guild.Id, 1000)
|
||||
.Where(user => socketGuild.GetUser(user.UserId) is not null)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.server_leaderboard)).WithOkColor();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.PageItems<UserXpStats>(opts.Clean
|
||||
? (curPage) => Task.FromResult<IEnumerable<UserXpStats>>(allCleanUsers.Skip(curPage * 9)
|
||||
.Take(9)
|
||||
.ToList())
|
||||
: (curPage) => Task.FromResult<IEnumerable<UserXpStats>>(_service.GetUserXps(ctx.Guild.Id, curPage)))
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.AddFooter(false)
|
||||
.Page((users, curPage) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed().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);
|
||||
if (!users.Any())
|
||||
return embed.WithDescription("-");
|
||||
|
||||
if (!users.Any())
|
||||
return embed.WithDescription("-");
|
||||
for (var 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);
|
||||
|
||||
for (var 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 userXpData = users[i];
|
||||
var awardStr = string.Empty;
|
||||
if (userXpData.AwardedXp > 0)
|
||||
awardStr = $"(+{userXpData.AwardedXp})";
|
||||
else if (userXpData.AwardedXp < 0)
|
||||
awardStr = $"({userXpData.AwardedXp})";
|
||||
|
||||
var awardStr = string.Empty;
|
||||
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(strs.level_x(levelStats.Level))} - {levelStats.TotalXp}xp {awardStr}");
|
||||
}
|
||||
|
||||
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,
|
||||
false);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -239,7 +243,7 @@ public partial class Xp : NadekoModule<XpService>
|
||||
return;
|
||||
var users = _service.GetUserXps(page);
|
||||
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.global_leaderboard)).WithOkColor();
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.global_leaderboard)).WithOkColor();
|
||||
|
||||
if (!users.Any())
|
||||
embed.WithDescription("-");
|
||||
@@ -317,7 +321,9 @@ public partial class Xp : NadekoModule<XpService>
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task XpReset(ulong userId)
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.reset)).WithDescription(GetText(strs.reset_user_confirm));
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.reset))
|
||||
.WithDescription(GetText(strs.reset_user_confirm));
|
||||
|
||||
if (!await PromptUserConfirmAsync(embed))
|
||||
return;
|
||||
@@ -332,7 +338,9 @@ public partial class Xp : NadekoModule<XpService>
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task XpReset()
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.reset)).WithDescription(GetText(strs.reset_server_confirm));
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.reset))
|
||||
.WithDescription(GetText(strs.reset_server_confirm));
|
||||
|
||||
if (!await PromptUserConfirmAsync(embed))
|
||||
return;
|
||||
@@ -383,94 +391,102 @@ public partial class Xp : NadekoModule<XpService>
|
||||
if (page < 0)
|
||||
return;
|
||||
|
||||
var items = type == XpShopInputType.Backgrounds
|
||||
var allItems = type == XpShopInputType.Backgrounds
|
||||
? await _service.GetShopBgs()
|
||||
: await _service.GetShopFrames();
|
||||
|
||||
if (items is null)
|
||||
if (allItems is null)
|
||||
{
|
||||
await Response().Error(strs.xp_shop_disabled).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
if (items.Count == 0)
|
||||
if (allItems.Count == 0)
|
||||
{
|
||||
await Response().Error(strs.not_found).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync<(string, XpShopItemType)?>(page,
|
||||
current =>
|
||||
{
|
||||
var (key, item) = items.Skip(current).First();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allItems)
|
||||
.PageSize(1)
|
||||
.CurrentPage(page)
|
||||
.AddFooter(false)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
if (!items.Any())
|
||||
return _sender.CreateEmbed()
|
||||
.WithDescription(GetText(strs.not_found))
|
||||
.WithErrorColor();
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(item.Name)
|
||||
.AddField(GetText(strs.price),
|
||||
CurrencyHelper.N(item.Price, Culture, _gss.GetCurrencySign()),
|
||||
true)
|
||||
.WithImageUrl(string.IsNullOrWhiteSpace(item.Preview)
|
||||
? item.Url
|
||||
: item.Preview);
|
||||
var (key, item) = items.FirstOrDefault();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(item.Desc))
|
||||
eb.AddField(GetText(strs.desc), item.Desc);
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(item.Name)
|
||||
.AddField(GetText(strs.price),
|
||||
CurrencyHelper.N(item.Price, Culture, _gss.GetCurrencySign()),
|
||||
true)
|
||||
.WithImageUrl(string.IsNullOrWhiteSpace(item.Preview)
|
||||
? item.Url
|
||||
: item.Preview);
|
||||
|
||||
if (key == "default")
|
||||
eb.WithDescription(GetText(strs.xpshop_website));
|
||||
if (!string.IsNullOrWhiteSpace(item.Desc))
|
||||
eb.AddField(GetText(strs.desc), item.Desc);
|
||||
|
||||
if (key == "default")
|
||||
eb.WithDescription(GetText(strs.xpshop_website));
|
||||
|
||||
|
||||
var tier = _service.GetXpShopTierRequirement(type);
|
||||
if (tier != PatronTier.None)
|
||||
{
|
||||
eb.WithFooter(GetText(strs.xp_shop_buy_required_tier(tier.ToString())));
|
||||
}
|
||||
var tier = _service.GetXpShopTierRequirement(type);
|
||||
if (tier != PatronTier.None)
|
||||
{
|
||||
eb.WithFooter(GetText(strs.xp_shop_buy_required_tier(tier.ToString())));
|
||||
}
|
||||
|
||||
return Task.FromResult(eb);
|
||||
},
|
||||
async current =>
|
||||
{
|
||||
var (key, _) = items.Skip(current).First();
|
||||
return eb;
|
||||
})
|
||||
.Interaction(async current =>
|
||||
{
|
||||
var (key, _) = allItems.Skip(current).First();
|
||||
|
||||
var itemType = type == XpShopInputType.Backgrounds
|
||||
? XpShopItemType.Background
|
||||
: XpShopItemType.Frame;
|
||||
var itemType = type == XpShopInputType.Backgrounds
|
||||
? XpShopItemType.Background
|
||||
: XpShopItemType.Frame;
|
||||
|
||||
var ownedItem = await _service.GetUserItemAsync(ctx.User.Id, itemType, key);
|
||||
if (ownedItem is not null)
|
||||
{
|
||||
var button = new ButtonBuilder(ownedItem.IsUsing
|
||||
? GetText(strs.in_use)
|
||||
: GetText(strs.use),
|
||||
"xpshop:use",
|
||||
emote: Emoji.Parse("👐"),
|
||||
isDisabled: ownedItem.IsUsing);
|
||||
var ownedItem = await _service.GetUserItemAsync(ctx.User.Id, itemType, key);
|
||||
if (ownedItem is not null)
|
||||
{
|
||||
var button = new ButtonBuilder(ownedItem.IsUsing
|
||||
? GetText(strs.in_use)
|
||||
: GetText(strs.use),
|
||||
"xpshop:use",
|
||||
emote: Emoji.Parse("👐"),
|
||||
isDisabled: ownedItem.IsUsing);
|
||||
|
||||
var inter = new SimpleInteraction<(string key, XpShopItemType type)?>(
|
||||
button,
|
||||
OnShopUse,
|
||||
(key, itemType));
|
||||
var inter = new SimpleInteraction<(string key, XpShopItemType type)?>(
|
||||
button,
|
||||
OnShopUse,
|
||||
(key, itemType));
|
||||
|
||||
return inter;
|
||||
}
|
||||
else
|
||||
{
|
||||
var button = new ButtonBuilder(GetText(strs.buy),
|
||||
"xpshop:buy",
|
||||
emote: Emoji.Parse("💰"));
|
||||
return inter;
|
||||
}
|
||||
else
|
||||
{
|
||||
var button = new ButtonBuilder(GetText(strs.buy),
|
||||
"xpshop:buy",
|
||||
emote: Emoji.Parse("💰"));
|
||||
|
||||
var inter = new SimpleInteraction<(string key, XpShopItemType type)?>(
|
||||
button,
|
||||
OnShopBuy,
|
||||
(key, itemType));
|
||||
var inter = new SimpleInteraction<(string key, XpShopItemType type)?>(
|
||||
button,
|
||||
OnShopBuy,
|
||||
(key, itemType));
|
||||
|
||||
return inter;
|
||||
}
|
||||
},
|
||||
items.Count,
|
||||
1,
|
||||
addPaginatedFooter: false);
|
||||
return inter;
|
||||
}
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -16,10 +16,10 @@ public partial class Xp
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task XpRewsReset()
|
||||
{
|
||||
var promptEmbed = new EmbedBuilder()
|
||||
.WithPendingColor()
|
||||
.WithDescription(GetText(strs.xprewsreset_confirm));
|
||||
|
||||
var promptEmbed = _sender.CreateEmbed()
|
||||
.WithPendingColor()
|
||||
.WithDescription(GetText(strs.xprewsreset_confirm));
|
||||
|
||||
var reply = await PromptUserConfirmAsync(promptEmbed);
|
||||
|
||||
if (!reply)
|
||||
@@ -66,24 +66,25 @@ public partial class Xp
|
||||
.OrderBy(x => x.Key)
|
||||
.ToList();
|
||||
|
||||
return Context.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.level_up_rewards)).WithOkColor();
|
||||
return Response()
|
||||
.Paginated()
|
||||
.Items(allRewards)
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed().WithTitle(GetText(strs.level_up_rewards)).WithOkColor();
|
||||
|
||||
var localRewards = allRewards.Skip(cur * 9).Take(9).ToList();
|
||||
if (!items.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 items)
|
||||
embed.AddField(GetText(strs.level_x(reward.Key)),
|
||||
string.Join("\n", reward.Select(y => y.Item2)));
|
||||
|
||||
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);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -112,8 +113,10 @@ public partial class Xp
|
||||
await Response().Confirm(strs.xp_role_reward_add_role(level, Format.Bold(role.ToString()))).SendAsync();
|
||||
else
|
||||
{
|
||||
await Response().Confirm(strs.xp_role_reward_remove_role(Format.Bold(level.ToString()),
|
||||
Format.Bold(role.ToString()))).SendAsync();
|
||||
await Response()
|
||||
.Confirm(strs.xp_role_reward_remove_role(Format.Bold(level.ToString()),
|
||||
Format.Bold(role.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,8 +132,10 @@ public partial class Xp
|
||||
if (amount == 0)
|
||||
await Response().Confirm(strs.cur_reward_cleared(level, _cp.GetCurrencySign())).SendAsync();
|
||||
else
|
||||
await Response().Confirm(strs.cur_reward_added(level,
|
||||
Format.Bold(amount + _cp.GetCurrencySign()))).SendAsync();
|
||||
await Response()
|
||||
.Confirm(strs.cur_reward_added(level,
|
||||
Format.Bold(amount + _cp.GetCurrencySign())))
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,7 +7,7 @@ public abstract class CleanupModuleBase : NadekoModule
|
||||
{
|
||||
try
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.sql_confirm_exec))
|
||||
.WithDescription(name);
|
||||
|
||||
|
@@ -1,8 +1,20 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public class SimpleInteraction<T>
|
||||
public static class InteractionHelpers
|
||||
{
|
||||
public ButtonBuilder Button { get; }
|
||||
public static readonly IEmote ArrowLeft = Emote.Parse("<:x:1232256519844790302>");
|
||||
public static readonly IEmote ArrowRight = Emote.Parse("<:x:1232256515298295838>");
|
||||
}
|
||||
|
||||
public abstract class SimpleInteractionBase
|
||||
{
|
||||
public abstract Task TriggerAsync(SocketMessageComponent smc);
|
||||
public abstract ButtonBuilder Button { get; }
|
||||
}
|
||||
|
||||
public class SimpleInteraction<T> : SimpleInteractionBase
|
||||
{
|
||||
public override ButtonBuilder Button { get; }
|
||||
private readonly Func<SocketMessageComponent, T, Task> _onClick;
|
||||
private readonly T? _state;
|
||||
|
||||
@@ -13,7 +25,7 @@ public class SimpleInteraction<T>
|
||||
_state = state;
|
||||
}
|
||||
|
||||
public async Task TriggerAsync(SocketMessageComponent smc)
|
||||
public override async Task TriggerAsync(SocketMessageComponent smc)
|
||||
{
|
||||
await _onClick(smc, _state!);
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ public abstract class NadekoModule : ModuleBase
|
||||
public INadekoInteractionService _inter { get; set; }
|
||||
public IReplacementService repSvc { get; set; }
|
||||
public IMessageSenderService _sender { get; set; }
|
||||
public BotConfigService _bcs { get; set; }
|
||||
|
||||
protected string prefix
|
||||
=> _cmdHandler.GetPrefix(ctx.Guild);
|
||||
@@ -27,7 +28,7 @@ public abstract class NadekoModule : ModuleBase
|
||||
=> Context;
|
||||
|
||||
public ResponseBuilder Response()
|
||||
=> new ResponseBuilder(Strings)
|
||||
=> new ResponseBuilder(Strings, _bcs, (DiscordSocketClient)ctx.Client)
|
||||
.Context(ctx);
|
||||
|
||||
protected override void BeforeExecute(CommandInfo command)
|
||||
|
@@ -7,4 +7,6 @@ public interface IMessageSenderService
|
||||
ResponseBuilder Response(IUser user);
|
||||
|
||||
ResponseBuilder Response(SocketMessageComponent smc);
|
||||
|
||||
NadekoEmbedBuilder CreateEmbed();
|
||||
}
|
@@ -1,280 +0,0 @@
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
public static class MessageChannelExtensions
|
||||
{
|
||||
// main overload that all other send methods reduce to
|
||||
public static Task<IUserMessage> SendAsync(
|
||||
this IMessageChannel channel,
|
||||
string? plainText,
|
||||
Embed? embed = null,
|
||||
IReadOnlyCollection<Embed>? embeds = null,
|
||||
bool sanitizeAll = false,
|
||||
MessageComponent? components = null,
|
||||
IUserMessage? replyTo = null)
|
||||
{
|
||||
plainText = sanitizeAll
|
||||
? plainText?.SanitizeAllMentions() ?? ""
|
||||
: plainText?.SanitizeMentions() ?? "";
|
||||
|
||||
var msgReference = CreateMessageReference(channel, replyTo);
|
||||
return channel.SendMessageAsync(plainText,
|
||||
embed: embed,
|
||||
embeds: embeds is null
|
||||
? null
|
||||
: embeds as Embed[] ?? embeds.ToArray(),
|
||||
components: components,
|
||||
messageReference: msgReference);
|
||||
}
|
||||
|
||||
private static MessageReference? CreateMessageReference(IChannel source, IMessage? replyTo)
|
||||
{
|
||||
if (replyTo is null)
|
||||
return null;
|
||||
|
||||
if (replyTo.Channel.Id != source.Id)
|
||||
return null;
|
||||
|
||||
return new(replyTo.Id,
|
||||
replyTo.Channel.Id,
|
||||
(replyTo.Channel as ITextChannel)?.GuildId,
|
||||
failIfNotExists: false);
|
||||
}
|
||||
|
||||
public static async Task<IUserMessage> SendAsync(
|
||||
this IMessageChannel channel,
|
||||
string? plainText,
|
||||
NadekoInteraction? inter,
|
||||
Embed? embed = null,
|
||||
IReadOnlyCollection<Embed>? embeds = null,
|
||||
bool sanitizeAll = false,
|
||||
IUserMessage? replyTo = null)
|
||||
{
|
||||
var msg = await channel.SendAsync(plainText,
|
||||
embed,
|
||||
embeds,
|
||||
sanitizeAll,
|
||||
inter?.CreateComponent(),
|
||||
replyTo);
|
||||
|
||||
if (inter is not null)
|
||||
await inter.RunAsync(msg);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static Task<IUserMessage> SendAsync(
|
||||
this IMessageChannel channel,
|
||||
SmartText text,
|
||||
bool sanitizeAll = false,
|
||||
IUserMessage? replyTo = null)
|
||||
=> text switch
|
||||
{
|
||||
SmartEmbedText set => channel.SendAsync(set.PlainText,
|
||||
set.IsValid ? set.GetEmbed().Build() : null,
|
||||
sanitizeAll: sanitizeAll,
|
||||
replyTo: replyTo),
|
||||
SmartPlainText st => channel.SendAsync(st.Text,
|
||||
default(Embed),
|
||||
sanitizeAll: sanitizeAll,
|
||||
replyTo: replyTo),
|
||||
SmartEmbedTextArray arr => channel.SendAsync(arr.Content,
|
||||
embeds: arr.GetEmbedBuilders().Map(e => e.Build()),
|
||||
sanitizeAll: sanitizeAll,
|
||||
replyTo: replyTo),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(text))
|
||||
};
|
||||
|
||||
public static Task<IUserMessage> EmbedAsync(
|
||||
this IMessageChannel ch,
|
||||
EmbedBuilder? embed,
|
||||
string plainText = "",
|
||||
IReadOnlyCollection<EmbedBuilder>? embeds = null,
|
||||
NadekoInteraction? inter = null,
|
||||
IUserMessage? replyTo = null)
|
||||
=> ch.SendAsync(plainText,
|
||||
inter,
|
||||
embed: embed?.Build(),
|
||||
embeds: embeds?.Map(x => x.Build()),
|
||||
replyTo: replyTo);
|
||||
|
||||
// embed title and optional footer overloads
|
||||
|
||||
public static Task SendPaginatedConfirmAsync(
|
||||
this ICommandContext ctx,
|
||||
int currentPage,
|
||||
Func<int, EmbedBuilder> pageFunc,
|
||||
int totalElements,
|
||||
int itemsPerPage,
|
||||
bool addPaginatedFooter = true)
|
||||
=> ctx.SendPaginatedConfirmAsync(currentPage,
|
||||
x => Task.FromResult(pageFunc(x)),
|
||||
totalElements,
|
||||
itemsPerPage,
|
||||
addPaginatedFooter);
|
||||
|
||||
private const string BUTTON_LEFT = "BUTTON_LEFT";
|
||||
private const string BUTTON_RIGHT = "BUTTON_RIGHT";
|
||||
|
||||
private static readonly IEmote _arrowLeft = Emote.Parse("<:x:1232256519844790302>");
|
||||
private static readonly IEmote _arrowRight = Emote.Parse("<:x:1232256515298295838>");
|
||||
|
||||
public static Task SendPaginatedConfirmAsync(
|
||||
this ICommandContext ctx,
|
||||
int currentPage,
|
||||
Func<int, Task<EmbedBuilder>> pageFunc,
|
||||
int totalElements,
|
||||
int itemsPerPage,
|
||||
bool addPaginatedFooter = true)
|
||||
=> ctx.SendPaginatedConfirmAsync(currentPage,
|
||||
pageFunc,
|
||||
default(Func<int, ValueTask<SimpleInteraction<object>?>>),
|
||||
totalElements,
|
||||
itemsPerPage,
|
||||
addPaginatedFooter);
|
||||
|
||||
public static async Task SendPaginatedConfirmAsync<T>(
|
||||
this ICommandContext ctx,
|
||||
int currentPage,
|
||||
Func<int, Task<EmbedBuilder>> pageFunc,
|
||||
Func<int, ValueTask<SimpleInteraction<T>?>>? interFactory,
|
||||
int totalElements,
|
||||
int itemsPerPage,
|
||||
bool addPaginatedFooter = true)
|
||||
{
|
||||
var lastPage = (totalElements - 1) / itemsPerPage;
|
||||
|
||||
var embed = await pageFunc(currentPage);
|
||||
|
||||
if (addPaginatedFooter)
|
||||
embed.AddPaginatedFooter(currentPage, lastPage);
|
||||
|
||||
SimpleInteraction<T>? maybeInter = null;
|
||||
|
||||
async Task<ComponentBuilder> GetComponentBuilder()
|
||||
{
|
||||
var cb = new ComponentBuilder();
|
||||
|
||||
cb.WithButton(new ButtonBuilder()
|
||||
.WithStyle(ButtonStyle.Primary)
|
||||
.WithCustomId(BUTTON_LEFT)
|
||||
.WithDisabled(lastPage == 0)
|
||||
.WithEmote(_arrowLeft)
|
||||
.WithDisabled(currentPage <= 0));
|
||||
|
||||
if (interFactory is not null)
|
||||
{
|
||||
maybeInter = await interFactory(currentPage);
|
||||
|
||||
if (maybeInter is not null)
|
||||
cb.WithButton(maybeInter.Button);
|
||||
}
|
||||
|
||||
cb.WithButton(new ButtonBuilder()
|
||||
.WithStyle(ButtonStyle.Primary)
|
||||
.WithCustomId(BUTTON_RIGHT)
|
||||
.WithDisabled(lastPage == 0 || currentPage >= lastPage)
|
||||
.WithEmote(_arrowRight));
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
async Task UpdatePageAsync(SocketMessageComponent smc)
|
||||
{
|
||||
var toSend = await pageFunc(currentPage);
|
||||
if (addPaginatedFooter)
|
||||
toSend.AddPaginatedFooter(currentPage, lastPage);
|
||||
|
||||
var component = (await GetComponentBuilder()).Build();
|
||||
|
||||
await smc.ModifyOriginalResponseAsync(x =>
|
||||
{
|
||||
x.Embed = toSend.Build();
|
||||
x.Components = component;
|
||||
});
|
||||
}
|
||||
|
||||
var component = (await GetComponentBuilder()).Build();
|
||||
var msg = await ctx.Channel.SendAsync(null, embed: embed.Build(), components: component, replyTo: ctx.Message);
|
||||
|
||||
async Task OnInteractionAsync(SocketInteraction si)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (si is not SocketMessageComponent smc)
|
||||
return;
|
||||
|
||||
if (smc.Message.Id != msg.Id)
|
||||
return;
|
||||
|
||||
await si.DeferAsync();
|
||||
if (smc.User.Id != ctx.User.Id)
|
||||
return;
|
||||
|
||||
if (smc.Data.CustomId == BUTTON_LEFT)
|
||||
{
|
||||
if (currentPage == 0)
|
||||
return;
|
||||
|
||||
--currentPage;
|
||||
_ = UpdatePageAsync(smc);
|
||||
}
|
||||
else if (smc.Data.CustomId == BUTTON_RIGHT)
|
||||
{
|
||||
if (currentPage >= lastPage)
|
||||
return;
|
||||
|
||||
++currentPage;
|
||||
_ = UpdatePageAsync(smc);
|
||||
}
|
||||
else if (maybeInter is { } inter && inter.Button.CustomId == smc.Data.CustomId)
|
||||
{
|
||||
await inter.TriggerAsync(smc);
|
||||
_ = UpdatePageAsync(smc);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastPage == 0 && interFactory is null)
|
||||
return;
|
||||
|
||||
var client = (DiscordSocketClient)ctx.Client;
|
||||
|
||||
client.InteractionCreated += OnInteractionAsync;
|
||||
|
||||
await Task.Delay(30_000);
|
||||
|
||||
client.InteractionCreated -= OnInteractionAsync;
|
||||
|
||||
await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build());
|
||||
}
|
||||
|
||||
private static readonly Emoji _okEmoji = new Emoji("✅");
|
||||
private static readonly Emoji _warnEmoji = new Emoji("⚠️");
|
||||
private static readonly Emoji _errorEmoji = new Emoji("❌");
|
||||
|
||||
public static Task ReactAsync(this ICommandContext ctx, MsgType type)
|
||||
{
|
||||
var emoji = type switch
|
||||
{
|
||||
MsgType.Error => _errorEmoji,
|
||||
MsgType.Pending => _warnEmoji,
|
||||
MsgType.Ok => _okEmoji,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type)),
|
||||
};
|
||||
|
||||
return ctx.Message.AddReactionAsync(emoji);
|
||||
}
|
||||
|
||||
public static Task OkAsync(this ICommandContext ctx)
|
||||
=> ctx.ReactAsync(MsgType.Ok);
|
||||
|
||||
public static Task ErrorAsync(this ICommandContext ctx)
|
||||
=> ctx.ReactAsync(MsgType.Error);
|
||||
|
||||
public static Task WarningAsync(this ICommandContext ctx)
|
||||
=> ctx.ReactAsync(MsgType.Pending);
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
using NadekoBot.Common.Configs;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace NadekoBot.Extensions;
|
||||
@@ -5,27 +6,52 @@ namespace NadekoBot.Extensions;
|
||||
public sealed class MessageSenderService : IMessageSenderService, INService
|
||||
{
|
||||
private readonly IBotStrings _bs;
|
||||
private readonly BotConfigService _bcs;
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public MessageSenderService(IBotStrings bs)
|
||||
public MessageSenderService(IBotStrings bs, BotConfigService bcs, DiscordSocketClient client)
|
||||
{
|
||||
_bs = bs;
|
||||
_bcs = bcs;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
|
||||
public ResponseBuilder Response(IMessageChannel channel)
|
||||
=> new ResponseBuilder(_bs)
|
||||
=> new ResponseBuilder(_bs, _bcs, _client)
|
||||
.Channel(channel);
|
||||
|
||||
public ResponseBuilder Response(ICommandContext ctx)
|
||||
=> new ResponseBuilder(_bs)
|
||||
=> new ResponseBuilder(_bs, _bcs, _client)
|
||||
.Context(ctx);
|
||||
|
||||
public ResponseBuilder Response(IUser user)
|
||||
=> new ResponseBuilder(_bs)
|
||||
=> new ResponseBuilder(_bs, _bcs, _client)
|
||||
.User(user);
|
||||
|
||||
// todo fix interactions
|
||||
|
||||
public ResponseBuilder Response(SocketMessageComponent smc)
|
||||
=> new ResponseBuilder(_bs)
|
||||
=> new ResponseBuilder(_bs, _bcs, _client)
|
||||
.Channel(smc.Channel);
|
||||
|
||||
public NadekoEmbedBuilder CreateEmbed()
|
||||
=> new NadekoEmbedBuilder(_bcs);
|
||||
}
|
||||
|
||||
public class NadekoEmbedBuilder : EmbedBuilder
|
||||
{
|
||||
private readonly BotConfig _bc;
|
||||
|
||||
public NadekoEmbedBuilder(BotConfigService bcs)
|
||||
{
|
||||
_bc = bcs.Data;
|
||||
}
|
||||
|
||||
public EmbedBuilder WithOkColor()
|
||||
=> WithColor(_bc.Color.Ok.ToDiscordColor());
|
||||
|
||||
public EmbedBuilder WithErrorColor()
|
||||
=> WithColor(_bc.Color.Error.ToDiscordColor());
|
||||
|
||||
public EmbedBuilder WithPendingColor()
|
||||
=> WithColor(_bc.Color.Pending.ToDiscordColor());
|
||||
}
|
@@ -7,24 +7,20 @@ public partial class ResponseBuilder
|
||||
private const string BUTTON_LEFT = "BUTTON_LEFT";
|
||||
private const string BUTTON_RIGHT = "BUTTON_RIGHT";
|
||||
|
||||
private static readonly IEmote _arrowLeft = Emote.Parse("<:x:1232256519844790302>");
|
||||
private static readonly IEmote _arrowRight = Emote.Parse("<:x:1232256515298295838>");
|
||||
|
||||
private readonly SourcedPaginatedResponseBuilder<T> _paginationBuilder;
|
||||
private readonly ResponseBuilder builder;
|
||||
private readonly DiscordSocketClient client;
|
||||
private readonly ResponseBuilder _builder;
|
||||
private readonly DiscordSocketClient _client;
|
||||
private int currentPage;
|
||||
|
||||
public PaginationSender(
|
||||
SourcedPaginatedResponseBuilder<T> paginationBuilder,
|
||||
ResponseBuilder builder
|
||||
)
|
||||
ResponseBuilder builder)
|
||||
{
|
||||
this._paginationBuilder = paginationBuilder;
|
||||
this.builder = builder;
|
||||
_paginationBuilder = paginationBuilder;
|
||||
_builder = builder;
|
||||
|
||||
client = (DiscordSocketClient)builder.ctx.Client;
|
||||
currentPage = 0;
|
||||
_client = builder.Client;
|
||||
currentPage = paginationBuilder.InitialPage;
|
||||
}
|
||||
|
||||
public async Task SendAsync(bool ephemeral = false)
|
||||
@@ -38,7 +34,7 @@ public partial class ResponseBuilder
|
||||
if (_paginationBuilder.AddPaginatedFooter)
|
||||
embed.AddPaginatedFooter(currentPage, lastPage);
|
||||
|
||||
SimpleInteraction<T>? maybeInter = null;
|
||||
SimpleInteractionBase? maybeInter = null;
|
||||
|
||||
async Task<ComponentBuilder> GetComponentBuilder()
|
||||
{
|
||||
@@ -48,22 +44,22 @@ public partial class ResponseBuilder
|
||||
.WithStyle(ButtonStyle.Primary)
|
||||
.WithCustomId(BUTTON_LEFT)
|
||||
.WithDisabled(lastPage == 0)
|
||||
.WithEmote(_arrowLeft)
|
||||
.WithEmote(InteractionHelpers.ArrowLeft)
|
||||
.WithDisabled(currentPage <= 0));
|
||||
// todo
|
||||
// if (interFactory is not null)
|
||||
// {
|
||||
// maybeInter = await interFactory(currentPage);
|
||||
//
|
||||
// if (maybeInter is not null)
|
||||
// cb.WithButton(maybeInter.Button);
|
||||
// }
|
||||
|
||||
if (_paginationBuilder.InteractionFunc is not null)
|
||||
{
|
||||
maybeInter = await _paginationBuilder.InteractionFunc(currentPage);
|
||||
|
||||
if (maybeInter is not null)
|
||||
cb.WithButton(maybeInter.Button);
|
||||
}
|
||||
|
||||
cb.WithButton(new ButtonBuilder()
|
||||
.WithStyle(ButtonStyle.Primary)
|
||||
.WithCustomId(BUTTON_RIGHT)
|
||||
.WithDisabled(lastPage == 0 || currentPage >= lastPage)
|
||||
.WithEmote(_arrowRight));
|
||||
.WithEmote(InteractionHelpers.ArrowRight));
|
||||
|
||||
return cb;
|
||||
}
|
||||
@@ -84,7 +80,7 @@ public partial class ResponseBuilder
|
||||
});
|
||||
}
|
||||
|
||||
var model = builder.Build(ephemeral);
|
||||
var model = await _builder.BuildAsync(ephemeral);
|
||||
|
||||
var component = (await GetComponentBuilder()).Build();
|
||||
var msg = await model.TargetChannel
|
||||
@@ -104,7 +100,8 @@ public partial class ResponseBuilder
|
||||
return;
|
||||
|
||||
await si.DeferAsync();
|
||||
if (smc.User.Id != model.User.Id)
|
||||
|
||||
if (smc.User.Id != model.User?.Id)
|
||||
return;
|
||||
|
||||
if (smc.Data.CustomId == BUTTON_LEFT)
|
||||
@@ -134,20 +131,15 @@ public partial class ResponseBuilder
|
||||
Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
|
||||
}
|
||||
}
|
||||
// todo re-add
|
||||
// if (lastPage == 0 && interFactory is null)
|
||||
// return;
|
||||
|
||||
if (lastPage == 0)
|
||||
if (lastPage == 0 && _paginationBuilder.InteractionFunc is null)
|
||||
return;
|
||||
|
||||
var client = this.client;
|
||||
|
||||
client.InteractionCreated += OnInteractionAsync;
|
||||
_client.InteractionCreated += OnInteractionAsync;
|
||||
|
||||
await Task.Delay(30_000);
|
||||
|
||||
client.InteractionCreated -= OnInteractionAsync;
|
||||
_client.InteractionCreated -= OnInteractionAsync;
|
||||
|
||||
await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build());
|
||||
}
|
||||
|
@@ -1,29 +1,39 @@
|
||||
namespace NadekoBot.Extensions;
|
||||
using NadekoBot.Common.Configs;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
public sealed partial class ResponseBuilder
|
||||
{
|
||||
private ICommandContext? ctx = null;
|
||||
private IMessageChannel? channel = null;
|
||||
private Embed? embed = null;
|
||||
private string? plainText = null;
|
||||
private IReadOnlyCollection<EmbedBuilder>? embeds = null;
|
||||
private IUserMessage? msg = null;
|
||||
private IUser? user = null;
|
||||
private ICommandContext? ctx;
|
||||
private IMessageChannel? channel;
|
||||
private string? plainText;
|
||||
private IReadOnlyCollection<EmbedBuilder>? embeds;
|
||||
private IUserMessage? msg;
|
||||
private IUser? user;
|
||||
private bool sanitizeMentions = true;
|
||||
private LocStr? locTxt;
|
||||
private object[] locParams = [];
|
||||
private bool shouldReply = true;
|
||||
private readonly IBotStrings _bs;
|
||||
private EmbedBuilder? embedBuilder = null;
|
||||
private readonly BotConfigService _bcs;
|
||||
private EmbedBuilder? embedBuilder;
|
||||
private NadekoInteraction? inter;
|
||||
private Stream? fileStream = null;
|
||||
private string? fileName = null;
|
||||
private Stream? fileStream;
|
||||
private string? fileName;
|
||||
private EmbedColor color = EmbedColor.Ok;
|
||||
private LocStr? embedLocDesc;
|
||||
|
||||
public ResponseBuilder(IBotStrings bs)
|
||||
public DiscordSocketClient Client { get; set; }
|
||||
|
||||
public ResponseBuilder(IBotStrings bs, BotConfigService bcs, DiscordSocketClient client)
|
||||
{
|
||||
_bs = bs;
|
||||
_bcs = bcs;
|
||||
Client = client;
|
||||
}
|
||||
|
||||
|
||||
private MessageReference? CreateMessageReference(IMessageChannel targetChannel)
|
||||
{
|
||||
if (!shouldReply)
|
||||
@@ -44,72 +54,116 @@ public sealed partial class ResponseBuilder
|
||||
failIfNotExists: false);
|
||||
}
|
||||
|
||||
public ResponseMessageModel Build(bool ephemeral = false)
|
||||
public async Task<ResponseMessageModel> BuildAsync(bool ephemeral)
|
||||
{
|
||||
// todo use ephemeral in interactions
|
||||
var targetChannel = InternalResolveChannel() ?? throw new ArgumentNullException(nameof(channel));
|
||||
var targetChannel = await InternalResolveChannel() ?? throw new ArgumentNullException(nameof(channel));
|
||||
var msgReference = CreateMessageReference(targetChannel);
|
||||
|
||||
var txt = GetText(locTxt);
|
||||
// todo check message sanitization
|
||||
var txt = GetText(locTxt, targetChannel);
|
||||
|
||||
if (embedLocDesc is LocStr ls)
|
||||
{
|
||||
InternalCreateEmbed(null, GetText(ls, targetChannel));
|
||||
}
|
||||
|
||||
if (embedBuilder is not null)
|
||||
PaintEmbedInternal(embedBuilder);
|
||||
|
||||
var finalEmbed = embedBuilder?.Build();
|
||||
|
||||
|
||||
var buildModel = new ResponseMessageModel()
|
||||
{
|
||||
TargetChannel = targetChannel,
|
||||
MessageReference = msgReference,
|
||||
Text = txt,
|
||||
User = ctx?.User,
|
||||
Embed = embed ?? embedBuilder?.Build(),
|
||||
User = user ?? ctx?.User,
|
||||
Embed = finalEmbed,
|
||||
Embeds = embeds?.Map(x => x.Build()),
|
||||
SanitizeMentions = sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All
|
||||
SanitizeMentions = sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All,
|
||||
Ephemeral = ephemeral,
|
||||
Interaction = inter
|
||||
};
|
||||
|
||||
return buildModel;
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendAsync(bool ephemeral = false)
|
||||
public async Task<IUserMessage> SendAsync(bool ephemeral = false)
|
||||
{
|
||||
var model = Build(ephemeral);
|
||||
return SendAsync(model);
|
||||
var model = await BuildAsync(ephemeral);
|
||||
var sentMsg = await SendAsync(model);
|
||||
|
||||
|
||||
return sentMsg;
|
||||
}
|
||||
|
||||
public async Task<IUserMessage> SendAsync(ResponseMessageModel model)
|
||||
{
|
||||
if (this.fileStream is Stream stream)
|
||||
return await model.TargetChannel.SendFileAsync(stream,
|
||||
IUserMessage sentMsg;
|
||||
if (fileStream is Stream stream)
|
||||
{
|
||||
sentMsg = await model.TargetChannel.SendFileAsync(stream,
|
||||
filename: fileName,
|
||||
model.Text,
|
||||
embed: model.Embed,
|
||||
components: null,
|
||||
components: inter?.CreateComponent(),
|
||||
allowedMentions: model.SanitizeMentions,
|
||||
messageReference: model.MessageReference);
|
||||
}
|
||||
else
|
||||
{
|
||||
sentMsg = await model.TargetChannel.SendMessageAsync(
|
||||
model.Text,
|
||||
embed: model.Embed,
|
||||
embeds: model.Embeds,
|
||||
components: inter?.CreateComponent(),
|
||||
allowedMentions: model.SanitizeMentions,
|
||||
messageReference: model.MessageReference);
|
||||
}
|
||||
|
||||
return await model.TargetChannel.SendMessageAsync(
|
||||
model.Text,
|
||||
embed: model.Embed,
|
||||
embeds: model.Embeds,
|
||||
components: null,
|
||||
allowedMentions: model.SanitizeMentions,
|
||||
messageReference: model.MessageReference);
|
||||
if (model.Interaction is not null)
|
||||
{
|
||||
await model.Interaction.RunAsync(sentMsg);
|
||||
}
|
||||
|
||||
return sentMsg;
|
||||
}
|
||||
|
||||
private EmbedBuilder PaintEmbedInternal(EmbedBuilder eb)
|
||||
=> color switch
|
||||
{
|
||||
EmbedColor.Ok => eb.WithOkColor(),
|
||||
EmbedColor.Pending => eb.WithPendingColor(),
|
||||
EmbedColor.Error => eb.WithErrorColor(),
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
|
||||
private ulong? InternalResolveGuildId(IMessageChannel? targetChannel)
|
||||
=> ctx?.Guild?.Id ?? (targetChannel as ITextChannel)?.GuildId;
|
||||
|
||||
// todo not good, has to go to the user
|
||||
private IMessageChannel? InternalResolveChannel()
|
||||
=> channel ?? ctx?.Channel ?? msg?.Channel;
|
||||
|
||||
private string? GetText(LocStr? locStr)
|
||||
private async Task<IMessageChannel?> InternalResolveChannel()
|
||||
{
|
||||
if (user is not null)
|
||||
{
|
||||
var ch = await user.CreateDMChannelAsync();
|
||||
|
||||
if (ch is not null)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
return channel ?? ctx?.Channel ?? msg?.Channel;
|
||||
}
|
||||
|
||||
private string? GetText(LocStr? locStr, IMessageChannel targetChannel)
|
||||
{
|
||||
var targetChannel = InternalResolveChannel();
|
||||
var guildId = InternalResolveGuildId(targetChannel);
|
||||
return locStr is LocStr ls ? _bs.GetText(ls.Key, guildId, locParams) : plainText;
|
||||
}
|
||||
|
||||
private string GetText(LocStr locStr)
|
||||
private string GetText(LocStr locStr, IMessageChannel targetChannel)
|
||||
{
|
||||
var targetChannel = InternalResolveChannel();
|
||||
var guildId = InternalResolveGuildId(targetChannel);
|
||||
return _bs.GetText(locStr.Key, guildId, locStr.Params);
|
||||
}
|
||||
@@ -125,91 +179,108 @@ public sealed partial class ResponseBuilder
|
||||
if (text is SmartPlainText spt)
|
||||
plainText = spt.Text;
|
||||
else if (text is SmartEmbedText set)
|
||||
embed = set.GetEmbed().Build();
|
||||
embedBuilder = set.GetEmbed();
|
||||
else if (text is SmartEmbedTextArray ser)
|
||||
embeds = ser.GetEmbedBuilders();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private ResponseBuilder InternalColoredText(string text, EmbedColor color)
|
||||
{
|
||||
embed = new EmbedBuilder()
|
||||
.WithColor(color)
|
||||
.WithDescription(text)
|
||||
.Build();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private EmbedBuilder CreateEmbedInternal(
|
||||
private void InternalCreateEmbed(
|
||||
string? title,
|
||||
string? text,
|
||||
string? url,
|
||||
string? footer = null)
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle(title)
|
||||
.WithDescription(text);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(url))
|
||||
embed = embed.WithUrl(url);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(footer))
|
||||
embed = embed.WithFooter(footer);
|
||||
|
||||
return embed;
|
||||
}
|
||||
|
||||
private EmbedBuilder PaintEmbedInternal(EmbedBuilder eb, EmbedColor color)
|
||||
=> color switch
|
||||
{
|
||||
EmbedColor.Ok => eb.WithOkColor(),
|
||||
EmbedColor.Pending => eb.WithPendingColor(),
|
||||
EmbedColor.Error => eb.WithErrorColor(),
|
||||
};
|
||||
|
||||
public ResponseBuilder Error(
|
||||
string? title,
|
||||
string? text,
|
||||
string text,
|
||||
string? url = null,
|
||||
string? footer = null)
|
||||
{
|
||||
var eb = CreateEmbedInternal(title, text, url, footer);
|
||||
embed = PaintEmbedInternal(eb, EmbedColor.Error).Build();
|
||||
return this;
|
||||
}
|
||||
var eb = new NadekoEmbedBuilder(_bcs)
|
||||
.WithDescription(text);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(title))
|
||||
eb.WithTitle(title);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(url))
|
||||
eb = eb.WithUrl(url);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(footer))
|
||||
eb = eb.WithFooter(footer);
|
||||
|
||||
embedBuilder = eb;
|
||||
}
|
||||
|
||||
public ResponseBuilder Confirm(
|
||||
string? title,
|
||||
string? text,
|
||||
string text,
|
||||
string? url = null,
|
||||
string? footer = null)
|
||||
{
|
||||
var eb = CreateEmbedInternal(title, text, url, footer);
|
||||
embed = PaintEmbedInternal(eb, EmbedColor.Error).Build();
|
||||
InternalCreateEmbed(title, text, url, footer);
|
||||
color = EmbedColor.Ok;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Error(
|
||||
string? title,
|
||||
string text,
|
||||
string? url = null,
|
||||
string? footer = null)
|
||||
{
|
||||
InternalCreateEmbed(title, text, url, footer);
|
||||
color = EmbedColor.Error;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Pending(
|
||||
string? title,
|
||||
string text,
|
||||
string? url = null,
|
||||
string? footer = null)
|
||||
{
|
||||
InternalCreateEmbed(title, text, url, footer);
|
||||
color = EmbedColor.Pending;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Confirm(string text)
|
||||
=> InternalColoredText(text, EmbedColor.Ok);
|
||||
{
|
||||
InternalCreateEmbed(null, text);
|
||||
color = EmbedColor.Ok;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Confirm(LocStr str)
|
||||
=> Confirm(GetText(str));
|
||||
{
|
||||
embedLocDesc = str;
|
||||
color = EmbedColor.Ok;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Pending(string text)
|
||||
=> InternalColoredText(text, EmbedColor.Ok);
|
||||
{
|
||||
InternalCreateEmbed(null, text);
|
||||
color = EmbedColor.Pending;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Pending(LocStr str)
|
||||
=> Pending(GetText(str));
|
||||
{
|
||||
embedLocDesc = str;
|
||||
color = EmbedColor.Pending;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Error(string text)
|
||||
=> InternalColoredText(text, EmbedColor.Error);
|
||||
{
|
||||
InternalCreateEmbed(null, text);
|
||||
color = EmbedColor.Error;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Error(LocStr str)
|
||||
=> Error(GetText(str));
|
||||
|
||||
{
|
||||
embedLocDesc = str;
|
||||
color = EmbedColor.Error;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder UserBasedMentions()
|
||||
{
|
||||
@@ -220,17 +291,15 @@ public sealed partial class ResponseBuilder
|
||||
private IUser? InternalResolveUser()
|
||||
=> ctx?.User ?? user ?? msg?.Author;
|
||||
|
||||
// todo embed colors
|
||||
|
||||
public ResponseBuilder Embed(EmbedBuilder eb)
|
||||
{
|
||||
embedBuilder = eb;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Channel(IMessageChannel channel)
|
||||
public ResponseBuilder Channel(IMessageChannel ch)
|
||||
{
|
||||
this.channel = channel;
|
||||
channel = ch;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -240,21 +309,21 @@ public sealed partial class ResponseBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Context(ICommandContext ctx)
|
||||
public ResponseBuilder Context(ICommandContext context)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
ctx = context;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Message(IUserMessage msg)
|
||||
public ResponseBuilder Message(IUserMessage message)
|
||||
{
|
||||
this.msg = msg;
|
||||
msg = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder User(IUser user)
|
||||
public ResponseBuilder User(IUser usr)
|
||||
{
|
||||
this.user = user;
|
||||
user = usr;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -266,7 +335,6 @@ public sealed partial class ResponseBuilder
|
||||
|
||||
public ResponseBuilder Interaction(NadekoInteraction? interaction)
|
||||
{
|
||||
// todo implement
|
||||
inter = interaction;
|
||||
return this;
|
||||
}
|
||||
@@ -277,10 +345,10 @@ public sealed partial class ResponseBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder FileName(Stream fileStream, string fileName)
|
||||
public ResponseBuilder File(Stream stream, string name)
|
||||
{
|
||||
this.fileStream = fileStream;
|
||||
this.fileName = fileName;
|
||||
fileStream = stream;
|
||||
fileName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -300,27 +368,51 @@ public class PaginatedResponseBuilder
|
||||
public SourcedPaginatedResponseBuilder<T> Items<T>(IReadOnlyCollection<T> items)
|
||||
=> new SourcedPaginatedResponseBuilder<T>(_builder)
|
||||
.Items(items);
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> PageItems<T>(Func<int, Task<IEnumerable<T>>> items)
|
||||
=> new SourcedPaginatedResponseBuilder<T>(_builder)
|
||||
.PageItems(items);
|
||||
}
|
||||
|
||||
public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilder
|
||||
{
|
||||
private IReadOnlyCollection<T>? items;
|
||||
public Func<IReadOnlyList<T>, int, Task<EmbedBuilder>> PageFunc { get; private set; }
|
||||
public Func<int, Task<IEnumerable<T>>> ItemsFunc { get; set; }
|
||||
|
||||
public Func<IReadOnlyList<T>, int, Task<EmbedBuilder>> PageFunc { get; private set; } = static delegate
|
||||
{
|
||||
return Task.FromResult<EmbedBuilder>(new());
|
||||
};
|
||||
|
||||
public Func<int, Task<IEnumerable<T>>> ItemsFunc { get; set; } = static delegate
|
||||
{
|
||||
return Task.FromResult(Enumerable.Empty<T>());
|
||||
};
|
||||
|
||||
public Func<int, Task<SimpleInteractionBase>>? InteractionFunc { get; private set; }
|
||||
|
||||
public int TotalElements { get; private set; } = 1;
|
||||
public int ItemsPerPage { get; private set; } = 9;
|
||||
public bool AddPaginatedFooter { get; private set; } = true;
|
||||
public bool IsEphemeral { get; private set; }
|
||||
|
||||
public int InitialPage { get; set; }
|
||||
|
||||
public SourcedPaginatedResponseBuilder(ResponseBuilder builder)
|
||||
: base(builder)
|
||||
{
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Items(IReadOnlyCollection<T> items)
|
||||
public SourcedPaginatedResponseBuilder<T> Items(IReadOnlyCollection<T> col)
|
||||
{
|
||||
this.items = items;
|
||||
ItemsFunc = (i) => Task.FromResult(this.items.Skip(i * ItemsPerPage).Take(ItemsPerPage));
|
||||
items = col;
|
||||
TotalElements = col.Count;
|
||||
ItemsFunc = (i) => Task.FromResult(items.Skip(i * ItemsPerPage).Take(ItemsPerPage));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> PageItems(Func<int, Task<IEnumerable<T>>> func)
|
||||
{
|
||||
ItemsFunc = func;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -337,24 +429,22 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
||||
return this;
|
||||
}
|
||||
|
||||
// todo use it
|
||||
public int InitialPage { get; set; }
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Page(Func<IReadOnlyList<T>, int, EmbedBuilder> pageFunc)
|
||||
{
|
||||
this.PageFunc = (xs, x) => Task.FromResult(pageFunc(xs, x));
|
||||
PageFunc = (xs, x) => Task.FromResult(pageFunc(xs, x));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Page(Func<IReadOnlyList<T>, int, Task<EmbedBuilder>> pageFunc)
|
||||
{
|
||||
this.PageFunc = pageFunc;
|
||||
PageFunc = pageFunc;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> AddFooter()
|
||||
public SourcedPaginatedResponseBuilder<T> AddFooter(bool addFooter = true)
|
||||
{
|
||||
AddPaginatedFooter = true;
|
||||
AddPaginatedFooter = addFooter;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -373,4 +463,10 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
||||
|
||||
return paginationSender.SendAsync(IsEphemeral);
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Interaction(Func<int, Task<SimpleInteractionBase>> func)
|
||||
{
|
||||
InteractionFunc = async (i) => await func(i);
|
||||
return this;
|
||||
}
|
||||
}
|
@@ -2,17 +2,27 @@
|
||||
|
||||
public static class ResponseBuilderExtensions
|
||||
{
|
||||
// todo delete this
|
||||
|
||||
public static EmbedBuilder WithColor(this EmbedBuilder eb, EmbedColor color)
|
||||
=> eb;
|
||||
|
||||
public static EmbedBuilder WithPendingColor(this EmbedBuilder eb)
|
||||
=> eb.WithColor(EmbedColor.Error);
|
||||
{
|
||||
if (eb is NadekoEmbedBuilder neb)
|
||||
return neb.WithPendingColor();
|
||||
|
||||
return eb;
|
||||
}
|
||||
|
||||
public static EmbedBuilder WithOkColor(this EmbedBuilder eb)
|
||||
=> eb.WithColor(EmbedColor.Ok);
|
||||
{
|
||||
if (eb is NadekoEmbedBuilder neb)
|
||||
return neb.WithOkColor();
|
||||
|
||||
return eb;
|
||||
}
|
||||
|
||||
public static EmbedBuilder WithErrorColor(this EmbedBuilder eb)
|
||||
=> eb.WithColor(EmbedColor.Error);
|
||||
{
|
||||
if (eb is NadekoEmbedBuilder neb)
|
||||
return neb.WithErrorColor();
|
||||
|
||||
return eb;
|
||||
}
|
||||
}
|
@@ -1,10 +1,12 @@
|
||||
public class ResponseMessageModel
|
||||
{
|
||||
public IMessageChannel TargetChannel { get; set; }
|
||||
public MessageReference MessageReference { get; set; }
|
||||
public string Text { get; set; }
|
||||
public Embed Embed { get; set; }
|
||||
public Embed[] Embeds { get; set; }
|
||||
public AllowedMentions SanitizeMentions { get; set; }
|
||||
public IUser User { get; set; }
|
||||
public required IMessageChannel TargetChannel { get; set; }
|
||||
public MessageReference? MessageReference { get; set; }
|
||||
public string? Text { get; set; }
|
||||
public Embed? Embed { get; set; }
|
||||
public Embed[]? Embeds { get; set; }
|
||||
public required AllowedMentions SanitizeMentions { get; set; }
|
||||
public IUser? User { get; set; }
|
||||
public bool Ephemeral { get; set; }
|
||||
public NadekoInteraction? Interaction { get; set; }
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
// todo remove
|
||||
public sealed class DiscordEmbedBuilderWrapper
|
||||
{
|
||||
// public EmbedBuilder WithColor(EmbedColor color)
|
||||
// => color switch
|
||||
// {
|
||||
// EmbedColor.Ok => Wrap(embed.WithColor(_botConfig.Color.Ok.ToDiscordColor())),
|
||||
// EmbedColor.Pending => Wrap(embed.WithColor(_botConfig.Color.Pending.ToDiscordColor())),
|
||||
// EmbedColor.Error => Wrap(embed.WithColor(_botConfig.Color.Error.ToDiscordColor())),
|
||||
// _ => throw new ArgumentOutOfRangeException(nameof(color), "Unsupported EmbedColor type")
|
||||
// };
|
||||
|
||||
}
|
@@ -39,7 +39,7 @@ public sealed class CommandsUtilityService : ICommandsUtilityService, INService
|
||||
|
||||
var culture = _loc.GetCultureInfo(guild);
|
||||
|
||||
var em = new EmbedBuilder()
|
||||
var em = _sender.CreateEmbed()
|
||||
.AddField(str, $"{com.RealSummary(_strings, _medusae, culture, prefix)}", true);
|
||||
|
||||
_dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides);
|
||||
|
@@ -0,0 +1,30 @@
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
public static class CommandContextExtensions
|
||||
{
|
||||
private static readonly Emoji _okEmoji = new Emoji("✅");
|
||||
private static readonly Emoji _warnEmoji = new Emoji("⚠️");
|
||||
private static readonly Emoji _errorEmoji = new Emoji("❌");
|
||||
|
||||
public static Task ReactAsync(this ICommandContext ctx, MsgType type)
|
||||
{
|
||||
var emoji = type switch
|
||||
{
|
||||
MsgType.Error => _errorEmoji,
|
||||
MsgType.Pending => _warnEmoji,
|
||||
MsgType.Ok => _okEmoji,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type)),
|
||||
};
|
||||
|
||||
return ctx.Message.AddReactionAsync(emoji);
|
||||
}
|
||||
|
||||
public static Task OkAsync(this ICommandContext ctx)
|
||||
=> ctx.ReactAsync(MsgType.Ok);
|
||||
|
||||
public static Task ErrorAsync(this ICommandContext ctx)
|
||||
=> ctx.ReactAsync(MsgType.Error);
|
||||
|
||||
public static Task WarningAsync(this ICommandContext ctx)
|
||||
=> ctx.ReactAsync(MsgType.Pending);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user