├── .gitattributes
├── .gitignore
├── App.config
├── App.xaml
├── App.xaml.cs
├── BiliClass.cs
├── Bilibili_Client.csproj
├── Bilibili_Client.sln
├── Dictionary.xaml
├── Geometry.xaml
├── LICENSE
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── PasswordBoxMonitor.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
├── Settings.settings
├── app.manifest
├── 分区.png
├── 动态.png
├── 历史记录.png
├── 收藏夹.png
└── 首页.png
├── README.md
├── Space.xaml
├── Space.xaml.cs
├── geetest.xaml
├── geetest.xaml.cs
├── index.xaml
├── index.xaml.cs
├── login.xaml
├── login.xaml.cs
├── packages.config
├── packages.zip
├── resource
├── Web
│ └── geetest-validator
│ │ ├── css
│ │ └── style.css
│ │ ├── geetest.html
│ │ └── js
│ │ ├── gt.js
│ │ └── jquery.js
└── img
│ ├── BILIBILI_LOGO-PINK.png
│ ├── BILIBILI_LOGO.png
│ ├── Bilibili_User_Cover.png
│ ├── PILIPILI_LOGO.png
│ ├── cover.jpg
│ ├── exported_qrcode_image_600.png
│ ├── preview1.png
│ ├── preview2.png
│ ├── preview3.png
│ ├── preview4.png
│ ├── 二维码.png
│ ├── 头像.png
│ ├── 弹幕数.png
│ ├── 播放量.png
│ ├── 收藏数.png
│ ├── 点赞数.png
│ ├── 硬币数.png
│ ├── 评论数.png
│ ├── 账号.png
│ ├── 转发数.png
│ ├── 返回.png
│ └── 频道.png
├── video.xaml
└── video.xaml.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # JustCode is a .NET coding add-in
131 | .JustCode
132 |
133 | # TeamCity is a build add-in
134 | _TeamCity*
135 |
136 | # DotCover is a Code Coverage Tool
137 | *.dotCover
138 |
139 | # AxoCover is a Code Coverage Tool
140 | .axoCover/*
141 | !.axoCover/settings.json
142 |
143 | # Visual Studio code coverage results
144 | *.coverage
145 | *.coveragexml
146 |
147 | # NCrunch
148 | _NCrunch_*
149 | .*crunch*.local.xml
150 | nCrunchTemp_*
151 |
152 | # MightyMoose
153 | *.mm.*
154 | AutoTest.Net/
155 |
156 | # Web workbench (sass)
157 | .sass-cache/
158 |
159 | # Installshield output folder
160 | [Ee]xpress/
161 |
162 | # DocProject is a documentation generator add-in
163 | DocProject/buildhelp/
164 | DocProject/Help/*.HxT
165 | DocProject/Help/*.HxC
166 | DocProject/Help/*.hhc
167 | DocProject/Help/*.hhk
168 | DocProject/Help/*.hhp
169 | DocProject/Help/Html2
170 | DocProject/Help/html
171 |
172 | # Click-Once directory
173 | publish/
174 |
175 | # Publish Web Output
176 | *.[Pp]ublish.xml
177 | *.azurePubxml
178 | # Note: Comment the next line if you want to checkin your web deploy settings,
179 | # but database connection strings (with potential passwords) will be unencrypted
180 | *.pubxml
181 | *.publishproj
182 |
183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
184 | # checkin your Azure Web App publish settings, but sensitive information contained
185 | # in these scripts will be unencrypted
186 | PublishScripts/
187 |
188 | # NuGet Packages
189 | *.nupkg
190 | # NuGet Symbol Packages
191 | *.snupkg
192 | # The packages folder can be ignored because of Package Restore
193 | **/[Pp]ackages/*
194 | # except build/, which is used as an MSBuild target.
195 | !**/[Pp]ackages/build/
196 | # Uncomment if necessary however generally it will be regenerated when needed
197 | #!**/[Pp]ackages/repositories.config
198 | # NuGet v3's project.json files produces more ignorable files
199 | *.nuget.props
200 | *.nuget.targets
201 |
202 | # Microsoft Azure Build Output
203 | csx/
204 | *.build.csdef
205 |
206 | # Microsoft Azure Emulator
207 | ecf/
208 | rcf/
209 |
210 | # Windows Store app package directories and files
211 | AppPackages/
212 | BundleArtifacts/
213 | Package.StoreAssociation.xml
214 | _pkginfo.txt
215 | *.appx
216 | *.appxbundle
217 | *.appxupload
218 |
219 | # Visual Studio cache files
220 | # files ending in .cache can be ignored
221 | *.[Cc]ache
222 | # but keep track of directories ending in .cache
223 | !?*.[Cc]ache/
224 |
225 | # Others
226 | ClientBin/
227 | ~$*
228 | *~
229 | *.dbmdl
230 | *.dbproj.schemaview
231 | *.jfm
232 | *.pfx
233 | *.publishsettings
234 | orleans.codegen.cs
235 |
236 | # Including strong name files can present a security risk
237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
238 | #*.snk
239 |
240 | # Since there are multiple workflows, uncomment next line to ignore bower_components
241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
242 | #bower_components/
243 |
244 | # RIA/Silverlight projects
245 | Generated_Code/
246 |
247 | # Backup & report files from converting an old project file
248 | # to a newer Visual Studio version. Backup files are not needed,
249 | # because we have git ;-)
250 | _UpgradeReport_Files/
251 | Backup*/
252 | UpgradeLog*.XML
253 | UpgradeLog*.htm
254 | ServiceFabricBackup/
255 | *.rptproj.bak
256 |
257 | # SQL Server files
258 | *.mdf
259 | *.ldf
260 | *.ndf
261 |
262 | # Business Intelligence projects
263 | *.rdl.data
264 | *.bim.layout
265 | *.bim_*.settings
266 | *.rptproj.rsuser
267 | *- [Bb]ackup.rdl
268 | *- [Bb]ackup ([0-9]).rdl
269 | *- [Bb]ackup ([0-9][0-9]).rdl
270 |
271 | # Microsoft Fakes
272 | FakesAssemblies/
273 |
274 | # GhostDoc plugin setting file
275 | *.GhostDoc.xml
276 |
277 | # Node.js Tools for Visual Studio
278 | .ntvs_analysis.dat
279 | node_modules/
280 |
281 | # Visual Studio 6 build log
282 | *.plg
283 |
284 | # Visual Studio 6 workspace options file
285 | *.opt
286 |
287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
288 | *.vbw
289 |
290 | # Visual Studio LightSwitch build output
291 | **/*.HTMLClient/GeneratedArtifacts
292 | **/*.DesktopClient/GeneratedArtifacts
293 | **/*.DesktopClient/ModelManifest.xml
294 | **/*.Server/GeneratedArtifacts
295 | **/*.Server/ModelManifest.xml
296 | _Pvt_Extensions
297 |
298 | # Paket dependency manager
299 | .paket/paket.exe
300 | paket-files/
301 |
302 | # FAKE - F# Make
303 | .fake/
304 |
305 | # CodeRush personal settings
306 | .cr/personal
307 |
308 | # Python Tools for Visual Studio (PTVS)
309 | __pycache__/
310 | *.pyc
311 |
312 | # Cake - Uncomment if you are using it
313 | # tools/**
314 | # !tools/packages.config
315 |
316 | # Tabs Studio
317 | *.tss
318 |
319 | # Telerik's JustMock configuration file
320 | *.jmconfig
321 |
322 | # BizTalk build output
323 | *.btp.cs
324 | *.btm.cs
325 | *.odx.cs
326 | *.xsd.cs
327 |
328 | # OpenCover UI analysis results
329 | OpenCover/
330 |
331 | # Azure Stream Analytics local run output
332 | ASALocalRun/
333 |
334 | # MSBuild Binary and Structured Log
335 | *.binlog
336 |
337 | # NVidia Nsight GPU debugger configuration file
338 | *.nvuser
339 |
340 | # MFractors (Xamarin productivity tool) working folder
341 | .mfractor/
342 |
343 | # Local History for Visual Studio
344 | .localhistory/
345 |
346 | # BeatPulse healthcheck temp database
347 | healthchecksdb
348 |
349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
350 | MigrationBackup/
351 |
352 | # Ionide (cross platform F# VS Code tools) working folder
353 | .ionide/
354 |
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using HandyControl.Data;
2 | using HandyControl.Tools;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Configuration;
6 | using System.Data;
7 | using System.Linq;
8 | using System.Management;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using Unosquare.FFME;
12 |
13 | namespace Bilibili_Client
14 | {
15 | ///
16 | /// App.xaml 的交互逻辑
17 | ///
18 | public partial class App : Application
19 | {
20 | protected override void OnStartup(StartupEventArgs e)
21 | {
22 | //if (Environment.Is64BitProcess)
23 | // Library.FFmpegDirectory = @"resource\FFmpeg\x64";
24 | //else
25 | // Library.FFmpegDirectory = @"resource\FFmpeg\x86";
26 | Library.FFmpegDirectory = @"resource\FFmpeg\";
27 | Library.LoadFFmpeg();
28 | MediaElement.FFmpegMessageLogged += (s, ev) =>
29 | {
30 | System.Diagnostics.Debug.WriteLine(ev.Message);
31 | };
32 | base.OnStartup(e);
33 |
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/BiliClass.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using RestSharp;
4 | using System;
5 | using System.Drawing.Imaging;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Security.Cryptography;
9 | using System.Text;
10 | using System.Text.RegularExpressions;
11 | using System.Windows;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Threading;
15 | namespace Bilibili_Client
16 | {
17 | public class Bilibili_Login//哔哩哔哩登录类
18 |
19 | {
20 | public DispatcherTimer Get_Scan_Login_Qrcode_status_Timer;
21 | public login Scan_login;
22 | public string Scan_oauthKey;
23 |
24 | //哔哩哔哩验证密钥类
25 | public class Verification_Key
26 | {
27 | public string gt;
28 | public string challenge;
29 | public string key;
30 | public string seccode;
31 | public string validate;
32 | public string tmp_code;
33 | public string phone;
34 | public int Sms_type = 0;
35 | }
36 |
37 | //哔哩哔哩Cookie类
38 | public class BiliCookie
39 | {
40 | public string DedeUserID;
41 | public string SESSDATA;
42 | public string bili_jct;
43 | }
44 |
45 | //获取结果的Cooie
46 | public BiliCookie Get_Cookie(string response)
47 | {
48 | BiliCookie biliCookie = new BiliCookie();
49 | biliCookie.DedeUserID = new Regex(@"DedeUserID=(?.*?)[&|;]", RegexOptions.IgnoreCase).Match(response).Groups["DedeUserID"].Value;
50 | biliCookie.SESSDATA = new Regex(@"SESSDATA=(?.*?)[&|;]", RegexOptions.IgnoreCase).Match(response).Groups["SESSDATA"].Value;
51 | biliCookie.bili_jct = new Regex(@"bili_jct=(?.*?)[&|;]", RegexOptions.IgnoreCase).Match(response).Groups["bili_jct"].Value;
52 | return biliCookie;
53 | }
54 |
55 | //获取登录Hash
56 | public string Password_login_Get_Hash()
57 | {
58 | var client = new RestClient("http://passport.bilibili.com/login?act=getkey");
59 | client.Timeout = -1;
60 | var request = new RestRequest(Method.GET);
61 | IRestResponse response = client.Execute(request);
62 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
63 | client = null;
64 | request = null;
65 | response = null;
66 | return recommend["hash"].ToString();
67 | }
68 |
69 | //获取极验密钥
70 | public Verification_Key Get_Verification_Key(int plat)
71 | {
72 | Verification_Key verification_key = new Verification_Key();
73 | var client = new RestClient("http://passport.bilibili.com/web/captcha/combine?plat=" + plat);
74 | client.Timeout = -1;
75 | var request = new RestRequest(Method.GET);
76 | IRestResponse response = client.Execute(request);
77 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
78 | verification_key.gt = recommend["data"]["result"]["gt"].ToString();
79 | verification_key.challenge = recommend["data"]["result"]["challenge"].ToString();
80 | verification_key.key = recommend["data"]["result"]["key"].ToString();
81 | client = null;
82 | request = null;
83 | response = null;
84 | recommend = null;
85 | return verification_key;
86 | }
87 |
88 | //(网页接口)密码登录
89 | public void Password_login_Web(string username, string password, string hash, Verification_Key verification_key, login login)
90 | {
91 |
92 | Coding coding = new Coding();
93 | var rsa = new RSACryptoServiceProvider();
94 | var public_key = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjb4V7EidX/ym28t2ybo0U6t0n
95 | 6p4ej8VjqKHg100va6jkNbNTrLQqMCQCAYtXMXXp2Fwkk6WR+12N9zknLjf+C9sx
96 | /+l48mjUU8RqahiFD1XT/u2e0m2EN029OhCgkHx3Fc/KlFSIbak93EH/XlYis0w+
97 | Xl69GV6klzgxW6d2xQIDAQAB";
98 | rsa.FromX509PublicKey(Convert.FromBase64String(public_key));
99 | var bytes = Convert.ToBase64String(rsa.Encrypt(Encoding.UTF8.GetBytes("mangohappy"), false));
100 | var client = new RestClient("http://passport.bilibili.com/web/login/v2");
101 | client.Timeout = -1;
102 | var request = new RestRequest(Method.POST);
103 | request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
104 | request.AddParameter("captchaType", "6");
105 | request.AddParameter("username", username);
106 | request.AddParameter("password", Convert.ToBase64String(rsa.Encrypt(Encoding.UTF8.GetBytes(hash + password), false)));
107 | request.AddParameter("keep", "true");
108 | request.AddParameter("key", verification_key.key);
109 | request.AddParameter("goUrl", coding.UrlEncode("https://www.bilibili.com/"));
110 | request.AddParameter("challenge", verification_key.challenge);
111 | request.AddParameter("validate", verification_key.validate);
112 | request.AddParameter("seccode", verification_key.seccode);
113 | IRestResponse response = client.Execute(request);
114 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
115 | string code = recommend["code"].ToString();
116 | if (string.Equals(code, "-2111"))
117 | {
118 | MessageBox.Show("由于您已开启二次验证,二次验证API出了点问题,请改用扫码或者验证码登录,抱歉了");
119 | /*Verification_Key Double_verification_key = Get_Verification_Key(7);
120 | Double_verification_key.Sms_type = 18;
121 | Double_verification_key.tmp_code = (recommend["data"].ToString()).Substring((recommend["data"].ToString()).IndexOf("tmp_token=") + 10, 32);*/
122 | login.Password_Login.Visibility = Visibility.Hidden;
123 | login.Sms_Code_Login.Visibility = Visibility.Visible;
124 | /*login.phone_textbox.Text = Double_verification_key.tmp_code;
125 | login.phone_textbox.IsReadOnly = true;
126 | login.Sms_code_Send_buttons.Content = "请验证";
127 | login.Sms_code_Send_buttons.IsEnabled = false;
128 | login.Sms_Login_button.Content = "请验证";
129 | login.Sms_Login_button.IsEnabled = false;
130 | login.sendKey_To_Geetest_page(Double_verification_key);*/
131 |
132 | }
133 | else if (string.Equals(code, "0"))
134 | {
135 | BiliCookie biliCookie = Get_Cookie(response.Content);
136 | Login_Success(biliCookie, login);
137 |
138 | }
139 | else
140 | {
141 | MessageBox.Show(response.Content);
142 | }
143 | client = null;
144 | request = null;
145 | response = null;
146 | recommend = null;
147 | code = null;
148 | }
149 |
150 | //发送手机验证码
151 | public void Send_Sms(Verification_Key verification_key, login login)
152 | {
153 | if (verification_key.Sms_type == 18)//二次验证
154 | {
155 | var client = new RestClient("https://api.bilibili.com/x/safecenter/sms/send");
156 | client.Timeout = -1;
157 | var request = new RestRequest(Method.POST);
158 | request.AddParameter("application/x-www-form-urlencoded",
159 | "type=18&captchaType=7" +
160 | "&captcha_key=" + verification_key.key +
161 | "&challenge=" + verification_key.challenge +
162 | "&validate=" + verification_key.validate +
163 | "&seccode=" + verification_key.seccode +
164 | "&tmp_code=" + verification_key.tmp_code
165 | , ParameterType.RequestBody);
166 | IRestResponse response = client.Execute(request);
167 | MessageBox.Show(response.Content);
168 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
169 | string code = recommend["code"].ToString();
170 | if (!string.Equals(code, "0"))
171 | {
172 | login.Sms_code_Send_buttons.Content = "失败";
173 | }
174 | client = null;
175 | request = null;
176 | response = null;
177 | recommend = null;
178 | code = null;
179 | }
180 | else if (verification_key.Sms_type == 21)//验证码登录
181 | {
182 | var client = new RestClient("http://passport.bilibili.com/web/sms/general/v2/send");
183 | client.Timeout = -1;
184 | var request = new RestRequest(Method.POST);
185 | request.AddParameter("application/x-www-form-urlencoded",
186 | "tel=" + verification_key.phone +
187 | "&cid=1&type=21&captchaType=6" +
188 | "&key=" + verification_key.key +
189 | "&challenge=" + verification_key.challenge +
190 | "&validate=" + verification_key.validate +
191 | "&seccode=" + verification_key.seccode, ParameterType.RequestBody);
192 | IRestResponse response = client.Execute(request);
193 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
194 | string code = recommend["code"].ToString();
195 | if (!string.Equals(code, "0"))
196 | {
197 | MessageBox.Show(response.Content);
198 | login.Sms_code_Send_buttons.Content = "发送";
199 | }
200 | else if (string.Equals(code, "0"))
201 | {
202 | login.Sms_code_Send_buttons.Content = "重发";
203 | login.Sms_Login_button.IsEnabled = true;
204 |
205 | }
206 | client = null;
207 | request = null;
208 | response = null;
209 | recommend = null;
210 | code = null;
211 |
212 | }
213 | }
214 |
215 | //手机验证码登录
216 | public void Sms_login(string Sms_Code, string ID, login login)
217 | {
218 | var client = new RestClient("http://passport.bilibili.com/web/login/rapid");
219 | client.Timeout = -1;
220 | var request = new RestRequest(Method.POST);
221 | request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
222 | request.AddHeader("Cookie", "sid=jd5w5fmn");
223 | request.AddParameter("cid", 1);
224 | request.AddParameter("tel", ID);
225 | request.AddParameter("smsCode", Sms_Code);
226 | IRestResponse response = client.Execute(request);
227 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
228 | string code = recommend["code"].ToString();
229 | if (!string.Equals(code, "0"))
230 | {
231 | MessageBox.Show(response.Content);
232 | }
233 | else if (string.Equals(code, "0"))
234 | {
235 | BiliCookie biliCookie = Get_Cookie(response.Headers[4].ToString());
236 | Login_Success(biliCookie, login);
237 |
238 | }
239 | client = null;
240 | request = null;
241 | response = null;
242 | recommend = null;
243 | code = null;
244 | }
245 |
246 | //获取登录二维码
247 | public void Get_Login_Qrcode(login login)
248 | {
249 | var client = new RestClient("http://passport.bilibili.com/qrcode/getLoginUrl");
250 | client.Timeout = -1;
251 | var request = new RestRequest(Method.GET);
252 | IRestResponse response = client.Execute(request);
253 | Console.WriteLine(response.Content);
254 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
255 | string url = recommend["data"]["url"].ToString();
256 | string oauthKey = recommend["data"]["oauthKey"].ToString();
257 | login.Qrcode_img.Source = login.NewQRCodeByThoughtWorks(url, ImageFormat.Png);
258 | Scan_login = login;
259 | Scan_oauthKey = oauthKey;
260 | Get_Scan_Login_Qrcode_status_Timer = new DispatcherTimer();
261 | Get_Scan_Login_Qrcode_status_Timer.Tick += new EventHandler(Get_Scan_Login_Qrcode_status);
262 | Get_Scan_Login_Qrcode_status_Timer.Interval = new TimeSpan(0, 0, 0, 1);
263 | Get_Scan_Login_Qrcode_status_Timer.Start();
264 | url = null;
265 | oauthKey = null;
266 | client = null;
267 | request = null;
268 | response = null;
269 | recommend = null;
270 | }
271 |
272 | //获取登录二维码的扫码状态
273 | public void Get_Scan_Login_Qrcode_status(object sender, EventArgs e)
274 | {
275 |
276 | var client = new RestClient("http://passport.bilibili.com/qrcode/getLoginInfo");
277 | var request = new RestRequest(Method.POST);
278 | request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
279 | request.AddParameter("oauthKey", Scan_oauthKey);
280 | IRestResponse response = client.Execute(request);
281 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
282 | if (string.Equals(recommend["status"].ToString(), "True"))
283 | {
284 | BiliCookie biliCookie = Get_Cookie(recommend["data"]["url"].ToString());
285 | Qrcode_Login(biliCookie, Scan_login);
286 | Get_Scan_Login_Qrcode_status_Timer.Stop();
287 | Get_Scan_Login_Qrcode_status_Timer = null;
288 | }
289 | else if (string.Equals(recommend["status"].ToString(), "False"))
290 | {
291 | string data = recommend["data"].ToString();
292 | if (string.Equals(data, "-5"))
293 | {
294 | Scan_login.Scan_status.Text = "扫描成功,请在手机上确认是否授权";
295 | Scan_login.Scan_status.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(33, 211, 97));
296 | }
297 | else if (string.Equals(data, "-4"))
298 | {
299 | Scan_login.Scan_status.Text = "请使用 哔哩哔哩客户端 扫码登录";
300 | Scan_login.Scan_status.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(251, 114, 153));
301 | }
302 | else if (string.Equals(data, "-2"))
303 | {
304 | Scan_login.Scan_status.Text = "二维码已失效,请点击二维码刷新";
305 | Scan_login.Scan_status.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(208, 2, 27));
306 | Get_Scan_Login_Qrcode_status_Timer.Stop();
307 | Get_Scan_Login_Qrcode_status_Timer =null;
308 |
309 | }
310 | }
311 | client = null;
312 | request = null;
313 | response = null;
314 | recommend = null;
315 | }
316 |
317 | //二维码登录
318 | public void Qrcode_Login(BiliCookie biliCookie, login login)
319 | {
320 | Login_Success(biliCookie, login);
321 |
322 | }
323 |
324 | //登录成功后的操作
325 | public void Login_Success(BiliCookie biliCookie, login login)
326 | {
327 | if (false == Directory.Exists(@"Data\User\Account\Cookie"))
328 | {
329 | Directory.CreateDirectory(@"Data\User\Account\Cookie");
330 | }
331 | File.WriteAllText(@"Data\User\Account\Cookie\Login_User.Json", JsonConvert.SerializeObject(biliCookie), Encoding.UTF8);
332 | login.Login_Success();
333 |
334 | }
335 |
336 | }
337 |
338 | public class Bilibili_Account//哔哩哔哩账户类
339 | {
340 | public class BiliCookie
341 | {
342 | public string DedeUserID;
343 | public string SESSDATA;
344 | public string bili_jct;
345 | }
346 | public bool Check_Login_status()
347 | {
348 | if (File.Exists(@"Data\User\Account\Cookie\Login_User.Json"))//如果存在用户数据文件
349 | {
350 | string Login_User_Json = File.ReadAllText(@"Data\User\Account\Cookie\Login_User.Json");
351 | var client = new RestClient("http://api.bilibili.com/x/web-interface/nav");
352 | var request = new RestRequest(Method.GET);
353 | request.AddCookie("SESSDATA", ((JObject)JsonConvert.DeserializeObject(Login_User_Json))["SESSDATA"].ToString());
354 | IRestResponse response = client.Execute(request);
355 | if (string.Equals(((JObject)JsonConvert.DeserializeObject(response.Content))["code"].ToString(), "0"))
356 | {
357 | client = null;
358 | request = null;
359 | response = null;
360 | return true;
361 | }
362 | else
363 | {
364 | client = null;
365 | request = null;
366 | response = null;
367 | return false;
368 | }
369 | }
370 | else
371 | {
372 | return false;
373 | }
374 |
375 | }
376 | public void Set_User_Data(MainWindow mainWindow)
377 | {
378 | string Login_User_Json = File.ReadAllText(@"Data\User\Account\Cookie\Login_User.Json");
379 | mainWindow.BiliCookie.SESSDATA = ((JObject)JsonConvert.DeserializeObject(Login_User_Json))["SESSDATA"].ToString();
380 | mainWindow.BiliCookie.DedeUserID = ((JObject)JsonConvert.DeserializeObject(Login_User_Json))["DedeUserID"].ToString();
381 | mainWindow.BiliCookie.bili_jct = ((JObject)JsonConvert.DeserializeObject(Login_User_Json))["bili_jct"].ToString();
382 | var client = new RestClient("http://api.bilibili.com/x/web-interface/nav");
383 | var request = new RestRequest(Method.GET);
384 | request.AddCookie("SESSDATA", mainWindow.BiliCookie.SESSDATA);
385 | IRestResponse response = client.Execute(request);
386 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
387 | JToken data = recommend["data"];
388 | string User_Cover = data["face"].ToString();
389 | string User_Name = data["uname"].ToString();
390 | mainWindow.Login_Button.Visibility = Visibility.Hidden;
391 | mainWindow.User_Name_Grid.Visibility = Visibility.Visible;
392 | mainWindow.User_SideMenu.Visibility = Visibility.Visible;
393 | mainWindow.User_Name_Label.Text = User_Name;
394 | mainWindow.User_Cover_Img.Source = new BitmapImage(new Uri(User_Cover, UriKind.RelativeOrAbsolute));
395 | mainWindow.User_Exp_Bar.Value = (data["level_info"]["current_exp"].ToObject() / data["level_info"]["current_min"].ToObject()) * 100;
396 | client = null;
397 | request = null;
398 | response = null;
399 | User_Name = null;
400 | User_Cover = null;
401 | data = null;
402 | recommend = null;
403 | }
404 | public string Get_User_Data(string str1, string str2, bool If_Doubel, MainWindow mainWindow)
405 | {
406 | string SESSDATA = mainWindow.BiliCookie.SESSDATA;
407 | if (If_Doubel)
408 | {
409 | var client = new RestClient("http://api.bilibili.com/x/web-interface/nav");
410 | var request = new RestRequest(Method.GET);
411 | request.AddCookie("SESSDATA", SESSDATA);
412 | IRestResponse response = client.Execute(request);
413 | client = null;
414 | request = null;
415 | return ((JObject)JsonConvert.DeserializeObject(response.Content))["data"][str1][str2].ToString();
416 | }
417 | else
418 | {
419 | var client = new RestClient("http://api.bilibili.com/x/web-interface/nav");
420 | var request = new RestRequest(Method.GET);
421 | request.AddCookie("SESSDATA", SESSDATA);
422 | IRestResponse response = client.Execute(request);
423 | client = null;
424 | request = null;
425 | return ((JObject)JsonConvert.DeserializeObject(response.Content))["data"][str1].ToString();
426 | }
427 |
428 |
429 |
430 | }
431 |
432 |
433 | }
434 |
435 | public class Bilibili_Video
436 | {
437 | public struct video_info
438 | {
439 | public bool Success;
440 | public string aid;//视频avID
441 | public string bvid;//视频bvID
442 | public int videos;//视频分P总数
443 | public int tid;//分区ID
444 | public string tname;//子分区名称
445 | public int copyright;//版权标志 1:自制 2:转载
446 | public string pic;//视频封面图片url
447 | public string title;//视频标题
448 | public string ctime;//视频审核通过时间
449 | public string desc;//视频简介
450 | public string mid;//UP主UID
451 | public string name;//UP主昵称
452 | public string face;//UP主头像
453 | public int view;//观看次数 普通:0 屏蔽时:-1
454 | public int danmaku;//弹幕数
455 | public int reply;//评论数
456 | public int favorite;//收藏数
457 | public int coin;//投币数
458 | public int share;//分享数
459 | public int like;//获赞数
460 | public pages[] pages;
461 | }
462 | public struct pages//视频分P列表
463 | {
464 | public string cid;//当前分P CID
465 | public int page;//当前分P
466 | public string part;//当前分P标题
467 | }
468 | public struct P_data
469 | {
470 | public bool Success;
471 | public string url;
472 | public string[] accept_description;
473 | public int[] accept_quality;
474 | }
475 | public video_info gets_video_info(string aid)
476 | {
477 | var client = new RestClient("http://api.bilibili.com/x/web-interface/view?aid=" + aid);
478 | client.Timeout = -1;
479 | var request = new RestRequest(Method.GET);
480 | IRestResponse response = client.Execute(request);
481 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
482 | video_info videoinfo = new video_info();
483 | JToken data = recommend["data"];
484 | if (Convert.ToInt32(recommend["code"]) == 0)
485 | {
486 | videoinfo.Success = true;
487 | videoinfo.aid = aid;
488 | videoinfo.bvid = data["bvid"].ToString();
489 | videoinfo.videos = Convert.ToInt32(data["videos"]);
490 | videoinfo.tid= Convert.ToInt32(data["tid"]);
491 | videoinfo.tname = data["tname"].ToString();
492 | videoinfo.copyright = Convert.ToInt32(data["copyright"]);
493 | videoinfo.pic = data["pic"].ToString();
494 | videoinfo.title = data["title"].ToString();
495 | videoinfo.ctime = data["ctime"].ToString();
496 | videoinfo.desc = data["desc"].ToString();
497 | videoinfo.mid= data["owner"]["mid"].ToString();
498 | videoinfo.name = data["owner"]["name"].ToString();
499 | videoinfo.face = data["owner"]["face"].ToString();
500 | videoinfo.view = Convert.ToInt32(data["stat"]["view"]);
501 | videoinfo.danmaku = Convert.ToInt32(data["stat"]["danmaku"]);
502 | videoinfo.reply = Convert.ToInt32(data["stat"]["reply"]);
503 | videoinfo.favorite = Convert.ToInt32(data["stat"]["favorite"]);
504 | videoinfo.coin = Convert.ToInt32(data["stat"]["coin"]);
505 | videoinfo.share = Convert.ToInt32(data["stat"]["share"]);
506 | videoinfo.like = Convert.ToInt32(data["stat"]["like"]);
507 | videoinfo.pages = new pages[videoinfo.videos];
508 | for(int i=0;i
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}
8 | WinExe
9 | Bilibili_Client
10 | Bilibili_Client
11 | v4.7.2
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 | false
18 | publish\
19 | true
20 | Disk
21 | false
22 | Foreground
23 | 7
24 | Days
25 | false
26 | false
27 | true
28 | 1
29 | 1.0.0.%2a
30 | false
31 | true
32 | true
33 |
34 |
35 | AnyCPU
36 | false
37 | none
38 | true
39 | bin\Debug\
40 | DEBUG;TRACE
41 | prompt
42 | 4
43 | Off
44 | true
45 |
46 |
47 | AnyCPU
48 | pdbonly
49 | true
50 | bin\Release\
51 | TRACE
52 | prompt
53 | 4
54 |
55 |
56 | true
57 | bin\x64\Debug\
58 | DEBUG;TRACE
59 | full
60 | x64
61 | 7.3
62 | prompt
63 | MinimumRecommendedRules.ruleset
64 | true
65 |
66 |
67 | bin\x64\Release\
68 | TRACE
69 | true
70 | pdbonly
71 | x64
72 | 7.3
73 | prompt
74 | MinimumRecommendedRules.ruleset
75 | true
76 |
77 |
78 | Bilibili_Client.App
79 |
80 |
81 | 992250BCF539864B5D8D75A20EB695D5E851B07D
82 |
83 |
84 | Bilibili_Client_TemporaryKey.pfx
85 |
86 |
87 | true
88 |
89 |
90 | LocalIntranet
91 |
92 |
93 |
94 | true
95 |
96 |
97 |
98 |
99 | packages\CommonServiceLocator.2.0.2\lib\net47\CommonServiceLocator.dll
100 |
101 |
102 | packages\FFME.Windows.4.2.330\lib\net472\ffme.win.dll
103 |
104 |
105 | packages\FFmpeg.AutoGen.4.2.0\lib\net45\FFmpeg.AutoGen.dll
106 |
107 |
108 | packages\MvvmLightLibs.5.4.1.1\lib\net45\GalaSoft.MvvmLight.dll
109 |
110 |
111 | packages\MvvmLightLibs.5.4.1.1\lib\net45\GalaSoft.MvvmLight.Extras.dll
112 |
113 |
114 | packages\MvvmLightLibs.5.4.1.1\lib\net45\GalaSoft.MvvmLight.Platform.dll
115 |
116 |
117 | packages\HandyControl.2.5.0.2\lib\net47\HandyControl.dll
118 | False
119 |
120 |
121 | packages\Microsoft.Xaml.Behaviors.Wpf.1.1.19\lib\net45\Microsoft.Xaml.Behaviors.dll
122 |
123 |
124 | packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
125 |
126 |
127 | packages\Prism.Core.7.2.0.1422\lib\net45\Prism.dll
128 |
129 |
130 | packages\RestSharp.106.11.4\lib\net452\RestSharp.dll
131 |
132 |
133 |
134 | packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll
135 |
136 |
137 |
138 |
139 | packages\System.Extended.3.4.16.616\lib\net40\System.Extended.dll
140 |
141 |
142 |
143 | packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
144 |
145 |
146 | packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
147 |
148 |
149 |
150 |
151 | packages\MvvmLightLibs.5.4.1.1\lib\net45\System.Windows.Interactivity.dll
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | 4.0
161 |
162 |
163 | packages\ThoughtWorks.QRCode.1.1.0\lib\ThoughtWorks.QRCode.dll
164 |
165 |
166 | packages\Vlc.DotNet.Core.3.1.0\lib\net45\Vlc.DotNet.Core.dll
167 |
168 |
169 | packages\Vlc.DotNet.Core.Interops.3.1.0\lib\net45\Vlc.DotNet.Core.Interops.dll
170 |
171 |
172 | packages\Vlc.DotNet.Wpf.3.1.0\lib\net45\Vlc.DotNet.Wpf.dll
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | MSBuild:Compile
181 | Designer
182 |
183 |
184 |
185 | geetest.xaml
186 |
187 |
188 | login.xaml
189 |
190 |
191 |
192 | Space.xaml
193 |
194 |
195 | video.xaml
196 |
197 |
198 | Designer
199 | MSBuild:Compile
200 |
201 |
202 | Designer
203 | MSBuild:Compile
204 |
205 |
206 | Designer
207 | MSBuild:Compile
208 |
209 |
210 | Designer
211 | MSBuild:Compile
212 |
213 |
214 | Designer
215 | MSBuild:Compile
216 |
217 |
218 | MSBuild:Compile
219 | Designer
220 |
221 |
222 | App.xaml
223 | Code
224 |
225 |
226 | index.xaml
227 |
228 |
229 | MainWindow.xaml
230 | Code
231 |
232 |
233 | Designer
234 | MSBuild:Compile
235 |
236 |
237 | Designer
238 | MSBuild:Compile
239 |
240 |
241 |
242 |
243 | Code
244 |
245 |
246 | True
247 | True
248 | Resources.resx
249 |
250 |
251 | True
252 | Settings.settings
253 | True
254 |
255 |
256 | ResXFileCodeGenerator
257 | Resources.Designer.cs
258 |
259 |
260 |
261 |
262 |
263 | SettingsSingleFileGenerator
264 | Settings.Designer.cs
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 | False
298 | Microsoft .NET Framework 4.7.2 %28x86 和 x64%29
299 | true
300 |
301 |
302 | False
303 | .NET Framework 3.5 SP1
304 | false
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 | Always
331 |
332 |
333 | Always
334 |
335 |
336 | Always
337 |
338 |
339 | Always
340 |
341 |
342 |
343 |
--------------------------------------------------------------------------------
/Bilibili_Client.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30320.27
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bilibili_Client", "Bilibili_Client.csproj", "{A871B3C0-D4C9-43ED-91D8-0F0770C8D282}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Release|Any CPU = Release|Any CPU
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Debug|x64.ActiveCfg = Debug|x64
19 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Debug|x64.Build.0 = Debug|x64
20 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Release|x64.ActiveCfg = Release|x64
23 | {A871B3C0-D4C9-43ED-91D8-0F0770C8D282}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {A32B4097-557D-4F4E-837A-0C7143126E76}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/Dictionary.xaml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
81 |
84 |
85 |
93 |
94 |
102 |
103 |
104 |
105 |
110 |
111 |
119 |
120 |
121 |
122 |
127 |
128 |
136 |
137 |
138 |
139 |
144 |
145 |
153 |
154 |
155 |
156 |
161 |
162 |
170 |
171 |
172 |
173 |
178 |
179 |
187 |
188 |
189 |
190 |
195 |
196 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
217 |
220 |
221 |
226 |
227 |
235 |
236 |
237 |
238 |
243 |
244 |
252 |
253 |
254 |
255 |
260 |
261 |
269 |
270 |
271 |
272 |
273 |
278 |
279 |
287 |
288 |
289 |
290 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
311 |
314 |
315 |
316 |
317 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
329 |
330 |
331 |
332 |
337 |
338 |
339 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
369 |
370 |
371 |
372 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
--------------------------------------------------------------------------------
/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using HandyControl.Controls;
2 | using Prism.Commands;
3 | using System;
4 | using System.ComponentModel;
5 | using System.IO;
6 | using System.Windows;
7 | using System.Windows.Input;
8 | using System.Windows.Media;
9 | using System.Windows.Threading;
10 |
11 | namespace Bilibili_Client
12 | {
13 |
14 |
15 | public partial class MainWindow : System.Windows.Window
16 | {
17 |
18 | // 实例化计时器
19 | private DispatcherTimer GCTimer = new DispatcherTimer();
20 | index index_page = new index();
21 | login login_page = new login();
22 | Space space_page = new Space();
23 | video video_page = new video();
24 | geetest geetest_page = new geetest();
25 | Bilibili_Account bilibili = new Bilibili_Account();
26 | public Bilibili_Account.BiliCookie BiliCookie = new Bilibili_Account.BiliCookie();
27 | public bool IsLogin = false;
28 | private delegate void MainWindow_SendMessage_To_Login_page();//主窗口发送给登录窗口类
29 | private MainWindow_SendMessage_To_Login_page mainWindow_SendMessage_To_Login_page;
30 |
31 | private delegate void MainWindow_Open_Video_page(string avid,MainWindow mainWindow);//主窗口发送给登录窗口类
32 | private MainWindow_Open_Video_page mainWindow_Open_Video_page;
33 |
34 | public MainWindow()
35 | {
36 | InitializeComponent();
37 | initialization();//初始化内容
38 | Adaptive();//屏幕自适应
39 | Message();//建立信息槽
40 | Create_data();//创建文件夹
41 |
42 | }
43 |
44 | //初始化内容
45 | private void initialization()
46 | {
47 | //初始化定时器,定时强制GC回收
48 | GCTimer.Tick += new EventHandler(TimerGC);
49 | GCTimer.Interval = new TimeSpan(0, 0, 0, 1);
50 | GCTimer.Start();
51 | middle_frame.Navigate(index_page);//默认打开主页
52 | if (bilibili.Check_Login_status())//判断是否登录
53 | {
54 | IsLogin = true;
55 | bilibili.Set_User_Data(this);
56 | }
57 | Last_sideMenuItem = Index_Button;
58 | Last_animationPath =(AnimationPath)Index_Button.Icon;
59 | Last_sideMenuItem.Foreground = new SolidColorBrush(Color.FromRgb(251, 114, 153));
60 | Last_animationPath.Stroke = new SolidColorBrush(Color.FromRgb(251, 114, 153));
61 | Last_animationPath.IsPlaying = true;
62 | }
63 |
64 | //屏幕自适应
65 | private void Adaptive()
66 | {
67 | WindowStartupLocation = WindowStartupLocation.CenterScreen;//显示位置屏幕居中
68 |
69 | }
70 |
71 | //建立信息槽
72 | private void Message()
73 | {
74 | login_page.Login_Success = Login_Success;//把登陆成功信号发给主窗口
75 | login_page.login_sendMessage_To_Mainwindow = MainWindow_Recevie_From_Login_Page;//把登录页面的发送函数和接受函数链接
76 | mainWindow_SendMessage_To_Login_page = login_page.Login_Recevie_From_Mainwindow;//把发送函数与登录页面的接收函数链接
77 | login_page.login_open_geetest_page = login_open_geetest_page;//登录页面控制主窗口打开验证页面
78 | geetest_page.geetest_SendKey_To_Login_page = login_page.Login_Recevie_Key_From_Geetest_page;//把验证页面的发送Key函数和登录页面接受Key函数链接
79 | geetest_page.geetest_SendSmsKey_To_Login_page = login_page.Login_Recevie_SmsKey_From_Geetest_page;//把验证页面的发送SmsKey函数和登录页面接受SmsKey函数链接
80 | login_page.sendKey_To_Geetest_page = geetest_page.Geetest_Get_Key_From_Login_Page;////把登录页面的发送函数和验证页面接受函数链接
81 | index_page.index_Page_Open_Video = Open_Video_Page;
82 | mainWindow_Open_Video_page=video_page.Open_New_Video;
83 | }
84 |
85 | //创建文件夹
86 | private void Create_data()
87 | {
88 | if (false == Directory.Exists(@"Data\Cache\Img\Cover"))
89 | {
90 | Directory.CreateDirectory(@"Data\Cache\Img\Cover");
91 | }
92 |
93 | }
94 | //主窗口从登录页面传回来的数据
95 | private void MainWindow_Recevie_From_Login_Page()
96 | {
97 |
98 |
99 | }
100 |
101 | //登录成功后操作
102 | private void Login_Success()
103 | {
104 | IsLogin = true;
105 | bilibili.Set_User_Data(this);
106 | middle_frame.Navigate(space_page);
107 | middle_title.Text = bilibili.Get_User_Data("uname", "", false, this) + "的个人空间";
108 | geetest_page.geetest_web.Dispose();
109 | geetest_page.Close();
110 | geetest_page = null;
111 | login_page = null;
112 |
113 | }
114 | //登录页面打开极验页面
115 | private void login_open_geetest_page()
116 | {
117 | geetest_page.Show();
118 | }
119 | private void Open_Video_Page(string avid)
120 | {
121 | middle_frame.Navigate(video_page);
122 | mainWindow_Open_Video_page(avid,this);
123 |
124 |
125 | }
126 | private void Window_MouseMove(object sender, MouseEventArgs e)//移动窗口
127 | {
128 | if (e.LeftButton == MouseButtonState.Pressed)
129 | {
130 | this.DragMove();
131 | }
132 | }
133 |
134 | //主页按钮
135 | private void Index_Refresh_button(object sender, RoutedEventArgs e)
136 | {
137 |
138 | mainWindow_SendMessage_To_Login_page();
139 | }
140 | // 定时器 GC
141 | private void TimerGC(object sender, EventArgs e)
142 | {
143 | GC.Collect();
144 | GC.WaitForPendingFinalizers();
145 | }
146 |
147 | //点击头像
148 | private void Open_User_Space(object sender, MouseButtonEventArgs e)
149 | {
150 | if (IsLogin)
151 | {
152 | middle_frame.Navigate(space_page);
153 | middle_title.Text = bilibili.Get_User_Data("uname", "", false, this)+"的个人空间";
154 |
155 |
156 | }
157 | else
158 | {
159 | middle_frame.Navigate(login_page);
160 | middle_title.Text ="登录";
161 | }
162 | Last_sideMenuItem.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
163 | Last_animationPath.IsPlaying = false;
164 | Last_animationPath.Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0));
165 |
166 | }
167 | //打开首页的按钮
168 | private void Open_Index(object sender, MouseButtonEventArgs e)
169 | {
170 | middle_frame.Navigate(index_page);
171 | middle_title.Text = "首页";
172 |
173 | }
174 |
175 |
176 | //登录按钮
177 | private void Login_Button_Click(object sender, RoutedEventArgs e)
178 | {
179 | middle_frame.Navigate(login_page);
180 | middle_title.Text = "登录";
181 | Last_sideMenuItem.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
182 | Last_animationPath.IsPlaying = false;
183 | Last_animationPath.Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0));
184 | }
185 |
186 | //页面返回按钮
187 | private void Black(object sender, RoutedEventArgs e)
188 | {
189 | if (middle_frame.CanGoBack)
190 | {
191 | if (video_page.Media.IsPlaying)
192 | {
193 | var converter = TypeDescriptor.GetConverter(typeof(Geometry));
194 | ((System.Windows.Shapes.Path)video_page.Pause_Button.Content).Data = (Geometry)(converter.ConvertFrom("M442.181818 709.818182c0 37.236364-30.254545 69.818182-69.818182 69.818182s-69.818182-30.254545-69.818181-69.818182v-395.636364c0-37.236364 30.254545-69.818182 69.818181-69.818182s69.818182 30.254545 69.818182 69.818182v395.636364z m279.272727 0c0 37.236364-30.254545 69.818182-69.818181 69.818182s-69.818182-30.254545-69.818182-69.818182v-395.636364c0-37.236364 30.254545-69.818182 69.818182-69.818182s69.818182 30.254545 69.818181 69.818182v395.636364z"));
195 | video_page.Media.Close();
196 | middle_frame.GoBack();
197 |
198 | }else
199 | middle_frame.GoBack();
200 | }
201 | }
202 |
203 | private void Left_SideMenu_SelectionChanged(object sender, HandyControl.Data.FunctionEventArgs
10 |
11 |     
12 |
13 | ## 项目截图
14 |
15 | 
16 |
17 | ## 项目引用
18 |
19 | * [WPF](https://github.com/dotnet/wpf)
20 | * [ HandyControl](https://github.com/HandyOrg/HandyControl)
21 |
--------------------------------------------------------------------------------
/Space.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Space.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 Bilibili_Client
17 | {
18 | ///
19 | /// Space.xaml 的交互逻辑
20 | ///
21 | public partial class Space : Page
22 | {
23 | public Space()
24 | {
25 | InitializeComponent();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/geetest.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/geetest.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Security.Permissions;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Data;
13 | using System.Windows.Documents;
14 | using System.Windows.Input;
15 | using System.Windows.Media;
16 | using System.Windows.Media.Imaging;
17 | using System.Windows.Shapes;
18 |
19 | namespace Bilibili_Client
20 | {
21 | ///
22 | /// geetest.xaml 的交互逻辑
23 | ///
24 | ///
25 | [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
26 | [ComVisible(true)]
27 |
28 | public class ObjectForScriptingHelper
29 | {
30 | geetest page;
31 | public ObjectForScriptingHelper(geetest main)
32 | {
33 | page = main;
34 | }
35 | public void SendKey(string validateg, string seccode)//网页回调
36 | {
37 | page.verification_keys.validate = validateg;
38 | page.verification_keys.seccode = seccode;
39 |
40 | if (page.verification_keys.Sms_type == 0)
41 | {
42 | this.page.Hide();
43 | page.geetest_SendKey_To_Login_page(page.verification_keys);
44 | }
45 | else
46 | {
47 | this.page.Hide();
48 | page.geetest_SendSmsKey_To_Login_page(page.verification_keys);
49 | }
50 |
51 | }
52 | }
53 | public partial class geetest : Window
54 | {
55 | public delegate void Geetest_SendKey_To_Login_page(Bilibili_Login.Verification_Key verification_key);
56 | public Geetest_SendKey_To_Login_page geetest_SendKey_To_Login_page;
57 | public Geetest_SendKey_To_Login_page geetest_SendSmsKey_To_Login_page;
58 |
59 | public Bilibili_Login.Verification_Key verification_keys = new Bilibili_Login.Verification_Key();
60 | public geetest()
61 | {
62 | InitializeComponent();
63 | WindowStartupLocation = WindowStartupLocation.CenterScreen;//显示位置屏幕居中
64 | SetWebBrowserFeatures();//IE11
65 | }
66 | public void Geetest_Get_Key_From_Login_Page(Bilibili_Login.Verification_Key verification_key)
67 | {
68 | verification_keys = verification_key;
69 | ObjectForScriptingHelper helper = new ObjectForScriptingHelper(this);
70 | geetest_web.ObjectForScripting = helper;
71 | geetest_web.Source = new Uri(@"pack://siteoforigin:,,,/resource/Web/geetest-validator/geetest.html?challenge=" + verification_keys.challenge + ">=" + verification_keys.gt);
72 | }
73 | static void SetWebBrowserFeatures()
74 | {
75 | if (LicenseManager.UsageMode != LicenseUsageMode.Runtime)
76 | return;
77 | var appName = System.IO.Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
78 | UInt32 ieMode = (UInt32)11001;
79 | var featureControlRegKey = @"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\";
80 | Registry.SetValue(featureControlRegKey + "FEATURE_BROWSER_EMULATION",
81 | appName, ieMode, RegistryValueKind.DWord);
82 | Registry.SetValue(featureControlRegKey + "FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION",
83 | appName, 1, RegistryValueKind.DWord);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/index.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
15 |
16 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
32 |
33 |
34 |
35 |
42 |
43 |
44 |
45 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
58 |
80 |
81 |
82 |
86 |
92 |
93 |
94 |
95 |
96 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
136 |
137 |
145 |
146 |
147 |
148 |
149 |
156 |
157 |
165 |
166 |
167 |
168 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
187 |
188 |
191 |
192 |
193 |
194 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
--------------------------------------------------------------------------------
/index.xaml.cs:
--------------------------------------------------------------------------------
1 | using HandyControl.Controls;
2 | using Newtonsoft.Json;
3 | using Newtonsoft.Json.Linq;
4 | using RestSharp;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.ComponentModel;
8 | using System.IO;
9 | using System.Linq;
10 | using System.Net;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using System.Windows;
14 | using System.Windows.Controls;
15 | using System.Windows.Input;
16 | using System.Windows.Media.Media3D;
17 | using System.Windows.Threading;
18 |
19 |
20 |
21 | namespace Bilibili_Client
22 | {
23 | ///
24 | /// index.xaml 的交互逻辑
25 | ///
26 |
27 |
28 | public partial class index : Page
29 | {
30 | public delegate void Index_Page_Open_Video(string avid);//主窗口发送给登录窗口类
31 | public Index_Page_Open_Video index_Page_Open_Video;
32 | ManualResetEvent Thread_blocking = new ManualResetEvent(true);//线程阻塞
33 | CoverFlow coverFlow = new CoverFlow();
34 | int Download_Complete = 0;
35 | public index()
36 | {
37 |
38 | InitializeComponent();
39 | Thread Updata_Index_Featured_Video_Thread = new Thread(Updata_Index);//加载推荐视频的函数加入一个新的子线程
40 | Updata_Index_Featured_Video_Thread.Name = "Updata_Index_Featured_Video_Thread";
41 | Updata_Index_Featured_Video_Thread.Start();//线程开始
42 | Thread ADD_Homepage_Ad_Thread = new Thread(ADD_Homepage_Ad);//加载推荐视频的函数加入一个新的子线程
43 | ADD_Homepage_Ad_Thread.Name = "ADD_Homepage_Ad_Thread";
44 | ADD_Homepage_Ad_Thread.Start();//线程开始
45 | CoverFlow coverFlow = new CoverFlow();
46 | coverFlow.Margin = new Thickness(32);
47 | coverFlow.Width = 800;
48 | coverFlow.Height = 260;
49 | coverFlow.Loop = true;
50 | Index_Grid.Children.Add(coverFlow);
51 | }
52 | private readonly TaskScheduler _syncContextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
53 |
54 | //主页广告
55 | private void ADD_Homepage_Ad()
56 | {
57 |
58 | var client = new RestClient("https://app.bilibili.com/x/v2/feed/index?idx=0&flush=0&column=4&device=pad&pull=true&build=5520400&appkey=4ebafd7c4951b366&mobi_app=iphone&platform=ios&ts=1596754509&access_key=71626a38ce02b8a18b9a8b0dd8add481&sign=5d3bbfa008082c409bf56603278ea7a8");
59 | var request = new RestRequest(Method.GET);
60 | IRestResponse response = client.Execute(request);
61 | JObject recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
62 | JToken items = recommend["data"]["items"][0]["banner_item"];
63 | for (int i = 0; i <= items.Count() - 1; i++)
64 | {
65 |
66 | if (File.Exists(@"Data\Cache\Img\Cover\" + items[i]["id"].ToString() + ".jpg"))
67 | {
68 | coverFlow.Add(new Uri(@"Data\Cache\Img\Cover\" + items[i]["id"].ToString() + ".jpg", UriKind.Relative));
69 | Download_Complete++;
70 | }
71 | else
72 | {
73 |
74 | WebClient Client = new WebClient();
75 | Uri uri = new Uri(items[i]["image"].ToString());
76 | Client.DownloadFileCompleted += Down_Cover_Completed;
77 | Client.DownloadFileAsync(uri, @"Data\Cache\Img\Cover\" + items[i]["id"].ToString() + ".jpg", @"Data\Cache\Img\Cover\" + items[i]["id"].ToString() + ".jpg");
78 |
79 | }
80 | }
81 |
82 | Thread AD_Cover_Download_Completed_Thread=new Thread((obj) =>
83 | {
84 | while (true)
85 | {
86 | if (Download_Complete == (int)obj)
87 | {
88 | this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate ()
89 | {
90 | coverFlow.JumpTo(1);
91 | Index_Grid.Children.Add(coverFlow);
92 | });
93 | break;
94 | }
95 | }
96 | });
97 | AD_Cover_Download_Completed_Thread.Name = "AD_Cover_Download_Completed_Thread";
98 | AD_Cover_Download_Completed_Thread.Start(items.Count());
99 | client = null;
100 | request = null;
101 | response = null;
102 | recommend = null;
103 | }
104 |
105 | //广告封面下载完成
106 | private void Down_Cover_Completed(object sender, AsyncCompletedEventArgs e)
107 | {
108 |
109 | if (e.UserState != null)
110 | {
111 | coverFlow.Add(new Uri(e.UserState.ToString(), UriKind.Relative));
112 | Download_Complete++;
113 | }
114 | }
115 | bool IsCompleted = false;
116 | bool first = true;
117 | List double_row_videos = new List();
118 | JToken items;
119 | int last_count = 1;
120 | //主页推荐
121 | private void Updata_Index()
122 | {
123 | var client = new RestClient("https://app.bilibili.com/x/v2/feed/index?device=pad&mobi_app=iphone");
124 | IRestResponse response;
125 | JObject recommend;
126 | while (true)
127 | {
128 | Thread_blocking.WaitOne();
129 | if (last_count == 19 | last_count == 1)
130 | {
131 | var request = new RestRequest(Method.GET);
132 | response = client.Execute(request);
133 | recommend = (JObject)JsonConvert.DeserializeObject(response.Content);
134 | items = recommend["data"]["items"];
135 | last_count = 1;
136 | }
137 | IsCompleted = Parallel.For(last_count, first ? 18 : last_count + 3, (obj, loopstate) =>
138 | {
139 | double_row_videos.Add
140 | (
141 | new double_row_video(
142 | items[obj]["avatar"]["cover"].ToString() + "@20w_20h_1q.jpg",//up头像
143 | items[obj]["desc"].ToString(),//up名字
144 | items[obj]["cover"].ToString() + "@288w_180h_1q.jpg",//封面
145 | items[obj]["cover_left_text_1"].ToString(),//时长
146 | items[obj]["title"].ToString(),//标题
147 | items[obj]["args"]["rname"].ToString(),//分区
148 | items[obj]["cover_left_text_2"].ToString(),//播放量
149 | items[obj]["cover_left_text_3"].ToString(),//弹幕数
150 | items[obj]["param"].ToString()//AV号
151 | )
152 | );
153 | }).IsCompleted;
154 | Parallel_IsCompleted = IsCompleted;
155 | if (!first)
156 | {
157 | Thread_blocking.Reset();
158 |
159 | }
160 | else
161 | first = false;
162 | }
163 | }
164 | public bool Parallel_IsCompleted
165 | {
166 | get
167 | {
168 | return IsCompleted;
169 | }
170 | set
171 | {
172 | if (IsCompleted)
173 | this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate ()
174 | {
175 | for (int i = 0; i < double_row_videos.Count; i++)
176 | content_box.Items.Add(double_row_videos[i]);//按照模板加入一个item
177 | double_row_videos.Clear();
178 | last_count += 3;
179 | });
180 | }
181 | }
182 | public class double_row_video
183 | {
184 | public string head_img_url { get; private set; }
185 | public string video_cover { get; private set; }
186 | public string video_up { get; private set; }
187 | public string video_title { get; private set; }
188 | public string video_play_volume { get; private set; }
189 | public string video_barrages { get; private set; }
190 | public string video_duration { get; private set; }
191 | public string video_partition { get; private set; }
192 | public string Avid { get; private set; }
193 |
194 |
195 | public double_row_video(
196 | string up_head, //up头像
197 | string up,//up名字
198 | string cover,//封面
199 | string duration,//时长
200 | string title,//标题
201 | string partition,//分区
202 | string play_volume, //播放量
203 | string barrages, //弹幕数
204 | string avid//AV号
205 | )
206 | {
207 | head_img_url = up_head;//up头像
208 | video_up = up;//up名字
209 | video_cover = cover;//封面
210 | video_duration = duration;//时长
211 | video_title = title;//标题
212 | video_partition = partition;//分区
213 | video_play_volume = play_volume;//播放量
214 | video_barrages = barrages;//弹幕数
215 | Avid = avid;
216 |
217 | }
218 | }
219 | double last_ContentVerticalOffset = 0;
220 | private void ScrollChanged(object sender, ScrollChangedEventArgs e)
221 | {
222 | if (index_scrollViewer.ContentVerticalOffset - last_ContentVerticalOffset > 10 && index_scrollViewer.ScrollableHeight - index_scrollViewer.ContentVerticalOffset < 2000)
223 | {
224 | Thread_blocking.Set();
225 | last_ContentVerticalOffset = index_scrollViewer.ContentVerticalOffset;
226 | }
227 |
228 |
229 | }
230 |
231 | private void content_box_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
232 | {
233 | var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
234 | {
235 | RoutedEvent = UIElement.MouseWheelEvent,
236 | Source = sender
237 | };
238 | this.content_box.RaiseEvent(eventArg);
239 | }
240 |
241 |
242 | private void Goto_Video_Page(object sender, ExecutedRoutedEventArgs e)
243 | {
244 | string avid = ((Button)e.Parameter).Uid.ToString();
245 |
246 | index_Page_Open_Video(avid);
247 |
248 | }
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/login.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
69 |
70 |
71 |
72 |
73 |
74 |
79 |
85 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
102 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
112 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
129 |
136 |
137 |
138 |
142 |
143 |
144 |
145 |
156 |
157 |
158 |
159 |
160 |
161 |
166 |
172 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
189 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
201 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
217 |
218 |
219 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
235 |
241 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
--------------------------------------------------------------------------------
/login.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using System.Drawing.Imaging;
3 | using System.IO;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Web;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using ThoughtWorks.QRCode.Codec;
13 |
14 | namespace Bilibili_Client
15 | {
16 |
17 | public class Coding
18 | {
19 |
20 | public string MD5Encoding(string rawPass)
21 | {
22 | MD5 md5 = MD5.Create();
23 | byte[] bs = Encoding.UTF8.GetBytes(rawPass);
24 | byte[] hs = md5.ComputeHash(bs);
25 | StringBuilder stb = new StringBuilder();
26 | foreach (byte b in hs)
27 | {
28 | // 以十六进制格式格式化
29 | stb.Append(b.ToString("x2"));
30 | }
31 | bs = null;
32 | hs = null;
33 | md5 = null;
34 | md5.Dispose();
35 | return stb.ToString();
36 | }
37 |
38 | public string UrlEncode(string str)
39 | {
40 | StringBuilder builder = new StringBuilder();
41 | foreach (char c in str)
42 | {
43 | if (HttpUtility.UrlEncode(c.ToString()).Length > 1)
44 | {
45 | builder.Append(HttpUtility.UrlEncode(c.ToString()).ToUpper());
46 | }
47 | else
48 | {
49 | builder.Append(c);
50 | }
51 | }
52 | return builder.ToString();
53 | }
54 |
55 |
56 | }//加密函数
57 |
58 |
59 |
60 | public partial class login : Page
61 | {
62 | public delegate void Login_SendMessage_To_Mainwindow();
63 | public Login_SendMessage_To_Mainwindow login_sendMessage_To_Mainwindow;
64 | public Login_SendMessage_To_Mainwindow login_open_geetest_page;
65 | public Login_SendMessage_To_Mainwindow Login_Success;
66 |
67 | public delegate void SendKey_To_Geetest_page(Bilibili_Login.Verification_Key verification_key);
68 | public SendKey_To_Geetest_page sendKey_To_Geetest_page;
69 |
70 | Bilibili_Login bilibili = new Bilibili_Login();
71 | public login()
72 | {
73 | InitializeComponent();
74 |
75 | }
76 |
77 | //从主窗口接收信息
78 | public void Login_Recevie_From_Mainwindow()
79 | {
80 |
81 | }
82 |
83 | //从验证页面接收信息
84 | public void Login_Recevie_Key_From_Geetest_page(Bilibili_Login.Verification_Key verification_key)
85 | {
86 |
87 | bilibili.Password_login_Web(account_textbox.Text, password_textbox.Password, bilibili.Password_login_Get_Hash(), verification_key, this);
88 | }
89 |
90 | //从验证页面接收Key
91 | public void Login_Recevie_SmsKey_From_Geetest_page(Bilibili_Login.Verification_Key verification_key)
92 | {
93 | bilibili.Send_Sms(verification_key, this);
94 | }
95 |
96 | //密码登录按钮
97 | private void Password_Login_buttons_Click(object sender, RoutedEventArgs e)
98 | {
99 | login_open_geetest_page();
100 | sendKey_To_Geetest_page(bilibili.Get_Verification_Key(6));
101 | }
102 |
103 | //验证码登录发送验证码
104 | private void Sms_code_Send(object sender, RoutedEventArgs e)
105 | {
106 | login_open_geetest_page();
107 | Bilibili_Login.Verification_Key verification_key = bilibili.Get_Verification_Key(6);
108 | verification_key.Sms_type = 21;
109 |
110 | verification_key.phone = phone_textbox.Text;
111 | sendKey_To_Geetest_page(verification_key);
112 |
113 | }
114 |
115 | //验证码登录按钮
116 | private void Sms_code_Login(object sender, RoutedEventArgs e)
117 | {
118 | bilibili.Sms_login(smscode_textbox.Password, phone_textbox.Text,this);
119 | }
120 |
121 | //点击二维码刷新二维码
122 | private void Refresh_Qrcode(object sender, MouseButtonEventArgs e)
123 | {
124 | bilibili.Get_Scan_Login_Qrcode_status_Timer.Stop();
125 | bilibili.Get_Login_Qrcode(this);
126 | Scan_status.Text = "请使用 哔哩哔哩客户端 扫码登录";
127 | Scan_status.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(251, 114, 153));
128 | }
129 |
130 | //切换到密码登录页面
131 | private void Password(object sender, MouseButtonEventArgs e)
132 | {
133 | if (QrCode_Login.Visibility == Visibility.Visible)
134 | bilibili.Get_Scan_Login_Qrcode_status_Timer.Stop();
135 | Password_Login.Visibility = Visibility.Visible;
136 | Sms_Code_Login.Visibility = Visibility.Hidden;
137 | QrCode_Login.Visibility = Visibility.Hidden;
138 |
139 | }
140 |
141 | //切换到验证码登录页面
142 | private void Sms(object sender, MouseButtonEventArgs e)
143 | {
144 | if (QrCode_Login.Visibility == Visibility.Visible)
145 | bilibili.Get_Scan_Login_Qrcode_status_Timer.Stop();
146 | Password_Login.Visibility = Visibility.Hidden;
147 | Sms_Code_Login.Visibility = Visibility.Visible;
148 | QrCode_Login.Visibility = Visibility.Hidden;
149 | }
150 |
151 | //切换到二维码登录页面
152 | private void Qrcode(object sender, MouseButtonEventArgs e)
153 | {
154 | Password_Login.Visibility = Visibility.Hidden;
155 | Sms_Code_Login.Visibility = Visibility.Hidden;
156 | QrCode_Login.Visibility = Visibility.Visible;
157 | bilibili.Get_Login_Qrcode(this);
158 | }
159 |
160 | //生成二维码函数
161 | public BitmapImage NewQRCodeByThoughtWorks(string codeContent, ImageFormat imgType)
162 | {
163 | QRCodeEncoder encoder = new QRCodeEncoder();
164 | encoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;//编码方式(注意:BYTE能支持中文,ALPHA_NUMERIC扫描出来的都是数字)
165 | encoder.QRCodeScale = 10;//大小(值越大生成的二维码图片像素越高)
166 | encoder.QRCodeVersion = 0;//版本(注意:设置为0主要是防止编码的字符串太长时发生错误)
167 | encoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;//错误效验、错误更正(有4个等级)
168 | encoder.QRCodeBackgroundColor = System.Drawing.Color.White;
169 | encoder.QRCodeForegroundColor = System.Drawing.Color.FromArgb(251, 114, 153);
170 |
171 | Bitmap bcodeBitmap = encoder.Encode(codeContent);
172 | BitmapImage bitmapImage = BitmapToBitmapImage(bcodeBitmap);
173 | bcodeBitmap.Dispose();
174 | encoder = null;
175 | return bitmapImage;
176 | }
177 |
178 | //Bitmap转BitmapImage
179 | public BitmapImage BitmapToBitmapImage(Bitmap bitmap)
180 | {
181 | Bitmap bitmapSource = new Bitmap(bitmap.Width, bitmap.Height);
182 | int i, j;
183 | for (i = 0; i < bitmap.Width; i++)
184 | for (j = 0; j < bitmap.Height; j++)
185 | {
186 | System.Drawing.Color pixelColor = bitmap.GetPixel(i, j);
187 | System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixelColor.R, pixelColor.G, pixelColor.B);
188 | bitmapSource.SetPixel(i, j, newColor);
189 | }
190 | MemoryStream ms = new MemoryStream();
191 | bitmapSource.Save(ms, ImageFormat.Bmp);
192 | BitmapImage bitmapImage = new BitmapImage();
193 | bitmapImage.BeginInit();
194 | bitmapImage.StreamSource = new MemoryStream(ms.ToArray());
195 | bitmapImage.EndInit();
196 |
197 | bitmapSource.Dispose();
198 | ms.Dispose();
199 | bitmap.Dispose();
200 |
201 |
202 | return bitmapImage;
203 | }
204 |
205 | }
206 |
207 | }
208 |
--------------------------------------------------------------------------------
/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/packages.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/packages.zip
--------------------------------------------------------------------------------
/resource/Web/geetest-validator/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 50px 0;
3 | text-align: center;
4 | font-family: "PingFangSC-Regular", "Open Sans", Arial, "Hiragino Sans GB", "Microsoft YaHei", "STHeiti", "WenQuanYi Micro Hei", SimSun, sans-serif;
5 | }
6 |
7 | .inp {
8 | border: 1px solid #cccccc;
9 | border-radius: 2px;
10 | padding: 0 10px;
11 | width: 320px;
12 | height: 40px;
13 | font-size: 18px;
14 | }
15 |
16 | .btn {
17 | display: inline-block;
18 | box-sizing: border-box;
19 | border: 1px solid #cccccc;
20 | border-radius: 2px;
21 | width: 100px;
22 | height: 40px;
23 | line-height: 40px;
24 | font-size: 16px;
25 | color: #666;
26 | cursor: pointer;
27 | background: white linear-gradient(180deg, #ffffff 0%, #f3f3f3 100%);
28 | }
29 |
30 | .btn:hover {
31 | background: white linear-gradient(0deg, #ffffff 0%, #f3f3f3 100%)
32 | }
33 |
34 | #captcha {
35 | width: 300px;
36 | display: inline-block;
37 | }
38 |
39 | label {
40 | vertical-align: top;
41 | display: inline-block;
42 | width: 120px;
43 | text-align: right;
44 | }
45 |
46 | #text {
47 | height: 42px;
48 | width: 298px;
49 | text-align: center;
50 | border-radius: 2px;
51 | background-color: #F3F3F3;
52 | color: #BBBBBB;
53 | font-size: 14px;
54 | letter-spacing: 0.1px;
55 | line-height: 42px;
56 | }
57 |
58 | #wait {
59 | display: none;
60 | height: 42px;
61 | width: 298px;
62 | text-align: center;
63 | border-radius: 2px;
64 | background-color: #F3F3F3;
65 | }
66 |
67 | .loading {
68 | margin: auto;
69 | width: 70px;
70 | height: 20px;
71 | }
72 |
73 | .loading-dot {
74 | float: left;
75 | width: 8px;
76 | height: 8px;
77 | margin: 18px 4px;
78 | background: #ccc;
79 |
80 | -webkit-border-radius: 50%;
81 | -moz-border-radius: 50%;
82 | border-radius: 50%;
83 |
84 | opacity: 0;
85 |
86 | -webkit-box-shadow: 0 0 2px black;
87 | -moz-box-shadow: 0 0 2px black;
88 | -ms-box-shadow: 0 0 2px black;
89 | -o-box-shadow: 0 0 2px black;
90 | box-shadow: 0 0 2px black;
91 |
92 | -webkit-animation: loadingFade 1s infinite;
93 | -moz-animation: loadingFade 1s infinite;
94 | animation: loadingFade 1s infinite;
95 | }
96 |
97 | .loading-dot:nth-child(1) {
98 | -webkit-animation-delay: 0s;
99 | -moz-animation-delay: 0s;
100 | animation-delay: 0s;
101 | }
102 |
103 | .loading-dot:nth-child(2) {
104 | -webkit-animation-delay: 0.1s;
105 | -moz-animation-delay: 0.1s;
106 | animation-delay: 0.1s;
107 | }
108 |
109 | .loading-dot:nth-child(3) {
110 | -webkit-animation-delay: 0.2s;
111 | -moz-animation-delay: 0.2s;
112 | animation-delay: 0.2s;
113 | }
114 |
115 | .loading-dot:nth-child(4) {
116 | -webkit-animation-delay: 0.3s;
117 | -moz-animation-delay: 0.3s;
118 | animation-delay: 0.3s;
119 | }
120 |
121 | @-webkit-keyframes loadingFade {
122 | 0% { opacity: 0; }
123 | 50% { opacity: 0.8; }
124 | 100% { opacity: 0; }
125 | }
126 |
127 | @-moz-keyframes loadingFade {
128 | 0% { opacity: 0; }
129 | 50% { opacity: 0.8; }
130 | 100% { opacity: 0; }
131 | }
132 |
133 | @keyframes loadingFade {
134 | 0% { opacity: 0; }
135 | 50% { opacity: 0.8; }
136 | 100% { opacity: 0; }
137 | }
--------------------------------------------------------------------------------
/resource/Web/geetest-validator/geetest.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
24 |
25 |
26 |
27 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/resource/Web/geetest-validator/js/gt.js:
--------------------------------------------------------------------------------
1 | "v0.4.8 Geetest Inc.";
2 |
3 | (function (window) {
4 | "use strict";
5 | if (typeof window === 'undefined') {
6 | throw new Error('Geetest requires browser environment');
7 | }
8 |
9 | var document = window.document;
10 | var Math = window.Math;
11 | var head = document.getElementsByTagName("head")[0];
12 |
13 | function _Object(obj) {
14 | this._obj = obj;
15 | }
16 |
17 | _Object.prototype = {
18 | _each: function (process) {
19 | var _obj = this._obj;
20 | for (var k in _obj) {
21 | if (_obj.hasOwnProperty(k)) {
22 | process(k, _obj[k]);
23 | }
24 | }
25 | return this;
26 | }
27 | };
28 |
29 | function Config(config) {
30 | var self = this;
31 | new _Object(config)._each(function (key, value) {
32 | self[key] = value;
33 | });
34 | }
35 |
36 | Config.prototype = {
37 | api_server: 'api.geetest.com',
38 | protocol: 'http://',
39 | typePath: '/gettype.php',
40 | fallback_config: {
41 | slide: {
42 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
43 | type: 'slide',
44 | slide: '/static/js/geetest.0.0.0.js'
45 | },
46 | fullpage: {
47 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
48 | type: 'fullpage',
49 | fullpage: '/static/js/fullpage.0.0.0.js'
50 | }
51 | },
52 | _get_fallback_config: function () {
53 | var self = this;
54 | if (isString(self.type)) {
55 | return self.fallback_config[self.type];
56 | } else if (self.new_captcha) {
57 | return self.fallback_config.fullpage;
58 | } else {
59 | return self.fallback_config.slide;
60 | }
61 | },
62 | _extend: function (obj) {
63 | var self = this;
64 | new _Object(obj)._each(function (key, value) {
65 | self[key] = value;
66 | })
67 | }
68 | };
69 | var isNumber = function (value) {
70 | return (typeof value === 'number');
71 | };
72 | var isString = function (value) {
73 | return (typeof value === 'string');
74 | };
75 | var isBoolean = function (value) {
76 | return (typeof value === 'boolean');
77 | };
78 | var isObject = function (value) {
79 | return (typeof value === 'object' && value !== null);
80 | };
81 | var isFunction = function (value) {
82 | return (typeof value === 'function');
83 | };
84 | var MOBILE = /Mobi/i.test(navigator.userAgent);
85 | var pt = MOBILE ? 3 : 0;
86 |
87 | var callbacks = {};
88 | var status = {};
89 |
90 | var nowDate = function () {
91 | var date = new Date();
92 | var year = date.getFullYear();
93 | var month = date.getMonth() + 1;
94 | var day = date.getDate();
95 | var hours = date.getHours();
96 | var minutes = date.getMinutes();
97 | var seconds = date.getSeconds();
98 |
99 | if (month >= 1 && month <= 9) {
100 | month = '0' + month;
101 | }
102 | if (day >= 0 && day <= 9) {
103 | day = '0' + day;
104 | }
105 | if (hours >= 0 && hours <= 9) {
106 | hours = '0' + hours;
107 | }
108 | if (minutes >= 0 && minutes <= 9) {
109 | minutes = '0' + minutes;
110 | }
111 | if (seconds >= 0 && seconds <= 9) {
112 | seconds = '0' + seconds;
113 | }
114 | var currentdate = year + '-' + month + '-' + day + " " + hours + ":" + minutes + ":" + seconds;
115 | return currentdate;
116 | }
117 |
118 | var random = function () {
119 | return parseInt(Math.random() * 10000) + (new Date()).valueOf();
120 | };
121 |
122 | var loadScript = function (url, cb) {
123 | var script = document.createElement("script");
124 | script.charset = "UTF-8";
125 | script.async = true;
126 |
127 | // 对geetest的静态资源添加 crossOrigin
128 | if ( /static\.geetest\.com/g.test(url)) {
129 | script.crossOrigin = "anonymous";
130 | }
131 |
132 | script.onerror = function () {
133 | cb(true);
134 | };
135 | var loaded = false;
136 | script.onload = script.onreadystatechange = function () {
137 | if (!loaded &&
138 | (!script.readyState ||
139 | "loaded" === script.readyState ||
140 | "complete" === script.readyState)) {
141 |
142 | loaded = true;
143 | setTimeout(function () {
144 | cb(false);
145 | }, 0);
146 | }
147 | };
148 | script.src = url;
149 | head.appendChild(script);
150 | };
151 |
152 | var normalizeDomain = function (domain) {
153 | // special domain: uems.sysu.edu.cn/jwxt/geetest/
154 | // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn
155 | return domain.replace(/^https?:\/\/|\/$/g, ''); // uems.sysu.edu.cn/jwxt/geetest
156 | };
157 | var normalizePath = function (path) {
158 | path = path.replace(/\/+/g, '/');
159 | if (path.indexOf('/') !== 0) {
160 | path = '/' + path;
161 | }
162 | return path;
163 | };
164 | var normalizeQuery = function (query) {
165 | if (!query) {
166 | return '';
167 | }
168 | var q = '?';
169 | new _Object(query)._each(function (key, value) {
170 | if (isString(value) || isNumber(value) || isBoolean(value)) {
171 | q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
172 | }
173 | });
174 | if (q === '?') {
175 | q = '';
176 | }
177 | return q.replace(/&$/, '');
178 | };
179 | var makeURL = function (protocol, domain, path, query) {
180 | domain = normalizeDomain(domain);
181 |
182 | var url = normalizePath(path) + normalizeQuery(query);
183 | if (domain) {
184 | url = protocol + domain + url;
185 | }
186 |
187 | return url;
188 | };
189 |
190 | var load = function (config, send, protocol, domains, path, query, cb) {
191 | var tryRequest = function (at) {
192 |
193 | var url = makeURL(protocol, domains[at], path, query);
194 | loadScript(url, function (err) {
195 | if (err) {
196 | if (at >= domains.length - 1) {
197 | cb(true);
198 | // report gettype error
199 | if (send) {
200 | config.error_code = 508;
201 | var url = protocol + domains[at] + path;
202 | reportError(config, url);
203 | }
204 | } else {
205 | tryRequest(at + 1);
206 | }
207 | } else {
208 | cb(false);
209 | }
210 | });
211 | };
212 | tryRequest(0);
213 | };
214 |
215 |
216 | var jsonp = function (domains, path, config, callback) {
217 | if (isObject(config.getLib)) {
218 | config._extend(config.getLib);
219 | callback(config);
220 | return;
221 | }
222 | if (config.offline) {
223 | callback(config._get_fallback_config());
224 | return;
225 | }
226 |
227 | var cb = "geetest_" + random();
228 | window[cb] = function (data) {
229 | if (data.status == 'success') {
230 | callback(data.data);
231 | } else if (!data.status) {
232 | callback(data);
233 | } else {
234 | callback(config._get_fallback_config());
235 | }
236 | window[cb] = undefined;
237 | try {
238 | delete window[cb];
239 | } catch (e) {
240 | }
241 | };
242 | load(config, true, config.protocol, domains, path, {
243 | gt: config.gt,
244 | callback: cb
245 | }, function (err) {
246 | if (err) {
247 | callback(config._get_fallback_config());
248 | }
249 | });
250 | };
251 |
252 | var reportError = function (config, url) {
253 | load(config, false, config.protocol, ['monitor.geetest.com'], '/monitor/send', {
254 | time: nowDate(),
255 | captcha_id: config.gt,
256 | challenge: config.challenge,
257 | pt: pt,
258 | exception_url: url,
259 | error_code: config.error_code
260 | }, function (err) {})
261 | }
262 |
263 | var throwError = function (errorType, config) {
264 | var errors = {
265 | networkError: '网络错误',
266 | gtTypeError: 'gt字段不是字符串类型'
267 | };
268 | if (typeof config.onError === 'function') {
269 | config.onError(errors[errorType]);
270 | } else {
271 | throw new Error(errors[errorType]);
272 | }
273 | };
274 |
275 | var detect = function () {
276 | return window.Geetest || document.getElementById("gt_lib");
277 | };
278 |
279 | if (detect()) {
280 | status.slide = "loaded";
281 | }
282 |
283 | window.initGeetest = function (userConfig, callback) {
284 |
285 | var config = new Config(userConfig);
286 |
287 | if (userConfig.https) {
288 | config.protocol = 'https://';
289 | } else if (!userConfig.protocol) {
290 | config.protocol = window.location.protocol + '//';
291 | }
292 |
293 | // for KFC
294 | if (userConfig.gt === '050cffef4ae57b5d5e529fea9540b0d1' ||
295 | userConfig.gt === '3bd38408ae4af923ed36e13819b14d42') {
296 | config.apiserver = 'yumchina.geetest.com/'; // for old js
297 | config.api_server = 'yumchina.geetest.com';
298 | }
299 |
300 | if(userConfig.gt){
301 | window.GeeGT = userConfig.gt
302 | }
303 |
304 | if(userConfig.challenge){
305 | window.GeeChallenge = userConfig.challenge
306 | }
307 |
308 | if (isObject(userConfig.getType)) {
309 | config._extend(userConfig.getType);
310 | }
311 | jsonp([config.api_server || config.apiserver], config.typePath, config, function (newConfig) {
312 | var type = newConfig.type;
313 | var init = function () {
314 | config._extend(newConfig);
315 | callback(new window.Geetest(config));
316 | };
317 |
318 | callbacks[type] = callbacks[type] || [];
319 | var s = status[type] || 'init';
320 | if (s === 'init') {
321 | status[type] = 'loading';
322 |
323 | callbacks[type].push(init);
324 |
325 | load(config, true, config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {
326 | if (err) {
327 | status[type] = 'fail';
328 | throwError('networkError', config);
329 | } else {
330 | status[type] = 'loaded';
331 | var cbs = callbacks[type];
332 | for (var i = 0, len = cbs.length; i < len; i = i + 1) {
333 | var cb = cbs[i];
334 | if (isFunction(cb)) {
335 | cb();
336 | }
337 | }
338 | callbacks[type] = [];
339 | }
340 | });
341 | } else if (s === "loaded") {
342 | init();
343 | } else if (s === "fail") {
344 | throwError('networkError', config);
345 | } else if (s === "loading") {
346 | callbacks[type].push(init);
347 | }
348 | });
349 |
350 | };
351 |
352 |
353 | })(window);
354 |
355 |
--------------------------------------------------------------------------------
/resource/img/BILIBILI_LOGO-PINK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/BILIBILI_LOGO-PINK.png
--------------------------------------------------------------------------------
/resource/img/BILIBILI_LOGO.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/BILIBILI_LOGO.png
--------------------------------------------------------------------------------
/resource/img/Bilibili_User_Cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/Bilibili_User_Cover.png
--------------------------------------------------------------------------------
/resource/img/PILIPILI_LOGO.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/PILIPILI_LOGO.png
--------------------------------------------------------------------------------
/resource/img/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/cover.jpg
--------------------------------------------------------------------------------
/resource/img/exported_qrcode_image_600.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/exported_qrcode_image_600.png
--------------------------------------------------------------------------------
/resource/img/preview1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/preview1.png
--------------------------------------------------------------------------------
/resource/img/preview2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/preview2.png
--------------------------------------------------------------------------------
/resource/img/preview3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/preview3.png
--------------------------------------------------------------------------------
/resource/img/preview4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/preview4.png
--------------------------------------------------------------------------------
/resource/img/二维码.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/二维码.png
--------------------------------------------------------------------------------
/resource/img/头像.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/头像.png
--------------------------------------------------------------------------------
/resource/img/弹幕数.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/弹幕数.png
--------------------------------------------------------------------------------
/resource/img/播放量.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/播放量.png
--------------------------------------------------------------------------------
/resource/img/收藏数.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/收藏数.png
--------------------------------------------------------------------------------
/resource/img/点赞数.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/点赞数.png
--------------------------------------------------------------------------------
/resource/img/硬币数.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/硬币数.png
--------------------------------------------------------------------------------
/resource/img/评论数.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/评论数.png
--------------------------------------------------------------------------------
/resource/img/账号.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/账号.png
--------------------------------------------------------------------------------
/resource/img/转发数.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/转发数.png
--------------------------------------------------------------------------------
/resource/img/返回.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/返回.png
--------------------------------------------------------------------------------
/resource/img/频道.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonyanDunh/BilibiliClient/9974483a17f972d7469c17b4192709c3c958ff07/resource/img/频道.png
--------------------------------------------------------------------------------
/video.xaml:
--------------------------------------------------------------------------------
1 |
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 |
44 |
50 |
53 |
55 |
56 |
60 |
61 |
62 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
88 |
94 |
95 |
96 |
97 |
98 |
100 |
101 |
102 |
103 |
104 |
116 |
117 |
118 |
124 |
125 |
126 |
127 |
128 |
141 |
145 |
149 |
153 |
157 |
161 |
165 |
166 |
184 |
185 |
202 |
203 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
235 |
250 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/video.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Globalization;
5 | using System.IO;
6 | using System.Text.RegularExpressions;
7 | using System.Threading;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Data;
11 | using System.Windows.Media;
12 | using System.Windows.Threading;
13 | using Unosquare.FFME.Common;
14 | using static Bilibili_Client.Bilibili_Video;
15 |
16 | namespace Bilibili_Client
17 | {
18 | ///
19 | /// video.xaml 的交互逻辑
20 | ///
21 | ///
22 |
23 | public class TimeConver : IValueConverter
24 | {
25 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
26 | {
27 |
28 | if (value == null)
29 | return DependencyProperty.UnsetValue;
30 | return new Regex(@"(?