NadekoBot/NadekoBot.Modules.Gambling/CurrencyEventsCommands.cs

282 lines
9.8 KiB
C#
Raw Normal View History

2017-01-15 14:09:48 +00:00
using Discord;
using Discord.Commands;
using NadekoBot.Extensions;
using NadekoBot.Services;
using System;
using System.Linq;
using System.Threading.Tasks;
2017-01-30 05:26:47 +00:00
using Discord.WebSocket;
using System.Threading;
2017-07-17 19:42:36 +00:00
using NadekoBot.Common;
using NadekoBot.Common.Attributes;
using NadekoBot.Common.Collections;
using NLog;
using System.Collections.Concurrent;
using System.Collections.Generic;
using NadekoBot.Services.Database.Models;
2017-01-15 14:09:48 +00:00
namespace NadekoBot.Modules.Gambling
{
//todo mess, needs unload thing too - refactor
2017-01-15 14:09:48 +00:00
public partial class Gambling
{
[Group]
2017-07-17 19:42:36 +00:00
public class CurrencyEventsCommands : NadekoSubmodule
2017-01-15 14:09:48 +00:00
{
public enum CurrencyEvent
{
Reaction,
2017-01-30 05:26:47 +00:00
SneakyGameStatus
2017-01-15 14:09:48 +00:00
}
//flower reaction event
2017-02-15 10:41:32 +00:00
private static readonly ConcurrentHashSet<ulong> _sneakyGameAwardedUsers = new ConcurrentHashSet<ulong>();
2017-05-24 20:28:16 +00:00
2017-01-30 05:26:47 +00:00
private static readonly char[] _sneakyGameStatusChars = Enumerable.Range(48, 10)
.Concat(Enumerable.Range(65, 26))
.Concat(Enumerable.Range(97, 26))
.Select(x => (char)x)
.ToArray();
2017-05-24 20:28:16 +00:00
private string _secretCode = string.Empty;
private readonly DiscordSocketClient _client;
private readonly IBotConfigProvider _bc;
private readonly CurrencyService _cs;
2017-05-24 20:28:16 +00:00
public CurrencyEventsCommands(DiscordSocketClient client, IBotConfigProvider bc, CurrencyService cs)
2017-05-24 20:28:16 +00:00
{
_client = client;
_bc = bc;
_cs = cs;
2017-05-24 20:28:16 +00:00
}
2017-01-30 05:26:47 +00:00
2017-01-15 14:09:48 +00:00
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
2017-01-30 05:26:47 +00:00
public async Task StartEvent(CurrencyEvent e, int arg = -1)
2017-01-15 14:09:48 +00:00
{
2017-02-14 13:30:21 +00:00
switch (e)
2017-01-15 14:09:48 +00:00
{
case CurrencyEvent.Reaction:
2017-09-18 07:24:42 +00:00
await ReactionEvent(Context, arg).ConfigureAwait(false);
2017-02-14 13:30:21 +00:00
break;
case CurrencyEvent.SneakyGameStatus:
await SneakyGameStatusEvent(Context, arg).ConfigureAwait(false);
break;
2017-01-15 14:09:48 +00:00
}
}
2017-04-15 00:54:19 +00:00
public async Task SneakyGameStatusEvent(ICommandContext context, int? arg)
2017-01-30 05:26:47 +00:00
{
int num;
if (arg == null || arg < 5)
num = 60;
else
num = arg.Value;
2017-02-15 10:41:32 +00:00
if (_secretCode != string.Empty)
2017-01-30 05:26:47 +00:00
return;
var rng = new NadekoRandom();
2017-02-15 10:41:32 +00:00
for (var i = 0; i < 5; i++)
2017-01-30 05:26:47 +00:00
{
_secretCode += _sneakyGameStatusChars[rng.Next(0, _sneakyGameStatusChars.Length)];
}
2017-02-14 13:30:21 +00:00
await _client.SetGameAsync($"type {_secretCode} for " + _bc.BotConfig.CurrencyPluralName)
2017-01-30 05:26:47 +00:00
.ConfigureAwait(false);
try
{
2017-02-15 10:41:32 +00:00
var title = GetText("sneakygamestatus_title");
var desc = GetText("sneakygamestatus_desc", Format.Bold(100.ToString()) + _bc.BotConfig.CurrencySign, Format.Bold(num.ToString()));
2017-02-15 10:41:32 +00:00
await context.Channel.SendConfirmAsync(title, desc).ConfigureAwait(false);
2017-01-30 05:26:47 +00:00
}
2017-02-14 13:30:21 +00:00
catch
{
// ignored
}
2017-01-30 05:26:47 +00:00
2017-05-24 20:28:16 +00:00
_client.MessageReceived += SneakyGameMessageReceivedEventHandler;
2017-01-30 05:26:47 +00:00
await Task.Delay(num * 1000);
2017-05-24 20:28:16 +00:00
_client.MessageReceived -= SneakyGameMessageReceivedEventHandler;
2017-01-30 05:26:47 +00:00
var cnt = _sneakyGameAwardedUsers.Count;
2017-01-30 05:26:47 +00:00
_sneakyGameAwardedUsers.Clear();
2017-02-15 10:41:32 +00:00
_secretCode = string.Empty;
2017-01-30 05:26:47 +00:00
2017-05-24 20:28:16 +00:00
await _client.SetGameAsync(GetText("sneakygamestatus_end", cnt))
2017-01-30 05:26:47 +00:00
.ConfigureAwait(false);
}
2017-05-24 20:28:16 +00:00
private Task SneakyGameMessageReceivedEventHandler(SocketMessage arg)
2017-01-30 05:26:47 +00:00
{
if (arg.Content == _secretCode &&
_sneakyGameAwardedUsers.Add(arg.Author.Id))
{
var _ = Task.Run(async () =>
{
await _cs.AddAsync(arg.Author, "Sneaky Game Event", 100, false)
2017-01-30 05:26:47 +00:00
.ConfigureAwait(false);
try { await arg.DeleteAsync(new RequestOptions() { RetryMode = RetryMode.AlwaysFail }).ConfigureAwait(false); }
2017-02-14 13:30:21 +00:00
catch
{
// ignored
}
2017-01-30 05:26:47 +00:00
});
}
2017-06-15 23:55:14 +00:00
return Task.CompletedTask;
2017-01-30 05:26:47 +00:00
}
2017-01-15 14:09:48 +00:00
2017-09-18 07:24:42 +00:00
public async Task ReactionEvent(ICommandContext context, int amount)
2017-02-15 10:41:32 +00:00
{
if (amount <= 0)
amount = 100;
var title = GetText("reaction_title");
var desc = GetText("reaction_desc", _bc.BotConfig.CurrencySign, Format.Bold(amount.ToString()) + _bc.BotConfig.CurrencySign);
var footer = GetText("reaction_footer", 24);
2017-02-15 10:41:32 +00:00
var msg = await context.Channel.SendConfirmAsync(title,
desc, footer: footer)
.ConfigureAwait(false);
await new ReactionEvent(_bc.BotConfig, _client, _cs, amount).Start(msg, context);
2017-02-15 10:41:32 +00:00
}
}
}
public abstract class CurrencyEvent
{
public abstract Task Start(IUserMessage msg, ICommandContext channel);
}
public class ReactionEvent : CurrencyEvent
{
private readonly ConcurrentHashSet<ulong> _reactionAwardedUsers = new ConcurrentHashSet<ulong>();
private readonly BotConfig _bc;
private readonly Logger _log;
private readonly DiscordSocketClient _client;
private readonly CurrencyService _cs;
private readonly SocketSelfUser _botUser;
2017-04-15 00:54:19 +00:00
private IUserMessage StartingMessage { get; set; }
2017-04-15 00:54:19 +00:00
private CancellationTokenSource Source { get; }
private CancellationToken CancelToken { get; }
private readonly ConcurrentQueue<ulong> _toGiveTo = new ConcurrentQueue<ulong>();
private readonly int _amount;
public ReactionEvent(BotConfig bc, DiscordSocketClient client, CurrencyService cs, int amount)
{
_bc = bc;
_log = LogManager.GetCurrentClassLogger();
2017-05-24 20:28:16 +00:00
_client = client;
_cs = cs;
_botUser = client.CurrentUser;
_amount = amount;
2017-04-15 00:54:19 +00:00
Source = new CancellationTokenSource();
CancelToken = Source.Token;
var _ = Task.Run(async () =>
{
var users = new List<ulong>();
while (!CancelToken.IsCancellationRequested)
{
await Task.Delay(1000).ConfigureAwait(false);
while (_toGiveTo.TryDequeue(out var usrId))
{
users.Add(usrId);
}
if (users.Count > 0)
{
await _cs.AddToManyAsync("Reaction Event", _amount, users.ToArray()).ConfigureAwait(false);
}
users.Clear();
}
}, CancelToken);
}
private async Task End()
{
2017-04-15 00:54:19 +00:00
if(StartingMessage != null)
await StartingMessage.DeleteAsync().ConfigureAwait(false);
2017-04-15 00:54:19 +00:00
if(!Source.IsCancellationRequested)
Source.Cancel();
2017-05-24 20:28:16 +00:00
_client.MessageDeleted -= MessageDeletedEventHandler;
}
2017-04-15 00:54:19 +00:00
private Task MessageDeletedEventHandler(Cacheable<IMessage, ulong> msg, ISocketMessageChannel channel) {
if (StartingMessage?.Id == msg.Id)
2017-01-15 14:09:48 +00:00
{
_log.Warn("Stopping flower reaction event because message is deleted.");
2017-02-14 13:30:21 +00:00
var __ = Task.Run(End);
}
return Task.CompletedTask;
}
public override async Task Start(IUserMessage umsg, ICommandContext context)
{
2017-04-15 00:54:19 +00:00
StartingMessage = umsg;
2017-05-24 20:28:16 +00:00
_client.MessageDeleted += MessageDeletedEventHandler;
IEmote iemote;
if (Emote.TryParse(_bc.CurrencySign, out var emote))
{
iemote = emote;
}
else
iemote = new Emoji(_bc.CurrencySign);
try { await StartingMessage.AddReactionAsync(iemote).ConfigureAwait(false); }
catch
{
try { await StartingMessage.AddReactionAsync(iemote).ConfigureAwait(false); }
2017-01-15 17:04:22 +00:00
catch
{
2017-04-15 00:54:19 +00:00
try { await StartingMessage.DeleteAsync().ConfigureAwait(false); }
catch { return; }
}
}
using (StartingMessage.OnReaction(_client, (r) =>
{
try
{
if (r.UserId == _botUser.Id)
return;
if (r.Emote.Name == iemote.Name && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _reactionAwardedUsers.Add(r.User.Value.Id))
2017-01-15 17:04:22 +00:00
{
_toGiveTo.Enqueue(r.UserId);
2017-01-15 17:04:22 +00:00
}
}
2017-02-14 13:30:21 +00:00
catch
{
// ignored
}
}))
{
try
2017-01-15 14:09:48 +00:00
{
2017-04-15 00:54:19 +00:00
await Task.Delay(TimeSpan.FromHours(24), CancelToken).ConfigureAwait(false);
2017-01-15 14:09:48 +00:00
}
catch (OperationCanceledException)
{
}
2017-04-15 00:54:19 +00:00
if (CancelToken.IsCancellationRequested)
return;
_log.Warn("Stopping flower reaction event because it expired.");
await End();
2017-01-15 14:09:48 +00:00
}
}
}
}