2016-10-08 02:25:12 +00:00
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
2016-10-09 04:38:46 +00:00
{
2016-10-08 02:25:12 +00:00
[NadekoModule("CustomReactions",".")]
public class CustomReactions : DiscordModule
{
2016-10-10 04:12:22 +00:00
public static ConcurrentHashSet < CustomReaction > GlobalReactions { get ; } = new ConcurrentHashSet < CustomReaction > ( ) ;
public static ConcurrentDictionary < ulong , ConcurrentHashSet < CustomReaction > > GuildReactions { get ; } = new ConcurrentDictionary < ulong , ConcurrentHashSet < CustomReaction > > ( ) ;
2016-10-08 02:25:12 +00:00
static CustomReactions ( )
{
using ( var uow = DbHandler . UnitOfWork ( ) )
{
2016-10-08 02:35:39 +00:00
var items = uow . CustomReactions . GetAll ( ) ;
2016-10-10 04:12:22 +00:00
GuildReactions = new ConcurrentDictionary < ulong , ConcurrentHashSet < CustomReaction > > ( items . Where ( g = > g . GuildId ! = null ) . GroupBy ( k = > k . GuildId . Value ) . ToDictionary ( g = > g . Key , g = > new ConcurrentHashSet < CustomReaction > ( g ) ) ) ;
GlobalReactions = new ConcurrentHashSet < CustomReaction > ( items . Where ( g = > g . GuildId = = null ) ) ;
2016-10-08 02:25:12 +00:00
}
}
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 )
return Task . CompletedTask ;
var channel = umsg . Channel as ITextChannel ;
if ( channel = = null )
return Task . CompletedTask ;
var t = Task . Run ( async ( ) = >
{
2016-10-10 03:04:50 +00:00
var content = umsg . Content . ToLowerInvariant ( ) ;
2016-10-10 04:12:22 +00:00
ConcurrentHashSet < CustomReaction > reactions ;
2016-10-08 18:24:34 +00:00
GuildReactions . TryGetValue ( channel . Guild . Id , out reactions ) ;
if ( reactions ! = null & & reactions . Any ( ) )
{
2016-10-10 03:04:50 +00:00
var reaction = reactions . Where ( cr = > cr . TriggerWithContext ( umsg ) = = content ) . Shuffle ( ) . FirstOrDefault ( ) ;
2016-10-08 18:24:34 +00:00
if ( reaction ! = null )
{
2016-10-09 04:38:46 +00:00
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
}
}
2016-10-10 03:04:50 +00:00
var greaction = GlobalReactions . Where ( cr = > cr . TriggerWithContext ( umsg ) = = content ) . Shuffle ( ) . FirstOrDefault ( ) ;
2016-10-08 22:21:29 +00:00
if ( greaction ! = null )
{
2016-10-09 04:38:46 +00:00
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 ;
} ;
2016-10-08 02:25:12 +00:00
}
[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 ;
2016-10-10 03:04:50 +00:00
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 ) )
2016-10-08 02:25:12 +00:00
{
2016-10-09 02:26:14 +00:00
try { await imsg . Channel . SendMessageAsync ( "Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions." ) ; } catch { }
2016-10-08 02:25:12 +00:00
return ;
}
var cr = new CustomReaction ( )
{
GuildId = channel ? . Guild . Id ,
IsRegex = false ,
2016-10-10 03:04:50 +00:00
Trigger = key ,
2016-10-08 02:25:12 +00:00
Response = message ,
} ;
using ( var uow = DbHandler . UnitOfWork ( ) )
{
uow . CustomReactions . Add ( cr ) ;
await uow . CompleteAsync ( ) . ConfigureAwait ( false ) ;
}
if ( channel = = null )
{
GlobalReactions . Add ( cr ) ;
}
else
{
2016-10-10 04:12:22 +00:00
var reactions = GuildReactions . GetOrAdd ( channel . Guild . Id , new ConcurrentHashSet < CustomReaction > ( ) ) ;
2016-10-08 02:25:12 +00:00
reactions . Add ( cr ) ;
}
2016-10-09 02:26:14 +00:00
await imsg . Channel . SendMessageAsync ( $"`Added new custom reaction:`\n\t`Trigger:` {key}\n\t`Response:` {message}" ) . ConfigureAwait ( false ) ;
2016-10-08 02:25:12 +00:00
}
[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 ;
2016-10-10 04:12:22 +00:00
ConcurrentHashSet < CustomReaction > customReactions ;
2016-10-08 02:25:12 +00:00
if ( channel = = null )
customReactions = GlobalReactions ;
else
2016-10-10 04:12:22 +00:00
customReactions = GuildReactions . GetOrAdd ( channel . Guild . Id , new ConcurrentHashSet < CustomReaction > ( ) ) ;
2016-10-08 02:25:12 +00:00
if ( customReactions = = null | | ! customReactions . Any ( ) )
2016-10-09 01:22:54 +00:00
await imsg . Channel . SendMessageAsync ( "`No custom reactions found`" ) . ConfigureAwait ( false ) ;
2016-10-08 02:25:12 +00:00
else
2016-10-14 08:50:04 +00:00
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}" ) ) )
2016-10-08 02:25:12 +00:00
. ConfigureAwait ( false ) ;
}
2016-10-14 08:50:04 +00:00
[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 ) ;
}
}
2016-10-08 02:25:12 +00:00
[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 ) )
2016-10-08 02:25:12 +00:00
{
2016-10-09 02:26:14 +00:00
try { await imsg . Channel . SendMessageAsync ( "Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions." ) ; } catch { }
2016-10-08 02:25:12 +00:00
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 ) ;
2016-10-08 02:25:12 +00:00
success = true ;
}
2016-10-09 02:26:14 +00:00
else if ( toDelete . GuildId ! = null & & channel ? . Guild . Id = = toDelete . GuildId )
2016-10-08 02:25:12 +00:00
{
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 ) ;
2016-10-08 02:25:12 +00:00
success = true ;
}
if ( success )
await uow . CompleteAsync ( ) . ConfigureAwait ( false ) ;
}
if ( success )
2016-10-09 02:26:14 +00:00
await imsg . Channel . SendMessageAsync ( "**Successfully deleted custom reaction** " + toDelete . ToString ( ) ) . ConfigureAwait ( false ) ;
2016-10-08 02:25:12 +00:00
else
2016-10-09 02:26:14 +00:00
await imsg . Channel . SendMessageAsync ( "`Failed to find that custom reaction.`" ) . ConfigureAwait ( false ) ;
2016-10-08 02:25:12 +00:00
}
}
}