refactor: Initial release
This commit is contained in:
commit
9505750e29
447 changed files with 41522 additions and 0 deletions
330
ProjectMakoto/Util/Initializers/DisCatSharpExtensionsLoader.cs
Normal file
330
ProjectMakoto/Util/Initializers/DisCatSharpExtensionsLoader.cs
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
// Project Makoto
|
||||
// Copyright (C) 2024 Fortunevale
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ProjectMakoto.Util.Initializers;
|
||||
internal static class DisCatSharpExtensionsLoader
|
||||
{
|
||||
static Bot bot = null;
|
||||
static List<DisCatSharp.ApplicationCommands.Entities.CommandTranslator> singleCommandTranslations = new();
|
||||
static List<DisCatSharp.ApplicationCommands.Entities.GroupTranslator> groupCommandTranslations = new();
|
||||
|
||||
internal static void GetCommandTranslations(ApplicationCommandsTranslationContext x)
|
||||
{
|
||||
if (singleCommandTranslations.IsNotNullAndNotEmpty() && groupCommandTranslations.IsNotNullAndNotEmpty())
|
||||
{
|
||||
x.AddSingleTranslation(JsonConvert.SerializeObject(singleCommandTranslations));
|
||||
x.AddGroupTranslation(JsonConvert.SerializeObject(groupCommandTranslations));
|
||||
return;
|
||||
}
|
||||
|
||||
object CreateTranslationRecursively(Type typeToCreate, CommandTranslation translation)
|
||||
{
|
||||
try
|
||||
{
|
||||
var nameValues = translation.Names;
|
||||
|
||||
if (nameValues is null)
|
||||
return null;
|
||||
|
||||
var descriptionValues = translation.Descriptions;
|
||||
var typeValue = translation.Type;
|
||||
var optionsValues = translation.Options;
|
||||
var choicesValues = translation.Choices;
|
||||
var groupsValues = translation.Groups;
|
||||
var commandsValues = translation.Commands;
|
||||
|
||||
Log.Verbose("Creating instance of '{type}'", typeToCreate.Name);
|
||||
var translator = Activator.CreateInstance(typeToCreate);
|
||||
|
||||
var createTypeProperties = typeToCreate.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "name")).SetValue(translator, nameValues["en"]);
|
||||
|
||||
if (typeToCreate == typeof(DisCatSharp.ApplicationCommands.Entities.GroupTranslator) || typeToCreate == typeof(DisCatSharp.ApplicationCommands.Entities.CommandTranslator))
|
||||
createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "type")).SetValue(translator, (ApplicationCommandType?)typeValue);
|
||||
|
||||
if (createTypeProperties.Any(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "description")))
|
||||
createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "description")).SetValue(translator, descriptionValues["en"]);
|
||||
|
||||
Dictionary<string, string> NameTranslationDictionary = new();
|
||||
foreach (var nameTranslation in nameValues ?? new())
|
||||
{
|
||||
if (nameTranslation.Key == "en")
|
||||
{
|
||||
NameTranslationDictionary.Add("en-GB", nameTranslation.Value);
|
||||
NameTranslationDictionary.Add("en-US", nameTranslation.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
NameTranslationDictionary.Add(nameTranslation.Key, nameTranslation.Value);
|
||||
}
|
||||
if (createTypeProperties.Any(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "name_translations")))
|
||||
createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "name_translations")).SetValue(translator, NameTranslationDictionary);
|
||||
|
||||
Dictionary<string, string> DescriptionTranslationDictionary = new();
|
||||
foreach (var descriptionTranslations in descriptionValues ?? new())
|
||||
{
|
||||
if (descriptionTranslations.Key == "en")
|
||||
{
|
||||
DescriptionTranslationDictionary.Add("en-GB", descriptionTranslations.Value);
|
||||
DescriptionTranslationDictionary.Add("en-US", descriptionTranslations.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
DescriptionTranslationDictionary.Add(descriptionTranslations.Key, descriptionTranslations.Value);
|
||||
}
|
||||
if (createTypeProperties.Any(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "description_translations")))
|
||||
createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "description_translations")).SetValue(translator, DescriptionTranslationDictionary);
|
||||
|
||||
if (commandsValues is not null && createTypeProperties.Any(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "commands")))
|
||||
{
|
||||
Log.Verbose("Creating sub-command translations for command '{name}'", nameValues.First());
|
||||
|
||||
var commandProperty = createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "commands"));
|
||||
commandProperty.SetValue(translator, new List<DisCatSharp.ApplicationCommands.Entities.CommandTranslator>());
|
||||
foreach (var value in commandsValues)
|
||||
{
|
||||
var obj = (DisCatSharp.ApplicationCommands.Entities.CommandTranslator)CreateTranslationRecursively(typeof(DisCatSharp.ApplicationCommands.Entities.CommandTranslator), value);
|
||||
|
||||
if (obj is null)
|
||||
continue;
|
||||
|
||||
((List<DisCatSharp.ApplicationCommands.Entities.CommandTranslator>)commandProperty.GetValue(translator)).Add(obj);
|
||||
}
|
||||
|
||||
if (((List<DisCatSharp.ApplicationCommands.Entities.CommandTranslator>)commandProperty.GetValue(translator)).Count == 0)
|
||||
commandProperty.SetValue(translator, null);
|
||||
}
|
||||
|
||||
if (optionsValues is not null && createTypeProperties.Any(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "options")))
|
||||
{
|
||||
Log.Verbose("Creating option translations for command '{name}'", nameValues.First());
|
||||
|
||||
var optionProperty = createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "options"));
|
||||
optionProperty.SetValue(translator, new List<DisCatSharp.ApplicationCommands.Entities.OptionTranslator>());
|
||||
foreach (var value in optionsValues)
|
||||
{
|
||||
var obj = (DisCatSharp.ApplicationCommands.Entities.OptionTranslator)CreateTranslationRecursively(typeof(DisCatSharp.ApplicationCommands.Entities.OptionTranslator), value);
|
||||
|
||||
if (obj is null)
|
||||
continue;
|
||||
|
||||
((List<DisCatSharp.ApplicationCommands.Entities.OptionTranslator>)optionProperty.GetValue(translator)).Add(obj);
|
||||
}
|
||||
|
||||
if (((List<DisCatSharp.ApplicationCommands.Entities.OptionTranslator>)optionProperty.GetValue(translator)).Count == 0)
|
||||
optionProperty.SetValue(translator, null);
|
||||
}
|
||||
|
||||
if (choicesValues is not null && createTypeProperties.Any(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "choices")))
|
||||
{
|
||||
Log.Verbose("Creating choice translations for command '{name}'", nameValues.First());
|
||||
|
||||
var choiceProperty = createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "choices"));
|
||||
choiceProperty.SetValue(translator, new List<DisCatSharp.ApplicationCommands.Entities.ChoiceTranslator>());
|
||||
foreach (var value in choicesValues)
|
||||
{
|
||||
var obj = (DisCatSharp.ApplicationCommands.Entities.ChoiceTranslator)CreateTranslationRecursively(typeof(DisCatSharp.ApplicationCommands.Entities.ChoiceTranslator), value);
|
||||
|
||||
if (obj is null)
|
||||
continue;
|
||||
|
||||
((List<DisCatSharp.ApplicationCommands.Entities.ChoiceTranslator>)choiceProperty.GetValue(translator)).Add(obj);
|
||||
}
|
||||
|
||||
if (((List<DisCatSharp.ApplicationCommands.Entities.ChoiceTranslator>)choiceProperty.GetValue(translator)).Count == 0)
|
||||
choiceProperty.SetValue(translator, null);
|
||||
}
|
||||
|
||||
if (groupsValues is not null && createTypeProperties.Any(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "groups")))
|
||||
{
|
||||
Log.Verbose("Creating group translations for command '{name}'", nameValues.First());
|
||||
|
||||
var groupProperty = createTypeProperties.First(x => x.GetCustomAttributes().Any(attr => attr is JsonPropertyAttribute attribute && attribute.PropertyName == "groups"));
|
||||
groupProperty.SetValue(translator, new List<DisCatSharp.ApplicationCommands.Entities.SubGroupTranslator>());
|
||||
|
||||
foreach (var value in groupsValues)
|
||||
{
|
||||
var obj = (DisCatSharp.ApplicationCommands.Entities.SubGroupTranslator)CreateTranslationRecursively(typeof(DisCatSharp.ApplicationCommands.Entities.SubGroupTranslator), value);
|
||||
|
||||
if (obj is null)
|
||||
continue;
|
||||
|
||||
((List<DisCatSharp.ApplicationCommands.Entities.SubGroupTranslator>)groupProperty.GetValue(translator)).Add(obj);
|
||||
}
|
||||
|
||||
if (((List<DisCatSharp.ApplicationCommands.Entities.SubGroupTranslator>)groupProperty.GetValue(translator)).Count == 0)
|
||||
groupProperty.SetValue(translator, null);
|
||||
}
|
||||
|
||||
return translator;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to generate DCS-Compatible Translations");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var translation in bot.LoadedTranslations.CommandList)
|
||||
singleCommandTranslations.Add(
|
||||
(DisCatSharp.ApplicationCommands.Entities.CommandTranslator)CreateTranslationRecursively(typeof(DisCatSharp.ApplicationCommands.Entities.CommandTranslator), translation));
|
||||
|
||||
foreach (var translation in bot.LoadedTranslations.CommandList)
|
||||
groupCommandTranslations.Add(
|
||||
(DisCatSharp.ApplicationCommands.Entities.GroupTranslator)CreateTranslationRecursively(typeof(DisCatSharp.ApplicationCommands.Entities.GroupTranslator), translation));
|
||||
|
||||
x.AddSingleTranslation(JsonConvert.SerializeObject(singleCommandTranslations));
|
||||
x.AddGroupTranslation(JsonConvert.SerializeObject(groupCommandTranslations));
|
||||
}
|
||||
|
||||
public static async Task Load(Bot bot)
|
||||
{
|
||||
DisCatSharpExtensionsLoader.bot = bot;
|
||||
|
||||
if (bot.status.LoadedConfig.Secrets.Discord.Token.Length <= 0)
|
||||
{
|
||||
Log.Fatal("No discord token provided");
|
||||
await Task.Delay(1000);
|
||||
Environment.Exit((int)ExitCodes.NoToken);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Debug("Registering DiscordClient..");
|
||||
|
||||
bot.DiscordClient = new DiscordShardedClient(new DiscordConfiguration
|
||||
{
|
||||
Token = bot.status.LoadedConfig.Secrets.Discord.Token,
|
||||
TokenType = TokenType.Bot,
|
||||
MinimumLogLevel = Microsoft.Extensions.Logging.LogLevel.Trace,
|
||||
Intents = DiscordIntents.All,
|
||||
AutoReconnect = true,
|
||||
LoggerFactory = bot.msLoggerFactory,
|
||||
HttpTimeout = TimeSpan.FromSeconds(60),
|
||||
MessageCacheSize = 4096,
|
||||
EnableSentry = true,
|
||||
ReportMissingFields = bot.status.LoadedConfig.IsDev,
|
||||
AttachUserInfo = true,
|
||||
DeveloperUserId = 411950662662881290,
|
||||
DisableUpdateCheck = true,
|
||||
});
|
||||
|
||||
bot.ExperienceHandler = new(bot);
|
||||
|
||||
Log.Debug("Registering CommandsNext..");
|
||||
|
||||
var cNext = await bot.DiscordClient.UseCommandsNextAsync(new CommandsNextConfiguration
|
||||
{
|
||||
EnableDefaultHelp = false,
|
||||
EnableMentionPrefix = false,
|
||||
IgnoreExtraArguments = true,
|
||||
EnableDms = false,
|
||||
ServiceProvider = new ServiceCollection()
|
||||
.AddSingleton(bot)
|
||||
.BuildServiceProvider(),
|
||||
PrefixResolver = new PrefixResolverDelegate(bot.GetPrefix)
|
||||
});
|
||||
|
||||
Log.Debug("Registering DisCatSharp TwoFactor..");
|
||||
|
||||
var tfa = bot.DiscordClient.UseTwoFactorAsync(new TwoFactorConfiguration
|
||||
{
|
||||
ResponseConfiguration = new TwoFactorResponseConfiguration
|
||||
{
|
||||
ShowResponse = false,
|
||||
AuthenticatorAccountPrefix = "Project Makoto"
|
||||
},
|
||||
Issuer = "Project Makoto",
|
||||
});
|
||||
|
||||
DiscordEventHandler.SetupEvents(bot);
|
||||
bot.DiscordClient.GuildDownloadCompleted += bot.GuildDownloadCompleted;
|
||||
|
||||
Log.Debug("Registering Interactivity..");
|
||||
_ = await bot.DiscordClient.UseInteractivityAsync(new InteractivityConfiguration { });
|
||||
|
||||
var appCommands = await bot.DiscordClient.UseApplicationCommandsAsync(new ApplicationCommandsConfiguration
|
||||
{
|
||||
ServiceProvider = new ServiceCollection()
|
||||
.AddSingleton(bot)
|
||||
.BuildServiceProvider(),
|
||||
EnableDefaultHelp = false,
|
||||
EnableLocalization = true,
|
||||
DebugStartup = true
|
||||
});
|
||||
|
||||
if (bot.status.CurrentAppHash != bot.status.LoadedConfig.DontModify.LastKnownHash)
|
||||
{
|
||||
Log.Debug("Clearing cached Commands..");
|
||||
await FileExtensions.CleanupFilesAndDirectories(new(), Directory.GetFiles("CompiledCommands").ToList());
|
||||
}
|
||||
|
||||
await BasePlugin.RaisePreLogin(bot, bot.DiscordClient);
|
||||
|
||||
Log.Debug("Compiling Built-In Commands..");
|
||||
var commandModules = Commands.Commands.GetList();
|
||||
bot._CommandModules = commandModules;
|
||||
var assemblies = await CommandCompiler.BuildCommands(bot, bot.status.CurrentAppHash, commandModules, null);
|
||||
CommandCompiler.RegisterAssemblies(bot, cNext, appCommands, GetCommandTranslations, assemblies);
|
||||
|
||||
Log.Debug("Registering Debug Commands..");
|
||||
appCommands.RegisterGuildCommands<ApplicationCommands.DebugCommands>(bot.status.LoadedConfig.Discord.DevelopmentGuild, GetCommandTranslations);
|
||||
|
||||
Log.Debug("Registering Command Converters..");
|
||||
cNext.RegisterConverter(new CustomArgumentConverter.BoolConverter());
|
||||
cNext.RegisterConverter(new CustomArgumentConverter.AttachmentConverter());
|
||||
|
||||
var commandsNextTypes = new List<Type>();
|
||||
var applicationCommandTypes = new List<Type>();
|
||||
|
||||
await Util.Initializers.PluginLoader.LoadPluginCommands(bot, cNext, appCommands);
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
while (!bot.status.DiscordInitialized)
|
||||
await Task.Delay(100);
|
||||
|
||||
Stopwatch sw = new();
|
||||
sw.Start();
|
||||
|
||||
_ = bot.DiscordClient.UpdateStatusAsync(userStatus: UserStatus.Online, activity: new DiscordActivity("Registering commands..", ActivityType.Custom));
|
||||
|
||||
var applicationCommandsExtension = bot.DiscordClient.GetFirstShard().GetApplicationCommands();
|
||||
while (applicationCommandsExtension?.RegisteredCommands?.Count == 0 && sw.ElapsedMilliseconds < TimeSpan.FromMinutes(5).TotalMilliseconds)
|
||||
await Task.Delay(1000);
|
||||
|
||||
if (applicationCommandsExtension?.RegisteredCommands?.Count == 0)
|
||||
{
|
||||
Log.Fatal("Commands did not register.");
|
||||
_ = bot.ExitApplication(true);
|
||||
return;
|
||||
}
|
||||
|
||||
bot.status.DiscordCommandsRegistered = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (bot.DatabaseClient.Disposed)
|
||||
return;
|
||||
|
||||
await bot.DiscordClient.UpdateStatusAsync(activity: new DiscordActivity($"{bot.DiscordClient.GetGuilds().Count.ToString("N0", CultureInfo.CreateSpecificCulture("en-US"))} guilds | Up for {Math.Round((DateTime.UtcNow - bot.status.startupTime).TotalHours, 1).ToString(CultureInfo.CreateSpecificCulture("en-US"))}h", ActivityType.Custom));
|
||||
await Task.Delay(30000);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to update user status");
|
||||
await Task.Delay(30000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue