Merge remote-tracking branch 'refs/remotes/Kwoth/1.0' into 1.0-fearnlj01
This commit is contained in:
commit
56471cb48b
37
license.md
37
license.md
@ -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
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
distribute this software, either in source code form or as a compiled
|
||||||
in the Software without restriction, including without limitation the rights
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
means.
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
copies or substantial portions of the Software.
|
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
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
SOFTWARE.
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -15,8 +16,18 @@ namespace NadekoBot.Modules.Games
|
|||||||
public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>();
|
public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>();
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequirePermission(GuildPermission.ManageMessages)]
|
||||||
[RequireContext(ContextType.Guild)]
|
[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;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
@ -28,57 +39,63 @@ namespace NadekoBot.Modules.Games
|
|||||||
if (data.Length < 3)
|
if (data.Length < 3)
|
||||||
return;
|
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))
|
if (ActivePolls.TryAdd(channel.Guild, poll))
|
||||||
{
|
{
|
||||||
await poll.StartPoll().ConfigureAwait(false);
|
await poll.StartPoll().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
await channel.SendMessageAsync("`Poll is already running on this server.`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequirePermission(GuildPermission.ManageMessages)]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Pollend(IUserMessage umsg)
|
public async Task Pollend(IUserMessage umsg)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)umsg.Channel;
|
var channel = (ITextChannel)umsg.Channel;
|
||||||
|
|
||||||
if (!(umsg.Author as IGuildUser).GuildPermissions.ManageChannels)
|
|
||||||
return;
|
|
||||||
Poll poll;
|
Poll poll;
|
||||||
ActivePolls.TryGetValue(channel.Guild, out poll);
|
ActivePolls.TryRemove(channel.Guild, out poll);
|
||||||
await poll.StopPoll(channel).ConfigureAwait(false);
|
await poll.StopPoll().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Poll
|
public class Poll
|
||||||
{
|
{
|
||||||
private readonly IUserMessage umsg;
|
private readonly IUserMessage originalMessage;
|
||||||
|
private readonly IGuild guild;
|
||||||
private readonly string[] answers;
|
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 readonly string question;
|
||||||
private DateTime started;
|
private DateTime started;
|
||||||
private CancellationTokenSource pollCancellationSource = new CancellationTokenSource();
|
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.question = question;
|
||||||
this.answers = enumerable as string[] ?? enumerable.ToArray();
|
this.answers = enumerable as string[] ?? enumerable.ToArray();
|
||||||
|
this.isPublic = isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartPoll()
|
public async Task StartPoll()
|
||||||
{
|
{
|
||||||
started = DateTime.Now;
|
started = DateTime.Now;
|
||||||
NadekoBot.Client.MessageReceived += Vote;
|
NadekoBot.Client.MessageReceived += Vote;
|
||||||
var msgToSend = $@"📃**{umsg.Author.Username}** has created a poll which requires your attention:
|
var msgToSend = $"📃**{originalMessage.Author.Username}** has created a poll which requires your attention:\n\n**{question}**\n";
|
||||||
|
|
||||||
**{question}**\n";
|
|
||||||
var num = 1;
|
var num = 1;
|
||||||
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
||||||
|
if (!isPublic)
|
||||||
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
|
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
|
||||||
await umsg.Channel.SendMessageAsync(msgToSend).ConfigureAwait(false);
|
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;
|
NadekoBot.Client.MessageReceived -= Vote;
|
||||||
try
|
try
|
||||||
@ -90,7 +107,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
var totalVotesCast = results.Sum(kvp => kvp.Value);
|
var totalVotesCast = results.Sum(kvp => kvp.Value);
|
||||||
if (totalVotesCast == 0)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
var closeMessage = $"--------------**POLL CLOSED**--------------\n" +
|
var closeMessage = $"--------------**POLL CLOSED**--------------\n" +
|
||||||
@ -99,7 +116,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
$" has {kvp.Value} votes." +
|
$" has {kvp.Value} votes." +
|
||||||
$"({kvp.Value * 1.0f / totalVotesCast * 100}%)\n");
|
$"({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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -113,23 +130,54 @@ namespace NadekoBot.Modules.Games
|
|||||||
var msg = imsg as IUserMessage;
|
var msg = imsg as IUserMessage;
|
||||||
if (msg == null || msg.Author.IsBot)
|
if (msg == null || msg.Author.IsBot)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
// channel must be private
|
|
||||||
IPrivateChannel ch;
|
|
||||||
if ((ch = msg.Channel as IPrivateChannel) == null)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
|
|
||||||
// has to be an integer
|
// has to be an integer
|
||||||
int vote;
|
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 () =>
|
var t = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
if (vote < 1 || vote > answers.Length)
|
try
|
||||||
return;
|
|
||||||
if (participants.TryAdd(msg.Author, vote))
|
|
||||||
{
|
{
|
||||||
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;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
@ -87,11 +87,6 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
url += $"/{width}/{height}";
|
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);
|
await channel.SendMessageAsync(url).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
29
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
@ -4443,7 +4443,7 @@ namespace NadekoBot.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public static string poll_desc {
|
public static string poll_desc {
|
||||||
get {
|
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>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to queue q yq.
|
/// Looks up a localized string similar to queue q yq.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1336,7 +1336,7 @@
|
|||||||
<value>poll</value>
|
<value>poll</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="poll_desc" xml:space="preserve">
|
<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>
|
||||||
<data name="poll_usage" xml:space="preserve">
|
<data name="poll_usage" xml:space="preserve">
|
||||||
<value>`{0}poll Question?;Answer1;Answ 2;A_3`</value>
|
<value>`{0}poll Question?;Answer1;Answ 2;A_3`</value>
|
||||||
@ -2538,4 +2538,13 @@
|
|||||||
<data name="togethertube_usage" xml:space="preserve">
|
<data name="togethertube_usage" xml:space="preserve">
|
||||||
<value>`{0}totube`</value>
|
<value>`{0}totube`</value>
|
||||||
</data>
|
</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>
|
</root>
|
@ -173,6 +173,10 @@ namespace NadekoBot.Services
|
|||||||
{
|
{
|
||||||
if (msg.Channel is IPrivateChannel)
|
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 msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
|
||||||
|
|
||||||
await DMForwardCommands.HandleDMForwarding(msg, ownerChannels);
|
await DMForwardCommands.HandleDMForwarding(msg, ownerChannels);
|
||||||
|
Loading…
Reference in New Issue
Block a user