NadekoBot/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs

195 lines
8.5 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using NadekoBot.Services;
using NadekoBot.Attributes;
using NadekoBot.Services.Database;
using System.Collections.Concurrent;
using NadekoBot.Services.Database.Models;
using Discord;
using NadekoBot.Extensions;
namespace NadekoBot.Modules.CustomReactions
{
[NadekoModule("CustomReactions",".")]
public class CustomReactions : DiscordModule
{
public static ConcurrentHashSet<CustomReaction> GlobalReactions { get; } = new ConcurrentHashSet<CustomReaction>();
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>> GuildReactions { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>();
static CustomReactions()
{
using (var uow = DbHandler.UnitOfWork())
{
2016-10-08 02:35:39 +00:00
var items = uow.CustomReactions.GetAll();
2016-10-14 22:56:29 +00:00
GuildReactions = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet<CustomReaction>(g)));
GlobalReactions = new ConcurrentHashSet<CustomReaction>(items.Where(g => g.GuildId == null || g.GuildId == 0));
}
}
public CustomReactions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{
2016-10-08 18:24:34 +00:00
client.MessageReceived += (imsg) =>
{
var umsg = imsg as IUserMessage;
if (umsg == null || imsg.Author.IsBot)
2016-10-08 18:24:34 +00:00
return Task.CompletedTask;
var channel = umsg.Channel as ITextChannel;
if (channel == null)
return Task.CompletedTask;
var t = Task.Run(async () =>
{
var content = umsg.Content.ToLowerInvariant();
ConcurrentHashSet<CustomReaction> reactions;
2016-10-08 18:24:34 +00:00
GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
if (reactions != null && reactions.Any())
{
var reaction = reactions.Where(cr => cr.TriggerWithContext(umsg) == content).Shuffle().FirstOrDefault();
2016-10-08 18:24:34 +00:00
if (reaction != null)
{
try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
2016-10-08 22:21:29 +00:00
return;
2016-10-08 18:24:34 +00:00
}
}
var greaction = GlobalReactions.Where(cr => cr.TriggerWithContext(umsg) == content).Shuffle().FirstOrDefault();
2016-10-08 22:21:29 +00:00
if (greaction != null)
{
try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
2016-10-08 22:21:29 +00:00
return;
}
2016-10-08 18:24:34 +00:00
});
return Task.CompletedTask;
};
}
[NadekoCommand, Usage, Description, Aliases]
public async Task AddCustReact(IUserMessage imsg, string key, [Remainder] string message)
{
var channel = imsg.Channel as ITextChannel;
if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key))
return;
key = key.ToLowerInvariant();
2016-10-08 18:24:34 +00:00
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator))
{
try { await imsg.Channel.SendMessageAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
return;
}
var cr = new CustomReaction()
{
GuildId = channel?.Guild.Id,
IsRegex = false,
Trigger = key,
Response = message,
};
using (var uow = DbHandler.UnitOfWork())
{
uow.CustomReactions.Add(cr);
await uow.CompleteAsync().ConfigureAwait(false);
}
if (channel == null)
{
GlobalReactions.Add(cr);
}
else
{
var reactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
reactions.Add(cr);
}
await imsg.Channel.SendMessageAsync($"`Added new custom reaction:`\n\t`Trigger:` {key}\n\t`Response:` {message}").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
public async Task ListCustReact(IUserMessage imsg,int page = 1)
{
var channel = imsg.Channel as ITextChannel;
if (page < 1 || page > 1000)
return;
ConcurrentHashSet<CustomReaction> customReactions;
if (channel == null)
customReactions = GlobalReactions;
else
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
if (customReactions == null || !customReactions.Any())
2016-10-09 01:22:54 +00:00
await imsg.Channel.SendMessageAsync("`No custom reactions found`").ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync($"`Page {page} of custom reactions:`\n" + string.Join("\n", customReactions.OrderBy(cr => cr.Trigger).Skip((page - 1) * 15).Take(15).Select(cr => $"`#{cr.Id}` `Trigger:` {cr.Trigger}")))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
public async Task ShowCustReact(IUserMessage imsg, int id)
{
var channel = imsg.Channel as ITextChannel;
ConcurrentHashSet<CustomReaction> customReactions;
if (channel == null)
customReactions = GlobalReactions;
else
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>());
var found = customReactions.FirstOrDefault(cr => cr.Id == id);
if (found == null)
await imsg.Channel.SendMessageAsync("`No custom reaction found with that id.`").ConfigureAwait(false);
else
{
await imsg.Channel.SendMessageAsync($"`Custom reaction #{id}`\n`Trigger:` {found.Trigger}\n`Response:` {found.Response}")
.ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases]
public async Task DelCustReact(IUserMessage imsg, int id)
{
var channel = imsg.Channel as ITextChannel;
2016-10-08 18:24:34 +00:00
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator))
{
try { await imsg.Channel.SendMessageAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
return;
}
var success = false;
CustomReaction toDelete;
using (var uow = DbHandler.UnitOfWork())
{
toDelete = uow.CustomReactions.Get(id);
if (toDelete == null) //not found
return;
if (toDelete.GuildId == null && channel == null)
{
uow.CustomReactions.Remove(toDelete);
2016-10-10 04:38:20 +00:00
GlobalReactions.RemoveWhere(cr => cr.Id == toDelete.Id);
success = true;
}
else if (toDelete.GuildId != null && channel?.Guild.Id == toDelete.GuildId)
{
uow.CustomReactions.Remove(toDelete);
2016-10-10 04:38:20 +00:00
GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()).RemoveWhere(cr=>cr.Id == toDelete.Id);
success = true;
}
if(success)
await uow.CompleteAsync().ConfigureAwait(false);
}
if (success)
await imsg.Channel.SendMessageAsync("**Successfully deleted custom reaction** " + toDelete.ToString()).ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync("`Failed to find that custom reaction.`").ConfigureAwait(false);
}
}
}