Merge remote-tracking branch 'refs/remotes/Kwoth/1.0' into 1.0-fearnlj01

This commit is contained in:
Jordan Fearnley 2016-10-24 22:13:35 +01:00
commit 56471cb48b
6 changed files with 138 additions and 50 deletions

View File

@ -1,19 +1,24 @@
Copyright (c) 2015 Master Kwoth
This is free and unencumbered software released into the public domain.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

View File

@ -1,5 +1,6 @@
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes;
using System;
using System.Collections.Concurrent;
@ -15,8 +16,18 @@ namespace NadekoBot.Modules.Games
public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>();
[NadekoCommand, Usage, Description, Aliases]
[RequirePermission(GuildPermission.ManageMessages)]
[RequireContext(ContextType.Guild)]
public async Task Poll(IUserMessage umsg, [Remainder] string arg = null)
public Task Poll(IUserMessage umsg, [Remainder] string arg = null)
=> InternalStartPoll(umsg, arg, isPublic: false);
[NadekoCommand, Usage, Description, Aliases]
[RequirePermission(GuildPermission.ManageMessages)]
[RequireContext(ContextType.Guild)]
public Task PublicPoll(IUserMessage umsg, [Remainder] string arg = null)
=> InternalStartPoll(umsg, arg, isPublic: true);
private async Task InternalStartPoll(IUserMessage umsg, string arg, bool isPublic = false)
{
var channel = (ITextChannel)umsg.Channel;
@ -28,57 +39,63 @@ namespace NadekoBot.Modules.Games
if (data.Length < 3)
return;
var poll = new Poll(umsg, data[0], data.Skip(1));
var poll = new Poll(umsg, data[0], data.Skip(1), isPublic: isPublic);
if (ActivePolls.TryAdd(channel.Guild, poll))
{
await poll.StartPoll().ConfigureAwait(false);
}
else
await channel.SendMessageAsync("`Poll is already running on this server.`").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequirePermission(GuildPermission.ManageMessages)]
[RequireContext(ContextType.Guild)]
public async Task Pollend(IUserMessage umsg)
{
var channel = (ITextChannel)umsg.Channel;
if (!(umsg.Author as IGuildUser).GuildPermissions.ManageChannels)
return;
Poll poll;
ActivePolls.TryGetValue(channel.Guild, out poll);
await poll.StopPoll(channel).ConfigureAwait(false);
ActivePolls.TryRemove(channel.Guild, out poll);
await poll.StopPoll().ConfigureAwait(false);
}
}
public class Poll
{
private readonly IUserMessage umsg;
private readonly IUserMessage originalMessage;
private readonly IGuild guild;
private readonly string[] answers;
private ConcurrentDictionary<IUser, int> participants = new ConcurrentDictionary<IUser, int>();
private ConcurrentDictionary<ulong, int> participants = new ConcurrentDictionary<ulong, int>();
private readonly string question;
private DateTime started;
private CancellationTokenSource pollCancellationSource = new CancellationTokenSource();
private readonly bool isPublic;
public Poll(IUserMessage umsg, string question, IEnumerable<string> enumerable)
public Poll(IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
{
this.umsg = umsg;
this.originalMessage = umsg;
this.guild = ((ITextChannel)umsg.Channel).Guild;
this.question = question;
this.answers = enumerable as string[] ?? enumerable.ToArray();
this.isPublic = isPublic;
}
public async Task StartPoll()
{
started = DateTime.Now;
NadekoBot.Client.MessageReceived += Vote;
var msgToSend = $@"📃**{umsg.Author.Username}** has created a poll which requires your attention:
**{question}**\n";
var msgToSend = $"📃**{originalMessage.Author.Username}** has created a poll which requires your attention:\n\n**{question}**\n";
var num = 1;
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
await umsg.Channel.SendMessageAsync(msgToSend).ConfigureAwait(false);
if (!isPublic)
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
else
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**";
await originalMessage.Channel.SendMessageAsync(msgToSend).ConfigureAwait(false);
}
public async Task StopPoll(IGuildChannel ch)
public async Task StopPoll()
{
NadekoBot.Client.MessageReceived -= Vote;
try
@ -90,7 +107,7 @@ namespace NadekoBot.Modules.Games
var totalVotesCast = results.Sum(kvp => kvp.Value);
if (totalVotesCast == 0)
{
await umsg.Channel.SendMessageAsync("📄 **No votes have been cast.**").ConfigureAwait(false);
await originalMessage.Channel.SendMessageAsync("📄 **No votes have been cast.**").ConfigureAwait(false);
return;
}
var closeMessage = $"--------------**POLL CLOSED**--------------\n" +
@ -99,7 +116,7 @@ namespace NadekoBot.Modules.Games
$" has {kvp.Value} votes." +
$"({kvp.Value * 1.0f / totalVotesCast * 100}%)\n");
await umsg.Channel.SendMessageAsync($"📄 **Total votes cast**: {totalVotesCast}\n{closeMessage}").ConfigureAwait(false);
await originalMessage.Channel.SendMessageAsync($"📄 **Total votes cast**: {totalVotesCast}\n{closeMessage}").ConfigureAwait(false);
}
catch (Exception ex)
{
@ -113,23 +130,54 @@ namespace NadekoBot.Modules.Games
var msg = imsg as IUserMessage;
if (msg == null || msg.Author.IsBot)
return Task.CompletedTask;
// channel must be private
IPrivateChannel ch;
if ((ch = msg.Channel as IPrivateChannel) == null)
return Task.CompletedTask;
// has to be an integer
int vote;
if (!int.TryParse(msg.Content, out vote)) return Task.CompletedTask;
if (!int.TryParse(imsg.Content, out vote))
return Task.CompletedTask;
if (vote < 1 || vote > answers.Length)
return Task.CompletedTask;
var t = Task.Run(async () =>
{
if (vote < 1 || vote > answers.Length)
return;
if (participants.TryAdd(msg.Author, vote))
try
{
try { await ((IMessageChannel)ch).SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false); } catch { }
IMessageChannel ch;
if (isPublic)
{
//if public, channel must be the same the poll started in
if (originalMessage.Channel.Id != imsg.Channel.Id)
return;
ch = imsg.Channel;
}
else
{
//if private, channel must be dm channel
if ((ch = msg.Channel as IDMChannel) == null)
return;
// user must be a member of the guild this poll is in
var guildUsers = await guild.GetUsersAsync().ConfigureAwait(false);
if (!guildUsers.Any(u => u.Id == imsg.Author.Id))
return;
}
//user can vote only once
if (participants.TryAdd(msg.Author.Id, vote))
{
if (!isPublic)
{
await ch.SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
}
else
{
var toDelete = await ch.SendMessageAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false);
await Task.Delay(5000);
await toDelete.DeleteAsync().ConfigureAwait(false);
}
}
}
catch { }
});
return Task.CompletedTask;
}

