From 3e0cb72513b849903cd975189bd445c03edea9e2 Mon Sep 17 00:00:00 2001 From: callbackcat <72662821+callbackcat@users.noreply.github.com> Date: Mon, 16 Aug 2021 00:31:53 +0300 Subject: [PATCH] poll-feat Added poll feature (raw) --- Kysect.BotFramework.ConsoleTest/Program.cs | 5 +- .../Discord/DiscordApiProvider.cs | 110 +++++++++++++++++- .../ApiProviders/IBotApiProvider.cs | 1 + .../Telegram/TelegramApiProvider.cs | 3 +- .../ApiProviders/VK/VkFixedApiProvider.cs | 2 + .../Core/BotMessages/BotPollMessage.cs | 23 ++++ .../Core/CommandInvoking/CommandHandler.cs | 3 +- .../Core/Commands/BotCommandDescriptor.cs | 9 +- .../DefaultCommands/PollCommand.cs | 25 ++++ .../Kysect.BotFramework.csproj | 1 + 10 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 Kysect.BotFramework/Core/BotMessages/BotPollMessage.cs create mode 100644 Kysect.BotFramework/DefaultCommands/PollCommand.cs diff --git a/Kysect.BotFramework.ConsoleTest/Program.cs b/Kysect.BotFramework.ConsoleTest/Program.cs index 85bc61e..30b0488 100644 --- a/Kysect.BotFramework.ConsoleTest/Program.cs +++ b/Kysect.BotFramework.ConsoleTest/Program.cs @@ -1,7 +1,9 @@ using System.Threading.Tasks; +using Kysect.BotFramework.ApiProviders.Discord; using Kysect.BotFramework.ApiProviders.Telegram; -using Kysect.BotFramework.Commands; +using Kysect.BotFramework.DefaultCommands; using Kysect.BotFramework.Core; +using Kysect.BotFramework.DefaultCommands; using Kysect.BotFramework.Settings; namespace Kysect.BotFramework.ConsoleTest @@ -19,6 +21,7 @@ private static async Task MainAsync() .SetPrefix('!') .SetCaseSensitive(false) .AddCommand(PingCommand.Descriptor) + .AddCommand(PollCommand.Descriptor) .Build(api); botManager.Start(); diff --git a/Kysect.BotFramework/ApiProviders/Discord/DiscordApiProvider.cs b/Kysect.BotFramework/ApiProviders/Discord/DiscordApiProvider.cs index 8690f9a..be7de42 100644 --- a/Kysect.BotFramework/ApiProviders/Discord/DiscordApiProvider.cs +++ b/Kysect.BotFramework/ApiProviders/Discord/DiscordApiProvider.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.Rest; using Discord.WebSocket; +using DSharpPlus; +using DSharpPlus.Entities; using FluentResults; using Kysect.BotFramework.Core; using Kysect.BotFramework.Core.BotMedia; @@ -13,6 +17,8 @@ using Kysect.BotFramework.Core.Tools.Loggers; using Kysect.BotFramework.DefaultCommands; using Kysect.BotFramework.Settings; +using TokenType = Discord.TokenType; +using System.Text.RegularExpressions; namespace Kysect.BotFramework.ApiProviders.Discord { @@ -21,6 +27,12 @@ public class DiscordApiProvider : IBotApiProvider, IDisposable private readonly object _lock = new object(); private readonly DiscordSettings _settings; private DiscordSocketClient _client; + private int _argsCount; + + private readonly string[] _emojis = + { + "", "1️⃣", "2️⃣", "3️⃣","4️⃣","5️⃣","6️⃣","7️⃣", "8️⃣", "9️⃣", "🔟" + }; public DiscordApiProvider(ISettingsProvider settingsProvider) { @@ -118,12 +130,26 @@ public Result SendTextMessage(string text, SenderInfo sender) if (text.Length == 0) { LoggerHolder.Instance.Error("The message wasn't sent by the command " + - $"\"{PingCommand.Descriptor.CommandName}\", the length must not be zero."); + "\"{CommandName}\", the length must not be zero", + PingCommand.Descriptor.CommandName); return Result.Ok(); } - + return SendText(text, sender); } + + public Result SendPollMessage(string text, SenderInfo sender) + { + if (text.Length == 0) + { + LoggerHolder.Instance.Error("The message wasn't sent by the command " + + "\"{CommandName}\", the length must not be zero", + PollCommand.Descriptor.CommandName); + return Result.Ok(); + } + + return SendPoll(text, sender); + } public void Dispose() { @@ -150,15 +176,22 @@ private Task ClientOnMessage(SocketMessage arg) } var context = new SocketCommandContext(_client, message); + if (!context.User.IsBot && context.Message.Content.Contains("!Poll")) + { + _argsCount = GetPollArguments(message.Content).Count() - 1; + } + if (context.User.IsBot && context.Message.Embeds.Any()) + { + ReactWithEmojis(context); + } + if (context.User.IsBot || context.Guild is null) { return Task.CompletedTask; } - LoggerHolder.Instance.Debug($"New message event: {context.Message}"); - + IBotMessage botMessage = ParseMessage(message, context); - OnMessage?.Invoke(context.Client, new BotEventArgs( botMessage, @@ -270,6 +303,45 @@ private Result SendText(string text, SenderInfo sender) return Result.Fail(new Error(message).CausedBy(e)); } } + + private Result SendPoll(string text, SenderInfo sender) + { + List arguments = GetPollArguments(text); + + Result result = CheckText(text); + if (result.IsFailed) + { + return result; + } + + for (int i = 1; i < arguments.Count; i++) + { + arguments[i] = _emojis[i] + "\t" + arguments[i]; + } + + var embed = new EmbedBuilder + { + Title = arguments[0], + Color = Color.Purple, + Description = String.Join("\n", arguments.Skip(1)) + }; + + Task task = _client.GetGuild((ulong) sender.GroupId) + .GetTextChannel((ulong) sender.UserSenderId) + .SendMessageAsync(embed: embed.Build()); + + try + { + task.Wait(); + return Result.Ok("Message send"); + } + catch (Exception e) + { + var message = "Error while sending message"; + LoggerHolder.Instance.Error(e, message); + return Result.Fail(new Error(message).CausedBy(e)); + } + } private Result CheckText(string text) { @@ -277,11 +349,37 @@ private Result CheckText(string text) { string subString = text.Substring(0, 99) + "..."; string errorMessage = "The message wasn't sent by the command " + - $"\"{PingCommand.Descriptor.CommandName}\", the length is too big."; + $"\"{PingCommand.Descriptor.CommandName}\", the length is too big"; return Result.Fail(new Error(errorMessage).CausedBy(subString)); } return Result.Ok(); } + + private List GetPollArguments(string args) + { + var regex = new Regex(@"[^\s""']+|""([^""]*)""|'([^']*)'"); // Splits into "..." '...' a b c + var matches = regex.Matches(args); + List options = new List(); + + if (matches.Count > 0) + { + foreach (Match match in matches) + { + options.Add(match.Value.Replace("\"", "")); + } + } + + return options; + } + + private async void ReactWithEmojis(SocketCommandContext context) + { + for (int i = 1; i < _argsCount; i++) + { + await context.Message.AddReactionAsync(new Emoji(_emojis[i])) + .ConfigureAwait(false); + } + } } } \ No newline at end of file diff --git a/Kysect.BotFramework/ApiProviders/IBotApiProvider.cs b/Kysect.BotFramework/ApiProviders/IBotApiProvider.cs index 894034d..e14b213 100644 --- a/Kysect.BotFramework/ApiProviders/IBotApiProvider.cs +++ b/Kysect.BotFramework/ApiProviders/IBotApiProvider.cs @@ -15,5 +15,6 @@ public interface IBotApiProvider Result SendMedia(IBotMediaFile mediaFile, string text, SenderInfo sender); Result SendOnlineMedia(IBotOnlineFile file, string text, SenderInfo sender); Result SendTextMessage(string text, SenderInfo sender); + Result SendPollMessage(string text, SenderInfo sender); } } \ No newline at end of file diff --git a/Kysect.BotFramework/ApiProviders/Telegram/TelegramApiProvider.cs b/Kysect.BotFramework/ApiProviders/Telegram/TelegramApiProvider.cs index 7e23316..dfa08ab 100644 --- a/Kysect.BotFramework/ApiProviders/Telegram/TelegramApiProvider.cs +++ b/Kysect.BotFramework/ApiProviders/Telegram/TelegramApiProvider.cs @@ -29,7 +29,6 @@ public TelegramApiProvider(ISettingsProvider settingsProvider) _settings = settingsProvider.GetSettings(); Initialize(); } - public event EventHandler OnMessage; public void Restart() @@ -308,6 +307,8 @@ private Result SendText(string text, SenderInfo sender) return Result.Fail(new Error(message).CausedBy(e)); } } + + public Result SendPollMessage(string text, SenderInfo sender) => throw new NotImplementedException(); private Result CheckText(string text) { diff --git a/Kysect.BotFramework/ApiProviders/VK/VkFixedApiProvider.cs b/Kysect.BotFramework/ApiProviders/VK/VkFixedApiProvider.cs index 68b7011..717fae6 100644 --- a/Kysect.BotFramework/ApiProviders/VK/VkFixedApiProvider.cs +++ b/Kysect.BotFramework/ApiProviders/VK/VkFixedApiProvider.cs @@ -31,6 +31,8 @@ public void Restart() public Result SendTextMessage(string text, SenderInfo sender) => throw new NotImplementedException(); + public Result SendPollMessage(string text, SenderInfo sender) => throw new NotImplementedException(); + public void Dispose() { throw new NotImplementedException(); diff --git a/Kysect.BotFramework/Core/BotMessages/BotPollMessage.cs b/Kysect.BotFramework/Core/BotMessages/BotPollMessage.cs new file mode 100644 index 0000000..342b0bb --- /dev/null +++ b/Kysect.BotFramework/Core/BotMessages/BotPollMessage.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Kysect.BotFramework.ApiProviders; +using Telegram.Bot.Requests; + +namespace Kysect.BotFramework.Core.BotMessages +{ + public class BotPollMessage : IBotMessage + { + public BotPollMessage(string text) + { + Text = text; + } + + public string Text { get; } + + public void Send(IBotApiProvider apiProvider, SenderInfo sender) + { + apiProvider.SendPollMessage(Text, sender); + } + } +} \ No newline at end of file diff --git a/Kysect.BotFramework/Core/CommandInvoking/CommandHandler.cs b/Kysect.BotFramework/Core/CommandInvoking/CommandHandler.cs index 837fd58..d02b37a 100644 --- a/Kysect.BotFramework/Core/CommandInvoking/CommandHandler.cs +++ b/Kysect.BotFramework/Core/CommandInvoking/CommandHandler.cs @@ -2,6 +2,7 @@ using FluentResults; using Kysect.BotFramework.Core.BotMessages; using Kysect.BotFramework.Core.Commands; +using Kysect.BotFramework.DefaultCommands; using Microsoft.Extensions.DependencyInjection; namespace Kysect.BotFramework.Core.CommandInvoking @@ -24,7 +25,7 @@ public Result CheckArgsCount(CommandContainer args) return commandTask.ToResult(); } - return commandTask.Value.Args.Length == args.Arguments.Count + return (commandTask.Value.Args.Count == args.Arguments.Count) || (args.CommandName == "Poll") // Better way to check for Poll? ? Result.Ok() : Result.Fail( "Cannot execute command. Argument count miss matched with command signature"); diff --git a/Kysect.BotFramework/Core/Commands/BotCommandDescriptor.cs b/Kysect.BotFramework/Core/Commands/BotCommandDescriptor.cs index e65f3ae..2625d67 100644 --- a/Kysect.BotFramework/Core/Commands/BotCommandDescriptor.cs +++ b/Kysect.BotFramework/Core/Commands/BotCommandDescriptor.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Kysect.BotFramework.Core.CommandInvoking; using Microsoft.Extensions.DependencyInjection; @@ -8,9 +9,9 @@ public abstract class BotCommandDescriptor { public string CommandName { get; } public string Description { get; } - public string[] Args { get; } + public List Args { get; } - public BotCommandDescriptor(string commandName, string description, string[] args) + public BotCommandDescriptor(string commandName, string description, List args) { CommandName = commandName; Description = description; @@ -22,13 +23,13 @@ public BotCommandDescriptor(string commandName, string description, string[] arg public class BotCommandDescriptor : BotCommandDescriptor where T : IBotCommand { - public BotCommandDescriptor(string commandName, string description, string[] args) + public BotCommandDescriptor(string commandName, string description, List args) : base(commandName, description, args) { } public BotCommandDescriptor(string commandName, string description) - : this(commandName, description, Array.Empty()) + : this(commandName, description, new List()) { } diff --git a/Kysect.BotFramework/DefaultCommands/PollCommand.cs b/Kysect.BotFramework/DefaultCommands/PollCommand.cs new file mode 100644 index 0000000..e24e6e2 --- /dev/null +++ b/Kysect.BotFramework/DefaultCommands/PollCommand.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using FluentResults; +using Kysect.BotFramework.Core.BotMessages; +using Kysect.BotFramework.Core.Commands; + +namespace Kysect.BotFramework.DefaultCommands +{ + public class PollCommand : IBotAsyncCommand + { + public static readonly BotCommandDescriptor Descriptor = new BotCommandDescriptor( + "Poll", + "Create a new poll", new List()); + + public Result CanExecute(CommandContainer args) => Result.Ok(); + + public Task> Execute(CommandContainer args) + { + IBotMessage message = new BotPollMessage(String.Join(" ", args.Arguments)); + return Task.FromResult(Result.Ok(message)); + } + } +} \ No newline at end of file diff --git a/Kysect.BotFramework/Kysect.BotFramework.csproj b/Kysect.BotFramework/Kysect.BotFramework.csproj index 5e64fe2..0a34278 100644 --- a/Kysect.BotFramework/Kysect.BotFramework.csproj +++ b/Kysect.BotFramework/Kysect.BotFramework.csproj @@ -24,6 +24,7 @@ +