├── .gitattributes ├── .gitignore ├── .vs ├── config │ └── applicationhost.config └── restore.dg ├── BiliRanking.Core.Tests ├── AsyncHelper.cs ├── BiliInterfaceTests.cs ├── BiliRanking.Core.Tests.csproj └── Properties │ └── AssemblyInfo.cs ├── BiliRanking.Core ├── AsyncHelper.cs ├── BiliApiHelper.cs ├── BiliIModel.cs ├── BiliInterface.cs ├── BiliParse.cs ├── BiliRanking.Core.csproj ├── BiliUser.cs ├── Download │ ├── DownloadCompletedEventArgs.cs │ ├── DownloadProgressChangedEventArgs.cs │ ├── DownloadStatus.cs │ ├── DownloaderHelper.cs │ ├── HttpDownloadClient.cs │ ├── IDownloader.cs │ ├── MultiThreadedWebDownloader.cs │ └── MultiThreadedWebDownloaderEx.cs ├── FileManager.cs ├── Fubang.cs ├── Log.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Resources │ ├── fubang.png │ ├── fubang2.png │ ├── zhubang.png │ └── zhubang_stardust.png ├── TSDownload.cs ├── TSDownloaderBase.cs ├── Zhubang.cs └── packages.config ├── BiliRanking.CoreStandard.Demo ├── BiliRanking.CoreStandard.Demo.csproj └── Program.cs ├── BiliRanking.CoreStandard ├── AsyncHelper.cs ├── BiliApiHelper.cs ├── BiliInterface.cs ├── BiliModel.cs ├── BiliRanking.CoreStandard.csproj └── log.cs ├── BiliRanking.WPF ├── App.xaml ├── App.xaml.cs ├── BiliRanking.WPF.csproj ├── Controls │ ├── ModernCheckboxTree.xaml │ └── ModernCheckboxTree.xaml.cs ├── Domain │ ├── Item.cs │ ├── NotifyPropertyChangedExtension.cs │ ├── SampleMessageDialog.xaml │ └── SampleMessageDialog.xaml.cs ├── Extensions.cs ├── FileManager.cs ├── FodyWeavers.xml ├── GlobalKeyboardHook.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── NLog.config ├── NLog.xsd ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ └── NoAvatar.png ├── SharedData.cs ├── UIHelpers.cs ├── Updater.cs ├── View │ ├── Data.xaml │ ├── Data.xaml.cs │ ├── Download.xaml │ ├── Download.xaml.cs │ ├── Home.xaml │ ├── Home.xaml.cs │ ├── ImageTemplateEditor.xaml │ ├── ImageTemplateEditor.xaml.cs │ ├── List.xaml │ ├── List.xaml.cs │ ├── Login.xaml │ ├── Login.xaml.cs │ ├── VideoClip.xaml │ ├── VideoClip.xaml.cs │ ├── WindowQuickCopy.xaml │ ├── WindowQuickCopy.xaml.cs │ ├── viewFubang.xaml │ ├── viewFubang.xaml.cs │ ├── viewZhubang.xaml │ └── viewZhubang.xaml.cs ├── app.config ├── app.manifest ├── logo.ico └── packages.config ├── BiliRanking.sln ├── BiliRanking.v12.suo ├── BiliRanking ├── BiliRanking.csproj ├── ConfigHelper.cs ├── Controls │ ├── ReverseUpDown.Designer.cs │ ├── ReverseUpDown.cs │ ├── VerticalProgressBar.Designer.cs │ └── VerticalProgressBar.cs ├── FodyWeavers.xml ├── FormMain.Designer.cs ├── FormMain.cs ├── FormMain.resx ├── FormQuickCopy.Designer.cs ├── FormQuickCopy.cs ├── FormQuickCopy.resx ├── GlobalKeyboardHook.cs ├── Log.cs ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── TaskbarProgress.cs ├── Updater.cs ├── app.config ├── changelog.txt ├── logo.ico ├── logo.png └── packages.config ├── LICENSE ├── MaterialSkin ├── Animations │ ├── AnimationDirection.cs │ ├── AnimationManager.cs │ └── Animations.cs ├── ColorScheme.cs ├── Controls │ ├── MaterialCheckbox.cs │ ├── MaterialContextMenuStrip.cs │ ├── MaterialDivider.cs │ ├── MaterialFlatButton.cs │ ├── MaterialForm.cs │ ├── MaterialLabel.cs │ ├── MaterialListView.cs │ ├── MaterialMenuStrip.cs │ ├── MaterialProgressBar.cs │ ├── MaterialRadioButton.cs │ ├── MaterialRaisedButton.cs │ ├── MaterialSingleLineTextField.cs │ ├── MaterialTabControl.cs │ └── MaterialTabSelector.cs ├── DrawHelper.cs ├── IMaterialControl.cs ├── MaterialSkin.csproj ├── MaterialSkinManager.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx └── Resources │ ├── Roboto-Medium.ttf │ └── Roboto-Regular.ttf ├── README.md ├── jkl.moe.conf └── project.lock.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.vs/restore.dg: -------------------------------------------------------------------------------- 1 | #:C:\Users\SkiTiSu\Documents\GitHub\BiliRanking\BiliRanking.Web\BiliRanking.Web.xproj 2 | -------------------------------------------------------------------------------- /BiliRanking.Core.Tests/AsyncHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace BiliRanking.Core.Tests 9 | { 10 | internal static class AsyncHelper 11 | { 12 | private static readonly TaskFactory _myTaskFactory = new 13 | TaskFactory(CancellationToken.None, 14 | TaskCreationOptions.None, 15 | TaskContinuationOptions.None, 16 | TaskScheduler.Default); 17 | 18 | public static TResult RunSync(Func> func) 19 | { 20 | return AsyncHelper._myTaskFactory 21 | .StartNew>(func) 22 | .Unwrap() 23 | .GetAwaiter() 24 | .GetResult(); 25 | } 26 | 27 | public static void RunSync(Func func) 28 | { 29 | AsyncHelper._myTaskFactory 30 | .StartNew(func) 31 | .Unwrap() 32 | .GetAwaiter() 33 | .GetResult(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /BiliRanking.Core.Tests/BiliInterfaceTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using BiliRanking.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Diagnostics; 9 | 10 | namespace BiliRanking.Core.Tests 11 | { 12 | [TestClass()] 13 | public class BiliInterfaceTests 14 | { 15 | [TestMethod()] 16 | public void EnvironmentTest() 17 | { 18 | Console.WriteLine("【运行环境检查】"); 19 | Console.WriteLine("逻辑处理器数量:" + Environment.ProcessorCount); 20 | } 21 | 22 | [TestMethod()] 23 | public void GetInfoAsyncTest() 24 | { 25 | BiliInterfaceInfo info = new BiliInterfaceInfo(); 26 | info = AsyncHelper.RunSync(() => BiliInterface.GetInfoAsync("av2680512")); 27 | 28 | Assert.AreEqual(info.title, "【创刊号】哔哩哔哩月刊鬼畜排行榜#001"); 29 | } 30 | 31 | [TestMethod()] 32 | public void GetFlvInfoTest() 33 | { 34 | BiliInterfaceInfo info = new BiliInterfaceInfo(); 35 | //info = BiliInterface.GetFlvInfo("av3153761"); 36 | //TestContext.WriteLine(info.flvurl); 37 | //Debug.WriteLine(info.flvurl); 38 | info = BiliInterface.GetFlvInfo("av9472850"); 39 | Assert.IsTrue(info.flvurl.Contains(".flv")); 40 | } 41 | 42 | [TestMethod()] 43 | public void GetFlvUrlsTest() 44 | { 45 | var c = BiliInterface.GetFlvUrls(15657517); 46 | Assert.IsTrue(c.Count() > 0); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /BiliRanking.Core.Tests/BiliRanking.Core.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {48A281E3-9CD1-456F-BAEE-8C91FC91E1E3} 7 | Library 8 | Properties 9 | BiliRanking.Core.Tests 10 | BiliRanking.Core.Tests 11 | v4.5 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {3C876F63-7749-4224-A444-0E0B3FF43194} 60 | BiliRanking.Core 61 | 62 | 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | False 71 | 72 | 73 | False 74 | 75 | 76 | False 77 | 78 | 79 | 80 | 81 | 82 | 83 | 90 | -------------------------------------------------------------------------------- /BiliRanking.Core.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("BiliRanking.Core.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BiliRanking.Core.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | //将 ComVisible 设置为 false 将使此程序集中的类型 18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("48a281e3-9cd1-456f-baee-8c91fc91e1e3")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /BiliRanking.Core/AsyncHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace BiliRanking.Core 9 | { 10 | internal static class AsyncHelper 11 | { 12 | private static readonly TaskFactory _myTaskFactory = new 13 | TaskFactory(CancellationToken.None, 14 | TaskCreationOptions.None, 15 | TaskContinuationOptions.None, 16 | TaskScheduler.Default); 17 | 18 | public static TResult RunSync(Func> func) 19 | { 20 | return AsyncHelper._myTaskFactory 21 | .StartNew>(func) 22 | .Unwrap() 23 | .GetAwaiter() 24 | .GetResult(); 25 | } 26 | 27 | public static void RunSync(Func func) 28 | { 29 | AsyncHelper._myTaskFactory 30 | .StartNew(func) 31 | .Unwrap() 32 | .GetAwaiter() 33 | .GetResult(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /BiliRanking.Core/BiliParse.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Parser.Html; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Linq; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.ComponentModel; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Net.Http; 10 | using System.Text; 11 | using System.Text.RegularExpressions; 12 | 13 | namespace BiliRanking.Core 14 | { 15 | public class BiliParse 16 | { 17 | private static HtmlParser htmlParser = new HtmlParser(); 18 | /// 19 | /// 排序类型。注意:Default和New需要ToLower! 20 | /// 21 | public enum SortType 22 | { 23 | [Description("播放数")] 24 | hot, 25 | [Description("按新投稿排序")] 26 | Default, 27 | [Description("按新评论排序")] 28 | New, 29 | [Description("评论数")] 30 | review, 31 | [Description("弹幕数")] 32 | damku, 33 | [Description("用户评分")] 34 | comment, 35 | [Description("硬币数")] 36 | promote, 37 | [Description("按标题拼音排序")] 38 | pinyin, 39 | [Description("收藏(不存在于API文档)")] 40 | stow 41 | } 42 | 43 | public static List GetListOld(SortType type, int zone, int page, DateTime from, DateTime to) 44 | { 45 | Log.Info("正在获取排行(旧版) - 依据" + type.ToString().ToLower() + "/分区" + zone + "/分页" + page + "/时间" + from.ToString("yyyy-MM-dd") + "~" + to.ToString("yyyy-MM-dd")); 46 | string url = "http://www.bilibili.com/list/" + type.ToString() + "-" + zone + "-" + page + "-" + from.ToString("yyyy-MM-dd") + "~" + to.ToString("yyyy-MM-dd") + ".html"; 47 | string html = BiliInterface.GetHtml(url); 48 | if (html == null) return null; 49 | int p = html.IndexOf("href=\"/video/av"); 50 | List r = new List(); 51 | while (p > 0) 52 | { 53 | string s = html.Substring(p + 13, html.IndexOf("/", p + 13) - p - 13); 54 | if (!r.Contains(s)) 55 | r.Add(s); 56 | p = html.IndexOf("href=\"/video/av", p + 3); 57 | } 58 | return r; 59 | } 60 | 61 | public static List GetList(int cate_id, DateTime from, DateTime to) 62 | { 63 | var res = GetListInternal(cate_id, from, to, 1); 64 | List infos = res.infos; 65 | for (int i = 2; i <= res.pages; i++) 66 | { 67 | infos.AddRange(GetListInternal(cate_id, from, to, i).infos); 68 | } 69 | return infos; 70 | } 71 | 72 | public static List GetList(int cate_id, DateTime from, DateTime to, int page = 1) 73 | => GetListInternal(cate_id, from, to, page).infos; 74 | 75 | public static (List infos, int pages) GetListInternal(int cate_id, DateTime from, DateTime to, int page = 1) 76 | { 77 | Log.Info($"正在获取排行 - 分区{cate_id} / 时间{from.ToString("yyyyMMdd")}~{to.ToString("yyyyMMdd")} / 页码{page}"); 78 | string url = "https://" + "s.search.bilibili.com/cate/search?main_ver=v3&search_type=video&view_type=hot_rank&pic_size=160x100&order=click©_right=-1&" + 79 | $"cate_id={cate_id}&page={page}&pagesize=100&time_from={from.ToString("yyyyMMdd")}&time_to={to.ToString("yyyyMMdd")}"; 80 | string html = BiliInterface.GetHtml(url); 81 | if (html == null) return (null, 0); 82 | JObject obj = JObject.Parse(html); 83 | IEnumerable avs = from n in obj["result"] 84 | select "av" + Regex.Match((string)n["arcurl"], @"\d+").Value; 85 | return (avs.ToList(), (int)obj["numPages"]); 86 | } 87 | 88 | public static List GetSearch(string keyword, int tids_1, int tids_2, string order, DateTime needFrom, int need = 0) 89 | { 90 | int page = 1; 91 | List re = new List(); 92 | //highlight=1会导致title被加入高亮样式html,改成0还是有,无解 93 | string url = "http://" + $"api.bilibili.com/x/web-interface/search/type?jsonp=jsonp&highlight=0&search_type=video&keyword={keyword}&order={order}&duration=0&page={page}&tids={tids_2}"; 94 | string html = BiliInterface.GetHtml(url); 95 | if (html == null) return null; 96 | JObject obj = JObject.Parse(html); 97 | int numResults = (int)obj["data"]["numResults"]; 98 | int numPages = (int)obj["data"]["numPages"]; 99 | Log.Info($"找到{numResults}个,{numPages}页"); 100 | for (int i = 2; i <= numPages + 1; i++) 101 | { 102 | IList results = obj["data"]["result"].Children().ToList(); 103 | foreach (var result in results) 104 | { 105 | DateTime uploadtime = UnixTimeStampToDateTime(result["pubdate"].ToObject()); 106 | if (uploadtime >= needFrom.Date) 107 | { 108 | string avnum = "av" + result["aid"]; 109 | re.Add(avnum); 110 | } 111 | else 112 | { 113 | i = 99999; 114 | break; 115 | } 116 | } 117 | if (i == 99999) break; 118 | url = "http://" + $"api.bilibili.com/x/web-interface/search/type?jsonp=jsonp&search_type=video&keyword={keyword}&order={order}&duration=0&page={i}&tids={tids_2}"; 119 | html = BiliInterface.GetHtml(url); 120 | obj = JObject.Parse(html); 121 | } 122 | return re; 123 | } 124 | 125 | //.net4.6有原生方法,在升级.net后修改为原生方法 126 | public static DateTime UnixTimeStampToDateTime(double unixTimeStamp) 127 | { 128 | System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 129 | dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime(); 130 | return dtDateTime; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /BiliRanking.Core/BiliRanking.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3C876F63-7749-4224-A444-0E0B3FF43194} 8 | Library 9 | Properties 10 | BiliRanking.Core 11 | BiliRanking.Core 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | true 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | true 33 | 34 | 35 | 36 | ..\packages\AngleSharp.0.9.9\lib\net45\AngleSharp.dll 37 | 38 | 39 | ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll 40 | True 41 | 42 | 43 | 44 | 45 | 46 | 47 | ..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | True 80 | True 81 | Resources.resx 82 | 83 | 84 | 85 | 86 | 87 | 88 | Resources.Designer.cs 89 | PublicResXFileCodeGenerator 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 113 | -------------------------------------------------------------------------------- /BiliRanking.Core/BiliUser.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace BiliRanking.Core 9 | { 10 | public class BiliUser 11 | { 12 | public async Task GetMyUserInfo() 13 | { 14 | if (IsLogin()) 15 | { 16 | try 17 | { 18 | string url = string.Format("http://account.bilibili.com/api/myinfo?access_key={0}&appkey={1}&platform=wp&type=json", BiliApiHelper.access_key, BiliApiHelper._appKey_IOS); 19 | url += "&sign=" + BiliApiHelper.GetSign(url); 20 | string results = await BiliInterface.GetHtmlAsync(url); 21 | UserInfoModel model = JsonConvert.DeserializeObject(results); 22 | //AttentionList = model.attentions; 23 | return model; 24 | } 25 | catch (Exception) 26 | { 27 | return null; 28 | } 29 | } 30 | else 31 | { 32 | return null; 33 | } 34 | } 35 | 36 | public bool IsLogin() 37 | { 38 | return true; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /BiliRanking.Core/Download/DownloadCompletedEventArgs.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | * Module Name: DownloadCompletedEventArgs.cs 3 | * Project: CSMultiThreadedWebDownloader 4 | * Copyright (c) Microsoft Corporation. 5 | * 6 | * The class DownloadCompletedEventArgs defines the arguments used by 7 | * the DownloadCompleted event of an IDownloader instance. 8 | * 9 | * This source is subject to the Microsoft Public License. 10 | * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 11 | * All other rights reserved. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 14 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 16 | \***************************************************************************/ 17 | 18 | using System; 19 | using System.IO; 20 | 21 | namespace BiliRanking.Core.Download 22 | { 23 | public class DownloadCompletedEventArgs : EventArgs 24 | { 25 | public Int64 DownloadedSize { get; private set; } 26 | public Int64 TotalSize { get; private set; } 27 | public Exception Error { get; private set; } 28 | public TimeSpan TotalTime { get; private set; } 29 | public FileInfo DownloadedFile { get; private set; } 30 | 31 | public DownloadCompletedEventArgs( 32 | FileInfo downloadedFile, Int64 downloadedSize, 33 | Int64 totalSize, TimeSpan totalTime, Exception ex) 34 | { 35 | this.DownloadedFile = downloadedFile; 36 | this.DownloadedSize = downloadedSize; 37 | this.TotalSize = totalSize; 38 | this.TotalTime = totalTime; 39 | this.Error = ex; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /BiliRanking.Core/Download/DownloadProgressChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | * Module Name: DownloadProgressChangedEventArgs.cs 3 | * Project: CSMultiThreadedWebDownloader 4 | * Copyright (c) Microsoft Corporation. 5 | * 6 | * The class DownloadProgressChangedEventArgs defines the arguments 7 | * used by the DownloadProgressChanged event of an IDownloader instance.. 8 | * 9 | * This source is subject to the Microsoft Public License. 10 | * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 11 | * All other rights reserved. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 14 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 16 | \***************************************************************************/ 17 | 18 | using System; 19 | 20 | namespace BiliRanking.Core.Download 21 | { 22 | public class DownloadProgressChangedEventArgs : EventArgs 23 | { 24 | public Int64 ReceivedSize { get; private set; } 25 | public Int64 TotalSize { get; private set; } 26 | public int DownloadSpeed { get; private set; } 27 | 28 | public DownloadProgressChangedEventArgs(Int64 receivedSize, 29 | Int64 totalSize, int downloadSpeed) 30 | { 31 | this.ReceivedSize = receivedSize; 32 | this.TotalSize = totalSize; 33 | this.DownloadSpeed = downloadSpeed; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /BiliRanking.Core/Download/DownloadStatus.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | * Module Name: DownloadStatus.cs 3 | * Project: CSMultiThreadedWebDownloader 4 | * Copyright (c) Microsoft Corporation. 5 | * 6 | * The enum DownloadStatus contains all status of 7 | * an IDownloader instance. 8 | * 9 | * This source is subject to the Microsoft Public License. 10 | * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 11 | * All other rights reserved. 12 | * 13 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 14 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 16 | \***************************************************************************/ 17 | 18 | namespace BiliRanking.Core.Download 19 | { 20 | public enum DownloadStatus 21 | { 22 | /// 23 | /// The DownloadClient is initialized. 24 | /// 25 | Initialized, 26 | 27 | /// 28 | /// The client is waiting for an idle thread / resource to start downloading. 29 | /// 30 | Waiting, 31 | 32 | /// 33 | /// The client is downloading data. 34 | /// 35 | Downloading, 36 | 37 | /// 38 | /// The client is releasing the resource, and then the downloading 39 | /// will be paused. 40 | /// 41 | Pausing, 42 | 43 | /// 44 | /// The downloading is paused. 45 | /// 46 | Paused, 47 | 48 | /// 49 | /// The client is releasing the resource, and then the downloading 50 | /// will be canceled. 51 | /// 52 | Canceling, 53 | 54 | /// 55 | /// The downloading is Canceled. 56 | /// 57 | Canceled, 58 | 59 | /// 60 | /// The downloading is Completed. 61 | /// 62 | Completed 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /BiliRanking.Core/Download/IDownloader.cs: -------------------------------------------------------------------------------- 1 | /****************************** Module Header ******************************\ 2 | * Module Name: IDownloader.cs 3 | * Project: CSMultiThreadedWebDownloader 4 | * Copyright (c) Microsoft Corporation. 5 | * 6 | * This interface defines the basic properties and methods of a WebDownloader. 7 | * 8 | * This source is subject to the Microsoft Public License. 9 | * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. 10 | * All other rights reserved. 11 | * 12 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 13 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 14 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 15 | \***************************************************************************/ 16 | 17 | using System; 18 | using System.Net; 19 | namespace BiliRanking.Core.Download 20 | { 21 | public interface IDownloader 22 | { 23 | 24 | #region Basic settings of a WebDownloader. 25 | 26 | Uri Url { get;} 27 | string DownloadPath { get; set; } 28 | long TotalSize { get; set; } 29 | 30 | ICredentials Credentials { get; set; } 31 | IWebProxy Proxy { get; set; } 32 | 33 | #endregion 34 | 35 | 36 | #region Support the "Pause", "Resume" and Multi-Threads feature. 37 | 38 | bool IsRangeSupported { get; set; } 39 | long StartPoint { get; set; } 40 | long EndPoint { get; set; } 41 | 42 | #endregion 43 | 44 | #region The downloaded data and status. 45 | 46 | long DownloadedSize { get; } 47 | int CachedSize { get; } 48 | 49 | bool HasChecked { get; set; } 50 | DownloadStatus Status { get; } 51 | TimeSpan TotalUsedTime { get; } 52 | 53 | #endregion 54 | 55 | #region Advanced settings of a WebDownloader 56 | 57 | int BufferSize { get; set; } 58 | int BufferCountPerNotification { get; set; } 59 | int MaxCacheSize { get; set; } 60 | 61 | #endregion 62 | 63 | 64 | event EventHandler DownloadCompleted; 65 | event EventHandler DownloadProgressChanged; 66 | event EventHandler StatusChanged; 67 | 68 | void CheckUrl(out string fileName); 69 | 70 | void BeginDownload(); 71 | void Download(); 72 | 73 | void Pause(); 74 | 75 | void Resume(); 76 | void BeginResume(); 77 | 78 | void Cancel(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /BiliRanking.Core/Download/MultiThreadedWebDownloaderEx.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 BiliRanking.Core.Download 9 | { 10 | public class MultiThreadedWebDownloaderEx : MultiThreadedWebDownloader 11 | { 12 | 13 | public float Percent 14 | { 15 | get 16 | { 17 | return (float)DownloadedSize / TotalSize; 18 | } 19 | } 20 | 21 | public MultiThreadedWebDownloaderEx(string url) : base(url, 1024, 1048576, 64, Environment.ProcessorCount) 22 | { 23 | } 24 | 25 | public new void BeginDownload() 26 | { 27 | base.DownloadPath = CheckDuplicateName(base.DownloadPath); 28 | base.BeginDownload(); 29 | } 30 | /// 31 | /// 检测是否有重名,有则加入(1),如仍重复加(2),以此类推 32 | /// 33 | /// 34 | public virtual void CheckDuplicateName(ref string fileName) 35 | { 36 | if (File.Exists(fileName)) 37 | { 38 | string fn1 = fileName.Substring(0, fileName.IndexOf('.')); //TODO: 换成File类自带的方法 39 | string fn2 = fileName.Substring(fileName.IndexOf('.')); 40 | int i = 0; 41 | string nFileName; 42 | do 43 | { 44 | i++; 45 | nFileName = string.Format("{0}({1}){2}", fn1, i, fn2); 46 | } while (File.Exists(nFileName)); 47 | fileName = nFileName; 48 | } 49 | } 50 | 51 | public virtual string CheckDuplicateName(string fileName) 52 | { 53 | CheckDuplicateName(ref fileName); 54 | return fileName; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /BiliRanking.Core/FileManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace BiliRanking.Core 10 | { 11 | public static class FileManager 12 | { 13 | public static string currentPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /BiliRanking.Core/Log.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace BiliRanking.Core 6 | { 7 | public static class Log 8 | { 9 | public static void Info(string s) 10 | { 11 | Console.WriteLine("[INFO] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 12 | } 13 | 14 | public static void Error(string s) 15 | { 16 | Console.ForegroundColor = ConsoleColor.Red; 17 | Console.WriteLine("[ERRO] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 18 | Console.ForegroundColor = ConsoleColor.Gray; 19 | } 20 | 21 | public static void Warn(string s) 22 | { 23 | Console.ForegroundColor = ConsoleColor.Yellow; 24 | Console.WriteLine("[WARN] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 25 | Console.ForegroundColor = ConsoleColor.Gray; 26 | } 27 | 28 | public static void Debug(string s) 29 | { 30 | #if DEBUG 31 | Console.ForegroundColor = ConsoleColor.Cyan; 32 | Console.WriteLine("[DEBU] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 33 | Console.ForegroundColor = ConsoleColor.Gray; 34 | #endif 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /BiliRanking.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("BiliRanking.Core")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BiliRanking.Core")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | //将 ComVisible 设置为 false 将使此程序集中的类型 18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("3c876f63-7749-4224-a444-0e0b3ff43194")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /BiliRanking.Core/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BiliRanking.Core.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BiliRanking.Core.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 使用此强类型资源类,为所有资源查找 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 65 | /// 66 | public static System.Drawing.Bitmap fubang { 67 | get { 68 | object obj = ResourceManager.GetObject("fubang", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 75 | /// 76 | public static System.Drawing.Bitmap fubang2 { 77 | get { 78 | object obj = ResourceManager.GetObject("fubang2", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 85 | /// 86 | public static System.Drawing.Bitmap zhubang { 87 | get { 88 | object obj = ResourceManager.GetObject("zhubang", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 95 | /// 96 | public static System.Drawing.Bitmap zhubang_stardust { 97 | get { 98 | object obj = ResourceManager.GetObject("zhubang_stardust", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /BiliRanking.Core/Resources/fubang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SkiTiSu/BiliRanking/26509add8011d92ff5acd3a230a64a2ada940978/BiliRanking.Core/Resources/fubang.png -------------------------------------------------------------------------------- /BiliRanking.Core/Resources/fubang2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SkiTiSu/BiliRanking/26509add8011d92ff5acd3a230a64a2ada940978/BiliRanking.Core/Resources/fubang2.png -------------------------------------------------------------------------------- /BiliRanking.Core/Resources/zhubang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SkiTiSu/BiliRanking/26509add8011d92ff5acd3a230a64a2ada940978/BiliRanking.Core/Resources/zhubang.png -------------------------------------------------------------------------------- /BiliRanking.Core/Resources/zhubang_stardust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SkiTiSu/BiliRanking/26509add8011d92ff5acd3a230a64a2ada940978/BiliRanking.Core/Resources/zhubang_stardust.png -------------------------------------------------------------------------------- /BiliRanking.Core/TSDownloaderBase.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 BiliRanking.Core 9 | { 10 | public abstract class TSDownloaderBase 11 | { 12 | public abstract void Start(); 13 | 14 | /// 15 | /// 检测是否有重名,有则加入(1),如仍重复加(2),以此类推 16 | /// 17 | /// 18 | public virtual void CheckDuplicateName(ref string fileName) 19 | { 20 | if (File.Exists(fileName)) 21 | { 22 | string fn1 = fileName.Substring(0, fileName.LastIndexOf('.')); //TODO: 换成File类自带的方法 23 | string fn2 = fileName.Substring(fileName.LastIndexOf('.')); 24 | int i = 0; 25 | string nFileName; 26 | do 27 | { 28 | i++; 29 | nFileName = string.Format("{0}({1}){2}", fn1, i, fn2); 30 | } while (File.Exists(nFileName)); 31 | fileName = nFileName; 32 | } 33 | } 34 | 35 | public virtual string CheckDuplicateName(string fileName) 36 | { 37 | CheckDuplicateName(ref fileName); 38 | return fileName; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /BiliRanking.Core/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BiliRanking.CoreStandard.Demo/BiliRanking.CoreStandard.Demo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BiliRanking.CoreStandard.Demo/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BiliRanking.CoreStandard; 3 | 4 | namespace BiliRanking.CoreStandard.Demo 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | BiliInterface.GetTagSort(30, "SHARPKEY中文曲", order: "new"); 11 | Console.WriteLine("Hello World!"); 12 | Console.ReadKey(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /BiliRanking.CoreStandard/AsyncHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace BiliRanking.CoreStandard 9 | { 10 | internal static class AsyncHelper 11 | { 12 | private static readonly TaskFactory _myTaskFactory = new 13 | TaskFactory(CancellationToken.None, 14 | TaskCreationOptions.None, 15 | TaskContinuationOptions.None, 16 | TaskScheduler.Default); 17 | 18 | public static TResult RunSync(Func> func) 19 | { 20 | return AsyncHelper._myTaskFactory 21 | .StartNew>(func) 22 | .Unwrap() 23 | .GetAwaiter() 24 | .GetResult(); 25 | } 26 | 27 | public static void RunSync(Func func) 28 | { 29 | AsyncHelper._myTaskFactory 30 | .StartNew(func) 31 | .Unwrap() 32 | .GetAwaiter() 33 | .GetResult(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /BiliRanking.CoreStandard/BiliApiHelper.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Security.Cryptography; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace BiliRanking.CoreStandard 12 | { 13 | //感谢https://github.com/xiaoyaocz/BiliBili-UWP! 14 | public class BiliApiHelper 15 | { 16 | public const string _appSecret_Wp = "ba3a4e554e9a6e15dc4d1d70c2b154e3";//Wp 17 | public const string _appSecret_IOS = "8cb98205e9b2ad3669aad0fce12a4c13";//Ios 18 | public const string _appSecret_Android = "ea85624dfcf12d7cc7b2b3a94fac1f2c";//Android 19 | public const string _appSecret_DONTNOT = "2ad42749773c441109bdc0191257a664";//Android 20 | 21 | public const string _appKey = "422fd9d7289a1dd9"; 22 | public const string _appKey_IOS = "4ebafd7c4951b366"; 23 | public const string _appKey_Android = "c1b107428d337928"; 24 | public const string _appkey_DONTNOT = "85eb6835b0a1034e"; 25 | 26 | public static string access_key = ""; 27 | 28 | public static string GetSign(string url, string Secret = "ba3a4e554e9a6e15dc4d1d70c2b154e3") 29 | { 30 | string result; 31 | string str = url.Substring(url.IndexOf("?", 4) + 1); 32 | List list = str.Split('&').ToList(); 33 | list.Sort(); 34 | StringBuilder stringBuilder = new StringBuilder(); 35 | foreach (string str1 in list) 36 | { 37 | stringBuilder.Append((stringBuilder.Length > 0 ? "&" : string.Empty)); 38 | stringBuilder.Append(str1); 39 | } 40 | stringBuilder.Append(Secret); 41 | using (var md5 = MD5.Create()) 42 | { 43 | result = BitConverter.ToString(md5.ComputeHash(Encoding.ASCII.GetBytes(stringBuilder.ToString()))).Replace("-", "").ToLower(); 44 | } 45 | return result; 46 | } 47 | 48 | public static async Task LoginBilibili(string UserName, string Password) 49 | { 50 | try 51 | { 52 | //发送第一次请求,得到access_key 53 | HttpClient wc = new HttpClient(); 54 | string url = "https://api.bilibili.com/login?appkey=422fd9d7289a1dd9&platform=wp&pwd=" + WebUtility.UrlEncode(Password) + "&type=json&userid=" + WebUtility.UrlEncode(UserName); 55 | //url += "&sign=" + BiliApiHelper.GetSign(url); 56 | 57 | string results = await wc.GetStringAsync(url); 58 | //Json解析及数据判断 59 | LoginModel model = new LoginModel(); 60 | model = JsonConvert.DeserializeObject(results); 61 | if (model.code == -627) 62 | { 63 | return "登录失败,密码错误!"; 64 | } 65 | if (model.code == -626) 66 | { 67 | return "登录失败,账号不存在!"; 68 | } 69 | if (model.code == -625) 70 | { 71 | return "密码错误多次"; 72 | } 73 | if (model.code == -628) 74 | { 75 | return "未知错误"; 76 | } 77 | if (model.code == -1) 78 | { 79 | return "登录失败,程序注册失败!请联系作者!"; 80 | } 81 | HttpClient hc = new HttpClient(); 82 | if (model.code == 0) 83 | { 84 | access_key = model.access_key; 85 | return model.access_key; 86 | /* 87 | 88 | Windows.Web.Http.HttpResponseMessage hr2 = await hc.GetAsync(new Uri("http://api.bilibili.com/login/sso?&access_key=" + model.access_key + "&appkey=422fd9d7289a1dd9&platform=wp")); 89 | hr2.EnsureSuccessStatusCode(); 90 | StorageFolder folder = ApplicationData.Current.LocalFolder; 91 | StorageFile file = await folder.CreateFileAsync("us.bili", CreationCollisionOption.OpenIfExists); 92 | await FileIO.WriteTextAsync(file, model.access_key); 93 | */ 94 | } 95 | 96 | return "err"; 97 | //看看存不存在Cookie 98 | //TODO: 读取cookie http://www.cnblogs.com/suger/p/3359146.html 99 | /* 100 | hb = new HttpBaseProtocolFilter(); 101 | HttpCookieCollection cookieCollection = hb.CookieManager.GetCookies(new Uri("http://bilibili.com/")); 102 | 103 | List ls = new List(); 104 | foreach (HttpCookie item in cookieCollection) 105 | { 106 | ls.Add(item.Name); 107 | } 108 | if (ls.Contains("DedeUserID")) 109 | { 110 | return "登录成功"; 111 | } 112 | else 113 | { 114 | return "登录失败"; 115 | } 116 | */ 117 | } 118 | catch (Exception ex) 119 | { 120 | if (ex.HResult == -2147012867) 121 | { 122 | return "登录失败,检查你的网络连接!"; 123 | } 124 | else 125 | { 126 | return "登录发生错误"; 127 | } 128 | 129 | } 130 | } 131 | 132 | public static long GetTimeSpen 133 | { 134 | get { return Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /BiliRanking.CoreStandard/BiliRanking.CoreStandard.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.4 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BiliRanking.CoreStandard/log.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace BiliRanking.CoreStandard 6 | { 7 | public class log 8 | { 9 | public static void Info(string s) 10 | { 11 | Console.WriteLine("[INFO] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 12 | } 13 | 14 | public static void Error(string s) 15 | { 16 | Console.ForegroundColor = ConsoleColor.Red; 17 | Console.WriteLine("[ERRO] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 18 | Console.ForegroundColor = ConsoleColor.Gray; 19 | } 20 | 21 | public static void Warn(string s) 22 | { 23 | Console.ForegroundColor = ConsoleColor.Yellow; 24 | Console.WriteLine("[WARN] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 25 | Console.ForegroundColor = ConsoleColor.Gray; 26 | } 27 | 28 | public static void Debug(string s) 29 | { 30 | #if DEBUG 31 | Console.ForegroundColor = ConsoleColor.Cyan; 32 | Console.WriteLine("[DEBU] " + DateTime.Now.ToString("HH:mm:ss") + " " + s); 33 | Console.ForegroundColor = ConsoleColor.Gray; 34 | #endif 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /BiliRanking.WPF/App.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto,Microsoft Yahei UI,Microsoft Yahei 20 | 21 | True 22 | 23 | 32 | 33 | 37 | 38 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /BiliRanking.WPF/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Windows; 7 | 8 | namespace BiliRanking.WPF 9 | { 10 | /// 11 | /// App.xaml 的交互逻辑 12 | /// 13 | public partial class App : Application 14 | { 15 | private void Application_Startup(object sender, StartupEventArgs e) 16 | { 17 | 18 | } 19 | 20 | private void Application_Exit(object sender, ExitEventArgs e) 21 | { 22 | BiliRanking.WPF.Properties.Settings.Default.Save(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Controls/ModernCheckboxTree.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Controls/ModernCheckboxTree.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 BiliRanking.WPF.Controls 17 | { 18 | /// 19 | /// ModernCheckboxTree.xaml 的交互逻辑 20 | /// 21 | public partial class ModernCheckboxTree : UserControl 22 | { 23 | public ModernCheckboxTree() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Domain/Item.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace BiliRanking.WPF.Domain 9 | { 10 | public class Item : INotifyPropertyChanged 11 | { 12 | private string name; 13 | private object content; 14 | 15 | public string Name 16 | { 17 | get 18 | { 19 | return name; 20 | } 21 | set 22 | { 23 | this.MutateVerbose(ref name, value, RaisePropertyChanged()); 24 | } 25 | } 26 | 27 | public object Content 28 | { 29 | get { return content; } 30 | set 31 | { 32 | this.MutateVerbose(ref content, value, RaisePropertyChanged()); 33 | } 34 | } 35 | public event PropertyChangedEventHandler PropertyChanged; 36 | 37 | private Action RaisePropertyChanged() 38 | { 39 | return args => PropertyChanged?.Invoke(this, args); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Domain/NotifyPropertyChangedExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace BiliRanking.WPF.Domain 10 | { 11 | public static class NotifyPropertyChangedExtension 12 | { 13 | public static void MutateVerbose(this INotifyPropertyChanged instance, ref TField field, TField newValue, Action raise, [CallerMemberName] string propertyName = null) 14 | { 15 | if (EqualityComparer.Default.Equals(field, newValue)) return; 16 | field = newValue; 17 | raise?.Invoke(new PropertyChangedEventArgs(propertyName)); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Domain/SampleMessageDialog.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 20 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Domain/SampleMessageDialog.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 BiliRanking.WPF.Domain 17 | { 18 | /// 19 | /// SampleMessageDialog.xaml 的交互逻辑 20 | /// 21 | public partial class SampleMessageDialog : UserControl 22 | { 23 | public SampleMessageDialog() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Markup; 8 | 9 | namespace BiliRanking.WPF 10 | { 11 | public class EnumerationExtension : MarkupExtension 12 | { 13 | private Type _enumType; 14 | 15 | 16 | public EnumerationExtension(Type enumType) 17 | { 18 | if (enumType == null) 19 | throw new ArgumentNullException("enumType"); 20 | 21 | EnumType = enumType; 22 | } 23 | 24 | public Type EnumType 25 | { 26 | get { return _enumType; } 27 | private set 28 | { 29 | if (_enumType == value) 30 | return; 31 | 32 | var enumType = Nullable.GetUnderlyingType(value) ?? value; 33 | 34 | if (enumType.IsEnum == false) 35 | throw new ArgumentException("Type must be an Enum."); 36 | 37 | _enumType = value; 38 | } 39 | } 40 | 41 | public override object ProvideValue(IServiceProvider serviceProvider) 42 | { 43 | var enumValues = Enum.GetValues(EnumType); 44 | 45 | return ( 46 | from object enumValue in enumValues 47 | select new EnumerationMember 48 | { 49 | Value = enumValue, 50 | Description = GetDescription(enumValue) 51 | }).ToArray(); 52 | } 53 | 54 | private string GetDescription(object enumValue) 55 | { 56 | var descriptionAttribute = EnumType 57 | .GetField(enumValue.ToString()) 58 | .GetCustomAttributes(typeof(DescriptionAttribute), false) 59 | .FirstOrDefault() as DescriptionAttribute; 60 | 61 | 62 | return descriptionAttribute != null 63 | ? descriptionAttribute.Description 64 | : enumValue.ToString(); 65 | } 66 | 67 | public class EnumerationMember 68 | { 69 | public string Description { get; set; } 70 | public object Value { get; set; } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /BiliRanking.WPF/FileManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace BiliRanking.WPF 10 | { 11 | public static class FileManager 12 | { 13 | public static string currentPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /BiliRanking.WPF/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /BiliRanking.WPF/NLog.config: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 14 | 18 | 19 | 20 | 25 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // 有关程序集的一般信息由以下 8 | // 控制。更改这些特性值可修改 9 | // 与程序集关联的信息。 10 | [assembly: AssemblyTitle("BiliRanking.WPF")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Xin Tianshu Li")] 14 | [assembly: AssemblyProduct("BiliRanking.WPF")] 15 | [assembly: AssemblyCopyright("Copyright © SkiTiSu 2016-2018")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | //将 ComVisible 设置为 false 将使此程序集中的类型 20 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | //若要开始生成可本地化的应用程序,请 25 | // 中的 .csproj 文件中 26 | //例如,如果您在源文件中使用的是美国英语, 27 | //使用的是美国英语,请将 设置为 en-US。 然后取消 28 | //对以下 NeutralResourceLanguage 特性的注释。 更新 29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置 36 | //(当资源未在页面 37 | //或应用程序资源字典中找到时使用) 38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 39 | //(当资源未在页面 40 | //、应用程序或任何主题专用资源字典中找到时使用) 41 | )] 42 | 43 | 44 | // 程序集的版本信息由下列四个值组成: 45 | // 46 | // 主版本 47 | // 次版本 48 | // 生成号 49 | // 修订号 50 | // 51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 52 | // 方法是按如下所示使用“*”: : 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.2.*")] 55 | [assembly: AssemblyFileVersion("2.2.1")] 56 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BiliRanking.WPF.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BiliRanking.WPF.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 使用此强类型资源类,为所有资源查找 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BiliRanking.WPF.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.1.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("")] 29 | public string access_key { 30 | get { 31 | return ((string)(this["access_key"])); 32 | } 33 | set { 34 | this["access_key"] = value; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Resources/NoAvatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SkiTiSu/BiliRanking/26509add8011d92ff5acd3a230a64a2ada940978/BiliRanking.WPF/Resources/NoAvatar.png -------------------------------------------------------------------------------- /BiliRanking.WPF/SharedData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using BiliRanking.Core; 9 | 10 | namespace BiliRanking.WPF 11 | { 12 | public static class SharedData 13 | { 14 | public static event EventHandler AVsChanged; 15 | 16 | private static string aVs = ""; 17 | public static string AVs 18 | { 19 | get 20 | { 21 | return aVs; 22 | } 23 | set 24 | { 25 | if (value != aVs) 26 | { 27 | aVs = value; 28 | AVsChanged?.Invoke(null, EventArgs.Empty); 29 | } 30 | } 31 | } 32 | 33 | public static IEnumerable SortedAVs 34 | { 35 | get => from s in Regex.Split((AVs != null) ? AVs : "" , "\r\n|\r|\n").ToList() 36 | where s != "" 37 | select s; 38 | set => AVs = String.Join("\r\n", value ?? new List()); 39 | } 40 | 41 | public static IEnumerable Infos { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /BiliRanking.WPF/UIHelpers.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.Data; 8 | using System.Windows.Media; 9 | 10 | namespace BiliRanking.WPF 11 | { 12 | //http://www.hardcodet.net/2009/03/moving-data-grid-rows-using-drag-and-drop 13 | public class UIHelpers 14 | { 15 | 16 | 17 | #region find parent 18 | 19 | /// 20 | /// Finds a parent of a given item on the visual tree. 21 | /// 22 | /// The type of the queried item. 23 | /// A direct or indirect child of the 24 | /// queried item. 25 | /// The first parent item that matches the submitted 26 | /// type parameter. If not matching item can be found, a null 27 | /// reference is being returned. 28 | public static T TryFindParent(DependencyObject child) 29 | where T : DependencyObject 30 | { 31 | //get parent item 32 | DependencyObject parentObject = GetParentObject(child); 33 | 34 | //we've reached the end of the tree 35 | if (parentObject == null) return null; 36 | 37 | //check if the parent matches the type we're looking for 38 | T parent = parentObject as T; 39 | if (parent != null) 40 | { 41 | return parent; 42 | } 43 | else 44 | { 45 | //use recursion to proceed with next level 46 | return TryFindParent(parentObject); 47 | } 48 | } 49 | 50 | 51 | /// 52 | /// This method is an alternative to WPF's 53 | /// method, which also 54 | /// supports content elements. Do note, that for content element, 55 | /// this method falls back to the logical tree of the element. 56 | /// 57 | /// The item to be processed. 58 | /// The submitted item's parent, if available. Otherwise 59 | /// null. 60 | public static DependencyObject GetParentObject(DependencyObject child) 61 | { 62 | if (child == null) return null; 63 | ContentElement contentElement = child as ContentElement; 64 | 65 | if (contentElement != null) 66 | { 67 | DependencyObject parent = ContentOperations.GetParent(contentElement); 68 | if (parent != null) return parent; 69 | 70 | FrameworkContentElement fce = contentElement as FrameworkContentElement; 71 | return fce != null ? fce.Parent : null; 72 | } 73 | 74 | //if it's not a ContentElement, rely on VisualTreeHelper 75 | return VisualTreeHelper.GetParent(child); 76 | } 77 | 78 | #endregion 79 | 80 | 81 | #region update binding sources 82 | 83 | /// 84 | /// Recursively processes a given dependency object and all its 85 | /// children, and updates sources of all objects that use a 86 | /// binding expression on a given property. 87 | /// 88 | /// The dependency object that marks a starting 89 | /// point. This could be a dialog window or a panel control that 90 | /// hosts bound controls. 91 | /// The properties to be updated if 92 | /// or one of its childs provide it along 93 | /// with a binding expression. 94 | public static void UpdateBindingSources(DependencyObject obj, 95 | params DependencyProperty[] properties) 96 | { 97 | foreach (DependencyProperty depProperty in properties) 98 | { 99 | //check whether the submitted object provides a bound property 100 | //that matches the property parameters 101 | BindingExpression be = BindingOperations.GetBindingExpression(obj, depProperty); 102 | if (be != null) be.UpdateSource(); 103 | } 104 | 105 | int count = VisualTreeHelper.GetChildrenCount(obj); 106 | for (int i = 0; i < count; i++) 107 | { 108 | //process child items recursively 109 | DependencyObject childObject = VisualTreeHelper.GetChild(obj, i); 110 | UpdateBindingSources(childObject, properties); 111 | } 112 | } 113 | 114 | #endregion 115 | 116 | 117 | /// 118 | /// Tries to locate a given item within the visual tree, 119 | /// starting with the dependency object at a given position. 120 | /// 121 | /// The type of the element to be found 122 | /// on the visual tree of the element at the given location. 123 | /// The main element which is used to perform 124 | /// hit testing. 125 | /// The position to be evaluated on the origin. 126 | public static T TryFindFromPoint(UIElement reference, Point point) 127 | where T : DependencyObject 128 | { 129 | DependencyObject element = reference.InputHitTest(point) 130 | as DependencyObject; 131 | if (element == null) return null; 132 | else if (element is T) return (T)element; 133 | else return TryFindParent(element); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /BiliRanking.WPF/Updater.cs: -------------------------------------------------------------------------------- 1 | using BiliRanking.Core; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Reflection; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Windows.Forms; 13 | 14 | namespace BiliRanking.WPF 15 | { 16 | 17 | public class Updater 18 | { 19 | private static NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); 20 | 21 | FileVersionInfo myFileVersion = FileVersionInfo.GetVersionInfo(Application.ExecutablePath); 22 | public string Version = ""; 23 | 24 | private const string UpdateURL = "http://dl.skitisu.com/biliranking/update.json"; 25 | private const string UserAgent = ""; 26 | 27 | public string LatestVersionNumber; 28 | 29 | private bool checkBeta = false; 30 | 31 | public Updater() 32 | { 33 | Version = myFileVersion.FileVersion; 34 | } 35 | 36 | public void CheckUpdate(bool beta = false) 37 | { 38 | checkBeta = beta; 39 | 40 | DirectoryInfo theFolder = new DirectoryInfo(FileManager.currentPath); 41 | FileInfo[] fileInfo = theFolder.GetFiles(); 42 | foreach (FileInfo file in fileInfo) 43 | { 44 | if (file.Name.Contains(".delete")) 45 | { 46 | File.Delete(file.FullName); 47 | log.Debug($"已删除更新残留文件{file.FullName}"); 48 | MessageBox.Show("更新完成o(^▽^)o", "蛤蛤蛤蛤蛤", MessageBoxButtons.OK, MessageBoxIcon.Information); 49 | } 50 | } 51 | 52 | try 53 | { 54 | log.Info("正在检查更新"); 55 | WebClient http = CreateWebClient(); 56 | http.DownloadStringCompleted += Http_DownloadStringCompleted; 57 | http.DownloadStringAsync(new Uri(UpdateURL + "?ts=" + ((DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds).ToString())); 58 | } 59 | catch 60 | { 61 | log.Error("检查更新失败 - 版本检查失败"); 62 | } 63 | } 64 | 65 | private void Http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 66 | { 67 | try 68 | { 69 | string response = e.Result; 70 | 71 | JObject result = JObject.Parse(response); 72 | 73 | //bool hasBeta = false; 74 | //bool hasStable = false; 75 | 76 | if (result != null) 77 | { 78 | JToken data = result["data"]; 79 | var ver = (string)data["version"]; 80 | int isnew = CompareVersion(ver, Version); 81 | 82 | if (isnew > 0) 83 | { 84 | log.Info($"发现新版本{ver}"); 85 | DialogResult res = MessageBox.Show($"发现新版本{ver}啦\r\n{data["updateInfo"]}\r\n\r\n马上更新嘛?", @"\(^o^)/更新啦", MessageBoxButtons.YesNo); 86 | if (res == DialogResult.Yes) 87 | { 88 | StartDownload((string)data["url"]); 89 | } 90 | else 91 | { 92 | log.Info("更新被取消"); 93 | } 94 | } 95 | else 96 | { 97 | log.Info("没有发现新版本"); 98 | } 99 | } 100 | } 101 | catch (Exception ex) 102 | { 103 | Log.Error("检查更新失败 - 解析json失败"); 104 | Log.Debug(ex.Message); 105 | } 106 | } 107 | 108 | string DownloadFileName = ""; 109 | 110 | private void StartDownload(string downloadurl) 111 | { 112 | Log.Info($"开始下载 - {downloadurl}"); 113 | Log.Info("提示:由于服务器在境外,下载可能比较慢,稍安勿躁哦!下载期间就不要再动程序了~"); 114 | 115 | DownloadFileName = Path.Combine(FileManager.currentPath, "BiliRanking.downloading"); 116 | try 117 | { 118 | WebClient http = CreateWebClient(); 119 | http.DownloadFileCompleted += Http_DownloadFileCompleted; ; 120 | http.DownloadFileAsync(new Uri(downloadurl), DownloadFileName); 121 | } 122 | catch (Exception ex) 123 | { 124 | Log.Error("文件下载失败"); 125 | Log.Debug(ex.Message); 126 | } 127 | } 128 | 129 | private void Http_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) 130 | { 131 | string filename = Assembly.GetExecutingAssembly().Location; 132 | File.Move(filename, filename + ".delete"); 133 | File.Move(DownloadFileName, FileManager.currentPath + $@"\BiliRanking.exe"); 134 | MessageBox.Show($"新版本已经准备完毕//天书好是辛苦的呢!\r\n我要重启自己来更新咯(●'◡'●)", "注意啊啊啊", MessageBoxButtons.OK, MessageBoxIcon.Information); 135 | System.Diagnostics.Process.Start(FileManager.currentPath + $@"\BiliRanking.exe"); 136 | //File.Move(filename + ".new", "BiliRanking.exe"); 137 | System.Windows.Application.Current.Shutdown(); 138 | } 139 | 140 | private WebClient CreateWebClient() 141 | { 142 | WebClient http = new WebClient(); 143 | http.Headers.Add("User-Agent", UserAgent); 144 | //http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); 145 | http.Encoding = System.Text.Encoding.UTF8; //否则遇到中文Json解析器会报错 146 | return http; 147 | } 148 | 149 | public static int CompareVersion(string l, string r) 150 | { 151 | if (l.StartsWith("V") || l.StartsWith("v")) 152 | l = l.Substring(1); 153 | var ls = l.Split('.'); 154 | var rs = r.Split('.'); 155 | for (int i = 0; i < Math.Max(ls.Length, rs.Length); i++) 156 | { 157 | int lp = (i < ls.Length) ? int.Parse(ls[i]) : 0; 158 | int rp = (i < rs.Length) ? int.Parse(rs[i]) : 0; 159 | if (lp != rp) 160 | { 161 | return lp - rp; 162 | } 163 | } 164 | return 0; 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /BiliRanking.WPF/View/Download.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 30 | Tip:全屏后将会关闭毛玻璃效果 31 | 32 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 开源项目 52 | 本项目使用LGPL-3.0协议在Github开源,请不要用于商业及非法用途,特别禁止“小曹铁路”及其支持者使用 54 | 55 | 56 | 57 | 65 | 66 | 同样是.NET开发者?欢迎点STAR并且一起来开发! 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /BiliRanking.WPF/View/Home.xaml.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 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 | 17 | namespace BiliRanking.WPF.View 18 | { 19 | /// 20 | /// Home.xaml 的交互逻辑 21 | /// 22 | public partial class Home : UserControl 23 | { 24 | public Home() 25 | { 26 | InitializeComponent(); 27 | 28 | textComplileVer.Text = "编译版本号:" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); 29 | } 30 | 31 | private void DonateButton_OnClick(object sender, RoutedEventArgs e) 32 | { 33 | Process.Start("https://github.com/SkiTiSu/BiliRanking"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /BiliRanking.WPF/View/ImageTemplateEditor.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 37 | 40 | 43 | 46 | 49 | 50 | 53 | 56 | 57 | 60 | 63 | 66 | 69 | 72 | 73 | 74 | 75 | 77 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |