NadekoBot/src/NadekoBot/Modules/CustomReactions/Services/CustomReactionsService.cs

149 lines
6.3 KiB
C#
Raw Normal View History

2017-05-24 04:43:00 +00:00
using Discord;
using Discord.WebSocket;
using NadekoBot.Services.Database.Models;
using NLog;
using System.Collections.Concurrent;
using System.Linq;
2017-05-25 02:24:43 +00:00
using System;
using System.Threading.Tasks;
2017-07-17 19:42:36 +00:00
using NadekoBot.Common;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Extensions;
using NadekoBot.Services.Database;
2017-07-17 02:37:51 +00:00
using NadekoBot.Services;
using NadekoBot.Modules.CustomReactions.Extensions;
2017-07-17 19:42:36 +00:00
using NadekoBot.Modules.Permissions.Common;
using NadekoBot.Modules.Permissions.Services;
using NadekoBot.Services.Impl;
2017-05-24 04:43:00 +00:00
2017-07-17 02:37:51 +00:00
namespace NadekoBot.Modules.CustomReactions.Services
2017-05-24 04:43:00 +00:00
{
public class CustomReactionsService : IEarlyBlockingExecutor, INService
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 DbService _db;
private readonly DiscordSocketClient _client;
private readonly PermissionService _perms;
private readonly CommandHandler _cmd;
private readonly IBotConfigProvider _bc;
private readonly NadekoStrings _strings;
2017-05-24 04:43:00 +00:00
public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings,
DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IUnitOfWork uow)
2017-05-24 04:43:00 +00:00
{
_log = LogManager.GetCurrentClassLogger();
_db = db;
2017-05-25 02:24:43 +00:00
_client = client;
_perms = perms;
_cmd = cmd;
_bc = bc;
_strings = strings;
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()));
GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
2017-05-24 04:43:00 +00:00
}
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();
if (GuildReactions.TryGetValue(channel.Guild.Id, out CustomReaction[] reactions))
if (reactions != null && reactions.Any())
2017-05-24 04:43:00 +00:00
{
var rs = reactions.Where(cr =>
{
if (cr == null)
return false;
2017-05-24 04:43:00 +00:00
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
var trigger = cr.TriggerWithContext(umsg, _client).Trim().ToLowerInvariant();
return ((cr.ContainsAnywhere &&
(content.StartsWith(trigger + " ")
|| content.EndsWith(" " + trigger)
|| content.Contains(" " + trigger + " ")))
|| (hasTarget && content.StartsWith(trigger + " "))
|| (_bc.BotConfig.CustomReactionsStartWith && content.StartsWith(trigger + " "))
|| content == trigger);
}).ToArray();
2017-05-24 04:43:00 +00:00
if (rs.Length != 0)
2017-05-24 04:43:00 +00:00
{
var reaction = rs[new NadekoRandom().Next(0, rs.Length)];
if (reaction != null)
{
if (reaction.Response == "-")
return null;
return reaction;
}
2017-05-24 04:43:00 +00:00
}
}
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();
return ((hasTarget && content.StartsWith(trigger + " ")) || (_bc.BotConfig.CustomReactionsStartWith && content.StartsWith(trigger + " ")) || content == trigger);
2017-05-24 04:43:00 +00:00
}).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> TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage msg)
2017-05-25 02:24:43 +00:00
{
// maybe this message is a custom reaction
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
if (cr != null)
2017-05-25 02:24:43 +00:00
{
try
{
if (guild is SocketGuild sg)
{
var pc = _perms.GetCache(guild.Id);
if (!pc.Permissions.CheckPermissions(msg, cr.Trigger, "ActualCustomReactions",
out int index))
{
if (pc.Verbose)
{
var returnMsg = _strings.GetText("trigger", guild.Id, "Permissions".ToLowerInvariant(), index + 1, Format.Bold(pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild)));
try { await msg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
_log.Info(returnMsg);
}
return true;
}
}
2017-05-25 02:24:43 +00:00
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
}
}