Refactored typereaders to use DI instead of getting services manually

This commit is contained in:
Kwoth
2021-07-03 23:16:53 +02:00
parent 3cc34bfdc3
commit 4c0c3c9228
11 changed files with 86 additions and 120 deletions

View File

@@ -198,7 +198,7 @@ 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)ActivatorUtilities.CreateInstance(Services, ft);
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);

View File

@@ -4,31 +4,30 @@ using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Modules.CustomReactions.Services; using NadekoBot.Modules.CustomReactions.Services;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public sealed class CommandTypeReader : NadekoTypeReader<CommandInfo> public sealed class CommandTypeReader : NadekoTypeReader<CommandInfo>
{ {
public CommandTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) private readonly CommandHandler _handler;
private readonly CommandService _cmds;
public CommandTypeReader(CommandHandler handler, CommandService cmds)
{ {
_handler = handler;
_cmds = cmds;
} }
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{ {
var cmds = services.GetRequiredService<CommandService>();
var cmdHandler = services.GetRequiredService<CommandHandler>();
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var prefix = cmdHandler.GetPrefix(context.Guild); var prefix = _handler.GetPrefix(context.Guild);
if (!input.StartsWith(prefix.ToUpperInvariant(), StringComparison.InvariantCulture)) if (!input.StartsWith(prefix.ToUpperInvariant(), StringComparison.InvariantCulture))
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found."));
input = input.Substring(prefix.Length); input = input.Substring(prefix.Length);
var cmd = cmds.Commands.FirstOrDefault(c => var cmd = _cmds.Commands.FirstOrDefault(c => c.Aliases.Select(a => a.ToUpperInvariant()).Contains(input));
c.Aliases.Select(a => a.ToUpperInvariant()).Contains(input));
if (cmd is null) if (cmd is null)
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found."));
@@ -38,26 +37,30 @@ namespace NadekoBot.Common.TypeReaders
public sealed class CommandOrCrTypeReader : NadekoTypeReader<CommandOrCrInfo> public sealed class CommandOrCrTypeReader : NadekoTypeReader<CommandOrCrInfo>
{ {
private readonly DiscordSocketClient _client;
private readonly CommandService _cmds; private readonly CommandService _cmds;
public CommandOrCrTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) private readonly CustomReactionsService _crs;
private readonly CommandHandler _commandHandler;
public CommandOrCrTypeReader(
CommandService cmds,
CustomReactionsService crs,
CommandHandler commandHandler)
{ {
_client = client;
_cmds = cmds; _cmds = cmds;
_crs = crs;
_commandHandler = commandHandler;
} }
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var crs = services.GetRequiredService<CustomReactionsService>(); if (_crs.ReactionExists(context.Guild?.Id, input))
if (crs.ReactionExists(context.Guild?.Id, input))
{ {
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input, CommandOrCrInfo.Type.Custom)); return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input, CommandOrCrInfo.Type.Custom));
} }
var cmd = await new CommandTypeReader(_client, _cmds).ReadAsync(context, input, services).ConfigureAwait(false); var cmd = await new CommandTypeReader(_commandHandler, _cmds).ReadAsync(context, input).ConfigureAwait(false);
if (cmd.IsSuccess) if (cmd.IsSuccess)
{ {
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name, CommandOrCrInfo.Type.Normal)); return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name, CommandOrCrInfo.Type.Normal));

View File

@@ -2,36 +2,35 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Modules.Administration.Services; using NadekoBot.Modules.Administration.Services;
using NadekoBot.Common.TypeReaders;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class GuildDateTimeTypeReader : NadekoTypeReader<GuildDateTime> public sealed class GuildDateTimeTypeReader : NadekoTypeReader<GuildDateTime>
{ {
public GuildDateTimeTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) private readonly GuildTimezoneService _gts;
{
}
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) public GuildDateTimeTypeReader(GuildTimezoneService gts)
{ {
var gdt = Parse(services, context.Guild.Id, input); _gts = gts;
}
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{
var gdt = Parse(context.Guild.Id, input);
if(gdt is null) if(gdt is null)
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input string is in an incorrect format.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input string is in an incorrect format."));
return Task.FromResult(TypeReaderResult.FromSuccess(gdt)); return Task.FromResult(TypeReaderResult.FromSuccess(gdt));
} }
public static GuildDateTime Parse(IServiceProvider services, ulong guildId, string input) private GuildDateTime Parse(ulong guildId, string input)
{ {
var gts = services.GetRequiredService<GuildTimezoneService>();
if (!DateTime.TryParse(input, out var dt)) if (!DateTime.TryParse(input, out var dt))
return null; return null;
var tz = gts.GetTimeZoneOrUtc(guildId); var tz = _gts.GetTimeZoneOrUtc(guildId);
return new GuildDateTime(tz, dt); return new(tz, dt);
} }
} }
@@ -42,8 +41,6 @@ namespace NadekoBot.Common.TypeReaders
public DateTime InputTime { get; } public DateTime InputTime { get; }
public DateTime InputTimeUtc { get; } public DateTime InputTimeUtc { get; }
private GuildDateTime() { }
public GuildDateTime(TimeZoneInfo guildTimezone, DateTime inputTime) public GuildDateTime(TimeZoneInfo guildTimezone, DateTime inputTime)
{ {
var now = DateTime.UtcNow; var now = DateTime.UtcNow;

View File

@@ -1,23 +1,21 @@
using System; using System.Linq;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Common.TypeReaders;
using Discord; using Discord;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class GuildTypeReader : NadekoTypeReader<IGuild> public sealed class GuildTypeReader : NadekoTypeReader<IGuild>
{ {
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
public GuildTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) public GuildTypeReader(DiscordSocketClient client)
{ {
_client = client; _client = client;
} }
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider _) public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{ {
input = input.Trim().ToUpperInvariant(); input = input.Trim().ToUpperInvariant();
var guilds = _client.Guilds; var guilds = _client.Guilds;

View File

@@ -1,17 +1,11 @@
using System; using System.Threading.Tasks;
using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class KwumTypeReader : NadekoTypeReader<kwum> public sealed class KwumTypeReader : NadekoTypeReader<kwum>
{ {
public KwumTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{
}
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
{ {
if (kwum.TryParse(input, out var val)) if (kwum.TryParse(input, out var val))
return Task.FromResult(TypeReaderResult.FromSuccess(val)); return Task.FromResult(TypeReaderResult.FromSuccess(val));

View File

@@ -1,23 +1,20 @@
using System; using System.Linq;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Common.TypeReaders;
using Discord.WebSocket;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class ModuleTypeReader : NadekoTypeReader<ModuleInfo> public sealed class ModuleTypeReader : NadekoTypeReader<ModuleInfo>
{ {
private readonly CommandService _cmds; private readonly CommandService _cmds;
public ModuleTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) public ModuleTypeReader(CommandService cmds)
{ {
_cmds = cmds; _cmds = cmds;
} }
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider _) public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()).FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input)?.Key; var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()).FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input)?.Key;
@@ -28,16 +25,16 @@ namespace NadekoBot.Common.TypeReaders
} }
} }
public class ModuleOrCrTypeReader : NadekoTypeReader<ModuleOrCrInfo> public sealed class ModuleOrCrTypeReader : NadekoTypeReader<ModuleOrCrInfo>
{ {
private readonly CommandService _cmds; private readonly CommandService _cmds;
public ModuleOrCrTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) public ModuleOrCrTypeReader(CommandService cmds)
{ {
_cmds = cmds; _cmds = cmds;
} }
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider _) public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()).FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input)?.Key; var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()).FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input)?.Key;
@@ -51,7 +48,7 @@ namespace NadekoBot.Common.TypeReaders
} }
} }
public class ModuleOrCrInfo public sealed class ModuleOrCrInfo
{ {
public string Name { get; set; } public string Name { get; set; }
} }

View File

@@ -1,18 +1,14 @@
using Discord.Commands; using System;
using Discord.WebSocket; using System.Threading.Tasks;
using Discord.Commands;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public abstract class NadekoTypeReader<T> : TypeReader public abstract class NadekoTypeReader<T> : TypeReader
{ {
private readonly DiscordSocketClient _client; public abstract Task<TypeReaderResult> ReadAsync(ICommandContext ctx, string input);
private readonly CommandService _cmds;
private NadekoTypeReader() { } public override Task<TypeReaderResult> ReadAsync(ICommandContext ctx, string input, IServiceProvider services)
protected NadekoTypeReader(DiscordSocketClient client, CommandService cmds) => ReadAsync(ctx, input);
{
_client = client;
_cmds = cmds;
}
} }
} }

View File

