Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
My-Responsitories committed Jun 9, 2023
1 parent 92373f6 commit 702533e
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 31 deletions.
2 changes: 2 additions & 0 deletions BBDown.Core/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class Config
//BiliPlus Area
public static string AREA { get; set; } = "";

public static string WBI { get; set; } = "";

public static readonly Dictionary<string, string> qualitys = new() {
{"127","8K 超高清" }, {"126","杜比视界" }, {"125","HDR 真彩" }, {"120","4K 超清" }, {"116","1080P 高帧率" },
{"112","1080P 高码率" }, {"80","1080P 高清" }, {"74","720P 高帧率" },
Expand Down
17 changes: 4 additions & 13 deletions BBDown.Core/Fetcher/SpaceVideoFetcher.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using BBDown.Core.Entity;
using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using static BBDown.Core.Util.HTTPUtil;
Expand All @@ -10,24 +9,16 @@ namespace BBDown.Core.Fetcher
{
public class SpaceVideoFetcher : IFetcher
{
public static string WbiSign(string api, string wbi)
{
return $"{api}&w_rid=" + string.Concat(MD5.HashData(Encoding.UTF8.GetBytes(api + wbi)).Select(i => i.ToString("x2")).ToArray());
}

public async Task<VInfo> FetchAsync(string id)
{
id = id[4..];
string[] tmp = id.Split("|");
id = tmp[0];
var wbi = tmp[1];
// using the live API can bypass w_rid
string userInfoApi = $"https://api.live.bilibili.com/live_user/v1/Master/info?uid={id}";
string userName = GetValidFileName(JsonDocument.Parse(await GetWebSourceAsync(userInfoApi)).RootElement.GetProperty("data").GetProperty("info").GetProperty("uname").ToString(), ".", true);
List<string> urls = new();
int pageSize = 50;
int pageNumber = 1;
var api = WbiSign($"mid={id}&order=pubdate&pn={pageNumber}&ps={pageSize}&tid=0&wts={DateTimeOffset.Now.ToUnixTimeSeconds().ToString()}", wbi);
var api = Parser.WbiSign($"mid={id}&order=pubdate&pn={pageNumber}&ps={pageSize}&tid=0&wts={DateTimeOffset.Now.ToUnixTimeSeconds().ToString()}");
api = $"https://api.bilibili.com/x/space/wbi/arc/search?{api}";
string json = await GetWebSourceAsync(api);
var infoJson = JsonDocument.Parse(json);
Expand All @@ -41,7 +32,7 @@ public async Task<VInfo> FetchAsync(string id)
while (pageNumber < totalPage)
{
pageNumber++;
urls.AddRange(await GetVideosByPageAsync(pageNumber, pageSize, id, wbi));
urls.AddRange(await GetVideosByPageAsync(pageNumber, pageSize, id));
}
File.WriteAllText($"{userName}的投稿视频.txt", string.Join('\n', urls));
Log("目前下载器不支持下载用户的全部投稿视频,不过程序已经获取到了该用户的全部投稿视频地址,你可以自行使用批处理脚本等手段调用本程序进行批量下载。如在Windows系统你可以使用如下代码:");
Expand All @@ -53,10 +44,10 @@ public async Task<VInfo> FetchAsync(string id)
throw new Exception("暂不支持该功能");
}

static async Task<List<string>> GetVideosByPageAsync(int pageNumber, int pageSize, string mid, string wbi)
static async Task<List<string>> GetVideosByPageAsync(int pageNumber, int pageSize, string mid)
{
List<string> urls = new();
var api = WbiSign($"mid={mid}&order=pubdate&pn={pageNumber}&ps={pageSize}&tid=0&wts={DateTimeOffset.Now.ToUnixTimeSeconds().ToString()}", wbi);
var api = Parser.WbiSign($"mid={mid}&order=pubdate&pn={pageNumber}&ps={pageSize}&tid=0&wts={DateTimeOffset.Now.ToUnixTimeSeconds().ToString()}");
api = $"https://api.bilibili.com/x/space/wbi/arc/search?{api}";
string json = await GetWebSourceAsync(api);
var infoJson = JsonDocument.Parse(json);
Expand Down
36 changes: 27 additions & 9 deletions BBDown.Core/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ namespace BBDown.Core
{
public partial class Parser
{
public static string WbiSign(string api)
{
return $"{api}&w_rid=" + string.Concat(MD5.HashData(Encoding.UTF8.GetBytes(api + Config.WBI)).Select(i => i.ToString("x2")).ToArray());
}

private static async Task<string> GetPlayJsonAsync(bool onlyAvc, string aidOri, string aid, string cid, string epId, bool tvApi, bool intl, bool appApi, string qn = "0")
{
LogDebug("aid={0},cid={1},epId={2},tvApi={3},IntlApi={4},appApi={5},qn={6}", aid, cid, epId, tvApi, intl, appApi, qn);
Expand All @@ -24,13 +29,14 @@ private static async Task<string> GetPlayJsonAsync(bool onlyAvc, string aidOri,
if (appApi) return await AppHelper.DoReqAsync(aid, cid, epId, qn, bangumi, onlyAvc, Config.TOKEN);

string prefix = tvApi ? bangumi ? "api.snm0516.aisee.tv/pgc/player/api/playurltv" : "api.snm0516.aisee.tv/x/tv/ugc/playurl"
: bangumi ? $"{Config.HOST}/pgc/player/web/playurl" : $"{Config.HOST}/x/player/playurl";
string api = $"https://{prefix}?avid={aid}&cid={cid}&qn={qn}&type=&otype=json" + (tvApi ? "" : "&fourk=1") +
$"&fnver=0&fnval=4048" + (Config.AREA != "" ? Config.TOKEN != "" ? $"&access_key={Config.TOKEN}&area={Config.AREA}" : $"&area={Config.AREA}" : "") +
(tvApi ? "&device=android&platform=android" +
"&mobi_app=android_tv_yst&npcybs=0&force_host=2&build=102801" +
(Config.TOKEN != "" ? $"&access_key={Config.TOKEN}" : "") : "") +
(bangumi ? $"&module=bangumi&ep_id={epId}&fourk=1" + "&session=" : "");
: bangumi ? $"{Config.HOST}/pgc/player/web/playurl" : "api.bilibili.com/x/player/wbi/playurl";

string api = $"avid={aid}&cid={cid}&fnval=4048&fnver=0" +
(tvApi ? "" : "&fourk=1") + (Config.AREA != "" ? Config.TOKEN != "" ? $"&access_key={Config.TOKEN}&area={Config.AREA}" : $"&area={Config.AREA}" : "") +
(tvApi ? "&device=android&platform=android&mobi_app=android_tv_yst&npcybs=0&force_host=2&build=102801" +
(Config.TOKEN != "" ? $"&access_key={Config.TOKEN}" : "") : "") + $"&otype=json&qn={qn}" +
(bangumi ? $"&module=bangumi&ep_id={epId}&fourk=1&session=" : $"&try_look=1&wts={GetTimeStamp(true)}");
api = $"https://{prefix}?{(bangumi ? api : WbiSign(api))}";
if (tvApi && bangumi)
{
api = (Config.TOKEN != "" ? $"access_key={Config.TOKEN}&" : "") +
Expand Down Expand Up @@ -79,6 +85,12 @@ private static async Task<string> GetPlayJsonAsync(string aid, string cid, strin
return webJson;
}

public static string SkiPcdn(List<string> urlList, string baseUrl)
{
urlList.Add(baseUrl);
return urlList.FirstOrDefault(i => !PcdnRegex().IsMatch(i), urlList.First());
}

public static async Task<(string, List<Video>, List<Audio>, List<string>, List<string>)> ExtractTracksAsync(string aidOri, string aid, string cid, string epId, bool tvApi, bool intlApi, bool appApi, string qn = "0")
{
List<Video> videoTracks = new();
Expand Down Expand Up @@ -106,13 +118,15 @@ private static async Task<string> GetPlayJsonAsync(string aid, string cid, strin
if (dashVideo.GetProperty("base_url").ToString() != "")
{
var videoId = stream.GetProperty("stream_info").GetProperty("quality").ToString();
var urlList = new List<string>() { dashVideo.GetProperty("base_url").ToString() };
urlList.AddRange(dashVideo.GetProperty("backup_url").EnumerateArray().ToList().Select(i => i.ToString()));
Video v = new()
{
dur = pDur,
id = videoId,
dfn = Config.qualitys[videoId],
bandwith = Convert.ToInt64(dashVideo.GetProperty("bandwidth").ToString()) / 1000,
baseUrl = dashVideo.GetProperty("base_url").ToString(),
baseUrl = urlList.FirstOrDefault(i => !BaseUrlRegex().IsMatch(i), urlList.First()),
codecs = GetVideoCodec(dashVideo.GetProperty("codecid").ToString()),
size = dashVideo.TryGetProperty("size", out var sizeNode) ? Convert.ToDouble(sizeNode.ToString()) : 0
};
Expand All @@ -123,13 +137,15 @@ private static async Task<string> GetPlayJsonAsync(string aid, string cid, strin

foreach(var node in audio)
{
var urlList = new List<string>() { node.GetProperty("base_url").ToString() };
urlList.AddRange(node.GetProperty("backup_url").EnumerateArray().ToList().Select(i => i.ToString()));
Audio a = new()
{
id = node.GetProperty("id").ToString(),
dfn = node.GetProperty("id").ToString(),
dur = pDur,
bandwith = Convert.ToInt64(node.GetProperty("bandwidth").ToString()) / 1000,
baseUrl = node.GetProperty("base_url").ToString(),
baseUrl = urlList.FirstOrDefault(i => !BaseUrlRegex().IsMatch(i), urlList.First()),
codecs = "M4A"
};
if (!audioTracks.Contains(a)) audioTracks.Add(a);
Expand Down Expand Up @@ -393,5 +409,7 @@ private static string GetSign(string parms, bool isBiliPlus)
private static partial Regex PlayerJsonRegex();
[GeneratedRegex("http.*:\\d+")]
private static partial Regex BaseUrlRegex();
[GeneratedRegex("://.*:\\d+/")]
private static partial Regex PcdnRegex();
}
}
14 changes: 7 additions & 7 deletions BBDown/BBDownUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -801,23 +801,23 @@ public static string RSubString(string sub)
return sub[..sub.LastIndexOf(".")];
}

public static string GetMixinKey(string orig)
private static string GetMixinKey(string orig)
{
byte[] mixinKeyEncTab = new byte[]
{
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
};

var tmp = new StringBuilder();
var tmp = new StringBuilder(32);
foreach (var index in mixinKeyEncTab)
{
tmp.Append(orig[index]);
}
return tmp.ToString();
}

public static async Task<(bool, string)> CheckLogin(string cookie)
public static async Task<bool> CheckLogin(string cookie)
{
try
{
Expand All @@ -826,13 +826,13 @@ public static string GetMixinKey(string orig)
var json = JsonDocument.Parse(source).RootElement;
var is_login = json.GetProperty("data").GetProperty("isLogin").GetBoolean();
var wbi_img = json.GetProperty("data").GetProperty("wbi_img");
var wbi = GetMixinKey(RSubString(wbi_img.GetProperty("img_url").GetString()) + RSubString(wbi_img.GetProperty("sub_url").GetString()));
LogDebug($"wbi: {wbi}");
return (is_login, wbi);
Core.Config.WBI = GetMixinKey(RSubString(wbi_img.GetProperty("img_url").GetString()) + RSubString(wbi_img.GetProperty("sub_url").GetString()));
LogDebug("wbi: {0}", Core.Config.WBI);
return is_login;
}
catch (Exception)
{
return (false, "");
return false;
}
}

Expand Down
3 changes: 1 addition & 2 deletions BBDown/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ private static async Task DoWorkAsync(MyOption myOption)
}

// 检测是否登录了账号
(bool is_login, string wbi) = await CheckLogin(Config.COOKIE);
bool is_login = await CheckLogin(Config.COOKIE);
if (!intlApi && !tvApi && Config.AREA == "")
{
Log("检测账号登录...");
Expand Down Expand Up @@ -411,7 +411,6 @@ private static async Task DoWorkAsync(MyOption myOption)
else if (aidOri.StartsWith("mid"))
{
fetcher = new SpaceVideoFetcher();
aidOri += $"|{wbi}";
}
else if (aidOri.StartsWith("listBizId"))
{
Expand Down

0 comments on commit 702533e

Please sign in to comment.