mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 01:38:27 -04:00
- Started cleanup of command handler
- Removed IUnloadableService - Started removing INService (removed it from services which implement behavior interfaces) - wip - Added scrutor for better service registration - wip
This commit is contained in:
@@ -28,32 +28,29 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot
|
namespace NadekoBot
|
||||||
{
|
{
|
||||||
// todo remove all migration code from
|
public sealed class Bot
|
||||||
// todo read prev commit
|
|
||||||
public class Bot
|
|
||||||
{
|
{
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
public DiscordSocketClient Client { get; }
|
private readonly CommandService _commandService;
|
||||||
public CommandService CommandService { get; }
|
|
||||||
|
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
private readonly BotCredsProvider _credsProvider;
|
||||||
|
|
||||||
|
public event Func<GuildConfig, Task> JoinedGuild = delegate { return Task.CompletedTask; };
|
||||||
|
|
||||||
|
public DiscordSocketClient Client { get; }
|
||||||
public ImmutableArray<GuildConfig> AllGuildConfigs { get; private set; }
|
public ImmutableArray<GuildConfig> AllGuildConfigs { get; private set; }
|
||||||
|
|
||||||
|
// todo change configs to records
|
||||||
// todo remove colors from here
|
// todo remove colors from here
|
||||||
public static Color OkColor { get; set; }
|
public static Color OkColor { get; set; }
|
||||||
public static Color ErrorColor { get; set; }
|
public static Color ErrorColor { get; set; }
|
||||||
public static Color PendingColor { get; set; }
|
public static Color PendingColor { get; set; }
|
||||||
|
|
||||||
// todo remove ready prop
|
private IServiceProvider Services { get; set; }
|
||||||
public TaskCompletionSource<bool> Ready { get; private set; } = new TaskCompletionSource<bool>();
|
|
||||||
|
|
||||||
public IServiceProvider Services { get; private set; }
|
|
||||||
|
|
||||||
public string Mention { get; set; }
|
public string Mention { get; private set; }
|
||||||
|
public bool IsReady { get; private set; }
|
||||||
|
|
||||||
public event Func<GuildConfig, Task> JoinedGuild = delegate { return Task.CompletedTask; };
|
|
||||||
|
|
||||||
private readonly BotCredsProvider _credsProvider;
|
|
||||||
public Bot(int shardId, int? totalShards)
|
public Bot(int shardId, int? totalShards)
|
||||||
{
|
{
|
||||||
if (shardId < 0)
|
if (shardId < 0)
|
||||||
@@ -80,7 +77,7 @@ namespace NadekoBot
|
|||||||
ExclusiveBulkDelete = true,
|
ExclusiveBulkDelete = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
CommandService = new CommandService(new CommandServiceConfig()
|
_commandService = new CommandService(new CommandServiceConfig()
|
||||||
{
|
{
|
||||||
CaseSensitiveCommands = false,
|
CaseSensitiveCommands = false,
|
||||||
DefaultRunMode = RunMode.Sync,
|
DefaultRunMode = RunMode.Sync,
|
||||||
@@ -96,12 +93,6 @@ namespace NadekoBot
|
|||||||
return Client.Guilds.Select(x => x.Id).ToList();
|
return Client.Guilds.Select(x => x.Id).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<GuildConfig> GetCurrentGuildConfigs()
|
|
||||||
{
|
|
||||||
using var uow = _db.GetDbContext();
|
|
||||||
return uow.GuildConfigs.GetAllGuildConfigs(GetCurrentGuildIds()).ToImmutableArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddServices()
|
private void AddServices()
|
||||||
{
|
{
|
||||||
var startingGuildIdList = GetCurrentGuildIds();
|
var startingGuildIdList = GetCurrentGuildIds();
|
||||||
@@ -119,7 +110,7 @@ namespace NadekoBot
|
|||||||
.AddSingleton(_db) // database
|
.AddSingleton(_db) // database
|
||||||
.AddRedis(_creds.RedisOptions) // redis
|
.AddRedis(_creds.RedisOptions) // redis
|
||||||
.AddSingleton(Client) // discord socket client
|
.AddSingleton(Client) // discord socket client
|
||||||
.AddSingleton(CommandService)
|
.AddSingleton(_commandService)
|
||||||
.AddSingleton(this) // pepega
|
.AddSingleton(this) // pepega
|
||||||
.AddSingleton<IDataCache, RedisCache>()
|
.AddSingleton<IDataCache, RedisCache>()
|
||||||
.AddSingleton<ISeria, JsonSeria>()
|
.AddSingleton<ISeria, JsonSeria>()
|
||||||
@@ -130,6 +121,7 @@ namespace NadekoBot
|
|||||||
.AddConfigMigrators() // todo remove config migrators
|
.AddConfigMigrators() // todo remove config migrators
|
||||||
.AddMemoryCache()
|
.AddMemoryCache()
|
||||||
.AddSingleton<IShopService, ShopService>()
|
.AddSingleton<IShopService, ShopService>()
|
||||||
|
.AddSingleton<IBehaviourExecutor, BehaviorExecutor>()
|
||||||
// music
|
// music
|
||||||
.AddMusic()
|
.AddMusic()
|
||||||
;
|
;
|
||||||
@@ -152,9 +144,27 @@ namespace NadekoBot
|
|||||||
.AddSingleton<IReadyExecutor>(x => (IReadyExecutor)x.GetRequiredService<ICoordinator>());
|
.AddSingleton<IReadyExecutor>(x => (IReadyExecutor)x.GetRequiredService<ICoordinator>());
|
||||||
}
|
}
|
||||||
|
|
||||||
svcs.AddSingleton<IReadyExecutor>(x => x.GetService<SelfService>());
|
svcs.Scan(scan => scan
|
||||||
svcs.AddSingleton<IReadyExecutor>(x => x.GetService<CustomReactionsService>());
|
.FromAssemblyOf<IReadyExecutor>()
|
||||||
svcs.AddSingleton<IReadyExecutor>(x => x.GetService<RepeaterService>());
|
.AddClasses(classes => classes.AssignableTo<IReadyExecutor>())
|
||||||
|
.AsSelf()
|
||||||
|
.AsImplementedInterfaces()
|
||||||
|
.WithSingletonLifetime()
|
||||||
|
|
||||||
|
// behaviours
|
||||||
|
.AddClasses(classes => classes.AssignableToAny(
|
||||||
|
typeof(IEarlyBehavior),
|
||||||
|
typeof(ILateBlocker),
|
||||||
|
typeof(IInputTransformer),
|
||||||
|
typeof(ILateExecutor)))
|
||||||
|
.AsSelf()
|
||||||
|
.AsImplementedInterfaces()
|
||||||
|
.WithSingletonLifetime()
|
||||||
|
);
|
||||||
|
|
||||||
|
// svcs.AddSingleton<IReadyExecutor>(x => x.GetService<SelfService>());
|
||||||
|
// svcs.AddSingleton<IReadyExecutor>(x => x.GetService<CustomReactionsService>());
|
||||||
|
// svcs.AddSingleton<IReadyExecutor>(x => x.GetService<RepeaterService>());
|
||||||
|
|
||||||
//initialize Services
|
//initialize Services
|
||||||
Services = svcs.BuildServiceProvider();
|
Services = svcs.BuildServiceProvider();
|
||||||
@@ -164,9 +174,7 @@ namespace NadekoBot
|
|||||||
{
|
{
|
||||||
ApplyConfigMigrations();
|
ApplyConfigMigrations();
|
||||||
}
|
}
|
||||||
|
|
||||||
//what the fluff
|
|
||||||
commandHandler.AddServices(svcs);
|
|
||||||
_ = LoadTypeReaders(typeof(Bot).Assembly);
|
_ = LoadTypeReaders(typeof(Bot).Assembly);
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
@@ -204,10 +212,10 @@ namespace NadekoBot
|
|||||||
var toReturn = new List<object>();
|
var toReturn = new List<object>();
|
||||||
foreach (var ft in filteredTypes)
|
foreach (var ft in filteredTypes)
|
||||||
{
|
{
|
||||||
var x = (TypeReader)Activator.CreateInstance(ft, Client, CommandService);
|
var x = (TypeReader)Activator.CreateInstance(ft, Client, _commandService);
|
||||||
var baseType = ft.BaseType;
|
var baseType = ft.BaseType;
|
||||||
var typeArgs = baseType.GetGenericArguments();
|
var typeArgs = baseType.GetGenericArguments();
|
||||||
CommandService.AddTypeReader(typeArgs[0], x);
|
_commandService.AddTypeReader(typeArgs[0], x);
|
||||||
toReturn.Add(x);
|
toReturn.Add(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,10 +242,6 @@ namespace NadekoBot
|
|||||||
{
|
{
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -325,7 +329,7 @@ namespace NadekoBot
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
HandleStatusChanges();
|
HandleStatusChanges();
|
||||||
Ready.TrySetResult(true);
|
IsReady = true;
|
||||||
_ = Task.Run(ExecuteReadySubscriptions);
|
_ = Task.Run(ExecuteReadySubscriptions);
|
||||||
Log.Information("Shard {ShardId} ready", Client.ShardId);
|
Log.Information("Shard {ShardId} ready", Client.ShardId);
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.Common.ModuleBehaviors
|
||||||
{
|
{
|
||||||
@@ -12,7 +11,7 @@ namespace NadekoBot.Common.ModuleBehaviors
|
|||||||
int Priority { get; }
|
int Priority { get; }
|
||||||
ModuleBehaviorType BehaviorType { get; }
|
ModuleBehaviorType BehaviorType { get; }
|
||||||
|
|
||||||
Task<bool> RunBehavior(DiscordSocketClient client, IGuild guild, IUserMessage msg);
|
Task<bool> RunBehavior(IGuild guild, IUserMessage msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ModuleBehaviorType
|
public enum ModuleBehaviorType
|
||||||
|
@@ -8,7 +8,6 @@ namespace NadekoBot.Common.ModuleBehaviors
|
|||||||
{
|
{
|
||||||
public int Priority { get; }
|
public int Priority { get; }
|
||||||
|
|
||||||
Task<bool> TryBlockLate(DiscordSocketClient client, ICommandContext context,
|
Task<bool> TryBlockLate(ICommandContext context, string moduleName, CommandInfo command);
|
||||||
string moduleName, CommandInfo command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common.ModuleBehaviors
|
namespace NadekoBot.Common.ModuleBehaviors
|
||||||
{
|
{
|
||||||
@@ -9,6 +8,6 @@ namespace NadekoBot.Common.ModuleBehaviors
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ILateExecutor
|
public interface ILateExecutor
|
||||||
{
|
{
|
||||||
Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg);
|
Task LateExecute(IGuild guild, IUserMessage msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -142,8 +142,7 @@ namespace NadekoBot.Modules.Administration.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryBlockLate(DiscordSocketClient client, ICommandContext context, string moduleName,
|
public async Task<bool> TryBlockLate(ICommandContext context, string moduleName, CommandInfo command)
|
||||||
CommandInfo command)
|
|
||||||
{
|
{
|
||||||
if (TryGetOverrides(context.Guild?.Id ?? 0, command.Name, out var perm) && perm is not null)
|
if (TryGetOverrides(context.Guild?.Id ?? 0, command.Name, out var perm) && perm is not null)
|
||||||
{
|
{
|
||||||
|
@@ -18,7 +18,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Services
|
namespace NadekoBot.Modules.Administration.Services
|
||||||
{
|
{
|
||||||
public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
|
public sealed class SelfService : ILateExecutor, IReadyExecutor
|
||||||
{
|
{
|
||||||
private readonly ConnectionMultiplexer _redis;
|
private readonly ConnectionMultiplexer _redis;
|
||||||
private readonly CommandHandler _cmdHandler;
|
private readonly CommandHandler _cmdHandler;
|
||||||
@@ -54,6 +54,7 @@ namespace NadekoBot.Modules.Administration.Services
|
|||||||
_httpFactory = factory;
|
_httpFactory = factory;
|
||||||
_bss = bss;
|
_bss = bss;
|
||||||
|
|
||||||
|
Log.Information("Self service created");
|
||||||
var sub = _redis.GetSubscriber();
|
var sub = _redis.GetSubscriber();
|
||||||
if (_client.ShardId == 0)
|
if (_client.ShardId == 0)
|
||||||
{
|
{
|
||||||
@@ -226,7 +227,7 @@ namespace NadekoBot.Modules.Administration.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
// forwards dms
|
// forwards dms
|
||||||
public async Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
public async Task LateExecute(IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
var bs = _bss.Data;
|
var bs = _bss.Data;
|
||||||
if (msg.Channel is IDMChannel && _bss.Data.ForwardMessages && ownerChannels.Any())
|
if (msg.Channel is IDMChannel && _bss.Data.ForwardMessages && ownerChannels.Any())
|
||||||
|
@@ -22,7 +22,7 @@ using YamlDotNet.Serialization;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.CustomReactions.Services
|
namespace NadekoBot.Modules.CustomReactions.Services
|
||||||
{
|
{
|
||||||
public sealed class CustomReactionsService : IEarlyBehavior, INService, IReadyExecutor
|
public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor
|
||||||
{
|
{
|
||||||
public enum CrField
|
public enum CrField
|
||||||
{
|
{
|
||||||
@@ -77,6 +77,7 @@ namespace NadekoBot.Modules.CustomReactions.Services
|
|||||||
_pubSub = pubSub;
|
_pubSub = pubSub;
|
||||||
_rng = new NadekoRandom();
|
_rng = new NadekoRandom();
|
||||||
|
|
||||||
|
Log.Information("Custom reaction service created");
|
||||||
_pubSub.Sub(_crsReloadedKey, OnCrsShouldReload);
|
_pubSub.Sub(_crsReloadedKey, OnCrsShouldReload);
|
||||||
pubSub.Sub(_gcrAddedKey, OnGcrAdded);
|
pubSub.Sub(_gcrAddedKey, OnGcrAdded);
|
||||||
pubSub.Sub(_gcrDeletedkey, OnGcrDeleted);
|
pubSub.Sub(_gcrDeletedkey, OnGcrDeleted);
|
||||||
@@ -380,7 +381,7 @@ namespace NadekoBot.Modules.CustomReactions.Services
|
|||||||
return result[_rng.Next(0, result.Count)];
|
return result[_rng.Next(0, result.Count)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RunBehavior(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
public async Task<bool> RunBehavior(IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
// maybe this message is a custom reaction
|
// maybe this message is a custom reaction
|
||||||
var cr = TryGetCustomReaction(msg);
|
var cr = TryGetCustomReaction(msg);
|
||||||
|
@@ -5,17 +5,8 @@ using NadekoBot.Modules.Gambling.Common.AnimalRacing;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Gambling.Services
|
namespace NadekoBot.Modules.Gambling.Services
|
||||||
{
|
{
|
||||||
public class AnimalRaceService : INService, IUnloadableService
|
public class AnimalRaceService : INService
|
||||||
{
|
{
|
||||||
public ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
public ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
||||||
|
|
||||||
public Task Unload()
|
|
||||||
{
|
|
||||||
foreach (var kvp in AnimalRaces)
|
|
||||||
{
|
|
||||||
try { kvp.Value.Dispose(); } catch { }
|
|
||||||
}
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Games.Services
|
namespace NadekoBot.Modules.Games.Services
|
||||||
{
|
{
|
||||||
public class ChatterBotService : IEarlyBehavior, INService
|
public class ChatterBotService : IEarlyBehavior
|
||||||
{
|
{
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly PermissionService _perms;
|
private readonly PermissionService _perms;
|
||||||
@@ -103,7 +103,7 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RunBehavior(DiscordSocketClient client, IGuild guild, IUserMessage usrMsg)
|
public async Task<bool> RunBehavior(IGuild guild, IUserMessage usrMsg)
|
||||||
{
|
{
|
||||||
if (!(guild is SocketGuild sg))
|
if (!(guild is SocketGuild sg))
|
||||||
return false;
|
return false;
|
||||||
|
@@ -21,7 +21,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Games.Services
|
namespace NadekoBot.Modules.Games.Services
|
||||||
{
|
{
|
||||||
public class GamesService : INService, IUnloadableService
|
public class GamesService : INService
|
||||||
{
|
{
|
||||||
private readonly GamesConfigService _gamesConfig;
|
private readonly GamesConfigService _gamesConfig;
|
||||||
|
|
||||||
@@ -101,26 +101,6 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Unload()
|
|
||||||
{
|
|
||||||
_t.Change(Timeout.Infinite, Timeout.Infinite);
|
|
||||||
|
|
||||||
AcrophobiaGames.ForEach(x => x.Value.Dispose());
|
|
||||||
AcrophobiaGames.Clear();
|
|
||||||
HangmanGames.ForEach(x => x.Value.Dispose());
|
|
||||||
HangmanGames.Clear();
|
|
||||||
await Task.WhenAll(RunningTrivias.Select(x => x.Value.StopGame())).ConfigureAwait(false);
|
|
||||||
RunningTrivias.Clear();
|
|
||||||
|
|
||||||
TicTacToeGames.Clear();
|
|
||||||
|
|
||||||
await Task.WhenAll(RunningContests.Select(x => x.Value.Stop()))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
RunningContests.Clear();
|
|
||||||
NunchiGames.ForEach(x => x.Value.Dispose());
|
|
||||||
NunchiGames.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddTypingArticle(IUser user, string text)
|
public void AddTypingArticle(IUser user, string text)
|
||||||
{
|
{
|
||||||
TypingArticles.Add(new TypingArticle
|
TypingArticles.Add(new TypingArticle
|
||||||
|
@@ -3,7 +3,6 @@ using System.Collections.Concurrent;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
using NadekoBot.Modules.Games.Common;
|
using NadekoBot.Modules.Games.Common;
|
||||||
using NadekoBot.Db.Models;
|
using NadekoBot.Db.Models;
|
||||||
@@ -16,7 +15,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Games.Services
|
namespace NadekoBot.Modules.Games.Services
|
||||||
{
|
{
|
||||||
public class PollService : IEarlyBehavior, INService
|
public class PollService : IEarlyBehavior
|
||||||
{
|
{
|
||||||
public ConcurrentDictionary<ulong, PollRunner> ActivePolls { get; } = new ConcurrentDictionary<ulong, PollRunner>();
|
public ConcurrentDictionary<ulong, PollRunner> ActivePolls { get; } = new ConcurrentDictionary<ulong, PollRunner>();
|
||||||
|
|
||||||
@@ -106,7 +105,7 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
|
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RunBehavior(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
public async Task<bool> RunBehavior(IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
if (guild is null)
|
if (guild is null)
|
||||||
return false;
|
return false;
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
|
||||||
using System;
|
using System;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
@@ -40,7 +39,7 @@ namespace NadekoBot.Modules.Help.Services
|
|||||||
.Build();
|
.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
public Task LateExecute(IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
var settings = _bss.Data;
|
var settings = _bss.Data;
|
||||||
if (guild is null)
|
if (guild is null)
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
@@ -12,7 +11,7 @@ using NadekoBot.Db;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Permissions.Services
|
namespace NadekoBot.Modules.Permissions.Services
|
||||||
{
|
{
|
||||||
public sealed class BlacklistService : IEarlyBehavior, INService
|
public sealed class BlacklistService : IEarlyBehavior
|
||||||
{
|
{
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly IPubSub _pubSub;
|
private readonly IPubSub _pubSub;
|
||||||
@@ -39,7 +38,7 @@ namespace NadekoBot.Modules.Permissions.Services
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> RunBehavior(DiscordSocketClient _, IGuild guild, IUserMessage usrMsg)
|
public Task<bool> RunBehavior(IGuild guild, IUserMessage usrMsg)
|
||||||
{
|
{
|
||||||
foreach (var bl in _blacklist)
|
foreach (var bl in _blacklist)
|
||||||
{
|
{
|
||||||
|
@@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Permissions.Services
|
|||||||
return Task.FromResult(false);
|
return Task.FromResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> TryBlockLate(DiscordSocketClient client, ICommandContext ctx, string moduleName, CommandInfo command)
|
public Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||||
{
|
{
|
||||||
var guild = ctx.Guild;
|
var guild = ctx.Guild;
|
||||||
var user = ctx.User;
|
var user = ctx.User;
|
||||||
|
@@ -17,7 +17,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Permissions.Services
|
namespace NadekoBot.Modules.Permissions.Services
|
||||||
{
|
{
|
||||||
public class FilterService : IEarlyBehavior, INService
|
public class FilterService : IEarlyBehavior
|
||||||
{
|
{
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
@@ -117,13 +117,13 @@ namespace NadekoBot.Modules.Permissions.Services
|
|||||||
if (guild is null || usrMsg is null)
|
if (guild is null || usrMsg is null)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
return RunBehavior(null, guild, usrMsg);
|
return RunBehavior(guild, usrMsg);
|
||||||
});
|
});
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RunBehavior(DiscordSocketClient _, IGuild guild, IUserMessage msg)
|
public async Task<bool> RunBehavior(IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
if (!(msg.Author is IGuildUser gu) || gu.GuildPermissions.Administrator)
|
if (!(msg.Author is IGuildUser gu) || gu.GuildPermissions.Administrator)
|
||||||
return false;
|
return false;
|
||||||
|
@@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Permissions.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Task<bool> TryBlockLate(DiscordSocketClient client, ICommandContext ctx, string moduleName, CommandInfo command)
|
public Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||||
{
|
{
|
||||||
var settings = _bss.Data;
|
var settings = _bss.Data;
|
||||||
var commandName = command.Name.ToLowerInvariant();
|
var commandName = command.Name.ToLowerInvariant();
|
||||||
|
@@ -98,8 +98,7 @@ namespace NadekoBot.Modules.Permissions.Services
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryBlockLate(DiscordSocketClient client, ICommandContext ctx, string moduleName,
|
public async Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||||
CommandInfo command)
|
|
||||||
{
|
{
|
||||||
var guild = ctx.Guild;
|
var guild = ctx.Guild;
|
||||||
var msg = ctx.Message;
|
var msg = ctx.Message;
|
||||||
|
@@ -31,7 +31,7 @@ using Image = SixLabors.ImageSharp.Image;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Searches.Services
|
namespace NadekoBot.Modules.Searches.Services
|
||||||
{
|
{
|
||||||
public class SearchesService : INService, IUnloadableService
|
public class SearchesService : INService
|
||||||
{
|
{
|
||||||
private readonly IHttpClientFactory _httpFactory;
|
private readonly IHttpClientFactory _httpFactory;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
@@ -482,19 +482,6 @@ namespace NadekoBot.Modules.Searches.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Unload()
|
|
||||||
{
|
|
||||||
AutoBoobTimers.ForEach(x => x.Value.Change(Timeout.Infinite, Timeout.Infinite));
|
|
||||||
AutoBoobTimers.Clear();
|
|
||||||
AutoButtTimers.ForEach(x => x.Value.Change(Timeout.Infinite, Timeout.Infinite));
|
|
||||||
AutoButtTimers.Clear();
|
|
||||||
AutoHentaiTimers.ForEach(x => x.Value.Change(Timeout.Infinite, Timeout.Infinite));
|
|
||||||
AutoHentaiTimers.Clear();
|
|
||||||
|
|
||||||
_imageCacher.Clear();
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<MtgData> GetMtgCardAsync(string search)
|
public async Task<MtgData> GetMtgCardAsync(string search)
|
||||||
{
|
{
|
||||||
search = search.Trim().ToLowerInvariant();
|
search = search.Trim().ToLowerInvariant();
|
||||||
|
@@ -13,7 +13,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Utility.Services
|
namespace NadekoBot.Modules.Utility.Services
|
||||||
{
|
{
|
||||||
public class ConverterService : INService, IUnloadableService
|
public class ConverterService : INService
|
||||||
{
|
{
|
||||||
public ConvertUnit[] Units =>
|
public ConvertUnit[] Units =>
|
||||||
_cache.Redis.GetDatabase()
|
_cache.Redis.GetDatabase()
|
||||||
@@ -87,12 +87,6 @@ namespace NadekoBot.Modules.Utility.Services
|
|||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Unload()
|
|
||||||
{
|
|
||||||
_currencyUpdater?.Change(Timeout.Infinite, Timeout.Infinite);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Rates
|
public class Rates
|
||||||
|
@@ -16,7 +16,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Utility.Services
|
namespace NadekoBot.Modules.Utility.Services
|
||||||
{
|
{
|
||||||
public class PatreonRewardsService : INService, IUnloadableService
|
public class PatreonRewardsService : INService
|
||||||
{
|
{
|
||||||
private readonly SemaphoreSlim getPledgesLocker = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim getPledgesLocker = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
@@ -218,11 +218,5 @@ namespace NadekoBot.Modules.Utility.Services
|
|||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Unload()
|
|
||||||
{
|
|
||||||
_updater?.Change(Timeout.Infinite, Timeout.Infinite);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Utility.Services
|
namespace NadekoBot.Modules.Utility.Services
|
||||||
{
|
{
|
||||||
public sealed class RepeaterService : IReadyExecutor, INService
|
public sealed class RepeaterService : IReadyExecutor
|
||||||
{
|
{
|
||||||
public const int MAX_REPEATERS = 5;
|
public const int MAX_REPEATERS = 5;
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ using Serilog;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Utility.Services
|
namespace NadekoBot.Modules.Utility.Services
|
||||||
{
|
{
|
||||||
public class StreamRoleService : INService, IUnloadableService
|
public class StreamRoleService : INService
|
||||||
{
|
{
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
@@ -48,12 +48,6 @@ namespace NadekoBot.Modules.Utility.Services
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Unload()
|
|
||||||
{
|
|
||||||
_client.GuildMemberUpdated -= Client_GuildMemberUpdated;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task Client_GuildMemberUpdated(SocketGuildUser before, SocketGuildUser after)
|
private Task Client_GuildMemberUpdated(SocketGuildUser before, SocketGuildUser after)
|
||||||
{
|
{
|
||||||
var _ = Task.Run(async () =>
|
var _ = Task.Run(async () =>
|
||||||
|
@@ -11,7 +11,7 @@ using NadekoBot.Modules.Administration;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Utility.Services
|
namespace NadekoBot.Modules.Utility.Services
|
||||||
{
|
{
|
||||||
public class VerboseErrorsService : INService, IUnloadableService
|
public class VerboseErrorsService : INService
|
||||||
{
|
{
|
||||||
private readonly ConcurrentHashSet<ulong> guildsEnabled;
|
private readonly ConcurrentHashSet<ulong> guildsEnabled;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
@@ -32,12 +32,6 @@ namespace NadekoBot.Modules.Utility.Services
|
|||||||
.Select(x => x.GuildId));
|
.Select(x => x.GuildId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Unload()
|
|
||||||
{
|
|
||||||
_ch.CommandErrored -= LogVerboseError;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LogVerboseError(CommandInfo cmd, ITextChannel channel, string reason)
|
private async Task LogVerboseError(CommandInfo cmd, ITextChannel channel, string reason)
|
||||||
{
|
{
|
||||||
if (channel is null || !guildsEnabled.Contains(channel.GuildId))
|
if (channel is null || !guildsEnabled.Contains(channel.GuildId))
|
||||||
|
@@ -28,7 +28,7 @@ using Image = SixLabors.ImageSharp.Image;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Xp.Services
|
namespace NadekoBot.Modules.Xp.Services
|
||||||
{
|
{
|
||||||
public class XpService : INService, IUnloadableService
|
public class XpService : INService
|
||||||
{
|
{
|
||||||
private enum NotifOf
|
private enum NotifOf
|
||||||
{
|
{
|
||||||
@@ -1182,14 +1182,6 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Unload()
|
|
||||||
{
|
|
||||||
_cmd.OnMessageNoTrigger -= _cmd_OnMessageNoTrigger;
|
|
||||||
_client.UserVoiceStateUpdated -= _client_OnUserVoiceStateUpdated;
|
|
||||||
_client.GuildAvailable -= _client_OnGuildAvailable;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void XpReset(ulong guildId, ulong userId)
|
public void XpReset(ulong guildId, ulong userId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using (var uow = _db.GetDbContext())
|
||||||
|
@@ -42,6 +42,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
|
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
<PackageReference Include="Scrutor" Version="3.3.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Seq" Version="5.0.1" />
|
<PackageReference Include="Serilog.Sinks.Seq" Version="5.0.1" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.3" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.3" />
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.Net;
|
using Discord.Net;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using NadekoBot.Common.Collections;
|
using NadekoBot.Common.Collections;
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
@@ -10,26 +9,16 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NadekoBot.Common.Configs;
|
using NadekoBot.Common.Configs;
|
||||||
using NadekoBot.Services;
|
|
||||||
using NadekoBot.Db;
|
using NadekoBot.Db;
|
||||||
using NadekoBot.Modules.Administration;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
public class GuildUserComparer : IEqualityComparer<IGuildUser>
|
|
||||||
{
|
|
||||||
public bool Equals(IGuildUser x, IGuildUser y) => x.Id == y.Id;
|
|
||||||
|
|
||||||
public int GetHashCode(IGuildUser obj) => obj.Id.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CommandHandler : INService
|
public class CommandHandler : INService
|
||||||
{
|
{
|
||||||
public const int GlobalCommandsCooldown = 750;
|
public const int GlobalCommandsCooldown = 750;
|
||||||
@@ -38,11 +27,8 @@ namespace NadekoBot.Services
|
|||||||
private readonly CommandService _commandService;
|
private readonly CommandService _commandService;
|
||||||
private readonly BotConfigService _bss;
|
private readonly BotConfigService _bss;
|
||||||
private readonly Bot _bot;
|
private readonly Bot _bot;
|
||||||
|
private readonly IBehaviourExecutor _behaviourExecutor;
|
||||||
private IServiceProvider _services;
|
private IServiceProvider _services;
|
||||||
private IEnumerable<IEarlyBehavior> _earlyBehaviors;
|
|
||||||
private IEnumerable<IInputTransformer> _inputTransformers;
|
|
||||||
private IEnumerable<ILateBlocker> _lateBlockers;
|
|
||||||
private IEnumerable<ILateExecutor> _lateExecutors;
|
|
||||||
|
|
||||||
private ConcurrentDictionary<ulong, string> _prefixes { get; } = new ConcurrentDictionary<ulong, string>();
|
private ConcurrentDictionary<ulong, string> _prefixes { get; } = new ConcurrentDictionary<ulong, string>();
|
||||||
|
|
||||||
@@ -56,17 +42,24 @@ namespace NadekoBot.Services
|
|||||||
public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>();
|
public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>();
|
||||||
private readonly Timer _clearUsersOnShortCooldown;
|
private readonly Timer _clearUsersOnShortCooldown;
|
||||||
|
|
||||||
public CommandHandler(DiscordSocketClient client, DbService db, CommandService commandService,
|
// todo move behaviours to a separate service
|
||||||
BotConfigService bss, Bot bot, IServiceProvider services)
|
public CommandHandler(
|
||||||
|
DiscordSocketClient client,
|
||||||
|
DbService db,
|
||||||
|
CommandService commandService,
|
||||||
|
BotConfigService bss,
|
||||||
|
Bot bot,
|
||||||
|
IBehaviourExecutor behaviourExecutor,
|
||||||
|
IServiceProvider services)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_commandService = commandService;
|
_commandService = commandService;
|
||||||
_bss = bss;
|
_bss = bss;
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
|
_behaviourExecutor = behaviourExecutor;
|
||||||
_db = db;
|
_db = db;
|
||||||
_services = services;
|
_services = services;
|
||||||
|
|
||||||
|
|
||||||
_clearUsersOnShortCooldown = new Timer(_ =>
|
_clearUsersOnShortCooldown = new Timer(_ =>
|
||||||
{
|
{
|
||||||
UsersOnShortCooldown.Clear();
|
UsersOnShortCooldown.Clear();
|
||||||
@@ -118,27 +111,6 @@ namespace NadekoBot.Services
|
|||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void AddServices(IServiceCollection services)
|
|
||||||
{
|
|
||||||
_lateBlockers = services.Where(x => x.ImplementationType?.GetInterfaces().Contains(typeof(ILateBlocker)) ?? false)
|
|
||||||
.Select(x => _services.GetService(x.ImplementationType) as ILateBlocker)
|
|
||||||
.OrderByDescending(x => x.Priority)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
_lateExecutors = services.Where(x => x.ImplementationType?.GetInterfaces().Contains(typeof(ILateExecutor)) ?? false)
|
|
||||||
.Select(x => _services.GetService(x.ImplementationType) as ILateExecutor)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
_inputTransformers = services.Where(x => x.ImplementationType?.GetInterfaces().Contains(typeof(IInputTransformer)) ?? false)
|
|
||||||
.Select(x => _services.GetService(x.ImplementationType) as IInputTransformer)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
_earlyBehaviors = services.Where(x => x.ImplementationType?.GetInterfaces().Contains(typeof(IEarlyBehavior)) ?? false)
|
|
||||||
.Select(x => _services.GetService(x.ImplementationType) as IEarlyBehavior)
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ExecuteExternal(ulong? guildId, ulong channelId, string commandText)
|
public async Task ExecuteExternal(ulong? guildId, ulong channelId, string commandText)
|
||||||
{
|
{
|
||||||
if (guildId != null)
|
if (guildId != null)
|
||||||
@@ -172,8 +144,7 @@ namespace NadekoBot.Services
|
|||||||
|
|
||||||
private Task LogSuccessfulExecution(IUserMessage usrMsg, ITextChannel channel, params int[] execPoints)
|
private Task LogSuccessfulExecution(IUserMessage usrMsg, ITextChannel channel, params int[] execPoints)
|
||||||
{
|
{
|
||||||
var bss = _services.GetService<BotConfigService>();
|
if (_bss.GetRawData().ConsoleOutputType == ConsoleOutputType.Normal)
|
||||||
if (bss.Data.ConsoleOutputType == ConsoleOutputType.Normal)
|
|
||||||
{
|
{
|
||||||
Log.Information($"Command Executed after " + string.Join("/", execPoints.Select(x => (x * _oneThousandth).ToString("F3"))) + "s\n\t" +
|
Log.Information($"Command Executed after " + string.Join("/", execPoints.Select(x => (x * _oneThousandth).ToString("F3"))) + "s\n\t" +
|
||||||
"User: {0}\n\t" +
|
"User: {0}\n\t" +
|
||||||
@@ -199,8 +170,7 @@ namespace NadekoBot.Services
|
|||||||
|
|
||||||
private void LogErroredExecution(string errorMessage, IUserMessage usrMsg, ITextChannel channel, params int[] execPoints)
|
private void LogErroredExecution(string errorMessage, IUserMessage usrMsg, ITextChannel channel, params int[] execPoints)
|
||||||
{
|
{
|
||||||
var bss = _services.GetService<BotConfigService>();
|
if (_bss.GetRawData().ConsoleOutputType == ConsoleOutputType.Normal)
|
||||||
if (bss.Data.ConsoleOutputType == ConsoleOutputType.Normal)
|
|
||||||
{
|
{
|
||||||
Log.Warning($"Command Errored after " + string.Join("/", execPoints.Select(x => (x * _oneThousandth).ToString("F3"))) + "s\n\t" +
|
Log.Warning($"Command Errored after " + string.Join("/", execPoints.Select(x => (x * _oneThousandth).ToString("F3"))) + "s\n\t" +
|
||||||
"User: {0}\n\t" +
|
"User: {0}\n\t" +
|
||||||
@@ -231,7 +201,7 @@ namespace NadekoBot.Services
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (msg.Author.IsBot || !_bot.Ready.Task.IsCompleted) //no bots, wait until bot connected and initialized
|
if (msg.Author.IsBot || !_bot.IsReady) //no bots, wait until bot connected and initialized
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(msg is SocketUserMessage usrMsg))
|
if (!(msg is SocketUserMessage usrMsg))
|
||||||
@@ -258,62 +228,33 @@ namespace NadekoBot.Services
|
|||||||
|
|
||||||
public async Task TryRunCommand(SocketGuild guild, ISocketMessageChannel channel, IUserMessage usrMsg)
|
public async Task TryRunCommand(SocketGuild guild, ISocketMessageChannel channel, IUserMessage usrMsg)
|
||||||
{
|
{
|
||||||
var execTime = Environment.TickCount;
|
var startTime = Environment.TickCount;
|
||||||
|
|
||||||
//its nice to have early blockers and early blocking executors separate, but
|
var blocked = await _behaviourExecutor.RunEarlyBehavioursAsync(guild, usrMsg);
|
||||||
//i could also have one interface with priorities, and just put early blockers on
|
if (blocked)
|
||||||
//highest priority. :thinking:
|
return;
|
||||||
foreach (var beh in _earlyBehaviors)
|
|
||||||
{
|
|
||||||
if (await beh.RunBehavior(_client, guild, usrMsg).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
if (beh.BehaviorType == ModuleBehaviorType.Blocker)
|
|
||||||
{
|
|
||||||
Log.Information("Blocked User: [{0}] Message: [{1}] Service: [{2}]", usrMsg.Author,
|
|
||||||
usrMsg.Content, beh.GetType().Name);
|
|
||||||
}
|
|
||||||
else if (beh.BehaviorType == ModuleBehaviorType.Executor)
|
|
||||||
{
|
|
||||||
Log.Information("User [{0}] executed [{1}] in [{2}]", usrMsg.Author, usrMsg.Content,
|
|
||||||
beh.GetType().Name);
|
|
||||||
|
|
||||||
}
|
var blockTime = Environment.TickCount - startTime;
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var exec2 = Environment.TickCount - execTime;
|
|
||||||
|
|
||||||
|
var messageContent = await _behaviourExecutor.RunInputTransformersAsync(guild, usrMsg);
|
||||||
|
|
||||||
string messageContent = usrMsg.Content;
|
|
||||||
foreach (var exec in _inputTransformers)
|
|
||||||
{
|
|
||||||
string newContent;
|
|
||||||
if ((newContent = await exec.TransformInput(guild, usrMsg.Channel, usrMsg.Author, messageContent)
|
|
||||||
.ConfigureAwait(false)) != messageContent.ToLowerInvariant())
|
|
||||||
{
|
|
||||||
messageContent = newContent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var prefix = GetPrefix(guild?.Id);
|
var prefix = GetPrefix(guild?.Id);
|
||||||
var isPrefixCommand = messageContent.StartsWith(".prefix", StringComparison.InvariantCultureIgnoreCase);
|
var isPrefixCommand = messageContent.StartsWith(".prefix", StringComparison.InvariantCultureIgnoreCase);
|
||||||
// execute the command and measure the time it took
|
// execute the command and measure the time it took
|
||||||
if (messageContent.StartsWith(prefix, StringComparison.InvariantCulture) || isPrefixCommand)
|
if (messageContent.StartsWith(prefix, StringComparison.InvariantCulture) || isPrefixCommand)
|
||||||
{
|
{
|
||||||
var (Success, Error, Info) = await ExecuteCommandAsync(new CommandContext(_client, usrMsg), messageContent, isPrefixCommand ? 1 : prefix.Length, _services, MultiMatchHandling.Best).ConfigureAwait(false);
|
var (Success, Error, Info) = await ExecuteCommandAsync(new CommandContext(_client, usrMsg), messageContent, isPrefixCommand ? 1 : prefix.Length, _services, MultiMatchHandling.Best).ConfigureAwait(false);
|
||||||
execTime = Environment.TickCount - execTime;
|
startTime = Environment.TickCount - startTime;
|
||||||
|
|
||||||
if (Success)
|
if (Success)
|
||||||
{
|
{
|
||||||
await LogSuccessfulExecution(usrMsg, channel as ITextChannel, exec2, execTime).ConfigureAwait(false);
|
await LogSuccessfulExecution(usrMsg, channel as ITextChannel, blockTime, startTime).ConfigureAwait(false);
|
||||||
await CommandExecuted(usrMsg, Info).ConfigureAwait(false);
|
await CommandExecuted(usrMsg, Info).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (Error != null)
|
else if (Error != null)
|
||||||
{
|
{
|
||||||
LogErroredExecution(Error, usrMsg, channel as ITextChannel, exec2, execTime);
|
LogErroredExecution(Error, usrMsg, channel as ITextChannel, blockTime, startTime);
|
||||||
if (guild != null)
|
if (guild != null)
|
||||||
await CommandErrored(Info, channel as ITextChannel, Error).ConfigureAwait(false);
|
await CommandErrored(Info, channel as ITextChannel, Error).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -323,11 +264,7 @@ namespace NadekoBot.Services
|
|||||||
await OnMessageNoTrigger(usrMsg).ConfigureAwait(false);
|
await OnMessageNoTrigger(usrMsg).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var exec in _lateExecutors)
|
await _behaviourExecutor.RunLateExecutorsAsync(guild, usrMsg);
|
||||||
{
|
|
||||||
await exec.LateExecute(_client, guild, usrMsg).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<(bool Success, string Error, CommandInfo Info)> ExecuteCommandAsync(CommandContext context, string input, int argPos, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
public Task<(bool Success, string Error, CommandInfo Info)> ExecuteCommandAsync(CommandContext context, string input, int argPos, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||||
@@ -423,17 +360,9 @@ namespace NadekoBot.Services
|
|||||||
return (false, null, cmd);
|
return (false, null, cmd);
|
||||||
//return SearchResult.FromError(CommandError.Exception, "You are on a global cooldown.");
|
//return SearchResult.FromError(CommandError.Exception, "You are on a global cooldown.");
|
||||||
|
|
||||||
var commandName = cmd.Aliases.First();
|
var blocked = await _behaviourExecutor.RunLateBlockersAsync(context, cmd);
|
||||||
foreach (var exec in _lateBlockers)
|
if (blocked)
|
||||||
{
|
return (false, null, cmd);
|
||||||
if (await exec.TryBlockLate(_client, context, cmd.Module.GetTopLevelModule().Name, cmd)
|
|
||||||
.ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
Log.Information("Late blocking User [{0}] Command: [{1}] in [{2}]", context.User, commandName,
|
|
||||||
exec.GetType().Name);
|
|
||||||
return (false, null, cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//If we get this far, at least one parse was successful. Execute the most likely overload.
|
//If we get this far, at least one parse was successful. Execute the most likely overload.
|
||||||
var chosenOverload = successfulParses[0];
|
var chosenOverload = successfulParses[0];
|
||||||
|
15
src/NadekoBot/Services/IBehaviourExecutor.cs
Normal file
15
src/NadekoBot/Services/IBehaviourExecutor.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services
|
||||||
|
{
|
||||||
|
public interface IBehaviourExecutor
|
||||||
|
{
|
||||||
|
public Task<bool> RunEarlyBehavioursAsync(SocketGuild guild, IUserMessage usrMsg);
|
||||||
|
public Task<string> RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg);
|
||||||
|
Task<bool> RunLateBlockersAsync(ICommandContext context, CommandInfo cmd);
|
||||||
|
Task RunLateExecutorsAsync(SocketGuild guild, IUserMessage usrMsg);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,4 @@
|
|||||||
using System.Threading.Tasks;
|
namespace NadekoBot.Services
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All services must implement this interface in order to be auto-discovered by the DI system
|
/// All services must implement this interface in order to be auto-discovered by the DI system
|
||||||
@@ -9,12 +7,4 @@ namespace NadekoBot.Services
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// All services which require cleanup after they are unloaded must implement this interface
|
|
||||||
/// </summary>
|
|
||||||
public interface IUnloadableService
|
|
||||||
{
|
|
||||||
Task Unload();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
100
src/NadekoBot/Services/Impl/BehaviorExecutor.cs
Normal file
100
src/NadekoBot/Services/Impl/BehaviorExecutor.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services
|
||||||
|
{
|
||||||
|
public sealed class BehaviorExecutor : IBehaviourExecutor
|
||||||
|
{
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly IEnumerable<ILateExecutor> _lateExecutors;
|
||||||
|
private readonly IEnumerable<ILateBlocker> _lateBlockers;
|
||||||
|
private readonly IEnumerable<IEarlyBehavior> _earlyBehaviors;
|
||||||
|
private readonly IEnumerable<IInputTransformer> _transformers;
|
||||||
|
|
||||||
|
public BehaviorExecutor(
|
||||||
|
DiscordSocketClient client,
|
||||||
|
IEnumerable<ILateExecutor> lateExecutors,
|
||||||
|
IEnumerable<ILateBlocker> lateBlockers,
|
||||||
|
IEnumerable<IEarlyBehavior> earlyBehaviors,
|
||||||
|
IEnumerable<IInputTransformer> transformers)
|
||||||
|
{
|
||||||
|
_client = client;
|
||||||
|
_lateExecutors = lateExecutors;
|
||||||
|
_lateBlockers = lateBlockers;
|
||||||
|
_earlyBehaviors = earlyBehaviors;
|
||||||
|
_transformers = transformers;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo early behaviors should print for themselves
|
||||||
|
public async Task<bool> RunEarlyBehavioursAsync(SocketGuild guild, IUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
foreach (var beh in _earlyBehaviors)
|
||||||
|
{
|
||||||
|
if (await beh.RunBehavior(guild, usrMsg))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
var messageContent = usrMsg.Content;
|
||||||
|
foreach (var exec in _transformers)
|
||||||
|
{
|
||||||
|
string newContent;
|
||||||
|
if ((newContent = await exec.TransformInput(guild, usrMsg.Channel, usrMsg.Author, messageContent))
|
||||||
|
!= messageContent.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
messageContent = newContent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> RunLateBlockersAsync(ICommandContext ctx, CommandInfo cmd)
|
||||||
|
{
|
||||||
|
foreach (var exec in _lateBlockers)
|
||||||
|
{
|
||||||
|
if (await exec.TryBlockLate(ctx, cmd.Module.GetTopLevelModule().Name, cmd))
|
||||||
|
{
|
||||||
|
Log.Information("Late blocking User [{0}] Command: [{1}] in [{2}]",
|
||||||
|
ctx.User,
|
||||||
|
cmd.Aliases[0],
|
||||||
|
exec.GetType().Name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunLateExecutorsAsync(SocketGuild guild, IUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
foreach (var exec in _lateExecutors)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await exec.LateExecute(guild, usrMsg).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Error in {TypeName} late executor: {ErrorMessage}",
|
||||||
|
exec.GetType().Name,
|
||||||
|
ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -24,7 +24,6 @@ namespace NadekoBot.Services
|
|||||||
private IDatabase _db => _con.GetDatabase();
|
private IDatabase _db => _con.GetDatabase();
|
||||||
|
|
||||||
private const string _basePath = "data/";
|
private const string _basePath = "data/";
|
||||||
private const string _oldBasePath = "data/images/";
|
|
||||||
private const string _cardsPath = "data/images/cards";
|
private const string _cardsPath = "data/images/cards";
|
||||||
|
|
||||||
public ImageUrls ImageUrls { get; private set; }
|
public ImageUrls ImageUrls { get; private set; }
|
||||||
@@ -79,112 +78,11 @@ namespace NadekoBot.Services
|
|||||||
_con = con;
|
_con = con;
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
_http = new HttpClient();
|
_http = new HttpClient();
|
||||||
|
|
||||||
Migrate();
|
|
||||||
ImageUrls = JsonConvert.DeserializeObject<ImageUrls>(
|
ImageUrls = JsonConvert.DeserializeObject<ImageUrls>(
|
||||||
File.ReadAllText(Path.Combine(_basePath, "images.json")));
|
File.ReadAllText(Path.Combine(_basePath, "images.json")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Migrate()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Migrate1();
|
|
||||||
Migrate2();
|
|
||||||
Migrate3();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warning(ex.Message);
|
|
||||||
Log.Error("Something has been incorrectly formatted in your 'images.json' file.\n" +
|
|
||||||
"Use the 'images_example.json' file as reference to fix it and restart the bot.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Migrate1()
|
|
||||||
{
|
|
||||||
if (!File.Exists(Path.Combine(_oldBasePath, "images.json")))
|
|
||||||
return;
|
|
||||||
Log.Information("Migrating images v0 to images v1.");
|
|
||||||
// load old images
|
|
||||||
var oldUrls = JsonConvert.DeserializeObject<ImageUrls>(
|
|
||||||
File.ReadAllText(Path.Combine(_oldBasePath, "images.json")));
|
|
||||||
// load new images
|
|
||||||
var newUrls = JsonConvert.DeserializeObject<ImageUrls>(
|
|
||||||
File.ReadAllText(Path.Combine(_basePath, "images.json")));
|
|
||||||
|
|
||||||
//swap new links with old ones if set. Also update old links.
|
|
||||||
newUrls.Coins = oldUrls.Coins;
|
|
||||||
|
|
||||||
newUrls.Currency = oldUrls.Currency;
|
|
||||||
newUrls.Dice = oldUrls.Dice;
|
|
||||||
newUrls.Rategirl = oldUrls.Rategirl;
|
|
||||||
newUrls.Xp = oldUrls.Xp;
|
|
||||||
newUrls.Version = 1;
|
|
||||||
|
|
||||||
File.WriteAllText(Path.Combine(_basePath, "images.json"),
|
|
||||||
JsonConvert.SerializeObject(newUrls, Formatting.Indented));
|
|
||||||
File.Delete(Path.Combine(_oldBasePath, "images.json"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Migrate2()
|
|
||||||
{
|
|
||||||
// load new images
|
|
||||||
var urls = JsonConvert.DeserializeObject<ImageUrls>(File.ReadAllText(Path.Combine(_basePath, "images.json")));
|
|
||||||
|
|
||||||
if (urls.Version >= 2)
|
|
||||||
return;
|
|
||||||
Log.Information("Migrating images v1 to images v2.");
|
|
||||||
urls.Version = 2;
|
|
||||||
|
|
||||||
var prefix = $"{_creds.RedisKey()}_localimg_";
|
|
||||||
_db.KeyDelete(new[] {
|
|
||||||
prefix + "heads",
|
|
||||||
prefix + "tails",
|
|
||||||
prefix + "dice",
|
|
||||||
prefix + "slot_background",
|
|
||||||
prefix + "slotnumbers",
|
|
||||||
prefix + "slotemojis",
|
|
||||||
prefix + "wife_matrix",
|
|
||||||
prefix + "rategirl_dot",
|
|
||||||
prefix + "xp_card",
|
|
||||||
prefix + "rip",
|
|
||||||
prefix + "rip_overlay" }
|
|
||||||
.Select(x => (RedisKey)x).ToArray());
|
|
||||||
|
|
||||||
File.WriteAllText(Path.Combine(_basePath, "images.json"), JsonConvert.SerializeObject(urls, Formatting.Indented));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Migrate3()
|
|
||||||
{
|
|
||||||
var urls = JsonConvert.DeserializeObject<ImageUrls>(
|
|
||||||
File.ReadAllText(Path.Combine(_basePath, "images.json")));
|
|
||||||
|
|
||||||
if (urls.Version >= 3)
|
|
||||||
return;
|
|
||||||
urls.Version = 3;
|
|
||||||
Log.Information("Migrating images v2 to images v3.");
|
|
||||||
|
|
||||||
var baseStr = "https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/currency/";
|
|
||||||
|
|
||||||
var replacementTable = new Dictionary<Uri, Uri>()
|
|
||||||
{
|
|
||||||
{new Uri(baseStr + "0.jpg"), new Uri(baseStr + "0.png") },
|
|
||||||
{new Uri(baseStr + "1.jpg"), new Uri(baseStr + "1.png") },
|
|
||||||
{new Uri(baseStr + "2.jpg"), new Uri(baseStr + "2.png") }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (replacementTable.Keys.Any(x => urls.Currency.Contains(x)))
|
|
||||||
{
|
|
||||||
urls.Currency = urls.Currency.Select(x => replacementTable.TryGetValue(x, out var newUri)
|
|
||||||
? newUri
|
|
||||||
: x).Append(new Uri(baseStr + "3.png"))
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllText(Path.Combine(_basePath, "images.json"), JsonConvert.SerializeObject(urls, Formatting.Indented));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> AllKeysExist()
|
public async Task<bool> AllKeysExist()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
Reference in New Issue
Block a user