mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 01:38:27 -04:00
More cleanup, namespace fixes, convenience methods for IKernel
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Common;
|
||||
|
||||
namespace NadekoBot;
|
||||
|
||||
public interface IBotCredentials
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#nullable disable
|
||||
using System.Globalization;
|
||||
using NadekoBot.Services;
|
||||
|
||||
namespace NadekoBot.Common;
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Services;
|
||||
|
||||
namespace NadekoBot.Common.TypeReaders;
|
||||
|
||||
public sealed class CommandTypeReader : NadekoTypeReader<CommandInfo>
|
||||
|
@@ -1,6 +1,4 @@
|
||||
#nullable disable
|
||||
using Nadeko.Common;
|
||||
|
||||
namespace NadekoBot.Common.TypeReaders;
|
||||
|
||||
public sealed class KwumTypeReader : NadekoTypeReader<kwum>
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using SixLabors.Fonts;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Drawing;
|
||||
using SixLabors.ImageSharp.Drawing.Processing;
|
||||
using SixLabors.ImageSharp.Formats;
|
||||
|
@@ -1,6 +1,4 @@
|
||||
using NadekoBot;
|
||||
using NadekoBot.Services;
|
||||
using OneOf;
|
||||
using OneOf;
|
||||
using OneOf.Types;
|
||||
|
||||
namespace Nadeko.Bot.Common;
|
||||
|
@@ -1,6 +1,4 @@
|
||||
using NadekoBot.Services;
|
||||
|
||||
namespace NadekoBot;
|
||||
namespace NadekoBot;
|
||||
|
||||
public class NadekoInteractionService : INadekoInteractionService, INService
|
||||
{
|
||||
|
6
src/Nadeko.Bot.Common/ModuleBehaviors/IBehavior.cs
Normal file
6
src/Nadeko.Bot.Common/ModuleBehaviors/IBehavior.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
public interface IBehavior
|
||||
{
|
||||
public virtual string Name => this.GetType().Name;
|
||||
}
|
@@ -3,7 +3,7 @@ namespace NadekoBot.Common.ModuleBehaviors;
|
||||
/// <summary>
|
||||
/// Executed if no command was found for this message
|
||||
/// </summary>
|
||||
public interface IExecNoCommand
|
||||
public interface IExecNoCommand : IBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Executed at the end of the lifecycle if no command was found
|
||||
|
@@ -3,7 +3,7 @@ namespace NadekoBot.Common.ModuleBehaviors;
|
||||
/// <summary>
|
||||
/// Implemented by modules to handle non-bot messages received
|
||||
/// </summary>
|
||||
public interface IExecOnMessage
|
||||
public interface IExecOnMessage : IBehavior
|
||||
{
|
||||
int Priority { get; }
|
||||
|
||||
|
@@ -5,7 +5,7 @@ namespace NadekoBot.Common.ModuleBehaviors;
|
||||
/// ***There is no support for this method in NadekoBot services.***
|
||||
/// It is only meant to be used in medusa system
|
||||
/// </summary>
|
||||
public interface IExecPostCommand
|
||||
public interface IExecPostCommand : IBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Executed after a command was successfully executed
|
||||
|
@@ -4,7 +4,7 @@ namespace NadekoBot.Common.ModuleBehaviors;
|
||||
/// This interface's method is executed after a command was found but before it was executed.
|
||||
/// Able to block further processing of a command
|
||||
/// </summary>
|
||||
public interface IExecPreCommand
|
||||
public interface IExecPreCommand : IBehavior
|
||||
{
|
||||
public int Priority { get; }
|
||||
|
||||
|
@@ -3,7 +3,7 @@ namespace NadekoBot.Common.ModuleBehaviors;
|
||||
/// <summary>
|
||||
/// Implemented by services which may transform input before a command is searched for
|
||||
/// </summary>
|
||||
public interface IInputTransformer
|
||||
public interface IInputTransformer : IBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Ran after a non-bot message was received
|
||||
|
@@ -4,7 +4,7 @@ namespace NadekoBot.Common.ModuleBehaviors;
|
||||
/// All services which need to execute something after
|
||||
/// the bot is ready should implement this interface
|
||||
/// </summary>
|
||||
public interface IReadyExecutor
|
||||
public interface IReadyExecutor : IBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Executed when bot is ready
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#nullable disable
|
||||
using System.Text.RegularExpressions;
|
||||
using NonBlocking;
|
||||
|
||||
namespace NadekoBot.Common;
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#nullable disable
|
||||
using System.Text.RegularExpressions;
|
||||
using Nadeko.Common;
|
||||
|
||||
namespace NadekoBot.Common;
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Services.Currency;
|
||||
|
@@ -1,7 +1,4 @@
|
||||
using NadekoBot.Modules.Administration;
|
||||
using NonBlocking;
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
public interface ICommandHandler
|
||||
{
|
||||
|
302
src/Nadeko.Bot.Common/Services/Impl/BehaviorExecutor.cs
Normal file
302
src/Nadeko.Bot.Common/Services/Impl/BehaviorExecutor.cs
Normal file
@@ -0,0 +1,302 @@
|
||||
#nullable disable
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
// should be renamed to handler as it's not only executing
|
||||
public sealed class BehaviorHandler : IBehaviorHandler
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
private IReadOnlyCollection<IExecNoCommand> noCommandExecs;
|
||||
private IReadOnlyCollection<IExecPreCommand> preCommandExecs;
|
||||
private IReadOnlyCollection<IExecOnMessage> onMessageExecs;
|
||||
private IReadOnlyCollection<IInputTransformer> inputTransformers;
|
||||
|
||||
private readonly SemaphoreSlim _customLock = new(1, 1);
|
||||
private readonly List<ICustomBehavior> _customExecs = new();
|
||||
|
||||
public BehaviorHandler(IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
noCommandExecs = _services.GetServices<IExecNoCommand>().ToArray();
|
||||
preCommandExecs = _services.GetServices<IExecPreCommand>().OrderByDescending(x => x.Priority).ToArray();
|
||||
onMessageExecs = _services.GetServices<IExecOnMessage>().OrderByDescending(x => x.Priority).ToArray();
|
||||
inputTransformers = _services.GetServices<IInputTransformer>().ToArray();
|
||||
}
|
||||
|
||||
#region Add/Remove
|
||||
|
||||
public async Task AddRangeAsync(IEnumerable<ICustomBehavior> execs)
|
||||
{
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
foreach (var exe in execs)
|
||||
{
|
||||
if (_customExecs.Contains(exe))
|
||||
continue;
|
||||
|
||||
_customExecs.Add(exe);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> AddAsync(ICustomBehavior behavior)
|
||||
{
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (_customExecs.Contains(behavior))
|
||||
return false;
|
||||
|
||||
_customExecs.Add(behavior);
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveAsync(ICustomBehavior behavior)
|
||||
{
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
return _customExecs.Remove(behavior);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RemoveRangeAsync(IEnumerable<ICustomBehavior> behs)
|
||||
{
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
foreach(var beh in behs)
|
||||
_customExecs.Remove(beh);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Running
|
||||
|
||||
public async Task<bool> RunExecOnMessageAsync(SocketGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
async Task<bool> Exec<T>(IReadOnlyCollection<T> execs)
|
||||
where T : IExecOnMessage
|
||||
{
|
||||
foreach (var exec in execs)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await exec.ExecOnMessageAsync(guild, usrMsg))
|
||||
{
|
||||
Log.Information("{TypeName} blocked message g:{GuildId} u:{UserId} c:{ChannelId} msg:{Message}",
|
||||
GetExecName(exec),
|
||||
guild?.Id,
|
||||
usrMsg.Author.Id,
|
||||
usrMsg.Channel.Id,
|
||||
usrMsg.Content?.TrimTo(10));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex,
|
||||
"An error occurred in {TypeName} late blocker: {ErrorMessage}",
|
||||
GetExecName(exec),
|
||||
ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (await Exec(onMessageExecs))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (await Exec(_customExecs))
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetExecName(IBehavior exec)
|
||||
=> exec.Name;
|
||||
|
||||
public async Task<bool> RunPreCommandAsync(ICommandContext ctx, CommandInfo cmd)
|
||||
{
|
||||
async Task<bool> Exec<T>(IReadOnlyCollection<T> execs) where T: IExecPreCommand
|
||||
{
|
||||
foreach (var exec in execs)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await exec.ExecPreCommandAsync(ctx, cmd.Module.GetTopLevelModule().Name, cmd))
|
||||
{
|
||||
Log.Information("{TypeName} Pre-Command blocked [{User}] Command: [{Command}]",
|
||||
GetExecName(exec),
|
||||
ctx.User,
|
||||
cmd.Aliases[0]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex,
|
||||
"An error occurred in {TypeName} PreCommand: {ErrorMessage}",
|
||||
GetExecName(exec),
|
||||
ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (await Exec(preCommandExecs))
|
||||
return true;
|
||||
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (await Exec(_customExecs))
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task RunOnNoCommandAsync(SocketGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
async Task Exec<T>(IReadOnlyCollection<T> execs) where T : IExecNoCommand
|
||||
{
|
||||
foreach (var exec in execs)
|
||||
{
|
||||
try
|
||||
{
|
||||
await exec.ExecOnNoCommandAsync(guild, usrMsg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex,
|
||||
"An error occurred in {TypeName} OnNoCommand: {ErrorMessage}",
|
||||
GetExecName(exec),
|
||||
ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Exec(noCommandExecs);
|
||||
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await Exec(_customExecs);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
async Task<string> Exec<T>(IReadOnlyCollection<T> execs, string content)
|
||||
where T : IInputTransformer
|
||||
{
|
||||
foreach (var exec in execs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newContent = await exec.TransformInput(guild, usrMsg.Channel, usrMsg.Author, content);
|
||||
if (newContent is not null)
|
||||
{
|
||||
Log.Information("{ExecName} transformed content {OldContent} -> {NewContent}",
|
||||
GetExecName(exec),
|
||||
content,
|
||||
newContent);
|
||||
return newContent;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "An error occured during InputTransform handling: {ErrorMessage}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var newContent = await Exec(inputTransformers, usrMsg.Content);
|
||||
if (newContent is not null)
|
||||
return newContent;
|
||||
|
||||
await _customLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
newContent = await Exec(_customExecs, usrMsg.Content);
|
||||
if (newContent is not null)
|
||||
return newContent;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_customLock.Release();
|
||||
}
|
||||
|
||||
return usrMsg.Content;
|
||||
}
|
||||
|
||||
public async ValueTask RunPostCommandAsync(ICommandContext ctx, string moduleName, CommandInfo cmd)
|
||||
{
|
||||
foreach (var exec in _customExecs)
|
||||
{
|
||||
try
|
||||
{
|
||||
await exec.ExecPostCommandAsync(ctx, moduleName, cmd.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex,
|
||||
"An error occured during PostCommand handling in {ExecName}: {ErrorMessage}",
|
||||
GetExecName(exec),
|
||||
ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@@ -1,6 +1,5 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Nadeko.Common;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
|
@@ -2,7 +2,6 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Nadeko.Common;
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
|
@@ -2,7 +2,6 @@ using NadekoBot.Common.Configs;
|
||||
using NadekoBot.Common.Yml;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using NadekoBot.Common;
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
|
@@ -4,8 +4,6 @@ using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using Nadeko.Medusa;
|
||||
using NadekoBot.Common;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
|
@@ -1,7 +1,3 @@
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Services;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
public static class MessageChannelExtensions
|
||||
|
@@ -1,8 +1,4 @@
|
||||
using Nadeko.Common;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Services;
|
||||
|
||||
namespace NadekoBot.Extensions;
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
public static class SocketMessageComponentExtensions
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using NadekoBot.Db.Models;
|
||||
using NadekoBot.Services;
|
||||
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
|
Reference in New Issue
Block a user