diff --git a/ArmaforcesMissionBot/Attributes/RequireRankAttribute.cs b/ArmaforcesMissionBot/Attributes/RequireRankAttribute.cs index db9d83b..e3b8c33 100644 --- a/ArmaforcesMissionBot/Attributes/RequireRankAttribute.cs +++ b/ArmaforcesMissionBot/Attributes/RequireRankAttribute.cs @@ -10,7 +10,8 @@ namespace ArmaforcesMissionBot.Attributes { public enum RanksEnum { - Recruiter + Recruiter, + RoleMaker } internal static class RanksEnumMethods @@ -19,6 +20,7 @@ public static ulong GetID(this RanksEnum role, Config config) => role switch { RanksEnum.Recruiter => config.RecruiterRole, + RanksEnum.RoleMaker => config.RoleMaker, _ => 0 }; } diff --git a/ArmaforcesMissionBot/DataClasses/Config.cs b/ArmaforcesMissionBot/DataClasses/Config.cs index 1f0ac7a..79454a7 100644 --- a/ArmaforcesMissionBot/DataClasses/Config.cs +++ b/ArmaforcesMissionBot/DataClasses/Config.cs @@ -29,6 +29,8 @@ public class Config public ulong HallOfShameChannel { get; set; } public ulong RecruitInfoChannel { get; set; } public ulong RecruitAskChannel { get; set; } + public ulong RoleMaker { get; set; } + public ulong RoleAssignChannel { get; set; } public void Load() { diff --git a/ArmaforcesMissionBot/Handlers/ReactionHandler.cs b/ArmaforcesMissionBot/Handlers/ReactionHandler.cs new file mode 100644 index 0000000..9585eaf --- /dev/null +++ b/ArmaforcesMissionBot/Handlers/ReactionHandler.cs @@ -0,0 +1,333 @@ +using ArmaforcesMissionBot.DataClasses; +using Discord; +using Discord.WebSocket; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Timers; +using ArmaforcesMissionBot.Helpers; + + +namespace ArmaforcesMissionBot.Handlers +{ + public static class StringExtensionMethods + { + public static string ReplaceFirst(this string text, string search, string replace) + { + int pos = text.IndexOf(search); + if (pos < 0) + { + return text; + } + return text.Substring(0, pos) + replace + text.Substring(pos + search.Length); + } + } + public class ReactionHandler : IInstallable + { + private DiscordSocketClient _client; + private MiscHelper _miscHelper; + private IServiceProvider _services; + private Config _config; + private Timer _timer; + + public async Task Install(IServiceProvider map) + { + _client = map.GetService(); + _config = map.GetService(); + _miscHelper = map.GetService(); + _services = map; + // Hook the MessageReceived event into our command handler + _client.ReactionAdded += HandleReactionAdded; + _client.ReactionRemoved += HandleReactionRemoved; + + _timer = new Timer(); + _timer.Interval = 2000; + + _timer.Elapsed += CheckReactionTimes; + _timer.AutoReset = true; + _timer.Enabled = true; + } + + private async Task HandleReactionAdded(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction) + { + var signups = _services.GetService(); + + if (reaction.User.IsSpecified && !reaction.User.Value.IsBot && _config.RoleAssignChannel == channel.Id) + { + await AddedReactionInRolesChannel(message, channel, reaction); + } + else if (reaction.User.IsSpecified && !reaction.User.Value.IsBot && signups.Missions.Any(x => x.SignupChannel == channel.Id)) + { + await AddedReactionInSignupsChannel(message, channel, reaction, signups); + } + else if (signups.Missions.Any(x => x.SignupChannel == channel.Id) && reaction.UserId != _client.CurrentUser.Id) + { + var user = _client.GetUser(reaction.UserId); + Console.WriteLine($"Naprawiam reakcje po spamie {user.Username}"); + var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; + await teamMsg.RemoveReactionAsync(reaction.Emote, user); + } + } + + private async Task HandleReactionRemoved(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction) + { + var signups = _services.GetService(); + + if (reaction.User.IsSpecified && !reaction.User.Value.IsBot && _config.RoleAssignChannel == channel.Id) + { + await RemovedReactionInRolesChannel(message, channel, reaction); + } + else if (signups.Missions.Any(x => x.SignupChannel == channel.Id)) + { + await RemovedReactionInSignupsChannel(message, channel, reaction, signups); + } + } + + private async Task HandleReactionChange(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction, SignupsData signups) + { + await signups.BanAccess.WaitAsync(-1); + try + { + if (!signups.ReactionTimes.ContainsKey(reaction.User.Value.Id)) + { + signups.ReactionTimes[reaction.User.Value.Id] = new Queue(); + } + + signups.ReactionTimes[reaction.User.Value.Id].Enqueue(DateTime.Now); + + Console.WriteLine($"[{DateTime.Now.ToString()}] {reaction.User.Value.Username} spam counter: {signups.ReactionTimes[reaction.User.Value.Id].Count}"); + + if (signups.ReactionTimes[reaction.User.Value.Id].Count >= 10 && !signups.SpamBans.ContainsKey(reaction.User.Value.Id)) + { + await Helpers.BanHelper.BanUserSpam(_services, reaction.User.Value); + } + } + finally + { + signups.BanAccess.Release(); + } + } + + private async void CheckReactionTimes(object source, ElapsedEventArgs e) + { + var signups = _services.GetService(); + + await signups.BanAccess.WaitAsync(-1); + try + { + foreach (var user in signups.ReactionTimes) + { + while (user.Value.Count > 0 && user.Value.Peek() < e.SignalTime.AddSeconds(-30)) + user.Value.Dequeue(); + } + } + finally + { + signups.BanAccess.Release(); + } + } + + private async Task AddedReactionInSignupsChannel(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction, SignupsData signups) + { + var reactionStringAnimatedVersion = reaction.Emote.ToString().Insert(1, "a"); + + var mission = signups.Missions.Single(x => x.SignupChannel == channel.Id); + + await HandleReactionChange(message, channel, reaction, signups); + Console.WriteLine($"[{DateTime.Now.ToString()}] {reaction.User.Value.Username} added reaction {reaction.Emote.Name}"); + + if (signups.SignupBans.ContainsKey(reaction.User.Value.Id) && signups.SignupBans[reaction.User.Value.Id] > mission.Date) + { + await reaction.User.Value.SendMessageAsync("Masz bana na zapisy, nie możesz zapisać się na misję, która odbędzie się w czasie trwania bana."); + var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; + await teamMsg.RemoveReactionAsync(reaction.Emote, reaction.User.Value); + return; + } + + await mission.Access.WaitAsync(-1); + try + { + if (mission.Teams.Any(x => x.TeamMsg == message.Id)) + { + var team = mission.Teams.Single(x => x.TeamMsg == message.Id); + if (team.Slots.Any(x => (x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion) && (x.Count > x.Signed.Count() || team.Reserve != 0))) + { + var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; + + var embed = teamMsg.Embeds.Single(); + + if (!mission.SignedUsers.Any(x => x == reaction.User.Value.Id)) + { + var slot = team.Slots.Single(x => x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion); + if (!slot.Signed.Contains(reaction.User.Value.Id)) + slot.Signed.Add(reaction.User.Value.Id); + if (!mission.SignedUsers.Contains(reaction.User.Value.Id)) + mission.SignedUsers.Add(reaction.User.Value.Id); + + var newDescription = _miscHelper.BuildTeamSlots(team); + + var newEmbed = new EmbedBuilder + { + Title = team.Name, + Color = embed.Color + }; + + if (newDescription.Count == 2) + newEmbed.WithDescription(newDescription[0] + newDescription[1]); + else if (newDescription.Count == 1) + newEmbed.WithDescription(newDescription[0]); + + if (embed.Footer.HasValue) + newEmbed.WithFooter(embed.Footer.Value.Text); + else + newEmbed.WithFooter(team.Pattern); + + await teamMsg.ModifyAsync(x => x.Embed = newEmbed.Build()); + } + else + { + await teamMsg.RemoveReactionAsync(reaction.Emote, reaction.User.Value); + } + } + else if (team.Slots.Any(x => x.Emoji == reaction.Emote.ToString())) + { + var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; + await teamMsg.RemoveReactionAsync(reaction.Emote, reaction.User.Value); + } + } + } + finally + { + mission.Access.Release(); + } + } + + private async Task AddedReactionInRolesChannel(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction) + { + var fullMessage = await channel.GetMessageAsync(message.Id) as IUserMessage; + + var messageDescription = fullMessage.Embeds.Single().Description; + ulong rank; + var reactionsMatches = MiscHelper.GetRankArrayMatchesFromText(messageDescription); + var rankForEmoji = reactionsMatches.Find(x => x.Item1 == reaction.Emote.ToString()); + + try + { + string regexPattern = @"\<\@\&([0-9]+)\>"; + var rankMatches = Regex.Matches(rankForEmoji.Item2, regexPattern, RegexOptions.IgnoreCase | RegexOptions.RightToLeft).First().ToString(); + rank = ulong.Parse(Regex.Matches(rankMatches, "[0-9]+", RegexOptions.IgnoreCase | RegexOptions.RightToLeft).First().Value); + } + catch (Exception e) + { + Console.WriteLine($"Parsing ranks failed."); + return; + } + + try + { + var role = (channel as SocketGuildChannel).Guild.GetRole(rank); + + await (reaction.User.Value as SocketGuildUser).AddRoleAsync(role); + + } + catch (Exception ex) + { + Console.WriteLine($"Adding rank failed."); + } + + return; + } + + private async Task RemovedReactionInSignupsChannel(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction, SignupsData signups) + { + var reactionStringAnimatedVersion = reaction.Emote.ToString().Insert(1, "a"); + + var mission = signups.Missions.Single(x => x.SignupChannel == channel.Id); + var user = await (channel as IGuildChannel).Guild.GetUserAsync(reaction.UserId); + + Console.WriteLine($"[{DateTime.Now.ToString()}] {user.Username} removed reaction {reaction.Emote.Name}"); + + await mission.Access.WaitAsync(-1); + try + { + if (mission.Teams.Any(x => x.TeamMsg == message.Id)) + { + var team = mission.Teams.Single(x => x.TeamMsg == message.Id); + if (team.Slots.Any(x => (x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion) && x.Signed.Contains(user.Id))) + { + var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; + var embed = teamMsg.Embeds.Single(); + + var slot = team.Slots.Single(x => x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion); + slot.Signed.Remove(user.Id); + mission.SignedUsers.Remove(user.Id); + + var newDescription = _miscHelper.BuildTeamSlots(team); + + var newEmbed = new EmbedBuilder + { + Title = team.Name, + Color = embed.Color + }; + + if (newDescription.Count == 2) + newEmbed.WithDescription(newDescription[0] + newDescription[1]); + else if (newDescription.Count == 1) + newEmbed.WithDescription(newDescription[0]); + + if (embed.Footer.HasValue) + newEmbed.WithFooter(embed.Footer.Value.Text); + else + newEmbed.WithFooter(team.Pattern); + + await teamMsg.ModifyAsync(x => x.Embed = newEmbed.Build()); + } + } + } + finally + { + mission.Access.Release(); + } + } + + private async Task RemovedReactionInRolesChannel(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction) + { + var fullMessage = await channel.GetMessageAsync(message.Id) as IUserMessage; + + var messageDescription = fullMessage.Embeds.Single().Description; + ulong rank; + var reactionsMatches = MiscHelper.GetRankArrayMatchesFromText(messageDescription); + var rankForEmoji = reactionsMatches.Find(x => x.Item1 == reaction.Emote.ToString()); + + try + { + string regexPattern = @"\<\@\&([0-9]+)\>"; + var rankMatches = Regex.Matches(rankForEmoji.Item2, regexPattern, RegexOptions.IgnoreCase | RegexOptions.RightToLeft).First().ToString(); + rank = ulong.Parse(Regex.Matches(rankMatches, "[0-9]+", RegexOptions.IgnoreCase | RegexOptions.RightToLeft).First().Value); + } + catch (Exception e) + { + Console.WriteLine($"Parsing ranks failed."); + return; + } + + try + { + var role = (channel as SocketGuildChannel).Guild.GetRole(rank); + + await (reaction.User.Value as SocketGuildUser).RemoveRoleAsync(role); + + } + catch (Exception ex) + { + Console.WriteLine($"Adding rank failed."); + } + + return; + } + + } +} diff --git a/ArmaforcesMissionBot/Handlers/SignupHandler.cs b/ArmaforcesMissionBot/Handlers/SignupHandler.cs index e5d7859..a17293d 100644 --- a/ArmaforcesMissionBot/Handlers/SignupHandler.cs +++ b/ArmaforcesMissionBot/Handlers/SignupHandler.cs @@ -13,25 +13,12 @@ namespace ArmaforcesMissionBot.Handlers { - public static class StringExtensionMethods - { - public static string ReplaceFirst(this string text, string search, string replace) - { - int pos = text.IndexOf(search); - if (pos < 0) - { - return text; - } - return text.Substring(0, pos) + replace + text.Substring(pos + search.Length); - } - } public class SignupHandler : IInstallable { private DiscordSocketClient _client; private MiscHelper _miscHelper; private IServiceProvider _services; private Config _config; - private Timer _timer; public async Task Install(IServiceProvider map) { @@ -40,160 +27,8 @@ public async Task Install(IServiceProvider map) _miscHelper = map.GetService(); _services = map; // Hook the MessageReceived event into our command handler - _client.ReactionAdded += HandleReactionAdded; - _client.ReactionRemoved += HandleReactionRemoved; _client.ChannelDestroyed += HandleChannelRemoved; - _timer = new Timer(); - _timer.Interval = 2000; - - _timer.Elapsed += CheckReactionTimes; - _timer.AutoReset = true; - _timer.Enabled = true; - } - - private async Task HandleReactionAdded(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction) - { - var signups = _services.GetService(); - - var reactionStringAnimatedVersion = reaction.Emote.ToString().Insert(1, "a"); - - if (reaction.User.IsSpecified && !reaction.User.Value.IsBot && signups.Missions.Any(x => x.SignupChannel == channel.Id)) - { - var mission = signups.Missions.Single(x => x.SignupChannel == channel.Id); - - await HandleReactionChange(message, channel, reaction, signups); - Console.WriteLine($"[{DateTime.Now.ToString()}] {reaction.User.Value.Username} added reaction {reaction.Emote.Name}"); - - if (signups.SignupBans.ContainsKey(reaction.User.Value.Id) && signups.SignupBans[reaction.User.Value.Id] > mission.Date) - { - await reaction.User.Value.SendMessageAsync("Masz bana na zapisy, nie moĹĽesz zapisać siÄ™ na misjÄ™, ktĂłra odbÄ™dzie siÄ™ w czasie trwania bana."); - var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; - await teamMsg.RemoveReactionAsync(reaction.Emote, reaction.User.Value); - return; - } - - await mission.Access.WaitAsync(-1); - try - { - if (mission.Teams.Any(x => x.TeamMsg == message.Id)) - { - var team = mission.Teams.Single(x => x.TeamMsg == message.Id); - if (team.Slots.Any(x => (x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion) && (x.Count > x.Signed.Count() || team.Reserve != 0))) - { - var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; - - var embed = teamMsg.Embeds.Single(); - - if (!mission.SignedUsers.Any(x => x == reaction.User.Value.Id)) - { - var slot = team.Slots.Single(x => x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion); - if(!slot.Signed.Contains(reaction.User.Value.Id)) - slot.Signed.Add(reaction.User.Value.Id); - if (!mission.SignedUsers.Contains(reaction.User.Value.Id)) - mission.SignedUsers.Add(reaction.User.Value.Id); - - var newDescription = _miscHelper.BuildTeamSlots(team); - - var newEmbed = new EmbedBuilder - { - Title = team.Name, - Color = embed.Color - }; - - if (newDescription.Count == 2) - newEmbed.WithDescription(newDescription[0] + newDescription[1]); - else if (newDescription.Count == 1) - newEmbed.WithDescription(newDescription[0]); - - if (embed.Footer.HasValue) - newEmbed.WithFooter(embed.Footer.Value.Text); - else - newEmbed.WithFooter(team.Pattern); - - await teamMsg.ModifyAsync(x => x.Embed = newEmbed.Build()); - } - else - { - await teamMsg.RemoveReactionAsync(reaction.Emote, reaction.User.Value); - } - } - else if (team.Slots.Any(x => x.Emoji == reaction.Emote.ToString())) - { - var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; - await teamMsg.RemoveReactionAsync(reaction.Emote, reaction.User.Value); - } - } - } - finally - { - mission.Access.Release(); - } - } - else if(signups.Missions.Any(x => x.SignupChannel == channel.Id) && reaction.UserId != _client.CurrentUser.Id) - { - var user = _client.GetUser(reaction.UserId); - Console.WriteLine($"Naprawiam reakcje po spamie {user.Username}"); - var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; - await teamMsg.RemoveReactionAsync(reaction.Emote, user); - } - } - - private async Task HandleReactionRemoved(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction) - { - var signups = _services.GetService(); - - var reactionStringAnimatedVersion = reaction.Emote.ToString().Insert(1, "a"); - - if (signups.Missions.Any(x => x.SignupChannel == channel.Id)) - { - var mission = signups.Missions.Single(x => x.SignupChannel == channel.Id); - var user = await (channel as IGuildChannel).Guild.GetUserAsync(reaction.UserId); - - Console.WriteLine($"[{DateTime.Now.ToString()}] {user.Username} removed reaction {reaction.Emote.Name}"); - - await mission.Access.WaitAsync(-1); - try - { - if (mission.Teams.Any(x => x.TeamMsg == message.Id)) - { - var team = mission.Teams.Single(x => x.TeamMsg == message.Id); - if (team.Slots.Any(x => (x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion) && x.Signed.Contains(user.Id))) - { - var teamMsg = await channel.GetMessageAsync(message.Id) as IUserMessage; - var embed = teamMsg.Embeds.Single(); - - var slot = team.Slots.Single(x => x.Emoji == reaction.Emote.ToString() || x.Emoji == reactionStringAnimatedVersion); - slot.Signed.Remove(user.Id); - mission.SignedUsers.Remove(user.Id); - - var newDescription = _miscHelper.BuildTeamSlots(team); - - var newEmbed = new EmbedBuilder - { - Title = team.Name, - Color = embed.Color - }; - - if (newDescription.Count == 2) - newEmbed.WithDescription(newDescription[0] + newDescription[1]); - else if (newDescription.Count == 1) - newEmbed.WithDescription(newDescription[0]); - - if (embed.Footer.HasValue) - newEmbed.WithFooter(embed.Footer.Value.Text); - else - newEmbed.WithFooter(team.Pattern); - - await teamMsg.ModifyAsync(x => x.Embed = newEmbed.Build()); - } - } - } - finally - { - mission.Access.Release(); - } - } } private async Task HandleChannelRemoved(SocketChannel channel) @@ -206,48 +41,5 @@ private async Task HandleChannelRemoved(SocketChannel channel) } } - private async Task HandleReactionChange(Cacheable message, ISocketMessageChannel channel, SocketReaction reaction, SignupsData signups) - { - await signups.BanAccess.WaitAsync(-1); - try - { - if (!signups.ReactionTimes.ContainsKey(reaction.User.Value.Id)) - { - signups.ReactionTimes[reaction.User.Value.Id] = new Queue(); - } - - signups.ReactionTimes[reaction.User.Value.Id].Enqueue(DateTime.Now); - - Console.WriteLine($"[{ DateTime.Now.ToString()}] { reaction.User.Value.Username} spam counter: { signups.ReactionTimes[reaction.User.Value.Id].Count}"); - - if (signups.ReactionTimes[reaction.User.Value.Id].Count >= 10 && !signups.SpamBans.ContainsKey(reaction.User.Value.Id)) - { - await Helpers.BanHelper.BanUserSpam(_services, reaction.User.Value); - } - } - finally - { - signups.BanAccess.Release(); - } - } - - private async void CheckReactionTimes(object source, ElapsedEventArgs e) - { - var signups = _services.GetService(); - - await signups.BanAccess.WaitAsync(-1); - try - { - foreach(var user in signups.ReactionTimes) - { - while (user.Value.Count > 0 && user.Value.Peek() < e.SignalTime.AddSeconds(-30)) - user.Value.Dequeue(); - } - } - finally - { - signups.BanAccess.Release(); - } - } } } diff --git a/ArmaforcesMissionBot/Helpers/MiscHelper.cs b/ArmaforcesMissionBot/Helpers/MiscHelper.cs index bbb2dfd..707e565 100644 --- a/ArmaforcesMissionBot/Helpers/MiscHelper.cs +++ b/ArmaforcesMissionBot/Helpers/MiscHelper.cs @@ -162,5 +162,56 @@ public static MatchCollection GetSlotMatchesFromText(string text) return Regex.Matches(text, rolePattern, RegexOptions.IgnoreCase | RegexOptions.RightToLeft); } + + public static List> GetRankArrayMatchesFromText(string text) + { + string unicodeEmoji = @"(?:\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])(?:\ufe0f)?"; + string emote = $@"((?:)?)|{unicodeEmoji})"; + string rank = @"\<\@\&([0-9]+)\>"; + string rolePattern = $@"[ ]*{emote}[ ]*-[ ]*{rank}"; + + var rankMatches = Regex.Matches(text, rolePattern, RegexOptions.IgnoreCase); + + var rankList = new List> { }; + + foreach (Match rankLine in rankMatches) + { + var spilttedTexts = rankLine.Value.Split(" - "); + rankList.Add(Tuple.Create(spilttedTexts[0], spilttedTexts[1])); + } + + return rankList; + } + + public static IEmote[] GetEmojiMatchesFromText(string text) + { + string unicodeEmoji = @"(?:\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])(?:\ufe0f)?"; + string emote = $@"((?:)?)|{unicodeEmoji})"; + + var emojiMatches = Regex.Matches(text, emote, RegexOptions.IgnoreCase); + + IEmote[] emoji = new IEmote[emojiMatches.Count]; + + foreach (var (emojiMatch, i) in emojiMatches.Select((value, i) => (value, i))) + { + try + { + emoji[i] = Emote.Parse(HttpUtility.HtmlDecode(emojiMatch.Value)); + } + catch (Exception e) + { + emoji[i] = new Emoji(HttpUtility.HtmlDecode(emojiMatch.Value)); + } + } + + return emoji; + } + + public static MatchCollection GetRankMatchesFromText(string text) + { + string rank = @"\<\@\&([0-9]+)\>"; + + return Regex.Matches(text, rank, RegexOptions.IgnoreCase); + } } } diff --git a/ArmaforcesMissionBot/Modules/Ranks.cs b/ArmaforcesMissionBot/Modules/Ranks.cs index d1d3fbb..48a48a3 100644 --- a/ArmaforcesMissionBot/Modules/Ranks.cs +++ b/ArmaforcesMissionBot/Modules/Ranks.cs @@ -1,5 +1,6 @@ using ArmaforcesMissionBot.Attributes; using ArmaforcesMissionBot.DataClasses; +using ArmaforcesMissionBot.Helpers; using Discord; using Discord.Commands; using Discord.WebSocket; @@ -8,6 +9,8 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; +using static ArmaforcesMissionBot.DataClasses.OpenedDialogs; +using System.Web; namespace ArmaforcesMissionBot.Modules { @@ -17,6 +20,8 @@ public class Ranks : ModuleBase public IServiceProvider _map { get; set; } public DiscordSocketClient _client { get; set; } public Config _config { get; set; } + public MiscHelper _miscHelper { get; set; } + public OpenedDialogs _dialogs { get; set; } [Command("rekrutuj")] [Summary("Przydziela rangÄ™ rekrut.")] @@ -79,5 +84,76 @@ await ReplyAsync( await Context.Message.DeleteAsync(); } + + [Command("ranga")] + [Summary("Dodaj wiadomość do automatycznego dodwania rangi. " + + "Argumenty: tytuĹ‚; opis; rangi do nadania; reakcje.")] + [RequireRank(RanksEnum.RoleMaker)] + public async Task RankAssign([Remainder] string rankText) + { + var spilttedTexts = rankText.Split(";"); + if (spilttedTexts.Length != 4) + { + await ReplyAsync("Ĺąle!"); + return; + } + var rankTitle = spilttedTexts[0]; + var rankDescription = spilttedTexts[1]; + var rankType = spilttedTexts[2]; + var reaction = spilttedTexts[3]; + + var rankMatches = MiscHelper.GetRankMatchesFromText(rankType); + var reactionsMatches = MiscHelper.GetEmojiMatchesFromText(reaction); + + if (reactionsMatches.Distinct().Count() != reactionsMatches.Length) + { + await ReplyAsync("Reakcje nie sÄ… unikalne!"); + return; + } + + if (rankMatches.Count != reactionsMatches.Length) + { + if (rankMatches.Count > reactionsMatches.Length) + { + await ReplyAsync("Za maĹ‚o reakcji do rang!"); + return; + } + + reactionsMatches = reactionsMatches[0..rankMatches.Count]; + } + + var embedBuilder = new EmbedBuilder(); + + string embedText = rankDescription + "\r\nReakcje:\r\n"; + + foreach (var (reactionMatch, i) in rankMatches.Select((value, i) => (value, i))) + { + embedText = embedText + reactionsMatches[i] + " - "; + embedText = embedText + reactionMatch.Value + "\r\n"; + } + + embedBuilder.WithTitle(rankTitle).WithDescription(embedText); + + _miscHelper.CreateConfirmationDialog( + _dialogs, + Context, + embedBuilder.Build(), + async dialog => + { + _dialogs.Dialogs.Remove(dialog); + ReplyAsync("Pasi!"); + + var channel = Context.Guild.GetTextChannel(_config.RoleAssignChannel); + var message = await channel.SendMessageAsync(embed: embedBuilder.Build()); + await message.AddReactionsAsync(reactionsMatches); + }, + dialog => + { + Context.Channel.DeleteMessageAsync(dialog.DialogID); + _dialogs.Dialogs.Remove(dialog); + ReplyAsync("Nie to nie!"); + return; + }); + } } }