Skip to content

Commit

Permalink
Merge branch 'dev' into dependabot/nuget/MySql.Data-8.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Demessence authored Mar 20, 2024
2 parents 6a02727 + 943d7db commit 90785da
Show file tree
Hide file tree
Showing 44 changed files with 2,341 additions and 648 deletions.
22 changes: 22 additions & 0 deletions DiscordBot/Attributes/BotCommandChannelAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Discord.Commands;
using DiscordBot.Settings;
using Microsoft.Extensions.DependencyInjection;

namespace DiscordBot.Attributes;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class BotCommandChannelAttribute : PreconditionAttribute
{
public override async Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var settings = services.GetRequiredService<BotSettings>();

if (context.Channel.Id == settings.BotCommandsChannel.Id)
{
return await Task.FromResult(PreconditionResult.FromSuccess());
}

Task task = context.Message.DeleteAfterSeconds(seconds: 10);
return await Task.FromResult(PreconditionResult.FromError($"This command can only be used in <#{settings.BotCommandsChannel.Id.ToString()}>."));
}
}
48 changes: 48 additions & 0 deletions DiscordBot/Attributes/IgnoreBotsAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Discord.Commands;

namespace DiscordBot.Attributes;

/// <summary>
/// Simple attribute, if the command is used by a bot, it escapes early and doesn't run the command.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class IgnoreBotsAttribute : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
if (context.Message.Author.IsBot)
{
return Task.FromResult(PreconditionResult.FromError(string.Empty));
}

return Task.FromResult(PreconditionResult.FromSuccess());
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class IgnoreBotsAndWebhooksAttribute : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
if (context.Message.Author.IsBot || context.Message.Author.IsWebhook)
{
return Task.FromResult(PreconditionResult.FromError(string.Empty));
}

return Task.FromResult(PreconditionResult.FromSuccess());
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class IgnoreWebhooksAttribute : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
if (context.Message.Author.IsWebhook)
{
return Task.FromResult(PreconditionResult.FromError(string.Empty));
}

return Task.FromResult(PreconditionResult.FromSuccess());
}
}
31 changes: 31 additions & 0 deletions DiscordBot/Attributes/RoleAttributes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Discord.Commands;
using Discord.WebSocket;
using DiscordBot.Settings;
using Microsoft.Extensions.DependencyInjection;

namespace DiscordBot.Attributes;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireAdminAttribute : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var user = (SocketGuildUser)context.Message.Author;

if (user.Roles.Any(x => x.Permissions.Administrator)) return Task.FromResult(PreconditionResult.FromSuccess());
return Task.FromResult(PreconditionResult.FromError(user + " attempted to use admin only command!"));
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireModeratorAttribute : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var user = (SocketGuildUser)context.Message.Author;
var settings = services.GetRequiredService<BotSettings>();

if (user.Roles.Any(x => x.Id == settings.ModeratorRoleId)) return Task.FromResult(PreconditionResult.FromSuccess());
return Task.FromResult(PreconditionResult.FromError(user + " attempted to use a moderator command!"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,7 @@
using DiscordBot.Settings;
using Microsoft.Extensions.DependencyInjection;

namespace DiscordBot;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireAdminAttribute : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var user = (SocketGuildUser)context.Message.Author;

if (user.Roles.Any(x => x.Permissions.Administrator)) return Task.FromResult(PreconditionResult.FromSuccess());
return Task.FromResult(PreconditionResult.FromError(user + " attempted to use admin only command!"));
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireModeratorAttribute : PreconditionAttribute
{
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var user = (SocketGuildUser)context.Message.Author;
var settings = services.GetRequiredService<BotSettings>();

if (user.Roles.Any(x => x.Id == settings.ModeratorRoleId)) return Task.FromResult(PreconditionResult.FromSuccess());
return Task.FromResult(PreconditionResult.FromError(user + " attempted to use a moderator command!"));
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class BotChannelOnlyAttribute : PreconditionAttribute
{
public override async Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var settings = services.GetRequiredService<BotSettings>();

if (context.Channel.Id == settings.BotCommandsChannel.Id)
{
return await Task.FromResult(PreconditionResult.FromSuccess());
}

Task task = context.Message.DeleteAfterSeconds(seconds: 10);
return await Task.FromResult(PreconditionResult.FromError($"This command can only be used in <#{settings.BotCommandsChannel.Id.ToString()}>."));
}
}
namespace DiscordBot.Attributes;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireThreadAttribute : PreconditionAttribute
Expand Down
2 changes: 1 addition & 1 deletion DiscordBot/DiscordBot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<LangVersion>10</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.11.0" />
<PackageReference Include="Discord.Net" Version="3.13.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.51" />
<PackageReference Include="Insight.Database" Version="6.3.11" />
<PackageReference Include="Magick.NET-Q8-x64" Version="7.5.0.1" />
Expand Down
36 changes: 34 additions & 2 deletions DiscordBot/Extensions/ContextExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,42 @@ namespace DiscordBot.Extensions;
public static class ContextExtension
{
/// <summary>
/// Returns true if the context includes a RoleID, UserID or Mentions Everyone (Should include @here, unsure)
/// Sanity test to confirm a Context doesn't contain role or everyone mentions.
/// </summary>
/// <remarks>Use `HasAnyPingableMention` to also include user mentions.</remarks>
public static bool HasRoleOrEveryoneMention(this ICommandContext context)
{
return context.Message.MentionedRoleIds.Count != 0 || context.Message.MentionedEveryone;
}

/// <summary>
/// True if the context includes a RoleID, UserID or Mentions Everyone (Should include @here, unsure)
/// </summary>
/// <remarks>Use `HasRoleOrEveryoneMention` to check for ONLY RoleIDs or Everyone mentions.</remarks>
public static bool HasAnyPingableMention(this ICommandContext context)
{
return context.Message.MentionedUserIds.Count > 0 || context.Message.MentionedRoleIds.Count > 0 || context.Message.MentionedEveryone;
return context.Message.MentionedUserIds.Count > 0 || context.HasRoleOrEveryoneMention();
}

/// <summary>
/// True if the Context contains a message that is a reply and only mentions the user that sent the message.
/// ie; the message is a reply to the user but doesn't contain any other mentions.
/// </summary>
public static bool IsOnlyReplyingToAuthor(this ICommandContext context)
{
if (!context.IsReply())
return false;
if (context.Message.MentionedUserIds.Count != 1)
return false;
return context.Message.MentionedUserIds.First() == context.Message.ReferencedMessage.Author.Id;
}

/// <summary>
/// Returns true if the Context has a reference to another message.
/// ie; the message is a reply to another message.
/// </summary>
public static bool IsReply(this ICommandContext context)
{
return context.Message.ReferencedMessage != null;
}
}
15 changes: 15 additions & 0 deletions DiscordBot/Extensions/DBConnectionExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Data.Common;
using Insight.Database;

namespace DiscordBot.Extensions;

public static class DBConnectionExtension
{
public static async Task<bool> ColumnExists(this DbConnection connection, string tableName, string columnName)
{
// Execute the query `SHOW COLUMNS FROM `{tableName}` LIKE '{columnName}'` and check if any rows are returned
var query = $"SHOW COLUMNS FROM `{tableName}` LIKE '{columnName}'";
var response = await connection.QuerySqlAsync(query);
return response.Count > 0;
}
}
45 changes: 45 additions & 0 deletions DiscordBot/Extensions/EmbedBuilderExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace DiscordBot.Extensions;

public static class EmbedBuilderExtension
{

public static EmbedBuilder FooterRequestedBy(this EmbedBuilder builder, IUser requestor)
{
builder.WithFooter(
$"Requested by {requestor.GetUserPreferredName()}",
requestor.GetAvatarUrl());
return builder;
}

public static EmbedBuilder FooterQuoteBy(this EmbedBuilder builder, IUser requestor, IChannel channel)
{
builder.WithFooter(
$"Quoted by {requestor.GetUserPreferredName()}, • From channel #{channel.Name}",
requestor.GetAvatarUrl());
return builder;
}

public static EmbedBuilder FooterInChannel(this EmbedBuilder builder, IChannel channel)
{
builder.WithFooter(
$"In channel #{channel.Name}", null);
return builder;
}

public static EmbedBuilder AddAuthor(this EmbedBuilder builder, IUser user, bool includeAvatar = true)
{
builder.WithAuthor(
user.GetUserPreferredName(),
includeAvatar ? user.GetAvatarUrl() : null);
return builder;
}

public static EmbedBuilder AddAuthorWithAction(this EmbedBuilder builder, IUser user, string action, bool includeAvatar = true)
{
builder.WithAuthor(
$"{user.GetUserPreferredName()} - {action}",
includeAvatar ? user.GetAvatarUrl() : null);
return builder;
}

}
29 changes: 29 additions & 0 deletions DiscordBot/Extensions/MessageExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
using System.Text.RegularExpressions;

namespace DiscordBot.Extensions;

public static class MessageExtensions
{
private const string InviteLinkPattern = @"(https?:\/\/)?(www\.)?(discord\.gg\/[a-zA-Z0-9]+)";

public static async Task<bool> TrySendMessage(this IDMChannel channel, string message = "", Embed embed = null)
{
try
Expand All @@ -22,4 +26,29 @@ public static bool HasAnyPingableMention(this IUserMessage message)
{
return message.MentionedUserIds.Count > 0 || message.MentionedRoleIds.Count > 0 || message.MentionedEveryone;
}

/// <summary>
/// Returns true if the message contains any discord invite links, ie; discord.gg/invite
/// </summary>
public static bool ContainsInviteLink(this IUserMessage message)
{
return Regex.IsMatch(message.Content, InviteLinkPattern, RegexOptions.IgnoreCase);
}

/// <summary>
/// Returns true if the message contains any discord invite links, ie; discord.gg/invite
/// </summary>
public static bool ContainsInviteLink(this string message)
{
return Regex.IsMatch(message, InviteLinkPattern, RegexOptions.IgnoreCase);
}

/// <summary>
/// Returns true if the message contains any discord invite links, ie; discord.gg/invite
/// </summary>
public static bool ContainsInviteLink(this IMessage message)
{
return Regex.IsMatch(message.Content, InviteLinkPattern, RegexOptions.IgnoreCase);
}

}
Loading

0 comments on commit 90785da

Please sign in to comment.