View File

@ -87,11 +87,6 @@ namespace NadekoBot.Modules.Searches
url += $"/{width}/{height}";
//using (var http = new HttpClient())
//{
// var res = await http.GetStreamAsync(url).ConfigureAwait(false);
// await channel.SendFileAsync()
//}
await channel.SendMessageAsync(url).ConfigureAwait(false);
}
}

View File

@ -4443,7 +4443,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Creates a poll, only person who has manage server permission can do it..
/// Looks up a localized string similar to Creates a poll which requires users to send the number of the voting option to the bot..
/// </summary>
public static string poll_desc {
get {
@ -4514,6 +4514,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to publicpoll ppoll.
/// </summary>
public static string publicpoll_cmd {
get {
return ResourceManager.GetString("publicpoll_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Creates a public poll which requires users to type a number of the voting option in the channel command is ran in..
/// </summary>
public static string publicpoll_desc {
get {
return ResourceManager.GetString("publicpoll_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}ppoll Question?;Answer1;Answ 2;A_3`.
/// </summary>
public static string publicpoll_usage {
get {
return ResourceManager.GetString("publicpoll_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to queue q yq.
/// </summary>

View File

@ -1336,7 +1336,7 @@
<value>poll</value>
</data>
<data name="poll_desc" xml:space="preserve">
<value>Creates a poll, only person who has manage server permission can do it.</value>
<value>Creates a poll which requires users to send the number of the voting option to the bot.</value>
</data>
<data name="poll_usage" xml:space="preserve">
<value>`{0}poll Question?;Answer1;Answ 2;A_3`</value>
@ -2538,4 +2538,13 @@
<data name="togethertube_usage" xml:space="preserve">
<value>`{0}totube`</value>
</data>
<data name="publicpoll_cmd" xml:space="preserve">
<value>publicpoll ppoll</value>
</data>
<data name="publicpoll_desc" xml:space="preserve">
<value>Creates a public poll which requires users to type a number of the voting option in the channel command is ran in.</value>
</data>
<data name="publicpoll_usage" xml:space="preserve">
<value>`{0}ppoll Question?;Answer1;Answ 2;A_3`</value>
</data>
</root>

View File

@ -173,6 +173,10 @@ namespace NadekoBot.Services
{
if (msg.Channel is IPrivateChannel)
{
//rofl, gotta do this to prevent this message from occuring on polls
int vote;
if (int.TryParse(msg.Content, out vote)) return;
await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
await DMForwardCommands.HandleDMForwarding(msg, ownerChannels);