2017-05-24 04:43:00 +00:00
|
|
|
|
using Discord;
|
|
|
|
|
using Discord.WebSocket;
|
2017-05-25 02:24:43 +00:00
|
|
|
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
2017-05-24 04:43:00 +00:00
|
|
|
|
using NadekoBot.Services.Database.Models;
|
|
|
|
|
using NLog;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Linq;
|
2017-05-25 02:24:43 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Threading.Tasks;
|
2017-05-24 04:43:00 +00:00
|
|
|
|
|
2017-05-25 02:24:43 +00:00
|
|
|
|
namespace NadekoBot.Services.CustomReactions
|
2017-05-24 04:43:00 +00:00
|
|
|
|
{
|
2017-05-25 02:24:43 +00:00
|
|
|
|
public class CustomReactionsService : IBlockingExecutor
|
2017-05-24 04:43:00 +00:00
|
|
|
|
{
|
2017-05-25 02:24:43 +00:00
|
|
|
|
public CustomReaction[] GlobalReactions = new CustomReaction[] { };
|
2017-05-24 04:43:00 +00:00
|
|
|
|
public ConcurrentDictionary<ulong, CustomReaction[]> GuildReactions { get; } = new ConcurrentDictionary<ulong, CustomReaction[]>();
|
|
|
|
|
|
|
|
|
|
public ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
|
|
|
|
|
|
|
|
|
|
private readonly Logger _log;
|
|
|
|
|
private readonly DbHandler _db;
|
2017-05-25 02:24:43 +00:00
|
|
|
|
private readonly DiscordShardedClient _client;
|
2017-05-24 04:43:00 +00:00
|
|
|
|
|
2017-05-25 02:24:43 +00:00
|
|
|
|
public CustomReactionsService(DbHandler db, DiscordShardedClient client)
|
2017-05-24 04:43:00 +00:00
|
|
|
|
{
|
|
|
|
|
_log = LogManager.GetCurrentClassLogger();
|
|
|
|
|
_db = db;
|
2017-05-25 02:24:43 +00:00
|
|
|
|
_client = client;
|
|
|
|
|
|
2017-05-24 04:43:00 +00:00
|
|
|
|
var sw = Stopwatch.StartNew();
|
|
|
|
|
using (var uow = _db.UnitOfWork)
|
|
|
|
|
{
|
|
|
|
|
var items = uow.CustomReactions.GetAll();
|
|
|
|
|
GuildReactions = new ConcurrentDictionary<ulong, CustomReaction[]>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray()));
|
2017-05-25 02:24:43 +00:00
|
|
|
|
GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
|
2017-05-24 04:43:00 +00:00
|
|
|
|
}
|
|
|
|
|
sw.Stop();
|
|
|
|
|
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ClearStats() => ReactionStats.Clear();
|
|
|
|
|
|
|
|
|
|
public CustomReaction TryGetCustomReaction(IUserMessage umsg)
|
|
|
|
|
{
|
|
|
|
|
var channel = umsg.Channel as SocketTextChannel;
|
|
|
|
|
if (channel == null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
var content = umsg.Content.Trim().ToLowerInvariant();
|
|
|
|
|
CustomReaction[] reactions;
|
|
|
|
|
|
|
|
|
|
GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
|
|
|
|
|
if (reactions != null && reactions.Any())
|
|
|
|
|
{
|
|
|
|
|
var rs = reactions.Where(cr =>
|
|
|
|
|
{
|
|
|
|
|
if (cr == null)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
2017-05-25 02:24:43 +00:00
|
|
|
|
var trigger = cr.TriggerWithContext(umsg, _client).Trim().ToLowerInvariant();
|
2017-05-24 04:43:00 +00:00
|
|
|
|
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
|
|
|
|
}).ToArray();
|
|
|
|
|
|
|
|
|
|
if (rs.Length != 0)
|
|
|
|
|
{
|
|
|
|
|
var reaction = rs[new NadekoRandom().Next(0, rs.Length)];
|
|
|
|
|
if (reaction != null)
|
|
|
|
|
{
|
|
|
|
|
if (reaction.Response == "-")
|
|
|
|
|
return null;
|
|
|
|
|
return reaction;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var grs = GlobalReactions.Where(cr =>
|
|
|
|
|
{
|
|
|
|
|
if (cr == null)
|
|
|
|
|
return false;
|
|
|
|
|
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
2017-05-25 02:24:43 +00:00
|
|
|
|
var trigger = cr.TriggerWithContext(umsg, _client).Trim().ToLowerInvariant();
|
2017-05-24 04:43:00 +00:00
|
|
|
|
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
|
|
|
|
}).ToArray();
|
|
|
|
|
if (grs.Length == 0)
|
|
|
|
|
return null;
|
|
|
|
|
var greaction = grs[new NadekoRandom().Next(0, grs.Length)];
|
|
|
|
|
|
|
|
|
|
return greaction;
|
|
|
|
|
}
|
2017-05-25 02:24:43 +00:00
|
|
|
|
|
|
|
|
|
public async Task<bool> TryExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
|
|
|
|
{
|
|
|
|
|
//todo custom reactions
|
|
|
|
|
// maybe this message is a custom reaction
|
|
|
|
|
// todo log custom reaction executions. return struct with info
|
|
|
|
|
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
|
|
|
|
|
if (cr != null) //if it was, don't execute the command
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//if (guild != null)
|
|
|
|
|
//{
|
|
|
|
|
// PermissionCache pc = Permissions.GetCache(guild.Id);
|
|
|
|
|
|
|
|
|
|
// if (!pc.Permissions.CheckPermissions(usrMsg, cr.Trigger, "ActualCustomReactions",
|
|
|
|
|
// out int index))
|
|
|
|
|
// {
|
|
|
|
|
// //todo print in guild actually
|
|
|
|
|
// var returnMsg =
|
|
|
|
|
// $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action.";
|
|
|
|
|
// _log.Info(returnMsg);
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
await cr.Send(msg, _client, this).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
if (cr.AutoDeleteTrigger)
|
|
|
|
|
{
|
|
|
|
|
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_log.Warn("Sending CREmbed failed");
|
|
|
|
|
_log.Warn(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-05-24 04:43:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|