Compare commits

...

30 Commits
v1.5.8 ... main

Author SHA1 Message Date
leiurayer
2c227d5d26 修复标题中无合法字符时崩溃的问题 #1143 2025-02-05 20:36:14 +08:00
leiurayer
e0ac25efbc Update package 2025-02-05 20:27:24 +08:00
leiurayer
1088b70cc8 Add local NuGet 2025-02-05 20:09:14 +08:00
leiurayer
d891541b4e 修复登录二维码无法显示的问题 2024-10-12 15:12:21 +08:00
leiurayer
29c6aa0375
Merge pull request #937 from yaobiao131/main
feat: 减少视频解析页面接口调用次数
2023-12-14 19:17:45 +08:00
yaobiao
6bf03de4f3 feat: 减少视频解析页面接口调用次数 2023-12-12 00:02:57 +08:00
leiurayer
0a5a13cdd6 CHANGELOG 2023-12-10 13:22:17 +08:00
leiurayer
c5db2cfb40 发布v1.6.1 2023-12-10 13:20:10 +08:00
leiurayer
6e9fef3d64 更新wbi签名算法 2023-12-10 13:03:44 +08:00
leiurayer
1a158dce32 如果存在下载完成列表,弹出选择框是否再次下载 2023-12-09 23:24:48 +08:00
leiurayer
f2b82a44b5 发布v1.6.0 2023-12-09 13:43:00 +08:00
leiurayer
a8c8626c3e
Merge pull request #923 from yaobiao131/bugfix
fix: #907
2023-12-09 13:15:29 +08:00
yaobiao
ca14b75038 fix: #907 2023-11-25 18:30:10 +08:00
yaobiao
8bd51907d1 fix: 添加缺失的文件 2023-11-13 16:48:50 +08:00
yaobiao
28f1c1e724 chore: 去掉无意义的修改 2023-11-12 14:33:33 +08:00
yaobiao
e63b24309c fix: 使用新版登录api修复登录失败的问题 2023-11-12 13:27:23 +08:00
leiurayer
3331737494 修复程序反复读取设置文件的问题 2023-07-28 00:07:23 +08:00
leiurayer
d15175f629 修复文件名导致的闪退问题 2023-07-13 23:11:29 +08:00
leiurayer
11538b6efa 下载列表弹出框优化 2023-07-10 23:13:43 +08:00
leiurayer
6221dd504e 添加任务栏图标 2023-07-10 23:13:17 +08:00
leiurayer
daabbb58d9 视频详细信息API支持wbi 2023-05-26 18:23:09 +08:00
leiurayer
1a80a16d19 更新视频流API支持wbi 2023-05-26 18:22:54 +08:00
leiurayer
9da37a7f28 修正未登录时不能正常获取wbi口令的问题 2023-05-24 23:48:50 +08:00
leiurayer
35ca6a3442 发布v1.5.9 2023-05-24 23:03:05 +08:00
leiurayer
a3579fbb28 支持wbi口令 2023-05-24 23:02:43 +08:00
leiurayer
eaa962aca1
Merge pull request #744 from xisuo67/patch-1 2023-05-11 16:38:37 +08:00
初十
b31d130ae8
Update ViewVideoDetailViewModel.cs
调整注释,之前提交注释写错了
2023-05-11 16:36:33 +08:00
初十
a7778b464d 切换多语言 2023-05-07 20:50:10 +08:00
初十
038e83b5b2 优化 Issues #724下载完成提示 2023-05-07 20:45:31 +08:00
leiurayer
29b154a225 更新UP主空间API #722 #730 2023-04-30 18:25:19 +08:00
44 changed files with 678 additions and 174 deletions

View File

@ -1,5 +1,25 @@
# 更新日志
## `2023/12/10` v1.6.1
* [优化] 如果存在下载完成列表,弹出选择框是否再次下载。
* [修复] 更新wbi签名算法解决无法解析下载视频的问题。
## `2023/12/09` v1.6.0
* [优化] 下载列表弹出框。
* [优化] 添加任务栏图标。
* [优化] 视频流API、视频详细信息API。
* [修复] 文件名导致的闪退问题。
* [修复] 程序反复读取设置文件的问题。
* [修复] 修复扫码登录的问题。
* [修复] 在下载设置窗口界面取消或关闭窗口之后导致的DownKyi闪退问题 #907
## `2023/05/24` v1.5.9
* [新增] 下载完成系统提示。
* [修复] UP主个人空间访问。
## `2023/04/30` v1.5.8
* [新增] 视频详情页搜索功能。

View File

@ -120,7 +120,7 @@ namespace DownKyi.Core.BiliApi.Login
public static BitmapImage GetLoginQRCode(string url)
{
// 设置的参数影响app能否成功扫码
Bitmap qrCode = Utils.QRCode.EncodeQRCode(url, 10, 10, null, 0, 0, false);
Bitmap qrCode = Utils.QRCode.EncodeQRCode(url, 12, 10, null, 0, 0, false);
MemoryStream ms = new MemoryStream();
qrCode.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);

