mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2024-10-02 20:13:13 +00:00
- strings rework continued
- added config/aliases.yml which contains mapping of command method names to command names + aliases - first alias is treated as a command name, while the following ones are treated as aliases - command strings' keys aren now using command name as keys (first entry in config/aliases.yml), and not command method name - command strings are now .yml files in config/strings/commands/commands.LANG.yml (actual localization is not yet implemented, but is trivial to add) - removed obsolete command strings and aliases for commands which no longer exist and added tests to check for them - added tests which will make sure commands.yml and aliases.yml files have entries for all commands - some commands are slightly renamed to be more consistent with other commands in their group/bot - removed (commented out) leftover yttrackmodule which had no commands
This commit is contained in:
parent
eca10671db
commit
188d957057
33 changed files with 3569 additions and 163 deletions
127
Nadeko.Tests/BotStringsTests.cs
Normal file
127
Nadeko.Tests/BotStringsTests.cs
Normal file
|
@ -0,0 +1,127 @@
|
|||
using NUnit.Framework;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using AngleSharp.Common;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using NadekoBot.Core.Services;
|
||||
using NadekoBot.Modules;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Nadeko.Tests
|
||||
{
|
||||
public class CommandStringsTests
|
||||
{
|
||||
[Test]
|
||||
public void AllCommandNamesHaveStrings()
|
||||
{
|
||||
var stringsSource = new LocalFileStringsSource(
|
||||
"../../../../src/NadekoBot/config/strings/responses",
|
||||
"../../../../src/NadekoBot/config/strings/commands");
|
||||
var strings = new LocalBotStringsProvider(stringsSource);
|
||||
|
||||
var culture = new CultureInfo("en-US");
|
||||
|
||||
var isSuccess = true;
|
||||
foreach (var entry in CommandNameLoadHelper.LoadCommandNames("../../../../src/NadekoBot/config/aliases.yml"))
|
||||
{
|
||||
var commandName = entry.Value[0];
|
||||
|
||||
var cmdStrings = strings.GetCommandStrings(culture.Name, commandName);
|
||||
if (cmdStrings is null)
|
||||
{
|
||||
isSuccess = false;
|
||||
TestContext.Out.WriteLine($"{commandName} doesn't exist in commands.en-US.yml");
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(isSuccess);
|
||||
}
|
||||
|
||||
private static string[] GetCommandMethodNames()
|
||||
=> typeof(NadekoBot.NadekoBot).Assembly
|
||||
.GetExportedTypes()
|
||||
.Where(type => type.IsClass && !type.IsAbstract)
|
||||
.Where(type => typeof(NadekoTopLevelModule).IsAssignableFrom(type) // if its a top level module
|
||||
|| !(type.GetCustomAttribute<GroupAttribute>(true) is null)) // or a submodule
|
||||
.SelectMany(x => x.GetMethods().Where(mi => mi.CustomAttributes.Any(ca => ca.AttributeType == typeof(NadekoCommandAttribute))))
|
||||
.Select(x => x.Name.ToLowerInvariant())
|
||||
.ToArray();
|
||||
|
||||
[Test]
|
||||
public void AllCommandMethodsHaveNames()
|
||||
{
|
||||
var allAliases = CommandNameLoadHelper.LoadCommandNames(
|
||||
"../../../../src/NadekoBot/config/aliases.yml");
|
||||
|
||||
var methodNames = GetCommandMethodNames();
|
||||
|
||||
var isSuccess = true;
|
||||
foreach (var methodName in methodNames)
|
||||
{
|
||||
if (!allAliases.TryGetValue(methodName, out var _))
|
||||
{
|
||||
TestContext.Error.WriteLine($"{methodName} is missing an alias.");
|
||||
isSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(isSuccess);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NoObsoleteAliases()
|
||||
{
|
||||
var allAliases = CommandNameLoadHelper.LoadCommandNames(
|
||||
"../../../../src/NadekoBot/config/aliases.yml");
|
||||
|
||||
var methodNames = GetCommandMethodNames()
|
||||
.ToHashSet();
|
||||
|
||||
var isSuccess = true;
|
||||
|
||||
foreach (var item in allAliases)
|
||||
{
|
||||
var methodName = item.Key;
|
||||
|
||||
if (!methodNames.Contains(methodName))
|
||||
{
|
||||
TestContext.WriteLine($"'{methodName}' from aliases.yml doesn't have a matching command method.");
|
||||
isSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(isSuccess);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NoObsoleteCommandStrings()
|
||||
{
|
||||
var stringsSource = new LocalFileStringsSource(
|
||||
"../../../../src/NadekoBot/config/strings/responses",
|
||||
"../../../../src/NadekoBot/config/strings/commands");
|
||||
|
||||
var culture = new CultureInfo("en-US");
|
||||
|
||||
var isSuccess = true;
|
||||
var allCommandNames = CommandNameLoadHelper.LoadCommandNames("../../../../src/NadekoBot/config/aliases.yml");
|
||||
var enUsCommandNames = allCommandNames
|
||||
.Select(x => x.Value[0]) // first alias is command name
|
||||
.ToHashSet();
|
||||
foreach (var entry in stringsSource.GetCommandStrings()[culture.Name])
|
||||
{
|
||||
// key is command name which should be specified in aliases[0] of any method name
|
||||
var cmdName = entry.Key;
|
||||
|
||||
if (!enUsCommandNames.Contains(cmdName))
|
||||
{
|
||||
TestContext.Out.WriteLine($"'{cmdName}' It's either obsolete or missing an alias entry.");
|
||||
isSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(isSuccess);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ using NUnit.Framework;
|
|||
|
||||
namespace Nadeko.Tests
|
||||
{
|
||||
public class Tests
|
||||
public class GroupGreetTests
|
||||
{
|
||||
private GreetGrouper<int> _grouper;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Discord.Commands;
|
||||
|
@ -8,7 +10,8 @@ namespace NadekoBot.Common.Attributes
|
|||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class AliasesAttribute : AliasAttribute
|
||||
{
|
||||
public AliasesAttribute([CallerMemberName] string memberName = "") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Cmd.Split(' ').Skip(1).ToArray())
|
||||
public AliasesAttribute([CallerMemberName] string memberName = "")
|
||||
: base(CommandNameLoadHelper.GetAliasesFor(memberName))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
36
NadekoBot.Core/Common/Attributes/CommandNameLoadHelper.cs
Normal file
36
NadekoBot.Core/Common/Attributes/CommandNameLoadHelper.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace NadekoBot.Common.Attributes
|
||||
{
|
||||
public static class CommandNameLoadHelper
|
||||
{
|
||||
|
||||
private static YamlDotNet.Serialization.IDeserializer _deserializer
|
||||
= new YamlDotNet.Serialization.Deserializer();
|
||||
|
||||
public static Lazy<Dictionary<string, string[]>> LazyCommandAliases
|
||||
= new Lazy<Dictionary<string, string[]>>(() => LoadCommandNames());
|
||||
public static Dictionary<string, string[]> LoadCommandNames(string aliasesFilePath = "config/aliases.yml")
|
||||
{
|
||||
var text = File.ReadAllText(aliasesFilePath);
|
||||
return _deserializer.Deserialize<Dictionary<string, string[]>>(text);
|
||||
}
|
||||
|
||||
public static string[] GetAliasesFor(string methodName)
|
||||
=> LazyCommandAliases.Value.TryGetValue(methodName.ToLowerInvariant(), out var aliases) && aliases.Length > 1
|
||||
? aliases.Skip(1).ToArray()
|
||||
: Array.Empty<string>();
|
||||
|
||||
public static string GetCommandNameFor(string methodName)
|
||||
{
|
||||
methodName = methodName.ToLowerInvariant();
|
||||
var toReturn = LazyCommandAliases.Value.TryGetValue(methodName, out var aliases) && aliases.Length > 0
|
||||
? aliases[0]
|
||||
: methodName;
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,9 +8,9 @@ namespace NadekoBot.Common.Attributes
|
|||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class DescriptionAttribute : SummaryAttribute
|
||||
{
|
||||
public DescriptionAttribute([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Desc)
|
||||
// Localization.LoadCommand(memberName.ToLowerInvariant()).Desc
|
||||
public DescriptionAttribute(string text = "") : base(text)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,12 @@ namespace NadekoBot.Common.Attributes
|
|||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class NadekoCommandAttribute : CommandAttribute
|
||||
{
|
||||
public NadekoCommandAttribute([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Cmd.Split(' ')[0])
|
||||
public NadekoCommandAttribute([CallerMemberName] string memberName="")
|
||||
: base(CommandNameLoadHelper.GetCommandNameFor(memberName))
|
||||
{
|
||||
|
||||
this.MethodName = memberName.ToLowerInvariant();
|
||||
}
|
||||
|
||||
public string MethodName { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,13 @@ namespace NadekoBot.Common.Attributes
|
|||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class UsageAttribute : RemarksAttribute
|
||||
{
|
||||
public UsageAttribute([CallerMemberName] string memberName="") : base(UsageAttribute.GetUsage(memberName))
|
||||
// public static string GetUsage(string memberName)
|
||||
// {
|
||||
// var usage = Localization.LoadCommand(memberName.ToLowerInvariant()).Usage;
|
||||
// return JsonConvert.SerializeObject(usage);
|
||||
// }
|
||||
public UsageAttribute(string text = "") : base(text)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static string GetUsage(string memberName)
|
||||
{
|
||||
var usage = Localization.LoadCommand(memberName.ToLowerInvariant()).Usage;
|
||||
return JsonConvert.SerializeObject(usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace NadekoBot.Modules.Administration
|
|||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
[BotPerm(GuildPerm.ManageRoles)]
|
||||
public async Task Tesar()
|
||||
public async Task Togglexclsar()
|
||||
{
|
||||
bool areExclusive = _service.ToggleEsar(ctx.Guild.Id);
|
||||
if (areExclusive)
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Administration
|
|||
if (cmdText.StartsWith(Prefix + "die", StringComparison.InvariantCulture))
|
||||
return;
|
||||
|
||||
var guser = ((IGuildUser)ctx.User);
|
||||
var guser = (IGuildUser)ctx.User;
|
||||
var cmd = new StartupCommand()
|
||||
{
|
||||
CommandText = cmdText,
|
||||
|
@ -85,7 +85,7 @@ namespace NadekoBot.Modules.Administration
|
|||
if (interval < 5)
|
||||
return;
|
||||
|
||||
var guser = ((IGuildUser)ctx.User);
|
||||
var guser = (IGuildUser)ctx.User;
|
||||
var cmd = new StartupCommand()
|
||||
{
|
||||
CommandText = cmdText,
|
||||
|
@ -105,7 +105,7 @@ namespace NadekoBot.Modules.Administration
|
|||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[OwnerOnly]
|
||||
public async Task StartupCommands(int page = 1)
|
||||
public async Task StartupCommandsList(int page = 1)
|
||||
{
|
||||
if (page-- < 1)
|
||||
return;
|
||||
|
|
|
@ -146,7 +146,7 @@ namespace NadekoBot.Modules.Gambling
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task WaifuClaimerAffinity([Leftover]IGuildUser u = null)
|
||||
public async Task Affinity([Leftover]IGuildUser u = null)
|
||||
{
|
||||
if (u?.Id == ctx.User.Id)
|
||||
{
|
||||
|
@ -184,7 +184,7 @@ namespace NadekoBot.Modules.Gambling
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task WaifuLeaderboard(int page = 1)
|
||||
public async Task WaifuLb(int page = 1)
|
||||
{
|
||||
page--;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Games
|
|||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[NadekoOptions(typeof(AcrophobiaGame.Options))]
|
||||
public async Task Acro(params string[] args)
|
||||
public async Task Acrophobia(params string[] args)
|
||||
{
|
||||
var (options, _) = OptionsParser.ParseFrom(new AcrophobiaGame.Options(), args);
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
|
|
@ -26,22 +26,22 @@ namespace NadekoBot.Modules.Help
|
|||
{
|
||||
public const string PatreonUrl = "https://patreon.com/nadekobot";
|
||||
public const string PaypalUrl = "https://paypal.me/Kwoth";
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly CommandService _cmds;
|
||||
private readonly GlobalPermissionService _perms;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly IBotStrings _strings;
|
||||
|
||||
private readonly AsyncLazy<ulong> _lazyClientId;
|
||||
|
||||
public Help(IBotCredentials creds, GlobalPermissionService perms, CommandService cmds,
|
||||
IServiceProvider services, DiscordSocketClient client)
|
||||
public Help(GlobalPermissionService perms, CommandService cmds,
|
||||
IServiceProvider services, DiscordSocketClient client, IBotStrings strings)
|
||||
{
|
||||
_creds = creds;
|
||||
_cmds = cmds;
|
||||
_perms = perms;
|
||||
_services = services;
|
||||
_client = client;
|
||||
_strings = strings;
|
||||
|
||||
_lazyClientId = new AsyncLazy<ulong>(async () => (await _client.GetApplicationInfoAsync()).Id);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ namespace NadekoBot.Modules.Help
|
|||
public async Task Modules()
|
||||
{
|
||||
var embed = new EmbedBuilder().WithOkColor()
|
||||
.WithFooter(efb => efb.WithText("ℹ️" + GetText("modules_footer", Prefix)))
|
||||
.WithFooter(efb => efb.WithText("ℹ️ " + GetText("modules_footer", Prefix)))
|
||||
.WithTitle(GetText("list_of_modules"))
|
||||
.WithDescription(string.Join("\n",
|
||||
_cmds.Modules.GroupBy(m => m.GetTopLevelModule())
|
||||
|
@ -221,46 +221,6 @@ namespace NadekoBot.Modules.Help
|
|||
await channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[OwnerOnly]
|
||||
public async Task Hgit()
|
||||
{
|
||||
Dictionary<string, List<object>> cmdData = new Dictionary<string, List<object>>();
|
||||
foreach (var com in _cmds.Commands
|
||||
.OrderBy(com => com.Module.GetTopLevelModule().Name)
|
||||
.GroupBy(c => c.Aliases.First())
|
||||
.Select(g => g.First()))
|
||||
{
|
||||
var module = com.Module.GetTopLevelModule();
|
||||
List<string> optHelpStr = null;
|
||||
var opt = ((NadekoOptionsAttribute)com.Attributes.FirstOrDefault(x => x is NadekoOptionsAttribute))?.OptionType;
|
||||
if (opt != null)
|
||||
{
|
||||
optHelpStr = HelpService.GetCommandOptionHelpList(opt);
|
||||
}
|
||||
var obj = new
|
||||
{
|
||||
Aliases = com.Aliases.Select(x => Prefix + x).ToArray(),
|
||||
Description = string.Format(com.Summary, Prefix),
|
||||
Usage = JsonConvert.DeserializeObject<string[]>(com.Remarks).Select(x => string.Format(x, Prefix)).ToArray(),
|
||||
Submodule = com.Module.Name,
|
||||
Module = com.Module.GetTopLevelModule().Name,
|
||||
Options = optHelpStr,
|
||||
Requirements = HelpService.GetCommandRequirements(com),
|
||||
};
|
||||
if (cmdData.TryGetValue(module.Name, out var cmds))
|
||||
cmds.Add(obj);
|
||||
else
|
||||
cmdData.Add(module.Name, new List<object>
|
||||
{
|
||||
obj
|
||||
});
|
||||
}
|
||||
File.WriteAllText("../../docs/cmds_new.json", JsonConvert.SerializeObject(cmdData, Formatting.Indented));
|
||||
await ReplyConfirmLocalizedAsync("commandlist_regen").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task GenCmdList([Leftover] string path = null)
|
||||
|
@ -288,10 +248,9 @@ namespace NadekoBot.Modules.Help
|
|||
|
||||
return new CommandJsonObject
|
||||
{
|
||||
Aliases = com.Aliases.Select(x => Prefix + x).ToArray(),
|
||||
Description = string.Format(com.Summary, Prefix),
|
||||
Usage = JsonConvert.DeserializeObject<string[]>(com.Remarks)
|
||||
.Select(x => string.Format(x, Prefix)).ToArray(),
|
||||
Aliases = com.Aliases.Select(alias => Prefix + alias).ToArray(),
|
||||
Description = com.RealSummary(_strings, Prefix),
|
||||
Usage = com.RealRemarksArr(_strings, Prefix),
|
||||
Submodule = com.Module.Name,
|
||||
Module = com.Module.GetTopLevelModule().Name,
|
||||
Options = optHelpStr,
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace NadekoBot.Modules.Help.Services
|
|||
str += string.Format(" **/ `{0}`**", prefix + alias);
|
||||
var em = new EmbedBuilder()
|
||||
.AddField(fb => fb.WithName(str)
|
||||
.WithValue($"{com.RealSummary(prefix)}")
|
||||
.WithValue($"{com.RealSummary(_strings, prefix)}")
|
||||
.WithIsInline(true));
|
||||
|
||||
_dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides);
|
||||
|
@ -79,7 +79,8 @@ namespace NadekoBot.Modules.Help.Services
|
|||
|
||||
em
|
||||
.AddField(fb => fb.WithName(GetText("usage", guild))
|
||||
.WithValue(com.RealRemarks(prefix))
|
||||
.WithValue(string.Join("\n", Array.ConvertAll(com.RealRemarksArr(_strings, prefix),
|
||||
arg => Format.Code(arg))))
|
||||
.WithIsInline(false))
|
||||
.WithFooter(efb => efb.WithText(GetText("module", guild, com.Module.GetTopLevelModule().Name)))
|
||||
.WithColor(NadekoBot.OkColor);
|
||||
|
|
|
@ -706,7 +706,7 @@ namespace NadekoBot.Modules.Music
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ShufflePlaylist()
|
||||
public async Task PlaylistShuffle()
|
||||
{
|
||||
var mp = await _service.GetOrCreatePlayer(Context).ConfigureAwait(false);
|
||||
var val = mp.ToggleShuffle();
|
||||
|
@ -788,7 +788,7 @@ namespace NadekoBot.Modules.Music
|
|||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[OwnerOnly]
|
||||
public async Task LocalPl([Leftover] string dirPath)
|
||||
public async Task LocalPlaylist([Leftover] string dirPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dirPath))
|
||||
return;
|
||||
|
@ -925,7 +925,7 @@ namespace NadekoBot.Modules.Music
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task RepeatPl()
|
||||
public async Task PlaylistRepeat()
|
||||
{
|
||||
var mp = await _service.GetOrCreatePlayer(Context).ConfigureAwait(false);
|
||||
var currentValue = mp.ToggleRepeatPlaylist();
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Permissions
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task Lgp()
|
||||
public async Task GlobalPermList()
|
||||
{
|
||||
if (!_service.BlockedModules.Any() && !_service.BlockedCommands.Any())
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Permissions
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task Gmod(ModuleOrCrInfo module)
|
||||
public async Task GlobalModule(ModuleOrCrInfo module)
|
||||
{
|
||||
var moduleName = module.Name.ToLowerInvariant();
|
||||
if (_service.BlockedModules.Add(moduleName))
|
||||
|
@ -83,7 +83,7 @@ namespace NadekoBot.Modules.Permissions
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task Gcmd(CommandOrCrInfo cmd)
|
||||
public async Task GlobalCommand(CommandOrCrInfo cmd)
|
||||
{
|
||||
var commandName = cmd.Name.ToLowerInvariant();
|
||||
if (_service.BlockedCommands.Add(commandName))
|
||||
|
|
|
@ -21,15 +21,15 @@ namespace NadekoBot.Modules.Permissions
|
|||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task ResetPermissions()
|
||||
public async Task ResetPerms()
|
||||
{
|
||||
await _service.ResetPermissions(ctx.Guild.Id).ConfigureAwait(false);
|
||||
await _service.ResetPerms(ctx.Guild.Id).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync("perms_reset").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task ResetGlobalPermissions()
|
||||
public async Task ResetGlobalPerms()
|
||||
{
|
||||
await _service.ResetGlobalPermissions().ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync("global_perms_reset").ConfigureAwait(false);
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Permissions.Services
|
|||
_db = db;
|
||||
}
|
||||
|
||||
public async Task ResetPermissions(ulong guildId)
|
||||
public async Task ResetPerms(ulong guildId)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace NadekoBot.Core.Modules.Searches.Services
|
||||
{
|
||||
public class YtTrackService : INService
|
||||
{
|
||||
// public class YtTrackService : INService
|
||||
// {
|
||||
// private readonly IGoogleApiService _google;
|
||||
// private readonly IHttpClientFactory httpClientFactory;
|
||||
// private readonly DiscordSocketClient _client;
|
||||
|
@ -133,5 +133,5 @@ namespace NadekoBot.Core.Modules.Searches.Services
|
|||
//
|
||||
// return true;
|
||||
// }
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ namespace NadekoBot.Core.Modules.Searches
|
|||
{
|
||||
public partial class Searches
|
||||
{
|
||||
[Group]
|
||||
public class YtTrackCommands : NadekoSubmodule<YtTrackService>
|
||||
{
|
||||
// [Group]
|
||||
// public class YtTrackCommands : NadekoSubmodule<YtTrackService>
|
||||
// {
|
||||
// [NadekoCommand, Usage, Description, Aliases]
|
||||
// [RequireContext(ContextType.Guild)]
|
||||
// public async Task YtFollow(string ytChannelId, [Leftover] string uploadMessage = null)
|
||||
|
@ -53,6 +53,6 @@ namespace NadekoBot.Core.Modules.Searches
|
|||
// // await ReplyConfirmLocalizedAsync("yt_track_fail").ConfigureAwait(false);
|
||||
// //}
|
||||
// }
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,18 +21,6 @@ namespace NadekoBot.Modules.Utility
|
|||
_creds = creds;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.DM)]
|
||||
[OwnerOnly]
|
||||
public async Task PatreonRewardsReload()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken))
|
||||
return;
|
||||
await _service.RefreshPledges().ConfigureAwait(false);
|
||||
|
||||
await ctx.OkAsync();
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.DM)]
|
||||
public async Task ClaimPatreonRewards()
|
||||
|
|
|
@ -188,7 +188,7 @@ namespace NadekoBot.Modules.Utility
|
|||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task AddQuote(string keyword, [Leftover] string text)
|
||||
public async Task QuoteAdd(string keyword, [Leftover] string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text))
|
||||
return;
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace NadekoBot.Core.Services.Database.Repositories.Impl
|
|||
public List<CurrencyTransaction> GetPageFor(ulong userId, int page)
|
||||
{
|
||||
return _set.AsQueryable()
|
||||
.AsNoTracking()
|
||||
.Where(x => x.UserId == userId)
|
||||
.OrderByDescending(x => x.DateAdded)
|
||||
.Skip(15 * page)
|
||||
|
|
|
@ -7,8 +7,10 @@ namespace NadekoBot.Core.Services
|
|||
/// </summary>
|
||||
public interface IBotStrings
|
||||
{
|
||||
public string GetText(string key, ulong? guildId = null, params object[] data);
|
||||
public string GetText(string key, CultureInfo locale, params object[] data);
|
||||
string GetText(string key, ulong? guildId = null, params object[] data);
|
||||
string GetText(string key, CultureInfo locale, params object[] data);
|
||||
void Reload();
|
||||
CommandStrings GetCommandStrings(string commandName, ulong? guildId = null);
|
||||
CommandStrings GetCommandStrings(string commandName, CultureInfo cultureInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,5 +17,12 @@
|
|||
/// Reloads string cache
|
||||
/// </summary>
|
||||
void Reload();
|
||||
|
||||
/// <summary>
|
||||
/// Gets command arg examples and description
|
||||
/// </summary>
|
||||
/// <param name="localeName">Language name</param>
|
||||
/// <param name="commandName">Command name</param>
|
||||
CommandStrings GetCommandStrings(string localeName, string commandName);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,8 @@ namespace NadekoBot.Core.Services
|
|||
/// Gets all response strings
|
||||
/// </summary>
|
||||
/// <returns>Dictionary(localename, Dictionary(key, response))</returns>
|
||||
public Dictionary<string, Dictionary<string, string>> GetResponseStrings();
|
||||
Dictionary<string, Dictionary<string, string>> GetResponseStrings();
|
||||
|
||||
Dictionary<string, Dictionary<string, CommandStrings>> GetCommandStrings();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using NLog;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
|
@ -59,12 +60,45 @@ namespace NadekoBot.Core.Services
|
|||
}
|
||||
}
|
||||
|
||||
// public string[] GetUsages(string commandName, ulong guildId)
|
||||
// => GetUsages(commandName, _localization.GetCultureInfo(guildId));
|
||||
public CommandStrings GetCommandStrings(string commandName, ulong? guildId = null)
|
||||
=> GetCommandStrings(commandName, _localization.GetCultureInfo(guildId));
|
||||
|
||||
public CommandStrings GetCommandStrings(string commandName, CultureInfo cultureInfo)
|
||||
{
|
||||
var cmdStrings = _stringsProvider.GetCommandStrings(cultureInfo.Name, commandName);
|
||||
if (cmdStrings is null)
|
||||
{
|
||||
if (cultureInfo.Name == _usCultureInfo.Name
|
||||
|| (cmdStrings = _stringsProvider.GetCommandStrings(_usCultureInfo.Name, commandName)) == null)
|
||||
{
|
||||
_log.Warn($"'{commandName}' doesn't exist in 'en-US' command strings. Please report this.");
|
||||
return new CommandStrings()
|
||||
{
|
||||
Args = new[] {""},
|
||||
Desc = "?"
|
||||
};
|
||||
}
|
||||
|
||||
// _log.Warn($"'{commandName}' command strings don't exist in {cultureInfo.Name} culture." +
|
||||
// $"This message is safe to ignore, however you can ask in Nadeko support server how you can" +
|
||||
// $" contribute command translations");
|
||||
return cmdStrings;
|
||||
}
|
||||
|
||||
return cmdStrings;
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
_stringsProvider.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
public class CommandStrings
|
||||
{
|
||||
[YamlMember(Alias = "desc")]
|
||||
public string Desc { get; set; }
|
||||
[YamlMember(Alias = "args")]
|
||||
public string[] Args { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
|
@ -8,6 +6,7 @@ namespace NadekoBot.Core.Services
|
|||
{
|
||||
private readonly IStringsSource _source;
|
||||
private IReadOnlyDictionary<string, Dictionary<string, string>> responseStrings;
|
||||
private IReadOnlyDictionary<string, Dictionary<string, CommandStrings>> commandStrings;
|
||||
|
||||
public LocalBotStringsProvider(IStringsSource source)
|
||||
{
|
||||
|
@ -29,6 +28,18 @@ namespace NadekoBot.Core.Services
|
|||
public void Reload()
|
||||
{
|
||||
responseStrings = _source.GetResponseStrings();
|
||||
commandStrings = _source.GetCommandStrings();
|
||||
}
|
||||
|
||||
public CommandStrings GetCommandStrings(string localeName, string commandName)
|
||||
{
|
||||
if (commandStrings.TryGetValue(localeName, out var langStrings)
|
||||
&& langStrings.TryGetValue(commandName, out var strings))
|
||||
{
|
||||
return strings;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +1,29 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads strings from the local default filepath <see cref="StringsPath"/>
|
||||
/// Loads strings from the local default filepath <see cref="_responsesPath"/>
|
||||
/// </summary>
|
||||
public class LocalFileStringsSource : IStringsSource
|
||||
{
|
||||
private const string StringsPath = "config/strings/responses";
|
||||
private readonly string _responsesPath = "config/strings/responses";
|
||||
private readonly string _commandsPath = "config/strings/commands";
|
||||
|
||||
public LocalFileStringsSource(string responsesPath = "config/strings/responses",
|
||||
string commandsPath = "config/strings/commands")
|
||||
{
|
||||
_responsesPath = responsesPath;
|
||||
_commandsPath = commandsPath;
|
||||
}
|
||||
|
||||
public Dictionary<string, Dictionary<string, string>> GetResponseStrings()
|
||||
{
|
||||
var outputDict = new Dictionary<string, Dictionary<string, string>>();
|
||||
foreach (var file in Directory.GetFiles(StringsPath))
|
||||
foreach (var file in Directory.GetFiles(_responsesPath))
|
||||
{
|
||||
var langDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(file));
|
||||
var localeName = GetLocaleName(file);
|
||||
|
@ -24,8 +33,26 @@ namespace NadekoBot.Core.Services
|
|||
return outputDict;
|
||||
}
|
||||
|
||||
public Dictionary<string, Dictionary<string, CommandStrings>> GetCommandStrings()
|
||||
{
|
||||
var deserializer = new DeserializerBuilder()
|
||||
.Build();
|
||||
|
||||
var outputDict = new Dictionary<string, Dictionary<string, CommandStrings>>();
|
||||
foreach (var file in Directory.GetFiles(_commandsPath))
|
||||
{
|
||||
var text = File.ReadAllText(file);
|
||||
var langDict = deserializer.Deserialize<Dictionary<string, CommandStrings>>(text);
|
||||
var localeName = GetLocaleName(file);
|
||||
outputDict[localeName] = langDict;
|
||||
}
|
||||
|
||||
return outputDict;
|
||||
}
|
||||
|
||||
private static string GetLocaleName(string fileName)
|
||||
{
|
||||
fileName = Path.GetFileName(fileName);
|
||||
var dotIndex = fileName.IndexOf('.') + 1;
|
||||
var secondDotIndex = fileName.LastIndexOf('.');
|
||||
return fileName.Substring(dotIndex, secondDotIndex - dotIndex);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Discord.WebSocket;
|
||||
using StackExchange.Redis;
|
||||
|
||||
|
@ -28,6 +30,24 @@ namespace NadekoBot.Core.Services
|
|||
return value;
|
||||
}
|
||||
|
||||
public CommandStrings GetCommandStrings(string localeName, string commandName)
|
||||
{
|
||||
string argsStr = _redis.GetDatabase().HashGet($"commands:{localeName}", $"{commandName}::args");
|
||||
if (argsStr == default)
|
||||
return null;
|
||||
|
||||
var descStr = _redis.GetDatabase().HashGet($"commands:{localeName}", $"{commandName}::desc");
|
||||
if (descStr == default)
|
||||
return null;
|
||||
|
||||
var args = Array.ConvertAll(argsStr.Split('&'), HttpUtility.UrlDecode);
|
||||
return new CommandStrings()
|
||||
{
|
||||
Args = args,
|
||||
Desc = descStr
|
||||
};
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
var redisDb = _redis.GetDatabase();
|
||||
|
@ -39,6 +59,18 @@ namespace NadekoBot.Core.Services
|
|||
|
||||
redisDb.HashSet($"responses:{localeName}", hashFields);
|
||||
}
|
||||
|
||||
foreach (var (localeName, localeStrings) in _source.GetCommandStrings())
|
||||
{
|
||||
var hashFields = localeStrings
|
||||
.Select(x => new HashEntry($"{x.Key}::args",
|
||||
string.Join('&', Array.ConvertAll(x.Value.Args, HttpUtility.UrlEncode))))
|
||||
.Concat(localeStrings
|
||||
.Select(x => new HashEntry($"{x.Key}::desc", x.Value.Desc)))
|
||||
.ToArray();
|
||||
|
||||
redisDb.HashSet($"commands:{localeName}", hashFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,8 @@ using System.Security.Cryptography;
|
|||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Attributes;
|
||||
using NadekoBot.Common.Attributes;
|
||||
|
||||
namespace NadekoBot.Extensions
|
||||
{
|
||||
|
@ -160,11 +162,21 @@ namespace NadekoBot.Extensions
|
|||
public static bool IsAuthor(this IMessage msg, IDiscordClient client)
|
||||
=> msg.Author?.Id == client.CurrentUser.Id;
|
||||
|
||||
public static string RealSummary(this CommandInfo cmd, string prefix)
|
||||
=> string.Format(cmd.Summary, prefix);
|
||||
public static string RealRemarks(this CommandInfo cmd, string prefix)
|
||||
=> string.Join("\n", JsonConvert.DeserializeObject<string[]>(cmd.Remarks)
|
||||
.Select(x => Format.Code(string.Format(x, prefix))));
|
||||
public static string RealSummary(this CommandInfo cmd, IBotStrings strings, string prefix)
|
||||
=> string.Format(strings.GetCommandStrings(cmd.Name).Desc, prefix);
|
||||
|
||||
public static string[] RealRemarksArr(this CommandInfo cmd, IBotStrings strings, string prefix)
|
||||
=> Array.ConvertAll(strings.GetCommandStrings(cmd.MethodName()).Args,
|
||||
arg => GetFullUsage(cmd.Name, arg, prefix));
|
||||
|
||||
public static string MethodName(this CommandInfo cmd)
|
||||
=> ((NadekoCommandAttribute) cmd.Attributes.FirstOrDefault(x => x is NadekoCommandAttribute))?.MethodName
|
||||
?? cmd.Name;
|
||||
// public static string RealRemarks(this CommandInfo cmd, IBotStrings strings, string prefix)
|
||||
// => string.Join('\n', cmd.RealRemarksArr(strings, prefix));
|
||||
|
||||
public static string GetFullUsage(string commandName, string args, string prefix)
|
||||
=> $"{prefix}{commandName} {args}";
|
||||
|
||||
public static EmbedBuilder AddPaginatedFooter(this EmbedBuilder embed, int curPage, int? lastPage)
|
||||
{
|
||||
|
|
1197
src/NadekoBot/config/aliases.yml
Normal file
1197
src/NadekoBot/config/aliases.yml
Normal file
File diff suppressed because it is too large
Load diff
1966
src/NadekoBot/config/strings/commands/commands.en-US.yml
Normal file
1966
src/NadekoBot/config/strings/commands/commands.en-US.yml
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue