From 9dae8289dcef8bf5fae3b88bafd96a7f219705de Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Thu, 20 Aug 2020 01:17:45 +0200 Subject: [PATCH 1/8] Add database model and migrations for RoleReaction --- .../20200819203430_RoleReaction.Designer.cs | 163 ++++++++++++++++++ .../Migrations/20200819203430_RoleReaction.cs | 33 ++++ .../ChaosbotContextModelSnapshot.cs | 26 ++- ChaosBot/Models/ChaosbotContext.cs | 3 + ChaosBot/Models/RoleReaction.cs | 37 ++++ 5 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 ChaosBot/Migrations/20200819203430_RoleReaction.Designer.cs create mode 100644 ChaosBot/Migrations/20200819203430_RoleReaction.cs create mode 100644 ChaosBot/Models/RoleReaction.cs diff --git a/ChaosBot/Migrations/20200819203430_RoleReaction.Designer.cs b/ChaosBot/Migrations/20200819203430_RoleReaction.Designer.cs new file mode 100644 index 0000000..6826a1a --- /dev/null +++ b/ChaosBot/Migrations/20200819203430_RoleReaction.Designer.cs @@ -0,0 +1,163 @@ +// +using System; +using ChaosBot.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace ChaosBot.Migrations +{ + [DbContext(typeof(ChaosbotContext))] + [Migration("20200819203430_RoleReaction")] + partial class RoleReaction + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.6") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("ChaosBot.Models.CommandPermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned"); + + b.Property("Command") + .IsRequired() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("TargetId") + .HasColumnType("bigint unsigned"); + + b.Property("TargetType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CommandPermissions"); + }); + + modelBuilder.Entity("ChaosBot.Models.Configuration", b => + { + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("Key") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("SerializedValue") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("DiscordGuildId", "Key"); + + b.ToTable("Configuration"); + }); + + modelBuilder.Entity("ChaosBot.Models.Experience", b => + { + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("DiscordUserId") + .HasColumnType("bigint unsigned"); + + b.Property("Amount") + .HasColumnType("bigint unsigned"); + + b.Property("LastUpdated") + .HasColumnType("datetime"); + + b.Property("Level") + .HasColumnType("bigint unsigned"); + + b.HasKey("DiscordGuildId", "DiscordUserId"); + + b.ToTable("ExperiencePoints"); + }); + + modelBuilder.Entity("ChaosBot.Models.LodestoneCharacter", b => + { + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("LodestoneId") + .HasColumnType("bigint unsigned"); + + b.Property("Avatar") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("DiscordUserId") + .HasColumnType("bigint unsigned"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("DiscordGuildId", "LodestoneId"); + + b.ToTable("LodestoneCharacter"); + }); + + modelBuilder.Entity("ChaosBot.Models.LodestoneFreeCompany", b => + { + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("LodestoneId") + .HasColumnType("bigint unsigned"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("DiscordGuildId", "LodestoneId"); + + b.ToTable("LodestoneFreeCompany"); + }); + + modelBuilder.Entity("ChaosBot.Models.Point", b => + { + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("DiscordUserId") + .HasColumnType("bigint unsigned"); + + b.Property("Amount") + .HasColumnType("bigint unsigned"); + + b.HasKey("DiscordGuildId", "DiscordUserId"); + + b.ToTable("Points"); + }); + + modelBuilder.Entity("ChaosBot.Models.Raffle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned"); + + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("DiscordUserId") + .HasColumnType("bigint unsigned"); + + b.HasKey("Id"); + + b.ToTable("Raffles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ChaosBot/Migrations/20200819203430_RoleReaction.cs b/ChaosBot/Migrations/20200819203430_RoleReaction.cs new file mode 100644 index 0000000..45887d3 --- /dev/null +++ b/ChaosBot/Migrations/20200819203430_RoleReaction.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace ChaosBot.Migrations +{ + public partial class RoleReaction : Migration + { + protected readonly string Table = "RoleReactions"; + + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: Table, + columns: table => new + { + DiscordGuildId = table.Column(nullable: false), + DiscordMessageId = table.Column(nullable: false), + DiscordRoleId = table.Column(nullable: false), + DiscordEmoteNameEncoded = table.Column(nullable: false, maxLength: 128) + }, + constraints: table => + { + table.PrimaryKey("PK_RoleReactions", x => new { x.DiscordGuildId, x.DiscordRoleId, x.DiscordMessageId, x.DiscordEmoteNameEncoded }); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable(name: Table); + } + } +} diff --git a/ChaosBot/Migrations/ChaosbotContextModelSnapshot.cs b/ChaosBot/Migrations/ChaosbotContextModelSnapshot.cs index 9903ed6..449c819 100644 --- a/ChaosBot/Migrations/ChaosbotContextModelSnapshot.cs +++ b/ChaosBot/Migrations/ChaosbotContextModelSnapshot.cs @@ -1,4 +1,5 @@ // +using System; using ChaosBot.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -24,7 +25,8 @@ namespace ChaosBot.Migrations b.Property("Command") .IsRequired() - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); b.Property("DiscordGuildId") .HasColumnType("bigint unsigned"); @@ -58,6 +60,28 @@ namespace ChaosBot.Migrations b.ToTable("Configuration"); }); + modelBuilder.Entity("ChaosBot.Models.Experience", b => + { + b.Property("DiscordGuildId") + .HasColumnType("bigint unsigned"); + + b.Property("DiscordUserId") + .HasColumnType("bigint unsigned"); + + b.Property("Amount") + .HasColumnType("bigint unsigned"); + + b.Property("LastUpdated") + .HasColumnType("datetime"); + + b.Property("Level") + .HasColumnType("bigint unsigned"); + + b.HasKey("DiscordGuildId", "DiscordUserId"); + + b.ToTable("ExperiencePoints"); + }); + modelBuilder.Entity("ChaosBot.Models.LodestoneCharacter", b => { b.Property("DiscordGuildId") diff --git a/ChaosBot/Models/ChaosbotContext.cs b/ChaosBot/Models/ChaosbotContext.cs index 7715eb6..bb6c866 100644 --- a/ChaosBot/Models/ChaosbotContext.cs +++ b/ChaosBot/Models/ChaosbotContext.cs @@ -12,6 +12,7 @@ namespace ChaosBot.Models public DbSet CommandPermissions { get; set; } public DbSet Configuration { get; set; } public DbSet ExperiencePoints { get; set; } + public DbSet RoleReactions { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -46,6 +47,8 @@ namespace ChaosBot.Models .HasKey(x => new {x.DiscordGuildId, x.DiscordUserId}); modelBuilder.Entity() .HasKey(x => new {x.DiscordGuildId, x.Key}); + modelBuilder.Entity() + .HasKey(x => new {x.DiscordGuildId, x.DiscordMessageId, x.DiscordRoleId, x.DiscordEmoteNameEncoded}); } } } \ No newline at end of file diff --git a/ChaosBot/Models/RoleReaction.cs b/ChaosBot/Models/RoleReaction.cs new file mode 100644 index 0000000..deaf0c7 --- /dev/null +++ b/ChaosBot/Models/RoleReaction.cs @@ -0,0 +1,37 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace ChaosBot.Models +{ + #region Required + public class RoleReaction + { + [Required] + public ulong DiscordGuildId { get; set; } + [Required] + public ulong DiscordMessageId { get; set; } + [Required] + public ulong DiscordRoleId { get; set; } + + [NotMapped] + public string DiscordEmoteName + { + get + { + if (DiscordEmoteNameEncoded == null) return null; + return Encoding.UTF8.GetString(Convert.FromBase64String(DiscordEmoteNameEncoded)); + } + set + { + if (value != null) + DiscordEmoteNameEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(value)); + } + } + + [Required] + public string DiscordEmoteNameEncoded { get; set; } + } + #endregion +} \ No newline at end of file From 38fd89eeefad53a0f0dbd5879726e11762d091d6 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Thu, 20 Aug 2020 01:18:02 +0200 Subject: [PATCH 2/8] Add basic role add command --- ChaosBot/Discord/Modules/Admin/Role.cs | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 ChaosBot/Discord/Modules/Admin/Role.cs diff --git a/ChaosBot/Discord/Modules/Admin/Role.cs b/ChaosBot/Discord/Modules/Admin/Role.cs new file mode 100644 index 0000000..bf99aa7 --- /dev/null +++ b/ChaosBot/Discord/Modules/Admin/Role.cs @@ -0,0 +1,94 @@ +using System; +using Discord; +using Discord.Commands; +using System.Threading.Tasks; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using ChaosBot.Discord.PreConditions; +using ChaosBot.Models; +using Microsoft.EntityFrameworkCore; +using NLog; + +namespace ChaosBot.Discord.Modules.Admin +{ + public class Role : ModuleBase + { + private static readonly ILogger Logger = Program.Logger; + + [Command("role add")] + [CheckCommandPerm("Admin")] + public async Task RoleAddCommand(params string[] parameters) + { + try + { + await using (ChaosbotContext dbContext = new ChaosbotContext()) + { + string parameterString = String.Join("", parameters); + + // Fetch last message + IMessage message = (await Context.Channel.GetMessagesAsync(2).FlattenAsync()).Last(); + + // Parse parameters + string pattern = @"((|[^<]+)<@&(\d+)>)"; + string input = parameterString; + + foreach (Match m in Regex.Matches(input, pattern)) + { + try + { + IEmote emote; + string emoteString = m.Groups[2].Value; + string roleString = m.Groups[3].Value; + IRole role = Context.Guild.Roles.First(r => r.Id.ToString() == roleString); + + if (Emote.TryParse(emoteString, out Emote tempEmote)) + { + if (tempEmote.Animated && Context.Client.CurrentUser.PremiumType != PremiumType.Nitro) + throw new NotSupportedException("No support for animated icons"); + + if (Context.Guild.Emotes.All(e => e.Id != tempEmote.Id) && + Context.Client.CurrentUser.PremiumType != PremiumType.Nitro) + throw new NotSupportedException($"No support for emotes from other servers"); + + emote = tempEmote; + } + else + { + emote = new Emoji(emoteString); + } + + // Register DB entry + RoleReaction roleReaction = new RoleReaction + { + DiscordGuildId = Context.Guild.Id, + DiscordMessageId = message.Id, + DiscordRoleId = role.Id, + DiscordEmoteName = emote.ToString() + }; + + await dbContext.RoleReactions.Upsert(roleReaction) + .On(r => new {r.DiscordGuildId, r.DiscordEmoteNameEncoded, r.DiscordMessageId, r.DiscordRoleId}) + .RunAsync(); + + // Add reaction to message + await message.AddReactionAsync(emote); + } + catch (Exception ex) + { + await ReplyAsync($"Something went wrong trying to process {m.Value}: {ex.Message}"); + Logger.Error( + $"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); + } + } + + await dbContext.SaveChangesAsync(); + } + } + catch (Exception ex) + { + Logger.Error($"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); + } + } + } +} \ No newline at end of file From 9fced133947f5c1d02df95a81daa8fae03f01c20 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Thu, 20 Aug 2020 01:18:27 +0200 Subject: [PATCH 3/8] Add template for the RoleReaction services --- ChaosBot/Discord/Services/CommandHandler.cs | 14 ++++++++++++++ .../Discord/Services/RoleReactionHandler.cs | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 ChaosBot/Discord/Services/RoleReactionHandler.cs diff --git a/ChaosBot/Discord/Services/CommandHandler.cs b/ChaosBot/Discord/Services/CommandHandler.cs index af9d4a3..f2d2290 100644 --- a/ChaosBot/Discord/Services/CommandHandler.cs +++ b/ChaosBot/Discord/Services/CommandHandler.cs @@ -33,6 +33,10 @@ namespace ChaosBot.Discord.Services _client.MessageReceived += MessageReceivedAsync; + _client.ReactionAdded += ReactionAddedAsync; + + _client.ReactionRemoved += ReactionRemovedAsync; + _client.UserJoined += AnnounceJoinedUser; _client.UserLeft += AnnounceLeftUser; @@ -81,6 +85,16 @@ namespace ChaosBot.Discord.Services } } + public async Task ReactionAddedAsync(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + RoleReactionHandler.HandleReactionAdded(cacheableMessage, socketMessageChannel, reaction); + } + + public async Task ReactionRemovedAsync(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + RoleReactionHandler.HandleReactionRemoved(cacheableMessage, socketMessageChannel, reaction); + } + public async Task AnnounceJoinedUser(SocketGuildUser user) { try diff --git a/ChaosBot/Discord/Services/RoleReactionHandler.cs b/ChaosBot/Discord/Services/RoleReactionHandler.cs new file mode 100644 index 0000000..f6980f9 --- /dev/null +++ b/ChaosBot/Discord/Services/RoleReactionHandler.cs @@ -0,0 +1,18 @@ +using Discord; +using Discord.WebSocket; + +namespace ChaosBot.Discord.Services +{ + public static class RoleReactionHandler + { + public async static void HandleReactionAdded(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + // This would grant roles based on database lookup + } + + public async static void HandleReactionRemoved(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + { + // This would take roles based on database lookup + } + } +} \ No newline at end of file From 5cf8c3f08b5a7a8323916f07171f03f7e0e9d865 Mon Sep 17 00:00:00 2001 From: Daniel_I_Am Date: Thu, 20 Aug 2020 14:24:51 +0200 Subject: [PATCH 4/8] Add role-reaction help command --- ChaosBot/Discord/Modules/Admin/Role.cs | 43 +++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/ChaosBot/Discord/Modules/Admin/Role.cs b/ChaosBot/Discord/Modules/Admin/Role.cs index bf99aa7..46f7a37 100644 --- a/ChaosBot/Discord/Modules/Admin/Role.cs +++ b/ChaosBot/Discord/Modules/Admin/Role.cs @@ -4,9 +4,11 @@ using Discord.Commands; using System.Threading.Tasks; using System.Linq; using System.Reflection; +using System.Text; using System.Text.RegularExpressions; using ChaosBot.Discord.PreConditions; using ChaosBot.Models; +using ChaosBot.Repositories; using Microsoft.EntityFrameworkCore; using NLog; @@ -16,6 +18,45 @@ namespace ChaosBot.Discord.Modules.Admin { private static readonly ILogger Logger = Program.Logger; + [Command("role")] + [Alias("role info")] + [CheckCommandPerm("Admin")] + public async Task RoleInfoCommand() + { + try + { + var sb = new StringBuilder(); + var embed = new EmbedBuilder(); + + embed.WithColor(new Color(255, 255, 0)); + embed.Title = $"Role Management Help"; + sb.AppendLine(); + sb.AppendLine("To add a role-reaction to a message:"); + sb.AppendLine($"{ConfigurationRepository.GetValue("Discord:Prefix", Context.Guild.Id, "!")}role add "); + sb.AppendLine("To add many role-reactions to a message add more sets of emote and role:"); + sb.AppendLine($"{ConfigurationRepository.GetValue("Discord:Prefix", Context.Guild.Id, "!")}role add "); + sb.AppendLine("To remove a role-reaction from a message:"); + sb.AppendLine($"{ConfigurationRepository.GetValue("Discord:Prefix", Context.Guild.Id, "!")}role remove "); + sb.AppendLine(); + sb.AppendLine("To view this help:"); + sb.AppendLine($"{ConfigurationRepository.GetValue("Discord:Prefix", Context.Guild.Id, "!")}role help"); + + /* + * Add the string to the Embed + */ + embed.Description = sb.ToString(); + + /* + * Reply with the Embed created above + */ + await ReplyAsync(null, false, embed.Build()); + } + catch (Exception ex) + { + Logger.Error($"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); + } + } + [Command("role add")] [CheckCommandPerm("Admin")] public async Task RoleAddCommand(params string[] parameters) @@ -91,4 +132,4 @@ namespace ChaosBot.Discord.Modules.Admin } } } -} \ No newline at end of file +} From d748de5a1517a76dc103a2c1dab1ab1dd1efc223 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Fri, 21 Aug 2020 22:15:25 +0200 Subject: [PATCH 5/8] Add role help alias --- ChaosBot/Discord/Modules/Admin/Role.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChaosBot/Discord/Modules/Admin/Role.cs b/ChaosBot/Discord/Modules/Admin/Role.cs index 46f7a37..2c58de3 100644 --- a/ChaosBot/Discord/Modules/Admin/Role.cs +++ b/ChaosBot/Discord/Modules/Admin/Role.cs @@ -19,7 +19,7 @@ namespace ChaosBot.Discord.Modules.Admin private static readonly ILogger Logger = Program.Logger; [Command("role")] - [Alias("role info")] + [Alias("role help", "role info")] [CheckCommandPerm("Admin")] public async Task RoleInfoCommand() { From 0681254476a758324d3781b76f7c4a65c05bc948 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Fri, 21 Aug 2020 22:15:35 +0200 Subject: [PATCH 6/8] Add role remove command --- ChaosBot/Discord/Modules/Admin/Role.cs | 70 ++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/ChaosBot/Discord/Modules/Admin/Role.cs b/ChaosBot/Discord/Modules/Admin/Role.cs index 2c58de3..1389d88 100644 --- a/ChaosBot/Discord/Modules/Admin/Role.cs +++ b/ChaosBot/Discord/Modules/Admin/Role.cs @@ -131,5 +131,75 @@ namespace ChaosBot.Discord.Modules.Admin Logger.Error($"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); } } + + [Command("role remove")] + [CheckCommandPerm("Admin")] + public async Task RoleRemoveCommand(params string[] parameters) + { + try + { + await using (ChaosbotContext dbContext = new ChaosbotContext()) + { + string parameterString = String.Join("", parameters); + + // Fetch last message + IMessage message = (await Context.Channel.GetMessagesAsync(2).FlattenAsync()).Last(); + + // Parse parameters + string pattern = @"(|..)"; + string input = parameterString; + + foreach (Match m in Regex.Matches(input, pattern)) + { + Logger.Info(m.Value); + try + { + IEmote emote; + string emoteString = m.Value; + + if (Emote.TryParse(emoteString, out Emote tempEmote)) + { + if (tempEmote.Animated && Context.Client.CurrentUser.PremiumType != PremiumType.Nitro) + throw new NotSupportedException("No support for animated icons"); + + if (Context.Guild.Emotes.All(e => e.Id != tempEmote.Id) && + Context.Client.CurrentUser.PremiumType != PremiumType.Nitro) + throw new NotSupportedException($"No support for emotes from other servers"); + + emote = tempEmote; + } + else + { + emote = new Emoji(emoteString); + } + + // Delete DB entries + IQueryable roleReactions = dbContext.RoleReactions; + dbContext.RemoveRange(roleReactions + .Where(r => r.DiscordGuildId == Context.Guild.Id) + .ToList() + .Where(r => r.DiscordEmoteName == emote.ToString()) + .Where(r => r.DiscordMessageId == message.Id) + .ToList()); + + // Remove reaction from message + await message.RemoveReactionAsync(emote, Context.Client.CurrentUser); + } + catch (Exception ex) + { + await ReplyAsync($"Something went wrong trying to process {m.Value}: {ex.Message}"); + Logger.Error( + $"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); + } + } + + await dbContext.SaveChangesAsync(); + } + } + catch (Exception ex) + { + Logger.Error($"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); + } + } } } From b80eb4767c84f523e0ce3cdea53a107bd84bc1f7 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Fri, 21 Aug 2020 22:17:17 +0200 Subject: [PATCH 7/8] Sort modifiers --- ChaosBot/Discord/Services/RoleReactionHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChaosBot/Discord/Services/RoleReactionHandler.cs b/ChaosBot/Discord/Services/RoleReactionHandler.cs index f6980f9..75c0834 100644 --- a/ChaosBot/Discord/Services/RoleReactionHandler.cs +++ b/ChaosBot/Discord/Services/RoleReactionHandler.cs @@ -5,12 +5,12 @@ namespace ChaosBot.Discord.Services { public static class RoleReactionHandler { - public async static void HandleReactionAdded(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + public static async void HandleReactionAdded(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) { // This would grant roles based on database lookup } - public async static void HandleReactionRemoved(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) + public static async void HandleReactionRemoved(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) { // This would take roles based on database lookup } From d1106a8fa4e14fae1040a39624ba392c68bda41b Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Fri, 21 Aug 2020 22:52:08 +0200 Subject: [PATCH 8/8] Add event handlers for role reactions --- .../Discord/Services/RoleReactionHandler.cs | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/ChaosBot/Discord/Services/RoleReactionHandler.cs b/ChaosBot/Discord/Services/RoleReactionHandler.cs index 75c0834..39c4802 100644 --- a/ChaosBot/Discord/Services/RoleReactionHandler.cs +++ b/ChaosBot/Discord/Services/RoleReactionHandler.cs @@ -1,18 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using ChaosBot.Models; using Discord; using Discord.WebSocket; +using NLog; namespace ChaosBot.Discord.Services { public static class RoleReactionHandler { + private static readonly ILogger Logger = Program.Logger; + public static async void HandleReactionAdded(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) { - // This would grant roles based on database lookup + Optional optionalUser = reaction.User; + if (!optionalUser.IsSpecified) return; + if (!(optionalUser.Value is IGuildUser user)) return; + if (!(socketMessageChannel is SocketGuildChannel channel)) return; + + await using ChaosbotContext dbContext = new ChaosbotContext(); + + IQueryable roleReactionsQueryable = dbContext.RoleReactions; + List roleReactions = roleReactionsQueryable + .Where(r => r.DiscordMessageId == cacheableMessage.Id) + .ToList() + .Where(r => r.DiscordEmoteName == reaction.Emote.ToString()) + .ToList(); + + foreach (RoleReaction roleReaction in roleReactions) + { + try + { + SocketRole role = channel.Guild.Roles.FirstOrDefault(r => r.Id == roleReaction.DiscordRoleId); + await user.AddRoleAsync(role); + } + catch (Exception ex) + { + Logger.Error($"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); + } + } } public static async void HandleReactionRemoved(Cacheable cacheableMessage, ISocketMessageChannel socketMessageChannel, SocketReaction reaction) { - // This would take roles based on database lookup + Optional optionalUser = reaction.User; + if (!optionalUser.IsSpecified) return; + if (!(optionalUser.Value is IGuildUser user)) return; + if (!(socketMessageChannel is SocketGuildChannel channel)) return; + + await using ChaosbotContext dbContext = new ChaosbotContext(); + + IQueryable roleReactionsQueryable = dbContext.RoleReactions; + List roleReactions = roleReactionsQueryable + .Where(r => r.DiscordMessageId == cacheableMessage.Id) + .ToList() + .Where(r => r.DiscordEmoteName == reaction.Emote.ToString()) + .ToList(); + + foreach (RoleReaction roleReaction in roleReactions) + { + try + { + SocketRole role = channel.Guild.Roles.FirstOrDefault(r => r.Id == roleReaction.DiscordRoleId); + await user.RemoveRoleAsync(role); + } + catch (Exception ex) + { + Logger.Error($"{MethodBase.GetCurrentMethod().ReflectedType.FullName}: Exception [{ex}] thrown, <[{ex.Message}]>."); + } + } } } } \ No newline at end of file