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

fix app subtitle download #818

Merged
merged 1 commit into from
May 12, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BBDown.Core/APP/Response/dmviewreply.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ message VideoMask {
message VideoSubtitle {
optional string lan = 1;
optional string lanDoc = 2;
optional SubtitleItem subtitles = 3;
repeated SubtitleItem subtitles = 3;

}

Expand Down
31 changes: 3 additions & 28 deletions BBDown.Core/AppHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
using System.Buffers.Binary;
using System.IO.Compression;
using System.Linq;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Serialization;
using static BBDown.Core.Util.HTTPUtil;
using static BBDown.Core.Logger;

namespace BBDown.Core
Expand Down Expand Up @@ -322,7 +322,7 @@ private static string GenerateFawkesReqBin()
/// </summary>
/// <param name="data"></param>
/// <returns>字节流</returns>
private static byte[] ReadMessage(byte[] data)
public static byte[] ReadMessage(byte[] data)
{
byte first;
int size;
Expand All @@ -348,7 +348,7 @@ private static (byte first, int size) ReadInfo(byte[] data)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private static byte[] PackMessage(byte[] input)
public static byte[] PackMessage(byte[] input)
{
using var stream = new MemoryStream();
using (var writer = new BinaryWriter(stream))
Expand Down Expand Up @@ -393,31 +393,6 @@ private static byte[] GzipDecompress(byte[] data)
}
return output.ToArray();
}

public static async Task<byte[]> GetPostResponseAsync(string Url, byte[] postData, Dictionary<string, string> headers)
{
LogDebug("Post to: {0}, data: {1}", Url, Convert.ToBase64String(postData));

ByteArrayContent content = new(postData);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/grpc");

HttpRequestMessage request = new()
{
RequestUri = new Uri(Url),
Method = HttpMethod.Post,
Content = content,
//Version = HttpVersion.Version20
};

if (headers != null)
foreach (KeyValuePair<string, string> header in headers)
request.Headers.TryAddWithoutValidation(header.Key, header.Value);

HttpResponseMessage response = await Util.HTTPUtil.AppHttpClient.SendAsync(request);
byte[] bytes = await response.Content.ReadAsByteArrayAsync();

return bytes;
}
}


Expand Down
38 changes: 28 additions & 10 deletions BBDown.Core/Util/HTTPUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,36 @@ public static async Task<string> GetWebLocationAsync(string url)
return location;
}

public static async Task<string> GetPostResponseAsync(string Url, byte[] postData)
public static async Task<byte[]> GetPostResponseAsync(string Url, byte[] postData, Dictionary<string, string> headers = null)
{
LogDebug("Post to: {0}, data: {1}", Url, Convert.ToBase64String(postData));
using HttpRequestMessage request = new(HttpMethod.Post, Url);
request.Headers.TryAddWithoutValidation("Content-Type", "application/grpc");
request.Headers.TryAddWithoutValidation("Content-Length", postData.Length.ToString());
request.Headers.TryAddWithoutValidation("User-Agent", "Dalvik/2.1.0 (Linux; U; Android 6.0.1; oneplus a5010 Build/V417IR) 6.10.0 os/android model/oneplus a5010 mobi_app/android build/6100500 channel/bili innerVer/6100500 osVer/6.0.1 network/2");
request.Headers.TryAddWithoutValidation("Cookie", Config.COOKIE);
request.Content = new ByteArrayContent(postData);
var webResponse = await AppHttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
string htmlCode = await webResponse.Content.ReadAsStringAsync();
return htmlCode;

ByteArrayContent content = new(postData);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/grpc");

HttpRequestMessage request = new()
{
RequestUri = new Uri(Url),
Method = HttpMethod.Post,
Content = content,
//Version = HttpVersion.Version20
};

if (headers != null)
{
foreach (KeyValuePair<string, string> header in headers)
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
else
{
request.Headers.TryAddWithoutValidation("User-Agent", "Dalvik/2.1.0 (Linux; U; Android 6.0.1; oneplus a5010 Build/V417IR) 6.10.0 os/android model/oneplus a5010 mobi_app/android build/6100500 channel/bili innerVer/6100500 osVer/6.0.1 network/2");
request.Headers.TryAddWithoutValidation("grpc-encoding", "gzip");
}

HttpResponseMessage response = await AppHttpClient.SendAsync(request);
byte[] bytes = await response.Content.ReadAsByteArrayAsync();

return bytes;
}
}
}
77 changes: 38 additions & 39 deletions BBDown.Core/Util/SubUtil.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Text;
using BBDown.Core.Protobuf;
using Google.Protobuf;
using System.Text;
using static BBDown.Core.Entity.Entity;
using static BBDown.Core.Util.HTTPUtil;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -356,48 +358,39 @@ public static (string, string) GetSubtitleCode(string key)
}
}

