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

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

View File

@@ -1,37 +1,15 @@
#nullable disable
using CommandLine;
using Nadeko.Common;
using Nadeko.Medusa;
using NadekoBot.Common.ModuleBehaviors;
namespace NadekoBot.Modules.Help.Services;
public class HelpService : IExecNoCommand, INService
{
private readonly CommandHandler _ch;
private readonly IBotStrings _strings;
private readonly DiscordPermOverrideService _dpos;
private readonly BotConfigService _bss;
private readonly IEmbedBuilderService _eb;
private readonly ILocalization _loc;
private readonly IMedusaLoaderService _medusae;
public HelpService(
CommandHandler ch,
IBotStrings strings,
DiscordPermOverrideService dpos,
BotConfigService bss,
IEmbedBuilderService eb,
ILocalization loc,
IMedusaLoaderService medusae)
public HelpService(BotConfigService bss)
{
_ch = ch;
_strings = strings;
_dpos = dpos;
_bss = bss;
_eb = eb;
_loc = loc;
_medusae = medusae;
}
public Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
@@ -44,13 +22,14 @@ public class HelpService : IExecNoCommand, INService
// only send dm help text if it contains one of the keywords, if they're specified
// if they're not, then reply to every DM
if (settings.DmHelpTextKeywords is not null && !settings.DmHelpTextKeywords.Any(k => msg.Content.Contains(k)))
if (settings.DmHelpTextKeywords is not null &&
!settings.DmHelpTextKeywords.Any(k => msg.Content.Contains(k)))
return Task.CompletedTask;
var rep = new ReplacementBuilder().WithOverride("%prefix%", () => _bss.Data.Prefix)
.WithOverride("%bot.prefix%", () => _bss.Data.Prefix)
.WithUser(msg.Author)
.Build();
.WithOverride("%bot.prefix%", () => _bss.Data.Prefix)
.WithUser(msg.Author)
.Build();
var text = SmartText.CreateFrom(settings.DmHelpText);
text = rep.Replace(text);
@@ -60,143 +39,4 @@ public class HelpService : IExecNoCommand, INService
return Task.CompletedTask;
}
public IEmbedBuilder GetCommandHelp(CommandInfo com, IGuild guild)
{
var prefix = _ch.GetPrefix(guild);
var str = $"**`{prefix + com.Aliases.First()}`**";
var alias = com.Aliases.Skip(1).FirstOrDefault();
if (alias is not null)
str += $" **/ `{prefix + alias}`**";
var culture = _loc.GetCultureInfo(guild);
var em = _eb.Create()
.AddField(str, $"{com.RealSummary(_strings, _medusae, culture, prefix)}", true);
_dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides);
var reqs = GetCommandRequirements(com, (GuildPermission?)overrides);
if (reqs.Any())
em.AddField(GetText(strs.requires, guild), string.Join("\n", reqs));
em.AddField(_strings.GetText(strs.usage),
string.Join("\n", com.RealRemarksArr(_strings,_medusae, culture, prefix).Map(arg => Format.Code(arg))))
.WithFooter(GetText(strs.module(com.Module.GetTopLevelModule().Name), guild))
.WithOkColor();
var opt = GetNadekoOptionType(com.Attributes);
if (opt is not null)
{
var hs = GetCommandOptionHelp(opt);
if (!string.IsNullOrWhiteSpace(hs))
em.AddField(GetText(strs.options, guild), hs);
}
return em;
}
public static Type GetNadekoOptionType(IEnumerable<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>
<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>
<PackageReference Include="AWSSDK.S3" Version="3.7.101.58" />
<PackageReference Include="AWSSDK.S3" Version="3.7.101.58"/>
</ItemGroup>
</Project>