├── WkyFast
├── icon.ico
├── Assets
│ └── Images
│ │ ├── heart.png
│ │ ├── star.png
│ │ ├── github.png
│ │ ├── heart26.png
│ │ └── github30.png
├── FodyWeavers.xml
├── View
│ ├── Model
│ │ └── MainTabItemModel.cs
│ ├── Dialogs
│ │ ├── ExitDialog.xaml.cs
│ │ ├── ExitDialog.xaml
│ │ ├── LoginDialog.xaml.cs
│ │ ├── WindowAddTask.xaml
│ │ ├── LoginDialog.xaml
│ │ ├── WindowAddSubscription.xaml
│ │ ├── WindowAddSubscription.xaml.cs
│ │ └── WindowAddTask.xaml.cs
│ ├── View
│ │ ├── TaskListCellControl.xaml.cs
│ │ ├── ConfigListItemControl.xaml.cs
│ │ └── ConfigListItemControl.xaml
│ ├── WkyFastSettingView.xaml.cs
│ ├── WkyMainTabView.xaml.cs
│ ├── WkyTaskListView.xaml
│ ├── WkyMainTabView.xaml
│ ├── WkySubscriptionListView.xaml.cs
│ ├── Contver
│ │ └── DownloadSizeContver.cs
│ └── WkyFastSettingView.xaml
├── Utils
│ ├── TimeHelper.cs
│ ├── PathHelper.cs
│ ├── FileSizeContver.cs
│ ├── BrowserHelper.cs
│ ├── PushDeer.cs
│ ├── TaskHelper.cs
│ ├── ActionVersion.cs
│ ├── Win11Style.cs
│ ├── AESHelper.cs
│ ├── OSSManager.cs
│ ├── SimpleLogger.cs
│ └── VisibilityAnimation.cs
├── AssemblyInfo.cs
├── Service
│ ├── Model
│ │ ├── DownloadResult.cs
│ │ ├── BaseNotificationModel.cs
│ │ ├── TaskModel.cs
│ │ └── SubscriptionModel.cs
│ ├── EasyLogManager.cs
│ ├── ChatGptTranslatorManager.cs
│ ├── WkyUserManager.cs
│ ├── GAHelper.cs
│ └── AppConfig.cs
├── Style
│ ├── MetroFont.xaml
│ ├── BootstrapIcons-Github.xaml
│ ├── AQScrollBar.xaml
│ └── CustomProgressBar.xaml
├── App.xaml
├── MainWindowEvent.cs
├── App.xaml.cs
├── WkyFast.csproj
├── app.manifest
└── MainWindow.xaml
├── docs
└── images
│ ├── logo.png
│ ├── wkyfast.png
│ ├── wkyfast1.png
│ └── wkyfast2.png
├── .gitmodules
├── WkyFast.UI.Test
├── MainWindowViewModel.cs
├── AssemblyInfo.cs
├── WkyFast.UI.Test.csproj
├── App.xaml
├── App.xaml.cs
├── MainWindow.xaml
└── MainWindow.xaml.cs
├── README.md
├── WkyFast.sln
├── .github
└── workflows
│ └── dotnet-desktop.yml
├── .gitattributes
└── .gitignore
/WkyFast/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/WkyFast/icon.ico
--------------------------------------------------------------------------------
/docs/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/docs/images/logo.png
--------------------------------------------------------------------------------
/docs/images/wkyfast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/docs/images/wkyfast.png
--------------------------------------------------------------------------------
/docs/images/wkyfast1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/docs/images/wkyfast1.png
--------------------------------------------------------------------------------
/docs/images/wkyfast2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/docs/images/wkyfast2.png
--------------------------------------------------------------------------------
/WkyFast/Assets/Images/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/WkyFast/Assets/Images/heart.png
--------------------------------------------------------------------------------
/WkyFast/Assets/Images/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/WkyFast/Assets/Images/star.png
--------------------------------------------------------------------------------
/WkyFast/Assets/Images/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/WkyFast/Assets/Images/github.png
--------------------------------------------------------------------------------
/WkyFast/Assets/Images/heart26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/WkyFast/Assets/Images/heart26.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "WkyApiSharp"]
2 | path = WkyApiSharp
3 | url = https://github.com/aiqinxuancai/WkyApiSharp.git
4 |
--------------------------------------------------------------------------------
/WkyFast/Assets/Images/github30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiqinxuancai/WkyFast/HEAD/WkyFast/Assets/Images/github30.png
--------------------------------------------------------------------------------
/WkyFast/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/WkyFast.UI.Test/MainWindowViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace WkyFast.UI.Test
4 | {
5 | public class MainWindowViewModel
6 | {
7 | public MainWindowViewModel(IServiceProvider serviceProvider)
8 | {
9 |
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/WkyFast/View/Model/MainTabItemModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WkyFast.View.Model
8 | {
9 |
10 | public enum MainTabItemModelType
11 | {
12 | DownloadList,
13 | SubscriptionList,
14 | }
15 |
16 | public class MainTabItemModel
17 | {
18 | public string Title {set; get;}
19 |
20 | public MainTabItemModelType Type { set; get; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/WkyFast/Utils/TimeHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WkyFast.Utils
8 | {
9 | class TimeHelper
10 | {
11 |
12 | public static string SecondsToFormatString(int seconds)
13 | {
14 | TimeSpan ts = new TimeSpan(0, 0, seconds);
15 | string r = string.Format("{0:D2}:{1:D2}:{2:D2}", ts.Hours, ts.Minutes, ts.Seconds);
16 | return r;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/WkyFast/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/WkyFast.UI.Test/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/WkyFast.UI.Test/WkyFast.UI.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net8.0-windows
6 | enable
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/WkyFast/View/Dialogs/ExitDialog.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 |
15 | namespace WkyFast.View.Dialogs
16 | {
17 | ///
18 | /// ExitDialog.xaml 的交互逻辑
19 | ///
20 | public partial class ExitDialog : Window
21 | {
22 | public ExitDialog()
23 | {
24 | InitializeComponent();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/WkyFast/Utils/PathHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace WkyFast.Utils
9 | {
10 | internal class PathHelper
11 | {
12 | public static string RemoveInvalidChars(string input)
13 | {
14 | var invalidFileNameChars = Path.GetInvalidFileNameChars();
15 | var invalidPathChars = Path.GetInvalidPathChars();
16 |
17 | foreach (var c in invalidFileNameChars.Union(invalidPathChars).Distinct())
18 | {
19 | input = input.Replace(c.ToString(), "");
20 | }
21 |
22 | return input;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/WkyFast.UI.Test/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/WkyFast/Service/Model/DownloadResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using WkyApiSharp.Service.Model.BtCheck;
7 | using WkyApiSharp.Service.Model.CreateTaskResult;
8 |
9 | namespace WkyFast.Service.Model
10 | {
11 | public class WkyDownloadResult
12 | {
13 | //返回值非0或网络请求有异常
14 | public bool hasError { get; set; }
15 |
16 | //总量
17 | public int AllTaskCount { get; set; }
18 |
19 | //成功添加的数量
20 | public int SuccessCount { get; set; }
21 |
22 | //已经存在的数量
23 | public int DuplicateAddTaskCount { get; set; }
24 |
25 |
26 | public WkyApiCreateTaskResultModel Result { get; set; }
27 |
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/WkyFast/View/View/TaskListCellControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace WkyFast.View.View
17 | {
18 | ///
19 | /// ConfigListItemControl.xaml 的交互逻辑
20 | ///
21 | public partial class TaskListCellControl : UserControl
22 | {
23 | public TaskListCellControl()
24 | {
25 | InitializeComponent();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/WkyFast/View/View/ConfigListItemControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace WkyFast.View.View
17 | {
18 | ///
19 | /// ConfigListItemControl.xaml 的交互逻辑
20 | ///
21 | public partial class ConfigListItemControl : UserControl
22 | {
23 | public ConfigListItemControl()
24 | {
25 | InitializeComponent();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/WkyFast/Service/Model/BaseNotificationModel.cs:
--------------------------------------------------------------------------------
1 | using PropertyChanged;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Linq;
6 | using System.Runtime.CompilerServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace WkyFast.Service.Model
11 | {
12 | [AddINotifyPropertyChangedInterface]
13 | public class BaseNotificationModel : INotifyPropertyChanged
14 | {
15 | public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
16 |
17 | public void OnPropertyChanged([CallerMemberName] string PropertyName = "")
18 | {
19 | PropertyChangedEventArgs propertyChangedEventArgs = new PropertyChangedEventArgs(PropertyName);
20 | PropertyChanged(this, propertyChangedEventArgs);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/WkyFast/Utils/FileSizeContver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WkyFast.Utils
8 | {
9 | internal class FileSizeContver
10 | {
11 | public static string GetSizeString(long size)
12 | {
13 | string strSize = "";
14 | long FactSize = size;
15 | if (FactSize < 1024.00)
16 | strSize = FactSize.ToString("F2") + "B";
17 | else if (FactSize >= 1024.00 && FactSize < 1048576)
18 | strSize = (FactSize / 1024.00).ToString("F2") + "K";
19 | else if (FactSize >= 1048576 && FactSize < 1073741824)
20 | strSize = (FactSize / 1024.00 / 1024.00).ToString("F2") + "M";
21 | else if (FactSize >= 1073741824)
22 | strSize = (FactSize / 1024.00 / 1024.00 / 1024.00).ToString("F2") + "G";
23 | return strSize;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
8 |
9 |
WkyFast
10 |
11 |
12 |
13 |
14 |
15 |
16 | 简易玩客云PC客户端,支持批量任务添加和订阅下载
17 |
18 |
19 | ## ⚠️注意⚠️
20 | **在玩客云在2024年2月29日停止运营,但我开发了新的项目,基于Aria2的订阅下载工具:**
21 | [Aria2Fast](https://github.com/aiqinxuancai/Aria2Fast)
22 |
23 | 欢迎使用新工具!
24 |
25 | #### 2024/03/05 10:24
26 | 不行了,**真的连不上了**,不用试了,换Aria2Fast吧
27 |
28 | #### 2024/03/04 12:00
29 | 好像不退出登录还能用
30 |
31 | ---
32 |
33 |
34 |
35 | ## 功能
36 |
37 |
38 |
39 |
40 | 注:关键字可使用|来表示或
41 |
42 |
--------------------------------------------------------------------------------
/WkyFast/View/Dialogs/ExitDialog.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/WkyFast/Utils/BrowserHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using System.Diagnostics;
3 |
4 | namespace WkyFast.Utils
5 | {
6 | class BrowserHelper
7 | {
8 |
9 | //public static void OpenUrlBrowser(string _url)
10 | //{
11 | // Process.Start(_url);
12 | //}
13 |
14 | public static void OpenUrlBrowser(string url)
15 | {
16 | try
17 | {
18 | Process.Start(url);
19 | }
20 | catch
21 | {
22 | // hack because of this: https://github.com/dotnet/corefx/issues/10361
23 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
24 | {
25 | url = url.Replace("&", "^&");
26 | Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });
27 | }
28 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
29 | {
30 | Process.Start("xdg-open", url);
31 | }
32 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
33 | {
34 | Process.Start("open", url);
35 | }
36 | else
37 | {
38 | throw;
39 | }
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/WkyFast/Utils/PushDeer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using WkyFast.Service;
8 |
9 | namespace WkyFast.Utils
10 | {
11 | internal class PushDeer
12 | {
13 |
14 | public static async Task SendPushDeer(string title, string msg = "")
15 | {
16 |
17 | if (string.IsNullOrEmpty(msg) || string.IsNullOrEmpty(AppConfig.Instance.ConfigData.PushDeerKey))
18 | {
19 | return;
20 | }
21 |
22 | Console.WriteLine($"SendPushDeer {msg}");
23 |
24 |
25 | HttpClient client = new HttpClient();
26 |
27 | try
28 | {
29 | var url = "https://api2.pushdeer.com/message/push";
30 |
31 | var postData = new FormUrlEncodedContent(new Dictionary()
32 | {
33 | {"pushkey" , AppConfig.Instance.ConfigData.PushDeerKey },
34 | {"text" , title },
35 | {"desp" , msg },
36 | });
37 |
38 | var ret = await client.PostAsync(url, postData);
39 |
40 | ret.EnsureSuccessStatusCode();
41 | Console.WriteLine(await ret.Content.ReadAsStringAsync());
42 | }
43 | catch (Exception ex)
44 | {
45 | Console.WriteLine(ex);
46 | }
47 |
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/WkyFast/Style/MetroFont.xaml:
--------------------------------------------------------------------------------
1 |
3 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
4 | Microsoft Yahei UI,Segoe UI Light, Lucida Sans Unicode, Verdana
5 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
6 | Microsoft Yahei UI,Segoe UI Semibold, Segoe UI, Lucida Sans Unicode, Verdana
7 | Microsoft Yahei UI,Segoe UI Semibold, Segoe UI, Lucida Sans Unicode, Verdana
8 |
9 |
10 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
11 | Microsoft Yahei UI,Segoe UI Light, Lucida Sans Unicode, Verdana
12 | Microsoft Yahei UI,Segoe UI Light, Lucida Sans Unicode, Verdana
13 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
14 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
15 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
16 |
17 |
--------------------------------------------------------------------------------
/WkyFast/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
25 | Microsoft Yahei UI,Segoe UI, Lucida Sans Unicode, Verdana
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/WkyFast/Utils/TaskHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace WkyFast.Utils
10 | {
11 |
12 | public class TaskHelper
13 | {
14 |
15 | public static void Sleep(int millisecondsToWait )
16 | {
17 | Stopwatch stopwatch = Stopwatch.StartNew();
18 | while (true)
19 | {
20 | if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
21 | {
22 | break;
23 | }
24 | Thread.Sleep(1);
25 | }
26 | }
27 |
28 | public static void Sleep(int millisecondsToWait, int millisecondsTocycle)
29 | {
30 | Stopwatch stopwatch = Stopwatch.StartNew();
31 | while (true)
32 | {
33 | if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
34 | {
35 | break;
36 | }
37 | Thread.Sleep(millisecondsTocycle);
38 | }
39 | }
40 |
41 |
42 | public static void Sleep(int millisecondsToWait, int millisecondsTocycle, CancellationToken cancellationToken)
43 | {
44 | Stopwatch stopwatch = Stopwatch.StartNew();
45 | while (true)
46 | {
47 | if (cancellationToken.IsCancellationRequested)
48 | {
49 | break;
50 | }
51 |
52 | if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
53 | {
54 | break;
55 | }
56 |
57 | Thread.Sleep(millisecondsTocycle);
58 |
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/WkyFast/MainWindowEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using Wpf.Ui.Common;
8 |
9 | namespace WkyFast
10 | {
11 | public partial class MainWindow
12 | {
13 | //注册事件,用于弹出提示等操作
14 |
15 | private Action _messageBoxLeft;
16 | private Action _messageBoxRight;
17 |
18 |
19 | public void ShowMessageBox(string title, string message, Action leftClick, Action rightClick, string buttonLeftName = "Yes", string buttonRightName = "No")
20 | {
21 | this.RootDialog.ButtonLeftName = buttonLeftName;
22 | this.RootDialog.ButtonRightName = buttonRightName;
23 | _messageBoxLeft = leftClick;
24 | _messageBoxRight = rightClick;
25 | this.RootDialog.ButtonLeftClick -= RootDialog_ButtonLeftClick;
26 | this.RootDialog.ButtonRightClick -= RootDialog_ButtonRightClick;
27 | this.RootDialog.ButtonLeftClick += RootDialog_ButtonLeftClick;
28 | this.RootDialog.ButtonRightClick += RootDialog_ButtonRightClick;
29 | this.RootDialog.Show(title, message);
30 | }
31 |
32 | private void RootDialog_ButtonRightClick(object sender, RoutedEventArgs e)
33 | {
34 | _messageBoxRight();
35 | this.RootDialog.Hide();
36 | }
37 |
38 | private void RootDialog_ButtonLeftClick(object sender, System.Windows.RoutedEventArgs e)
39 | {
40 | _messageBoxLeft();
41 | this.RootDialog.Hide();
42 | }
43 |
44 |
45 | ///
46 | /// 展示提示类
47 | ///
48 | public void ShowSnackbar(string title, string message, SymbolRegular icon = SymbolRegular.Info24)
49 | {
50 | this.RootSnackbar.Show(title, message, icon);
51 | }
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/WkyFast/Utils/ActionVersion.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Flurl.Http;
8 | using Newtonsoft.Json.Linq;
9 |
10 | namespace WkyFast.Utils
11 | {
12 | public class ActionVersion
13 | {
14 | //版本号完整样例
15 | //v0.1.1.33
16 | public const string Version = "{VERSION}";
17 |
18 | public const string Build = "{BUILD}";
19 |
20 | public const string Url = "https://api.github.com/repos/aiqinxuancai/WkyFast/releases/latest";
21 |
22 |
23 | //检测最后的build,如果不符合,则
24 | public static string NowGithubVersion { set; get; } = "";
25 |
26 | public static bool HasNewVersion { set; get; }
27 |
28 | public static async Task CheckVersion ()
29 | {
30 | try
31 | {
32 |
33 | var result = await Url.WithTimeout(20)
34 | .WithHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36")
35 | .GetStringAsync();
36 |
37 | if (!string.IsNullOrWhiteSpace(result))
38 | {
39 | JObject root = JObject.Parse(result);
40 | if (root.ContainsKey("tag_name"))
41 | {
42 | string tagName = root["tag_name"].ToString();
43 |
44 | NowGithubVersion = tagName;
45 |
46 | if (Version != tagName)
47 | {
48 | //新版本
49 | HasNewVersion = true;
50 | }
51 |
52 | }
53 |
54 |
55 | }
56 | }
57 | catch (Exception ex)
58 | {
59 | Debug.WriteLine(ex);
60 | }
61 |
62 |
63 | }
64 |
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/WkyFast.UI.Test/App.xaml.cs:
--------------------------------------------------------------------------------
1 | global using Microsoft.Extensions.Configuration;
2 | global using Microsoft.Extensions.DependencyInjection;
3 | global using Microsoft.Extensions.Hosting;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Configuration;
7 | using System.Data;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using Wpf.Ui;
12 |
13 | namespace WkyFast.UI.Test
14 | {
15 | ///
16 | /// Interaction logic for App.xaml
17 | ///
18 | public partial class App : Application
19 | {
20 |
21 | private static readonly IHost _host = Host.CreateDefaultBuilder()
22 | .ConfigureAppConfiguration(c =>
23 | {
24 | c.SetBasePath(AppContext.BaseDirectory);
25 | })
26 | .ConfigureServices(
27 | (context, services) =>
28 | {
29 | // App Host
30 | //services.AddHostedService();
31 |
32 | // Main window container with navigation
33 | // services.AddSingleton();
34 | services.AddSingleton();
35 | services.AddSingleton();
36 | services.AddSingleton();
37 | services.AddSingleton();
38 | //services.AddSingleton();
39 | }
40 | )
41 | .Build();
42 |
43 | ///
44 | /// Gets registered service.
45 | ///
46 | /// Type of the service to get.
47 | /// Instance of the service or .
48 | public static T? GetService() where T : class
49 | {
50 | return _host.Services.GetService(typeof(T)) as T ?? null;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/WkyFast/Utils/Win11Style.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace WkyFast.Utils
9 | {
10 | public class Win11Style
11 | {
12 | // The enum flag for DwmSetWindowAttribute's second parameter, which tells the function what attribute to set.
13 | public enum DWMWINDOWATTRIBUTE
14 | {
15 | DWMWA_WINDOW_CORNER_PREFERENCE = 33
16 | }
17 |
18 | // The DWM_WINDOW_CORNER_PREFERENCE enum for DwmSetWindowAttribute's third parameter, which tells the function
19 | // what value of the enum to set.
20 | public enum DWM_WINDOW_CORNER_PREFERENCE
21 | {
22 | DWMWCP_DEFAULT = 0,
23 | DWMWCP_DONOTROUND = 1,
24 | DWMWCP_ROUND = 2,
25 | DWMWCP_ROUNDSMALL = 3
26 | }
27 |
28 | // Import dwmapi.dll and define DwmSetWindowAttribute in C# corresponding to the native function.
29 |
30 |
31 |
32 | [DllImport("dwmapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
33 | private static extern long DwmSetWindowAttribute(IntPtr hwnd,
34 | DWMWINDOWATTRIBUTE attribute,
35 | ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute,
36 | uint cbAttribute);
37 |
38 | public static void LoadWin11Style(IntPtr hWnd)
39 | {
40 | //win11
41 | if (System.Environment.OSVersion.Version.Major >= 10.0 && System.Environment.OSVersion.Version.Build >= 22000)
42 | {
43 | //IntPtr hWnd = new WindowInteropHelper(GetWindow(this)).EnsureHandle();
44 | var attribute = DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE;
45 | var preference = DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND;
46 | DwmSetWindowAttribute(hWnd, attribute, ref preference, sizeof(uint));
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/WkyFast/Service/EasyLogManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Threading;
7 | using System.IO;
8 | using System.Diagnostics;
9 | using WkyFast.Utils;
10 | using System.Diagnostics.Eventing.Reader;
11 |
12 | namespace WkyFast.Service
13 | {
14 | public class EasyLogManager
15 | {
16 | private static string _logFilename = "";
17 |
18 | public static SimpleLogger Logger { set; get; }
19 |
20 | ///
21 | /// 如果日志大于10M则清除
22 | ///
23 | static EasyLogManager ()
24 | {
25 | string machineName = Environment.MachineName;
26 | if (!string.IsNullOrWhiteSpace(machineName))
27 | {
28 | _logFilename = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + "-" + machineName + ".log";
29 | }
30 | else
31 | {
32 | _logFilename = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".log";
33 | }
34 |
35 |
36 | if (File.Exists(_logFilename))
37 | {
38 | FileInfo finfo = new FileInfo(_logFilename);
39 | if (!finfo.Exists)
40 | {
41 | FileStream fs = File.Create(_logFilename);
42 | fs.Close();
43 | }
44 | else
45 | {
46 | try
47 | {
48 | if (finfo.Length > 1024 * 1024 * 20)
49 | {
50 | File.Delete(_logFilename);
51 | FileStream fs = File.Create(_logFilename);
52 | fs.Close();
53 | }
54 | }
55 | catch (Exception ex)
56 | {
57 | Debug.WriteLine(ex);
58 | }
59 | }
60 | }
61 |
62 | Logger = new SimpleLogger();
63 |
64 |
65 | }
66 |
67 |
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/WkyFast.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31903.59
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WkyFast", "WkyFast\WkyFast.csproj", "{93542562-AD8C-49B3-BAFA-2721E6200282}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WkyApiSharp", "WkyApiSharp\WkyApiSharp\WkyApiSharp.csproj", "{A107AFD1-7B3F-467A-A86B-EF8750347559}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WkyFast.UI.Test", "WkyFast.UI.Test\WkyFast.UI.Test.csproj", "{274BB079-3656-4645-8602-CF79E7811317}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {93542562-AD8C-49B3-BAFA-2721E6200282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {93542562-AD8C-49B3-BAFA-2721E6200282}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {93542562-AD8C-49B3-BAFA-2721E6200282}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {93542562-AD8C-49B3-BAFA-2721E6200282}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {A107AFD1-7B3F-467A-A86B-EF8750347559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {A107AFD1-7B3F-467A-A86B-EF8750347559}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {A107AFD1-7B3F-467A-A86B-EF8750347559}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {A107AFD1-7B3F-467A-A86B-EF8750347559}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {274BB079-3656-4645-8602-CF79E7811317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {274BB079-3656-4645-8602-CF79E7811317}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {274BB079-3656-4645-8602-CF79E7811317}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {274BB079-3656-4645-8602-CF79E7811317}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {33AB0C0F-8230-4F25-96A5-6786F345E537}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet-desktop.yml:
--------------------------------------------------------------------------------
1 | name: .NET Core Desktop
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | build:
10 | runs-on: windows-latest
11 | name: Dotnet Build
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 | with:
16 | submodules: true
17 | - name: Setup dotnet
18 | uses: actions/setup-dotnet@v1
19 | with:
20 | dotnet-version: '8.0.x'
21 | - name: Echo tag
22 | run: echo The tag is ${{ github.event.inputs.tag }}
23 | - name: Clean
24 | run: dotnet clean $env:GITHUB_WORKSPACE\WkyFast.sln --configuration Release && dotnet nuget locals all --clear
25 | - name: Restore dependencies
26 | run: dotnet restore
27 | - name: Set Version
28 | run: powershell -Command "(gc $env:GITHUB_WORKSPACE\WkyFast\Utils\ActionVersion.cs) -replace '{VERSION}', '$env:GITHUB_REF_NAME' | Out-File $env:GITHUB_WORKSPACE\WkyFast\Utils\ActionVersion.cs"
29 | - name: Set Build
30 | run: powershell -Command "(gc $env:GITHUB_WORKSPACE\WkyFast\Utils\ActionVersion.cs) -replace '{BUILD}', '$env:GITHUB_RUN_NUMBER' | Out-File $env:GITHUB_WORKSPACE\WkyFast\Utils\ActionVersion.cs"
31 | - name: Build
32 | run: dotnet build --no-restore
33 | - name: Test
34 | run: dotnet test --no-build --verbosity normal
35 | - name: Publish
36 | run: dotnet publish -c Release -r win-x64 --self-contained=true
37 | - run: powershell curl https://github.com/aiqinxuancai/DotNetDllPathPatcherWPF/releases/download/v0.0.15/DotNetDllPathPatcherCMD.zip -o DotNetDllPathPatcherCMD.zip
38 | - run: powershell Expand-Archive -Path .\DotNetDllPathPatcherCMD.zip -DestinationPath .\DotNetDllPathPatcherCMD
39 | - run: powershell .\DotNetDllPathPatcherCMD\publish\DotNetDllPathPatcherCMD.exe $env:GITHUB_WORKSPACE\WkyFast\bin\Release\net8.0-windows\win-x64\publish\WkyFast.exe
40 | - name: Compress
41 | run: powershell Compress-Archive -Path $env:GITHUB_WORKSPACE\WkyFast\bin\Release\net8.0-windows\win-x64\publish -DestinationPath .\WkyFast.zip
42 | - name: Create a Release
43 | uses: ncipollo/release-action@v1
44 | with:
45 | artifacts: "WkyFast.zip"
46 | token: ${{ secrets.GITHUB_TOKEN }}
47 |
--------------------------------------------------------------------------------
/WkyFast.UI.Test/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
37 |
38 |
39 |
40 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/WkyFast/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 | using System.Data;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 | using System.Windows;
10 | using System.Windows.Media;
11 | using WkyFast.Service;
12 | using WkyFast.Utils;
13 |
14 | namespace WkyFast
15 | {
16 | ///
17 | /// Interaction logic for App.xaml
18 | ///
19 | public partial class App : Application
20 | {
21 | static App()
22 | {
23 | TimeHelper.SecondsToFormatString(99);
24 |
25 | TextOptions.TextFormattingModeProperty.OverrideMetadata(typeof(Window),
26 | new FrameworkPropertyMetadata(TextFormattingMode.Display, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits));
27 | }
28 | public static void ExitWkyFast()
29 | {
30 | if (WkyFast.MainWindow.Instance != null)
31 | {
32 | WkyFast.MainWindow.Instance.Close();
33 | }
34 | App.Current.Shutdown();
35 | }
36 |
37 |
38 | App()
39 | {
40 | //TODO 检查多开
41 |
42 |
43 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
44 | DispatcherUnhandledException += Current_DispatcherUnhandledException;
45 | }
46 |
47 |
48 | void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
49 | {
50 | Exception ex = (Exception)e.ExceptionObject;
51 | EasyLogManager.Logger.Error(ex);
52 | MessageBox.Show(ex?.Message + Environment.NewLine + ex?.InnerException?.ToString(), "Error#1", MessageBoxButton.OK, MessageBoxImage.Information);
53 | }
54 |
55 | void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
56 | {
57 | EasyLogManager.Logger.Error(e.Exception);
58 | MessageBox.Show(e?.Exception?.Message + Environment.NewLine + e?.Exception?.InnerException?.ToString(), "Error#2", MessageBoxButton.OK, MessageBoxImage.Information);
59 | e.Handled = true;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/WkyFast/Service/Model/TaskModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Xml.Linq;
7 |
8 | namespace WkyFast.Service.Model
9 | {
10 |
11 |
12 | public class TaskModel : BaseNotificationModel
13 | {
14 | //获取展示用的名字
15 |
16 | public bool FromSubscription
17 | {
18 | get
19 | {
20 | return SubscriptionManager.Instance.TaskUrlToSubscriptionName.ContainsKey(Data.Url);
21 | }
22 |
23 | }
24 |
25 | ///
26 | /// 绑定的是此代码来显示名字
27 | ///
28 | public string ShowName {
29 | get
30 | {
31 | if (FromSubscription)
32 | {
33 | if (SubscriptionManager.Instance.TaskUrlToSubscriptionName.ContainsKey(Data.Url))
34 | {
35 | var name = (string)SubscriptionManager.Instance.TaskUrlToSubscriptionName[Data.Url];
36 | if (!string.IsNullOrWhiteSpace(name))
37 | {
38 | return name;
39 | }
40 | }
41 | return Data.Name;
42 |
43 | }
44 | else
45 | {
46 | return Data.Name;
47 | }
48 |
49 |
50 | }
51 | }
52 |
53 | public string SubscriptionName
54 | {
55 | get
56 | {
57 | if (FromSubscription)
58 | {
59 | if (SubscriptionManager.Instance.TaskUrlToSubscriptionName.ContainsKey(Data.Name))
60 | {
61 | var name = (string)SubscriptionManager.Instance.TaskUrlToSubscriptionName[Data.Name];
62 | if (!string.IsNullOrWhiteSpace(name))
63 | {
64 | return name;
65 | }
66 | }
67 | return Data.Name;
68 |
69 | }
70 | else
71 | {
72 | return Data.Name;
73 | }
74 |
75 |
76 | }
77 | }
78 |
79 | public WkyApiSharp.Service.Model.RemoteDownloadList.Task Data { get; set; }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/WkyFast/Style/BootstrapIcons-Github.xaml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
--------------------------------------------------------------------------------
/WkyFast/WkyFast.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net8.0-windows
6 | enable
7 | true
8 | icon.ico
9 | app.manifest
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | Code
50 |
51 |
52 |
53 |
54 |
55 | $(DefaultXamlRuntime)
56 |
57 |
58 | $(DefaultXamlRuntime)
59 | Designer
60 |
61 |
62 | $(DefaultXamlRuntime)
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/WkyFast/View/View/ConfigListItemControl.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
32 |
33 |
39 |
40 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/WkyFast/Service/ChatGptTranslatorManager.cs:
--------------------------------------------------------------------------------
1 |
2 | using ChatGPTSharp;
3 | using Flurl.Http;
4 | using Newtonsoft.Json;
5 | using Newtonsoft.Json.Linq;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Diagnostics;
9 | using System.Linq;
10 | using System.Reflection;
11 | using System.Text;
12 | using System.Text.Json.Nodes;
13 | using System.Threading.Tasks;
14 | using WkyFast.Utils;
15 |
16 | namespace WkyFast.Service
17 | {
18 | internal class ChatGPTTranslatorManager
19 | {
20 | const string kSystemMessage = """
21 | 请从我提供的内容中告诉我这个作品的名称,请返回如下JSON格式:
22 | { "title": }
23 | 请注意:
24 | 1.不要添加解释。
25 | 2.内容中可能包含多种语言的作品名称,通常可能会使用符号/进行分割,请返回第一种语言名称。
26 | 3.请避免将字幕组名称及字幕名称等识别为标题。
27 | 4.不要对作品名称进行删减或翻译以及字符的转换。
28 | 5.作品名称不会包含包含[]【】等符号。
29 | 以下为内容:
30 |
31 | """;
32 |
33 | static Dictionary _cache = new Dictionary();
34 |
35 | ///
36 | /// 完整调用一次提取episode
37 | ///
38 | ///
39 | ///
40 | public static async Task GetEpisode(string s)
41 | {
42 | var client = new ChatGPTClient(AppConfig.Instance.ConfigData.OpenAIKey, timeoutSeconds: 60, proxyUri: AppConfig.Instance.ConfigData.OpenAIProxy);
43 |
44 | if (!string.IsNullOrEmpty(AppConfig.Instance.ConfigData.OpenAIHost))
45 | {
46 | client.Settings.OpenAIAPIBaseUri = AppConfig.Instance.ConfigData.OpenAIHost;
47 | }
48 |
49 | if (client != null)
50 | {
51 | try
52 | {
53 | s = $"{kSystemMessage}{s}";
54 |
55 | if (_cache.TryGetValue(s, out var r))
56 | {
57 | return r;
58 | }
59 |
60 | var result = await client.SendMessage(s);
61 |
62 | if (!string.IsNullOrEmpty(result.Response))
63 | {
64 | JObject root = JObject.Parse(result.Response);
65 | var title = (string)root["title"];
66 |
67 | //if (title.Contains("/"))
68 | //{
69 | // title.Split("/");
70 | //}
71 |
72 |
73 | _cache[s] = title;
74 | return title;
75 | }
76 |
77 | return string.Empty;
78 | }
79 | catch (Exception ex)
80 | {
81 | EasyLogManager.Logger.Error(ex.ToString());
82 | }
83 | }
84 | return string.Empty;
85 | }
86 |
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/WkyFast/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
54 |
55 |
56 |
57 | PerMonitorV2
58 | true
59 | true
60 |
61 |
62 |
63 |
64 |
65 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/WkyFast/View/WkyFastSettingView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reactive.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Navigation;
15 | using System.Windows.Shapes;
16 | using WkyApiSharp.Events.Account;
17 | using WkyFast.Service;
18 | using WkyFast.Utils;
19 |
20 | namespace WkyFast.View
21 | {
22 | ///
23 | /// WkyFastSetting.xaml 的交互逻辑
24 | ///
25 | public partial class WkyFastSettingView : Page
26 | {
27 | public WkyFastSettingView()
28 | {
29 | InitializeComponent();
30 |
31 | AccountTextBlock.Text = WkyApiManager.Instance.API.User;
32 |
33 | WkyApiManager.Instance.API.EventReceived
34 | .OfType()
35 | .Subscribe(async r =>
36 | {
37 | AccountTextBlock.Text = r.Account;
38 | });
39 |
40 |
41 |
42 | #if DEBUG
43 | TestTurnServerPanel.Visibility = Visibility.Visible;
44 | #endif
45 |
46 | }
47 |
48 | private void AccountCardAction_Click(object sender, RoutedEventArgs e)
49 | {
50 | //询问登出
51 | //if (MessageBox.Show("是否登出账号?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
52 | //{
53 | //}
54 |
55 | MainWindow.Instance.ShowMessageBox("提示", "是否登出账号?", () => {
56 | MainWindow.Instance.ReLoginFunc();
57 | this.AccountTextBlock.Text = "-";
58 | }, () => {
59 | //没有操作
60 | });
61 | }
62 |
63 | public void OnLoginResult(LoginResultEvent e)
64 | {
65 | if (e.IsSuccess)
66 | {
67 | this.AccountTextBlock.Text = e.Account;
68 | }
69 | }
70 |
71 | private void BadgeNewVersion_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
72 | {
73 | //跳转至最新
74 | BrowserHelper.OpenUrlBrowser("https://github.com/aiqinxuancai/WkyFast/releases/latest");
75 | }
76 |
77 | private async void TestTurnServerButton_Click(object sender, RoutedEventArgs e)
78 | {
79 | await WkyApiManager.Instance.API.GetTurnServer(WkyApiManager.Instance.NowDevice.Device.DeviceSn);
80 | }
81 |
82 | private async void LinkAIKEY_Click(object sender, RoutedEventArgs e)
83 | {
84 | BrowserHelper.OpenUrlBrowser("https://aikey.one/register?aff=qHFBWX");
85 | }
86 |
87 | private async void LinkAPI2D_Click(object sender, RoutedEventArgs e)
88 | {
89 | BrowserHelper.OpenUrlBrowser("https://api2d.com/r/211572");
90 | }
91 |
92 | private void HomePageTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
93 | {
94 | BrowserHelper.OpenUrlBrowser("https://github.com/aiqinxuancai/WkyFast");
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/WkyFast/Utils/AESHelper.cs:
--------------------------------------------------------------------------------
1 | using Org.BouncyCastle.Crypto;
2 | using Org.BouncyCastle.Crypto.Engines;
3 | using Org.BouncyCastle.Crypto.Generators;
4 | using Org.BouncyCastle.Crypto.Parameters;
5 | using Org.BouncyCastle.Security;
6 | using Org.BouncyCastle.X509;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Security.Cryptography;
10 | using System.Text;
11 |
12 | namespace WkyFast.Utils
13 | {
14 | public class AESHelper
15 | {
16 | IBufferedCipher aesCipher = null;
17 | ICipherParameters cipherParameters;
18 | UTF8Encoding Byte_Transform = new UTF8Encoding();
19 |
20 |
21 | public AESHelper()
22 | {
23 | AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
24 | }
25 |
26 | // private static int AES_KEY_SIZE = 128 ;
27 | // private static int IV_SIZE = 16;
28 |
29 | ///
30 | /// 加密
31 | ///
32 | ///
33 | public static string AesEncode(string text, string key, string iv)
34 | {
35 | AESHelper helper = new AESHelper();
36 | helper.InitAESCodec(key, iv);
37 | return helper.AesEncode(text);
38 | }
39 |
40 | ///
41 | /// 解密
42 | ///
43 | ///
44 | ///
45 | ///
46 | ///
47 | public static string AesDecode(string base64, string key, string iv)
48 | {
49 | AESHelper helper = new AESHelper();
50 | helper.InitAESCodec(key, iv);
51 | return helper.AesDecode(base64);
52 | }
53 |
54 |
55 | public void InitAESCodec(string messageKey, string ivText)
56 | {
57 | //byte[] messageKeyArray = System.Convert.FromBase64String(messageKey);
58 | //byte[] ivTextArray = System.Convert.FromBase64String(ivText);
59 |
60 | byte[] messageKeyArray = Encoding.UTF8.GetBytes(messageKey);
61 | byte[] ivTextArray = Encoding.UTF8.GetBytes(ivText);
62 |
63 | aesCipher = CipherUtilities.GetCipher("AES/CTR/NoPadding");
64 | KeyParameter keyParameter = ParameterUtilities.CreateKeyParameter("AES", messageKeyArray);
65 | cipherParameters = new ParametersWithIV(keyParameter, ivTextArray, 0, 16);
66 |
67 | }
68 |
69 | public string AesEncode(string plainText)
70 | {
71 | byte[] plainBytes = Byte_Transform.GetBytes(plainText);
72 | byte[] outputBytes = new byte[aesCipher.GetOutputSize(plainBytes.Length)];
73 | aesCipher.Reset();
74 | aesCipher.Init(true, cipherParameters);
75 | int length = aesCipher.ProcessBytes(plainBytes, outputBytes, 0);
76 | aesCipher.DoFinal(outputBytes, length); //Do the final block
77 | return Convert.ToBase64String(outputBytes);
78 | }
79 |
80 | public string AesDecode(string cipherText)
81 | {
82 | byte[] encryptBytes = System.Convert.FromBase64String(cipherText);
83 | byte[] comparisonBytes = new byte[aesCipher.GetOutputSize(encryptBytes.Length)];
84 |
85 | aesCipher.Reset();
86 | aesCipher.Init(false, cipherParameters);
87 | int length = aesCipher.ProcessBytes(encryptBytes, comparisonBytes, 0);
88 | aesCipher.DoFinal(comparisonBytes, length); //Do the final block
89 |
90 | return Encoding.UTF8.GetString(comparisonBytes);
91 | }
92 |
93 | }
94 | }
--------------------------------------------------------------------------------
/WkyFast/Service/WkyUserManager.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using WkyFast.Utils;
10 |
11 | namespace WkyFast.Service
12 | {
13 | ///
14 | /// 账户的配置
15 | ///
16 | public class WkyUserManager
17 | {
18 | private static WkyUserManager instance = new WkyUserManager();
19 |
20 | public static WkyUserManager Instance
21 | {
22 | get
23 | {
24 | return instance;
25 | }
26 | }
27 |
28 | private const string kConfigPath = @".\UserConfig.json";
29 |
30 | private const string kAesKey = @"T7v5Te7hbq5kukbB";
31 |
32 | private const string kAesIv = @"vBKdjmGzHRgvghByH7zzXdHhNx44QoNh";
33 |
34 |
35 | ///
36 | /// 勾选保存密码后并且登录成功保存
37 | ///
38 | ///
39 | ///
40 | public void SavePassword(string mail, string password, bool autoLogin)
41 | {
42 | try
43 | {
44 | JObject root = new JObject();
45 | root["mail"] = mail;
46 | root["password"] = AESHelper.AesEncode(password, kAesKey, kAesIv); //EncryptionHelper.AesEncryptionBase64(password, kAesKey); //加密
47 | root["autoLogin"] = autoLogin;
48 | File.WriteAllText(kConfigPath, root.ToString());
49 | }
50 | catch (System.Exception ex)
51 | {
52 | Debug.WriteLine(ex);
53 | }
54 | }
55 |
56 | ///
57 | /// 登录UI中使用,获取是否有保存的密码
58 | ///
59 | ///
60 | ///
61 | public void LoadPasswrod(out string mail, out string password, out bool autoLogin)
62 | {
63 | try
64 | {
65 | if (File.Exists(kConfigPath))
66 | {
67 | JObject root = JObject.Parse(File.ReadAllText(kConfigPath));
68 | mail = root["mail"].ToString();
69 | //password = EncryptionHelper.AesDecryptBase64(root["password"].ToString(), kAesKey);
70 | password = AESHelper.AesDecode(root["password"].ToString(), kAesKey, kAesIv);
71 |
72 | if (root.ContainsKey("autoLogin"))
73 | {
74 | autoLogin = root["autoLogin"].ToObject();
75 | }
76 | else
77 | {
78 | autoLogin = false;
79 | }
80 |
81 |
82 | return;
83 | }
84 |
85 | }
86 | catch (System.Exception ex)
87 | {
88 | Debug.WriteLine(ex);
89 | }
90 | mail = "";
91 | password = "";
92 | autoLogin = false;
93 | return;
94 | }
95 |
96 | public void Clear()
97 | {
98 | try
99 | {
100 | if (File.Exists(kConfigPath))
101 | {
102 | File.Delete(kConfigPath);
103 | }
104 | }
105 | catch (System.Exception ex)
106 | {
107 | Debug.WriteLine(ex);
108 | }
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/WkyFast/View/WkyMainTabView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Navigation;
15 | using System.Windows.Shapes;
16 | using WkyFast.View.Model;
17 |
18 | namespace WkyFast.View
19 | {
20 | ///
21 | /// WkyMainTabView.xaml 的交互逻辑
22 | ///
23 | public partial class WkyMainTabView : UserControl
24 | {
25 | MainTabItemModel? _lastSelectedConfig = null;
26 |
27 | public MainTabItemModel LastSelectedConfig
28 | {
29 | set
30 | {
31 | _lastSelectedConfig = value;
32 | }
33 | get
34 | {
35 | return _lastSelectedConfig;
36 | }
37 | }
38 | public WkyMainTabView()
39 | : this(new ObservableCollection())
40 | { }
41 |
42 | public WkyMainTabView(ObservableCollection viewModel)
43 | {
44 | InitializeComponent();
45 |
46 | this.ViewModel = viewModel;
47 | }
48 |
49 | public static readonly DependencyProperty ViewModelProperty =
50 | DependencyProperty.Register("ViewModel", typeof(ObservableCollection), typeof(WkyMainTabView));
51 |
52 | public ObservableCollection ViewModel
53 | {
54 | get { return (ObservableCollection)GetValue(ViewModelProperty); }
55 | set {
56 | SetValue(ViewModelProperty, value);
57 | if (value != null && value.Count > 0)
58 | {
59 | mainConfigViewDataGrid.SelectedItem = value.First();
60 | }
61 | }
62 | }
63 |
64 |
65 | public static readonly RoutedEvent OnConfigSelectedEvent = EventManager.RegisterRoutedEvent("OnConfigSelected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(WkyMainTabView));
66 |
67 | public event RoutedEventHandler OnConfigSelected
68 | {
69 | add { AddHandler(OnConfigSelectedEvent, value); }
70 | remove { RemoveHandler(OnConfigSelectedEvent, value); }
71 | }
72 |
73 | void RaiseSelectedEvent(SelectionChangedEventArgs e)
74 | {
75 | var arg = new RoutedEventArgs(OnConfigSelectedEvent, e);
76 | RaiseEvent(arg);
77 | }
78 |
79 |
80 | private void mainConfigViewDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
81 | {
82 | LastSelectedConfig = (MainTabItemModel)mainConfigViewDataGrid.SelectedItem;
83 | RaiseSelectedEvent(e);
84 | }
85 |
86 |
87 |
88 | private void UIElement_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
89 | {
90 | if (!e.Handled)
91 | {
92 | e.Handled = true;
93 | var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
94 | eventArg.RoutedEvent = MouseWheelEvent;
95 | eventArg.Source = sender;
96 | var parent = ((Control)sender).Parent as UIElement;
97 | parent?.RaiseEvent(eventArg);
98 | }
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/WkyFast/Utils/OSSManager.cs:
--------------------------------------------------------------------------------
1 | using Aliyun.OSS;
2 | using Newtonsoft.Json.Linq;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Text;
7 | using WkyFast.Service;
8 |
9 | namespace WkyFast.Utils
10 | {
11 | class OSSManager
12 | {
13 |
14 | private static OssClient CreateOssClient()
15 | {
16 | var client = new OssClient(AppConfig.Instance.ConfigData.OSSEndpoint, AppConfig.Instance.ConfigData.OSSAccessKeyId, AppConfig.Instance.ConfigData.OSSAccessKeySecret);
17 | return client;
18 | }
19 |
20 | public static string ReadFile(string fileName)
21 | {
22 | var objectName = fileName.Replace(@"/", "_");
23 | string ret = string.Empty;
24 | var client = CreateOssClient();
25 | try
26 | {
27 | //文件是否存在
28 | if (client.DoesObjectExist(AppConfig.Instance.ConfigData.OSSBucket, objectName))
29 | {
30 | var oldData = client.GetObject(AppConfig.Instance.ConfigData.OSSBucket, objectName).Content;
31 | StreamReader reader = new StreamReader(oldData);
32 | string oldText = reader.ReadToEnd();
33 | ret = oldText;
34 | }
35 | else
36 | {
37 | }
38 | }
39 | catch (Exception ex)
40 | {
41 | }
42 | return ret;
43 | }
44 |
45 | public static Stream ReadFileStream(string fileName)
46 | {
47 | var objectName = fileName.Replace(@"/", "_");
48 | var client = CreateOssClient();
49 | try
50 | {
51 | //文件是否存在
52 | if (client.DoesObjectExist(AppConfig.Instance.ConfigData.OSSBucket, objectName))
53 | {
54 | var oldData = client.GetObject(AppConfig.Instance.ConfigData.OSSBucket, objectName).Content;
55 | StreamReader reader = new StreamReader(oldData);
56 | reader.BaseStream.Position = 0;
57 | return reader.BaseStream;
58 | }
59 | else
60 | {
61 | }
62 | }
63 | catch (Exception ex)
64 | {
65 | }
66 | return null;
67 | }
68 |
69 | ///
70 | /// 文字内容写出
71 | ///
72 | ///
73 | ///
74 | public static void WriteFile(string fileName, string fileContent)
75 | {
76 | var objectName = fileName.Replace(@"/", "_");
77 |
78 | var client = CreateOssClient();
79 | try
80 | {
81 | byte[] array = Encoding.UTF8.GetBytes(fileContent);
82 | MemoryStream stream = new MemoryStream(array);
83 | client.PutObject(AppConfig.Instance.ConfigData.OSSBucket, objectName, stream);
84 | stream.Dispose();
85 |
86 | }
87 | catch (Exception ex)
88 | {
89 |
90 | }
91 |
92 | }
93 |
94 |
95 | ///
96 | /// 流文件写入
97 | ///
98 | ///
99 | ///
100 | public static void WriteFile(string fileName, Stream stream)
101 | {
102 | var objectName = fileName.Replace(@"/", "_");
103 |
104 | var client = CreateOssClient();
105 | try
106 | {
107 | client.PutObject(AppConfig.Instance.ConfigData.OSSBucket, objectName, stream);
108 | stream.Dispose();
109 |
110 | }
111 | catch (Exception ex)
112 | {
113 |
114 | }
115 |
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/WkyFast/Service/GAHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Flurl.Http;
4 | using System.Threading.Tasks;
5 | using WkyFast.Service;
6 | using System.Diagnostics;
7 |
8 | namespace WkyFast.Service
9 | {
10 | ///
11 | /// 相关文档:
12 | /// GA4教程 https://firebase.google.com/codelabs/firebase_mp
13 | /// 测试 https://ga-dev-tools.google/ga4/event-builder/
14 | ///
15 | public class GAHelper
16 | {
17 | private static GAHelper instance = null;
18 | private static readonly object obj = new object();
19 |
20 | public static GAHelper Instance
21 | {
22 | get
23 | {
24 | lock (obj)
25 | {
26 | if (instance == null)
27 | {
28 | instance = new GAHelper();
29 | }
30 | return instance;
31 | }
32 | }
33 | }
34 |
35 | private const string GAUrl = "https://www.google-analytics.com/mp/collect?api_secret=O5FOlVSiSmGmuGtj2xSZcQ&measurement_id=G-SDSDNLC0JV";
36 | private static readonly string cid = AppConfig.Instance.ConfigData.ClientId;
37 | public string UserAgent { get; set; }
38 |
39 | public GAHelper()
40 | {
41 | UserAgent = $"Google Analytics Tracker/1.1 ({Environment.OSVersion.Platform.ToString()}; {Environment.OSVersion.Version.ToString()}; {Environment.OSVersion.VersionString})";
42 | }
43 |
44 | public async Task RequestPageViewAsync(string page, string title = null)
45 | {
46 | try
47 | {
48 | if (page.StartsWith("/"))
49 | {
50 | page = page.Remove(0, 1);
51 | }
52 | page = page.Replace("/", "_").Replace(".", "_");
53 | var values = new
54 | {
55 | client_id = UserAgent,
56 | user_id = cid,
57 | non_personalized_ads = "false",
58 | events = new List