using Lagrange.Core.Common; using Lagrange.Core.Common.Interface; using Lagrange.OneBot.Core.Login; using Lagrange.OneBot.Core.Network; using Lagrange.OneBot.Core.Network.Service; using Lagrange.OneBot.Core.Notify; using Lagrange.OneBot.Core.Operation; using Lagrange.OneBot.Database; using Lagrange.OneBot.Message; using Lagrange.OneBot.Utility; using LiteDB; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using JsonSerializer = System.Text.Json.JsonSerializer; namespace Lagrange.OneBot.Extensions; public static class HostApplicationBuilderExtension { public static HostApplicationBuilder ConfigureLagrangeCore(this HostApplicationBuilder builder) { builder.Services .AddSingleton() // Signer .AddSingleton((services) => // BotConfig { var configuration = services.GetRequiredService(); return new BotConfig { Protocol = configuration["Account:Protocol"] switch { "Windows" => Protocols.Windows, "MacOs" => Protocols.MacOs, _ => Protocols.Linux, }, AutoReconnect = configuration.GetValue("Account:AutoReconnect", true), UseIPv6Network = configuration.GetValue("Account:UseIPv6Network", false), GetOptimumServer = configuration.GetValue("Account:GetOptimumServer", true), AutoReLogin = configuration.GetValue("Account:AutoReLogin", true), CustomSignProvider = services.GetRequiredService() }; }) .AddSingleton((services) => // Device { var configuration = services.GetRequiredService(); string path = configuration["ConfigPath:DeviceInfo"] ?? "device.json"; var device = File.Exists(path) ? JsonSerializer.Deserialize(File.ReadAllText(path)) ?? BotDeviceInfo.GenerateInfo() : BotDeviceInfo.GenerateInfo(); string deviceJson = JsonSerializer.Serialize(device); File.WriteAllText(path, deviceJson); return device; }) .AddSingleton((services) => // Keystore { var configuration = services.GetRequiredService(); string path = configuration["ConfigPath:Keystore"] ?? "keystore.json"; return File.Exists(path) ? JsonSerializer.Deserialize(File.ReadAllText(path)) ?? new() : new(); }) .AddSingleton((services) => services.GetRequiredService().GetAppInfo()) // AppInfo .AddSingleton((services) => BotFactory.Create( // BotContext services.GetRequiredService(), services.GetRequiredService(), services.GetRequiredService(), services.GetRequiredService() )) .AddHostedService(); return builder; } public static HostApplicationBuilder ConfigureOneBot(this HostApplicationBuilder builder) { builder.Services.AddOptions() .AddSingleton(services => // Database { var configuration = services.GetRequiredService(); var logger = services.GetRequiredService>(); BsonMapper.Global.TrimWhitespace = false; BsonMapper.Global.EmptyStringToNull = false; // Specify ctor for some classes BsonMapper.Global.RegisterType( LiteDbUtility.IMessageEntitySerialize, LiteDbUtility.IMessageEntityDeserialize ); string path = configuration["ConfigPath:Database"] ?? $"lagrange-{configuration["Account:Uin"]}.db"; bool isFirstCreate = false; if (!File.Exists(path)) isFirstCreate = true; var db = new LiteDatabase(path) { CheckpointSize = 50 }; string[] expressions = ["$.Sequence", "$.MessageId", "$.FriendUin", "$.GroupUin"]; bool hasFirstIndex = false; var indexes = db.GetCollection("$indexes"); foreach (var expression in expressions) { if (indexes.Exists(Query.EQ("expression", expression))) continue; logger.LogWarning("In the database index"); logger.LogWarning("Depending on the size of the database will consume some time and memory"); logger.LogWarning("Not yet finished, please wait..."); hasFirstIndex = true; break; } var records = db.GetCollection(); foreach (var expression in expressions) { records.EnsureIndex(BsonExpression.Create(expression)); } // Skipping the first database creation is a restart after indexing if (!isFirstCreate && hasFirstIndex) { db.Dispose(); // Ensure that the database is written correctly logger.LogInformation("Indexing Complete! Press any key to close and restart the program manually!"); Console.ReadKey(true); Environment.Exit(0); } return db; }) // // OneBot Netword Service .AddSingleton() .AddScoped, ForwardWSServiceFactory>() .AddScoped() .AddScoped, ReverseWSServiceFactory>() .AddScoped() .AddScoped, HttpServiceFactory>() .AddScoped() .AddScoped, HttpPostServiceFactory>() .AddScoped() .AddScoped() .AddScoped(services => services.GetRequiredService().Create() ?? throw new Exception("Invalid conf detected")) // // OneBot Misc Service .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton(); return builder; } }