Skip to content

Commit b286f1b

Browse files
committed
Many optimizations, addition of Unix arguments and addition of the Announce command
1 parent 9d9260d commit b286f1b

File tree

94 files changed

+717
-602
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+717
-602
lines changed

.editorconfig

+5
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
# CA1031: Do not catch general exception types
22

3+
4+
[*.cs]
5+
6+
# IDE0008: Use explicit type
7+
dotnet_diagnostic.IDE0008.severity = none

.github/CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @GreemDev
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading.Tasks;
4+
using Discord;
5+
using Discord.Rest;
6+
using Discord.WebSocket;
7+
using Gommon;
8+
using Qmmands;
9+
using Volte.Core;
10+
using Volte.Core.Helpers;
11+
12+
namespace Volte.Commands.Modules
13+
{
14+
public sealed partial class AdminUtilityModule
15+
{
16+
[Command("Announce")]
17+
[Description("Allows you to construct a custom embed from Unix-style command arguments.")]
18+
public async Task<ActionResult> AnnounceAsync(
19+
[Remainder,
20+
Description(
21+
"Unix-style command line arguments. Example: `-description=\"Some cool thing!\"` will set the embed's description.")]
22+
Dictionary<string, string> options)
23+
{
24+
var embed = new EmbedBuilder();
25+
26+
string GetRoleMention(TypeParserResult<SocketRole> res) => res.IsSuccessful ? res.Value.Mention : null;
27+
28+
Color GetColor(TypeParserResult<Color> res) =>
29+
res.IsSuccessful ? res.Value : new Color(Config.SuccessColor);
30+
31+
RestGuildUser GetUser(TypeParserResult<RestGuildUser> res) => res.IsSuccessful ? res.Value : null;
32+
33+
string toMention = null;
34+
35+
if (options.TryGetValue("mention", out var result) || options.TryGetValue("ping", out result))
36+
{
37+
toMention = result switch
38+
{
39+
"none" => null,
40+
"everyone" => "@everyone",
41+
"here" => "@here",
42+
_ => GetRoleMention(await CommandService.GetTypeParser<SocketRole>()
43+
.ParseAsync(null, result, Context))
44+
};
45+
}
46+
47+
if (options.TryGetValue("footer", out result) || options.TryGetValue("foot", out result))
48+
embed.WithFooter(result);
49+
50+
if (options.TryGetValue("thumbnail", out result))
51+
{
52+
if (!Uri.IsWellFormedUriString(result, UriKind.Absolute))
53+
return BadRequest("Thumbnail URL must be a valid image URL.");
54+
55+
embed.WithThumbnailUrl(result);
56+
}
57+
58+
if (options.TryGetValue("image", out result))
59+
{
60+
if (!Uri.IsWellFormedUriString(result, UriKind.Absolute))
61+
return BadRequest("Image URL must be a valid image URL.");
62+
63+
embed.WithImageUrl(result);
64+
}
65+
66+
if (options.TryGetValue("description", out result) || options.TryGetValue("desc", out result))
67+
embed.WithDescription(result);
68+
69+
if (options.TryGetValue("title", out result))
70+
embed.WithTitle(result);
71+
72+
if (options.TryGetValue("color", out result) || options.TryGetValue("colour", out result))
73+
embed.WithColor(GetColor(await CommandService.GetTypeParser<Color>()
74+
.ParseAsync(null, result, Context)));
75+
76+
if (options.TryGetValue("author", out result))
77+
{
78+
if (result.EqualsIgnoreCase("self") || result.EqualsIgnoreCase("me"))
79+
embed.WithAuthor(Context.User);
80+
else if (result.EqualsIgnoreCase("bot")
81+
|| result.EqualsIgnoreCase("you")
82+
|| result.EqualsIgnoreCase("volte"))
83+
embed.WithAuthor(Context.Guild.CurrentUser);
84+
else
85+
{
86+
var user = GetUser(await CommandService.GetTypeParser<RestGuildUser>()
87+
.ParseAsync(null, result, Context));
88+
if (user != null)
89+
embed.WithAuthor(user);
90+
}
91+
}
92+
93+
return Ok(async () =>
94+
{
95+
await Context.Channel.SendMessageAsync(toMention, embed: embed.Build());
96+
await Context.Message.TryDeleteAsync();
97+
});
98+
}
99+
}
100+
}

src/Commands/Modules/BlacklistModule.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,11 @@ public Task<ActionResult> BlacklistActionAsync(
6868
[Command("List", "L")]
6969
[Description("Lists every single word/phrase inside of the blacklist.")]
7070
public Task<ActionResult> BlacklistListAsync()
71-
{
72-
return Ok(Context.CreateEmbedBuilder()
71+
=> Ok(Context.CreateEmbedBuilder()
7372
.WithTitle($"Blacklist for {Context.Guild.Name}")
7473
.WithDescription(Context.GuildData.Configuration.Moderation.Blacklist.IsEmpty()
7574
? "This guild has no words/phrases blacklisted."
7675
: Context.GuildData.Configuration.Moderation.Blacklist.Select(x => Format.Code(x)).Join(", "))
7776
);
78-
}
7977
}
8078
}

src/Commands/Modules/BotOwner/CreateConfigCommand.cs

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
using Discord;
33
using Discord.WebSocket;
44
using Qmmands;
5-
using Volte.Core.Entities;
6-
using Volte.Commands;
75

86
namespace Volte.Commands.Modules
97
{

src/Commands/Modules/BotOwner/SetGameCommand.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ public Task<ActionResult> SetGameAsync([Remainder, Description("The name of the
1515
{
1616
var activity = Context.Client.Activity;
1717
return activity.Type is ActivityType.Streaming
18-
? Ok($"Set the bot's game to **{game}**.", _ => Context.Client.SetGameAsync(game, activity.Cast<StreamingGame>().Url, activity.Type))
19-
: Ok($"Set the bot's game to **{game}**.", _ => Context.Client.SetGameAsync(game));
18+
? Ok($"Set the bot's game to {Format.Bold(game)}.", _ => Context.Client.SetGameAsync(game, activity.Cast<StreamingGame>().Url, activity.Type))
19+
: Ok($"Set the bot's game to {Format.Bold(game)}.", _ => Context.Client.SetGameAsync(game));
2020
}
2121
}
2222
}

src/Commands/Modules/BotOwner/SetNameCommand.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Threading.Tasks;
2+
using Discord;
23
using Qmmands;
34
using Volte.Core.Entities;
45
using Volte.Commands;
@@ -10,6 +11,6 @@ public sealed partial class BotOwnerModule
1011
[Command("SetName")]
1112
[Description("Sets the bot's username.")]
1213
public Task<ActionResult> SetNameAsync([Remainder, Description("The username to use.")] string name)
13-
=> Ok($"Set my username to **{name}**.", _ => Context.Client.CurrentUser.ModifyAsync(u => u.Username = name));
14+
=> Ok($"Set my username to {Format.Bold(name)}.", _ => Context.Client.CurrentUser.ModifyAsync(u => u.Username = name));
1415
}
1516
}

src/Commands/Modules/BotOwner/SetStreamCommand.cs

+10-9
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ public sealed partial class BotOwnerModule
1010
{
1111
[Command("SetStream")]
1212
[Description("Sets the bot's stream via Twitch username and Stream name, respectively.")]
13-
public Task<ActionResult> SetStreamAsync([Description("The Twitch username to link to in the status.")] string stream, [Remainder, Description("The stream title to show.")] string game = null)
14-
{
15-
return !game.IsNullOrWhitespace()
13+
public Task<ActionResult> SetStreamAsync([Description("The Twitch username to link to in the status.")]
14+
string stream, [Remainder, Description("The stream title to show.")]
15+
string game = null)
16+
=> !game.IsNullOrWhitespace()
1617
? Ok(
17-
$"Set the bot's game to **{game}**, and the Twitch URL to **[{stream}](https://twitch.tv/{stream})**.",
18-
_ => Context.Client.SetGameAsync(game, $"https://twitch.tv/{stream}", ActivityType.Streaming))
18+
$"Set the bot's game to **{game}**, and the Twitch URL to **[{stream}](https://twitch.tv/{stream})**.",
19+
_ => Context.Client.SetGameAsync(game, $"https://twitch.tv/{stream}", ActivityType.Streaming))
1920
: Ok(
20-
$"Set the bot's stream URL to **[{stream}](https://twitch.tv/{stream})**.",
21-
_ => Context.Client.SetGameAsync(Context.Client.Activity.Name, $"https://twitch.tv/{stream}", ActivityType.Streaming));
22-
}
21+
$"Set the bot's stream URL to **[{stream}](https://twitch.tv/{stream})**.",
22+
_ => Context.Client.SetGameAsync(Context.Client.Activity.Name, $"https://twitch.tv/{stream}",
23+
ActivityType.Streaming));
2324
}
24-
}
25+
}

src/Commands/Modules/HelpCommand.cs

+5-11
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,20 @@ public async Task<ActionResult> HelpAsync(
4747

4848
try
4949
{
50-
if (!cmds.IsEmpty())
51-
e.AddField("Regular Commands", cmds.Join(", "));
50+
if (!cmds.IsEmpty()) e.AddField("Regular Commands", cmds.Join(", "));
5251
}
5352
catch (ArgumentException)
5453
{
55-
e.AppendDescriptionLine()
56-
.AppendDescriptionLine(cmds.Join(", "));
54+
e.AppendDescriptionLine().AppendDescriptionLine(cmds.Join(", "));
5755
}
5856

5957
try
6058
{
61-
if (!groupCmds.IsEmpty())
62-
e.AddField("Group Commands", groupCmds.Join(", "));
59+
if (!groupCmds.IsEmpty()) e.AddField("Group Commands", groupCmds.Join(", "));
6360
}
6461
catch (ArgumentException)
6562
{
66-
e.AppendDescriptionLine()
67-
.AppendDescriptionLine(groupCmds.Join(", "));
63+
e.AppendDescriptionLine().AppendDescriptionLine(groupCmds.Join(", "));
6864
}
6965

7066
return Ok(e);
@@ -97,12 +93,10 @@ private async IAsyncEnumerable<string> GetAllGroupCommandsAsync()
9793
}
9894
}
9995

100-
private async IAsyncEnumerable<EmbedBuilder> GetPagesAsync()
96+
private async IAsyncEnumerable<EmbedBuilder> GetPagesAsync()
10197
{
10298
foreach (var cmd in await CommandService.GetAllCommands().WhereAccessibleAsync(Context).ToListAsync())
103-
{
10499
yield return await CommandHelper.CreateCommandEmbedAsync(cmd, Context);
105-
}
106100
}
107101
}
108102
}

src/Commands/Modules/Moderation/BanCommand.cs

+5-7
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@ public async Task<ActionResult> BanAsync([CheckHierarchy, EnsureNotSelf, Descrip
1919
[Remainder, Description("The reason for the ban.")]
2020
string reason = "Banned by a Moderator.")
2121
{
22-
var e = Context.CreateEmbedBuilder($"You've been banned from **{Context.Guild.Name}** for **{reason}**.");
23-
if (!Context.GuildData.Configuration.Moderation.ShowResponsibleModerator)
24-
{
25-
e.WithAuthor(author: null);
26-
e.WithSuccessColor();
27-
}
22+
var e = Context
23+
.CreateEmbedBuilder(
24+
$"You've been banned from {Format.Bold(Context.Guild.Name)} for {Format.Bold(reason)}.")
25+
.ApplyConfig(Context.GuildData);
2826

2927
if (!await member.TrySendMessageAsync(embed: e.Build()))
30-
Logger.Warn(LogSource.Volte, $"encountered a 403 when trying to message {member}!");
28+
Logger.Warn(LogSource.Module, $"encountered a 403 when trying to message {member}!");
3129

3230
try
3331
{

src/Commands/Modules/Moderation/BansCommand.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public async Task<ActionResult> BansAsync()
1818
var banList = await Context.Guild.GetBansAsync();
1919
return !banList.Any()
2020
? BadRequest("This guild doesn't have anyone banned.")
21-
: Ok(banList.Select(b => $"**{b.User}**: `{b.Reason ?? "No reason provided."}`").Join('\n'));
21+
: Ok(banList.Select(b => $"**{b.User}**: {Format.Code(b.Reason ?? "No reason provided.")}").Join('\n'));
2222
}
2323
}
2424
}

src/Commands/Modules/Moderation/KickCommand.cs

+3-7
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,11 @@ public async Task<ActionResult> KickAsync([CheckHierarchy, EnsureNotSelf, Descri
1919
[Remainder, Description("The reason for the kick.")]
2020
string reason = "Kicked by a Moderator.")
2121
{
22-
var e = Context.CreateEmbedBuilder($"You've been kicked from **{Context.Guild.Name}** for **{reason}**.");
23-
if (!Context.GuildData.Configuration.Moderation.ShowResponsibleModerator)
24-
{
25-
e.WithAuthor(author: null);
26-
e.WithSuccessColor();
27-
}
22+
var e = Context.CreateEmbedBuilder($"You've been kicked from **{Context.Guild.Name}** for **{reason}**.")
23+
.ApplyConfig(Context.GuildData);
2824

2925
if (!await user.TrySendMessageAsync(embed: e.Build()))
30-
Logger.Warn(LogSource.Volte, $"encountered a 403 when trying to message {user}!");
26+
Logger.Warn(LogSource.Module, $"encountered a 403 when trying to message {user}!");
3127

3228
try
3329
{

src/Commands/Modules/Moderation/PurgeCommand.cs

+5-7
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,28 @@ public async Task<ActionResult> PurgeAsync([Description("The amount of messages
2626
var messages = (await Context.Channel.GetMessagesAsync(count + 1).FlattenAsync()).ToList();
2727
try
2828
{
29-
var reqOpts = DiscordHelper.CreateRequestOptions(opts =>
30-
opts.AuditLogReason = $"Messages purged by {Context.User}.");
31-
3229
await Context.Channel.DeleteMessagesAsync(
3330
messages.Where(x => targetAuthor is null || x.Author.Id == targetAuthor.Id),
34-
reqOpts);
31+
DiscordHelper.CreateRequestOptions(opts =>
32+
opts.AuditLogReason = $"Messages purged by {Context.User}."));
3533
}
3634
catch (ArgumentOutOfRangeException)
3735
{
3836
return BadRequest(
39-
"Messages bulk deleted must be younger than 14 days. (**This is a Discord restriction, not a Volte one.**)");
37+
$"Messages bulk deleted must be younger than 14 days. {Format.Code("This is a Discord restriction, not a Volte one.")}");
4038
}
4139

4240
//-1 to show that the correct amount of messages were deleted.
4341
return None(async () =>
4442
{
4543
await Interactive.ReplyAndDeleteAsync(Context, string.Empty,
46-
embed: Context.CreateEmbed($"Successfully deleted **{"message".ToQuantity(messages.Count - 1)}**."),
44+
embed: Context.CreateEmbed($"Successfully deleted {Format.Bold("message".ToQuantity(messages.Count - 1))}."),
4745
timeout: 3.Seconds());
4846
await ModerationService.OnModActionCompleteAsync(ModActionEventArgs.New
4947
.WithDefaultsFromContext(Context)
5048
.WithActionType(ModActionType.Purge)
5149
.WithCount(count));
52-
});
50+
}, false);
5351
}
5452
}
5553
}

src/Commands/Modules/Moderation/SoftbanCommand.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public async Task<ActionResult> SoftBanAsync(
3131
}
3232

3333
if (!await user.TrySendMessageAsync(embed: e.Build()))
34-
Logger.Warn(LogSource.Volte, $"encountered a 403 when trying to message {user}!");
34+
Logger.Warn(LogSource.Module, $"encountered a 403 when trying to message {user}!");
3535

3636
try
3737
{

src/Commands/Modules/Moderation/VerifyCommand.cs

+12-9
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ public partial class ModerationModule
1212
{
1313
[Command("Verify", "V")]
1414
[Description("Verifies a member.")]
15-
public async Task<ActionResult> VerifyAsync([Remainder, EnsureNotSelf, Description("The user to verify; by removing the Unverified role and granting the Verified role.")] SocketGuildUser member)
15+
public async Task<ActionResult> VerifyAsync(
16+
[Remainder, EnsureNotSelf,
17+
Description("The user to verify; by removing the Unverified role and granting the Verified role.")]
18+
SocketGuildUser member)
1619
{
1720
var e = Context.CreateEmbedBuilder($"You've been verified in **{Context.Guild.Name}**.");
1821
if (!Context.GuildData.Configuration.Moderation.ShowResponsibleModerator)
@@ -22,12 +25,13 @@ public partial class ModerationModule
2225
}
2326

2427
if (!await member.TrySendMessageAsync(embed: e.Build()))
25-
Logger.Warn(LogSource.Volte, $"encountered a 403 when trying to message {member}!");
28+
Logger.Warn(LogSource.Module, $"encountered a 403 when trying to message {member}!");
2629

2730
var uRole = Context.Guild.GetRole(Context.GuildData.Configuration.Moderation.UnverifiedRole);
2831
var vRole = Context.Guild.GetRole(Context.GuildData.Configuration.Moderation.VerifiedRole);
2932
if (uRole is null)
30-
return BadRequest("This guild does not have an Unverified role set. Please use the VerifyRole command.");
33+
return BadRequest(
34+
"This guild does not have an Unverified role set. Please use the VerifyRole command.");
3135
if (vRole is null)
3236
return BadRequest("This guild does not have a Verified role set. Please use the VerifyRole command.");
3337
if (member.HasRole(vRole.Id))
@@ -37,14 +41,13 @@ public partial class ModerationModule
3741

3842
await member.RemoveRoleAsync(uRole);
3943
await member.AddRoleAsync(vRole);
40-
41-
return Ok($"Successfully verified {member.Mention}.", async _ =>
42-
{
43-
await ModerationService.OnModActionCompleteAsync(ModActionEventArgs.New
44+
45+
return Ok($"Successfully verified {member.Mention}.", _ =>
46+
ModerationService.OnModActionCompleteAsync(ModActionEventArgs.New
4447
.WithDefaultsFromContext(Context)
4548
.WithActionType(ModActionType.Verify)
46-
.WithTarget(member));
47-
});
49+
.WithTarget(member))
50+
);
4851
}
4952
}
5053
}

0 commit comments

Comments
 (0)