Cleaning up projects, project is building

This commit is contained in:
Kwoth
2023-04-06 10:57:30 +02:00
parent 1f1b01995e
commit 069f8fab9d
82 changed files with 822 additions and 706 deletions

View File

@@ -1,5 +0,0 @@
namespace Nadeko.Bot.Modules.Searches;
public class Class1
{
}

View File

@@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -25,7 +25,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Tests", "src\Nade
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Coordinator", "src\NadekoBot.Coordinator\NadekoBot.Coordinator.csproj", "{AE9B7F8C-81D7-4401-83A3-643B38258374}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Coordinator", "src\NadekoBot.Coordinator\NadekoBot.Coordinator.csproj", "{AE9B7F8C-81D7-4401-83A3-643B38258374}"
EndProject 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 EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.VotesApi", "src\NadekoBot.VotesApi\NadekoBot.VotesApi.csproj", "{3BC82CFE-BEE7-451F-986B-17EDD1570C4F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.VotesApi", "src\NadekoBot.VotesApi\NadekoBot.VotesApi.csproj", "{3BC82CFE-BEE7-451F-986B-17EDD1570C4F}"
EndProject EndProject
@@ -57,6 +57,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Bot.Modules.Administ
EndProject 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}" 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 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 Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{C6359697-25F1-4049-8D73-AC48043CA192}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -210,6 +226,8 @@ Global
{A5B51533-33B6-43AF-9D2D-410613078E96} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} {A5B51533-33B6-43AF-9D2D-410613078E96} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
{08C31FF8-AC47-498D-ACD9-612FA8001F1F} = {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} {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 EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4} SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4}

View File

@@ -1,13 +1,13 @@
// namespace NadekoBot.Common; namespace NadekoBot;
//
// public readonly struct LocStr public readonly struct LocStr
// { {
// public readonly string Key; public readonly string Key;
// public readonly object[] Params; public readonly object[] Params;
//
// public LocStr(string key, params object[] data) public LocStr(string key, params object[] data)
// { {
// Key = key; Key = key;
// Params = data; Params = data;
// } }
// } }

View File

@@ -12,7 +12,7 @@ public sealed class OnlyPublicBotAttribute : PreconditionAttribute
CommandInfo command, CommandInfo command,
IServiceProvider services) IServiceProvider services)
{ {
#if GLOBAL_NADEKO || DEBUG #if GLOBAL_NADEKO
return Task.FromResult(PreconditionResult.FromSuccess()); return Task.FromResult(PreconditionResult.FromSuccess());
#else #else
return Task.FromResult(PreconditionResult.FromError("Only available on the public bot.")); return Task.FromResult(PreconditionResult.FromError("Only available on the public bot."));

View File

@@ -11,5 +11,5 @@ public interface IPermissionChecker
IMessageChannel channel, IMessageChannel channel,
IUser author, IUser author,
string module, string module,
string cmd); string? cmd);
} }

View File

@@ -7,7 +7,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Cloneable" Version="1.3.0" />
<PackageReference Include="Discord.Net" Version="3.104.0" /> <PackageReference Include="Discord.Net" Version="3.104.0" />
</ItemGroup> </ItemGroup>
@@ -30,7 +29,8 @@
<ProjectReference Include="..\Nadeko.Medusa\Nadeko.Medusa.csproj" /> <ProjectReference Include="..\Nadeko.Medusa\Nadeko.Medusa.csproj" />
<ProjectReference Include="..\NadekoBot.Generators\NadekoBot.Generators.csproj" OutputItemType="Analyzer" /> <ProjectReference Include="..\Nadeko.Bot.Generators.Strings\Nadeko.Bot.Generators.Strings.csproj" OutputItemType="Analyzer" />
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,6 +1,5 @@
#nullable disable #nullable disable
using System.Globalization; using System.Globalization;
using NadekoBot.Services;
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming

View File