private static byte[] GetPayload(long aid, long cid)
{
var obj = new DmViewReq
{
Pid = aid,
Oid = cid,
Type = 1,
Spmid = "main.ugc-video-detail.0.0",
};
return AppHelper.PackMessage(obj.ToByteArray());
}

private static async Task<List<Subtitle>?> GetSubtitlesFromApi3Async(string aid, string cid, string epId, int index)
{
try
{
List<Subtitle> subtitles = new();
//grpc调用接口 protobuf
string api = "https://app.biliapi.net/bilibili.community.service.dm.v1.DM/DmView";
int _aid = Convert.ToInt32(aid);
int _cid = Convert.ToInt32(cid);
int _type = 1;
byte[] data = new byte[18];
data[0] = 0x0; data[1] = 0x0; data[2] = 0x0; data[3] = 0x0; data[4] = 0xD; //先固定死了
int i = 5;
data[i++] = Convert.ToByte((1 << 3) | 0); // index=1
while ((_aid & -128) != 0)
{
data[i++] = Convert.ToByte((_aid & 127) | 128);
_aid >>= 7;
}
data[i++] = Convert.ToByte(_aid);
data[i++] = Convert.ToByte((2 << 3) | 0); // index=2
while ((_cid & -128) != 0)

var data = GetPayload(Convert.ToInt64(aid), Convert.ToInt64(cid));

var t = AppHelper.ReadMessage(await GetPostResponseAsync(api, data));
var resp = new MessageParser<DmViewReply>(() => new DmViewReply()).ParseFrom(t);

if (resp.Subtitle != null && resp.Subtitle.Subtitles != null)
{
data[i++] = Convert.ToByte((_cid & 127) | 128);
_cid >>= 7;
subtitles.AddRange(resp.Subtitle.Subtitles.Select(item => new Subtitle() {
url = item.SubtitleUrl,
lan = item.Lan,
path = $"{aid}/{aid}.{cid}.{item.Lan}.srt"
}));
}
data[i++] = Convert.ToByte(_cid);
data[i++] = Convert.ToByte((3 << 3) | 0); // index=3
data[i++] = Convert.ToByte(_type);
string t = await GetPostResponseAsync(api, data);
Regex reg = CnJsonRegex();
foreach (Match m in reg.Matches(t).Cast<Match>())
{
Subtitle subtitle = new()
{
url = m.Groups[2].Value,
lan = m.Groups[1].Value,
path = $"{aid}/{aid}.{cid}.{m.Groups[1].Value}.srt"
};
subtitles.Add(subtitle);
}

//有空的URL 不合法
if (subtitles.Any(s => string.IsNullOrEmpty(s.url)))
throw new Exception("Bad url");
Expand All @@ -421,9 +414,17 @@ public static async Task<List<Subtitle>> GetSubtitlesAsync(string aid, string ci
}
else
{
subtitles = await GetSubtitlesFromApi2Async(aid, cid, epId, index)
?? await GetSubtitlesFromApi1Async(aid, cid, epId, index)
?? await GetSubtitlesFromApi3Async(aid, cid, epId, index);
if (Config.COOKIE == "")
{
subtitles = await GetSubtitlesFromApi3Async(aid, cid, epId, index); // 未登录只有APP可以拿到字幕了
}
else
{
subtitles = await GetSubtitlesFromApi2Async(aid, cid, epId, index)
?? await GetSubtitlesFromApi1Async(aid, cid, epId, index)
?? await GetSubtitlesFromApi3Async(aid, cid, epId, index);
}

}

if (subtitles == null)
Expand Down Expand Up @@ -480,7 +481,5 @@ private static string FormatTime(double sec) //64.13

[GeneratedRegex("-[a-z]")]
private static partial Regex NonCapsRegex();
[GeneratedRegex("(zh-Han[st]).*?(http.*?\\.json)")]
private static partial Regex CnJsonRegex();
}
}