diff --git a/Login/BotService.cs b/Login/BotService.cs new file mode 100644 index 0000000..7313a4e --- /dev/null +++ b/Login/BotService.cs @@ -0,0 +1,136 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Debugger; +using Grpc.Core; +using Lagrange.Core; +using Lagrange.Core.Common; +using Lagrange.Core.Common.Interface; +using Lagrange.Core.Common.Interface.Api; +using Shrink.API; +using Shrink.Utility; +using Console = System.Console; + +namespace Shrink.Login; + +public class BotService +{ + private static readonly Lazy _instance = new(() => new BotService()); + public static BotService Instance => _instance.Value; + + public BotContext? Client; + private bool _isOnline; + private static string KeystoreFilePath => "Keystore.json"; + private static string DeviceInfoFilePath => "DeviceInfo.json"; + + + private static BotDeviceInfo GetDeviceInfo() => + ReadOrCreateJsonFile(DeviceInfoFilePath, BotDeviceInfo.GenerateInfo); + + // 登录方法 + public async Task Login() + { + const int port = 50051; + var server = new Server + { + Services = { APIService.BindService(new BotServiceImpl()) }, + Ports = { new ServerPort("localhost", port, ServerCredentials.Insecure) } + }; + + var deviceInfo = File.Exists(DeviceInfoFilePath) + ? ReadJsonFromFile(DeviceInfoFilePath) + : GetDeviceInfo(); + + var keyStore = File.Exists(KeystoreFilePath) + ? ReadJsonFromFile(KeystoreFilePath) + : new BotKeystore(); + + Client = BotFactory.Create(new BotConfig + { + UseIPv6Network = false, + GetOptimumServer = true, + AutoReconnect = true, + Protocol = Protocols.Linux + }, deviceInfo, keyStore); + + // Log模式 + Client.Invoker.OnBotLogEvent += (_, @event) => + { + @event.Level.ChangeColorByTitle(); + Console.WriteLine(@event.ToString()); + }; + + // bot信息保存 + Client.Invoker.OnBotOnlineEvent += (_, @event) => + { + Console.WriteLine(@event.ToString()); + _isOnline = true; + server.Start(); + Console.WriteLine($"gRPC server listening on port {port}"); + }; + Client.Invoker.OnBotOfflineEvent += async (_, @event) => + { + Console.WriteLine(@event.ToString()); + await server.ShutdownAsync(); + _isOnline = false; + }; + + if (File.Exists(KeystoreFilePath)) + { + await Client.LoginByPassword(); + if (!_isOnline) + { + Console.WriteLine("账密登录失败,请尝试二维码登录。"); + var qrCode = await Client.FetchQrCode(); + if (qrCode != null) + { + await File.WriteAllBytesAsync("qr.png", qrCode.Value.QrCode); + await Client.LoginByQrCode(); + } + } + } + + await File.WriteAllTextAsync(KeystoreFilePath, JsonSerializer.Serialize(Client.UpdateKeystore())); + await File.WriteAllTextAsync(DeviceInfoFilePath, JsonSerializer.Serialize(Client.UpdateDeviceInfo())); + } + + private static T ReadJsonFromFile(string filePath) + { + try + { + var json = File.ReadAllText(filePath); + return JsonSerializer.Deserialize(json, + new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.Preserve })!; + } + catch (Exception ex) + { + Console.WriteLine($"读取文件出错: {filePath}: {ex.Message}"); + throw; + } + } + + private static T ReadOrCreateJsonFile(string filePath, Func createFunc) + { + if (File.Exists(filePath)) + { + return ReadJsonFromFile(filePath); + } + + var newData = createFunc(); + WriteJsonToFile(filePath, newData); + return newData; + } + + private static void WriteJsonToFile(string filePath, T data) + { + try + { + var json = JsonSerializer.Serialize(data); + File.WriteAllText(filePath, json); + } + catch (Exception ex) + { + Console.WriteLine($"写入文件出错: {filePath}: {ex.Message}"); + throw; + } + } +} \ No newline at end of file diff --git a/Login/QrCode.cs b/Login/QrCode.cs deleted file mode 100644 index e1aecb7..0000000 --- a/Login/QrCode.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using Lagrange.Core; -using Lagrange.Core.Common; -using Lagrange.Core.Common.Interface; -using Lagrange.Core.Common.Interface.Api; -using Lagrange.Core.Event.EventArg; -using Shrink.Utility; -using Console = System.Console; - -namespace Shrink.Login; - -public class QrCode -{ - private static QrCode? _instance; - - private static readonly object Lock = new(); - - public static QrCode Instance - { - get - { - if (_instance != null) return _instance; - lock (Lock) - { - _instance ??= new QrCode(); - } - return _instance; - } - } - - public BotContext? Client; - public static void SaveKeystore(BotKeystore keystore) => - File.WriteAllText("Keystore.json", JsonSerializer.Serialize(keystore)); - - public static BotDeviceInfo GetDeviceInfo() - { - if (File.Exists("DeviceInfo.json")) - { - var info = JsonSerializer.Deserialize(File.ReadAllText("DeviceInfo.json")); - if (info != null) return info; - - info = BotDeviceInfo.GenerateInfo(); - File.WriteAllText("DeviceInfo.json", JsonSerializer.Serialize(info)); - return info; - } - - var deviceInfo = BotDeviceInfo.GenerateInfo(); - File.WriteAllText("DeviceInfo.json", JsonSerializer.Serialize(deviceInfo)); - return deviceInfo; - } - public static BotKeystore? LoadKeystore() - { - try - { - var text = File.ReadAllText("Keystore.json"); - return JsonSerializer.Deserialize(text, new JsonSerializerOptions() - { - ReferenceHandler = ReferenceHandler.Preserve - }); - } - catch - { - return null; - } - } - // 登录方法 - public async Task Login() - { - #region bot实例化 - - var deviceInfo = GetDeviceInfo(); - var keyStore = LoadKeystore() ?? new BotKeystore(); - - Client = BotFactory.Create(new BotConfig - { - UseIPv6Network = false, - GetOptimumServer = true, - AutoReconnect = true, - Protocol = Protocols.Linux - }, deviceInfo, keyStore); - - #endregion - - // Log模式 - Client.Invoker.OnBotLogEvent += (_, @event) => - { - @event.Level.ChangeColorByTitle(); - Console.WriteLine(@event.ToString()); - }; - - // bot信息保存,但存在bug未修复 - Client.Invoker.OnBotOnlineEvent += (_, @event) => - { - Console.WriteLine(@event.ToString()); - SaveKeystore(Client.UpdateKeystore()); - }; - // 二维码生成,启动后在根目录下生成qr.png - var qrCode = await Client.FetchQrCode(); - if (qrCode != null) - { - await File.WriteAllBytesAsync("qr.png", qrCode.Value.QrCode); - await Client.LoginByQrCode(); - } - } -} \ No newline at end of file diff --git a/Program.cs b/Program.cs index 2108713..7116630 100644 --- a/Program.cs +++ b/Program.cs @@ -1,8 +1,4 @@ -using Debugger; -using Grpc.Core; -using Shrink.API; -using Shrink.Command; -using Shrink.Login; +using BotService = Shrink.Login.BotService; namespace Shrink; @@ -10,62 +6,6 @@ public static class Program { public static async Task Main() { - /*var originalAssemblyPath = "Lagrange.Core.dll"; - var tempAssemblyPath = "ModifiedExternalAssembly.dll"; - var oldUrl = "自己找"; - var newUrl = "自己找"; - - ModifyAssembly(originalAssemblyPath, tempAssemblyPath, oldUrl, newUrl);*/ - const int port = 50051; - - var server = new Server - { - Services = { BotService.BindService(new BotServiceImpl()) }, - Ports = { new ServerPort("localhost", port, ServerCredentials.Insecure) } - }; - - server.Start(); - - Console.WriteLine($"gRPC server listening on port {port}"); - - await QrCode.Instance.Login(); - await Commands.Instance.Init(); - await Commands.Instance.Run(); - //await server.ShutdownAsync(); + await BotService.Instance.Login(); } - /*private static void ModifyAssembly(string originalAssemblyPath, string tempAssemblyPath, string oldUrl, string newUrl) - { - var assembly = AssemblyDefinition.ReadAssembly(originalAssemblyPath); - var module = assembly.MainModule; - - // 查找LinuxSigner类型 - var linuxSignerType = module.Types.FirstOrDefault(t => t.Name == "LinuxSigner"); - if (linuxSignerType == null) - { - Console.WriteLine("无LinuxSigner类型"); - return; - } - - // 查找构造函数 - var constructor = linuxSignerType.Methods.FirstOrDefault(m => m.IsConstructor); - if (constructor == null) - { - Console.WriteLine("无构造函数"); - return; - } - - var ilProcessor = constructor.Body.GetILProcessor(); - foreach (var instruction in constructor.Body.Instructions) - { - // 检查是否是加载字符串操作 - if (instruction.OpCode == OpCodes.Ldstr && instruction.Operand is string str && str == oldUrl) - { - instruction.Operand = newUrl; // 替换为新URL - Console.WriteLine($"替换: {oldUrl}为{newUrl}"); - } - } - - assembly.Write(tempAssemblyPath); - Console.WriteLine($"已将修改后的程序集保存在{tempAssemblyPath}"); - }*/ } \ No newline at end of file