Small refactoring. Finally made use of the type parameter in NadekoTypeReader<T> class

This commit is contained in:
Kwoth
2022-01-31 05:45:51 +01:00
parent 0f36242597
commit 3e0bbd8ada
29 changed files with 130 additions and 128 deletions

View File

@@ -1,6 +1,5 @@
#nullable disable #nullable disable
#pragma warning disable #pragma warning disable
#pragma warning disable *
// License MIT // License MIT
// Source: https://github.com/i3arnon/ConcurrentHashSet // Source: https://github.com/i3arnon/ConcurrentHashSet

View File

@@ -11,19 +11,21 @@ namespace NadekoBot.Modules;
public abstract class NadekoModule : ModuleBase public abstract class NadekoModule : ModuleBase
{ {
protected CultureInfo Culture { get; set; } protected CultureInfo Culture { get; set; }
// Injected by Discord.net
public IBotStrings Strings { get; set; } public IBotStrings Strings { get; set; }
public CommandHandler CmdHandler { get; set; } public CommandHandler _cmdHandler { get; set; }
public ILocalization Localization { get; set; } public ILocalization _localization { get; set; }
public IEmbedBuilderService _eb { get; set; } public IEmbedBuilderService _eb { get; set; }
protected string prefix protected string prefix
=> CmdHandler.GetPrefix(ctx.Guild); => _cmdHandler.GetPrefix(ctx.Guild);
protected ICommandContext ctx protected ICommandContext ctx
=> Context; => Context;
protected override void BeforeExecute(CommandInfo cmd) protected override void BeforeExecute(CommandInfo command)
=> Culture = Localization.GetCultureInfo(ctx.Guild?.Id); => Culture = _localization.GetCultureInfo(ctx.Guild?.Id);
protected string GetText(in LocStr data) protected string GetText(in LocStr data)
=> Strings.GetText(data, Culture); => Strings.GetText(data, Culture);

View File

@@ -17,8 +17,8 @@ public static class OptionsParser
x.HelpWriter = null; x.HelpWriter = null;
}); });
var res = p.ParseArguments<T>(args); var res = p.ParseArguments<T>(args);
options = res.MapResult(x => x, _ => options); var output = res.MapResult(x => x, _ => options);
options.NormalizeOptions(); output.NormalizeOptions();
return (options, res.Tag == ParserResultType.Parsed); return (output, res.Tag == ParserResultType.Parsed);
} }
} }

View File

@@ -2,7 +2,7 @@ namespace NadekoBot.Common;
public readonly struct TypedKey<TData> public readonly struct TypedKey<TData>
{ {
public readonly string Key; public string Key { get; }
public TypedKey(in string key) public TypedKey(in string key)
=> Key = key; => Key = key;

View File

@@ -37,7 +37,7 @@ public abstract record SmartText
var smartEmbedText = JsonConvert.DeserializeObject<SmartEmbedText>(input); var smartEmbedText = JsonConvert.DeserializeObject<SmartEmbedText>(input);
if (smartEmbedText is null) if (smartEmbedText is null)
throw new(); throw new FormatException();
smartEmbedText.NormalizeFields(); smartEmbedText.NormalizeFields();

View File

@@ -14,20 +14,20 @@ public sealed class CommandTypeReader : NadekoTypeReader<CommandInfo>
_cmds = cmds; _cmds = cmds;
} }
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<CommandInfo>> ReadAsync(ICommandContext ctx, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var prefix = _handler.GetPrefix(context.Guild); var prefix = _handler.GetPrefix(ctx.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 new(TypeReaderResult.FromError<CommandInfo>(CommandError.ParseFailed, "No such command found."));
input = input[prefix.Length..]; input = input[prefix.Length..];
var cmd = _cmds.Commands.FirstOrDefault(c => c.Aliases.Select(a => a.ToUpperInvariant()).Contains(input)); var cmd = _cmds.Commands.FirstOrDefault(c => 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 new(TypeReaderResult.FromError<CommandInfo>(CommandError.ParseFailed, "No such command found."));
return Task.FromResult(TypeReaderResult.FromSuccess(cmd)); return new(TypeReaderResult.FromSuccess(cmd));
} }
} }
@@ -44,19 +44,19 @@ public sealed class CommandOrCrTypeReader : NadekoTypeReader<CommandOrCrInfo>
_commandHandler = commandHandler; _commandHandler = commandHandler;
} }
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override async ValueTask<TypeReaderResult<CommandOrCrInfo>> ReadAsync(ICommandContext ctx, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
if (_exprs.ExpressionExists(context.Guild?.Id, input)) if (_exprs.ExpressionExists(ctx.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(_commandHandler, _cmds).ReadAsync(context, input); var cmd = await new CommandTypeReader(_commandHandler, _cmds).ReadAsync(ctx, input);
if (cmd.IsSuccess) if (cmd.IsSuccess)
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name, return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name,
CommandOrCrInfo.Type.Normal)); CommandOrCrInfo.Type.Normal));
return TypeReaderResult.FromError(CommandError.ParseFailed, "No such command or cr found."); return TypeReaderResult.FromError<CommandOrCrInfo>(CommandError.ParseFailed, "No such command or cr found.");
} }
} }

