Work on custom reactions, fixed -modules

This commit is contained in:
Kwoth 2016-10-08 04:25:12 +02:00
parent 8dbc7075da
commit 895727d052
10 changed files with 218 additions and 29 deletions

View 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);
}
}
}

View File

@ -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.`") 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); .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] [NadekoCommand, Usage, Description, Aliases]

View File

@ -9,6 +9,8 @@ namespace NadekoBot.Services.Database
{ {
public interface IUnitOfWork : IDisposable public interface IUnitOfWork : IDisposable
{ {
NadekoContext _context { get; }
IQuoteRepository Quotes { get; } IQuoteRepository Quotes { get; }
IGuildConfigRepository GuildConfigs { get; } IGuildConfigRepository GuildConfigs { get; }
IDonatorsRepository Donators { get; } IDonatorsRepository Donators { get; }
@ -18,6 +20,10 @@ namespace NadekoBot.Services.Database
IBotConfigRepository BotConfig { get; } IBotConfigRepository BotConfig { get; }
IRepeaterRepository Repeaters { get; } IRepeaterRepository Repeaters { get; }
IUnitConverterRepository ConverterUnits { get; } IUnitConverterRepository ConverterUnits { get; }
ICustomReactionRepository CustomReactions { get; }
ICurrencyRepository Currency { get; }
ITypingArticlesRepository TypingArticles { get; }
IMusicPlaylistRepository MusicPlaylists { get; }
int Complete(); int Complete();
Task<int> CompleteAsync(); Task<int> CompleteAsync();

View 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; }
}
}

View File

@ -23,6 +23,7 @@ namespace NadekoBot.Services.Database
public DbSet<ConvertUnit> ConversionUnits { get; set; } public DbSet<ConvertUnit> ConversionUnits { get; set; }
public DbSet<TypingArticle> TypingArticles { get; set; } public DbSet<TypingArticle> TypingArticles { get; set; }
public DbSet<MusicPlaylist> MusicPlaylists { get; set; } public DbSet<MusicPlaylist> MusicPlaylists { get; set; }
public DbSet<CustomReaction> CustomReactions { get; set; }
//logging //logging
public DbSet<LogSetting> LogSettings { get; set; } public DbSet<LogSetting> LogSettings { get; set; }
@ -60,7 +61,8 @@ namespace NadekoBot.Services.Database
new ModulePrefix() { ModuleName = "Gambling", Prefix = "$" }, new ModulePrefix() { ModuleName = "Gambling", Prefix = "$" },
new ModulePrefix() { ModuleName = "Permissions", Prefix = ";" }, new ModulePrefix() { ModuleName = "Permissions", Prefix = ";" },
new ModulePrefix() { ModuleName = "Pokemon", 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> bc.RaceAnimals.AddRange(new HashSet<RaceAnimal>
{ {

View File

@ -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();
}
}

View File

@ -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();
}
}
}

View File

@ -10,7 +10,7 @@ namespace NadekoBot.Services.Database
{ {
public class UnitOfWork : IUnitOfWork public class UnitOfWork : IUnitOfWork
{ {
public NadekoContext _context; public NadekoContext _context { get; }
private IQuoteRepository _quotes; private IQuoteRepository _quotes;
public IQuoteRepository Quotes => _quotes ?? (_quotes = new QuoteRepository(_context)); public IQuoteRepository Quotes => _quotes ?? (_quotes = new QuoteRepository(_context));
@ -48,6 +48,9 @@ namespace NadekoBot.Services.Database
private IMusicPlaylistRepository _musicPlaylists; private IMusicPlaylistRepository _musicPlaylists;
public IMusicPlaylistRepository MusicPlaylists => _musicPlaylists ?? (_musicPlaylists = new MusicPlaylistRepository(_context)); public IMusicPlaylistRepository MusicPlaylists => _musicPlaylists ?? (_musicPlaylists = new MusicPlaylistRepository(_context));
private ICustomReactionRepository _customReactions;
public ICustomReactionRepository CustomReactions => _customReactions ?? (_customReactions = new CustomReactionsRepository(_context));
public UnitOfWork(NadekoContext context) public UnitOfWork(NadekoContext context)
{ {
_context = context; _context = context;

View File

@ -36,10 +36,10 @@ namespace NadekoBot.Services
public NadekoContext GetDbContext() => public NadekoContext GetDbContext() =>
Activator.CreateInstance(dbType) as NadekoContext; Activator.CreateInstance(dbType) as NadekoContext;
public UnitOfWork GetUnitOfWork() => public IUnitOfWork GetUnitOfWork() =>
new UnitOfWork(GetDbContext()); new UnitOfWork(GetDbContext());
public static UnitOfWork UnitOfWork() => public static IUnitOfWork UnitOfWork() =>
DbHandler.Instance.GetUnitOfWork(); DbHandler.Instance.GetUnitOfWork();
} }
} }

View File

@ -49,7 +49,11 @@ namespace NadekoBot.Services.Impl
Db = new DB(cm.Db.Type, cm.Db.ConnectionString); Db = new DB(cm.Db.Type, cm.Db.ConnectionString);
} }
else 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 private class CredentialsModel