fix(core): fix websocket danmu transport

This commit is contained in:
genteure 2023-08-19 19:00:48 +08:00
parent b2ef1d982c
commit 2a38e2ccb9
3 changed files with 43 additions and 15 deletions

View File

@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.IO.Pipelines;
using System.Net;
using System.Net.WebSockets;
using System.Runtime.InteropServices;
using System.Threading;
@ -11,24 +13,43 @@ namespace BililiveRecorder.Core.Api.Danmaku
{
internal class DanmakuTransportWebSocket : IDanmakuTransport
{
private static readonly bool isDotNetFramework = RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal);
private readonly ClientWebSocket socket;
protected virtual string Scheme => "ws";
static DanmakuTransportWebSocket()
{
if (!RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal))
return;
var headerInfoTable = typeof(WebHeaderCollection).Assembly.GetType("System.Net.HeaderInfoTable", false);
if (headerInfoTable is null) return;
var headerHashTable = headerInfoTable.GetField("HeaderHashTable", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
if (headerHashTable is null) return;
if (headerHashTable.GetValue(null) is not Hashtable table) return;
var info = table["User-Agent"];
if (info is null) return;
var isRequestRestrictedProperty = info.GetType().GetField("IsRequestRestricted", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (isRequestRestrictedProperty is null) return;
isRequestRestrictedProperty.SetValue(info, false);
}
public DanmakuTransportWebSocket()
{
this.socket = new ClientWebSocket();
this.socket.Options.UseDefaultCredentials = false;
this.socket.Options.Credentials = null;
this.socket.Options.Proxy = null;
this.socket.Options.Cookies = null;
this.socket.Options.SetRequestHeader("Origin", HttpApiClient.HttpHeaderOrigin);
if (!isDotNetFramework)
this.socket.Options.SetRequestHeader("User-Agent", HttpApiClient.HttpHeaderUserAgent);
var options = this.socket.Options;
options.UseDefaultCredentials = false;
options.Credentials = null;
options.Proxy = null;
options.Cookies = null;
options.SetRequestHeader("Origin", HttpApiClient.HttpHeaderOrigin);
options.SetRequestHeader("Accept-Language", HttpApiClient.HttpHeaderAcceptLanguage);
options.SetRequestHeader("User-Agent", HttpApiClient.HttpHeaderUserAgent);
}
public async Task<PipeReader> ConnectAsync(string host, int port, CancellationToken cancellationToken)

View File

@ -15,9 +15,10 @@ namespace BililiveRecorder.Core.Api.Http
internal class HttpApiClient : IApiClient, IDanmakuServerApiClient, ICookieTester
{
internal const string HttpHeaderAccept = "application/json, text/javascript, */*; q=0.01";
internal const string HttpHeaderAcceptLanguage = "zh-CN";
internal const string HttpHeaderReferer = "https://live.bilibili.com/";
internal const string HttpHeaderOrigin = "https://live.bilibili.com";
internal const string HttpHeaderUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36";
internal const string HttpHeaderUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36";
private static readonly Regex matchCookieUidRegex = new Regex(@"DedeUserID=(\d+?);", RegexOptions.Compiled);
private static readonly Regex matchCookieBuvid3Regex = new Regex(@"buvid3=(.+?);", RegexOptions.Compiled);
private long uid;
@ -49,6 +50,7 @@ namespace BililiveRecorder.Core.Api.Http
};
var headers = client.DefaultRequestHeaders;
headers.Add("Accept", HttpHeaderAccept);
headers.Add("Accept-Language", HttpHeaderAcceptLanguage);
headers.Add("Origin", HttpHeaderOrigin);
headers.Add("Referer", HttpHeaderReferer);
headers.Add("User-Agent", HttpHeaderUserAgent);
@ -59,7 +61,7 @@ namespace BililiveRecorder.Core.Api.Http
headers.Add("Cookie", cookie_string);
long.TryParse(matchCookieUidRegex.Match(cookie_string).Groups[1].Value, out var uid);
this.uid = uid;
string buvid3 = matchCookieBuvid3Regex.Match(cookie_string).Groups[1].Value;
var buvid3 = matchCookieBuvid3Regex.Match(cookie_string).Groups[1].Value;
if (!string.IsNullOrWhiteSpace(buvid3))
this.buvid3 = buvid3;
else
@ -137,7 +139,7 @@ namespace BililiveRecorder.Core.Api.Http
if (jo["code"]?.ToObject<int>() != 0)
return (false, $"Response:\n{resp}");
string message = $@"User: {jo["data"]?["uname"]?.ToObject<string>()}
var message = $@"User: {jo["data"]?["uname"]?.ToObject<string>()}
UID (from API response): {jo["data"]?["uid"]?.ToObject<string>()}
UID (from Cookie): {this.GetUid()}
BUVID3 (from Cookie): {this.GetBuvid3()}";

View File

@ -209,6 +209,8 @@ namespace BililiveRecorder.Core
var room = (await this.apiClient.GetRoomInfoAsync(this.RoomConfig.RoomId).ConfigureAwait(false)).Data;
if (room != null)
{
this.logger.Debug("拉取房间信息成功: {@room}", room);
this.RoomConfig.RoomId = room.Room.RoomId;
this.ShortId = room.Room.ShortId;
this.Uid = room.Room.Uid;
@ -479,7 +481,7 @@ namespace BililiveRecorder.Core
{
const int MAX_ATTEMPT = 3;
var attempt = 0;
retry:
retry:
try
{
var coverUrl = this.RawBilibiliApiJsonData?["room_info"]?["cover"]?.ToObject<string>();
@ -575,12 +577,15 @@ retry:
switch (d.MsgType)
{
case Api.Danmaku.DanmakuMsgType.LiveStart:
this.logger.Debug("推送直播开始");
this.Streaming = true;
break;
case Api.Danmaku.DanmakuMsgType.LiveEnd:
this.logger.Debug("推送直播结束");
this.Streaming = false;
break;
case Api.Danmaku.DanmakuMsgType.RoomChange:
this.logger.Debug("推送房间信息变更, {Title}, {AreaNameParent}, {AreaNameChild}", d.Title, d.ParentAreaName, d.AreaName);
this.Title = d.Title ?? this.Title;
this.AreaNameParent = d.ParentAreaName ?? this.AreaNameParent;
this.AreaNameChild = d.AreaName ?? this.AreaNameChild;