View File

@@ -3,11 +3,11 @@ namespace NadekoBot.Common.TypeReaders;
public sealed class EmoteTypeReader : NadekoTypeReader<Emote> public sealed class EmoteTypeReader : NadekoTypeReader<Emote>
{ {
public override Task<TypeReaderResult> ReadAsync(ICommandContext ctx, string input) public override ValueTask<TypeReaderResult<Emote>> ReadAsync(ICommandContext ctx, string input)
{ {
if (!Emote.TryParse(input, out var emote)) if (!Emote.TryParse(input, out var emote))
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input is not a valid emote")); return new(TypeReaderResult.FromError<Emote>(CommandError.ParseFailed, "Input is not a valid emote"));
return Task.FromResult(TypeReaderResult.FromSuccess(emote)); return new(TypeReaderResult.FromSuccess(emote));
} }
} }

View File

@@ -10,14 +10,14 @@ public sealed class GuildDateTimeTypeReader : NadekoTypeReader<GuildDateTime>
public GuildDateTimeTypeReader(GuildTimezoneService gts) public GuildDateTimeTypeReader(GuildTimezoneService gts)
=> _gts = gts; => _gts = gts;
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<GuildDateTime>> ReadAsync(ICommandContext context, string input)
{ {
var gdt = Parse(context.Guild.Id, input); var gdt = Parse(context.Guild.Id, input);
if (gdt is null) if (gdt is null)
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, return new(TypeReaderResult.FromError<GuildDateTime>(CommandError.ParseFailed,
"Input string is in an incorrect format.")); "Input string is in an incorrect format."));
return Task.FromResult(TypeReaderResult.FromSuccess(gdt)); return new(TypeReaderResult.FromSuccess(gdt));
} }
private GuildDateTime Parse(ulong guildId, string input) private GuildDateTime Parse(ulong guildId, string input)

View File

@@ -8,18 +8,17 @@ public sealed class GuildTypeReader : NadekoTypeReader<IGuild>
public GuildTypeReader(DiscordSocketClient client) public GuildTypeReader(DiscordSocketClient client)
=> _client = client; => _client = client;
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<IGuild>> ReadAsync(ICommandContext context, string input)
{ {
input = input.Trim().ToUpperInvariant(); input = input.Trim().ToUpperInvariant();
var guilds = _client.Guilds; var guilds = _client.Guilds;
var guild = guilds.FirstOrDefault(g => g.Id.ToString().Trim().ToUpperInvariant() == input) IGuild guild = guilds.FirstOrDefault(g => g.Id.ToString().Trim().ToUpperInvariant() == input) //by id
?? //by id ?? guilds.FirstOrDefault(g => g.Name.Trim().ToUpperInvariant() == input); //by name
guilds.FirstOrDefault(g => g.Name.Trim().ToUpperInvariant() == input); //by name
if (guild is not null) if (guild is not null)
return Task.FromResult(TypeReaderResult.FromSuccess(guild)); return new(TypeReaderResult.FromSuccess(guild));
return Task.FromResult( return new(
TypeReaderResult.FromError(CommandError.ParseFailed, "No guild by that name or Id found")); TypeReaderResult.FromError<IGuild>(CommandError.ParseFailed, "No guild by that name or Id found"));
} }
} }

View File

@@ -3,17 +3,17 @@ namespace NadekoBot.Common.TypeReaders;
public sealed class KwumTypeReader : NadekoTypeReader<kwum> public sealed class KwumTypeReader : NadekoTypeReader<kwum>
{ {
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<kwum>> ReadAsync(ICommandContext context, string input)
{ {
if (kwum.TryParse(input, out var val)) if (kwum.TryParse(input, out var val))
return Task.FromResult(TypeReaderResult.FromSuccess(val)); return new(TypeReaderResult.FromSuccess(val));
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input is not a valid kwum")); return new(TypeReaderResult.FromError<kwum>(CommandError.ParseFailed, "Input is not a valid kwum"));
} }
} }
public sealed class SmartTextTypeReader : NadekoTypeReader<SmartText> public sealed class SmartTextTypeReader : NadekoTypeReader<SmartText>
{ {
public override Task<TypeReaderResult> ReadAsync(ICommandContext ctx, string input) public override ValueTask<TypeReaderResult<SmartText>> ReadAsync(ICommandContext ctx, string input)
=> Task.FromResult(TypeReaderResult.FromSuccess(SmartText.CreateFrom(input))); => new(TypeReaderResult.FromSuccess(SmartText.CreateFrom(input)));
} }

View File

@@ -8,16 +8,16 @@ public sealed class ModuleTypeReader : NadekoTypeReader<ModuleInfo>
public ModuleTypeReader(CommandService cmds) public ModuleTypeReader(CommandService cmds)
=> _cmds = cmds; => _cmds = cmds;
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<ModuleInfo>> ReadAsync(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()) var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule())
.FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input) .FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input)
?.Key; ?.Key;
if (module is null) if (module is null)
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such module found.")); return new(TypeReaderResult.FromError<ModuleInfo>(CommandError.ParseFailed, "No such module found."));
return Task.FromResult(TypeReaderResult.FromSuccess(module)); return new(TypeReaderResult.FromSuccess(module));
} }
} }
@@ -28,16 +28,16 @@ public sealed class ModuleOrCrTypeReader : NadekoTypeReader<ModuleOrCrInfo>
public ModuleOrCrTypeReader(CommandService cmds) public ModuleOrCrTypeReader(CommandService cmds)
=> _cmds = cmds; => _cmds = cmds;
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<ModuleOrCrInfo>> ReadAsync(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()) var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule())
.FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input) .FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input)
?.Key; ?.Key;
if (module is null && input != "ACTUALEXPRESSIONS") if (module is null && input != "ACTUALEXPRESSIONS")
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such module found.")); return new(TypeReaderResult.FromError<ModuleOrCrInfo>(CommandError.ParseFailed, "No such module found."));
return Task.FromResult(TypeReaderResult.FromSuccess(new ModuleOrCrInfo { Name = input })); return new(TypeReaderResult.FromSuccess(new ModuleOrCrInfo { Name = input }));
} }
} }

View File

@@ -4,8 +4,40 @@ namespace NadekoBot.Common.TypeReaders;
[MeansImplicitUse(ImplicitUseTargetFlags.Default | ImplicitUseTargetFlags.WithInheritors)] [MeansImplicitUse(ImplicitUseTargetFlags.Default | ImplicitUseTargetFlags.WithInheritors)]
public abstract class NadekoTypeReader<T> : TypeReader public abstract class NadekoTypeReader<T> : TypeReader
{ {
public abstract Task<TypeReaderResult> ReadAsync(ICommandContext ctx, string input); public abstract ValueTask<TypeReaderResult<T>> ReadAsync(ICommandContext ctx, string input);
public override Task<TypeReaderResult> ReadAsync(ICommandContext ctx, string input, IServiceProvider services) public override async Task<Discord.Commands.TypeReaderResult> ReadAsync(
=> ReadAsync(ctx, input); ICommandContext ctx,
string input,
IServiceProvider services)
=> await ReadAsync(ctx, input);
}
public static class TypeReaderResult
{
public static TypeReaderResult<T> FromError<T>(CommandError error, string reason)
=> Discord.Commands.TypeReaderResult.FromError(error, reason);
public static TypeReaderResult<T> FromSuccess<T>(in T value)
=> Discord.Commands.TypeReaderResult.FromSuccess(value);
}
public readonly struct TypeReaderResult<T>
{
public bool IsSuccess
=> _result.IsSuccess;
public IReadOnlyCollection<TypeReaderValue> Values
=> _result.Values;
private readonly Discord.Commands.TypeReaderResult _result;
private TypeReaderResult(in Discord.Commands.TypeReaderResult result)
=> _result = result;
public static implicit operator TypeReaderResult<T>(in Discord.Commands.TypeReaderResult result)
=> new(result);
public static implicit operator Discord.Commands.TypeReaderResult(in TypeReaderResult<T> wrapper)
=> wrapper._result;
} }