@@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public readonly struct FeatureLimitKey public readonly struct FeatureLimitKey
{ {

View File

@@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public readonly struct FeatureQuotaStats public readonly struct FeatureQuotaStats
{ {

View File

@@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Patronage;
public interface ISubscriberData public interface ISubscriberData
{ {

View File

@@ -1,7 +1,7 @@
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
using OneOf; using OneOf;
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
/// <summary> /// <summary>
/// Manages patrons and provides access to their data /// Manages patrons and provides access to their data

View File

@@ -1,5 +1,5 @@
#nullable disable #nullable disable
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Patronage;
/// <summary> /// <summary>
/// Services implementing this interface are handling pledges/subscriptions/payments coming /// Services implementing this interface are handling pledges/subscriptions/payments coming

View File

@@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public readonly struct Patron public readonly struct Patron
{ {

View File

@@ -1,7 +1,7 @@
using NadekoBot.Common.Yml; using NadekoBot.Common.Yml;
using Cloneable; using Cloneable;
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
[Cloneable] [Cloneable]
public partial class PatronConfigData : ICloneable<PatronConfigData> public partial class PatronConfigData : ICloneable<PatronConfigData>

View File

@@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public static class PatronExtensions public static class PatronExtensions
{ {

View File

@@ -1,5 +1,5 @@
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public enum PatronTier public enum PatronTier
{ {

View File

@@ -1,6 +1,6 @@
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
/// <summary> /// <summary>
/// Represents information about why the user has triggered a quota limit /// Represents information about why the user has triggered a quota limit

View File

@@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public enum QuotaPer public enum QuotaPer
{ {

View File

@@ -1,5 +1,5 @@
#nullable disable #nullable disable
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Patronage;
public enum SubscriptionChargeStatus public enum SubscriptionChargeStatus
{ {

View File

@@ -1,4 +1,4 @@
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public readonly struct UserQuotaStats public readonly struct UserQuotaStats
{ {

View File

@@ -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<string> GetCommandOptionHelpList(Type opt)
{
var strs = opt.GetProperties()
.Select(x => x.GetCustomAttributes(true).FirstOrDefault(a => a is OptionAttribute))
.Where(x => x is not null)
.Cast<OptionAttribute>()
.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<Attribute> 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<string>();
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<UserPermAttribute>()
.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);
}

View File

@@ -4,7 +4,7 @@ using Nadeko.Common;
using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Administration.Services; namespace NadekoBot.Services;
public class DiscordPermOverrideService : INService, IExecPreCommand, IDiscordPermOverrideService public class DiscordPermOverrideService : INService, IExecPreCommand, IDiscordPermOverrideService
{ {

View File

@@ -9,16 +9,16 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="linq2db.EntityFrameworkCore" Version="7.1.0" /> <PackageReference Include="linq2db.EntityFrameworkCore" Version="7.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.2"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.4">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.1" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.3" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
<PackageReference Include="EFCore.NamingConventions" Version="7.0.2" /> <PackageReference Include="EFCore.NamingConventions" Version="7.0.2" />

View File

@@ -6,8 +6,6 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
namespace Cloneable namespace Cloneable
@@ -23,54 +21,60 @@ namespace Cloneable
private const string CLONE_ATTRIBUTE_STRING = "CloneAttribute"; private const string CLONE_ATTRIBUTE_STRING = "CloneAttribute";
private const string IGNORE_CLONE_ATTRIBUTE_STRING = "IgnoreCloneAttribute"; private const string IGNORE_CLONE_ATTRIBUTE_STRING = "IgnoreCloneAttribute";
private const string CLONEABLE_ATTRIBUTE_TEXT = @"// <AutoGenerated/> private const string CLONEABLE_ATTRIBUTE_TEXT = $$"""
using System; // <AutoGenerated/>
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 = $$"""
} // <AutoGenerated/>
} 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 = @"// <AutoGenerated/> """;
using System;
namespace " + CLONEABLE_NAMESPACE + @" private const string IGNORE_CLONE_PROPERTY_ATTRIBUTE_TEXT = $$"""
{ // <AutoGenerated/>
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] using System;
public sealed class " + CLONE_ATTRIBUTE_STRING + @" : Attribute
{ namespace {{CLONEABLE_NAMESPACE}}
public " + CLONE_ATTRIBUTE_STRING + @"() {
{ [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 = @"// <AutoGenerated/>
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? _cloneableAttribute;
private INamedTypeSymbol? _ignoreCloneAttribute; private INamedTypeSymbol? _ignoreCloneAttribute;

View File

@@ -1,9 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<IncludeBuildOutput>false</IncludeBuildOutput>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
</ItemGroup>
</Project> </Project>

View File

@@ -26,20 +26,20 @@ namespace NadekoBot.Generators
[Generator] [Generator]
public class LocalizedStringsGenerator : ISourceGenerator public class LocalizedStringsGenerator : ISourceGenerator
{ {
private const string LOC_STR_SOURCE = @"namespace NadekoBot // private const string LOC_STR_SOURCE = @"namespace NadekoBot
{ // {
public readonly struct LocStr // public readonly struct LocStr
{ // {
public readonly string Key; // public readonly string Key;
public readonly object[] Params; // public readonly object[] Params;
//
public LocStr(string key, params object[] data) // public LocStr(string key, params object[] data)
{ // {
Key = key; // Key = key;
Params = data; // Params = data;
} // }
} // }
}"; // }";
public void Initialize(GeneratorInitializationContext context) public void Initialize(GeneratorInitializationContext context)
{ {
@@ -106,7 +106,7 @@ namespace NadekoBot.Generators
context.AddSource("strs.g.cs", stringWriter.ToString()); 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<TranslationPair> GetFields(string? dataText) private List<TranslationPair> GetFields(string? dataText)

View File

@@ -6,6 +6,9 @@
<IncludeBuildOutput>false</IncludeBuildOutput> <IncludeBuildOutput>false</IncludeBuildOutput>
<IsRoslynComponent>true</IsRoslynComponent> <IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>NadekoBot.Generators</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,5 +1,5 @@
#nullable disable #nullable disable
using NadekoBot.Modules.Utility.Patronage; using NadekoBot.Modules.Patronage;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using OneOf; using OneOf;
using OneOf.Types; using OneOf.Types;

View File

@@ -3,7 +3,7 @@ using LinqToDB;
using LinqToDB.EntityFrameworkCore; using LinqToDB.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db; using NadekoBot.Db;
using NadekoBot.Modules.Utility.Patronage; using NadekoBot.Modules.Patronage;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using OneOf.Types; using OneOf.Types;
using OneOf; using OneOf;

View File

@@ -18,8 +18,4 @@
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="strs\" />
</ItemGroup>
</Project> </Project>

View File

@@ -3,7 +3,6 @@ using LinqToDB;
using LinqToDB.EntityFrameworkCore; using LinqToDB.EntityFrameworkCore;
using NadekoBot.Db; using NadekoBot.Db;
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
using NadekoBot.Modules.Utility.Patronage;
using NadekoBot.Modules.Gambling.Bank; using NadekoBot.Modules.Gambling.Bank;
using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Common;
using NadekoBot.Modules.Gambling.Services; using NadekoBot.Modules.Gambling.Services;
@@ -15,6 +14,7 @@ using System.Globalization;
using System.Text; using System.Text;
using Nadeko.Econ.Gambling.Rps; using Nadeko.Econ.Gambling.Rps;
using NadekoBot.Common.TypeReaders; using NadekoBot.Common.TypeReaders;
using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Gambling; namespace NadekoBot.Modules.Gambling;

View File

@@ -4,8 +4,8 @@ using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
using NadekoBot.Modules.Games.Common; using NadekoBot.Modules.Games.Common;
using NadekoBot.Modules.Games.Common.ChatterBot; using NadekoBot.Modules.Games.Common.ChatterBot;
using NadekoBot.Modules.Patronage;
using NadekoBot.Modules.Permissions; using NadekoBot.Modules.Permissions;
using NadekoBot.Modules.Utility.Patronage;
namespace NadekoBot.Modules.Games.Services; namespace NadekoBot.Modules.Games.Services;

View File

@@ -7,13 +7,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Econ\Nadeko.Econ.csproj" /> <ProjectReference Include="..\Nadeko.Econ\Nadeko.Econ.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CoreCLR-NCalc" Version="2.2.110" /> <PackageReference Include="CoreCLR-NCalc" Version="2.2.110"/>
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -6,18 +6,20 @@ using NadekoBot.Modules.Help.Services;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using Nadeko.Bot.Common;
using JsonSerializer = System.Text.Json.JsonSerializer; using JsonSerializer = System.Text.Json.JsonSerializer;
namespace NadekoBot.Modules.Help; namespace NadekoBot.Modules.Help;
public partial class Help : NadekoModule<HelpService> public sealed class Help : NadekoModule<HelpService>
{ {
public const string PATREON_URL = "https://patreon.com/nadekobot"; public const string PATREON_URL = "https://patreon.com/nadekobot";
public const string PAYPAL_URL = "https://paypal.me/Kwoth"; public const string PAYPAL_URL = "https://paypal.me/Kwoth";
private readonly ICommandsUtilityService _cus;
private readonly CommandService _cmds; private readonly CommandService _cmds;
private readonly BotConfigService _bss; private readonly BotConfigService _bss;
private readonly GlobalPermissionService _perms; private readonly IPermissionChecker _perms;
private readonly IServiceProvider _services; private readonly IServiceProvider _services;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly IBotStrings _strings; private readonly IBotStrings _strings;
@@ -26,7 +28,8 @@ public partial class Help : NadekoModule<HelpService>
private readonly IMedusaLoaderService _medusae; private readonly IMedusaLoaderService _medusae;
public Help( public Help(
GlobalPermissionService perms, ICommandsUtilityService _cus,
IPermissionChecker perms,
CommandService cmds, CommandService cmds,
BotConfigService bss, BotConfigService bss,
IServiceProvider services, IServiceProvider services,
@@ -34,6 +37,7 @@ public partial class Help : NadekoModule<HelpService>
IBotStrings strings, IBotStrings strings,
IMedusaLoaderService medusae) IMedusaLoaderService medusae)
{ {
this._cus = _cus;
_cmds = cmds; _cmds = cmds;
_bss = bss; _bss = bss;
_perms = perms; _perms = perms;
@@ -53,11 +57,11 @@ public partial class Help : NadekoModule<HelpService>
var clientId = await _lazyClientId.Value; var clientId = await _lazyClientId.Value;
var r = new ReplacementBuilder().WithDefault(Context) var r = new ReplacementBuilder().WithDefault(Context)
.WithOverride("{0}", () => clientId.ToString()) .WithOverride("{0}", () => clientId.ToString())
.WithOverride("{1}", () => prefix) .WithOverride("{1}", () => prefix)
.WithOverride("%prefix%", () => prefix) .WithOverride("%prefix%", () => prefix)
.WithOverride("%bot.prefix%", () => prefix) .WithOverride("%bot.prefix%", () => prefix)
.Build(); .Build();
var text = SmartText.CreateFrom(botSettings.HelpText); var text = SmartText.CreateFrom(botSettings.HelpText);
return r.Replace(text); return r.Replace(text);
@@ -69,10 +73,15 @@ public partial class Help : NadekoModule<HelpService>
if (--page < 0) if (--page < 0)
return; return;
var topLevelModules = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()) var topLevelModules = new List<ModuleInfo>();
.Where(m => !_perms.BlockedModules.Contains(m.Key.Name.ToLowerInvariant())) foreach (var m in _cmds.Modules.GroupBy(x => x.GetTopLevelModule()).Select(x => x.Key))
.Select(x => x.Key) {
.ToList(); var result = await _perms.CheckAsync(ctx.Guild, ctx.Channel, ctx.User,
m.Name, null);
if (result.IsT0)
topLevelModules.Add(m);
}
await ctx.SendPaginatedConfirmAsync(page, await ctx.SendPaginatedConfirmAsync(page,
cur => cur =>
@@ -88,12 +97,12 @@ public partial class Help : NadekoModule<HelpService>
} }
localModules.OrderBy(module => module.Name) localModules.OrderBy(module => module.Name)
.ToList() .ToList()
.ForEach(module => embed.AddField($"{GetModuleEmoji(module.Name)} {module.Name}", .ForEach(module => embed.AddField($"{GetModuleEmoji(module.Name)} {module.Name}",
GetModuleDescription(module.Name) GetModuleDescription(module.Name)
+ "\n" + "\n"
+ Format.Code(GetText(strs.module_footer(prefix, module.Name.ToLowerInvariant()))), + Format.Code(GetText(strs.module_footer(prefix, module.Name.ToLowerInvariant()))),
true)); true));
return embed; return embed;
}, },
@@ -109,11 +118,11 @@ public partial class Help : NadekoModule<HelpService>
if (key.Key == strs.module_description_missing.Key) if (key.Key == strs.module_description_missing.Key)
{ {
var desc = _medusae var desc = _medusae
.GetLoadedMedusae(Culture) .GetLoadedMedusae(Culture)
.FirstOrDefault(m => m.Sneks .FirstOrDefault(m => m.Sneks
.Any(x => x.Name.Equals(moduleName, .Any(x => x.Name.Equals(moduleName,
StringComparison.InvariantCultureIgnoreCase))) StringComparison.InvariantCultureIgnoreCase)))
?.Description; ?.Description;
if (desc is not null) if (desc is not null)
return desc; return desc;
@@ -150,6 +159,8 @@ public partial class Help : NadekoModule<HelpService>
return strs.module_description_xp; return strs.module_description_xp;
case "medusa": case "medusa":
return strs.module_description_medusa; return strs.module_description_medusa;
case "patronage":
return strs.module_description_patronage;
default: default:
return strs.module_description_missing; return strs.module_description_missing;
} }
@@ -182,6 +193,8 @@ public partial class Help : NadekoModule<HelpService>
return "🚓"; return "🚓";
case "xp": case "xp":
return "📝"; return "📝";
case "patronage":
return "💝";
default: default:
return "📖"; return "📖";
} }
@@ -191,7 +204,6 @@ public partial class Help : NadekoModule<HelpService>
[NadekoOptions<CommandsOptions>] [NadekoOptions<CommandsOptions>]
public async Task Commands(string module = null, params string[] args) public async Task Commands(string module = null, params string[] args)
{ {
module = module?.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(module)) if (string.IsNullOrWhiteSpace(module))
{ {
await Modules(); await Modules();
@@ -203,14 +215,22 @@ public partial class Help : NadekoModule<HelpService>
// Find commands for that module // Find commands for that module
// don't show commands which are blocked // don't show commands which are blocked
// order by name // order by name
var cmds = _cmds.Commands var allowed = new List<CommandInfo>();
.Where(c => c.Module.GetTopLevelModule()
.Name.ToUpperInvariant() foreach (var cmd in _cmds.Commands
.StartsWith(module, StringComparison.InvariantCulture)) .Where(c => c.Module.GetTopLevelModule()
.Where(c => !_perms.BlockedCommands.Contains(c.Aliases[0].ToLowerInvariant())) .Name
.OrderBy(c => c.Aliases[0]) .StartsWith(module, StringComparison.InvariantCultureIgnoreCase)))
.DistinctBy(x => x.Aliases[0]) {
.ToList(); 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' // check preconditions for all commands, but only if it's not 'all'
@@ -219,12 +239,12 @@ public partial class Help : NadekoModule<HelpService>
if (opts.View != CommandsOptions.ViewType.All) if (opts.View != CommandsOptions.ViewType.All)
{ {
succ = new((await cmds.Select(async x => succ = new((await cmds.Select(async x =>
{ {
var pre = await x.CheckPreconditionsAsync(Context, _services); var pre = await x.CheckPreconditionsAsync(Context, _services);
return (Cmd: x, Succ: pre.IsSuccess); return (Cmd: x, Succ: pre.IsSuccess);
}) })
.WhenAll()).Where(x => x.Succ) .WhenAll()).Where(x => x.Succ)
.Select(x => x.Cmd)); .Select(x => x.Cmd));
if (opts.View == CommandsOptions.ViewType.Hide) if (opts.View == CommandsOptions.ViewType.Hide)
// if hidden is specified, completely remove these commands from the list // if hidden is specified, completely remove these commands from the list
@@ -232,8 +252,8 @@ public partial class Help : NadekoModule<HelpService>
} }
var cmdsWithGroup = cmds.GroupBy(c => c.Module.GetGroupName()) var cmdsWithGroup = cmds.GroupBy(c => c.Module.GetGroupName())
.OrderBy(x => x.Key == x.First().Module.Name ? int.MaxValue : x.Count()) .OrderBy(x => x.Key == x.First().Module.Name ? int.MaxValue : x.Count())
.ToList(); .ToList();
if (cmdsWithGroup.Count == 0) if (cmdsWithGroup.Count == 0)
{ {
@@ -253,28 +273,28 @@ public partial class Help : NadekoModule<HelpService>
for (var i = 0; i < last; i++) for (var i = 0; i < last; i++)
{ {
var transformed = g.ElementAt(i) var transformed = g.ElementAt(i)
.Select(x => .Select(x =>
{ {
//if cross is specified, and the command doesn't satisfy the requirements, cross it out //if cross is specified, and the command doesn't satisfy the requirements, cross it out
if (opts.View == CommandsOptions.ViewType.Cross) if (opts.View == CommandsOptions.ViewType.Cross)
{ {
return return
$"{(succ.Contains(x) ? "" : "")}{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}"; $"{(succ.Contains(x) ? "" : "")}{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
} }
return return
$"{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}"; $"{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
}); });
if (i == last - 1 && (i + 1) % 2 != 0) if (i == last - 1 && (i + 1) % 2 != 0)
{ {
transformed = transformed.Chunk(2) transformed = transformed.Chunk(2)
.Select(x => .Select(x =>
{ {
if (x.Count() == 1) if (x.Count() == 1)
return $"{x.First()}"; return $"{x.First()}";
return string.Concat(x); return string.Concat(x);
}); });
} }
embed.AddField(g.ElementAt(i).Key, "```css\n" + string.Join("\n", transformed) + "\n```", true); embed.AddField(g.ElementAt(i).Key, "```css\n" + string.Join("\n", transformed) + "\n```", true);
@@ -288,8 +308,8 @@ public partial class Help : NadekoModule<HelpService>
private async Task Group(ModuleInfo group) private async Task Group(ModuleInfo group)
{ {
var eb = _eb.Create(ctx) var eb = _eb.Create(ctx)
.WithTitle(GetText(strs.cmd_group_commands(group.Name))) .WithTitle(GetText(strs.cmd_group_commands(group.Name)))
.WithOkColor(); .WithOkColor();
foreach (var cmd in group.Commands) foreach (var cmd in group.Commands)
{ {
@@ -315,9 +335,9 @@ public partial class Help : NadekoModule<HelpService>
fail = fail.Substring(prefix.Length); fail = fail.Substring(prefix.Length);
var group = _cmds.Modules var group = _cmds.Modules
.SelectMany(x => x.Submodules) .SelectMany(x => x.Submodules)
.Where(x => !string.IsNullOrWhiteSpace(x.Group)) .Where(x => !string.IsNullOrWhiteSpace(x.Group))
.FirstOrDefault(x => x.Group.Equals(fail, StringComparison.InvariantCultureIgnoreCase)); .FirstOrDefault(x => x.Group.Equals(fail, StringComparison.InvariantCultureIgnoreCase));
if (group is not null) if (group is not null)
{ {
@@ -343,8 +363,13 @@ public partial class Help : NadekoModule<HelpService>
if (data == default) if (data == default)
return; return;
await ch.SendAsync(data); await ch.SendAsync(data);
try { await ctx.OkAsync(); } try
catch { } // ignore if bot can't react {
await ctx.OkAsync();
}
catch
{
} // ignore if bot can't react
} }
catch (Exception) catch (Exception)
{ {
@@ -354,7 +379,7 @@ public partial class Help : NadekoModule<HelpService>
return; return;
} }
var embed = _service.GetCommandHelp(com, ctx.Guild); var embed = _cus.GetCommandHelp(com, ctx.Guild);
await channel.EmbedAsync(embed); await channel.EmbedAsync(embed);
} }
@@ -367,29 +392,29 @@ public partial class Help : NadekoModule<HelpService>
// order commands by top level module name // order commands by top level module name
// and make a dictionary of <ModuleName, Array<JsonCommandData>> // and make a dictionary of <ModuleName, Array<JsonCommandData>>
var cmdData = _cmds.Commands.GroupBy(x => x.Module.GetTopLevelModule().Name) var cmdData = _cmds.Commands.GroupBy(x => x.Module.GetTopLevelModule().Name)
.OrderBy(x => x.Key) .OrderBy(x => x.Key)
.ToDictionary(x => x.Key, .ToDictionary(x => x.Key,
x => x.DistinctBy(c => c.Aliases.First()) x => x.DistinctBy(c => c.Aliases.First())
.Select(com => .Select(com =>
{ {
List<string> optHelpStr = null; List<string> optHelpStr = null;
var opt = HelpService.GetNadekoOptionType(com.Attributes);
if (opt is not null)
optHelpStr = HelpService.GetCommandOptionHelpList(opt);
return new CommandJsonObject var opt = CommandsUtilityService.GetNadekoOptionType(com.Attributes);
{ if (opt is not null)
Aliases = com.Aliases.Select(alias => prefix + alias).ToArray(), optHelpStr = CommandsUtilityService.GetCommandOptionHelpList(opt);
Description = com.RealSummary(_strings, _medusae, Culture, prefix),
Usage = com.RealRemarksArr(_strings, _medusae, Culture, prefix), return new CommandJsonObject
Submodule = com.Module.Name, {
Module = com.Module.GetTopLevelModule().Name, Aliases = com.Aliases.Select(alias => prefix + alias).ToArray(),
Options = optHelpStr, Description = com.RealSummary(_strings, _medusae, Culture, prefix),
Requirements = HelpService.GetCommandRequirements(com) Usage = com.RealRemarksArr(_strings, _medusae, Culture, prefix),
}; Submodule = com.Module.Name,
}) Module = com.Module.GetTopLevelModule().Name,
.ToList()); Options = optHelpStr,
Requirements = CommandsUtilityService.GetCommandRequirements(com)
};
})
.ToList());
var readableData = JsonConvert.SerializeObject(cmdData, Formatting.Indented); var readableData = JsonConvert.SerializeObject(cmdData, Formatting.Indented);
var uploadData = JsonConvert.SerializeObject(cmdData, Formatting.None); var uploadData = JsonConvert.SerializeObject(cmdData, Formatting.None);
@@ -512,8 +537,8 @@ public partial class Help : NadekoModule<HelpService>
SelfhostAction)); SelfhostAction));
var eb = _eb.Create(ctx) var eb = _eb.Create(ctx)
.WithOkColor() .WithOkColor()
.WithTitle("Thank you for considering to donate to the NadekoBot project!"); .WithTitle("Thank you for considering to donate to the NadekoBot project!");
eb eb
.WithDescription("NadekoBot relies on donations to keep the servers, services and APIs running.\n" .WithDescription("NadekoBot relies on donations to keep the servers, services and APIs running.\n"

View File

@@ -1,37 +1,15 @@
#nullable disable #nullable disable
using CommandLine;
using Nadeko.Common;
using Nadeko.Medusa;
using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Common.ModuleBehaviors;
namespace NadekoBot.Modules.Help.Services; namespace NadekoBot.Modules.Help.Services;
public class HelpService : IExecNoCommand, INService public class HelpService : IExecNoCommand, INService
{ {
private readonly CommandHandler _ch;
private readonly IBotStrings _strings;
private readonly DiscordPermOverrideService _dpos;
private readonly BotConfigService _bss; private readonly BotConfigService _bss;
private readonly IEmbedBuilderService _eb;
private readonly ILocalization _loc;
private readonly IMedusaLoaderService _medusae;
public HelpService( public HelpService(BotConfigService bss)
CommandHandler ch,
IBotStrings strings,
DiscordPermOverrideService dpos,
BotConfigService bss,
IEmbedBuilderService eb,
ILocalization loc,
IMedusaLoaderService medusae)
{ {
_ch = ch;
_strings = strings;
_dpos = dpos;
_bss = bss; _bss = bss;
_eb = eb;
_loc = loc;
_medusae = medusae;
} }
public Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg) 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 // 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 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; return Task.CompletedTask;
var rep = new ReplacementBuilder().WithOverride("%prefix%", () => _bss.Data.Prefix) var rep = new ReplacementBuilder().WithOverride("%prefix%", () => _bss.Data.Prefix)
.WithOverride("%bot.prefix%", () => _bss.Data.Prefix) .WithOverride("%bot.prefix%", () => _bss.Data.Prefix)
.WithUser(msg.Author) .WithUser(msg.Author)
.Build(); .Build();
var text = SmartText.CreateFrom(settings.DmHelpText); var text = SmartText.CreateFrom(settings.DmHelpText);
text = rep.Replace(text); text = rep.Replace(text);
@@ -60,143 +39,4 @@ public class HelpService : IExecNoCommand, INService
return Task.CompletedTask; 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<Attribute> 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<string> GetCommandOptionHelpList(Type opt)
{
var strs = opt.GetProperties()
.Select(x => x.GetCustomAttributes(true).FirstOrDefault(a => a is OptionAttribute))
.Where(x => x is not null)
.Cast<OptionAttribute>()
.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<string>();
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<UserPermAttribute>()
.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);
}

View File

@@ -7,11 +7,13 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AWSSDK.S3" Version="3.7.101.58" /> <PackageReference Include="AWSSDK.S3" Version="3.7.101.58"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -7,13 +7,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ayu\Ayu.Discord.Voice\Ayu.Discord.Voice.csproj" /> <ProjectReference Include="..\ayu\Ayu.Discord.Voice\Ayu.Discord.Voice.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Searches\Nadeko.Bot.Modules.Searches.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Modules.Searches\Nadeko.Bot.Modules.Searches.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -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;

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Gambling\Nadeko.Bot.Modules.Gambling.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup>
</Project>

View File

@@ -1,6 +1,6 @@
using NadekoBot.Common.Configs; using NadekoBot.Common.Configs;
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public class PatronageConfig : ConfigServiceBase<PatronConfigData> public class PatronageConfig : ConfigServiceBase<PatronConfigData>
{ {
@@ -8,7 +8,7 @@ public class PatronageConfig : ConfigServiceBase<PatronConfigData>
=> "patron"; => "patron";
private static readonly TypedKey<PatronConfigData> _changeKey private static readonly TypedKey<PatronConfigData> _changeKey
= new TypedKey<PatronConfigData>("config.patron.updated"); = new("config.patron.updated");
private const string FILE_PATH = "data/patron.yml"; private const string FILE_PATH = "data/patron.yml";

View File

@@ -1,20 +1,18 @@
#nullable disable #nullable disable
using LinqToDB; using LinqToDB;
using LinqToDB.EntityFrameworkCore; using LinqToDB.EntityFrameworkCore;
using NadekoBot.Modules.Utility.Patronage;
using NadekoBot.Modules.Gambling.Bank;
using NadekoBot.Modules.Gambling.Services; using NadekoBot.Modules.Gambling.Services;
using NadekoBot.Modules.Patronage;
using NadekoBot.Services.Currency; using NadekoBot.Services.Currency;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Utility;
public class CurrencyRewardService : INService, IDisposable public sealed class CurrencyRewardService : INService, IDisposable
{ {
private readonly ICurrencyService _cs; private readonly ICurrencyService _cs;
private readonly IPatronageService _ps; private readonly IPatronageService _ps;
private readonly DbService _db; private readonly DbService _db;
private readonly IBankService _bs;
private readonly IEmbedBuilderService _eb; private readonly IEmbedBuilderService _eb;
private readonly GamblingConfigService _config; private readonly GamblingConfigService _config;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
@@ -23,7 +21,6 @@ public class CurrencyRewardService : INService, IDisposable
ICurrencyService cs, ICurrencyService cs,
IPatronageService ps, IPatronageService ps,
DbService db, DbService db,
IBankService bs,
IEmbedBuilderService eb, IEmbedBuilderService eb,
GamblingConfigService config, GamblingConfigService config,
DiscordSocketClient client) DiscordSocketClient client)
@@ -31,7 +28,6 @@ public class CurrencyRewardService : INService, IDisposable
_cs = cs; _cs = cs;
_ps = ps; _ps = ps;
_db = db; _db = db;
_bs = bs;
_eb = eb; _eb = eb;
_config = config; _config = config;
_client = client; _client = client;

View File

@@ -1,6 +1,6 @@
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
public readonly struct InsufficientTier public readonly struct InsufficientTier
{ {

View File

@@ -1,11 +1,10 @@
#nullable disable #nullable disable
using NadekoBot.Modules.Utility.Common.Patreon;
using OneOf; using OneOf;
using OneOf.Types; using OneOf.Types;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text.Json; using System.Text.Json;
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Patronage;
public class PatreonClient : IDisposable public class PatreonClient : IDisposable
{ {

View File

@@ -1,5 +1,5 @@
#nullable disable #nullable disable
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Patronage;
public readonly struct PatreonCredentials public readonly struct PatreonCredentials
{ {

View File

@@ -1,7 +1,7 @@
#nullable disable #nullable disable
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace NadekoBot.Modules.Utility.Common.Patreon; namespace NadekoBot.Modules.Patronage;
public sealed class Attributes public sealed class Attributes
{ {

View File

@@ -1,5 +1,5 @@
#nullable disable #nullable disable
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Patronage;
public sealed class PatreonMemberData : ISubscriberData public sealed class PatreonMemberData : ISubscriberData
{ {

View File

@@ -1,7 +1,7 @@
#nullable disable #nullable disable
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Patronage;
public sealed class PatreonRefreshData public sealed class PatreonRefreshData
{ {

View File

@@ -1,15 +1,13 @@
#nullable disable #nullable disable
using NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Utility;
/// <summary> /// <summary>
/// Service tasked with handling pledges on patreon /// Service tasked with handling pledges on patreon
/// </summary> /// </summary>
public sealed class PatreonSubscriptionHandler : ISubscriptionHandler, INService public sealed class PatreonSubscriptionHandler : ISubscriptionHandler, INService
{ {
private readonly IBotCredsProvider _credsProvider; private readonly IBotCredsProvider _credsProvider;
private readonly PatreonClient _patreonClient; private readonly PatreonClient _patreonClient;
public PatreonSubscriptionHandler(IBotCredsProvider credsProvider) public PatreonSubscriptionHandler(IBotCredsProvider credsProvider)
{ {

View File

@@ -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<string, FeatureQuotaStats> 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
? "✅"
: "⚠️";
}

View File

@@ -6,7 +6,7 @@ using OneOf;
using OneOf.Types; using OneOf.Types;
using CommandInfo = Discord.Commands.CommandInfo; using CommandInfo = Discord.Commands.CommandInfo;
namespace NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Patronage;
/// <inheritdoc cref="IPatronageService"/> /// <inheritdoc cref="IPatronageService"/>
public sealed class PatronageService public sealed class PatronageService

View File

@@ -7,12 +7,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Db\Nadeko.Bot.Db.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Db\Nadeko.Bot.Db.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Discord.Net.Core" Version="3.104.0" /> <PackageReference Include="Discord.Net.Core" Version="3.104.0"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -7,25 +7,27 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Db\Nadeko.Bot.Db.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Db\Nadeko.Bot.Db.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AngleSharp" Version="1.0.1" /> <PackageReference Include="AngleSharp" Version="1.0.1"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0"/>
<PackageReference Include="CsvHelper" Version="30.0.1" /> <PackageReference Include="CsvHelper" Version="30.0.1"/>
<PackageReference Include="MorseCode.ITask" Version="2.0.3" /> <PackageReference Include="MorseCode.ITask" Version="2.0.3"/>
<!-- Stream Notifications --> <!-- Stream Notifications -->
<PackageReference Include="TwitchLib.Api" Version="3.4.1" /> <PackageReference Include="TwitchLib.Api" Version="3.4.1"/>
<!-- Feeds, ... ? --> <!-- Feeds, ... ? -->
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.4" /> <PackageReference Include="CodeHollow.FeedReader" Version="1.2.6"/>
<!-- .hs, nothing else --> <!-- .hs, nothing else -->
<PackageReference Include="Html2Markdown" Version="5.1.0.703" /> <PackageReference Include="Html2Markdown" Version="5.1.0.703"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,7 +1,6 @@
#nullable disable #nullable disable
using NadekoBot.Modules.Utility.Patronage;
using System.Text; using System.Text;
using Nadeko.Common; using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Utility; namespace NadekoBot.Modules.Utility;

View File

@@ -5,21 +5,23 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0"/>
<!-- .eval --> <!-- .eval -->
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.4.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.5.0"/>
<!-- .calc --> <!-- .calc -->
<PackageReference Include="CoreCLR-NCalc" Version="2.2.110" /> <PackageReference Include="CoreCLR-NCalc" Version="2.2.110"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Searches\Nadeko.Bot.Modules.Searches.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Modules.Searches\Nadeko.Bot.Modules.Searches.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -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<string, FeatureQuotaStats> 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
? "✅"
: "⚠️";
}
}

View File

@@ -1,6 +1,5 @@
#nullable disable #nullable disable
using NadekoBot.Db; using NadekoBot.Db;
using NadekoBot.Modules.Help.Services;
namespace NadekoBot.Modules.Utility.Services; namespace NadekoBot.Modules.Utility.Services;
@@ -9,13 +8,13 @@ public class VerboseErrorsService : INService
private readonly ConcurrentHashSet<ulong> _guildsDisabled; private readonly ConcurrentHashSet<ulong> _guildsDisabled;
private readonly DbService _db; private readonly DbService _db;
private readonly CommandHandler _ch; private readonly CommandHandler _ch;
private readonly HelpService _hs; private readonly ICommandsUtilityService _hs;
public VerboseErrorsService( public VerboseErrorsService(
IBot bot, IBot bot,
DbService db, DbService db,
CommandHandler ch, CommandHandler ch,
HelpService hs) ICommandsUtilityService hs)
{ {
_db = db; _db = db;
_ch = ch; _ch = ch;

View File

@@ -7,12 +7,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="linq2db.EntityFrameworkCore" Version="7.1.0" /> <PackageReference Include="linq2db.EntityFrameworkCore" Version="7.3.0"/>
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Db\Nadeko.Bot.Db.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Db\Nadeko.Bot.Db.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,11 +1,10 @@
#nullable disable warnings #nullable disable warnings
using NadekoBot.Modules.Xp.Services; using NadekoBot.Modules.Xp.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Globalization;
using Nadeko.Bot.Common; using Nadeko.Bot.Common;
using NadekoBot.Db; using NadekoBot.Db;
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
using NadekoBot.Modules.Utility.Patronage; using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Xp; namespace NadekoBot.Modules.Xp;

View File

@@ -2,7 +2,7 @@
using Cloneable; using Cloneable;
using NadekoBot.Common.Yml; using NadekoBot.Common.Yml;
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
using NadekoBot.Modules.Utility.Patronage; using NadekoBot.Modules.Patronage;
namespace NadekoBot.Modules.Xp; namespace NadekoBot.Modules.Xp;

View File

@@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db; using NadekoBot.Db;
using NadekoBot.Db.Models; using NadekoBot.Db.Models;
using NadekoBot.Modules.Utility.Patronage;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using SixLabors.Fonts; using SixLabors.Fonts;
@@ -15,7 +14,7 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using System.Threading.Channels; using System.Threading.Channels;
using LinqToDB.EntityFrameworkCore; using LinqToDB.EntityFrameworkCore;
using NadekoBot.Services; using NadekoBot.Modules.Patronage;
using Color = SixLabors.ImageSharp.Color; using Color = SixLabors.ImageSharp.Color;
using Exception = System.Exception; using Exception = System.Exception;
using Image = SixLabors.ImageSharp.Image; using Image = SixLabors.ImageSharp.Image;

View File

@@ -10,7 +10,7 @@
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageReference Include="NonBlocking" Version="2.1.1" /> <PackageReference Include="NonBlocking" Version="2.1.1" />
<PackageReference Include="OneOf" Version="3.0.223" /> <PackageReference Include="OneOf" Version="3.0.243" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
</ItemGroup> </ItemGroup>

View File

@@ -10,5 +10,4 @@ public static class EmbedBuilderExtensions
public static IEmbedBuilder WithErrorColor(this IEmbedBuilder eb) public static IEmbedBuilder WithErrorColor(this IEmbedBuilder eb)
=> eb.WithColor(EmbedColor.Error); => eb.WithColor(EmbedColor.Error);
} }

View File

@@ -11,7 +11,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Discord.Net.Core" Version="3.104.0" /> <PackageReference Include="Discord.Net.Core" Version="3.104.0" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="YamlDotNet" Version="12.3.1" /> <PackageReference Include="YamlDotNet" Version="13.0.2" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition=" '$(Version)' == '' "> <PropertyGroup Condition=" '$(Version)' == '' ">

View File

@@ -10,11 +10,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.51.0" /> <PackageReference Include="Grpc.AspNetCore" Version="2.52.0" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="YamlDotNet" Version="12.3.1" /> <PackageReference Include="YamlDotNet" Version="13.0.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -7,8 +7,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="NUnit" Version="3.13.3" /> <PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" /> <PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,8 +4,16 @@ using Microsoft.Extensions.DependencyInjection;
using NadekoBot.Common.Configs; using NadekoBot.Common.Configs;
using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db; 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.NadekoExpressions;
using NadekoBot.Modules.Patronage;
using NadekoBot.Modules.Permissions;
using NadekoBot.Modules.Searches;
using NadekoBot.Modules.Utility; using NadekoBot.Modules.Utility;
using NadekoBot.Modules.Xp;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using Ninject; using Ninject;
using Ninject.Planning; using Ninject.Planning;
@@ -94,6 +102,15 @@ public sealed class Bot : IBot
// modules // modules
typeof(NadekoExpressions).Assembly, 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 //initialize Services
Services = kernel; Services = kernel;
Services.GetRequiredService<IBehaviorHandler>().Initialize(); Services.GetRequiredService<IBehaviorHandler>().Initialize();
Services.GetRequiredService<CurrencyRewardService>();
if (Client.ShardId == 0) if (Client.ShardId == 0)
ApplyConfigMigrations(); ApplyConfigMigrations();

View File

@@ -17,7 +17,7 @@ public class MedusaAssemblyLoadContext : AssemblyLoadContext
var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null) if (assemblyPath != null)
{ {
Assembly assembly = LoadFromAssemblyPath(assemblyPath); var assembly = LoadFromAssemblyPath(assemblyPath);
LoadDependencies(assembly); LoadDependencies(assembly);
return assembly; return assembly;
} }

View File

@@ -6,10 +6,12 @@ using Ninject.Modules;
using Ninject.Planning; using Ninject.Planning;
using System.Text.Json; using System.Text.Json;
namespace Nadeko.Medusa;
public sealed class MedusaNinjectModule : NinjectModule public sealed class MedusaNinjectModule : NinjectModule
{ {
public override string Name { get; } public override string Name { get; }
private volatile bool _isLoaded = false; private volatile bool isLoaded = false;
private readonly Dictionary<Type, Type[]> _types; private readonly Dictionary<Type, Type[]> _types;
public MedusaNinjectModule(Assembly assembly, string name) public MedusaNinjectModule(Assembly assembly, string name)
@@ -24,7 +26,7 @@ public sealed class MedusaNinjectModule : NinjectModule
public override void Load() public override void Load()
{ {
if (_isLoaded) if (isLoaded)
return; return;
foreach (var (type, data) in _types) foreach (var (type, data) in _types)
@@ -44,7 +46,7 @@ public sealed class MedusaNinjectModule : NinjectModule
} }
} }
_isLoaded = true; isLoaded = true;
} }
private Func<IContext, object?> GetScope(Lifetime lt) private Func<IContext, object?> GetScope(Lifetime lt)
@@ -52,14 +54,15 @@ public sealed class MedusaNinjectModule : NinjectModule
{ {
Lifetime.Singleton => this, Lifetime.Singleton => this,
Lifetime.Transient => null, Lifetime.Transient => null,
_ => null,
}; };
public override void Unload() public override void Unload()
{ {
if (!_isLoaded) if (!isLoaded)
return; return;
var planner = (RemovablePlanner)Kernel.Components.Get<IPlanner>(); var planner = (RemovablePlanner)Kernel!.Components.Get<IPlanner>();
var cache = Kernel.Components.Get<ICache>(); var cache = Kernel.Components.Get<ICache>();
foreach (var binding in this.Bindings) foreach (var binding in this.Bindings)
{ {
@@ -90,6 +93,6 @@ public sealed class MedusaNinjectModule : NinjectModule
var clearCacheMethod = updateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public); var clearCacheMethod = updateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public);
clearCacheMethod?.Invoke(null, new object?[] { null }); clearCacheMethod?.Invoke(null, new object?[] { null });
_isLoaded = false; isLoaded = false;
} }
} }

View File

@@ -16,7 +16,6 @@ namespace Nadeko.Medusa;
public sealed class MedusaLoaderService : IMedusaLoaderService, IReadyExecutor, INService public sealed class MedusaLoaderService : IMedusaLoaderService, IReadyExecutor, INService
{ {
private readonly CommandService _cmdService; private readonly CommandService _cmdService;
private readonly IServiceProvider _botServices;
private readonly IBehaviorHandler _behHandler; private readonly IBehaviorHandler _behHandler;
private readonly IPubSub _pubSub; private readonly IPubSub _pubSub;
private readonly IMedusaConfigService _medusaConfig; private readonly IMedusaConfigService _medusaConfig;

View File

@@ -12,5 +12,5 @@ public sealed record ResolvedMedusa(
IReadOnlyCollection<ICustomBehavior> Execs IReadOnlyCollection<ICustomBehavior> Execs
) )
{ {
public INinjectModule KernelModule { get; set; } public required INinjectModule KernelModule { get; set; }
} }

View File

@@ -4,7 +4,7 @@ using NadekoBot.Modules.Gambling.Services;
namespace NadekoBot.Modules.Gambling; namespace NadekoBot.Modules.Gambling;
// todo do we need both currencyprovider and currencyservice // todo do we need both currencyprovider and currencyservice
public sealed class CurrencyProvider : ICurrencyProvider public sealed class CurrencyProvider : ICurrencyProvider, INService
{ {
private readonly GamblingConfigService _cs; private readonly GamblingConfigService _cs;

View File

@@ -1,4 +1,6 @@
namespace NadekoBot.Modules; using NadekoBot.Modules;
namespace NadekoBot.Modules;
public interface IMedusaeRepositoryService public interface IMedusaeRepositoryService
{ {

View File

@@ -1,6 +1,8 @@
public class ModuleItem namespace NadekoBot.Modules;
public sealed class ModuleItem
{ {
public string Name { get; init; } public required string Name { get; init; }
public string Description { get; init; } public required string Description { get; init; }
public string Command { get; init; } public required string Command { get; init; }
} }

View File

@@ -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; }
}

View File

@@ -24,94 +24,97 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<Publish>True</Publish> <Publish>True</Publish>
</PackageReference> </PackageReference>
<PackageReference Include="AWSSDK.S3" Version="3.7.101.58" /> <PackageReference Include="AWSSDK.S3" Version="3.7.101.58"/>
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.4" /> <PackageReference Include="CodeHollow.FeedReader" Version="1.2.6"/>
<PackageReference Include="CommandLineParser" Version="2.9.1" /> <PackageReference Include="CommandLineParser" Version="2.9.1"/>
<PackageReference Include="CoreCLR-NCalc" Version="2.2.110" /> <PackageReference Include="CoreCLR-NCalc" Version="2.2.110"/>
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138" /> <PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138"/>
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.58.0.2874" /> <PackageReference Include="Google.Apis.YouTube.v3" Version="1.60.0.2945"/>
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.49.0.2084" /> <PackageReference Include="Google.Apis.Customsearch.v1" Version="1.49.0.2084"/>
<PackageReference Include="Google.Protobuf" Version="3.21.12" /> <PackageReference Include="Google.Protobuf" Version="3.22.1"/>
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.51.0" /> <PackageReference Include="Grpc.Net.ClientFactory" Version="2.52.0"/>
<PackageReference Include="Grpc.Tools" Version="2.51.0"> <PackageReference Include="Grpc.Tools" Version="2.53.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Html2Markdown" Version="5.1.0.703" /> <PackageReference Include="Html2Markdown" Version="5.1.0.703"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.4.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.5.0"/>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0"/>
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0"/>
<PackageReference Include="MorseCode.ITask" Version="2.0.3"/>
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.0.0"/>
<PackageReference Include="MorseCode.ITask" Version="2.0.3" />
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="2.2.0" />
<!-- DI --> <!-- DI -->
<PackageReference Include="Ninject" Version="3.3.6" /> <PackageReference Include="Ninject" Version="3.3.6"/>
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" /> <PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0"/>
<!-- <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />--> <!-- <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />-->
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0"/>
<!-- <PackageReference Include="Scrutor" Version="4.2.0" />--> <!-- <PackageReference Include="Scrutor" Version="4.2.0" />-->
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0"/>
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" /> <PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageReference Include="NonBlocking" Version="2.1.1" /> <PackageReference Include="NonBlocking" Version="2.1.1"/>
<PackageReference Include="OneOf" Version="3.0.223" /> <PackageReference Include="OneOf" Version="3.0.243"/>
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0"/>
<PackageReference Include="Serilog.Sinks.Seq" Version="5.2.2" /> <PackageReference Include="Serilog.Sinks.Seq" Version="5.2.2"/>
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17" /> <PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17"/>
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" /> <PackageReference Include="SixLabors.ImageSharp" Version="2.1.3"/>
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14"/>
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" /> <PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009"/>
<PackageReference Include="StackExchange.Redis" Version="2.6.90" /> <PackageReference Include="StackExchange.Redis" Version="2.6.104"/>
<PackageReference Include="YamlDotNet" Version="12.3.1" /> <PackageReference Include="YamlDotNet" Version="13.0.2"/>
<PackageReference Include="Humanizer" Version="2.14.1"> <PackageReference Include="Humanizer" Version="2.14.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<Publish>True</Publish> <Publish>True</Publish>
</PackageReference> </PackageReference>
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" /> <PackageReference Include="JetBrains.Annotations" Version="2022.3.1"/>
<!-- Db-related packages --> <!-- Db-related packages -->
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.4"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.2"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.4">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="linq2db.EntityFrameworkCore" Version="7.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
<PackageReference Include="EFCore.NamingConventions" Version="7.0.2" /> <PackageReference Include="linq2db.EntityFrameworkCore" Version="7.3.0"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4"/>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.3"/>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0"/>
<PackageReference Include="EFCore.NamingConventions" Version="7.0.2"/>
<!-- Used by stream notifications --> <!-- Used by stream notifications -->
<PackageReference Include="TwitchLib.Api" Version="3.4.1" /> <PackageReference Include="TwitchLib.Api" Version="3.4.1"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ayu\Ayu.Discord.Voice\Ayu.Discord.Voice.csproj" /> <ProjectReference Include="..\ayu\Ayu.Discord.Voice\Ayu.Discord.Voice.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Music\Nadeko.Bot.Modules.Music.csproj" /> <ProjectReference Include="..\Nadeko.Econ\Nadeko.Econ.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Permisssions\Nadeko.Bot.Modules.Permisssions.csproj" /> <ProjectReference Include="..\Nadeko.Medusa\Nadeko.Medusa.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Utility\Nadeko.Bot.Modules.Utility.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj"/>
<!-- <ProjectReference Include="..\Nadeko.Common\Nadeko.Common.csproj" />--> <ProjectReference Include="..\Nadeko.Bot.Modules.Administration\Nadeko.Bot.Modules.Administration.csproj"/>
<ProjectReference Include="..\Nadeko.Econ\Nadeko.Econ.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Modules.Help\Nadeko.Bot.Modules.Help.csproj"/>
<ProjectReference Include="..\Nadeko.Medusa\Nadeko.Medusa.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Modules.Music\Nadeko.Bot.Modules.Music.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Common\Nadeko.Bot.Common.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Modules.Patronage\Nadeko.Bot.Modules.Patronage.csproj"/>
<ProjectReference Include="..\NadekoBot.Generators\NadekoBot.Generators.csproj" OutputItemType="Analyzer" /> <ProjectReference Include="..\Nadeko.Bot.Modules.Permisssions\Nadeko.Bot.Modules.Permisssions.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Utility\Nadeko.Bot.Modules.Utility.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Expresssions\Nadeko.Bot.Modules.Expresssions.csproj" /> <ProjectReference Include="..\Nadeko.Bot.Modules.Xp\Nadeko.Bot.Modules.Xp.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Gambling\Nadeko.Bot.Modules.Gambling.csproj" /> <!-- <ProjectReference Include="..\Nadeko.Common\Nadeko.Common.csproj" />-->
<ProjectReference Include="..\Nadeko.Bot.Modules.Expresssions\Nadeko.Bot.Modules.Expresssions.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Modules.Gambling\Nadeko.Bot.Modules.Gambling.csproj"/>
<ProjectReference Include="..\Nadeko.Bot.Generators.Cloneable\Nadeko.Bot.Generators.Cloneable.csproj" OutputItemType="Analyzer"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Protobuf Include="..\NadekoBot.Coordinator\Protos\coordinator.proto" GrpcServices="Client"> <Protobuf Include="..\NadekoBot.Coordinator\Protos\coordinator.proto" GrpcServices="Client">
@@ -128,7 +131,7 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Common\TypeReaders\" /> <Folder Include="Common\TypeReaders\"/>
</ItemGroup> </ItemGroup>
<PropertyGroup Condition=" '$(Version)' == '' "> <PropertyGroup Condition=" '$(Version)' == '' ">

View File

@@ -24,10 +24,12 @@ public sealed class PermissionChecker : IPermissionChecker, INService
IMessageChannel channel, IMessageChannel channel,
IUser author, IUser author,
string module, string module,
string cmd) string? cmd)
{ {
module = module.ToLowerInvariant();
cmd = cmd?.ToLowerInvariant();
// todo add proper string // 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<LocStr>(new()); return new Error<LocStr>(new());
try try

View File

@@ -989,6 +989,7 @@
"module_description_searches": "Search for jokes, images of animals, anime and manga", "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_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_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.", "module_description_missing": "Description is missing for this module.",
"purge_user_confirm": "Are you sure that you want to purge {0} from the database?", "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.", "expr_import_no_input": "Invalid input. No valid file upload or input text found.",

View File

@@ -7,7 +7,7 @@
<Version>1.0.2</Version> <Version>1.0.2</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="System.Threading.Channels" Version="7.0.0" /> <PackageReference Include="System.Threading.Channels" Version="7.0.0" />
</ItemGroup> </ItemGroup>