diff --git a/src/EllieBot/_common/AddRemove.cs b/src/EllieBot/_common/AddRemove.cs index bb3862e..cccd892 100644 --- a/src/EllieBot/_common/AddRemove.cs +++ b/src/EllieBot/_common/AddRemove.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Common; public enum AddRemove diff --git a/src/EllieBot/_common/Attributes/CmdAttribute.cs b/src/EllieBot/_common/Attributes/CmdAttribute.cs index a02fd1e..363348c 100644 --- a/src/EllieBot/_common/Attributes/CmdAttribute.cs +++ b/src/EllieBot/_common/Attributes/CmdAttribute.cs @@ -1,4 +1,4 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; namespace EllieBot.Common.Attributes; diff --git a/src/EllieBot/_common/Attributes/DIIgnoreAttribute.cs b/src/EllieBot/_common/Attributes/DIIgnoreAttribute.cs index 7be799a..608e079 100644 --- a/src/EllieBot/_common/Attributes/DIIgnoreAttribute.cs +++ b/src/EllieBot/_common/Attributes/DIIgnoreAttribute.cs @@ -7,5 +7,5 @@ namespace EllieBot.Common; [AttributeUsage(AttributeTargets.Class)] public class DIIgnoreAttribute : Attribute { - + } \ No newline at end of file diff --git a/src/EllieBot/_common/Attributes/EllieOptionsAttribute.cs b/src/EllieBot/_common/Attributes/EllieOptionsAttribute.cs index c94b109..7db4315 100644 --- a/src/EllieBot/_common/Attributes/EllieOptionsAttribute.cs +++ b/src/EllieBot/_common/Attributes/EllieOptionsAttribute.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.Attributes; +namespace EllieBot.Common.Attributes; [AttributeUsage(AttributeTargets.Method)] public sealed class EllieOptionsAttribute : Attribute diff --git a/src/EllieBot/_common/Attributes/OnlyPublicBotAttribute.cs b/src/EllieBot/_common/Attributes/OnlyPublicBotAttribute.cs index 6ae9408..2ee7958 100644 --- a/src/EllieBot/_common/Attributes/OnlyPublicBotAttribute.cs +++ b/src/EllieBot/_common/Attributes/OnlyPublicBotAttribute.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System.Diagnostics.CodeAnalysis; namespace EllieBot.Common; diff --git a/src/EllieBot/_common/Attributes/OwnerOnlyAttribute.cs b/src/EllieBot/_common/Attributes/OwnerOnlyAttribute.cs index 7aa9317..c1baa53 100644 --- a/src/EllieBot/_common/Attributes/OwnerOnlyAttribute.cs +++ b/src/EllieBot/_common/Attributes/OwnerOnlyAttribute.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace EllieBot.Common.Attributes; @@ -16,4 +16,4 @@ public sealed class OwnerOnlyAttribute : PreconditionAttribute ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Not owner")); } -} +} \ No newline at end of file diff --git a/src/EllieBot/_common/Attributes/RatelimitAttribute.cs b/src/EllieBot/_common/Attributes/RatelimitAttribute.cs index 7fcf9c8..54402d9 100644 --- a/src/EllieBot/_common/Attributes/RatelimitAttribute.cs +++ b/src/EllieBot/_common/Attributes/RatelimitAttribute.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace EllieBot.Common.Attributes; diff --git a/src/EllieBot/_common/Attributes/UserPermAttribute.cs b/src/EllieBot/_common/Attributes/UserPermAttribute.cs index 1b4ee75..2e0af03 100644 --- a/src/EllieBot/_common/Attributes/UserPermAttribute.cs +++ b/src/EllieBot/_common/Attributes/UserPermAttribute.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace Discord; diff --git a/src/EllieBot/_common/CommandNameLoadHelper.cs b/src/EllieBot/_common/CommandNameLoadHelper.cs index 3d69f2e..0a811e2 100644 --- a/src/EllieBot/_common/CommandNameLoadHelper.cs +++ b/src/EllieBot/_common/CommandNameLoadHelper.cs @@ -1,4 +1,4 @@ -using EllieBot.Common.Yml; +using EllieBot.Common.Yml; using YamlDotNet.Serialization; namespace EllieBot.Common.Attributes; diff --git a/src/EllieBot/_common/Configs/BotConfig.cs b/src/EllieBot/_common/Configs/BotConfig.cs index 0715701..0908577 100644 --- a/src/EllieBot/_common/Configs/BotConfig.cs +++ b/src/EllieBot/_common/Configs/BotConfig.cs @@ -44,13 +44,13 @@ public sealed partial class BotConfig : ICloneable or all owners? (this might cause the bot to lag if there's a lot of owners specified) """)] public bool ForwardToAllOwners { get; set; } - + [Comment(""" Any messages sent by users in Bot's DM to be forwarded to the specified channel. This option will only work when ForwardToAllOwners is set to false """)] public ulong? ForwardToChannel { get; set; } - + [Comment(""" Should the bot ignore messages from other bots? Settings this to false might get your bot banned if it gets into a spam loop with another bot. @@ -155,11 +155,11 @@ public sealed partial class BotConfig : ICloneable ]; } - // [Comment(@"Whether the prefix will be a suffix, or prefix. - // For example, if your prefix is ! you will run a command called 'cash' by typing either - // '!cash @Someone' if your prefixIsSuffix: false or - // 'cash @Someone!' if your prefixIsSuffix: true")] - // public bool PrefixIsSuffix { get; set; } +// [Comment(@"Whether the prefix will be a suffix, or prefix. +// For example, if your prefix is ! you will run a command called 'cash' by typing either +// '!cash @Someone' if your prefixIsSuffix: false or +// 'cash @Someone!' if your prefixIsSuffix: true")] +// public bool PrefixIsSuffix { get; set; } // public string Prefixed(string text) => PrefixIsSuffix // ? text + Prefix diff --git a/src/EllieBot/_common/Configs/IConfigSeria.cs b/src/EllieBot/_common/Configs/IConfigSeria.cs index 1f96850..a5d3a10 100644 --- a/src/EllieBot/_common/Configs/IConfigSeria.cs +++ b/src/EllieBot/_common/Configs/IConfigSeria.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.Configs; +namespace EllieBot.Common.Configs; /// /// Base interface for available config serializers diff --git a/src/EllieBot/_common/Creds.cs b/src/EllieBot/_common/Creds.cs index f6aef5d..8f454a0 100644 --- a/src/EllieBot/_common/Creds.cs +++ b/src/EllieBot/_common/Creds.cs @@ -1,7 +1,7 @@ -#nullable disable +#nullable disable using EllieBot.Common.Yml; -namespace Ellie.Common; +namespace EllieBot.Common; public sealed class Creds : IBotCredentials { @@ -16,7 +16,7 @@ public sealed class Creds : IBotCredentials **DO NOT ADD PEOPLE YOU DON'T TRUST** """)] public ICollection OwnerIds { get; set; } - + [Comment("Keep this on 'true' unless you're sure your bot shouldn't use privileged intents or you're waiting to be accepted")] public bool UsePrivilegedIntents { get; set; } @@ -29,15 +29,24 @@ public sealed class Creds : IBotCredentials """)] public int TotalShards { get; set; } - [Comment( + [Comment(""" + Pledge 5$ or more on https://patreon.com/elliebot and connect your discord account to Patreon. + Go to https://dashy.elliebot.net and login with your discord account + Go to the Keys page and click "Generate New Key" and copy it here + You and anyone else with the permission to run `.prompt` command will be able to use natural language to run bot's commands. + For example '@Bot how's the weather in Paris' will return the current weather in Paris as if you were to run `.weather Paris` command + """)] + public string EllieAiToken { get; set; } + + [Comment( """ Login to https://console.cloud.google.com, create a new project, go to APIs & Services -> Library -> YouTube Data API and enable it. Then, go to APIs and Services -> Credentials and click Create credentials -> API key. Used only for Youtube Data Api (at the moment). """)] public string GoogleApiKey { get; set; } - - [Comment( + + [Comment( """ Create a new custom search here https://programmablesearchengine.google.com/cse/create/new Enable SafeSearch @@ -64,16 +73,16 @@ public sealed class Creds : IBotCredentials [Comment("""Official cleverbot api key.""")] public string CleverbotApiKey { get; set; } - [Comment(@"Official GPT-3 api key.")] + [Comment(@"OpenAi api key.")] public string Gpt3ApiKey { get; set; } - + [Comment(""" Which cache implementation should bot use. 'memory' - Cache will be in memory of the bot's process itself. Only use this on bots with a single shard. When the bot is restarted the cache is reset. 'redis' - Uses redis (which needs to be separately downloaded and installed). The cache will persist through bot restarts. You can configure connection string in creds.yml """)] public BotCacheImplemenation BotCache { get; set; } - + [Comment(""" Redis connection string. Don't change if you don't know what you're doing. Only used if botCache is set to 'redis' @@ -110,10 +119,10 @@ public sealed class Creds : IBotCredentials Used for cryptocurrency related commands. """)] public string CoinmarketcapApiKey { get; set; } - - // [Comment(@"https://polygon.io/dashboard/api-keys api key. Free plan allows for 5 queries per minute. - // Used for stocks related commands.")] - // public string PolygonIoApiKey { get; set; } + +// [Comment(@"https://polygon.io/dashboard/api-keys api key. Free plan allows for 5 queries per minute. +// Used for stocks related commands.")] +// public string PolygonIoApiKey { get; set; } [Comment("""Api key used for Osu related commands. Obtain this key at https://osu.ppy.sh/p/api""")] public string OsuApiKey { get; set; } @@ -171,7 +180,7 @@ public sealed class Creds : IBotCredentials RestartCommand = new RestartConfig(); Google = new GoogleApiConfig(); } - + public class DbOptions : IDbOptions { @@ -270,3 +279,6 @@ public class GoogleApiConfig : IGoogleApiConfig public string SearchId { get; init; } public string ImageSearchId { get; init; } } + + + diff --git a/src/EllieBot/_common/DoAsUserMessage.cs b/src/EllieBot/_common/DoAsUserMessage.cs index f8fba27..f7f2980 100644 --- a/src/EllieBot/_common/DoAsUserMessage.cs +++ b/src/EllieBot/_common/DoAsUserMessage.cs @@ -1,4 +1,4 @@ -using MessageType = Discord.MessageType; +using MessageType = Discord.MessageType; namespace EllieBot.Modules.Administration; diff --git a/src/EllieBot/_common/DownloadTracker.cs b/src/EllieBot/_common/DownloadTracker.cs index 51d7cc6..b886228 100644 --- a/src/EllieBot/_common/DownloadTracker.cs +++ b/src/EllieBot/_common/DownloadTracker.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Common; public class DownloadTracker : IEService diff --git a/src/EllieBot/_common/EllieModule.cs b/src/EllieBot/_common/EllieModule.cs index ba52708..d8867c1 100644 --- a/src/EllieBot/_common/EllieModule.cs +++ b/src/EllieBot/_common/EllieModule.cs @@ -91,7 +91,7 @@ public abstract class EllieModule : ModuleBase if (validate is not null && !validate(arg.Content)) return Task.CompletedTask; - + if (userInputTask.TrySetResult(arg.Content)) userMsg.DeleteAfter(1); diff --git a/src/EllieBot/_common/ILogCommandService.cs b/src/EllieBot/_common/ILogCommandService.cs index 344be96..7e5bcd5 100644 --- a/src/EllieBot/_common/ILogCommandService.cs +++ b/src/EllieBot/_common/ILogCommandService.cs @@ -28,7 +28,7 @@ public enum LogType VoicePresence, UserMuted, UserWarned, - + ThreadDeleted, ThreadCreated } \ No newline at end of file diff --git a/src/EllieBot/_common/IPermissionChecker.cs b/src/EllieBot/_common/IPermissionChecker.cs index 81aaa64..5b4bc48 100644 --- a/src/EllieBot/_common/IPermissionChecker.cs +++ b/src/EllieBot/_common/IPermissionChecker.cs @@ -17,14 +17,14 @@ public partial class PermCheckResult { public bool IsAllowed => IsT0; - - public bool IsCooldown + + public bool IsCooldown => IsT1; - - public bool IsGlobalBlock + + public bool IsGlobalBlock => IsT2; - - public bool IsDisallowed + + public bool IsDisallowed => IsT3; } diff --git a/src/EllieBot/_common/IPlaceholderProvider.cs b/src/EllieBot/_common/IPlaceholderProvider.cs index 1766577..20fcc12 100644 --- a/src/EllieBot/_common/IPlaceholderProvider.cs +++ b/src/EllieBot/_common/IPlaceholderProvider.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Common; public interface IPlaceholderProvider diff --git a/src/EllieBot/_common/ImageUrls.cs b/src/EllieBot/_common/ImageUrls.cs index 7274e60..449043f 100644 --- a/src/EllieBot/_common/ImageUrls.cs +++ b/src/EllieBot/_common/ImageUrls.cs @@ -5,7 +5,7 @@ using Cloneable; namespace EllieBot.Common; [Cloneable] -public partial class ImageUrls : ICloneable +public partial class ImageUrls : ICloneable { [Comment("DO NOT CHANGE")] public int Version { get; set; } = 3; diff --git a/src/EllieBot/_common/Interaction/EllieInteraction.cs b/src/EllieBot/_common/Interaction/EllieInteraction.cs index 89e2103..6157aad 100644 --- a/src/EllieBot/_common/Interaction/EllieInteraction.cs +++ b/src/EllieBot/_common/Interaction/EllieInteraction.cs @@ -1,4 +1,4 @@ -namespace EllieBot; +namespace EllieBot; public abstract class EllieInteractionBase { @@ -85,6 +85,9 @@ public abstract class EllieInteractionBase public Task ExecuteOnActionAsync(SocketMessageComponent smc) => _onAction(smc); + + public void SetCompleted() + => _interactionCompletedSource.TrySetResult(true); } public sealed class EllieModalSubmitHandler diff --git a/src/EllieBot/_common/Interaction/IEllieInteractionService.cs b/src/EllieBot/_common/Interaction/IEllieInteractionService.cs index 967e91d..4d2530c 100644 --- a/src/EllieBot/_common/Interaction/IEllieInteractionService.cs +++ b/src/EllieBot/_common/Interaction/IEllieInteractionService.cs @@ -20,9 +20,9 @@ public interface IEllieInteractionService SelectMenuBuilder menu, Func onTrigger, bool singleUse = true); - + EllieInteractionBase Create( - ulong userId, + ulong userId, ButtonBuilder button, ModalBuilder modal, Func onTrigger, diff --git a/src/EllieBot/_common/Interaction/Models/EllieButtonInteraction.cs b/src/EllieBot/_common/Interaction/Models/EllieButtonInteraction.cs index 3e65c1c..1ad7128 100644 --- a/src/EllieBot/_common/Interaction/Models/EllieButtonInteraction.cs +++ b/src/EllieBot/_common/Interaction/Models/EllieButtonInteraction.cs @@ -1,4 +1,4 @@ -namespace EllieBot; +namespace EllieBot; public sealed class EllieButtonInteractionHandler : EllieInteractionBase { @@ -16,6 +16,6 @@ public sealed class EllieButtonInteractionHandler : EllieInteractionBase public ButtonBuilder Button { get; } - public override void AddTo(ComponentBuilder cb) + public override void AddTo(ComponentBuilder cb) => cb.WithButton(Button); } \ No newline at end of file diff --git a/src/EllieBot/_common/JsonConverters/CultureInfoConverter.cs b/src/EllieBot/_common/JsonConverters/CultureInfoConverter.cs index 28167d6..0c26f15 100644 --- a/src/EllieBot/_common/JsonConverters/CultureInfoConverter.cs +++ b/src/EllieBot/_common/JsonConverters/CultureInfoConverter.cs @@ -7,8 +7,8 @@ namespace EllieBot.Common.JsonConverters; public class CultureInfoConverter : JsonConverter { public override CultureInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - => new(reader.GetString() ?? "en_US"); + => new(reader.GetString() ?? "en-US"); - public override void Write(Utf8JsonWriter writer, CultureInfo value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, CultureInfo value, JsonSerializerOptions options) => writer.WriteStringValue(value.Name); } \ No newline at end of file diff --git a/src/EllieBot/_common/JsonConverters/NumberToStringConverter.cs b/src/EllieBot/_common/JsonConverters/NumberToStringConverter.cs new file mode 100644 index 0000000..bc20b10 --- /dev/null +++ b/src/EllieBot/_common/JsonConverters/NumberToStringConverter.cs @@ -0,0 +1,30 @@ +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +public class NumberToStringConverter : JsonConverter +{ + public override bool CanConvert(Type typeToConvert) + => typeof(string) == typeToConvert; + + public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + switch (reader.TokenType) + { + case JsonTokenType.Number: + return reader.TryGetInt64(out var l) + ? l.ToString() + : reader.GetDouble().ToString(CultureInfo.InvariantCulture); + case JsonTokenType.String: + return reader.GetString() ?? string.Empty; + default: + { + using var document = JsonDocument.ParseValue(ref reader); + return document.RootElement.Clone().ToString(); + } + } + } + + public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString()); +} \ No newline at end of file diff --git a/src/EllieBot/_common/JsonConverters/Rgba32Converter.cs b/src/EllieBot/_common/JsonConverters/Rgba32Converter.cs index ef619a6..906db1e 100644 --- a/src/EllieBot/_common/JsonConverters/Rgba32Converter.cs +++ b/src/EllieBot/_common/JsonConverters/Rgba32Converter.cs @@ -1,4 +1,4 @@ -using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.PixelFormats; using System.Text.Json; using System.Text.Json.Serialization; diff --git a/src/EllieBot/_common/Linq2DbExpressions.cs b/src/EllieBot/_common/Linq2DbExpressions.cs index a724652..53c90e6 100644 --- a/src/EllieBot/_common/Linq2DbExpressions.cs +++ b/src/EllieBot/_common/Linq2DbExpressions.cs @@ -9,7 +9,7 @@ public static class Linq2DbExpressions [ExpressionMethod(nameof(GuildOnShardExpression))] public static bool GuildOnShard(ulong guildId, int totalShards, int shardId) => throw new NotSupportedException(); - + private static Expression> GuildOnShardExpression() => (guildId, totalShards, shardId) => guildId / 4194304 % (ulong)totalShards == (ulong)shardId; diff --git a/src/EllieBot/_common/ModuleBehaviors/IExecNoCommand.cs b/src/EllieBot/_common/ModuleBehaviors/IExecNoCommand.cs index 4ceeaaf..f23d085 100644 --- a/src/EllieBot/_common/ModuleBehaviors/IExecNoCommand.cs +++ b/src/EllieBot/_common/ModuleBehaviors/IExecNoCommand.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.ModuleBehaviors; +namespace EllieBot.Common.ModuleBehaviors; /// /// Executed if no command was found for this message diff --git a/src/EllieBot/_common/ModuleBehaviors/IExecOnMessage.cs b/src/EllieBot/_common/ModuleBehaviors/IExecOnMessage.cs index 7b37a24..3e39152 100644 --- a/src/EllieBot/_common/ModuleBehaviors/IExecOnMessage.cs +++ b/src/EllieBot/_common/ModuleBehaviors/IExecOnMessage.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.ModuleBehaviors; +namespace EllieBot.Common.ModuleBehaviors; /// /// Implemented by modules to handle non-bot messages received diff --git a/src/EllieBot/_common/ModuleBehaviors/IExecPostCommand.cs b/src/EllieBot/_common/ModuleBehaviors/IExecPostCommand.cs index ccb949c..b97f584 100644 --- a/src/EllieBot/_common/ModuleBehaviors/IExecPostCommand.cs +++ b/src/EllieBot/_common/ModuleBehaviors/IExecPostCommand.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.ModuleBehaviors; +namespace EllieBot.Common.ModuleBehaviors; /// /// This interface's method is executed after the command successfully finished execution. diff --git a/src/EllieBot/_common/ModuleBehaviors/IExecPreCommand.cs b/src/EllieBot/_common/ModuleBehaviors/IExecPreCommand.cs index 438cbd0..4320d8f 100644 --- a/src/EllieBot/_common/ModuleBehaviors/IExecPreCommand.cs +++ b/src/EllieBot/_common/ModuleBehaviors/IExecPreCommand.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.ModuleBehaviors; +namespace EllieBot.Common.ModuleBehaviors; /// /// This interface's method is executed after a command was found but before it was executed. diff --git a/src/EllieBot/_common/ModuleBehaviors/IInputTransformer.cs b/src/EllieBot/_common/ModuleBehaviors/IInputTransformer.cs index 957e659..7039989 100644 --- a/src/EllieBot/_common/ModuleBehaviors/IInputTransformer.cs +++ b/src/EllieBot/_common/ModuleBehaviors/IInputTransformer.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.ModuleBehaviors; +namespace EllieBot.Common.ModuleBehaviors; /// /// Implemented by services which may transform input before a command is searched for diff --git a/src/EllieBot/_common/ModuleBehaviors/IReadyExecutor.cs b/src/EllieBot/_common/ModuleBehaviors/IReadyExecutor.cs index f0a200b..9364286 100644 --- a/src/EllieBot/_common/ModuleBehaviors/IReadyExecutor.cs +++ b/src/EllieBot/_common/ModuleBehaviors/IReadyExecutor.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common.ModuleBehaviors; +namespace EllieBot.Common.ModuleBehaviors; /// /// All services which need to execute something after diff --git a/src/EllieBot/_common/NinjectKernelExtensions.cs b/src/EllieBot/_common/NinjectIKernelExtensions.cs similarity index 98% rename from src/EllieBot/_common/NinjectKernelExtensions.cs rename to src/EllieBot/_common/NinjectIKernelExtensions.cs index 36b4fa8..5b5b909 100644 --- a/src/EllieBot/_common/NinjectKernelExtensions.cs +++ b/src/EllieBot/_common/NinjectIKernelExtensions.cs @@ -1,4 +1,4 @@ -using DryIoc; +using DryIoc; namespace EllieBot.Extensions; @@ -11,7 +11,7 @@ public static class DryIocExtensions return container; } - + public static IContainer AddSingleton(this IContainer container, TImpl obj) where TImpl : TSvc { @@ -41,7 +41,7 @@ public static class DryIocExtensions return container; } - + public static IContainer AddSingleton(this IContainer container, Func factory) { container.RegisterDelegate(factory); diff --git a/src/EllieBot/_common/Patronage/FeatureLimitKey.cs b/src/EllieBot/_common/Patronage/FeatureLimitKey.cs index 9aa8a46..10278e1 100644 --- a/src/EllieBot/_common/Patronage/FeatureLimitKey.cs +++ b/src/EllieBot/_common/Patronage/FeatureLimitKey.cs @@ -1,5 +1,12 @@ namespace EllieBot.Modules.Patronage; +public enum LimitedFeatureName +{ + ChatBot, + ReactionRole, + Prune, + +} public readonly struct FeatureLimitKey { public string PrettyName { get; init; } diff --git a/src/EllieBot/_common/Patronage/FeatureQuotaStats.cs b/src/EllieBot/_common/Patronage/FeatureQuotaStats.cs deleted file mode 100644 index 02db5d3..0000000 --- a/src/EllieBot/_common/Patronage/FeatureQuotaStats.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace EllieBot.Modules.Patronage; - -public readonly struct FeatureQuotaStats -{ - public (uint Cur, uint Max) Hourly { get; init; } - public (uint Cur, uint Max) Daily { get; init; } - public (uint Cur, uint Max) Monthly { get; init; } -} \ No newline at end of file diff --git a/src/EllieBot/_common/Patronage/IPatronageService.cs b/src/EllieBot/_common/Patronage/IPatronageService.cs index 77fed4b..650bf06 100644 --- a/src/EllieBot/_common/Patronage/IPatronageService.cs +++ b/src/EllieBot/_common/Patronage/IPatronageService.cs @@ -31,26 +31,15 @@ public interface IPatronageService /// /// UserId for which to get the patron data for. /// A patron with the specifeid userId - public Task GetPatronAsync(ulong userId); + public Task GetPatronAsync(ulong userId); - /// - /// Gets the quota statistic for the user/patron specified by the userId - /// - /// UserId of the user for which to get the quota statistic for - /// Quota stats for the specified user - Task GetUserQuotaStatistic(ulong userId); - + Task LimitHitAsync(LimitedFeatureName key, ulong userId, int amount = 1); + Task LimitForceHit(LimitedFeatureName key, ulong userId, int amount); + Task GetUserLimit(LimitedFeatureName name, ulong userId); - Task TryGetFeatureLimitAsync(FeatureLimitKey key, ulong userId, int? defaultValue); - - ValueTask> TryIncrementQuotaCounterAsync( - ulong userId, - bool isSelf, - FeatureType featureType, - string featureName, - uint? maybeHourly, - uint? maybeDaily, - uint? maybeMonthly); + Task> LimitStats(ulong userId); PatronConfigData GetConfig(); + int PercentBonus(Patron? user); + int PercentBonus(long amount); } \ No newline at end of file diff --git a/src/EllieBot/_common/Patronage/Patron.cs b/src/EllieBot/_common/Patronage/Patron.cs index a7c9d97..93a7575 100644 --- a/src/EllieBot/_common/Patronage/Patron.cs +++ b/src/EllieBot/_common/Patronage/Patron.cs @@ -13,7 +13,7 @@ public readonly struct Patron public ulong UserId { get; init; } /// - /// Amount the Patron is currently pledging or paid + /// Amount the Patron is currently pledging or paid in cents /// public int Amount { get; init; } diff --git a/src/EllieBot/_common/Patronage/PatronConfigData.cs b/src/EllieBot/_common/Patronage/PatronConfigData.cs index 09ed100..9becae0 100644 --- a/src/EllieBot/_common/Patronage/PatronConfigData.cs +++ b/src/EllieBot/_common/Patronage/PatronConfigData.cs @@ -7,31 +7,11 @@ namespace EllieBot.Modules.Patronage; public partial class PatronConfigData : ICloneable { [Comment("DO NOT CHANGE")] - public int Version { get; set; } = 2; - + public int Version { get; set; } = 3; + [Comment("Whether the patronage feature is enabled")] public bool IsEnabled { get; set; } - [Comment("List of patron only features and relevant quota data")] - public FeatureQuotas Quotas { get; set; } - - public PatronConfigData() - { - Quotas = new(); - } - - public class FeatureQuotas - { - [Comment("Dictionary of feature names with their respective limits. Set to null for unlimited")] - public Dictionary> Features { get; set; } = new(); - - [Comment("Dictionary of commands with their respective quota data")] - public Dictionary?>> Commands { get; set; } = new(); - - [Comment("Dictionary of groups with their respective quota data")] - public Dictionary?>> Groups { get; set; } = new(); - - [Comment("Dictionary of modules with their respective quota data")] - public Dictionary?>> Modules { get; set; } = new(); - } + [Comment("Who can do how much of what")] + public Dictionary> Limits { get; set; } = new(); } \ No newline at end of file diff --git a/src/EllieBot/_common/Patronage/PatronExtensions.cs b/src/EllieBot/_common/Patronage/PatronExtensions.cs index b422b73..1686a4c 100644 --- a/src/EllieBot/_common/Patronage/PatronExtensions.cs +++ b/src/EllieBot/_common/Patronage/PatronExtensions.cs @@ -8,15 +8,6 @@ public static class PatronExtensions _ => $"Patron Tier {tier}", }; - public static string ToFullName(this QuotaPer per) - => per switch - { - QuotaPer.PerDay => "per day", - QuotaPer.PerHour => "per hour", - QuotaPer.PerMonth => "per month", - _ => "Unknown", - }; - public static DateTime DayOfNextMonth(this DateTime date, int day) { var nextMonth = date.AddMonths(1); diff --git a/src/EllieBot/_common/Patronage/QuotaLimit.cs b/src/EllieBot/_common/Patronage/QuotaLimit.cs index b40017c..ed2cae9 100644 --- a/src/EllieBot/_common/Patronage/QuotaLimit.cs +++ b/src/EllieBot/_common/Patronage/QuotaLimit.cs @@ -10,57 +10,16 @@ public readonly struct QuotaLimit /// /// Amount of usages reached, which is the limit /// - public uint Quota { get; init; } + public int Quota { get; init; } /// /// Which period is this quota limit for (hourly, daily, monthly, etc...) /// public QuotaPer QuotaPeriod { get; init; } - /// - /// When does this quota limit reset - /// - public DateTime ResetsAt { get; init; } - - /// - /// Type of the feature this quota limit is for - /// - public FeatureType FeatureType { get; init; } - - /// - /// Name of the feature this quota limit is for - /// - public string Feature { get; init; } - - /// - /// Whether it is the user's own quota (true), or server owners (false) - /// - public bool IsOwnQuota { get; init; } -} - - -/// -/// Respresent information about the feature limit -/// -public readonly struct FeatureLimit -{ - - /// - /// Whether this limit comes from the patronage system - /// - public bool IsPatronLimit { get; init; } = false; - - /// - /// Maximum limit allowed - /// - public int? Quota { get; init; } = null; - - /// - /// Name of the limit - /// - public string Name { get; init; } = string.Empty; - - public FeatureLimit() + public QuotaLimit(int quota, QuotaPer quotaPeriod) { + Quota = quota; + QuotaPeriod = quotaPeriod; } } \ No newline at end of file diff --git a/src/EllieBot/_common/Patronage/QuotaPer.cs b/src/EllieBot/_common/Patronage/QuotaPer.cs index c6080ac..9f67a40 100644 --- a/src/EllieBot/_common/Patronage/QuotaPer.cs +++ b/src/EllieBot/_common/Patronage/QuotaPer.cs @@ -5,4 +5,5 @@ public enum QuotaPer PerHour, PerDay, PerMonth, + Total, } \ No newline at end of file diff --git a/src/EllieBot/_common/Patronage/UserQuotaStats.cs b/src/EllieBot/_common/Patronage/UserQuotaStats.cs deleted file mode 100644 index a9e33e4..0000000 --- a/src/EllieBot/_common/Patronage/UserQuotaStats.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EllieBot.Modules.Patronage; - -public readonly struct UserQuotaStats -{ - private static readonly IReadOnlyDictionary _emptyDictionary - = new Dictionary(); - public PatronTier Tier { get; init; } - = PatronTier.None; - - public IReadOnlyDictionary Features { get; init; } - = _emptyDictionary; - - public IReadOnlyDictionary Commands { get; init; } - = _emptyDictionary; - - public IReadOnlyDictionary Groups { get; init; } - = _emptyDictionary; - - public IReadOnlyDictionary Modules { get; init; } - = _emptyDictionary; - - public UserQuotaStats() - { - } -} \ No newline at end of file diff --git a/src/EllieBot/_common/Pokemon/SearchPokemonAbility.cs b/src/EllieBot/_common/Pokemon/SearchPokemonAbility.cs index c3f8f36..f401284 100644 --- a/src/EllieBot/_common/Pokemon/SearchPokemonAbility.cs +++ b/src/EllieBot/_common/Pokemon/SearchPokemonAbility.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Common.Pokemon; public class SearchPokemonAbility diff --git a/src/EllieBot/_common/Replacements/Impl/ReplacementRegistrator.default.cs b/src/EllieBot/_common/Replacements/Impl/ReplacementRegistrator.default.cs index d42bba6..acecd9e 100644 --- a/src/EllieBot/_common/Replacements/Impl/ReplacementRegistrator.default.cs +++ b/src/EllieBot/_common/Replacements/Impl/ReplacementRegistrator.default.cs @@ -95,7 +95,7 @@ public sealed partial class ReplacementPatternStore Register(_rngRegex, match => { - var rng = new EllieRandom(); + var rng = new NadekoRandom(); if (!int.TryParse(match.Groups["from"].ToString(), out var from)) from = 0; if (!int.TryParse(match.Groups["to"].ToString(), out var to)) diff --git a/src/EllieBot/_common/Sender/MessageSenderService.cs b/src/EllieBot/_common/Sender/MessageSenderService.cs index f91f1ab..c6e34ad 100644 --- a/src/EllieBot/_common/Sender/MessageSenderService.cs +++ b/src/EllieBot/_common/Sender/MessageSenderService.cs @@ -33,15 +33,15 @@ public sealed class MessageSenderService : IMessageSenderService, IEService => new ResponseBuilder(_bs, _bcs, _client) .Channel(smc.Channel); - public EllieEmbedBuilder CreateEmbed() - => new EllieEmbedBuilder(_bcs); + public NadekoEmbedBuilder CreateEmbed() + => new NadekoEmbedBuilder(_bcs); } -public class EllieEmbedBuilder : EmbedBuilder +public class NadekoEmbedBuilder : EmbedBuilder { private readonly BotConfig _bc; - public EllieEmbedBuilder(BotConfigService bcs) + public NadekoEmbedBuilder(BotConfigService bcs) { _bc = bcs.Data; } diff --git a/src/EllieBot/_common/Sender/ResponseBuilder.PaginationSender.cs b/src/EllieBot/_common/Sender/ResponseBuilder.PaginationSender.cs index a1dee4d..f4be0c1 100644 --- a/src/EllieBot/_common/Sender/ResponseBuilder.PaginationSender.cs +++ b/src/EllieBot/_common/Sender/ResponseBuilder.PaginationSender.cs @@ -11,6 +11,10 @@ public partial class ResponseBuilder private readonly ResponseBuilder _builder; private readonly DiscordSocketClient _client; private int currentPage; + + private EllieButtonInteractionHandler left; + private EllieButtonInteractionHandler right; + private EllieInteractionBase? extra; public PaginationSender( SourcedPaginatedResponseBuilder paginationBuilder, @@ -106,6 +110,8 @@ public partial class ResponseBuilder return (leftBtnInter, maybeInter, rightBtnInter); } + + (left, extra, right) = await GetInteractions(); async Task UpdatePageAsync(SocketMessageComponent smc) { @@ -114,21 +120,25 @@ public partial class ResponseBuilder if (_paginationBuilder.AddPaginatedFooter) toSend.AddPaginatedFooter(currentPage, lastPage); - var (left, extra, right) = (await GetInteractions()); + left.SetCompleted(); + right.SetCompleted(); + extra?.SetCompleted(); + (left, extra, right) = (await GetInteractions()); var cb = new ComponentBuilder(); left.AddTo(cb); right.AddTo(cb); extra?.AddTo(cb); - + await smc.ModifyOriginalResponseAsync(x => { x.Embed = toSend.Build(); x.Components = cb.Build(); }); + + await Task.WhenAll(left.RunAsync(smc.Message), extra?.RunAsync(smc.Message) ?? Task.CompletedTask, right.RunAsync(smc.Message)); } - var (left, extra, right) = await GetInteractions(); var cb = new ComponentBuilder(); left.AddTo(cb); @@ -144,9 +154,11 @@ public partial class ResponseBuilder if (lastPage == 0 && _paginationBuilder.InteractionFunc is null) return; - + await Task.WhenAll(left.RunAsync(msg), extra?.RunAsync(msg) ?? Task.CompletedTask, right.RunAsync(msg)); + await Task.Delay(30_000); + await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build()); } } diff --git a/src/EllieBot/_common/ServiceCollectionExtensions.cs b/src/EllieBot/_common/ServiceCollectionExtensions.cs index 4b468d2..3a59226 100644 --- a/src/EllieBot/_common/ServiceCollectionExtensions.cs +++ b/src/EllieBot/_common/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using DryIoc; +using DryIoc; using LinqToDB.Extensions; using Microsoft.Extensions.DependencyInjection; using EllieBot.Modules.Music; @@ -33,7 +33,7 @@ public static class ServiceCollectionExtensions public static IContainer AddConfigServices(this IContainer svcs, Assembly a) { - + foreach (var type in a.GetTypes() .Where(x => !x.IsAbstract && x.IsAssignableToGenericType(typeof(ConfigServiceBase<>)))) { @@ -41,7 +41,7 @@ public static class ServiceCollectionExtensions getServiceTypes: type => type.GetImplementedTypes(ReflectionTools.AsImplementedType.SourceType), getImplFactory: type => ReflectionFactory.Of(type, Reuse.Singleton)); } - + return svcs; } @@ -95,7 +95,7 @@ public static class ServiceCollectionExtensions }); var prov = proxySvcs.BuildServiceProvider(); - + svcs.RegisterDelegate(_ => prov.GetRequiredService()); svcs.RegisterDelegate(_ => prov.GetRequiredService()); @@ -113,7 +113,7 @@ public static class ServiceCollectionExtensions typeof(IInputTransformer), typeof(IEService) ]; - + foreach (var svc in a.GetTypes() .Where(type => type.IsClass && types.Any(t => type.IsAssignableTo(t)) && !type.HasAttribute() #if GLOBAL_ELLIE diff --git a/src/EllieBot/_common/Services/CommandHandler.cs b/src/EllieBot/_common/Services/CommandHandler.cs index c058887..2061b29 100644 --- a/src/EllieBot/_common/Services/CommandHandler.cs +++ b/src/EllieBot/_common/Services/CommandHandler.cs @@ -9,7 +9,7 @@ namespace EllieBot.Services; public class CommandHandler : IEService, IReadyExecutor, ICommandHandler { - private const int GLOBAL_COMMANDS_COOLDOWN = 750; + private const int GLOBAL_COMMANDS_COOLDOWN = 200; private const float ONE_THOUSANDTH = 1.0f / 1000; @@ -262,7 +262,7 @@ public class CommandHandler : IEService, IReadyExecutor, ICommandHandler var blockTime = Environment.TickCount - startTime; var messageContent = await _behaviorHandler.RunInputTransformersAsync(guild, usrMsg); - + var prefix = GetPrefix(guild?.Id); var isPrefixCommand = messageContent.StartsWith(".prefix", StringComparison.InvariantCultureIgnoreCase); // execute the command and measure the time it took diff --git a/src/EllieBot/_common/Services/IBehaviourHandler.cs b/src/EllieBot/_common/Services/IBehaviourHandler.cs index 79e8e5a..2f75074 100644 --- a/src/EllieBot/_common/Services/IBehaviourHandler.cs +++ b/src/EllieBot/_common/Services/IBehaviourHandler.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Services; public interface IBehaviorHandler @@ -7,7 +7,7 @@ public interface IBehaviorHandler Task AddRangeAsync(IEnumerable behavior); Task RemoveAsync(ICustomBehavior behavior); Task RemoveRangeAsync(IEnumerable behs); - + Task RunExecOnMessageAsync(SocketGuild guild, IUserMessage usrMsg); Task RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg); Task RunPreCommandAsync(ICommandContext context, CommandInfo cmd); diff --git a/src/EllieBot/_common/Services/ILocalization.cs b/src/EllieBot/_common/Services/ILocalization.cs index 3fa7c5e..ab37be5 100644 --- a/src/EllieBot/_common/Services/ILocalization.cs +++ b/src/EllieBot/_common/Services/ILocalization.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System.Globalization; namespace EllieBot.Services; diff --git a/src/EllieBot/_common/Services/ITimezoneService.cs b/src/EllieBot/_common/Services/ITimezoneService.cs index aa8cbff..e70b985 100644 --- a/src/EllieBot/_common/Services/ITimezoneService.cs +++ b/src/EllieBot/_common/Services/ITimezoneService.cs @@ -1,4 +1,4 @@ -namespace EllieBot.Common; +namespace EllieBot.Common; public interface ITimezoneService { diff --git a/src/EllieBot/_common/Services/Impl/YtdlOperation.cs b/src/EllieBot/_common/Services/Impl/YtdlOperation.cs index f302ab7..3813b80 100644 --- a/src/EllieBot/_common/Services/Impl/YtdlOperation.cs +++ b/src/EllieBot/_common/Services/Impl/YtdlOperation.cs @@ -53,7 +53,7 @@ public class YtdlOperation } catch (Win32Exception) { - Log.Error("youtube-dl is likely not installed. " + "Please install it before running the command again"); + Log.Error("youtube-dl is likely not installed. Please install it before running the command again"); return default; } catch (Exception ex) diff --git a/src/EllieBot/_common/Settings/BotConfigService.cs b/src/EllieBot/_common/Settings/BotConfigService.cs index 952f402..477f080 100644 --- a/src/EllieBot/_common/Settings/BotConfigService.cs +++ b/src/EllieBot/_common/Settings/BotConfigService.cs @@ -49,21 +49,21 @@ public sealed class BotConfigService : ConfigServiceBase .ToHashSet(); }); } - + if (data.Version < 4) ModifyConfig(c => { c.Version = 4; c.CheckForUpdates = true; }); - - if (data.Version < 5) + + if(data.Version < 5) ModifyConfig(c => { c.Version = 5; }); - - if (data.Version < 7) + + if(data.Version < 7) ModifyConfig(c => { c.Version = 7; diff --git a/src/EllieBot/_common/Settings/ConfigParsers.cs b/src/EllieBot/_common/Settings/ConfigParsers.cs index c32b7ca..8eda144 100644 --- a/src/EllieBot/_common/Settings/ConfigParsers.cs +++ b/src/EllieBot/_common/Settings/ConfigParsers.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using SixLabors.ImageSharp.PixelFormats; using System.Globalization; @@ -33,7 +33,7 @@ public static class ConfigParsers } public static bool InsensitiveEnum(string input, out T output) - where T : struct + where T: struct => Enum.TryParse(input, true, out output); } diff --git a/src/EllieBot/_common/Settings/ConfigServiceBase.cs b/src/EllieBot/_common/Settings/ConfigServiceBase.cs index bdf76d8..ab4a15f 100644 --- a/src/EllieBot/_common/Settings/ConfigServiceBase.cs +++ b/src/EllieBot/_common/Settings/ConfigServiceBase.cs @@ -1,9 +1,9 @@ -using EllieBot.Common.Configs; +using EllieBot.Common.Configs; using EllieBot.Common.Yml; using System.Linq.Expressions; using System.Reflection; -namespace EllieBot.Services; +namespace NadekoBot.Services; /// /// Base service for all settings services diff --git a/src/EllieBot/_common/Settings/IConfigService.cs b/src/EllieBot/_common/Settings/IConfigService.cs index 69ac966..ae97198 100644 --- a/src/EllieBot/_common/Settings/IConfigService.cs +++ b/src/EllieBot/_common/Settings/IConfigService.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Services; /// diff --git a/src/EllieBot/_common/Settings/SettingParser.cs b/src/EllieBot/_common/Settings/SettingParser.cs index 06a8e75..1437591 100644 --- a/src/EllieBot/_common/Settings/SettingParser.cs +++ b/src/EllieBot/_common/Settings/SettingParser.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Services; /// diff --git a/src/EllieBot/_common/Yml/CommentAttribute.cs b/src/EllieBot/_common/Yml/CommentAttribute.cs index 7c04bea..1c1ad89 100644 --- a/src/EllieBot/_common/Yml/CommentAttribute.cs +++ b/src/EllieBot/_common/Yml/CommentAttribute.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Common.Yml; [AttributeUsage(AttributeTargets.Property)] diff --git a/src/EllieBot/_common/Yml/MultilineScalarFlowStyleEmitter.cs b/src/EllieBot/_common/Yml/MultilineScalarFlowStyleEmitter.cs index e2cfd97..c63dcab 100644 --- a/src/EllieBot/_common/Yml/MultilineScalarFlowStyleEmitter.cs +++ b/src/EllieBot/_common/Yml/MultilineScalarFlowStyleEmitter.cs @@ -5,7 +5,6 @@ using YamlDotNet.Serialization.EventEmitters; namespace EllieBot.Common.Yml; - public class MultilineScalarFlowStyleEmitter : ChainedEventEmitter { public MultilineScalarFlowStyleEmitter(IEventEmitter nextEmitter) diff --git a/src/EllieBot/_common/_Extensions/CommandContextExtensions.cs b/src/EllieBot/_common/_Extensions/CommandContextExtensions.cs index 7f90d78..ebb019b 100644 --- a/src/EllieBot/_common/_Extensions/CommandContextExtensions.cs +++ b/src/EllieBot/_common/_Extensions/CommandContextExtensions.cs @@ -27,4 +27,14 @@ public static class CommandContextExtensions public static Task WarningAsync(this ICommandContext ctx) => ctx.ReactAsync(MsgType.Pending); + + + public static Task OkAsync(this IUserMessage msg) + => msg.AddReactionAsync(_okEmoji); + + public static Task ErrorAsync(this IUserMessage msg) + => msg.AddReactionAsync(_errorEmoji); + + public static Task WarningAsync(this IUserMessage msg) + => msg.AddReactionAsync(_warnEmoji); } \ No newline at end of file diff --git a/src/EllieBot/_common/_Extensions/Extensions.cs b/src/EllieBot/_common/_Extensions/Extensions.cs index 27341ad..f0cb9f9 100644 --- a/src/EllieBot/_common/_Extensions/Extensions.cs +++ b/src/EllieBot/_common/_Extensions/Extensions.cs @@ -229,6 +229,7 @@ public static class Extensions public static IEnumerable GetRoles(this IGuildUser user) => user.RoleIds.Select(r => user.Guild.GetRole(r)).Where(r => r is not null); + // todo remove public static void Lap(this Stopwatch sw, string checkpoint) { Log.Information("Checkpoint {CheckPoint}: {Time}ms", checkpoint, sw.Elapsed.TotalMilliseconds);