View File

@@ -8,7 +8,7 @@ namespace NadekoBot.Common.TypeReaders;
/// </summary> /// </summary>
public sealed class PermissionActionTypeReader : NadekoTypeReader<PermissionAction> public sealed class PermissionActionTypeReader : NadekoTypeReader<PermissionAction>
{ {
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<PermissionAction>> ReadAsync(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
switch (input) switch (input)
@@ -21,7 +21,7 @@ public sealed class PermissionActionTypeReader : NadekoTypeReader<PermissionActi
case "ALLOW": case "ALLOW":
case "PERMIT": case "PERMIT":
case "UNBAN": case "UNBAN":
return Task.FromResult(TypeReaderResult.FromSuccess(PermissionAction.Enable)); return new(TypeReaderResult.FromSuccess(PermissionAction.Enable));
case "0": case "0":
case "F": case "F":
case "FALSE": case "FALSE":
@@ -30,9 +30,9 @@ public sealed class PermissionActionTypeReader : NadekoTypeReader<PermissionActi
case "DISABLED": case "DISABLED":
case "DISALLOW": case "DISALLOW":
case "BAN": case "BAN":
return Task.FromResult(TypeReaderResult.FromSuccess(PermissionAction.Disable)); return new(TypeReaderResult.FromSuccess(PermissionAction.Disable));
default: default:
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, return new(TypeReaderResult.FromError<PermissionAction>(CommandError.ParseFailed,
"Did not receive a valid boolean value")); "Did not receive a valid boolean value"));
} }
} }

View File

@@ -5,7 +5,7 @@ namespace NadekoBot.Common.TypeReaders;
public sealed class Rgba32TypeReader : NadekoTypeReader<Color> public sealed class Rgba32TypeReader : NadekoTypeReader<Color>
{ {
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override async ValueTask<TypeReaderResult<Color>> ReadAsync(ICommandContext context, string input)
{ {
await Task.Yield(); await Task.Yield();
@@ -16,7 +16,7 @@ public sealed class Rgba32TypeReader : NadekoTypeReader<Color>
} }
catch catch
{ {
return TypeReaderResult.FromError(CommandError.ParseFailed, "Parameter is not a valid color hex."); return TypeReaderResult.FromError<Color>(CommandError.ParseFailed, "Parameter is not a valid color hex.");
} }
} }
} }

View File

@@ -18,12 +18,10 @@ public sealed class ShmartNumberTypeReader : NadekoTypeReader<ShmartNumber>
_gambling = gambling; _gambling = gambling;
} }
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<ShmartNumber>> ReadAsync(ICommandContext context, string input)
{ {
await Task.Yield();
if (string.IsNullOrWhiteSpace(input)) if (string.IsNullOrWhiteSpace(input))
return TypeReaderResult.FromError(CommandError.ParseFailed, "Input is empty."); return new(TypeReaderResult.FromError<ShmartNumber>(CommandError.ParseFailed, "Input is empty."));
var i = input.Trim().ToUpperInvariant(); var i = input.Trim().ToUpperInvariant();
@@ -32,17 +30,17 @@ public sealed class ShmartNumberTypeReader : NadekoTypeReader<ShmartNumber>
//can't add m because it will conflict with max atm //can't add m because it will conflict with max atm
if (TryHandlePercentage(context, i, out var num)) if (TryHandlePercentage(context, i, out var num))
return TypeReaderResult.FromSuccess(new ShmartNumber(num, i)); return new(TypeReaderResult.FromSuccess(new ShmartNumber(num, i)));
try try
{ {
var expr = new Expression(i, EvaluateOptions.IgnoreCase); var expr = new Expression(i, EvaluateOptions.IgnoreCase);
expr.EvaluateParameter += (str, ev) => EvaluateParam(str, ev, context); 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 new(TypeReaderResult.FromSuccess(new ShmartNumber(lon, input)));
} }
catch (Exception) catch (Exception)
{ {
return TypeReaderResult.FromError(CommandError.ParseFailed, $"Invalid input: {input}"); return ValueTask.FromResult(TypeReaderResult.FromError<Common.ShmartNumber>(CommandError.ParseFailed, $"Invalid input: {input}"));
} }
} }

View File

@@ -5,18 +5,18 @@ namespace NadekoBot.Common.TypeReaders;
public sealed class StoopidTimeTypeReader : NadekoTypeReader<StoopidTime> public sealed class StoopidTimeTypeReader : NadekoTypeReader<StoopidTime>
{ {
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input) public override ValueTask<TypeReaderResult<StoopidTime>> ReadAsync(ICommandContext context, string input)
{ {
if (string.IsNullOrWhiteSpace(input)) if (string.IsNullOrWhiteSpace(input))
return Task.FromResult(TypeReaderResult.FromError(CommandError.Unsuccessful, "Input is empty.")); return new(TypeReaderResult.FromError<StoopidTime>(CommandError.Unsuccessful, "Input is empty."));
try try
{ {
var time = StoopidTime.FromInput(input); var time = StoopidTime.FromInput(input);
return Task.FromResult(TypeReaderResult.FromSuccess(time)); return new(TypeReaderResult.FromSuccess(time));
} }
catch (Exception ex) catch (Exception ex)
{ {
return Task.FromResult(TypeReaderResult.FromError(CommandError.Exception, ex.Message)); return new(TypeReaderResult.FromError<StoopidTime>(CommandError.Exception, ex.Message));
} }
} }
} }

View File

@@ -1,6 +1,7 @@
#nullable disable #nullable disable
namespace NadekoBot.Common.Yml; namespace NadekoBot.Common.Yml;
[AttributeUsage(AttributeTargets.Property)]
public class CommentAttribute : Attribute public class CommentAttribute : Attribute
{ {
public string Comment { get; } public string Comment { get; }

View File

@@ -10,7 +10,7 @@ public class CommentGatheringTypeInspector : TypeInspectorSkeleton
private readonly ITypeInspector _innerTypeDescriptor; private readonly ITypeInspector _innerTypeDescriptor;
public CommentGatheringTypeInspector(ITypeInspector innerTypeDescriptor) public CommentGatheringTypeInspector(ITypeInspector innerTypeDescriptor)
=> _innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException("innerTypeDescriptor"); => _innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException(nameof(innerTypeDescriptor));
public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container) public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container)
=> _innerTypeDescriptor.GetProperties(type, container).Select(d => new CommentsPropertyDescriptor(d)); => _innerTypeDescriptor.GetProperties(type, container).Select(d => new CommentsPropertyDescriptor(d));

View File

@@ -9,7 +9,7 @@ public static class MusicPlaylistExtensions
public static List<MusicPlaylist> GetPlaylistsOnPage(this DbSet<MusicPlaylist> playlists, int num) public static List<MusicPlaylist> GetPlaylistsOnPage(this DbSet<MusicPlaylist> playlists, int num)
{ {
if (num < 1) if (num < 1)
throw new IndexOutOfRangeException(); throw new ArgumentOutOfRangeException(nameof(num));
return playlists.AsQueryable().Skip((num - 1) * 20).Take(20).Include(pl => pl.Songs).ToList(); return playlists.AsQueryable().Skip((num - 1) * 20).Take(20).Include(pl => pl.Songs).ToList();
} }

View File

@@ -24,7 +24,7 @@ public class AntiSpamSetting : DbEntity
public PunishmentAction Action { get; set; } public PunishmentAction Action { get; set; }
public int MessageThreshold { get; set; } = 3; public int MessageThreshold { get; set; } = 3;
public int MuteTime { get; set; } = 0; public int MuteTime { get; set; }
public ulong? RoleId { get; set; } public ulong? RoleId { get; set; }
public HashSet<AntiSpamIgnore> IgnoredChannels { get; set; } = new(); public HashSet<AntiSpamIgnore> IgnoredChannels { get; set; } = new();
} }

View File

