diff --git a/Nadeko.Bot.Modules.Searches/Class1.cs b/Nadeko.Bot.Modules.Searches/Class1.cs
deleted file mode 100644
index 9be3e7956..000000000
--- a/Nadeko.Bot.Modules.Searches/Class1.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace Nadeko.Bot.Modules.Searches;
-
-public class Class1
-{
-}
\ No newline at end of file
diff --git a/Nadeko.Bot.Modules.Searches/Nadeko.Bot.Modules.Searches.csproj b/Nadeko.Bot.Modules.Searches/Nadeko.Bot.Modules.Searches.csproj
deleted file mode 100644
index 6836c6808..000000000
--- a/Nadeko.Bot.Modules.Searches/Nadeko.Bot.Modules.Searches.csproj
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- net7.0
- enable
- enable
-
-
-
diff --git a/NadekoBot.sln b/NadekoBot.sln
index 9d2391daf..556fe8503 100644
--- a/NadekoBot.sln
+++ b/NadekoBot.sln
@@ -25,7 +25,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Tests", "src\Nade
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Coordinator", "src\NadekoBot.Coordinator\NadekoBot.Coordinator.csproj", "{AE9B7F8C-81D7-4401-83A3-643B38258374}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Generators", "src\NadekoBot.Generators\NadekoBot.Generators.csproj", "{3BC3BDF8-1A0B-45EB-AB2B-C0891D4D37B8}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Bot.Generators.Strings", "src\Nadeko.Bot.Generators.Strings\Nadeko.Bot.Generators.Strings.csproj", "{3BC3BDF8-1A0B-45EB-AB2B-C0891D4D37B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.VotesApi", "src\NadekoBot.VotesApi\NadekoBot.VotesApi.csproj", "{3BC82CFE-BEE7-451F-986B-17EDD1570C4F}"
EndProject
@@ -57,6 +57,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Bot.Modules.Administ
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Bot.Modules.Help", "src\Nadeko.Bot.Modules.Help\Nadeko.Bot.Modules.Help.csproj", "{C6359697-25F1-4049-8D73-AC48043CA192}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Bot.Modules.Patronage", "src\Nadeko.Bot.Modules.Patronage\Nadeko.Bot.Modules.Patronage.csproj", "{CE434517-926B-44FE-8449-FE34A4382267}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Bot.Generators.Cloneable", "src\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj", "{92770AF3-83EE-49F1-A0BB-79124D19A13D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -184,6 +188,18 @@ Global
{C6359697-25F1-4049-8D73-AC48043CA192}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
{C6359697-25F1-4049-8D73-AC48043CA192}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6359697-25F1-4049-8D73-AC48043CA192}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CE434517-926B-44FE-8449-FE34A4382267}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CE434517-926B-44FE-8449-FE34A4382267}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CE434517-926B-44FE-8449-FE34A4382267}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
+ {CE434517-926B-44FE-8449-FE34A4382267}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
+ {CE434517-926B-44FE-8449-FE34A4382267}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CE434517-926B-44FE-8449-FE34A4382267}.Release|Any CPU.Build.0 = Release|Any CPU
+ {92770AF3-83EE-49F1-A0BB-79124D19A13D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {92770AF3-83EE-49F1-A0BB-79124D19A13D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {92770AF3-83EE-49F1-A0BB-79124D19A13D}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
+ {92770AF3-83EE-49F1-A0BB-79124D19A13D}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
+ {92770AF3-83EE-49F1-A0BB-79124D19A13D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {92770AF3-83EE-49F1-A0BB-79124D19A13D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -210,6 +226,8 @@ Global
{A5B51533-33B6-43AF-9D2D-410613078E96} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
{08C31FF8-AC47-498D-ACD9-612FA8001F1F} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
{C6359697-25F1-4049-8D73-AC48043CA192} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
+ {CE434517-926B-44FE-8449-FE34A4382267} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
+ {92770AF3-83EE-49F1-A0BB-79124D19A13D} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4}
diff --git a/src/Nadeko.Bot.Common/Abstractions/strings/LocStr.cs b/src/Nadeko.Bot.Common/Abstractions/strings/LocStr.cs
index 4f1822e87..e578e957b 100644
--- a/src/Nadeko.Bot.Common/Abstractions/strings/LocStr.cs
+++ b/src/Nadeko.Bot.Common/Abstractions/strings/LocStr.cs
@@ -1,13 +1,13 @@
-// namespace NadekoBot.Common;
-//
-// public readonly struct LocStr
-// {
-// public readonly string Key;
-// public readonly object[] Params;
-//
-// public LocStr(string key, params object[] data)
-// {
-// Key = key;
-// Params = data;
-// }
-// }
\ No newline at end of file
+namespace NadekoBot;
+
+public readonly struct LocStr
+{
+ public readonly string Key;
+ public readonly object[] Params;
+
+ public LocStr(string key, params object[] data)
+ {
+ Key = key;
+ Params = data;
+ }
+}
\ No newline at end of file
diff --git a/src/Nadeko.Bot.Common/Attributes/OnlyPublicBotAttribute.cs b/src/Nadeko.Bot.Common/Attributes/OnlyPublicBotAttribute.cs
index e9400ec17..081ab8dbe 100644
--- a/src/Nadeko.Bot.Common/Attributes/OnlyPublicBotAttribute.cs
+++ b/src/Nadeko.Bot.Common/Attributes/OnlyPublicBotAttribute.cs
@@ -12,7 +12,7 @@ public sealed class OnlyPublicBotAttribute : PreconditionAttribute
CommandInfo command,
IServiceProvider services)
{
-#if GLOBAL_NADEKO || DEBUG
+#if GLOBAL_NADEKO
return Task.FromResult(PreconditionResult.FromSuccess());
#else
return Task.FromResult(PreconditionResult.FromError("Only available on the public bot."));
diff --git a/src/Nadeko.Bot.Modules.Gambling/Gambling/Bank/IBankService.cs b/src/Nadeko.Bot.Common/Currency/IBankService.cs
similarity index 100%
rename from src/Nadeko.Bot.Modules.Gambling/Gambling/Bank/IBankService.cs
rename to src/Nadeko.Bot.Common/Currency/IBankService.cs
diff --git a/src/Nadeko.Bot.Common/IPermissionChecker.cs b/src/Nadeko.Bot.Common/IPermissionChecker.cs
index 90c9d68ab..f41a898cd 100644
--- a/src/Nadeko.Bot.Common/IPermissionChecker.cs
+++ b/src/Nadeko.Bot.Common/IPermissionChecker.cs
@@ -11,5 +11,5 @@ public interface IPermissionChecker
IMessageChannel channel,
IUser author,
string module,
- string cmd);
+ string? cmd);
}
\ No newline at end of file
diff --git a/src/Nadeko.Bot.Common/Nadeko.Bot.Common.csproj b/src/Nadeko.Bot.Common/Nadeko.Bot.Common.csproj
index 86391348e..94651c6b1 100644
--- a/src/Nadeko.Bot.Common/Nadeko.Bot.Common.csproj
+++ b/src/Nadeko.Bot.Common/Nadeko.Bot.Common.csproj
@@ -7,7 +7,6 @@
-
@@ -30,7 +29,8 @@
-
+
+
diff --git a/src/Nadeko.Bot.Common/NadekoModule.cs b/src/Nadeko.Bot.Common/NadekoModule.cs
index ab6830337..33c492fff 100644
--- a/src/Nadeko.Bot.Common/NadekoModule.cs
+++ b/src/Nadeko.Bot.Common/NadekoModule.cs
@@ -1,6 +1,5 @@
#nullable disable
using System.Globalization;
-using NadekoBot.Services;
// ReSharper disable InconsistentNaming
diff --git a/src/Nadeko.Bot.Common/Patronage/FeatureLimitKey.cs b/src/Nadeko.Bot.Common/Patronage/FeatureLimitKey.cs
index 36780b0e2..17a42bc61 100644
--- a/src/Nadeko.Bot.Common/Patronage/FeatureLimitKey.cs
+++ b/src/Nadeko.Bot.Common/Patronage/FeatureLimitKey.cs
@@ -1,4 +1,4 @@
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public readonly struct FeatureLimitKey
{
diff --git a/src/Nadeko.Bot.Common/Patronage/FeatureQuotaStats.cs b/src/Nadeko.Bot.Common/Patronage/FeatureQuotaStats.cs
index f3bbe4bfc..538088ef4 100644
--- a/src/Nadeko.Bot.Common/Patronage/FeatureQuotaStats.cs
+++ b/src/Nadeko.Bot.Common/Patronage/FeatureQuotaStats.cs
@@ -1,4 +1,4 @@
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public readonly struct FeatureQuotaStats
{
diff --git a/src/Nadeko.Bot.Common/Patronage/IPatronData.cs b/src/Nadeko.Bot.Common/Patronage/IPatronData.cs
index 811beb7d8..f72d2238c 100644
--- a/src/Nadeko.Bot.Common/Patronage/IPatronData.cs
+++ b/src/Nadeko.Bot.Common/Patronage/IPatronData.cs
@@ -1,4 +1,4 @@
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
public interface ISubscriberData
{
diff --git a/src/Nadeko.Bot.Common/Patronage/IPatronageService.cs b/src/Nadeko.Bot.Common/Patronage/IPatronageService.cs
index cbb6cac45..48eb061f8 100644
--- a/src/Nadeko.Bot.Common/Patronage/IPatronageService.cs
+++ b/src/Nadeko.Bot.Common/Patronage/IPatronageService.cs
@@ -1,7 +1,7 @@
using NadekoBot.Db.Models;
using OneOf;
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
///
/// Manages patrons and provides access to their data
diff --git a/src/Nadeko.Bot.Common/Patronage/ISubscriptionHandler.cs b/src/Nadeko.Bot.Common/Patronage/ISubscriptionHandler.cs
index 7e2a49773..76f6d9593 100644
--- a/src/Nadeko.Bot.Common/Patronage/ISubscriptionHandler.cs
+++ b/src/Nadeko.Bot.Common/Patronage/ISubscriptionHandler.cs
@@ -1,5 +1,5 @@
#nullable disable
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
///
/// Services implementing this interface are handling pledges/subscriptions/payments coming
diff --git a/src/Nadeko.Bot.Common/Patronage/Patron.cs b/src/Nadeko.Bot.Common/Patronage/Patron.cs
index bfe928f04..1dfc5df86 100644
--- a/src/Nadeko.Bot.Common/Patronage/Patron.cs
+++ b/src/Nadeko.Bot.Common/Patronage/Patron.cs
@@ -1,4 +1,4 @@
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public readonly struct Patron
{
diff --git a/src/Nadeko.Bot.Common/Patronage/PatronConfigData.cs b/src/Nadeko.Bot.Common/Patronage/PatronConfigData.cs
index 51f5794f9..223019eff 100644
--- a/src/Nadeko.Bot.Common/Patronage/PatronConfigData.cs
+++ b/src/Nadeko.Bot.Common/Patronage/PatronConfigData.cs
@@ -1,7 +1,7 @@
using NadekoBot.Common.Yml;
using Cloneable;
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
[Cloneable]
public partial class PatronConfigData : ICloneable
diff --git a/src/Nadeko.Bot.Common/Patronage/PatronExtensions.cs b/src/Nadeko.Bot.Common/Patronage/PatronExtensions.cs
index e41fc66b5..1b261fce1 100644
--- a/src/Nadeko.Bot.Common/Patronage/PatronExtensions.cs
+++ b/src/Nadeko.Bot.Common/Patronage/PatronExtensions.cs
@@ -1,4 +1,4 @@
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public static class PatronExtensions
{
diff --git a/src/Nadeko.Bot.Common/Patronage/PatronTier.cs b/src/Nadeko.Bot.Common/Patronage/PatronTier.cs
index d9eb32a7c..2f6f64fa4 100644
--- a/src/Nadeko.Bot.Common/Patronage/PatronTier.cs
+++ b/src/Nadeko.Bot.Common/Patronage/PatronTier.cs
@@ -1,5 +1,5 @@
// ReSharper disable InconsistentNaming
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public enum PatronTier
{
diff --git a/src/Nadeko.Bot.Common/Patronage/QuotaLimit.cs b/src/Nadeko.Bot.Common/Patronage/QuotaLimit.cs
index 79a6a1a58..ff4336376 100644
--- a/src/Nadeko.Bot.Common/Patronage/QuotaLimit.cs
+++ b/src/Nadeko.Bot.Common/Patronage/QuotaLimit.cs
@@ -1,6 +1,6 @@
using NadekoBot.Db.Models;
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
///
/// Represents information about why the user has triggered a quota limit
diff --git a/src/Nadeko.Bot.Common/Patronage/QuotaPer.cs b/src/Nadeko.Bot.Common/Patronage/QuotaPer.cs
index 9c7db6c34..a93d8979c 100644
--- a/src/Nadeko.Bot.Common/Patronage/QuotaPer.cs
+++ b/src/Nadeko.Bot.Common/Patronage/QuotaPer.cs
@@ -1,4 +1,4 @@
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public enum QuotaPer
{
diff --git a/src/Nadeko.Bot.Common/Patronage/SubscriptionChargeStatus.cs b/src/Nadeko.Bot.Common/Patronage/SubscriptionChargeStatus.cs
index 6b4644b82..56d3d7152 100644
--- a/src/Nadeko.Bot.Common/Patronage/SubscriptionChargeStatus.cs
+++ b/src/Nadeko.Bot.Common/Patronage/SubscriptionChargeStatus.cs
@@ -1,5 +1,5 @@
#nullable disable
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
public enum SubscriptionChargeStatus
{
diff --git a/src/Nadeko.Bot.Common/Patronage/UserQuotaStats.cs b/src/Nadeko.Bot.Common/Patronage/UserQuotaStats.cs
index 3d8387f53..d36f756c8 100644
--- a/src/Nadeko.Bot.Common/Patronage/UserQuotaStats.cs
+++ b/src/Nadeko.Bot.Common/Patronage/UserQuotaStats.cs
@@ -1,4 +1,4 @@
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public readonly struct UserQuotaStats
{
diff --git a/src/Nadeko.Bot.Modules.Permisssions/Blacklist/BlacklistService.cs b/src/Nadeko.Bot.Common/Services/Impl/BlacklistService.cs
similarity index 100%
rename from src/Nadeko.Bot.Modules.Permisssions/Blacklist/BlacklistService.cs
rename to src/Nadeko.Bot.Common/Services/Impl/BlacklistService.cs
diff --git a/src/Nadeko.Bot.Common/Services/Impl/CommandsUtilityService.cs b/src/Nadeko.Bot.Common/Services/Impl/CommandsUtilityService.cs
new file mode 100644
index 000000000..9102e28c4
--- /dev/null
+++ b/src/Nadeko.Bot.Common/Services/Impl/CommandsUtilityService.cs
@@ -0,0 +1,172 @@
+using CommandLine;
+
+namespace NadekoBot.Common;
+
+public sealed class CommandsUtilityService : ICommandsUtilityService, INService
+{
+ private readonly CommandHandler _ch;
+ private readonly IBotStrings _strings;
+ private readonly DiscordPermOverrideService _dpos;
+ private readonly IEmbedBuilderService _eb;
+ private readonly ILocalization _loc;
+ private readonly Nadeko.Medusa.IMedusaLoaderService _medusae;
+
+ public CommandsUtilityService(
+ CommandHandler ch,
+ IBotStrings strings,
+ DiscordPermOverrideService dpos,
+ IEmbedBuilderService eb,
+ ILocalization loc,
+ Nadeko.Medusa.IMedusaLoaderService medusae)
+ {
+ _ch = ch;
+ _strings = strings;
+ _dpos = dpos;
+ _eb = eb;
+ _loc = loc;
+ _medusae = medusae;
+ }
+
+ public IEmbedBuilder GetCommandHelp(CommandInfo com, IGuild guild)
+ {
+ var prefix = _ch.GetPrefix(guild);
+
+ var str = $"**`{prefix + com.Aliases.First()}`**";
+ var alias = com.Aliases.Skip(1).FirstOrDefault();
+ if (alias is not null)
+ str += $" **/ `{prefix + alias}`**";
+
+ var culture = _loc.GetCultureInfo(guild);
+
+ var em = _eb.Create()
+ .AddField(str, $"{com.RealSummary(_strings, _medusae, culture, prefix)}", true);
+
+ _dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides);
+ var reqs = GetCommandRequirements(com, (GuildPermission?)overrides);
+ if (reqs.Any())
+ em.AddField(GetText(strs.requires, guild), string.Join("\n", reqs));
+
+ em.AddField(_strings.GetText(strs.usage),
+ string.Join("\n", com.RealRemarksArr(_strings, _medusae, culture, prefix).Map(arg => Format.Code(arg))))
+ .WithFooter(GetText(strs.module(com.Module.GetTopLevelModule().Name), guild))
+ .WithOkColor();
+
+ var opt = GetNadekoOptionType(com.Attributes);
+ if (opt is not null)
+ {
+ var hs = GetCommandOptionHelp(opt);
+ if (!string.IsNullOrWhiteSpace(hs))
+ em.AddField(GetText(strs.options, guild), hs);
+ }
+
+ return em;
+ }
+
+ public static string GetCommandOptionHelp(Type opt)
+ {
+ var strs = GetCommandOptionHelpList(opt);
+
+ return string.Join("\n", strs);
+ }
+
+ public static List GetCommandOptionHelpList(Type opt)
+ {
+ var strs = opt.GetProperties()
+ .Select(x => x.GetCustomAttributes(true).FirstOrDefault(a => a is OptionAttribute))
+ .Where(x => x is not null)
+ .Cast()
+ .Select(x =>
+ {
+ var toReturn = $"`--{x.LongName}`";
+
+ if (!string.IsNullOrWhiteSpace(x.ShortName))
+ toReturn += $" (`-{x.ShortName}`)";
+
+ toReturn += $" {x.HelpText} ";
+ return toReturn;
+ })
+ .ToList();
+
+ return strs;
+ }
+
+ public static Type GetNadekoOptionType(IEnumerable attributes)
+ => attributes
+ .Select(a => a.GetType())
+ .Where(a => a.IsGenericType
+ && a.GetGenericTypeDefinition() == typeof(NadekoOptionsAttribute<>))
+ .Select(a => a.GenericTypeArguments[0])
+ .FirstOrDefault();
+
+ public static string[] GetCommandRequirements(CommandInfo cmd, GuildPerm? overrides = null)
+ {
+ var toReturn = new List();
+
+ if (cmd.Preconditions.Any(x => x is OwnerOnlyAttribute))
+ toReturn.Add("Bot Owner Only");
+
+ if (cmd.Preconditions.Any(x => x is NoPublicBotAttribute)
+ || cmd.Module
+ .Preconditions
+ .Any(x => x is NoPublicBotAttribute)
+ || cmd.Module.GetTopLevelModule()
+ .Preconditions
+ .Any(x => x is NoPublicBotAttribute))
+ toReturn.Add("No Public Bot");
+
+ if (cmd.Preconditions
+ .Any(x => x is OnlyPublicBotAttribute)
+ || cmd.Module
+ .Preconditions
+ .Any(x => x is OnlyPublicBotAttribute)
+ || cmd.Module.GetTopLevelModule()
+ .Preconditions
+ .Any(x => x is OnlyPublicBotAttribute))
+ toReturn.Add("Only Public Bot");
+
+ var userPermString = cmd.Preconditions
+ .Where(ca => ca is UserPermAttribute)
+ .Cast()
+ .Select(userPerm =>
+ {
+ if (userPerm.ChannelPermission is { } cPerm)
+ return GetPreconditionString(cPerm);
+
+ if (userPerm.GuildPermission is { } gPerm)
+ return GetPreconditionString(gPerm);
+
+ return string.Empty;
+ })
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .Join('\n');
+
+ if (overrides is null)
+ {
+ if (!string.IsNullOrWhiteSpace(userPermString))
+ toReturn.Add(userPermString);
+ }
+ else
+ {
+ if (!string.IsNullOrWhiteSpace(userPermString))
+ toReturn.Add(Format.Strikethrough(userPermString));
+
+ toReturn.Add(GetPreconditionString(overrides.Value));
+ }
+
+ return toReturn.ToArray();
+ }
+
+ public static string GetPreconditionString(ChannelPerm perm)
+ => (perm + " Channel Permission").Replace("Guild", "Server");
+
+ public static string GetPreconditionString(GuildPerm perm)
+ => (perm + " Server Permission").Replace("Guild", "Server");
+
+ public string GetText(LocStr str, IGuild? guild)
+ => _strings.GetText(str, guild?.Id);
+}
+
+public interface ICommandsUtilityService
+{
+ IEmbedBuilder GetCommandHelp(CommandInfo com, IGuild guild);
+}
\ No newline at end of file
diff --git a/src/Nadeko.Bot.Modules.Administration/PermOverrides/DiscordPermOverrideService.cs b/src/Nadeko.Bot.Common/Services/Impl/DiscordPermOverrideService.cs
similarity index 98%
rename from src/Nadeko.Bot.Modules.Administration/PermOverrides/DiscordPermOverrideService.cs
rename to src/Nadeko.Bot.Common/Services/Impl/DiscordPermOverrideService.cs
index 27bbe0aa1..dcc36b354 100644
--- a/src/Nadeko.Bot.Modules.Administration/PermOverrides/DiscordPermOverrideService.cs
+++ b/src/Nadeko.Bot.Common/Services/Impl/DiscordPermOverrideService.cs
@@ -4,7 +4,7 @@ using Nadeko.Common;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Services.Database.Models;
-namespace NadekoBot.Modules.Administration.Services;
+namespace NadekoBot.Services;
public class DiscordPermOverrideService : INService, IExecPreCommand, IDiscordPermOverrideService
{
diff --git a/src/Nadeko.Bot.Db/Nadeko.Bot.Db.csproj b/src/Nadeko.Bot.Db/Nadeko.Bot.Db.csproj
index 4453a756b..0921b5ce7 100644
--- a/src/Nadeko.Bot.Db/Nadeko.Bot.Db.csproj
+++ b/src/Nadeko.Bot.Db/Nadeko.Bot.Db.csproj
@@ -9,16 +9,16 @@
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
diff --git a/src/Nadeko.Bot.Generators.Cloneable/CloneableGenerator.cs b/src/Nadeko.Bot.Generators.Cloneable/CloneableGenerator.cs
index 0c583fb1b..45392d16b 100644
--- a/src/Nadeko.Bot.Generators.Cloneable/CloneableGenerator.cs
+++ b/src/Nadeko.Bot.Generators.Cloneable/CloneableGenerator.cs
@@ -6,8 +6,6 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
-using System.Collections.Generic;
-using System.Linq;
using System.Text;
namespace Cloneable
@@ -23,54 +21,60 @@ namespace Cloneable
private const string CLONE_ATTRIBUTE_STRING = "CloneAttribute";
private const string IGNORE_CLONE_ATTRIBUTE_STRING = "IgnoreCloneAttribute";
- private const string CLONEABLE_ATTRIBUTE_TEXT = @"//
-using System;
+ private const string CLONEABLE_ATTRIBUTE_TEXT = $$"""
+ //
+ using System;
+
+ namespace {{CLONEABLE_NAMESPACE}}
+ {
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = false)]
+ internal sealed class {{CLONEABLE_ATTRIBUTE_STRING}} : Attribute
+ {
+ public {{CLONEABLE_ATTRIBUTE_STRING}}()
+ {
+ }
+
+ public bool {{EXPLICIT_DECLARATION_KEY_STRING}} { get; set; }
+ }
+ }
-namespace " + CLONEABLE_NAMESPACE + @"
-{
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = false)]
- public sealed class " + CLONEABLE_ATTRIBUTE_STRING + @" : Attribute
- {
- public " + CLONEABLE_ATTRIBUTE_STRING + @"()
- {
- }
+ """;
- public bool " + EXPLICIT_DECLARATION_KEY_STRING + @" { get; set; }
- }
-}
-";
+ private const string CLONE_PROPERTY_ATTRIBUTE_TEXT = $$"""
+ //
+ using System;
+
+ namespace {{CLONEABLE_NAMESPACE}}
+ {
+ [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
+ internal sealed class {{CLONE_ATTRIBUTE_STRING}} : Attribute
+ {
+ public {{CLONE_ATTRIBUTE_STRING}}()
+ {
+ }
+
+ public bool {{PREVENT_DEEP_COPY_KEY_STRING}} { get; set; }
+ }
+ }
- private const string CLONE_PROPERTY_ATTRIBUTE_TEXT = @"//
-using System;
+ """;
-namespace " + CLONEABLE_NAMESPACE + @"
-{
- [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
- public sealed class " + CLONE_ATTRIBUTE_STRING + @" : Attribute
- {
- public " + CLONE_ATTRIBUTE_STRING + @"()
- {
- }
+ private const string IGNORE_CLONE_PROPERTY_ATTRIBUTE_TEXT = $$"""
+ //
+ using System;
+
+ namespace {{CLONEABLE_NAMESPACE}}
+ {
+ [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
+ internal sealed class {{IGNORE_CLONE_ATTRIBUTE_STRING}} : Attribute
+ {
+ public {{IGNORE_CLONE_ATTRIBUTE_STRING}}()
+ {
+ }
+ }
+ }
- public bool " + PREVENT_DEEP_COPY_KEY_STRING + @" { get; set; }
- }
-}
-";
-
- private const string IGNORE_CLONE_PROPERTY_ATTRIBUTE_TEXT = @"//
-using System;
-
-namespace " + CLONEABLE_NAMESPACE + @"
-{
- [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
- public sealed class " + IGNORE_CLONE_ATTRIBUTE_STRING + @" : Attribute
- {
- public " + IGNORE_CLONE_ATTRIBUTE_STRING + @"()
- {
- }
- }
-}
-";
+ """;
private INamedTypeSymbol? _cloneableAttribute;
private INamedTypeSymbol? _ignoreCloneAttribute;
diff --git a/src/Nadeko.Bot.Generators.Cloneable/Nadeko.Bot.Generators.Cloneable.csproj b/src/Nadeko.Bot.Generators.Cloneable/Nadeko.Bot.Generators.Cloneable.csproj
index 6836c6808..5ba6445d2 100644
--- a/src/Nadeko.Bot.Generators.Cloneable/Nadeko.Bot.Generators.Cloneable.csproj
+++ b/src/Nadeko.Bot.Generators.Cloneable/Nadeko.Bot.Generators.Cloneable.csproj
@@ -1,9 +1,17 @@
- net7.0
+ netstandard2.0
+ latest
+ false
+ true
+ true
enable
enable
+
+
+
+
diff --git a/src/NadekoBot.Generators/LocalizedStringsGenerator.cs b/src/Nadeko.Bot.Generators.Strings/LocalizedStringsGenerator.cs
similarity index 89%
rename from src/NadekoBot.Generators/LocalizedStringsGenerator.cs
rename to src/Nadeko.Bot.Generators.Strings/LocalizedStringsGenerator.cs
index 52d2491bd..4fe5cce09 100644
--- a/src/NadekoBot.Generators/LocalizedStringsGenerator.cs
+++ b/src/Nadeko.Bot.Generators.Strings/LocalizedStringsGenerator.cs
@@ -26,20 +26,20 @@ namespace NadekoBot.Generators
[Generator]
public class LocalizedStringsGenerator : ISourceGenerator
{
- private const string LOC_STR_SOURCE = @"namespace NadekoBot
-{
- public readonly struct LocStr
- {
- public readonly string Key;
- public readonly object[] Params;
-
- public LocStr(string key, params object[] data)
- {
- Key = key;
- Params = data;
- }
- }
-}";
+// private const string LOC_STR_SOURCE = @"namespace NadekoBot
+// {
+// public readonly struct LocStr
+// {
+// public readonly string Key;
+// public readonly object[] Params;
+//
+// public LocStr(string key, params object[] data)
+// {
+// Key = key;
+// Params = data;
+// }
+// }
+// }";
public void Initialize(GeneratorInitializationContext context)
{
@@ -106,7 +106,7 @@ namespace NadekoBot.Generators
context.AddSource("strs.g.cs", stringWriter.ToString());
}
- context.AddSource("LocStr.g.cs", LOC_STR_SOURCE);
+ // context.AddSource("LocStr.g.cs", LOC_STR_SOURCE);
}
private List GetFields(string? dataText)
diff --git a/src/NadekoBot.Generators/NadekoBot.Generators.csproj b/src/Nadeko.Bot.Generators.Strings/Nadeko.Bot.Generators.Strings.csproj
similarity index 88%
rename from src/NadekoBot.Generators/NadekoBot.Generators.csproj
rename to src/Nadeko.Bot.Generators.Strings/Nadeko.Bot.Generators.Strings.csproj
index de4842b04..c49280b68 100644
--- a/src/NadekoBot.Generators/NadekoBot.Generators.csproj
+++ b/src/Nadeko.Bot.Generators.Strings/Nadeko.Bot.Generators.Strings.csproj
@@ -6,6 +6,9 @@
false
true
true
+ enable
+ enable
+ NadekoBot.Generators
diff --git a/src/NadekoBot.Generators/README.md b/src/Nadeko.Bot.Generators.Strings/README.md
similarity index 100%
rename from src/NadekoBot.Generators/README.md
rename to src/Nadeko.Bot.Generators.Strings/README.md
diff --git a/src/Nadeko.Bot.Modules.Administration/Role/IReactionRoleService.cs b/src/Nadeko.Bot.Modules.Administration/Role/IReactionRoleService.cs
index cdd5a51a8..3966d91bd 100644
--- a/src/Nadeko.Bot.Modules.Administration/Role/IReactionRoleService.cs
+++ b/src/Nadeko.Bot.Modules.Administration/Role/IReactionRoleService.cs
@@ -1,5 +1,5 @@
#nullable disable
-using NadekoBot.Modules.Utility.Patronage;
+using NadekoBot.Modules.Patronage;
using NadekoBot.Services.Database.Models;
using OneOf;
using OneOf.Types;
diff --git a/src/Nadeko.Bot.Modules.Administration/Role/ReactionRolesService.cs b/src/Nadeko.Bot.Modules.Administration/Role/ReactionRolesService.cs
index b70e4ec97..9b35ab141 100644
--- a/src/Nadeko.Bot.Modules.Administration/Role/ReactionRolesService.cs
+++ b/src/Nadeko.Bot.Modules.Administration/Role/ReactionRolesService.cs
@@ -3,7 +3,7 @@ using LinqToDB;
using LinqToDB.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db;
-using NadekoBot.Modules.Utility.Patronage;
+using NadekoBot.Modules.Patronage;
using NadekoBot.Services.Database.Models;
using OneOf.Types;
using OneOf;
diff --git a/src/Nadeko.Bot.Modules.Expresssions/Nadeko.Bot.Modules.Expresssions.csproj b/src/Nadeko.Bot.Modules.Expresssions/Nadeko.Bot.Modules.Expresssions.csproj
index 4dd08788e..49b978351 100644
--- a/src/Nadeko.Bot.Modules.Expresssions/Nadeko.Bot.Modules.Expresssions.csproj
+++ b/src/Nadeko.Bot.Modules.Expresssions/Nadeko.Bot.Modules.Expresssions.csproj
@@ -18,8 +18,4 @@
-
-
-
-
diff --git a/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs b/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs
index 136ab7f36..dc8cb7102 100644
--- a/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs
+++ b/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs
@@ -3,7 +3,6 @@ using LinqToDB;
using LinqToDB.EntityFrameworkCore;
using NadekoBot.Db;
using NadekoBot.Db.Models;
-using NadekoBot.Modules.Utility.Patronage;
using NadekoBot.Modules.Gambling.Bank;
using NadekoBot.Modules.Gambling.Common;
using NadekoBot.Modules.Gambling.Services;
@@ -15,6 +14,7 @@ using System.Globalization;
using System.Text;
using Nadeko.Econ.Gambling.Rps;
using NadekoBot.Common.TypeReaders;
+using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Gambling;
diff --git a/src/Nadeko.Bot.Modules.Gambling/Games/ChatterBot/ChatterbotService.cs b/src/Nadeko.Bot.Modules.Gambling/Games/ChatterBot/ChatterbotService.cs
index e5e11e0a8..5910d8ce8 100644
--- a/src/Nadeko.Bot.Modules.Gambling/Games/ChatterBot/ChatterbotService.cs
+++ b/src/Nadeko.Bot.Modules.Gambling/Games/ChatterBot/ChatterbotService.cs
@@ -4,8 +4,8 @@ using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db.Models;
using NadekoBot.Modules.Games.Common;
using NadekoBot.Modules.Games.Common.ChatterBot;
+using NadekoBot.Modules.Patronage;
using NadekoBot.Modules.Permissions;
-using NadekoBot.Modules.Utility.Patronage;
namespace NadekoBot.Modules.Games.Services;
diff --git a/src/Nadeko.Bot.Modules.Gambling/Nadeko.Bot.Modules.Gambling.csproj b/src/Nadeko.Bot.Modules.Gambling/Nadeko.Bot.Modules.Gambling.csproj
index 1a78c0607..ff82a6739 100644
--- a/src/Nadeko.Bot.Modules.Gambling/Nadeko.Bot.Modules.Gambling.csproj
+++ b/src/Nadeko.Bot.Modules.Gambling/Nadeko.Bot.Modules.Gambling.csproj
@@ -7,13 +7,15 @@
-
-
+
+
+
+
-
-
+
+
diff --git a/src/Nadeko.Bot.Modules.Help/Help.cs b/src/Nadeko.Bot.Modules.Help/Help.cs
index e52a865d5..7c71a9606 100644
--- a/src/Nadeko.Bot.Modules.Help/Help.cs
+++ b/src/Nadeko.Bot.Modules.Help/Help.cs
@@ -6,18 +6,20 @@ using NadekoBot.Modules.Help.Services;
using Newtonsoft.Json;
using System.Text;
using System.Text.Json;
+using Nadeko.Bot.Common;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace NadekoBot.Modules.Help;
-public partial class Help : NadekoModule
+public sealed class Help : NadekoModule
{
public const string PATREON_URL = "https://patreon.com/nadekobot";
public const string PAYPAL_URL = "https://paypal.me/Kwoth";
+ private readonly ICommandsUtilityService _cus;
private readonly CommandService _cmds;
private readonly BotConfigService _bss;
- private readonly GlobalPermissionService _perms;
+ private readonly IPermissionChecker _perms;
private readonly IServiceProvider _services;
private readonly DiscordSocketClient _client;
private readonly IBotStrings _strings;
@@ -26,7 +28,8 @@ public partial class Help : NadekoModule
private readonly IMedusaLoaderService _medusae;
public Help(
- GlobalPermissionService perms,
+ ICommandsUtilityService _cus,
+ IPermissionChecker perms,
CommandService cmds,
BotConfigService bss,
IServiceProvider services,
@@ -34,6 +37,7 @@ public partial class Help : NadekoModule
IBotStrings strings,
IMedusaLoaderService medusae)
{
+ this._cus = _cus;
_cmds = cmds;
_bss = bss;
_perms = perms;
@@ -53,11 +57,11 @@ public partial class Help : NadekoModule
var clientId = await _lazyClientId.Value;
var r = new ReplacementBuilder().WithDefault(Context)
- .WithOverride("{0}", () => clientId.ToString())
- .WithOverride("{1}", () => prefix)
- .WithOverride("%prefix%", () => prefix)
- .WithOverride("%bot.prefix%", () => prefix)
- .Build();
+ .WithOverride("{0}", () => clientId.ToString())
+ .WithOverride("{1}", () => prefix)
+ .WithOverride("%prefix%", () => prefix)
+ .WithOverride("%bot.prefix%", () => prefix)
+ .Build();
var text = SmartText.CreateFrom(botSettings.HelpText);
return r.Replace(text);
@@ -69,10 +73,15 @@ public partial class Help : NadekoModule
if (--page < 0)
return;
- var topLevelModules = _cmds.Modules.GroupBy(m => m.GetTopLevelModule())
- .Where(m => !_perms.BlockedModules.Contains(m.Key.Name.ToLowerInvariant()))
- .Select(x => x.Key)
- .ToList();
+ var topLevelModules = new List();
+ foreach (var m in _cmds.Modules.GroupBy(x => x.GetTopLevelModule()).Select(x => x.Key))
+ {
+ var result = await _perms.CheckAsync(ctx.Guild, ctx.Channel, ctx.User,
+ m.Name, null);
+
+ if (result.IsT0)
+ topLevelModules.Add(m);
+ }
await ctx.SendPaginatedConfirmAsync(page,
cur =>
@@ -88,12 +97,12 @@ public partial class Help : NadekoModule
}
localModules.OrderBy(module => module.Name)
- .ToList()
- .ForEach(module => embed.AddField($"{GetModuleEmoji(module.Name)} {module.Name}",
- GetModuleDescription(module.Name)
- + "\n"
- + Format.Code(GetText(strs.module_footer(prefix, module.Name.ToLowerInvariant()))),
- true));
+ .ToList()
+ .ForEach(module => embed.AddField($"{GetModuleEmoji(module.Name)} {module.Name}",
+ GetModuleDescription(module.Name)
+ + "\n"
+ + Format.Code(GetText(strs.module_footer(prefix, module.Name.ToLowerInvariant()))),
+ true));
return embed;
},
@@ -109,11 +118,11 @@ public partial class Help : NadekoModule
if (key.Key == strs.module_description_missing.Key)
{
var desc = _medusae
- .GetLoadedMedusae(Culture)
- .FirstOrDefault(m => m.Sneks
- .Any(x => x.Name.Equals(moduleName,
- StringComparison.InvariantCultureIgnoreCase)))
- ?.Description;
+ .GetLoadedMedusae(Culture)
+ .FirstOrDefault(m => m.Sneks
+ .Any(x => x.Name.Equals(moduleName,
+ StringComparison.InvariantCultureIgnoreCase)))
+ ?.Description;
if (desc is not null)
return desc;
@@ -150,6 +159,8 @@ public partial class Help : NadekoModule
return strs.module_description_xp;
case "medusa":
return strs.module_description_medusa;
+ case "patronage":
+ return strs.module_description_patronage;
default:
return strs.module_description_missing;
}
@@ -182,6 +193,8 @@ public partial class Help : NadekoModule
return "🚓";
case "xp":
return "📝";
+ case "patronage":
+ return "💝";
default:
return "📖";
}
@@ -191,7 +204,6 @@ public partial class Help : NadekoModule
[NadekoOptions]
public async Task Commands(string module = null, params string[] args)
{
- module = module?.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(module))
{
await Modules();
@@ -203,14 +215,22 @@ public partial class Help : NadekoModule
// Find commands for that module
// don't show commands which are blocked
// order by name
- var cmds = _cmds.Commands
- .Where(c => c.Module.GetTopLevelModule()
- .Name.ToUpperInvariant()
- .StartsWith(module, StringComparison.InvariantCulture))
- .Where(c => !_perms.BlockedCommands.Contains(c.Aliases[0].ToLowerInvariant()))
- .OrderBy(c => c.Aliases[0])
- .DistinctBy(x => x.Aliases[0])
- .ToList();
+ var allowed = new List();
+
+ foreach (var cmd in _cmds.Commands
+ .Where(c => c.Module.GetTopLevelModule()
+ .Name
+ .StartsWith(module, StringComparison.InvariantCultureIgnoreCase)))
+ {
+ var result = await _perms.CheckAsync(ctx.Guild, ctx.Channel, ctx.User, cmd.Module.GetTopLevelModule().Name,
+ cmd.Name);
+ if (result.IsT0)
+ allowed.Add(cmd);
+ }
+
+ var cmds = allowed.OrderBy(c => c.Aliases[0])
+ .DistinctBy(x => x.Aliases[0])
+ .ToList();
// check preconditions for all commands, but only if it's not 'all'
@@ -219,12 +239,12 @@ public partial class Help : NadekoModule
if (opts.View != CommandsOptions.ViewType.All)
{
succ = new((await cmds.Select(async x =>
- {
- var pre = await x.CheckPreconditionsAsync(Context, _services);
- return (Cmd: x, Succ: pre.IsSuccess);
- })
- .WhenAll()).Where(x => x.Succ)
- .Select(x => x.Cmd));
+ {
+ var pre = await x.CheckPreconditionsAsync(Context, _services);
+ return (Cmd: x, Succ: pre.IsSuccess);
+ })
+ .WhenAll()).Where(x => x.Succ)
+ .Select(x => x.Cmd));
if (opts.View == CommandsOptions.ViewType.Hide)
// if hidden is specified, completely remove these commands from the list
@@ -232,8 +252,8 @@ public partial class Help : NadekoModule
}
var cmdsWithGroup = cmds.GroupBy(c => c.Module.GetGroupName())
- .OrderBy(x => x.Key == x.First().Module.Name ? int.MaxValue : x.Count())
- .ToList();
+ .OrderBy(x => x.Key == x.First().Module.Name ? int.MaxValue : x.Count())
+ .ToList();
if (cmdsWithGroup.Count == 0)
{
@@ -253,28 +273,28 @@ public partial class Help : NadekoModule
for (var i = 0; i < last; i++)
{
var transformed = g.ElementAt(i)
- .Select(x =>
- {
- //if cross is specified, and the command doesn't satisfy the requirements, cross it out
- if (opts.View == CommandsOptions.ViewType.Cross)
- {
- return
- $"{(succ.Contains(x) ? "✅" : "❌")}{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
- }
+ .Select(x =>
+ {
+ //if cross is specified, and the command doesn't satisfy the requirements, cross it out
+ if (opts.View == CommandsOptions.ViewType.Cross)
+ {
+ return
+ $"{(succ.Contains(x) ? "✅" : "❌")}{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
+ }
- return
- $"{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
- });
+ return
+ $"{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
+ });
if (i == last - 1 && (i + 1) % 2 != 0)
{
transformed = transformed.Chunk(2)
- .Select(x =>
- {
- if (x.Count() == 1)
- return $"{x.First()}";
- return string.Concat(x);
- });
+ .Select(x =>
+ {
+ if (x.Count() == 1)
+ return $"{x.First()}";
+ return string.Concat(x);
+ });
}
embed.AddField(g.ElementAt(i).Key, "```css\n" + string.Join("\n", transformed) + "\n```", true);
@@ -288,8 +308,8 @@ public partial class Help : NadekoModule
private async Task Group(ModuleInfo group)
{
var eb = _eb.Create(ctx)
- .WithTitle(GetText(strs.cmd_group_commands(group.Name)))
- .WithOkColor();
+ .WithTitle(GetText(strs.cmd_group_commands(group.Name)))
+ .WithOkColor();
foreach (var cmd in group.Commands)
{
@@ -315,9 +335,9 @@ public partial class Help : NadekoModule
fail = fail.Substring(prefix.Length);
var group = _cmds.Modules
- .SelectMany(x => x.Submodules)
- .Where(x => !string.IsNullOrWhiteSpace(x.Group))
- .FirstOrDefault(x => x.Group.Equals(fail, StringComparison.InvariantCultureIgnoreCase));
+ .SelectMany(x => x.Submodules)
+ .Where(x => !string.IsNullOrWhiteSpace(x.Group))
+ .FirstOrDefault(x => x.Group.Equals(fail, StringComparison.InvariantCultureIgnoreCase));
if (group is not null)
{
@@ -343,8 +363,13 @@ public partial class Help : NadekoModule
if (data == default)
return;
await ch.SendAsync(data);
- try { await ctx.OkAsync(); }
- catch { } // ignore if bot can't react
+ try
+ {
+ await ctx.OkAsync();
+ }
+ catch
+ {
+ } // ignore if bot can't react
}
catch (Exception)
{
@@ -354,7 +379,7 @@ public partial class Help : NadekoModule
return;
}
- var embed = _service.GetCommandHelp(com, ctx.Guild);
+ var embed = _cus.GetCommandHelp(com, ctx.Guild);
await channel.EmbedAsync(embed);
}
@@ -367,29 +392,29 @@ public partial class Help : NadekoModule
// order commands by top level module name
// and make a dictionary of >
var cmdData = _cmds.Commands.GroupBy(x => x.Module.GetTopLevelModule().Name)
- .OrderBy(x => x.Key)
- .ToDictionary(x => x.Key,
- x => x.DistinctBy(c => c.Aliases.First())
- .Select(com =>
- {
- List optHelpStr = null;
-
- var opt = HelpService.GetNadekoOptionType(com.Attributes);
- if (opt is not null)
- optHelpStr = HelpService.GetCommandOptionHelpList(opt);
+ .OrderBy(x => x.Key)
+ .ToDictionary(x => x.Key,
+ x => x.DistinctBy(c => c.Aliases.First())
+ .Select(com =>
+ {
+ List optHelpStr = null;
- return new CommandJsonObject
- {
- Aliases = com.Aliases.Select(alias => prefix + alias).ToArray(),
- Description = com.RealSummary(_strings, _medusae, Culture, prefix),
- Usage = com.RealRemarksArr(_strings, _medusae, Culture, prefix),
- Submodule = com.Module.Name,
- Module = com.Module.GetTopLevelModule().Name,
- Options = optHelpStr,
- Requirements = HelpService.GetCommandRequirements(com)
- };
- })
- .ToList());
+ var opt = CommandsUtilityService.GetNadekoOptionType(com.Attributes);
+ if (opt is not null)
+ optHelpStr = CommandsUtilityService.GetCommandOptionHelpList(opt);
+
+ return new CommandJsonObject
+ {
+ Aliases = com.Aliases.Select(alias => prefix + alias).ToArray(),
+ Description = com.RealSummary(_strings, _medusae, Culture, prefix),
+ Usage = com.RealRemarksArr(_strings, _medusae, Culture, prefix),
+ Submodule = com.Module.Name,
+ Module = com.Module.GetTopLevelModule().Name,
+ Options = optHelpStr,
+ Requirements = CommandsUtilityService.GetCommandRequirements(com)
+ };
+ })
+ .ToList());
var readableData = JsonConvert.SerializeObject(cmdData, Formatting.Indented);
var uploadData = JsonConvert.SerializeObject(cmdData, Formatting.None);
@@ -512,8 +537,8 @@ public partial class Help : NadekoModule
SelfhostAction));
var eb = _eb.Create(ctx)
- .WithOkColor()
- .WithTitle("Thank you for considering to donate to the NadekoBot project!");
+ .WithOkColor()
+ .WithTitle("Thank you for considering to donate to the NadekoBot project!");
eb
.WithDescription("NadekoBot relies on donations to keep the servers, services and APIs running.\n"
diff --git a/src/Nadeko.Bot.Modules.Help/HelpService.cs b/src/Nadeko.Bot.Modules.Help/HelpService.cs
index 678a0ce7b..96bc87fac 100644
--- a/src/Nadeko.Bot.Modules.Help/HelpService.cs
+++ b/src/Nadeko.Bot.Modules.Help/HelpService.cs
@@ -1,37 +1,15 @@
#nullable disable
-using CommandLine;
-using Nadeko.Common;
-using Nadeko.Medusa;
using NadekoBot.Common.ModuleBehaviors;
namespace NadekoBot.Modules.Help.Services;
public class HelpService : IExecNoCommand, INService
{
- private readonly CommandHandler _ch;
- private readonly IBotStrings _strings;
- private readonly DiscordPermOverrideService _dpos;
private readonly BotConfigService _bss;
- private readonly IEmbedBuilderService _eb;
- private readonly ILocalization _loc;
- private readonly IMedusaLoaderService _medusae;
- public HelpService(
- CommandHandler ch,
- IBotStrings strings,
- DiscordPermOverrideService dpos,
- BotConfigService bss,
- IEmbedBuilderService eb,
- ILocalization loc,
- IMedusaLoaderService medusae)
+ public HelpService(BotConfigService bss)
{
- _ch = ch;
- _strings = strings;
- _dpos = dpos;
_bss = bss;
- _eb = eb;
- _loc = loc;
- _medusae = medusae;
}
public Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
@@ -44,13 +22,14 @@ public class HelpService : IExecNoCommand, INService
// only send dm help text if it contains one of the keywords, if they're specified
// if they're not, then reply to every DM
- if (settings.DmHelpTextKeywords is not null && !settings.DmHelpTextKeywords.Any(k => msg.Content.Contains(k)))
+ if (settings.DmHelpTextKeywords is not null &&
+ !settings.DmHelpTextKeywords.Any(k => msg.Content.Contains(k)))
return Task.CompletedTask;
var rep = new ReplacementBuilder().WithOverride("%prefix%", () => _bss.Data.Prefix)
- .WithOverride("%bot.prefix%", () => _bss.Data.Prefix)
- .WithUser(msg.Author)
- .Build();
+ .WithOverride("%bot.prefix%", () => _bss.Data.Prefix)
+ .WithUser(msg.Author)
+ .Build();
var text = SmartText.CreateFrom(settings.DmHelpText);
text = rep.Replace(text);
@@ -60,143 +39,4 @@ public class HelpService : IExecNoCommand, INService
return Task.CompletedTask;
}
-
- public IEmbedBuilder GetCommandHelp(CommandInfo com, IGuild guild)
- {
- var prefix = _ch.GetPrefix(guild);
-
- var str = $"**`{prefix + com.Aliases.First()}`**";
- var alias = com.Aliases.Skip(1).FirstOrDefault();
- if (alias is not null)
- str += $" **/ `{prefix + alias}`**";
-
- var culture = _loc.GetCultureInfo(guild);
-
- var em = _eb.Create()
- .AddField(str, $"{com.RealSummary(_strings, _medusae, culture, prefix)}", true);
-
- _dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides);
- var reqs = GetCommandRequirements(com, (GuildPermission?)overrides);
- if (reqs.Any())
- em.AddField(GetText(strs.requires, guild), string.Join("\n", reqs));
-
- em.AddField(_strings.GetText(strs.usage),
- string.Join("\n", com.RealRemarksArr(_strings,_medusae, culture, prefix).Map(arg => Format.Code(arg))))
- .WithFooter(GetText(strs.module(com.Module.GetTopLevelModule().Name), guild))
- .WithOkColor();
-
- var opt = GetNadekoOptionType(com.Attributes);
- if (opt is not null)
- {
- var hs = GetCommandOptionHelp(opt);
- if (!string.IsNullOrWhiteSpace(hs))
- em.AddField(GetText(strs.options, guild), hs);
- }
-
- return em;
- }
-
- public static Type GetNadekoOptionType(IEnumerable attributes)
- => attributes
- .Select(a => a.GetType())
- .Where(a => a.IsGenericType
- && a.GetGenericTypeDefinition() == typeof(NadekoOptionsAttribute<>))
- .Select(a => a.GenericTypeArguments[0])
- .FirstOrDefault();
-
- public static string GetCommandOptionHelp(Type opt)
- {
- var strs = GetCommandOptionHelpList(opt);
-
- return string.Join("\n", strs);
- }
-
- public static List GetCommandOptionHelpList(Type opt)
- {
- var strs = opt.GetProperties()
- .Select(x => x.GetCustomAttributes(true).FirstOrDefault(a => a is OptionAttribute))
- .Where(x => x is not null)
- .Cast()
- .Select(x =>
- {
- var toReturn = $"`--{x.LongName}`";
-
- if (!string.IsNullOrWhiteSpace(x.ShortName))
- toReturn += $" (`-{x.ShortName}`)";
-
- toReturn += $" {x.HelpText} ";
- return toReturn;
- })
- .ToList();
-
- return strs;
- }
-
-
- public static string[] GetCommandRequirements(CommandInfo cmd, GuildPerm? overrides = null)
- {
- var toReturn = new List();
-
- if (cmd.Preconditions.Any(x => x is OwnerOnlyAttribute))
- toReturn.Add("Bot Owner Only");
-
- if(cmd.Preconditions.Any(x => x is NoPublicBotAttribute)
- || cmd.Module
- .Preconditions
- .Any(x => x is NoPublicBotAttribute)
- || cmd.Module.GetTopLevelModule()
- .Preconditions
- .Any(x => x is NoPublicBotAttribute))
- toReturn.Add("No Public Bot");
-
- if (cmd.Preconditions
- .Any(x => x is OnlyPublicBotAttribute)
- || cmd.Module
- .Preconditions
- .Any(x => x is OnlyPublicBotAttribute)
- || cmd.Module.GetTopLevelModule()
- .Preconditions
- .Any(x => x is OnlyPublicBotAttribute))
- toReturn.Add("Only Public Bot");
-
- var userPermString = cmd.Preconditions
- .Where(ca => ca is UserPermAttribute)
- .Cast()
- .Select(userPerm =>
- {
- if (userPerm.ChannelPermission is { } cPerm)
- return GetPreconditionString(cPerm);
-
- if (userPerm.GuildPermission is { } gPerm)
- return GetPreconditionString(gPerm);
-
- return string.Empty;
- })
- .Where(x => !string.IsNullOrWhiteSpace(x))
- .Join('\n');
-
- if (overrides is null)
- {
- if (!string.IsNullOrWhiteSpace(userPermString))
- toReturn.Add(userPermString);
- }
- else
- {
- if (!string.IsNullOrWhiteSpace(userPermString))
- toReturn.Add(Format.Strikethrough(userPermString));
-
- toReturn.Add(GetPreconditionString(overrides.Value));
- }
-
- return toReturn.ToArray();
- }
-
- public static string GetPreconditionString(ChannelPerm perm)
- => (perm + " Channel Permission").Replace("Guild", "Server");
-
- public static string GetPreconditionString(GuildPerm perm)
- => (perm + " Server Permission").Replace("Guild", "Server");
-
- private string GetText(LocStr str, IGuild guild)
- => _strings.GetText(str, guild?.Id);
-}
+}
\ No newline at end of file
diff --git a/src/Nadeko.Bot.Modules.Help/Nadeko.Bot.Modules.Help.csproj b/src/Nadeko.Bot.Modules.Help/Nadeko.Bot.Modules.Help.csproj
index 88326f525..4018c363d 100644
--- a/src/Nadeko.Bot.Modules.Help/Nadeko.Bot.Modules.Help.csproj
+++ b/src/Nadeko.Bot.Modules.Help/Nadeko.Bot.Modules.Help.csproj
@@ -7,11 +7,13 @@
-
+
+
+
-
+
-
+
diff --git a/src/Nadeko.Bot.Modules.Music/Nadeko.Bot.Modules.Music.csproj b/src/Nadeko.Bot.Modules.Music/Nadeko.Bot.Modules.Music.csproj
index 00a63d5fa..2e2dfd4c1 100644
--- a/src/Nadeko.Bot.Modules.Music/Nadeko.Bot.Modules.Music.csproj
+++ b/src/Nadeko.Bot.Modules.Music/Nadeko.Bot.Modules.Music.csproj
@@ -7,13 +7,15 @@
-
-
-
+
+
+
+
+
-
+
-
+
diff --git a/src/Nadeko.Bot.Modules.Patronage/GlobalUsings.cs b/src/Nadeko.Bot.Modules.Patronage/GlobalUsings.cs
new file mode 100644
index 000000000..f36328bd4
--- /dev/null
+++ b/src/Nadeko.Bot.Modules.Patronage/GlobalUsings.cs
@@ -0,0 +1,31 @@
+// global using System.Collections.Concurrent;
+global using NonBlocking;
+
+// packages
+global using Serilog;
+global using Humanizer;
+
+// nadekobot
+global using NadekoBot;
+global using NadekoBot.Services;
+global using Nadeko.Common; // new project
+global using NadekoBot.Common; // old + nadekobot specific things
+global using NadekoBot.Common.Attributes;
+global using NadekoBot.Extensions;
+global using Nadeko.Snake;
+
+// discord
+global using Discord;
+global using Discord.Commands;
+global using Discord.Net;
+global using Discord.WebSocket;
+
+// aliases
+global using GuildPerm = Discord.GuildPermission;
+global using ChannelPerm = Discord.ChannelPermission;
+global using BotPermAttribute = Discord.Commands.RequireBotPermissionAttribute;
+global using LeftoverAttribute = Discord.Commands.RemainderAttribute;
+global using TypeReaderResult = NadekoBot.Common.TypeReaders.TypeReaderResult;
+
+// non-essential
+global using JetBrains.Annotations;
\ No newline at end of file
diff --git a/src/Nadeko.Bot.Modules.Patronage/Nadeko.Bot.Modules.Patronage.csproj b/src/Nadeko.Bot.Modules.Patronage/Nadeko.Bot.Modules.Patronage.csproj
new file mode 100644
index 000000000..49ff4f201
--- /dev/null
+++ b/src/Nadeko.Bot.Modules.Patronage/Nadeko.Bot.Modules.Patronage.csproj
@@ -0,0 +1,16 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/Config/PatronageConfig.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/Config/PatronageConfig.cs
similarity index 87%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/Config/PatronageConfig.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/Config/PatronageConfig.cs
index f5bef4a91..e4c9339b4 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/Config/PatronageConfig.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/Config/PatronageConfig.cs
@@ -1,6 +1,6 @@
using NadekoBot.Common.Configs;
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public class PatronageConfig : ConfigServiceBase
{
@@ -8,7 +8,7 @@ public class PatronageConfig : ConfigServiceBase
=> "patron";
private static readonly TypedKey _changeKey
- = new TypedKey("config.patron.updated");
+ = new("config.patron.updated");
private const string FILE_PATH = "data/patron.yml";
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/CurrencyRewardService.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/CurrencyRewardService.cs
similarity index 96%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/CurrencyRewardService.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/CurrencyRewardService.cs
index 800471529..4c4812c38 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/CurrencyRewardService.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/CurrencyRewardService.cs
@@ -1,20 +1,18 @@
#nullable disable
using LinqToDB;
using LinqToDB.EntityFrameworkCore;
-using NadekoBot.Modules.Utility.Patronage;
-using NadekoBot.Modules.Gambling.Bank;
using NadekoBot.Modules.Gambling.Services;
+using NadekoBot.Modules.Patronage;
using NadekoBot.Services.Currency;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Utility;
-public class CurrencyRewardService : INService, IDisposable
+public sealed class CurrencyRewardService : INService, IDisposable
{
private readonly ICurrencyService _cs;
private readonly IPatronageService _ps;
private readonly DbService _db;
- private readonly IBankService _bs;
private readonly IEmbedBuilderService _eb;
private readonly GamblingConfigService _config;
private readonly DiscordSocketClient _client;
@@ -23,7 +21,6 @@ public class CurrencyRewardService : INService, IDisposable
ICurrencyService cs,
IPatronageService ps,
DbService db,
- IBankService bs,
IEmbedBuilderService eb,
GamblingConfigService config,
DiscordSocketClient client)
@@ -31,7 +28,6 @@ public class CurrencyRewardService : INService, IDisposable
_cs = cs;
_ps = ps;
_db = db;
- _bs = bs;
_eb = eb;
_config = config;
_client = client;
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/InsufficientTier.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/InsufficientTier.cs
similarity index 84%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/InsufficientTier.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/InsufficientTier.cs
index 7d478b98d..3bd213498 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/InsufficientTier.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/InsufficientTier.cs
@@ -1,6 +1,6 @@
using NadekoBot.Db.Models;
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
public readonly struct InsufficientTier
{
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonClient.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonClient.cs
similarity index 98%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonClient.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonClient.cs
index 63d1184e3..b210ac11c 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonClient.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonClient.cs
@@ -1,11 +1,10 @@
#nullable disable
-using NadekoBot.Modules.Utility.Common.Patreon;
using OneOf;
using OneOf.Types;
using System.Net.Http.Json;
using System.Text.Json;
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
public class PatreonClient : IDisposable
{
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonCredentials.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonCredentials.cs
similarity index 86%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonCredentials.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonCredentials.cs
index 67f619a30..db3c205ee 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonCredentials.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonCredentials.cs
@@ -1,5 +1,5 @@
#nullable disable
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
public readonly struct PatreonCredentials
{
diff --git a/src/Nadeko.Bot.Modules.Utility/_Common/Patreon/PatreonData.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonData.cs
similarity index 98%
rename from src/Nadeko.Bot.Modules.Utility/_Common/Patreon/PatreonData.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonData.cs
index 9a855e004..713ea030b 100644
--- a/src/Nadeko.Bot.Modules.Utility/_Common/Patreon/PatreonData.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonData.cs
@@ -1,7 +1,7 @@
#nullable disable
using System.Text.Json.Serialization;
-namespace NadekoBot.Modules.Utility.Common.Patreon;
+namespace NadekoBot.Modules.Patronage;
public sealed class Attributes
{
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonMemberData.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonMemberData.cs
similarity index 96%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonMemberData.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonMemberData.cs
index f4c309348..6a5035f2a 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonMemberData.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonMemberData.cs
@@ -1,5 +1,5 @@
#nullable disable
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
public sealed class PatreonMemberData : ISubscriberData
{
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonRefreshData.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonRefreshData.cs
similarity index 92%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonRefreshData.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonRefreshData.cs
index 917c450cd..f761b8348 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonRefreshData.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonRefreshData.cs
@@ -1,7 +1,7 @@
#nullable disable
using System.Text.Json.Serialization;
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
public sealed class PatreonRefreshData
{
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonSubscriptionHandler.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonSubscriptionHandler.cs
similarity index 93%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonSubscriptionHandler.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonSubscriptionHandler.cs
index 4c17e2ae9..b465b7e49 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/Patreon/PatreonSubscriptionHandler.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/Patreon/PatreonSubscriptionHandler.cs
@@ -1,15 +1,13 @@
#nullable disable
-using NadekoBot.Modules.Utility.Patronage;
-
-namespace NadekoBot.Modules.Utility;
+namespace NadekoBot.Modules.Patronage;
///
/// Service tasked with handling pledges on patreon
///
public sealed class PatreonSubscriptionHandler : ISubscriptionHandler, INService
{
- private readonly IBotCredsProvider _credsProvider;
- private readonly PatreonClient _patreonClient;
+ private readonly IBotCredsProvider _credsProvider;
+ private readonly PatreonClient _patreonClient;
public PatreonSubscriptionHandler(IBotCredsProvider credsProvider)
{
diff --git a/src/Nadeko.Bot.Modules.Patronage/Patronage/PatronageCommands.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/PatronageCommands.cs
new file mode 100644
index 000000000..9fd961929
--- /dev/null
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/PatronageCommands.cs
@@ -0,0 +1,148 @@
+namespace NadekoBot.Modules.Patronage;
+
+[OnlyPublicBot]
+public partial class Patronage : NadekoModule
+{
+ private readonly PatronageService _service;
+ private readonly PatronageConfig _pConf;
+
+ public Patronage(PatronageService service, PatronageConfig pConf)
+ {
+ _service = service;
+ _pConf = pConf;
+ }
+
+ [Cmd]
+ [Priority(2)]
+ public Task Patron()
+ => InternalPatron(ctx.User);
+
+ [Cmd]
+ [Priority(0)]
+ [OwnerOnly]
+ public Task Patron(IUser user)
+ => InternalPatron(user);
+
+ [Cmd]
+ [Priority(0)]
+ [OwnerOnly]
+ public async Task PatronMessage(PatronTier tierAndHigher, string message)
+ {
+ _ = ctx.Channel.TriggerTypingAsync();
+ var result = await _service.SendMessageToPatronsAsync(tierAndHigher, message);
+
+ await ReplyConfirmLocalizedAsync(strs.patron_msg_sent(
+ Format.Code(tierAndHigher.ToString()),
+ Format.Bold(result.Success.ToString()),
+ Format.Bold(result.Failed.ToString())));
+ }
+
+ // [Cmd]
+ // [OwnerOnly]
+ // public async Task PatronGift(IUser user, int amount)
+ // {
+ // // i can't figure out a good way to gift more than one month at the moment.
+ //
+ // if (amount < 1)
+ // return;
+ //
+ // var patron = _service.GiftPatronAsync(user, amount);
+ //
+ // var eb = _eb.Create(ctx);
+ //
+ // await ctx.Channel.EmbedAsync(eb.WithDescription($"Added **{days}** days of Patron benefits to {user.Mention}!")
+ // .AddField("Tier", Format.Bold(patron.Tier.ToString()), true)
+ // .AddField("Amount", $"**{patron.Amount / 100.0f:N1}$**", true)
+ // .AddField("Until", TimestampTag.FromDateTime(patron.ValidThru.AddDays(1))));
+ //
+ //
+ // }
+
+ private async Task InternalPatron(IUser user)
+ {
+ if (!_pConf.Data.IsEnabled)
+ {
+ await ReplyErrorLocalizedAsync(strs.patron_not_enabled);
+ return;
+ }
+
+ var patron = await _service.GetPatronAsync(user.Id);
+ var quotaStats = await _service.GetUserQuotaStatistic(user.Id);
+
+ var eb = _eb.Create(ctx)
+ .WithAuthor(user)
+ .WithTitle(GetText(strs.patron_info))
+ .WithOkColor();
+
+ if (quotaStats.Commands.Count == 0
+ && quotaStats.Groups.Count == 0
+ && quotaStats.Modules.Count == 0)
+ {
+ eb.WithDescription(GetText(strs.no_quota_found));
+ }
+ else
+ {
+ eb.AddField(GetText(strs.tier), Format.Bold(patron.Tier.ToFullName()), true)
+ .AddField(GetText(strs.pledge), $"**{patron.Amount / 100.0f:N1}$**", true);
+
+ if (patron.Tier != PatronTier.None)
+ eb.AddField(GetText(strs.expires), patron.ValidThru.AddDays(1).ToShortAndRelativeTimestampTag(), true);
+
+ eb.AddField(GetText(strs.quotas), "", false);
+
+ if (quotaStats.Commands.Count > 0)
+ {
+ var text = GetQuotaList(quotaStats.Commands);
+ if (!string.IsNullOrWhiteSpace(text))
+ eb.AddField(GetText(strs.commands), text, true);
+ }
+
+ if (quotaStats.Groups.Count > 0)
+ {
+ var text = GetQuotaList(quotaStats.Groups);
+ if (!string.IsNullOrWhiteSpace(text))
+ eb.AddField(GetText(strs.groups), text, true);
+ }
+
+ if (quotaStats.Modules.Count > 0)
+ {
+ var text = GetQuotaList(quotaStats.Modules);
+ if (!string.IsNullOrWhiteSpace(text))
+ eb.AddField(GetText(strs.modules), text, true);
+ }
+ }
+
+
+ try
+ {
+ await ctx.User.EmbedAsync(eb);
+ _ = ctx.OkAsync();
+ }
+ catch
+ {
+ await ReplyErrorLocalizedAsync(strs.cant_dm);
+ }
+ }
+
+ private string GetQuotaList(IReadOnlyDictionary featureQuotaStats)
+ {
+ var text = string.Empty;
+ foreach (var (key, q) in featureQuotaStats)
+ {
+ text += $"\n\t`{key}`\n";
+ if (q.Hourly != default)
+ text += $" {GetEmoji(q.Hourly)} {q.Hourly.Cur}/{q.Hourly.Max} per hour\n";
+ if (q.Daily != default)
+ text += $" {GetEmoji(q.Daily)} {q.Daily.Cur}/{q.Daily.Max} per day\n";
+ if (q.Monthly != default)
+ text += $" {GetEmoji(q.Monthly)} {q.Monthly.Cur}/{q.Monthly.Max} per month\n";
+ }
+
+ return text;
+ }
+
+ private string GetEmoji((uint Cur, uint Max) limit)
+ => limit.Cur < limit.Max
+ ? "✅"
+ : "⚠️";
+}
\ No newline at end of file
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/PatronageService.cs b/src/Nadeko.Bot.Modules.Patronage/Patronage/PatronageService.cs
similarity index 99%
rename from src/Nadeko.Bot.Modules.Utility/Patronage/PatronageService.cs
rename to src/Nadeko.Bot.Modules.Patronage/Patronage/PatronageService.cs
index 761ec55bc..49b3071d9 100644
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/PatronageService.cs
+++ b/src/Nadeko.Bot.Modules.Patronage/Patronage/PatronageService.cs
@@ -6,7 +6,7 @@ using OneOf;
using OneOf.Types;
using CommandInfo = Discord.Commands.CommandInfo;
-namespace NadekoBot.Modules.Utility.Patronage;
+namespace NadekoBot.Modules.Patronage;
///
public sealed class PatronageService
diff --git a/src/Nadeko.Bot.Modules.Permisssions/Nadeko.Bot.Modules.Permisssions.csproj b/src/Nadeko.Bot.Modules.Permisssions/Nadeko.Bot.Modules.Permisssions.csproj
index 3a88c91f3..1cd65638c 100644
--- a/src/Nadeko.Bot.Modules.Permisssions/Nadeko.Bot.Modules.Permisssions.csproj
+++ b/src/Nadeko.Bot.Modules.Permisssions/Nadeko.Bot.Modules.Permisssions.csproj
@@ -7,12 +7,14 @@
-
-
+
+
+
+
-
+
-
+
diff --git a/src/Nadeko.Bot.Modules.Searches/Nadeko.Bot.Modules.Searches.csproj b/src/Nadeko.Bot.Modules.Searches/Nadeko.Bot.Modules.Searches.csproj
index 99c3e8660..1f61198f4 100644
--- a/src/Nadeko.Bot.Modules.Searches/Nadeko.Bot.Modules.Searches.csproj
+++ b/src/Nadeko.Bot.Modules.Searches/Nadeko.Bot.Modules.Searches.csproj
@@ -7,25 +7,27 @@
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
-
+
+
-
+
diff --git a/src/Nadeko.Bot.Modules.Utility/Info/InfoCommands.cs b/src/Nadeko.Bot.Modules.Utility/Info/InfoCommands.cs
index 40c7d1947..5f15947f7 100644
--- a/src/Nadeko.Bot.Modules.Utility/Info/InfoCommands.cs
+++ b/src/Nadeko.Bot.Modules.Utility/Info/InfoCommands.cs
@@ -1,7 +1,6 @@
#nullable disable
-using NadekoBot.Modules.Utility.Patronage;
using System.Text;
-using Nadeko.Common;
+using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Utility;
diff --git a/src/Nadeko.Bot.Modules.Utility/Nadeko.Bot.Modules.Utility.csproj b/src/Nadeko.Bot.Modules.Utility/Nadeko.Bot.Modules.Utility.csproj
index 6a30e8002..807f6287f 100644
--- a/src/Nadeko.Bot.Modules.Utility/Nadeko.Bot.Modules.Utility.csproj
+++ b/src/Nadeko.Bot.Modules.Utility/Nadeko.Bot.Modules.Utility.csproj
@@ -5,21 +5,23 @@
enable
enable
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
+
+
diff --git a/src/Nadeko.Bot.Modules.Utility/Patronage/PatronageCommands.cs b/src/Nadeko.Bot.Modules.Utility/Patronage/PatronageCommands.cs
deleted file mode 100644
index d598d4dfd..000000000
--- a/src/Nadeko.Bot.Modules.Utility/Patronage/PatronageCommands.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-using NadekoBot.Modules.Utility.Patronage;
-
-namespace NadekoBot.Modules.Utility;
-
-public partial class Utility
-{
- [OnlyPublicBot]
- public partial class PatronageCommands : NadekoModule
- {
- private readonly PatronageService _service;
- private readonly PatronageConfig _pConf;
-
- public PatronageCommands(PatronageService service, PatronageConfig pConf)
- {
- _service = service;
- _pConf = pConf;
- }
-
- [Cmd]
- [Priority(2)]
- public Task Patron()
- => InternalPatron(ctx.User);
-
- [Cmd]
- [Priority(0)]
- [OwnerOnly]
- public Task Patron(IUser user)
- => InternalPatron(user);
-
- [Cmd]
- [Priority(0)]
- [OwnerOnly]
- public async Task PatronMessage(PatronTier tierAndHigher, string message)
- {
- _ = ctx.Channel.TriggerTypingAsync();
- var result = await _service.SendMessageToPatronsAsync(tierAndHigher, message);
-
- await ReplyConfirmLocalizedAsync(strs.patron_msg_sent(
- Format.Code(tierAndHigher.ToString()),
- Format.Bold(result.Success.ToString()),
- Format.Bold(result.Failed.ToString())));
- }
-
- // [Cmd]
- // [OwnerOnly]
- // public async Task PatronGift(IUser user, int amount)
- // {
- // // i can't figure out a good way to gift more than one month at the moment.
- //
- // if (amount < 1)
- // return;
- //
- // var patron = _service.GiftPatronAsync(user, amount);
- //
- // var eb = _eb.Create(ctx);
- //
- // await ctx.Channel.EmbedAsync(eb.WithDescription($"Added **{days}** days of Patron benefits to {user.Mention}!")
- // .AddField("Tier", Format.Bold(patron.Tier.ToString()), true)
- // .AddField("Amount", $"**{patron.Amount / 100.0f:N1}$**", true)
- // .AddField("Until", TimestampTag.FromDateTime(patron.ValidThru.AddDays(1))));
- //
- //
- // }
-
- private async Task InternalPatron(IUser user)
- {
- if (!_pConf.Data.IsEnabled)
- {
- await ReplyErrorLocalizedAsync(strs.patron_not_enabled);
- return;
- }
-
- var patron = await _service.GetPatronAsync(user.Id);
- var quotaStats = await _service.GetUserQuotaStatistic(user.Id);
-
- var eb = _eb.Create(ctx)
- .WithAuthor(user)
- .WithTitle(GetText(strs.patron_info))
- .WithOkColor();
-
- if (quotaStats.Commands.Count == 0
- && quotaStats.Groups.Count == 0
- && quotaStats.Modules.Count == 0)
- {
- eb.WithDescription(GetText(strs.no_quota_found));
- }
- else
- {
- eb.AddField(GetText(strs.tier), Format.Bold(patron.Tier.ToFullName()), true)
- .AddField(GetText(strs.pledge), $"**{patron.Amount / 100.0f:N1}$**", true);
-
- if (patron.Tier != PatronTier.None)
- eb.AddField(GetText(strs.expires), patron.ValidThru.AddDays(1).ToShortAndRelativeTimestampTag(), true);
-
- eb.AddField(GetText(strs.quotas), "", false);
-
- if (quotaStats.Commands.Count > 0)
- {
- var text = GetQuotaList(quotaStats.Commands);
- if (!string.IsNullOrWhiteSpace(text))
- eb.AddField(GetText(strs.commands), text, true);
- }
-
- if (quotaStats.Groups.Count > 0)
- {
- var text = GetQuotaList(quotaStats.Groups);
- if (!string.IsNullOrWhiteSpace(text))
- eb.AddField(GetText(strs.groups), text, true);
- }
-
- if (quotaStats.Modules.Count > 0)
- {
- var text = GetQuotaList(quotaStats.Modules);
- if (!string.IsNullOrWhiteSpace(text))
- eb.AddField(GetText(strs.modules), text, true);
- }
- }
-
-
- try
- {
- await ctx.User.EmbedAsync(eb);
- _ = ctx.OkAsync();
- }
- catch
- {
- await ReplyErrorLocalizedAsync(strs.cant_dm);
- }
- }
-
- private string GetQuotaList(IReadOnlyDictionary featureQuotaStats)
- {
- var text = string.Empty;
- foreach (var (key, q) in featureQuotaStats)
- {
- text += $"\n\t`{key}`\n";
- if (q.Hourly != default)
- text += $" {GetEmoji(q.Hourly)} {q.Hourly.Cur}/{q.Hourly.Max} per hour\n";
- if (q.Daily != default)
- text += $" {GetEmoji(q.Daily)} {q.Daily.Cur}/{q.Daily.Max} per day\n";
- if (q.Monthly != default)
- text += $" {GetEmoji(q.Monthly)} {q.Monthly.Cur}/{q.Monthly.Max} per month\n";
- }
-
- return text;
- }
-
- private string GetEmoji((uint Cur, uint Max) limit)
- => limit.Cur < limit.Max
- ? "✅"
- : "⚠️";
- }
-}
\ No newline at end of file
diff --git a/src/Nadeko.Bot.Modules.Utility/VerboseErrorsService.cs b/src/Nadeko.Bot.Modules.Utility/VerboseErrorsService.cs
index 2829995a9..1dc393cf6 100644
--- a/src/Nadeko.Bot.Modules.Utility/VerboseErrorsService.cs
+++ b/src/Nadeko.Bot.Modules.Utility/VerboseErrorsService.cs
@@ -1,6 +1,5 @@
#nullable disable
using NadekoBot.Db;
-using NadekoBot.Modules.Help.Services;
namespace NadekoBot.Modules.Utility.Services;
@@ -9,13 +8,13 @@ public class VerboseErrorsService : INService
private readonly ConcurrentHashSet _guildsDisabled;
private readonly DbService _db;
private readonly CommandHandler _ch;
- private readonly HelpService _hs;
+ private readonly ICommandsUtilityService _hs;
public VerboseErrorsService(
IBot bot,
DbService db,
CommandHandler ch,
- HelpService hs)
+ ICommandsUtilityService hs)
{
_db = db;
_ch = ch;
diff --git a/src/Nadeko.Bot.Modules.Xp/Nadeko.Bot.Modules.Xp.csproj b/src/Nadeko.Bot.Modules.Xp/Nadeko.Bot.Modules.Xp.csproj
index 1233b9592..dc514acc1 100644
--- a/src/Nadeko.Bot.Modules.Xp/Nadeko.Bot.Modules.Xp.csproj
+++ b/src/Nadeko.Bot.Modules.Xp/Nadeko.Bot.Modules.Xp.csproj
@@ -7,12 +7,15 @@
-
-
+
+
-
-
+
+
+
+
+
diff --git a/src/Nadeko.Bot.Modules.Xp/Xp.cs b/src/Nadeko.Bot.Modules.Xp/Xp.cs
index fd861a339..be3e86c34 100644
--- a/src/Nadeko.Bot.Modules.Xp/Xp.cs
+++ b/src/Nadeko.Bot.Modules.Xp/Xp.cs
@@ -1,11 +1,10 @@
#nullable disable warnings
using NadekoBot.Modules.Xp.Services;
using NadekoBot.Services.Database.Models;
-using System.Globalization;
using Nadeko.Bot.Common;
using NadekoBot.Db;
using NadekoBot.Db.Models;
-using NadekoBot.Modules.Utility.Patronage;
+using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Xp;
diff --git a/src/Nadeko.Bot.Modules.Xp/XpConfig.cs b/src/Nadeko.Bot.Modules.Xp/XpConfig.cs
index 54c0a78d3..d6e4e9d6d 100644
--- a/src/Nadeko.Bot.Modules.Xp/XpConfig.cs
+++ b/src/Nadeko.Bot.Modules.Xp/XpConfig.cs
@@ -2,7 +2,7 @@
using Cloneable;
using NadekoBot.Common.Yml;
using NadekoBot.Db.Models;
-using NadekoBot.Modules.Utility.Patronage;
+using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Xp;
diff --git a/src/Nadeko.Bot.Modules.Xp/XpService.cs b/src/Nadeko.Bot.Modules.Xp/XpService.cs
index 9fca4e642..6ebbd766b 100644
--- a/src/Nadeko.Bot.Modules.Xp/XpService.cs
+++ b/src/Nadeko.Bot.Modules.Xp/XpService.cs
@@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db;
using NadekoBot.Db.Models;
-using NadekoBot.Modules.Utility.Patronage;
using NadekoBot.Services.Database.Models;
using Newtonsoft.Json;
using SixLabors.Fonts;
@@ -15,7 +14,7 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.Threading.Channels;
using LinqToDB.EntityFrameworkCore;
-using NadekoBot.Services;
+using NadekoBot.Modules.Patronage;
using Color = SixLabors.ImageSharp.Color;
using Exception = System.Exception;
using Image = SixLabors.ImageSharp.Image;
diff --git a/src/Nadeko.Common/Nadeko.Common.csproj b/src/Nadeko.Common/Nadeko.Common.csproj
index d6c83a15f..9883c5a0b 100644
--- a/src/Nadeko.Common/Nadeko.Common.csproj
+++ b/src/Nadeko.Common/Nadeko.Common.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/src/Nadeko.Medusa/Extensions/EmbedBuilderExtensions.cs b/src/Nadeko.Medusa/Extensions/EmbedBuilderExtensions.cs
index 6506308c4..f6ff9f235 100644
--- a/src/Nadeko.Medusa/Extensions/EmbedBuilderExtensions.cs
+++ b/src/Nadeko.Medusa/Extensions/EmbedBuilderExtensions.cs
@@ -10,5 +10,4 @@ public static class EmbedBuilderExtensions
public static IEmbedBuilder WithErrorColor(this IEmbedBuilder eb)
=> eb.WithColor(EmbedColor.Error);
-
}
\ No newline at end of file
diff --git a/src/Nadeko.Medusa/Nadeko.Medusa.csproj b/src/Nadeko.Medusa/Nadeko.Medusa.csproj
index 8adb79a0f..761571fc5 100644
--- a/src/Nadeko.Medusa/Nadeko.Medusa.csproj
+++ b/src/Nadeko.Medusa/Nadeko.Medusa.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj b/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj
index f5535c759..b9b8dcf8f 100644
--- a/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj
+++ b/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj
@@ -10,11 +10,11 @@
-
+
-
+
diff --git a/src/NadekoBot.Tests/NadekoBot.Tests.csproj b/src/NadekoBot.Tests/NadekoBot.Tests.csproj
index 4f0b4b54d..eadf0eb94 100644
--- a/src/NadekoBot.Tests/NadekoBot.Tests.csproj
+++ b/src/NadekoBot.Tests/NadekoBot.Tests.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/src/NadekoBot/Bot.cs b/src/NadekoBot/Bot.cs
index 21b6072ab..251d85bee 100644
--- a/src/NadekoBot/Bot.cs
+++ b/src/NadekoBot/Bot.cs
@@ -4,8 +4,16 @@ using Microsoft.Extensions.DependencyInjection;
using NadekoBot.Common.Configs;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db;
+using NadekoBot.Modules.Administration;
+using NadekoBot.Modules.Gambling;
+using NadekoBot.Modules.Help;
+using NadekoBot.Modules.Music;
using NadekoBot.Modules.NadekoExpressions;
+using NadekoBot.Modules.Patronage;
+using NadekoBot.Modules.Permissions;
+using NadekoBot.Modules.Searches;
using NadekoBot.Modules.Utility;
+using NadekoBot.Modules.Xp;
using NadekoBot.Services.Database.Models;
using Ninject;
using Ninject.Planning;
@@ -94,6 +102,15 @@ public sealed class Bot : IBot
// modules
typeof(NadekoExpressions).Assembly,
+ typeof(Administration).Assembly,
+ typeof(Gambling).Assembly,
+ typeof(Help).Assembly,
+ typeof(Music).Assembly,
+ typeof(Patronage).Assembly,
+ typeof(Permissions).Assembly,
+ typeof(Searches).Assembly,
+ typeof(Utility).Assembly,
+ typeof(Xp).Assembly,
};
}
@@ -161,7 +178,6 @@ public sealed class Bot : IBot
//initialize Services
Services = kernel;
Services.GetRequiredService().Initialize();
- Services.GetRequiredService();
if (Client.ShardId == 0)
ApplyConfigMigrations();
diff --git a/src/NadekoBot/Medusa/MedusaAssemblyLoadContext.cs b/src/NadekoBot/Medusa/MedusaAssemblyLoadContext.cs
index a6930f04e..2d39fa797 100644
--- a/src/NadekoBot/Medusa/MedusaAssemblyLoadContext.cs
+++ b/src/NadekoBot/Medusa/MedusaAssemblyLoadContext.cs
@@ -17,7 +17,7 @@ public class MedusaAssemblyLoadContext : AssemblyLoadContext
var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null)
{
- Assembly assembly = LoadFromAssemblyPath(assemblyPath);
+ var assembly = LoadFromAssemblyPath(assemblyPath);
LoadDependencies(assembly);
return assembly;
}
diff --git a/src/NadekoBot/Medusa/MedusaIoCKernelModule.cs b/src/NadekoBot/Medusa/MedusaIoCKernelModule.cs
index d9de7e786..e6f3f513e 100644
--- a/src/NadekoBot/Medusa/MedusaIoCKernelModule.cs
+++ b/src/NadekoBot/Medusa/MedusaIoCKernelModule.cs
@@ -6,10 +6,12 @@ using Ninject.Modules;
using Ninject.Planning;
using System.Text.Json;
+namespace Nadeko.Medusa;
+
public sealed class MedusaNinjectModule : NinjectModule
{
public override string Name { get; }
- private volatile bool _isLoaded = false;
+ private volatile bool isLoaded = false;
private readonly Dictionary _types;
public MedusaNinjectModule(Assembly assembly, string name)
@@ -24,7 +26,7 @@ public sealed class MedusaNinjectModule : NinjectModule
public override void Load()
{
- if (_isLoaded)
+ if (isLoaded)
return;
foreach (var (type, data) in _types)
@@ -44,7 +46,7 @@ public sealed class MedusaNinjectModule : NinjectModule
}
}
- _isLoaded = true;
+ isLoaded = true;
}
private Func GetScope(Lifetime lt)
@@ -52,14 +54,15 @@ public sealed class MedusaNinjectModule : NinjectModule
{
Lifetime.Singleton => this,
Lifetime.Transient => null,
+ _ => null,
};
public override void Unload()
{
- if (!_isLoaded)
+ if (!isLoaded)
return;
- var planner = (RemovablePlanner)Kernel.Components.Get();
+ var planner = (RemovablePlanner)Kernel!.Components.Get();
var cache = Kernel.Components.Get();
foreach (var binding in this.Bindings)
{
@@ -90,6 +93,6 @@ public sealed class MedusaNinjectModule : NinjectModule
var clearCacheMethod = updateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public);
clearCacheMethod?.Invoke(null, new object?[] { null });
- _isLoaded = false;
+ isLoaded = false;
}
}
\ No newline at end of file
diff --git a/src/NadekoBot/Medusa/MedusaLoaderService.cs b/src/NadekoBot/Medusa/MedusaLoaderService.cs
index 85aad392b..f2d5a8a63 100644
--- a/src/NadekoBot/Medusa/MedusaLoaderService.cs
+++ b/src/NadekoBot/Medusa/MedusaLoaderService.cs
@@ -16,7 +16,6 @@ namespace Nadeko.Medusa;
public sealed class MedusaLoaderService : IMedusaLoaderService, IReadyExecutor, INService
{
private readonly CommandService _cmdService;
- private readonly IServiceProvider _botServices;
private readonly IBehaviorHandler _behHandler;
private readonly IPubSub _pubSub;
private readonly IMedusaConfigService _medusaConfig;
diff --git a/src/NadekoBot/Medusa/Models/ResolvedMedusa.cs b/src/NadekoBot/Medusa/Models/ResolvedMedusa.cs
index a8f98c19d..0c3e3dd3a 100644
--- a/src/NadekoBot/Medusa/Models/ResolvedMedusa.cs
+++ b/src/NadekoBot/Medusa/Models/ResolvedMedusa.cs
@@ -12,5 +12,5 @@ public sealed record ResolvedMedusa(
IReadOnlyCollection Execs
)
{
- public INinjectModule KernelModule { get; set; }
+ public required INinjectModule KernelModule { get; set; }
}
\ No newline at end of file
diff --git a/src/NadekoBot/Modules/Gambling/CurrencyProvider.cs b/src/NadekoBot/Modules/Gambling/CurrencyProvider.cs
index 6b228a295..cff259571 100644
--- a/src/NadekoBot/Modules/Gambling/CurrencyProvider.cs
+++ b/src/NadekoBot/Modules/Gambling/CurrencyProvider.cs
@@ -4,7 +4,7 @@ using NadekoBot.Modules.Gambling.Services;
namespace NadekoBot.Modules.Gambling;
// todo do we need both currencyprovider and currencyservice
-public sealed class CurrencyProvider : ICurrencyProvider
+public sealed class CurrencyProvider : ICurrencyProvider, INService
{
private readonly GamblingConfigService _cs;
diff --git a/src/NadekoBot/Modules/Medusae/IMedusaeRepositoryService.cs b/src/NadekoBot/Modules/Medusae/IMedusaeRepositoryService.cs
index 769491181..4896a891b 100644
--- a/src/NadekoBot/Modules/Medusae/IMedusaeRepositoryService.cs
+++ b/src/NadekoBot/Modules/Medusae/IMedusaeRepositoryService.cs
@@ -1,4 +1,6 @@
-namespace NadekoBot.Modules;
+using NadekoBot.Modules;
+
+namespace NadekoBot.Modules;
public interface IMedusaeRepositoryService
{
diff --git a/src/NadekoBot/Modules/Medusae/MedusaItem.cs b/src/NadekoBot/Modules/Medusae/MedusaItem.cs
index beffb6cfb..fae4e8076 100644
--- a/src/NadekoBot/Modules/Medusae/MedusaItem.cs
+++ b/src/NadekoBot/Modules/Medusae/MedusaItem.cs
@@ -1,6 +1,8 @@
-public class ModuleItem
+namespace NadekoBot.Modules;
+
+public sealed class ModuleItem
{
- public string Name { get; init; }
- public string Description { get; init; }
- public string Command { get; init; }
+ public required string Name { get; init; }
+ public required string Description { get; init; }
+ public required string Command { get; init; }
}
\ No newline at end of file
diff --git a/src/NadekoBot/Modules/Medusae/ModuleItem.cs b/src/NadekoBot/Modules/Medusae/ModuleItem.cs
deleted file mode 100644
index 0aac10051..000000000
--- a/src/NadekoBot/Modules/Medusae/ModuleItem.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace NadekoBot.Modules;
-
-public class ModuleItem
-{
- public string Name { get; init; }
- public string Description { get; init; }
- public string Command { get; init; }
-}
\ No newline at end of file
diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj
index f59eeb8b1..1207377f8 100644
--- a/src/NadekoBot/NadekoBot.csproj
+++ b/src/NadekoBot/NadekoBot.csproj
@@ -24,94 +24,97 @@
all
True
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
all
True
-
-
-
+
+
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -128,7 +131,7 @@
-
+
diff --git a/src/NadekoBot/PermissionChecker.cs b/src/NadekoBot/PermissionChecker.cs
index f5498d542..9e3612222 100644
--- a/src/NadekoBot/PermissionChecker.cs
+++ b/src/NadekoBot/PermissionChecker.cs
@@ -24,10 +24,12 @@ public sealed class PermissionChecker : IPermissionChecker, INService
IMessageChannel channel,
IUser author,
string module,
- string cmd)
+ string? cmd)
{
+ module = module.ToLowerInvariant();
+ cmd = cmd?.ToLowerInvariant();
// todo add proper string
- if (await _cmdCds.TryBlock(guild, author, cmd))
+ if (cmd is not null && await _cmdCds.TryBlock(guild, author, cmd))
return new Error(new());
try
diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json
index 0e176b734..452b0fe0b 100644
--- a/src/NadekoBot/data/strings/responses/responses.en-US.json
+++ b/src/NadekoBot/data/strings/responses/responses.en-US.json
@@ -989,6 +989,7 @@
"module_description_searches": "Search for jokes, images of animals, anime and manga",
"module_description_xp": "Gain xp based on chat activity, check users' xp cards",
"module_description_medusa": "**Bot Owner only.** Load, unload and handle dynamic modules. Read more [here](https://nadekobot.readthedocs.io/en/latest/medusa/creating-a-medusa/)",
+ "module_description_patronage": "Commands related to supporting the bot",
"module_description_missing": "Description is missing for this module.",
"purge_user_confirm": "Are you sure that you want to purge {0} from the database?",
"expr_import_no_input": "Invalid input. No valid file upload or input text found.",
diff --git a/src/ayu/Ayu.Discord.Voice/Ayu.Discord.Voice.csproj b/src/ayu/Ayu.Discord.Voice/Ayu.Discord.Voice.csproj
index b46dcbdcb..c2b80e137 100644
--- a/src/ayu/Ayu.Discord.Voice/Ayu.Discord.Voice.csproj
+++ b/src/ayu/Ayu.Discord.Voice/Ayu.Discord.Voice.csproj
@@ -7,7 +7,7 @@
1.0.2
-
+