View File

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Media.Imaging;
using DownKyi.Core.BiliApi.LoginNew.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.LoginNew
{
public static class LoginQR
{
/// <summary>
/// 申请二维码URL及扫码密钥web端
/// </summary>
/// <returns></returns>
public static LoginUrlOrigin GetLoginUrl()
{
string getLoginUrl = "https://passport.bilibili.com/x/passport-login/web/qrcode/generate";
string response = WebClient.RequestWeb(getLoginUrl);
Console.Out.WriteLine(response);
try
{
return JsonConvert.DeserializeObject<LoginUrlOrigin>(response);
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetLoginUrl()发生异常: {0}", e);
LogManager.Error("LoginQR", e);
return null;
}
}
/// <summary>
/// 使用扫码登录web端
/// </summary>
/// <param name="qrcodeKey"></param>
/// <param name="goUrl"></param>
/// <returns></returns>
public static LoginStatus GetLoginStatus(string qrcodeKey, string goUrl = "https://www.bilibili.com")
{
string url = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + qrcodeKey;
string response = WebClient.RequestWeb(url);
try
{
return JsonConvert.DeserializeObject<LoginStatus>(response);
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetLoginInfo()发生异常: {0}", e);
LogManager.Error("LoginQR", e);
return null;
}
}
/// <summary>
/// 获得登录二维码
/// </summary>
/// <returns></returns>
public static BitmapImage GetLoginQRCode()
{
try
{
string loginUrl = GetLoginUrl().Data.Url;
return GetLoginQRCode(loginUrl);
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetLoginQRCode()发生异常: {0}", e);
LogManager.Error("LoginQR", e);
return null;
}
}
/// <summary>
/// 根据输入url生成二维码
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static BitmapImage GetLoginQRCode(string url)
{
// 设置的参数影响app能否成功扫码
Bitmap qrCode = Utils.QRCode.EncodeQRCode(url, 12, 10, null, 0, 0, false);
MemoryStream ms = new MemoryStream();
qrCode.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] bytes = ms.GetBuffer();
ms.Close();
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = new MemoryStream(bytes);
image.EndInit();
return image;
}
}
}

View File

@ -0,0 +1,23 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.LoginNew.Models
{
[JsonObject]
public class LoginStatus : BaseModel
{
[JsonProperty("code")] public int Code { get; set; }
[JsonProperty("message")] public string Message { get; set; }
[JsonProperty("data")] public LoginStatusData Data { get; set; }
}
[JsonObject]
public class LoginStatusData : BaseModel
{
[JsonProperty("url")] public string Url { get; set; }
[JsonProperty("refresh_token")] public string RefreshToken { get; set; }
[JsonProperty("code")] public int Code { get; set; }
[JsonProperty("message")] public string Message { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.LoginNew.Models
{
// https://passport.bilibili.com/qrcode/getLoginUrl
[JsonObject]
public class LoginUrlOrigin : BaseModel
{
//public int code { get; set; }
[JsonProperty("data")]
public LoginUrl Data { get; set; }
[JsonProperty("code")]
public int Code { get; set; }
//public long ts { get; set; }
}
[JsonObject]
public class LoginUrl : BaseModel
{
[JsonProperty("qrcode_key")]
public string QrcodeKey { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
}
}

View File

@ -0,0 +1,163 @@
using DownKyi.Core.Settings;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace DownKyi.Core.BiliApi.Sign
{
public static class WbiSign
{
/// <summary>
/// 打乱重排实时口令
/// </summary>
/// <param name="origin"></param>
/// <returns></returns>
private static string GetMixinKey(string origin)
{
int[] mixinKeyEncTab = new int[]
{
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39,12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
};
var temp = new StringBuilder();
foreach (var i in mixinKeyEncTab)
{
temp.Append(origin[i]);
}
return temp.ToString().Substring(0, 32);
}
/// <summary>
/// 将字典参数转为字符串
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
public static string ParametersToQuery(Dictionary<string, string> parameters)
{
var keys = parameters.Keys.ToList();
var queryList = new List<string>();
foreach (var item in keys)
{
var value = parameters[item];
queryList.Add($"{item}={value}");
}
return string.Join("&", queryList);
}
/// <summary>
/// Wbi签名返回所有参数字典
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
public static Dictionary<string, string> EncodeWbi(Dictionary<string, object> parameters)
{
return EncWbi(parameters, GetKey().Item1, GetKey().Item2);
}
/// <summary>
/// Wbi签名返回所有参数字典
/// </summary>
/// <param name="parameters"></param>
/// <param name="imgKey"></param>
/// <param name="subKey"></param>
/// <returns></returns>
private static Dictionary<string, string> EncWbi(Dictionary<string, object> parameters, string imgKey, string subKey)
{
Dictionary<string, string> paraStr = new Dictionary<string, string>();
foreach (var para in parameters)
{
var key = para.Key;
var value = para.Value.ToString();
paraStr.Add(key, value);
}
string mixinKey = GetMixinKey(imgKey + subKey);
string currTime = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
//添加 wts 字段
paraStr["wts"] = currTime;
// 按照 key 重排参数
paraStr = paraStr.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
//过滤 value 中的 "!'()*" 字符
paraStr = paraStr.ToDictionary(
kvp => kvp.Key,
kvp => new string(kvp.Value.Where(chr => !"!'()*".Contains(chr)).ToArray())
);
// 序列化参数
string query = new FormUrlEncodedContent(paraStr).ReadAsStringAsync().Result;
//计算 w_rid
using (MD5 md5 = MD5.Create())
{
//using MD5 md5 = MD5.Create();
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query + mixinKey));
string wbiSign = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
paraStr["w_rid"] = wbiSign;
}
return paraStr;
}
/// <summary>
/// Wbi签名返回所有参数字典
/// </summary>
/// <param name="parameters"></param>
/// <param name="imgKey"></param>
/// <param name="subKey"></param>
/// <returns></returns>
public static Dictionary<string, object> EncodeWbi(Dictionary<string, object> parameters, string imgKey, string subKey)
{
var mixinKey = GetMixinKey(imgKey + subKey);
var chrFilter = new Regex("[!'()*]");
var newParameters = new Dictionary<string, object>
{
{ "wts", DateTimeOffset.Now.ToUnixTimeSeconds().ToString() }
};
foreach (var para in parameters)
{
var key = para.Key;
var value = para.Value.ToString();
var encodedValue = chrFilter.Replace(value, "");
newParameters.Add(Uri.EscapeDataString(key), Uri.EscapeDataString(encodedValue));
}
var keys = newParameters.Keys.ToList();
keys.Sort();
var queryList = new List<string>();
foreach (var item in keys)
{
var value = newParameters[item];
queryList.Add($"{item}={value}");
}
var queryString = string.Join("&", queryList);
var md5Hasher = MD5.Create();
var hashStr = queryString + mixinKey;
var hashedQueryString = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(hashStr));
var wbiSign = BitConverter.ToString(hashedQueryString).Replace("-", "").ToLower();
newParameters.Add("w_rid", wbiSign);
return newParameters;
}
public static Tuple<string, string> GetKey()
{
var user = SettingsManager.GetInstance().GetUserInfo();
return new Tuple<string, string>(user.ImgKey, user.SubKey);
}
}
}

View File

@ -53,6 +53,9 @@ namespace DownKyi.Core.BiliApi.Users.Models
//public int vip_theme_type { get; set; }
[JsonProperty("wallet")]
public UserInfoWallet Wallet { get; set; }
[JsonProperty("wbi_img")]
public Wbi Wbi { get; set; }
}
//public class NavDataLevelInfo
@ -105,4 +108,14 @@ namespace DownKyi.Core.BiliApi.Users.Models
[JsonProperty("mid")]
public long Mid { get; set; }
}
[JsonObject]
public class Wbi
{
[JsonProperty("img_url")]
public string ImgUrl { get; set; }
[JsonProperty("sub_url")]
public string SubUrl { get; set; }
}
}

View File

@ -1,7 +1,9 @@
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.BiliApi.Sign;
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Users
{
@ -25,8 +27,7 @@ namespace DownKyi.Core.BiliApi.Users
UserInfoForNavigationOrigin userInfo = JsonConvert.DeserializeObject<UserInfoForNavigationOrigin>(response);
if (userInfo == null || userInfo.Data == null) { return null; }
if (userInfo.Data.IsLogin) { return userInfo.Data; }
else { return null; }
return userInfo.Data;
}
catch (Exception e)
{
@ -43,7 +44,12 @@ namespace DownKyi.Core.BiliApi.Users
/// <returns></returns>
public static UserInfoForSpace GetUserInfoForSpace(long mid)
{
string url = $"https://api.bilibili.com/x/space/acc/info?mid={mid}";
var parameters = new Dictionary<string, object>
{
{ "mid", mid }
};
string query = WbiSign.ParametersToQuery(WbiSign.EncodeWbi(parameters));
string url = $"https://api.bilibili.com/x/space/wbi/acc/info?{query}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);

View File

@ -1,4 +1,5 @@
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.BiliApi.Sign;
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -114,7 +115,17 @@ namespace DownKyi.Core.BiliApi.Users
/// <returns></returns>
public static SpacePublicationList GetPublication(long mid, int pn, int ps, long tid = 0, PublicationOrder order = PublicationOrder.PUBDATE, string keyword = "")
{
string url = $"https://api.bilibili.com/x/space/arc/search?mid={mid}&pn={pn}&ps={ps}&order={order.ToString("G").ToLower()}&tid={tid}&keyword={keyword}";
var parameters = new Dictionary<string, object>
{
{ "mid", mid },
{ "pn", pn },
{ "ps", ps },
{ "order", order.ToString("G").ToLower() },
{ "tid", tid },
{ "keyword", keyword },
};
string query = WbiSign.ParametersToQuery(WbiSign.EncodeWbi(parameters));
string url = $"https://api.bilibili.com/x/space/wbi/arc/search?{query}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);

View File

@ -1,4 +1,5 @@
using DownKyi.Core.BiliApi.Video.Models;
using DownKyi.Core.BiliApi.Sign;
using DownKyi.Core.BiliApi.Video.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
using System;
@ -17,13 +18,23 @@ namespace DownKyi.Core.BiliApi.Video
public static VideoView VideoViewInfo(string bvid = null, long aid = -1)
{
// https://api.bilibili.com/x/web-interface/view/detail?bvid=BV1Sg411F7cb&aid=969147110&need_operation_card=1&web_rm_repeat=1&need_elec=1&out_referer=https%3A%2F%2Fspace.bilibili.com%2F42018135%2Ffavlist%3Ffid%3D94341835
string baseUrl = "https://api.bilibili.com/x/web-interface/view";
string referer = "https://www.bilibili.com";
string url;
if (bvid != null) { url = $"{baseUrl}?bvid={bvid}"; }
else if (aid > -1) { url = $"{baseUrl}?aid={aid}"; }
else { return null; }
var parameters = new Dictionary<string, object>();
if (bvid != null)
{
parameters.Add("bvid", bvid);
}
else if (aid > -1)
{
parameters.Add("aid", aid);
}
else
{
return null;
}
string query = WbiSign.ParametersToQuery(WbiSign.EncodeWbi(parameters));
string url = $"https://api.bilibili.com/x/web-interface/wbi/view?{query}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try

View File

@ -1,4 +1,5 @@
using DownKyi.Core.BiliApi.Models.Json;
using DownKyi.Core.BiliApi.Sign;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
@ -19,7 +20,14 @@ namespace DownKyi.Core.BiliApi.VideoStream
/// <returns></returns>
public static PlayerV2 PlayerV2(long avid, string bvid, long cid)
{
string url = $"https://api.bilibili.com/x/player/v2?cid={cid}&aid={avid}&bvid={bvid}";
var parameters = new Dictionary<string, object>
{
{ "avid", avid },
{ "bvid", bvid },
{ "cid", cid },
};
string query = WbiSign.ParametersToQuery(WbiSign.EncodeWbi(parameters));
string url = $"https://api.bilibili.com/x/player/wbi/v2?{query}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
@ -93,11 +101,31 @@ namespace DownKyi.Core.BiliApi.VideoStream
/// <returns></returns>
public static PlayUrl GetVideoPlayUrl(long avid, string bvid, long cid, int quality = 125)
{
string baseUrl = $"https://api.bilibili.com/x/player/playurl?cid={cid}&qn={quality}&fourk=1&fnver=0&fnval=4048";
string url;
if (bvid != null) { url = $"{baseUrl}&bvid={bvid}"; }
else if (avid > -1) { url = $"{baseUrl}&aid={avid}"; }
else { return null; }
var parameters = new Dictionary<string, object>
{
{ "from_client", "BROWSER" },
{ "fourk", 1 },
{ "fnver", 0 },
{ "fnval", 4048 },
{ "cid", cid },
{ "qn", quality },
};
if (bvid != null)
{
parameters.Add("bvid", bvid);
}
else if (avid > -1)
{
parameters.Add("aid", avid);
}
else
{
return null;
}
string query = WbiSign.ParametersToQuery(WbiSign.EncodeWbi(parameters));
string url = $"https://api.bilibili.com/x/player/wbi/playurl?{query}";
return GetPlayUrl(url);
}

View File

@ -52,20 +52,20 @@
<Reference Include="Brotli.Core, Version=2.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Brotli.NET.2.1.1\lib\net45\Brotli.Core.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf, Version=3.21.12.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.21.12\lib\net45\Google.Protobuf.dll</HintPath>
<Reference Include="Google.Protobuf, Version=3.29.3.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.29.3\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="QRCoder, Version=1.4.3.0, Culture=neutral, PublicKeyToken=c4ed5b9ae8358a28, processorArchitecture=MSIL">
<HintPath>..\packages\QRCoder.1.4.3\lib\net40\QRCoder.dll</HintPath>
<Reference Include="QRCoder, Version=1.6.0.0, Culture=neutral, PublicKeyToken=c4ed5b9ae8358a28, processorArchitecture=MSIL">
<HintPath>..\packages\QRCoder.1.6.0\lib\net40\QRCoder.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
<Reference Include="System.Buffers, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.112.1, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
@ -73,15 +73,15 @@
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
<Reference Include="System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
<Reference Include="System.Numerics.Vectors, Version=4.1.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
@ -179,6 +179,9 @@
<Compile Include="BiliApi\History\Models\ToViewData.cs" />
<Compile Include="BiliApi\History\Models\ToViewList.cs" />
<Compile Include="BiliApi\History\ToView.cs" />
<Compile Include="BiliApi\LoginNew\LoginQR.cs" />
<Compile Include="BiliApi\LoginNew\Models\LoginStatus.cs" />
<Compile Include="BiliApi\LoginNew\Models\LoginUrl.cs" />
<Compile Include="BiliApi\Login\LoginHelper.cs" />
<Compile Include="BiliApi\Models\BaseModel.cs" />
<Compile Include="BiliApi\BiliUtils\BvId.cs" />
@ -186,6 +189,7 @@
<Compile Include="BiliApi\Login\LoginQR.cs" />
<Compile Include="BiliApi\Login\Models\LoginStatus.cs" />
<Compile Include="BiliApi\Login\Models\LoginUrl.cs" />
<Compile Include="BiliApi\Sign\WbiSign.cs" />
<Compile Include="BiliApi\Users\Models\BangumiFollow.cs" />
<Compile Include="BiliApi\Users\Models\BangumiFollowAreas.cs" />
<Compile Include="BiliApi\Users\Models\BangumiFollowNewEp.cs" />
@ -388,9 +392,9 @@
<Error Condition="!Exists('..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets'))" />
<Error Condition="!Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets'))" />
<Error Condition="!Exists('..\packages\WebPSharp.0.5.1\build\WebPSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WebPSharp.0.5.1\build\WebPSharp.targets'))" />
<Error Condition="!Exists('..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets'))" />
<Error Condition="!Exists('..\packages\Google.Protobuf.Tools.3.29.3\build\Google.Protobuf.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Google.Protobuf.Tools.3.29.3\build\Google.Protobuf.Tools.targets'))" />
</Target>
<Import Project="..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" />
<Import Project="..\packages\WebPSharp.0.5.1\build\WebPSharp.targets" Condition="Exists('..\packages\WebPSharp.0.5.1\build\WebPSharp.targets')" />
<Import Project="..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets" Condition="Exists('..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets')" />
<Import Project="..\packages\Google.Protobuf.Tools.3.29.3\build\Google.Protobuf.Tools.targets" Condition="Exists('..\packages\Google.Protobuf.Tools.3.29.3\build\Google.Protobuf.Tools.targets')" />
</Project>

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.1.8.0")]
[assembly: AssemblyFileVersion("2.1.8.0")]
[assembly: AssemblyVersion("2.2.1.0")]
[assembly: AssemblyFileVersion("2.2.1.0")]

View File

@ -6,5 +6,8 @@
public string Name { get; set; }
public bool IsLogin { get; set; } // 是否登录
public bool IsVip { get; set; } // 是否为大会员未登录时为false
public string ImgKey { get; set; }
public string SubKey { get; set; }
}
}

View File

@ -55,13 +55,23 @@ namespace DownKyi.Core.Settings
/// <returns></returns>
private AppSettings GetSettings()
{
if (appSettings != null) { return appSettings; }
try
{
FileStream fileStream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader streamReader = new StreamReader(fileStream, System.Text.Encoding.UTF8);
string jsonWordTemplate = streamReader.ReadToEnd();
streamReader.Close();
fileStream.Close();
//FileStream fileStream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
//StreamReader streamReader = new StreamReader(fileStream, System.Text.Encoding.UTF8);
//string jsonWordTemplate = streamReader.ReadToEnd();
//streamReader.Close();
//fileStream.Close();
string jsonWordTemplate = string.Empty;
using (var stream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
{
using (var reader = new StreamReader(stream, System.Text.Encoding.UTF8))
{
jsonWordTemplate = reader.ReadToEnd();
}
}
#if DEBUG
#else

View File

@ -198,6 +198,12 @@ namespace DownKyi.Core.Utils
// 控制字符
destName = Regex.Replace(destName, @"\p{C}+", string.Empty);
// 如果只有空白字符、dot符
if (string.IsNullOrWhiteSpace(destName) || destName == ".")
{
return "[empty title]";
}
// 移除前导和尾部的空白字符、dot符
int i, j;
for (i = 0; i < destName.Length; i++)

View File

@ -45,7 +45,7 @@ namespace DownKyi.Core.Utils
if (name == "Expires" || name == "gourl") { continue; }
// 添加cookie
cookieContainer.Add(new Cookie(name, value, "/", ".bilibili.com") { Expires = dateTime });
cookieContainer.Add(new Cookie(name, value.Replace(",","%2c"), "/", ".bilibili.com") { Expires = dateTime });
Debugging.Console.PrintLine(name + ": " + value + "\t" + cookieContainer.Count);
}

View File

@ -4,11 +4,11 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-6.0.1.0" newVersion="6.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Brotli.NET" version="2.1.1" targetFramework="net472" />
<package id="Google.Protobuf" version="3.21.12" targetFramework="net472" />
<package id="Google.Protobuf.Tools" version="3.21.12" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net472" />
<package id="QRCoder" version="1.4.3" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="Google.Protobuf" version="3.29.3" targetFramework="net472" />
<package id="Google.Protobuf.Tools" version="3.29.3" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
<package id="QRCoder" version="1.6.0" targetFramework="net472" />
<package id="System.Buffers" version="4.6.0" targetFramework="net472" />
<package id="System.Data.SQLite.Core" version="1.0.112.2" targetFramework="net472" />
<package id="System.Memory" version="4.5.5" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
<package id="System.Memory" version="4.6.0" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.6.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" />
<package id="WebPSharp" version="0.5.1" targetFramework="net472" />
</packages>

View File

@ -561,8 +561,11 @@
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Hardcodet.NotifyIcon.Wpf">
<Version>2.0.1</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.2</Version>
<Version>13.0.3</Version>
</PackageReference>
<PackageReference Include="Prism.DryIoc" Version="8.1.97" />
<PackageReference Include="System.Data.SQLite.Core">

View File

@ -144,14 +144,15 @@
<system:String x:Key="TipAlreadyToAddDownloading">已经添加到下载列表~</system:String>
<system:String x:Key="TipAlreadyToAddDownloaded">已经下载完成~</system:String>
<system:String x:Key="TipAddDownloadingZero">没有选中项符合下载要求!</system:String>
<system:String x:Key="TipAlreadyToAddDownloaded2">该视频已经下载完成,是否重新下载?</system:String>
<system:String x:Key="TipAddDownloadingZero">没有添加任何视频~</system:String>
<system:String x:Key="TipAddDownloadingFinished1">成功添加了</system:String>
<system:String x:Key="TipAddDownloadingFinished2">项~</system:String>
<!-- DownloadManager -->
<system:String x:Key="Downloading">正在下载</system:String>
<system:String x:Key="DownloadFinished">已下载</system:String>
<system:String x:Key="DownloadSuccess">下载完成</system:String>
<system:String x:Key="DownloadingAudio">音频</system:String>
<system:String x:Key="DownloadingVideo">视频</system:String>
<system:String x:Key="DownloadingDanmaku">弹幕</system:String>
@ -200,7 +201,7 @@
<system:String x:Key="UseSSL">启用https若下载器提示SSL错误则关闭此项</system:String>
<system:String x:Key="UserAgent">UserAgent</system:String>
<system:String x:Key="SelectDownloader">选择下载器(重启生效):</system:String>
<system:String x:Key="BuiltinDownloader">内建下载器(测试)</system:String>
<system:String x:Key="BuiltinDownloader">内建下载器</system:String>
<system:String x:Key="Aria2cDownloader">Aria2下载器</system:String>
<system:String x:Key="CustomAria2cDownloader">自定义Aria2下载器</system:String>
<system:String x:Key="AriaServerHost">Aria服务器地址</system:String>

View File

@ -67,7 +67,7 @@
<!-- DownloadManager -->
<system:String x:Key="Downloading">正在下载</system:String>
<system:String x:Key="DownloadFinished">已下载</system:String>
<system:String x:Key="DownloadSuccess">下载完成</system:String>
<!-- Settings -->
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>

View File

@ -68,7 +68,7 @@
<!-- DownloadManager -->
<system:String x:Key="Downloading">正在下载</system:String>
<system:String x:Key="DownloadFinished">已下载</system:String>
<system:String x:Key="DownloadSuccess">下载完成</system:String>
<!-- Settings -->
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>

View File

@ -68,7 +68,7 @@
<!-- DownloadManager -->
<system:String x:Key="Downloading">正在下载</system:String>
<system:String x:Key="DownloadFinished">已下载</system:String>
<system:String x:Key="DownloadSuccess">下载完成</system:String>
<!-- Settings -->
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>

View File

@ -10,8 +10,8 @@ namespace DownKyi.Models
public string VersionName { get; }
const int a = 1;
const int b = 5;
const int c = 8;
const int b = 6;
const int c = 1;
public AppInfo()
{

View File

@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.8.0")]
[assembly: AssemblyFileVersion("1.5.8.0")]
[assembly: AssemblyVersion("1.6.1.0")]
[assembly: AssemblyFileVersion("1.6.1.0")]

View File

@ -31,12 +31,13 @@ namespace DownKyi.Services
/// 显示一个警告弹窗
/// </summary>
/// <param name="message"></param>
/// <param name="buttonNumber"></param>
/// <returns></returns>
public ButtonResult ShowWarning(string message)
public ButtonResult ShowWarning(string message, int buttonNumber = 1)
{
VectorImage image = SystemIcon.Instance().Warning;
string title = DictionaryResource.GetString("Warning");
return ShowMessage(image, title, message, 1);
return ShowMessage(image, title, message, buttonNumber);
}
/// <summary>
@ -66,10 +67,15 @@ namespace DownKyi.Services
{ "message", message },
{ "button_number", buttonNumber }
};
dialogService.ShowDialog(ViewAlertDialogViewModel.Tag, param, buttonResult =>
App.PropertyChangeAsync(() =>
{
result = buttonResult.Result;
dialogService.ShowDialog(ViewAlertDialogViewModel.Tag, param, buttonResult =>
{
result = buttonResult.Result;
});
});
return result;
}

View File

@ -191,6 +191,11 @@ namespace DownKyi.Services.Download
});
}
// 下载设置dialog中如果点击取消或者关闭窗口
// 会返回空字符串,
// 这时直接退出
if (string.IsNullOrEmpty(directory)) { return null; }
if (!Directory.Exists(Directory.GetDirectoryRoot(directory)))
{
var alert = new AlertService(dialogService);
@ -199,10 +204,6 @@ namespace DownKyi.Services.Download
directory = string.Empty;
}
// 下载设置dialog中如果点击取消或者关闭窗口
// 会返回空字符串,
// 这时直接退出
if (directory == null || directory == string.Empty) { return null; }
// 文件夹不存在则创建
if (!Directory.Exists(directory))
@ -220,7 +221,7 @@ namespace DownKyi.Services.Download
/// <param name="directory">下载路径</param>
/// <param name="isAll">是否下载所有,包括未选中项</param>
/// <returns>添加的数量</returns>
public int AddToDownload(IEventAggregator eventAggregator, string directory, bool isAll = false)
public int AddToDownload(IEventAggregator eventAggregator, IDialogService dialogService, string directory, bool isAll = false)
{
if (directory == null || directory == string.Empty) { return -1; }
if (videoSections == null) { return -1; }
@ -268,7 +269,7 @@ namespace DownKyi.Services.Download
}
if (isDownloading) { continue; }
// TODO 如果存在下载完成列表,弹出选择框是否再次下载
// 如果存在下载完成列表,弹出选择框是否再次下载
bool isDownloaded = false;
foreach (DownloadedItem item in App.DownloadedList)
{
@ -276,8 +277,25 @@ namespace DownKyi.Services.Download
if (item.DownloadBase.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}");
isDownloaded = true;
//eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}");
//isDownloaded = true;
AlertService alertService = new AlertService(dialogService);
ButtonResult result = alertService.ShowInfo(DictionaryResource.GetString("TipAlreadyToAddDownloaded2"));
if (result == ButtonResult.OK)
{
App.PropertyChangeAsync(() =>
{
App.DownloadedList.Remove(item);
});
isDownloaded = false;
}
else
{
isDownloaded = true;
}
break;
}
}

View File

@ -11,6 +11,7 @@ using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils;
using DownKyi.ViewModels.DownloadManager;
using Hardcodet.Wpf.TaskbarNotification;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
@ -19,15 +20,15 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
namespace DownKyi.Services.Download
{
public abstract class DownloadService
{
protected string Tag = "DownloadService";
protected TaskbarIcon _notifyIcon;
protected IDialogService dialogService;
protected ObservableCollection<DownloadingItem> downloadingList;
protected ObservableCollection<DownloadedItem> downloadedList;
@ -673,6 +674,7 @@ namespace DownKyi.Services.Download
DownloadFinishedSort finishedSort = SettingsManager.GetInstance().GetDownloadFinishedSort();
App.SortDownloadedList(finishedSort);
}));
_notifyIcon.ShowBalloonTip(DictionaryResource.GetString("DownloadSuccess"), $"{downloadedItem.DownloadBase.Name}", BalloonIcon.Info);
}));
}
catch (OperationCanceledException e)
@ -795,7 +797,6 @@ namespace DownKyi.Services.Download
downloadStorageService.UpdateDownloaded(item);
}
}
/// <summary>
/// 启动基本下载服务
/// </summary>
@ -803,6 +804,9 @@ namespace DownKyi.Services.Download
{
tokenSource = new CancellationTokenSource();
cancellationToken = tokenSource.Token;
_notifyIcon = new TaskbarIcon();
_notifyIcon.IconSource = new BitmapImage(new Uri("pack://application:,,,/Resources/favicon.ico"));
workTask = Task.Run(DoWork);
}

View File

@ -155,7 +155,7 @@ namespace DownKyi.ViewModels.DownloadManager
private void ExecuteRemoveVideoCommand()
{
AlertService alertService = new AlertService(DialogService);
ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete"));
ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete"), 2);
if (result != ButtonResult.OK)
{
return;

View File

@ -218,7 +218,7 @@ namespace DownKyi.ViewModels.DownloadManager
private void ExecuteDeleteCommand()
{
AlertService alertService = new AlertService(DialogService);
ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete"));
ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete"), 2);
if (result != ButtonResult.OK)
{
return;

View File

@ -295,7 +295,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(videoInfoService);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -1,4 +1,5 @@
using DownKyi.Core.BiliApi.Users;
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.Logging;
using DownKyi.Core.Settings;
using DownKyi.Core.Settings.Models;
@ -12,6 +13,7 @@ using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
@ -227,15 +229,59 @@ namespace DownKyi.ViewModels
InputText = string.Empty;
}
private async Task<UserInfoForNavigation> GetUserInfo()
{
UserInfoForNavigation userInfo = null;
await Task.Run(new Action(() =>
{
// 获取用户信息
userInfo = UserInfo.GetUserInfoForNavigation();
if (userInfo != null)
{
SettingsManager.GetInstance().SetUserInfo(new UserInfoSettings
{
Mid = userInfo.Mid,
Name = userInfo.Name,
IsLogin = userInfo.IsLogin,
IsVip = userInfo.VipStatus == 1,
ImgKey = userInfo.Wbi.ImgUrl.Split('/').ToList().Last().Split('.')[0],
SubKey = userInfo.Wbi.SubUrl.Split('/').ToList().Last().Split('.')[0],
});
}
else
{
SettingsManager.GetInstance().SetUserInfo(new UserInfoSettings
{
Mid = -1,
Name = "",
IsLogin = false,
IsVip = false,
});
}
}));
return userInfo;
}
/// <summary>
/// 更新用户登录信息
/// </summary>
private async void UpdateUserInfo()
private async void UpdateUserInfo(bool isBackgroud = false)
{
try
{
if (isBackgroud)
{
// 获取用户信息
await GetUserInfo();
return;
}
LoginPanelVisibility = Visibility.Hidden;
// 获取用户信息
var userInfo = await GetUserInfo();
// 检查本地是否存在login文件没有则说明未登录
if (!File.Exists(StorageManager.GetLogin()))
{
@ -245,54 +291,26 @@ namespace DownKyi.ViewModels
return;
}
await Task.Run(new Action(() =>
LoginPanelVisibility = Visibility.Visible;
if (userInfo != null)
{
// 获取用户信息
var userInfo = UserInfo.GetUserInfoForNavigation();
if (userInfo != null)
if (userInfo.Face != null)
{
SettingsManager.GetInstance().SetUserInfo(new UserInfoSettings
{
Mid = userInfo.Mid,
Name = userInfo.Name,
IsLogin = userInfo.IsLogin,
IsVip = userInfo.VipStatus == 1
});
Header = new StorageHeader().GetHeaderThumbnail(userInfo.Mid, userInfo.Name, userInfo.Face, 36, 36);
}
else
{
SettingsManager.GetInstance().SetUserInfo(new UserInfoSettings
{
Mid = -1,
Name = "",
IsLogin = false,
IsVip = false
});
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
}
UserName = userInfo.Name;
}
else
{
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
UserName = null;
}
PropertyChangeAsync(new Action(() =>
{
LoginPanelVisibility = Visibility.Visible;
if (userInfo != null)
{
if (userInfo.Face != null)
{
Header = new StorageHeader().GetHeaderThumbnail(userInfo.Mid, userInfo.Name, userInfo.Face, 36, 36);
}
else
{
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
}
UserName = userInfo.Name;
}
else
{
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
UserName = null;
}
}));
}));
}
catch (Exception e)
{
@ -316,23 +334,31 @@ namespace DownKyi.ViewModels
string parameter = navigationContext.Parameters.GetValue<string>("Parameter");
if (parameter == null)
{
// 其他情况只更新设置的用户信息不更新UI
UpdateUserInfo(true);
return;
}
// 启动
if (parameter == "start")
{
UpdateUserInfo();
}
// 从登录页面返回
if (parameter == "login")
else if (parameter == "login")
{
UpdateUserInfo();
}
// 注销
if (parameter == "logout")
else if (parameter == "logout")
{
UpdateUserInfo();
}
else
{
// 其他情况只更新设置的用户信息不更新UI
UpdateUserInfo(true);
}
}

View File

@ -1,4 +1,4 @@
using DownKyi.Core.BiliApi.Login;

using DownKyi.Core.Logging;
using DownKyi.Events;
using DownKyi.Images;
@ -11,6 +11,8 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using DownKyi.Core.BiliApi.Login;
using LoginQR = DownKyi.Core.BiliApi.LoginNew.LoginQR;
namespace DownKyi.ViewModels
{
@ -103,7 +105,7 @@ namespace DownKyi.ViewModels
var loginUrl = LoginQR.GetLoginUrl();
if (loginUrl == null) { return; }
if (loginUrl.Status != true)
if (loginUrl.Code != 0)
{
ExecuteBackSpace();
return;
@ -119,7 +121,7 @@ namespace DownKyi.ViewModels
Core.Utils.Debugging.Console.PrintLine(loginUrl.Data.Url + "\n");
LogManager.Debug(Tag, loginUrl.Data.Url);
GetLoginStatus(loginUrl.Data.OauthKey);
GetLoginStatus(loginUrl.Data.QrcodeKey);
}
catch (Exception e)
{
@ -141,24 +143,24 @@ namespace DownKyi.ViewModels
var loginStatus = LoginQR.GetLoginStatus(oauthKey);
if (loginStatus == null) { continue; }
Core.Utils.Debugging.Console.PrintLine(loginStatus.Code + "\n" + loginStatus.Message + "\n" + loginStatus.Url + "\n");
Core.Utils.Debugging.Console.PrintLine(loginStatus.Data.Code + "\n" + loginStatus.Data.Message + "\n" + loginStatus.Data.Url + "\n");
switch (loginStatus.Code)
switch (loginStatus.Data.Code)
{
case -1:
// 没有这个oauthKey
// 发送通知
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginKeyError"));
LogManager.Info(Tag, DictionaryResource.GetString("LoginKeyError"));
// 取消任务
tokenSource.Cancel();
// 创建新任务
PropertyChangeAsync(new Action(() => { Task.Run(Login, (tokenSource = new CancellationTokenSource()).Token); }));
break;
case -2:
// case -1:
// // 没有这个oauthKey
//
// // 发送通知
// eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginKeyError"));
// LogManager.Info(Tag, DictionaryResource.GetString("LoginKeyError"));
//
// // 取消任务
// tokenSource.Cancel();
//
// // 创建新任务
// PropertyChangeAsync(new Action(() => { Task.Run(Login, (tokenSource = new CancellationTokenSource()).Token); }));
// break;
case 86038:
// 不匹配的oauthKey超时或已确认的oauthKey
// 发送通知
@ -171,10 +173,10 @@ namespace DownKyi.ViewModels
// 创建新任务
PropertyChangeAsync(new Action(() => { Task.Run(Login, (tokenSource = new CancellationTokenSource()).Token); }));
break;
case -4:
case 86101:
// 未扫码
break;
case -5:
case 86090:
// 已扫码,未确认
PropertyChangeAsync(new Action(() =>
{
@ -192,7 +194,7 @@ namespace DownKyi.ViewModels
// 保存登录信息
try
{
bool isSucceed = LoginHelper.SaveLoginInfoCookies(loginStatus.Url);
bool isSucceed = LoginHelper.SaveLoginInfoCookies(loginStatus.Data.Url);
if (!isSucceed)
{
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginFailed"));

View File

@ -348,7 +348,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(service);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -378,7 +378,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(videoInfoService);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -291,7 +291,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(service);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -277,7 +277,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(videoInfoService);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -298,7 +298,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(videoInfoService);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -332,7 +332,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(videoInfoService);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -296,7 +296,7 @@ namespace DownKyi.ViewModels
addToDownloadService.GetVideo();
addToDownloadService.ParseVideo(videoInfoService);
// 下载
i += addToDownloadService.AddToDownload(eventAggregator, directory);
i += addToDownloadService.AddToDownload(eventAggregator, dialogService, directory);
}
});

View File

@ -362,7 +362,7 @@ namespace DownKyi.ViewModels
sexUri = new Uri($"pack://application:,,,/Resources/sex/female.png");
}
// 显示vip信息
if (userInfo.Vip.Label.Text == null || userInfo.Vip.Label.Text == "")
if (userInfo.Vip == null || userInfo.Vip.Label.Text == null || userInfo.Vip.Label.Text == "")
{
VipTypeVisibility = Visibility.Collapsed;
}

View File

@ -34,6 +34,9 @@ namespace DownKyi.ViewModels
// 保存输入字符串,避免被用户修改
private string input = null;
// 保存当前页面服务减少new的开销和接口调用次数
private IInfoService infoService;
#region
private VectorImage arrowBack;
@ -186,7 +189,7 @@ namespace DownKyi.ViewModels
public DelegateCommand InputSearchCommand => inputSearchCommand ?? (inputSearchCommand = new DelegateCommand(ExcuteInputSearchCommand));
/// <summary>
/// 搜索视频输入时间
/// 搜索视频输入事件
/// </summary>
private async void ExcuteInputSearchCommand() {
await Task.Run(() =>
@ -233,7 +236,7 @@ namespace DownKyi.ViewModels
input = InputText;
// 更新页面
UnityUpdateView(UpdateView, input, null);
UnityUpdateView(UpdateView, input, null, true);
// 是否自动解析视频
if (SettingsManager.GetInstance().IsAutoParseVideo() == AllowStatus.YES)
@ -410,7 +413,7 @@ namespace DownKyi.ViewModels
{
LogManager.Debug(Tag, $"Video Page: {videoPage.Cid}");
UnityUpdateView(ParseVideo, input, videoPage);
UnityUpdateView(ParseVideo, input, videoPage, true);
});
}
catch (Exception e)
@ -635,25 +638,34 @@ namespace DownKyi.ViewModels
/// <param name="action"></param>
/// <param name="input"></param>
/// <param name="page"></param>
private void UnityUpdateView(Action<IInfoService, VideoPage> action, string input, VideoPage page)
/// <param name="force">强制new</param>
private void UnityUpdateView(Action<IInfoService, VideoPage> action, string input, VideoPage page,bool force = false)
{
// 视频
if (ParseEntrance.IsAvUrl(input) || ParseEntrance.IsBvUrl(input))
if (infoService == null || force)
{
action(new VideoInfoService(input), page);
}
// 视频
if (ParseEntrance.IsAvUrl(input) || ParseEntrance.IsBvUrl(input))
{
infoService = new VideoInfoService(input);
}
// 番剧(电影、电视剧)
if (ParseEntrance.IsBangumiSeasonUrl(input) || ParseEntrance.IsBangumiEpisodeUrl(input) || ParseEntrance.IsBangumiMediaUrl(input))
{
action(new BangumiInfoService(input), page);
}
// 番剧(电影、电视剧)
if (ParseEntrance.IsBangumiSeasonUrl(input) || ParseEntrance.IsBangumiEpisodeUrl(input) || ParseEntrance.IsBangumiMediaUrl(input))
{
infoService = new BangumiInfoService(input);
}
// 课程
if (ParseEntrance.IsCheeseSeasonUrl(input) || ParseEntrance.IsCheeseEpisodeUrl(input))
{
action(new CheeseInfoService(input), page);
// 课程
if (ParseEntrance.IsCheeseSeasonUrl(input) || ParseEntrance.IsCheeseEpisodeUrl(input))
{
infoService = new CheeseInfoService(input);
}
}
if (infoService == null)
{
return;
}
action(infoService, page);
}
/// <summary>
@ -773,7 +785,7 @@ namespace DownKyi.ViewModels
// 传递video对象
addToDownloadService.GetVideo(VideoInfoView, VideoSections.ToList());
// 下载
i = addToDownloadService.AddToDownload(eventAggregator, directory, isAll);
i = addToDownloadService.AddToDownload(eventAggregator, dialogService, directory, isAll);
});
if (directory == null)

8
src/NuGet.config Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!-- 下一行的 clear 如果取消了注释,那么就会清除掉全局的 NuGet 源,而注释掉可以继承全局 NuGet 源,只是额外添加。 -->
<!-- <clear /> -->
<add key="MyNuget" value="../third_party" />
</packageSources>
</configuration>