@@ -8,7 +8,7 @@ public class GuildConfig : DbEntity
{ {
public ulong GuildId { get; set; } public ulong GuildId { get; set; }
public string Prefix { get; set; } = null; public string Prefix { get; set; }
public bool DeleteMessageOnCommand { get; set; } public bool DeleteMessageOnCommand { get; set; }
public HashSet<DelMsgOnCmdChannel> DelMsgOnCmdChannels { get; set; } = new(); public HashSet<DelMsgOnCmdChannel> DelMsgOnCmdChannels { get; set; } = new();
@@ -16,8 +16,6 @@ public class GuildConfig : DbEntity
public string AutoAssignRoleIds { get; set; } public string AutoAssignRoleIds { get; set; }
//greet stuff //greet stuff
public bool AutoDeleteGreetMessages { get; set; } //unused
public bool AutoDeleteByeMessages { get; set; } // unused
public int AutoDeleteGreetMessagesTimer { get; set; } = 30; public int AutoDeleteGreetMessagesTimer { get; set; } = 30;
public int AutoDeleteByeMessagesTimer { get; set; } = 30; public int AutoDeleteByeMessagesTimer { get; set; } = 30;
@@ -45,7 +43,7 @@ public class GuildConfig : DbEntity
public List<Permissionv2> Permissions { get; set; } public List<Permissionv2> Permissions { get; set; }
public bool VerbosePermissions { get; set; } = true; public bool VerbosePermissions { get; set; } = true;
public string PermissionRole { get; set; } = null; public string PermissionRole { get; set; }
public HashSet<CommandCooldown> CommandCooldowns { get; set; } = new(); public HashSet<CommandCooldown> CommandCooldowns { get; set; } = new();
@@ -71,8 +69,8 @@ public class GuildConfig : DbEntity
public AntiSpamSetting AntiSpamSetting { get; set; } public AntiSpamSetting AntiSpamSetting { get; set; }
public AntiAltSetting AntiAltSetting { get; set; } public AntiAltSetting AntiAltSetting { get; set; }
public string Locale { get; set; } = null; public string Locale { get; set; }
public string TimeZoneId { get; set; } = null; public string TimeZoneId { get; set; }
public HashSet<UnmuteTimer> UnmuteTimers { get; set; } = new(); public HashSet<UnmuteTimer> UnmuteTimers { get; set; } = new();
public HashSet<UnbanTimer> UnbanTimer { get; set; } = new(); public HashSet<UnbanTimer> UnbanTimer { get; set; } = new();
@@ -85,8 +83,8 @@ public class GuildConfig : DbEntity
public HashSet<SlowmodeIgnoredRole> SlowmodeIgnoredRoles { get; set; } public HashSet<SlowmodeIgnoredRole> SlowmodeIgnoredRoles { get; set; }
public List<ShopEntry> ShopEntries { get; set; } public List<ShopEntry> ShopEntries { get; set; }
public ulong? GameVoiceChannel { get; set; } = null; public ulong? GameVoiceChannel { get; set; }
public bool VerboseErrors { get; set; } = false; public bool VerboseErrors { get; set; }
public StreamRoleSettings StreamRole { get; set; } public StreamRoleSettings StreamRole { get; set; }
@@ -95,7 +93,7 @@ public class GuildConfig : DbEntity
public IndexedCollection<ReactionRoleMessage> ReactionRoleMessages { get; set; } = new(); public IndexedCollection<ReactionRoleMessage> ReactionRoleMessages { get; set; } = new();
public bool NotifyStreamOffline { get; set; } public bool NotifyStreamOffline { get; set; }
public List<GroupName> SelfAssignableRoleGroupNames { get; set; } public List<GroupName> SelfAssignableRoleGroupNames { get; set; }
public int WarnExpireHours { get; set; } = 0; public int WarnExpireHours { get; set; }
public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear; public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear;
#region Boost Message #region Boost Message

View File

@@ -21,7 +21,7 @@ public class MusicPlayerSettings
/// <summary> /// <summary>
/// Channel id the bot will always try to send track related messages to /// Channel id the bot will always try to send track related messages to
/// </summary> /// </summary>
public ulong? MusicChannelId { get; set; } = null; public ulong? MusicChannelId { get; set; }
/// <summary> /// <summary>
/// Default volume player will be created with /// Default volume player will be created with
@@ -32,7 +32,7 @@ public class MusicPlayerSettings
/// Whether the bot should auto disconnect from the voice channel once the queue is done /// Whether the bot should auto disconnect from the voice channel once the queue is done
/// This only has effect if /// This only has effect if
/// </summary> /// </summary>
public bool AutoDisconnect { get; set; } = false; public bool AutoDisconnect { get; set; }
/// <summary> /// <summary>
/// Selected quality preset for the music player /// Selected quality preset for the music player

View File

@@ -22,6 +22,7 @@ global using GuildPerm = Discord.GuildPermission;
global using ChannelPerm = Discord.ChannelPermission; global using ChannelPerm = Discord.ChannelPermission;
global using BotPermAttribute = Discord.Commands.RequireBotPermissionAttribute; global using BotPermAttribute = Discord.Commands.RequireBotPermissionAttribute;
global using LeftoverAttribute = Discord.Commands.RemainderAttribute; global using LeftoverAttribute = Discord.Commands.RemainderAttribute;
global using TypeReaderResult = NadekoBot.Common.TypeReaders.TypeReaderResult;
// non-essential // non-essential
global using JetBrains.Annotations; global using JetBrains.Annotations;

View File

@@ -341,38 +341,6 @@ public class GreetService : INService, IReadyExecutor
return settings; return settings;
} }
public async Task<bool> SetSettings(ulong guildId, GreetSettings settings)
{
if (settings.AutoDeleteByeMessagesTimer is > 600 or < 0
|| settings.AutoDeleteGreetMessagesTimer is > 600 or < 0)
return false;
await using var uow = _db.GetDbContext();
var conf = uow.GuildConfigsForId(guildId, set => set);
conf.DmGreetMessageText = settings.DmGreetMessageText?.SanitizeMentions();
conf.ChannelGreetMessageText = settings.ChannelGreetMessageText?.SanitizeMentions();
conf.ChannelByeMessageText = settings.ChannelByeMessageText?.SanitizeMentions();
conf.AutoDeleteGreetMessagesTimer = settings.AutoDeleteGreetMessagesTimer;
conf.AutoDeleteGreetMessages = settings.AutoDeleteGreetMessagesTimer > 0;
conf.AutoDeleteByeMessagesTimer = settings.AutoDeleteByeMessagesTimer;
conf.AutoDeleteByeMessages = settings.AutoDeleteByeMessagesTimer > 0;
conf.GreetMessageChannelId = settings.GreetMessageChannelId;
conf.ByeMessageChannelId = settings.ByeMessageChannelId;
conf.SendChannelGreetMessage = settings.SendChannelGreetMessage;
conf.SendChannelByeMessage = settings.SendChannelByeMessage;
await uow.SaveChangesAsync();
var toAdd = GreetSettings.Create(conf);
_guildConfigsCache[guildId] = toAdd;
return true;
}
public async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null) public async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
{ {
await using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();

View File

@@ -56,13 +56,13 @@ public partial class Administration
CultureInfo ci; CultureInfo ci;
if (name.Trim().ToLowerInvariant() == "default") if (name.Trim().ToLowerInvariant() == "default")
{ {
Localization.RemoveGuildCulture(ctx.Guild); _localization.RemoveGuildCulture(ctx.Guild);
ci = Localization.DefaultCultureInfo; ci = _localization.DefaultCultureInfo;
} }
else else
{ {
ci = new(name); ci = new(name);
Localization.SetGuildCulture(ctx.Guild, ci); _localization.SetGuildCulture(ctx.Guild, ci);
} }
await ReplyConfirmLocalizedAsync(strs.lang_set(Format.Bold(ci.ToString()), Format.Bold(ci.NativeName))); await ReplyConfirmLocalizedAsync(strs.lang_set(Format.Bold(ci.ToString()), Format.Bold(ci.NativeName)));
@@ -76,7 +76,7 @@ public partial class Administration
[Cmd] [Cmd]
public async partial Task LanguageSetDefault() public async partial Task LanguageSetDefault()
{ {
var cul = Localization.DefaultCultureInfo; var cul = _localization.DefaultCultureInfo;
await ReplyErrorLocalizedAsync(strs.lang_set_bot_show(cul, cul.NativeName)); await ReplyErrorLocalizedAsync(strs.lang_set_bot_show(cul, cul.NativeName));
} }
@@ -89,13 +89,13 @@ public partial class Administration
CultureInfo ci; CultureInfo ci;
if (name.Trim().ToLowerInvariant() == "default") if (name.Trim().ToLowerInvariant() == "default")
{ {
Localization.ResetDefaultCulture(); _localization.ResetDefaultCulture();
ci = Localization.DefaultCultureInfo; ci = _localization.DefaultCultureInfo;
} }
else else
{ {
ci = new(name); ci = new(name);
Localization.SetDefaultCulture(ci); _localization.SetDefaultCulture(ci);
} }
await ReplyConfirmLocalizedAsync(strs.lang_set_bot(Format.Bold(ci.ToString()), await ReplyConfirmLocalizedAsync(strs.lang_set_bot(Format.Bold(ci.ToString()),

View File

@@ -14,7 +14,7 @@ public partial class Administration
[Cmd] [Cmd]
[Priority(1)] [Priority(1)]
public async partial Task Prefix() public async partial Task Prefix()
=> await ReplyConfirmLocalizedAsync(strs.prefix_current(Format.Code(CmdHandler.GetPrefix(ctx.Guild)))); => await ReplyConfirmLocalizedAsync(strs.prefix_current(Format.Code(_cmdHandler.GetPrefix(ctx.Guild))));
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -33,7 +33,7 @@ public partial class Administration
return; return;
var oldPrefix = prefix; var oldPrefix = prefix;
var newPrefix = CmdHandler.SetPrefix(ctx.Guild, toSet); var newPrefix = _cmdHandler.SetPrefix(ctx.Guild, toSet);
await ReplyConfirmLocalizedAsync(strs.prefix_new(Format.Code(oldPrefix), Format.Code(newPrefix))); await ReplyConfirmLocalizedAsync(strs.prefix_new(Format.Code(oldPrefix), Format.Code(newPrefix)));
} }
@@ -44,12 +44,12 @@ public partial class Administration
{ {
if (string.IsNullOrWhiteSpace(toSet)) if (string.IsNullOrWhiteSpace(toSet))
{ {
await ReplyConfirmLocalizedAsync(strs.defprefix_current(CmdHandler.GetPrefix())); await ReplyConfirmLocalizedAsync(strs.defprefix_current(_cmdHandler.GetPrefix()));
return; return;
} }
var oldPrefix = CmdHandler.GetPrefix(); var oldPrefix = _cmdHandler.GetPrefix();
var newPrefix = CmdHandler.SetDefaultPrefix(toSet); var newPrefix = _cmdHandler.SetDefaultPrefix(toSet);
await ReplyConfirmLocalizedAsync(strs.defprefix_new(Format.Code(oldPrefix), Format.Code(newPrefix))); await ReplyConfirmLocalizedAsync(strs.defprefix_new(Format.Code(oldPrefix), Format.Code(newPrefix)));
} }

View File

@@ -130,7 +130,7 @@ public partial class Utility
var startCount = page * activityPerPage; var startCount = page * activityPerPage;
var str = new StringBuilder(); var str = new StringBuilder();
foreach (var kvp in CmdHandler.UserMessagesSent.OrderByDescending(kvp => kvp.Value) foreach (var kvp in _cmdHandler.UserMessagesSent.OrderByDescending(kvp => kvp.Value)
.Skip(page * activityPerPage) .Skip(page * activityPerPage)
.Take(activityPerPage)) .Take(activityPerPage))
str.AppendLine(GetText(strs.activity_line(++startCount, str.AppendLine(GetText(strs.activity_line(++startCount,
@@ -142,7 +142,7 @@ public partial class Utility
.WithTitle(GetText(strs.activity_page(page + 1))) .WithTitle(GetText(strs.activity_page(page + 1)))
.WithOkColor() .WithOkColor()
.WithFooter(GetText( .WithFooter(GetText(
strs.activity_users_total(CmdHandler.UserMessagesSent.Count))) strs.activity_users_total(_cmdHandler.UserMessagesSent.Count)))
.WithDescription(str.ToString())); .WithDescription(str.ToString()));
} }
} }

View File

@@ -6,11 +6,17 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<EnablePreviewFeatures>True</EnablePreviewFeatures> <EnablePreviewFeatures>True</EnablePreviewFeatures>
<ImplicitUsings>true</ImplicitUsings> <ImplicitUsings>true</ImplicitUsings>
<!-- Output/build -->
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory> <RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
<OutputType>exe</OutputType> <OutputType>exe</OutputType>
<ApplicationIcon>nadeko_icon.ico</ApplicationIcon> <ApplicationIcon>nadeko_icon.ico</ApplicationIcon>
<NoWarn>CS1066,CA1069</NoWarn>
<AnalysisMode>Recommended</AnalysisMode> <!-- Analysis/Warnings -->
<!-- <AnalysisMode>Recommended</AnalysisMode>-->
<!-- <AnalysisModeGlobalization>None</AnalysisModeGlobalization>-->
<!-- <AnalysisModeNaming>None</AnalysisModeNaming> -->
<NoWarn>CS1066</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,5 +1,3 @@
using NadekoBot.Services.Currency;
#nullable disable #nullable disable
namespace NadekoBot.Services; namespace NadekoBot.Services;