Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make biliplus support ss/md & replace upos host #492

Merged
merged 2 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion BBDown.Core/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ private static string GetTimeStamp(bool bflag)
private static string GetSign(string parms, bool isBiliPlus)
{
string toEncode = parms + (isBiliPlus ? "acd495b248ec528c2eed1e862d393126" : "59b43e04ad6965f34319062b478f83dd");
return string.Join("", MD5.HashData(Encoding.UTF8.GetBytes(toEncode)).Select(i => i.ToString("x2")).ToArray());
return string.Concat(MD5.HashData(Encoding.UTF8.GetBytes(toEncode)).Select(i => i.ToString("x2")).ToArray());
}

[GeneratedRegex("window.__playinfo__=([\\s\\S]*?)<\\/script>")]
Expand Down
136 changes: 67 additions & 69 deletions BBDown/BBDownUtil.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
Expand Down Expand Up @@ -53,14 +53,10 @@ public static async Task<string> GetAvIdAsync(string input)
{
avid = AvRegex().Match(input).Groups[1].Value;
}
else if (input.Contains("video/BV"))
else if (input.ToLower().Contains("video/bv"))
{
avid = await GetAidByBVAsync(BVRegex().Match(input).Groups[1].Value);
}
else if (input.Contains("video/bv"))
{
avid = await GetAidByBVAsync(BvRegex().Match(input).Groups[1].Value);
}
else if (input.Contains("/cheese/"))
{
string epId = "";
Expand All @@ -79,6 +75,11 @@ public static async Task<string> GetAvIdAsync(string input)
string epId = EpRegex().Match(input).Groups[1].Value;
avid = $"ep:{epId}";
}
else if (input.Contains("/ss"))
{
string epId = await GetEpIdByBangumiSSIdAsync(SsRegex().Match(input).Groups[1].Value);
avid = $"ep:{epId}";
}
else if (input.Contains("/medialist/") && input.Contains("business_id=") && input.Contains("business=space_collection")) //列表类型是合集
{
string bizId = GetQueryString("business_id", input);
Expand Down Expand Up @@ -135,11 +136,7 @@ public static async Task<string> GetAvIdAsync(string input)
avid = $"ep:{epId}";
}
}
else if (input.StartsWith("BV"))
{
avid = await GetAidByBVAsync(input[2..]);
}
else if (input.StartsWith("bv"))
else if (input.ToLower().StartsWith("bv"))
{
avid = await GetAidByBVAsync(input[2..]);
}
Expand All @@ -154,31 +151,14 @@ public static async Task<string> GetAvIdAsync(string input)
}
else if (input.StartsWith("ss"))
{
string web = await GetWebSourceAsync("https://www.bilibili.com/bangumi/play/" + input);
Regex regex = StateRegex();
string json = regex.Match(web).Groups[1].Value;
try
{
using var jDoc = JsonDocument.Parse(json);
string epId = jDoc.RootElement.GetProperty("epList").EnumerateArray().First().GetProperty("id").ToString();
avid = $"ep:{epId}";
}
catch (JsonException)
{
throw new Exception("输入有误");
}
string epId = await GetEpIdByBangumiSSIdAsync(input[2..]);
avid = $"ep:{epId}";
}
else if (input.StartsWith("md"))
{
string mdId = MdRegex().Match(input).Groups[1].Value;
try
{
avid = await GetAvIdAsync(await GetSSIdByMDAsync(mdId));
}
catch (JsonException)
{
throw new Exception("输入有误");
}
string epId = await GetEpIdByMDAsync(mdId);
avid = $"ep:{epId}";
}
else
{
Expand Down Expand Up @@ -209,7 +189,7 @@ public static string FormatTime(int time, bool absolute = false)
}

/// <summary>
/// 通过avid检测是否为版权内容如果是的话返回ep:xx格式
/// 通过avid检测是否为版权内容, 如果是的话返回ep:xx格式
/// </summary>
/// <param name="avid"></param>
/// <returns></returns>
Expand Down Expand Up @@ -238,11 +218,31 @@ public static async Task<string> FixAvidAsync(string avid)

public static async Task<string> GetAidByBVAsync(string bv)
{
string api = $"https://api.bilibili.com/x/web-interface/archive/stat?bvid={bv}";
string json = await GetWebSourceAsync(api);
using var jDoc = JsonDocument.Parse(json);
string aid = jDoc.RootElement.GetProperty("data").GetProperty("aid").ToString();
return aid;
if (bv.Length == 10)
{
// 能在本地就在本地
string TABLE = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF";
var BVChange = new Dictionary<char, byte>();
byte[] S = { 9, 8, 1, 6, 2, 4 };
long XOR = 177451812;
long ADD = 8728348608;
for (byte i = 0; i < 58; i++) BVChange.Add(TABLE[i], i);

long T = 0;
for (byte i = 0; i < 6; i++)
{
T += (long)Math.Pow(58, i) * BVChange[bv[S[i]]];
}
return ((T - ADD) ^ XOR).ToString();
}
else
{
string api = $"https://api.bilibili.com/x/web-interface/archive/stat?bvid={bv}";
string json = await GetWebSourceAsync(api);
using var jDoc = JsonDocument.Parse(json);
string aid = jDoc.RootElement.GetProperty("data").GetProperty("aid").ToString();
return aid;
}
}

public static async Task<string> GetEpidBySSIdAsync(string ssid)
Expand All @@ -254,13 +254,22 @@ public static async Task<string> GetEpidBySSIdAsync(string ssid)
return epId;
}

public static async Task<string> GetSSIdByMDAsync(string mdId)
public static async Task<string> GetEpIdByBangumiSSIdAsync(string ssId)
{
string api = $"https://{Core.Config.EPHOST}/pgc/view/web/season?season_id={ssId}";
string json = await GetWebSourceAsync(api);
using var jDoc = JsonDocument.Parse(json);
string epId = jDoc.RootElement.GetProperty("result").GetProperty("episodes").EnumerateArray().First().GetProperty("id").ToString();
return epId;
}

public static async Task<string> GetEpIdByMDAsync(string mdId)
{
var api = $"https://api.bilibili.com/pgc/review/user?media_id={mdId}";
var json = await GetWebSourceAsync(api);
string api = $"https://api.bilibili.com/pgc/review/user?media_id={mdId}";
string json = await GetWebSourceAsync(api);
using var jDoc = JsonDocument.Parse(json);
var ssId = "ss" + jDoc.RootElement.GetProperty("result").GetProperty("media").GetProperty("season_id").ToString();
return ssId;
string epId = jDoc.RootElement.GetProperty("result").GetProperty("media").GetProperty("new_ep").GetProperty("id").ToString();
return epId;
}

private static async Task RangeDownloadToTmpAsync(int id, string url, string tmpName, long fromPosition, long? toPosition, Action<int, long, long> onProgress, bool failOnRangeNotSupported = false)
Expand Down Expand Up @@ -402,7 +411,7 @@ public static async Task MultiThreadDownloadFileAsync(string url, string path, b
}
catch (NotSupportedException)
{
if (++retry == 3) throw new Exception($"服务器可能并不支持多线程下载请使用 --multi-thread false 关闭多线程");
if (++retry == 3) throw new Exception($"服务器可能并不支持多线程下载, 请使用 --multi-thread false 关闭多线程");
goto reDown;
}
catch (Exception)
Expand Down Expand Up @@ -448,7 +457,7 @@ private static List<Clip> GetAllClips(string url, long fileSize)
}

/// <summary>
/// 输入一堆已存在的文件合并到新文件
/// 输入一堆已存在的文件, 合并到新文件
/// </summary>
/// <param name="files"></param>
/// <param name="outputFilePath"></param>
Expand Down Expand Up @@ -564,7 +573,7 @@ public static string GetValidFileName(string input, string re = ".", bool filter


/// <summary>
/// 获取url字符串参数返回参数值字符串
/// 获取url字符串参数, 返回参数值字符串
/// </summary>
/// <param name="name">参数名称</param>
/// <param name="url">url字符串</param>
Expand Down Expand Up @@ -605,22 +614,13 @@ public static string GetSession(string buvid3)
public static string GetSign(string parms)
{
string toEncode = parms + "59b43e04ad6965f34319062b478f83dd";
byte[] bs = Encoding.UTF8.GetBytes(toEncode);
byte[] hs = MD5.HashData(bs);
StringBuilder sb = new();
foreach (byte b in hs)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
return string.Concat(MD5.HashData(Encoding.UTF8.GetBytes(toEncode)).Select(i => i.ToString("x2")).ToArray());
}

public static string GetTimeStamp(bool bflag)
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
string ret = bflag ? Convert.ToInt64(ts.TotalSeconds).ToString() : Convert.ToInt64(ts.TotalMilliseconds).ToString();

return ret;
DateTimeOffset ts = DateTimeOffset.Now;
return bflag ? ts.ToUnixTimeSeconds().ToString() : ts.ToUnixTimeMilliseconds().ToString();
}

//https://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings
Expand Down Expand Up @@ -750,7 +750,7 @@ public static async Task<List<ViewPoint>> FetchPointsAsync(string cid, string ai
}

/// <summary>
/// 生成metadata文件用于ffmpeg混流章节信息
/// 生成metadata文件, 用于ffmpeg混流章节信息
/// </summary>
/// <param name="points"></param>
/// <returns></returns>
Expand All @@ -772,7 +772,7 @@ public static string GetFFmpegMetaString(List<ViewPoint> points)
}

/// <summary>
/// 生成metadata文件用于mp4box混流章节信息
/// 生成metadata文件, 用于mp4box混流章节信息
/// </summary>
/// <param name="points"></param>
/// <returns></returns>
Expand Down Expand Up @@ -810,27 +810,25 @@ public static async Task<bool> CheckLogin(string cookie)
}
}

[GeneratedRegex("av(\\d{1,})")]
[GeneratedRegex("av(\\d+)")]
private static partial Regex AvRegex();
[GeneratedRegex("BV(\\w+)")]
[GeneratedRegex("[Bb][Vv](\\w+)")]
private static partial Regex BVRegex();
[GeneratedRegex("bv(\\w+)")]
private static partial Regex BvRegex();
[GeneratedRegex("/ep(\\d{1,})")]
[GeneratedRegex("/ep(\\d+)")]
private static partial Regex EpRegex();
[GeneratedRegex("/ss(\\d{1,})")]
[GeneratedRegex("/ss(\\d+)")]
private static partial Regex SsRegex();
[GeneratedRegex("space\\.bilibili\\.com/(\\d{1,})")]
[GeneratedRegex("space\\.bilibili\\.com/(\\d+)")]
private static partial Regex UidRegex();
[GeneratedRegex("global\\.bilibili\\.com/play/\\d+/(\\d+)")]
private static partial Regex GlobalEpRegex();
[GeneratedRegex("bangumi/media/(md\\d+)")]
private static partial Regex BangumiMdRegex();
[GeneratedRegex("window.__INITIAL_STATE__=([\\s\\S].*?);\\(function\\(\\)")]
private static partial Regex StateRegex();
[GeneratedRegex("ep(\\d{1,})")]
[GeneratedRegex("ep(\\d+)")]
private static partial Regex EpRegex2();
[GeneratedRegex("md(\\d{1,})")]
[GeneratedRegex("md(\\d+)")]
private static partial Regex MdRegex();
[GeneratedRegex("^\\d+$")]
private static partial Regex NumRegex();
Expand Down
5 changes: 4 additions & 1 deletion BBDown/CommandLineInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal class CommandLineInvoker
private readonly static Argument<string> Url = new("url", description: "视频地址 或 av|bv|BV|ep|ss");
private readonly static Option<bool> UseTvApi = new(new string[] { "--use-tv-api", "-tv" }, "使用TV端解析模式");
private readonly static Option<bool> UseAppApi = new(new string[] { "--use-app-api", "-app" }, "使用APP端解析模式");
private readonly static Option<bool> UseIntlApi = new(new string[] { "--use-intl-api", "-intl" }, "使用国际版解析模式");
private readonly static Option<bool> UseIntlApi = new(new string[] { "--use-intl-api", "-intl" }, "使用国际版(东南亚视频)解析模式");
private readonly static Option<bool> UseMP4box = new(new string[] { "--use-mp4box" }, "使用MP4Box来混流");
private readonly static Option<string> EncodingPriority = new(new string[] { "--encoding-priority" }, "视频编码的选择优先级, 用逗号分割 例: \"hevc,av1,avc\"");
private readonly static Option<string> DfnPriority = new(new string[] { "--dfn-priority" }, "画质优先级,用逗号分隔 例: \"8K 超高清, 1080P 高码率, HDR 真彩, 杜比视界\"");
Expand Down Expand Up @@ -44,6 +44,7 @@ internal class CommandLineInvoker
private readonly static Option<string> FFmpegPath = new(new string[] { "--ffmpeg-path" }, "设置ffmpeg的路径");
private readonly static Option<string> Mp4boxPath = new(new string[] { "--mp4box-path" }, "设置mp4box的路径");
private readonly static Option<string> Aria2cPath = new(new string[] { "--aria2c-path" }, "设置aria2c的路径");
private readonly static Option<string> UposHost = new(new string[] { "--upos-host" }, "自定义upos服务器");
private readonly static Option<string> DelayPerPage = new(new string[] { "--delay-per-page" }, "设置下载合集分P之间的下载间隔时间(单位: 秒, 默认无间隔)");
private readonly static Option<string> FilePattern = new(new string[] { "--file-pattern", "-F" }, $"使用内置变量自定义单P存储文件名:\r\n\r\n" + $"<videoTitle>: 视频主标题\r\n" + $"<pageNumber>: 视频分P序号\r\n" + $"<pageNumberWithZero>: 视频分P序号(前缀补零)\r\n" + $"<pageTitle>: 视频分P标题\r\n" + $"<aid>: 视频aid\r\n" + $"<cid>: 视频cid\r\n" + $"<dfn>: 视频清晰度\r\n" + $"<res>: 视频分辨率\r\n" + $"<fps>: 视频帧率\r\n" + $"<videoCodecs>: 视频编码\r\n" + $"<videoBandwidth>: 视频码率\r\n" + $"<audioCodecs>: 音频编码\r\n" + $"<audioBandwidth>: 音频码率\r\n" + $"<ownerName>: 上传者名称\r\n" + $"<ownerMid>: 上传者mid\r\n\r\n" + $"默认为: {Program.SinglePageDefaultSavePath}\r\n");
private readonly static Option<string> MultiFilePattern = new(new string[] { "--multi-file-pattern", "-M" }, $"使用内置变量自定义多P存储文件名:\r\n\r\n" + $"默认为: {Program.MultiPageDefaultSavePath}\r\n");
Expand Down Expand Up @@ -102,6 +103,7 @@ protected override MyOption GetBoundValue(BindingContext bindingContext)
if (bindingContext.ParseResult.HasOption(FFmpegPath)) option.FFmpegPath = bindingContext.ParseResult.GetValueForOption(FFmpegPath)!;
if (bindingContext.ParseResult.HasOption(Mp4boxPath)) option.Mp4boxPath = bindingContext.ParseResult.GetValueForOption(Mp4boxPath)!;
if (bindingContext.ParseResult.HasOption(Aria2cPath)) option.Aria2cPath = bindingContext.ParseResult.GetValueForOption(Aria2cPath)!;
if (bindingContext.ParseResult.HasOption(UposHost)) option.UposHost = bindingContext.ParseResult.GetValueForOption(UposHost)!;
if (bindingContext.ParseResult.HasOption(DelayPerPage)) option.DelayPerPage = bindingContext.ParseResult.GetValueForOption(DelayPerPage)!;
if (bindingContext.ParseResult.HasOption(Host)) option.Host = bindingContext.ParseResult.GetValueForOption(Host)!;
if (bindingContext.ParseResult.HasOption(EpHost)) option.EpHost = bindingContext.ParseResult.GetValueForOption(EpHost)!;
Expand Down Expand Up @@ -156,6 +158,7 @@ public static RootCommand GetRootCommand(Func<MyOption, Task> action)
FFmpegPath,
Mp4boxPath,
Aria2cPath,
UposHost,
DelayPerPage,
Host,
EpHost,
Expand Down
1 change: 1 addition & 0 deletions BBDown/MyOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ internal class MyOption
public string FFmpegPath { get; set; } = "";
public string Mp4boxPath { get; set; } = "";
public string Aria2cPath { get; set; } = "";
public string UposHost { get; set; } = "";
public string DelayPerPage { get; set; } = "0";
public string Host { get; set; } = "api.bilibili.com";
public string EpHost { get; set; } = "api.bilibili.com";
Expand Down