@@ -1,22 +1,15 @@
using System; using System.Threading.Tasks;
using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Common.TypeReaders.Models; using NadekoBot.Common.TypeReaders.Models;
using NadekoBot.Common.TypeReaders;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
/// <summary> /// <summary>
/// Used instead of bool for more flexible keywords for true/false only in the permission module /// Used instead of bool for more flexible keywords for true/false only in the permission module
/// </summary> /// </summary>
public class PermissionActionTypeReader : NadekoTypeReader<PermissionAction> public sealed class PermissionActionTypeReader : NadekoTypeReader<PermissionAction>
{ {
public PermissionActionTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{
}
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider _)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
switch (input) switch (input)

View File

@@ -1,18 +1,13 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class Rgba32TypeReader : NadekoTypeReader<Color> public sealed class Rgba32TypeReader : NadekoTypeReader<Color>
{ {
public Rgba32TypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{
}
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
{ {
await Task.Yield(); await Task.Yield();

View File

@@ -1,22 +1,26 @@
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using NadekoBot.Services;
using System; using System;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Db; using NadekoBot.Db;
using NadekoBot.Modules.Gambling.Services; using NadekoBot.Modules.Gambling.Services;
using NadekoBot.Services;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class ShmartNumberTypeReader : NadekoTypeReader<ShmartNumber> // todo test max/half/all
public sealed class ShmartNumberTypeReader : NadekoTypeReader<ShmartNumber>
{ {
public ShmartNumberTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) private readonly DbService _db;
private readonly GamblingConfigService _gambling;
public ShmartNumberTypeReader(DbService db, GamblingConfigService gambling)
{ {
_db = db;
_gambling = gambling;
} }
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{ {
await Task.Yield(); await Task.Yield();
@@ -29,12 +33,12 @@ namespace NadekoBot.Common.TypeReaders
//can't add m because it will conflict with max atm //can't add m because it will conflict with max atm
if (TryHandlePercentage(services, context, i, out var num)) if (TryHandlePercentage(context, i, out var num))
return TypeReaderResult.FromSuccess(new ShmartNumber(num, i)); return TypeReaderResult.FromSuccess(new ShmartNumber(num, i));
try try
{ {
var expr = new NCalc.Expression(i, NCalc.EvaluateOptions.IgnoreCase); var expr = new NCalc.Expression(i, NCalc.EvaluateOptions.IgnoreCase);
expr.EvaluateParameter += (str, ev) => EvaluateParam(str, ev, context, services); expr.EvaluateParameter += (str, ev) => EvaluateParam(str, ev, context);
var lon = (long)(decimal.Parse(expr.Evaluate().ToString())); var lon = (long)(decimal.Parse(expr.Evaluate().ToString()));
return TypeReaderResult.FromSuccess(new ShmartNumber(lon, input)); return TypeReaderResult.FromSuccess(new ShmartNumber(lon, input));
} }
@@ -44,7 +48,7 @@ namespace NadekoBot.Common.TypeReaders
} }
} }
private static void EvaluateParam(string name, NCalc.ParameterArgs args, ICommandContext ctx, IServiceProvider svc) private void EvaluateParam(string name, NCalc.ParameterArgs args, ICommandContext ctx)
{ {
switch (name.ToUpperInvariant()) switch (name.ToUpperInvariant())
{ {
@@ -56,13 +60,13 @@ namespace NadekoBot.Common.TypeReaders
break; break;
case "ALL": case "ALL":
case "ALLIN": case "ALLIN":
args.Result = Cur(svc, ctx); args.Result = Cur(ctx);
break; break;
case "HALF": case "HALF":
args.Result = Cur(svc, ctx) / 2; args.Result = Cur(ctx) / 2;
break; break;
case "MAX": case "MAX":
args.Result = Max(svc, ctx); args.Result = Max(ctx);
break; break;
default: default:
break; break;
@@ -71,28 +75,22 @@ namespace NadekoBot.Common.TypeReaders
private static readonly Regex percentRegex = new Regex(@"^((?<num>100|\d{1,2})%)$", RegexOptions.Compiled); private static readonly Regex percentRegex = new Regex(@"^((?<num>100|\d{1,2})%)$", RegexOptions.Compiled);
private static long Cur(IServiceProvider services, ICommandContext ctx) private long Cur(ICommandContext ctx)
{ {
var db = services.GetRequiredService<DbService>(); using var uow = _db.GetDbContext();
long cur; return uow.DiscordUser.GetUserCurrency(ctx.User.Id);
using (var uow = db.GetDbContext())
{
cur = uow.DiscordUser.GetUserCurrency(ctx.User.Id);
uow.SaveChanges();
}
return cur;
} }
private static long Max(IServiceProvider services, ICommandContext ctx) private long Max(ICommandContext ctx)
{ {
var settings = services.GetRequiredService<GamblingConfigService>().Data; var settings = _gambling.Data;
var max = settings.MaxBet; var max = settings.MaxBet;
return max == 0 return max == 0
? Cur(services, ctx) ? Cur(ctx)
: max; : max;
} }
private static bool TryHandlePercentage(IServiceProvider services, ICommandContext ctx, string input, out long num) private bool TryHandlePercentage(ICommandContext ctx, string input, out long num)
{ {
num = 0; num = 0;
var m = percentRegex.Match(input); var m = percentRegex.Match(input);
@@ -101,7 +99,7 @@ namespace NadekoBot.Common.TypeReaders
if (!long.TryParse(m.Groups["num"].ToString(), out var percent)) if (!long.TryParse(m.Groups["num"].ToString(), out var percent))
return false; return false;
num = (long)(Cur(services, ctx) * (percent / 100.0f)); num = (long)(Cur(ctx) * (percent / 100.0f));
return true; return true;
} }
return false; return false;

View File

@@ -1,18 +1,13 @@
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Common.TypeReaders.Models; using NadekoBot.Common.TypeReaders.Models;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Common.TypeReaders namespace NadekoBot.Common.TypeReaders
{ {
public class StoopidTimeTypeReader : NadekoTypeReader<StoopidTime> public sealed class StoopidTimeTypeReader : NadekoTypeReader<StoopidTime>
{ {
public StoopidTimeTypeReader(DiscordSocketClient client, CommandService cmds) : base(client, cmds) public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input)
{
}
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
{ {
if (string.IsNullOrWhiteSpace(input)) if (string.IsNullOrWhiteSpace(input))
return Task.FromResult(TypeReaderResult.FromError(CommandError.Unsuccessful, "Input is empty.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.Unsuccessful, "Input is empty."));