Work on custom reactions, fixed -modules
This commit is contained in:
		
							
								
								
									
										136
									
								
								src/NadekoBot/Modules/CustomReactions/CustomReactions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/NadekoBot/Modules/CustomReactions/CustomReactions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
			
		||||
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 HashSet<CustomReaction> GlobalReactions { get; } = new HashSet<CustomReaction>();
 | 
			
		||||
        public static ConcurrentDictionary<ulong, HashSet<CustomReaction>> AllReactions { get; } = new ConcurrentDictionary<ulong, HashSet<CustomReaction>>();
 | 
			
		||||
        static CustomReactions()
 | 
			
		||||
        {
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                var list = uow.CustomReactions.GetList();
 | 
			
		||||
                AllReactions = new ConcurrentDictionary<ulong, HashSet<CustomReaction>>(list.Where(g => g.GuildId != null).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new HashSet<CustomReaction>(g)));
 | 
			
		||||
                GlobalReactions = new HashSet<CustomReaction>(list.Where(g => g.GuildId == null));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public CustomReactions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequirePermission(GuildPermission.Administrator)]
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
            if ((channel == null && NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && ((IGuildUser)imsg.Author).GuildPermissions.Administrator))
 | 
			
		||||
            {
 | 
			
		||||
                try { await 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.ToLowerInvariant(),
 | 
			
		||||
                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 = AllReactions.GetOrAdd(channel.Guild.Id, new HashSet<CustomReaction>());
 | 
			
		||||
                reactions.Add(cr);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await 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;
 | 
			
		||||
            HashSet<CustomReaction> customReactions;
 | 
			
		||||
            if (channel == null)
 | 
			
		||||
                customReactions = GlobalReactions;
 | 
			
		||||
            else
 | 
			
		||||
                customReactions = AllReactions.GetOrAdd(channel.Guild.Id, new HashSet<CustomReaction>());
 | 
			
		||||
 | 
			
		||||
            if (customReactions == null || !customReactions.Any())
 | 
			
		||||
                await channel.SendMessageAsync("`No custom reactions found`").ConfigureAwait(false);
 | 
			
		||||
            else
 | 
			
		||||
                await channel.SendTableAsync(customReactions.OrderBy(cr => cr.Trigger).Skip((page - 1) * 10).Take(10), c => c.ToString())
 | 
			
		||||
                             .ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        public async Task DelCustReact(IUserMessage imsg, int id)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            if ((channel == null && NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && ((IGuildUser)imsg.Author).GuildPermissions.Administrator))
 | 
			
		||||
            {
 | 
			
		||||
                try { await 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);
 | 
			
		||||
                    success = true;
 | 
			
		||||
                }
 | 
			
		||||
                else if (toDelete.GuildId != null && channel.Guild.Id == toDelete.GuildId)
 | 
			
		||||
                {
 | 
			
		||||
                    uow.CustomReactions.Remove(toDelete);
 | 
			
		||||
                    success = true;
 | 
			
		||||
                }
 | 
			
		||||
                if(success)
 | 
			
		||||
                    await uow.CompleteAsync().ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (success)
 | 
			
		||||
                await channel.SendMessageAsync("**Successfully deleted custom reaction** " + toDelete.ToString()).ConfigureAwait(false);
 | 
			
		||||
            else
 | 
			
		||||
                await channel.SendMessageAsync("Failed to find that custom reaction.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -53,30 +53,6 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
 | 
			
		||||
            await umsg.Channel.SendMessageAsync("`List of modules:` ```xl\n• " + string.Join("\n• ", _commands.Modules.Select(m => m.Name)) + $"\n``` `Type \"-commands module_name\" to get a list of commands in that module.`")
 | 
			
		||||
                                       .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            await RunWithTypingIntheBackgorund(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(100000);
 | 
			
		||||
            }, umsg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task RunWithTypingIntheBackgorund(Func<Task> someFUnc, IUserMessage ctx)
 | 
			
		||||
        {
 | 
			
		||||
            var cancelSource = new CancellationTokenSource();
 | 
			
		||||
            var cancelToken = cancelSource.Token;
 | 
			
		||||
            var t = Task.Run(async () => 
 | 
			
		||||
            {
 | 
			
		||||
                while (!cancelToken.IsCancellationRequested)
 | 
			
		||||
                {
 | 
			
		||||
                    await Task.Delay(10000);
 | 
			
		||||
                    await ctx.Channel.TriggerTypingAsync();
 | 
			
		||||
                }
 | 
			
		||||
            }, cancelToken);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await someFUnc();
 | 
			
		||||
            }
 | 
			
		||||
            finally { cancelSource.Cancel(); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,8 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
{
 | 
			
		||||
    public interface IUnitOfWork : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        NadekoContext _context { get; }
 | 
			
		||||
 | 
			
		||||
        IQuoteRepository Quotes { get; }
 | 
			
		||||
        IGuildConfigRepository GuildConfigs { get; }
 | 
			
		||||
        IDonatorsRepository Donators { get; }
 | 
			
		||||
@@ -18,6 +20,10 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        IBotConfigRepository BotConfig { get; }
 | 
			
		||||
        IRepeaterRepository Repeaters { get; }
 | 
			
		||||
        IUnitConverterRepository ConverterUnits { get; }
 | 
			
		||||
        ICustomReactionRepository CustomReactions { get; }
 | 
			
		||||
        ICurrencyRepository Currency { get; }
 | 
			
		||||
        ITypingArticlesRepository TypingArticles { get; }
 | 
			
		||||
        IMusicPlaylistRepository MusicPlaylists { get; }
 | 
			
		||||
 | 
			
		||||
        int Complete();
 | 
			
		||||
        Task<int> CompleteAsync();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								src/NadekoBot/Services/Database/Models/CustomReaction.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/NadekoBot/Services/Database/Models/CustomReaction.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.ComponentModel.DataAnnotations.Schema;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Models
 | 
			
		||||
{
 | 
			
		||||
    public class CustomReaction : DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public ulong? GuildId { get; set; }
 | 
			
		||||
        [NotMapped]
 | 
			
		||||
        public Regex Regex { get; set; }
 | 
			
		||||
        public string Response { get; set; }
 | 
			
		||||
        public string Trigger { get; set; }
 | 
			
		||||
        public bool IsRegex { get; set; }
 | 
			
		||||
        public override string ToString() => $"Id: {Id}\nTrigger: {Trigger}\n Regex: {IsRegex}";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ReactionResponse : DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public bool OwnerOnly { get; set; }
 | 
			
		||||
        public string Text { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,6 +23,7 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        public DbSet<ConvertUnit> ConversionUnits { get; set; }
 | 
			
		||||
        public DbSet<TypingArticle> TypingArticles { get; set; }
 | 
			
		||||
        public DbSet<MusicPlaylist> MusicPlaylists { get; set; }
 | 
			
		||||
        public DbSet<CustomReaction> CustomReactions { get; set; }
 | 
			
		||||
 | 
			
		||||
        //logging
 | 
			
		||||
        public DbSet<LogSetting> LogSettings { get; set; }
 | 
			
		||||
@@ -60,7 +61,8 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
                    new ModulePrefix() { ModuleName = "Gambling", Prefix = "$" },
 | 
			
		||||
                    new ModulePrefix() { ModuleName = "Permissions", Prefix = ";" },
 | 
			
		||||
                    new ModulePrefix() { ModuleName = "Pokemon", Prefix = ">" },
 | 
			
		||||
                    new ModulePrefix() { ModuleName = "Utility", Prefix = "." }
 | 
			
		||||
                    new ModulePrefix() { ModuleName = "Utility", Prefix = "." },
 | 
			
		||||
                    new ModulePrefix() { ModuleName = "CustomReactions", Prefix = "." }
 | 
			
		||||
                });
 | 
			
		||||
                bc.RaceAnimals.AddRange(new HashSet<RaceAnimal>
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
{
 | 
			
		||||
    public interface ICustomReactionRepository : IRepository<CustomReaction>
 | 
			
		||||
    {
 | 
			
		||||
        List<CustomReaction> GetList();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
{
 | 
			
		||||
    public class CustomReactionsRepository : Repository<CustomReaction>, ICustomReactionRepository
 | 
			
		||||
    {
 | 
			
		||||
        public CustomReactionsRepository(DbContext context) : base(context)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public List<CustomReaction> GetList()
 | 
			
		||||
        {
 | 
			
		||||
            return _set.Include(x => x.Responses).ToList();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,7 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
{
 | 
			
		||||
    public class UnitOfWork : IUnitOfWork
 | 
			
		||||
    {
 | 
			
		||||
        public NadekoContext _context;
 | 
			
		||||
        public NadekoContext _context { get; }
 | 
			
		||||
 | 
			
		||||
        private IQuoteRepository _quotes;
 | 
			
		||||
        public IQuoteRepository Quotes => _quotes ?? (_quotes = new QuoteRepository(_context));
 | 
			
		||||
@@ -48,6 +48,9 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        private IMusicPlaylistRepository _musicPlaylists;
 | 
			
		||||
        public IMusicPlaylistRepository MusicPlaylists => _musicPlaylists ?? (_musicPlaylists = new MusicPlaylistRepository(_context));
 | 
			
		||||
 | 
			
		||||
        private ICustomReactionRepository _customReactions;
 | 
			
		||||
        public ICustomReactionRepository CustomReactions => _customReactions ?? (_customReactions = new CustomReactionsRepository(_context));
 | 
			
		||||
 | 
			
		||||
        public UnitOfWork(NadekoContext context)
 | 
			
		||||
        {
 | 
			
		||||
            _context = context;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,10 +36,10 @@ namespace NadekoBot.Services
 | 
			
		||||
        public NadekoContext GetDbContext() => 
 | 
			
		||||
            Activator.CreateInstance(dbType) as NadekoContext;
 | 
			
		||||
 | 
			
		||||
        public UnitOfWork GetUnitOfWork() =>
 | 
			
		||||
        public IUnitOfWork GetUnitOfWork() =>
 | 
			
		||||
            new UnitOfWork(GetDbContext());
 | 
			
		||||
 | 
			
		||||
        public static UnitOfWork UnitOfWork() =>
 | 
			
		||||
        public static IUnitOfWork UnitOfWork() =>
 | 
			
		||||
            DbHandler.Instance.GetUnitOfWork();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,11 @@ namespace NadekoBot.Services.Impl
 | 
			
		||||
                    Db = new DB(cm.Db.Type, cm.Db.ConnectionString);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                _log.Fatal("credentials.json is missing. Failed to start.");
 | 
			
		||||
            {
 | 
			
		||||
                File.WriteAllText("./credentials_example.json", JsonConvert.SerializeObject(new CredentialsModel(), Formatting.Indented));
 | 
			
		||||
                _log.Fatal($"credentials.json is missing. Failed to start. Example written to {Path.GetFullPath("./credentials_example.json")}");
 | 
			
		||||
                throw new FileNotFoundException();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private class CredentialsModel
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user