From 06a4cf9f30890f7126589545ed1a66bdab245b24 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sat, 6 Feb 2016 14:43:20 +0100 Subject: [PATCH] Poll command --- NadekoBot/Commands/PollCommand.cs | 119 ++++++++++++++++++++++++++++++ NadekoBot/Modules/Games.cs | 1 + NadekoBot/NadekoBot.csproj | 1 + 3 files changed, 121 insertions(+) create mode 100644 NadekoBot/Commands/PollCommand.cs diff --git a/NadekoBot/Commands/PollCommand.cs b/NadekoBot/Commands/PollCommand.cs new file mode 100644 index 00000000..055ef72c --- /dev/null +++ b/NadekoBot/Commands/PollCommand.cs @@ -0,0 +1,119 @@ +ο»Ώusing System; +using System.Threading.Tasks; +using Discord.Commands; +using System.Linq; +using System.Collections.Generic; +using System.Collections.Concurrent; +using Discord; +using System.Threading; + +namespace NadekoBot.Modules { + internal class PollCommand : DiscordCommand { + + public static ConcurrentDictionary ActivePolls = new ConcurrentDictionary(); + + public override Func DoFunc() { + throw new NotImplementedException(); + } + + public override void Init(CommandGroupBuilder cgb) { + cgb.CreateCommand(">poll") + .Description("Creates a poll, only person who has manage server permission can do it.\n**Usage**: >poll What is my question?;Answer1;Answer 2; Answer 3") + .Parameter("allargs", ParameterType.Unparsed) + .Do(e => { + if (ActivePolls.ContainsKey(e.Server)) + return; + var arg = e.GetArg("allargs"); + if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";")) + return; + var data = arg.Split(';'); + if (data.Length < 3) + return; + + new Poll(e, data[0], data.Skip(1)); + }); + cgb.CreateCommand(">pollend") + .Description("Stops active poll on this server and prints the results in this channel.") + .Do(async e => { + if (!ActivePolls.ContainsKey(e.Server)) + return; + await ActivePolls[e.Server].StopPoll(e.Channel); + }); + } + } + + internal class Poll { + private CommandEventArgs e; + private string[] answers; + private ConcurrentDictionary participants = new ConcurrentDictionary(); + private string question; + private DateTime started; + private CancellationTokenSource pollCancellationSource = new CancellationTokenSource(); + + public Poll(CommandEventArgs e, string v, IEnumerable enumerable) { + this.e = e; + this.question = v; + this.answers = enumerable.ToArray(); + + if (PollCommand.ActivePolls.TryAdd(e.Server, this)) { + Task.Factory.StartNew(async () => await StartPoll()); + } + } + + private async Task StartPoll() { + started = DateTime.Now; + NadekoBot.client.MessageReceived += Vote; + var msgToSend = + $"πŸ“ƒ**{e.User.Name}** from **{e.Server.Name}** server has created a poll which requires your attention:\n\n" + + $"**{question}**\n"; + int num = 1; + foreach (var answ in answers) { + msgToSend += $"`{num++}.` **{answ}**\n"; + } + msgToSend += "\n**Private Message me with the corresponding number of the answer.\n @everyone**"; + await e.Channel.SendMessage(msgToSend); + } + + public async Task StopPoll(Channel ch) { + NadekoBot.client.MessageReceived -= Vote; + Poll throwaway; + PollCommand.ActivePolls.TryRemove(e.Server, out throwaway); + try { + var results = participants.GroupBy(kvp => kvp.Value) + .ToDictionary(x => x.Key, x => x.Sum(kvp => 1)) + .OrderBy(kvp => kvp.Value); + + int totalVotesCast = results.Sum(kvp => kvp.Value); + if (totalVotesCast == 0) { + await ch.SendMessage("πŸ“„ **No votes have been cast.**"); + return; + } + var closeMessage = $"--------------**POLL CLOSED**--------------\n" + + $"πŸ“„ , here are the results:\n"; + foreach (var kvp in results) { + closeMessage += $"`{kvp.Key}.` **[{answers[kvp.Key - 1]}]** has {kvp.Value} votes.({kvp.Value * 1.0f / totalVotesCast * 100}%)\n"; + } + + await ch.SendMessage($"πŸ“„ **Total votes cast**: {totalVotesCast}\n{closeMessage}"); + } catch (Exception ex) { + Console.WriteLine($"Error in poll game {ex}"); + } + } + + private async void Vote(object sender, MessageEventArgs e) { + if (!e.Channel.IsPrivate) + return; + if (participants.ContainsKey(e.User)) + return; + + int vote; + if (int.TryParse(e.Message.Text, out vote)) { + if (vote < 1 || vote > answers.Length) + return; + if (participants.TryAdd(e.User, vote)) { + await e.User.SendMessage($"Thanks for voting **{e.User.Name}**."); + } + } + } + } +} \ No newline at end of file diff --git a/NadekoBot/Modules/Games.cs b/NadekoBot/Modules/Games.cs index 4d7b984e..41b6f11a 100644 --- a/NadekoBot/Modules/Games.cs +++ b/NadekoBot/Modules/Games.cs @@ -15,6 +15,7 @@ namespace NadekoBot.Modules public Games() : base() { commands.Add(new Trivia()); commands.Add(new SpeedTyping()); + commands.Add(new PollCommand()); } public override void Install(ModuleManager manager) diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index 0fbbf8f2..b2729ef1 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -159,6 +159,7 @@ +