From b29e36030d7e45723100961e53ce6090ea98efbb Mon Sep 17 00:00:00 2001
From: Muihd <1083092844@qq.com>
Date: Fri, 26 Apr 2024 00:47:08 +0800
Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=9B=B4=E6=92=AD=E4=BC=B4?=
=?UTF-8?q?=E4=BE=A3=E5=BC=80=E6=92=AD=E8=8E=B7=E5=8F=96=E6=88=BF=E9=97=B4?=
=?UTF-8?q?=E4=BF=A1=E6=81=AF;=20WebRoomid=20=E5=85=A8=E9=83=A8=E6=94=B9?=
=?UTF-8?q?=E4=B8=BA=20string?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
BarrageGrab/AppRuntime.cs | 6 +-
BarrageGrab/AppSetting.cs | 4 +-
.../Modles/JsonEntity/BarrageMessages.cs | 2 +-
BarrageGrab/Modles/RoomInfo.cs | 67 +-
BarrageGrab/Modles/WebCastGift.cs | 759 ++++++++++++++++++
BarrageGrab/ObjectExtension.cs | 6 +-
BarrageGrab/Proxy/TitaniumProxy.cs | 59 +-
BarrageGrab/WssBarrageGrab.cs | 42 +-
BarrageGrab/WssBarrageService.csproj | 7 +
9 files changed, 900 insertions(+), 52 deletions(-)
create mode 100644 BarrageGrab/Modles/WebCastGift.cs
diff --git a/BarrageGrab/AppRuntime.cs b/BarrageGrab/AppRuntime.cs
index b949d2d..390466f 100644
--- a/BarrageGrab/AppRuntime.cs
+++ b/BarrageGrab/AppRuntime.cs
@@ -144,11 +144,11 @@ namespace BarrageGrab
///
///
///
- public long GetCachedWebRoomid(string roomid)
+ public string GetCachedWebRoomid(string roomid)
{
RoomInfo value;
- if (RoomInfoCache.TryGetValue(roomid,out value)) return long.Parse(value.WebRoomId??"-1");
- return -1;
+ if (RoomInfoCache.TryGetValue(roomid,out value)) return value.WebRoomId??"未知";
+ return "未知";
}
///
diff --git a/BarrageGrab/AppSetting.cs b/BarrageGrab/AppSetting.cs
index b5543e6..5a08010 100644
--- a/BarrageGrab/AppSetting.cs
+++ b/BarrageGrab/AppSetting.cs
@@ -39,7 +39,7 @@ namespace BarrageGrab
ForcePolling = bool.Parse(AppSettings["forcePolling"].Trim());
PollingInterval = int.Parse(AppSettings["pollingInterval"].Trim());
DisableLivePageScriptCache = bool.Parse(AppSettings["disableLivePageScriptCache"].Trim());
- WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).Select(x => long.Parse(x)).ToArray();
+ WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
ConfigComPort();
ConfigFilter();
@@ -177,7 +177,7 @@ namespace BarrageGrab
///
/// 监听的房间号
///
- public long[] WebRoomIds { get; private set; } = new long[0];
+ public string[] WebRoomIds { get; private set; } = new string[0];
///
/// 使用域名过滤
diff --git a/BarrageGrab/Modles/JsonEntity/BarrageMessages.cs b/BarrageGrab/Modles/JsonEntity/BarrageMessages.cs
index 46f333a..7ae4a19 100644
--- a/BarrageGrab/Modles/JsonEntity/BarrageMessages.cs
+++ b/BarrageGrab/Modles/JsonEntity/BarrageMessages.cs
@@ -115,7 +115,7 @@ namespace BarrageGrab.Modles.JsonEntity
///
/// web直播间ID
///
- public long WebRoomId { get; set; }
+ public string WebRoomId { get; set; }
}
///
diff --git a/BarrageGrab/Modles/RoomInfo.cs b/BarrageGrab/Modles/RoomInfo.cs
index 2b6e4c9..635438c 100644
--- a/BarrageGrab/Modles/RoomInfo.cs
+++ b/BarrageGrab/Modles/RoomInfo.cs
@@ -16,7 +16,7 @@ namespace BarrageGrab.Modles
/// Web房间号
///
public string WebRoomId { get; set; }
-
+
///
/// 房间号
///
@@ -66,7 +66,7 @@ namespace BarrageGrab.Modles
/// 直播间管理员用户id
///
public List AdminUserIds { get; set; } = new List();
-
+
///
/// 主播信息
///
@@ -510,7 +510,7 @@ namespace BarrageGrab.Modles
///
///
///
- public static Tuple TryParseRoomPageHtml(string html, out RoomInfo result)
+ public static Tuple TryParseRoomPageHtml(string html, out RoomInfo result)
{
result = null;
if (html.IsNullOrWhiteSpace())
@@ -579,7 +579,66 @@ namespace BarrageGrab.Modles
HeadUrl = roomOwner["avatar_thumb"]["url_list"].Values()?.FirstOrDefault() ?? "",
FollowStatus = roomOwner["follow_info"]["follow_status"].Value()
};
- }
+ }
+ return Tuple.Create(0, "succ");
+ }
+
+
+ ///
+ /// 从直播伴侣的直播创建回调中解析房间信息
+ ///
+ ///
+ ///
+ /// 缓存
+ ///
+ public static Tuple TryParseStreamPusherCreate(string json, out RoomInfo info)
+ {
+ info = null;
+ JObject res;
+ try
+ {
+ res = JsonConvert.DeserializeObject(json);
+ }
+ catch (Exception)
+ {
+ return Tuple.Create(4, "不是合法的json格式");
+ }
+ if (res == null)
+ {
+ return Tuple.Create(1, "正文为空");
+ }
+
+ var rootData = res["data"];
+ var ownerInfo = rootData["owner"];
+
+ var dto = new RoomInfo();
+ dto.RoomId = rootData["id_str"]?.ToString() ?? "";
+ dto.AdminUserIds = rootData["admin_user_ids_str"]?.Values().ToList() ?? new List();
+ dto.IsLive = rootData["status"]?.Value() == 2;
+ dto.Title = rootData["title"]?.ToString() ?? "";
+ dto.UserCount = long.Parse(rootData["room_view_stats"]?["display_value"]?.Value() ?? "0");
+ dto.TotalUserCount = rootData["room_view_stats"]?["total_user_str"]?.Value() ?? "0";
+ dto.LikeCount = rootData["like_count"]?.Value() ?? 0;
+ dto.QrcodeUrl = $"https://live.douyin.com/{ownerInfo?["display_id"] ?? ""}";
+ dto.AuthInfo = rootData["room_auth"]?.ToObject();
+ dto.Cover = rootData["cover"]?["url_list"]?.Values().FirstOrDefault() ?? "";//下播情况下没有cover字段
+ dto.WebRoomId = rootData["web_rid"]?.ToString() ?? ownerInfo?["display_id"]?.ToString() ?? "";
+ if (ownerInfo != null)
+ {
+ dto.Owner = new RoomAnchor()
+ {
+ UserId = ownerInfo["id_str"].ToString(),
+ Nickname = ownerInfo["nickname"].ToString(),
+ SecUid = ownerInfo["sec_uid"].ToString(),
+ HeadUrl = ownerInfo["avatar_thumb"]?["url_list"]?.Values()?.FirstOrDefault()?.ToString(),
+ FollowStatus = ownerInfo["follow_info"]?["follow_status"]?.Value() ?? 0
+ };
+ }
+
+
+
+ info = dto;
+
return Tuple.Create(0, "succ");
}
}
diff --git a/BarrageGrab/Modles/WebCastGift.cs b/BarrageGrab/Modles/WebCastGift.cs
new file mode 100644
index 0000000..27b2e49
--- /dev/null
+++ b/BarrageGrab/Modles/WebCastGift.cs
@@ -0,0 +1,759 @@
+using System.Collections.Generic;
+
+namespace BarrageGrab.Modles
+{
+ ///
+ /// 礼物信息
+ ///
+ public class WebCastGift
+ {
+ ///
+ /// 图片信息
+ ///
+ public GiftImage image { get; set; }
+ ///
+ /// 描述
+ ///
+ public string describe { get; set; }
+ ///
+ /// 是否通知
+ ///
+ public bool notify { get; set; }
+ ///
+ /// 持续时长
+ ///
+ public int duration { get; set; }
+ ///
+ /// ID
+ ///
+ public long id { get; set; }
+ ///
+ /// 用于连麦
+ ///
+ public bool for_linkmic { get; set; }
+ ///
+ /// 涂鸦
+ ///
+ public bool doodle { get; set; }
+ ///
+ /// 用于粉丝团
+ ///
+ public bool for_fansclub { get; set; }
+ ///
+ /// 是否是连击礼物
+ ///
+ public bool combo { get; set; }
+ ///
+ /// 类型
+ ///
+ public int type { get; set; }
+ ///
+ /// 钻石数量
+ ///
+ public int diamond_count { get; set; }
+ ///
+ /// 是否显示在礼物面板上
+ ///
+ public bool is_displayed_on_panel { get; set; }
+ ///
+ /// 主要效果 ID
+ ///
+ public int primary_effect_id { get; set; }
+ ///
+ /// 名称
+ ///
+ public string name { get; set; }
+ ///
+ /// 区域
+ ///
+ public string region { get; set; }
+ ///
+ /// 手动
+ ///
+ public string manual { get; set; }
+ ///
+ /// 是否为自定义礼物
+ ///
+ public bool for_custom { get; set; }
+ ///
+ /// 特殊效果
+ ///
+ public Dictionary special_effects { get; set; }
+ ///
+ /// 图标信息
+ ///
+ public Icon icon { get; set; }
+ ///
+ /// 行为类型
+ ///
+ public int action_type { get; set; }
+
+ ///
+ /// 西瓜子数
+ ///
+ public int watermelon_seeds { get; set; }
+
+ ///
+ /// 金特效
+ ///
+ public string gold_effect { get; set; }
+
+ ///
+ /// 订阅列表
+ ///
+ public List
///
///
- public static string ToJson(this object obj)
+ public static string ToJson(this object obj,bool format = false)
{
if (obj is string)
{
return obj.ToString();
- }
- return JsonConvert.SerializeObject(obj);
+ }
+ return JsonConvert.SerializeObject(obj, format?Formatting.Indented:Formatting.None);
}
///
diff --git a/BarrageGrab/Proxy/TitaniumProxy.cs b/BarrageGrab/Proxy/TitaniumProxy.cs
index 24a9bc4..724f3a7 100644
--- a/BarrageGrab/Proxy/TitaniumProxy.cs
+++ b/BarrageGrab/Proxy/TitaniumProxy.cs
@@ -7,7 +7,10 @@ using System.Net.Security;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BarrageGrab.Modles;
+using BarrageGrab.Modles.JsonEntity;
using BarrageGrab.Proxy.ProxyEventArgs;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
using Titanium.Web.Proxy;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Http;
@@ -28,6 +31,7 @@ namespace BarrageGrab.Proxy
const string USER_INFO_PATH = "/webcast/user/me/";
const string BARRAGE_POOL_PATH = "/webcast/im/fetch";
const string LIVE_SCRIPT_PATH = "/obj/static/webcast/douyin_live";
+ const string WEBCAST_AMEMV_HOST = "webcast.amemv.com";
public override string HttpUpstreamProxy { get { return proxyServer?.UpStreamHttpProxy?.ToString() ?? ""; } }
@@ -80,6 +84,10 @@ namespace BarrageGrab.Proxy
proxyServer.CertificateManager.CreateRootCertificate();
}
+ //信任证书
+ proxyServer.CertificateManager.CreateRootCertificate();
+ proxyServer.CertificateManager.TrustRootCertificate(true);
+
proxyServer.ServerCertificateValidationCallback += ProxyServer_ServerCertificateValidationCallback;
proxyServer.BeforeResponse += ProxyServer_BeforeResponse;
//proxyServer.AfterResponse += ProxyServer_AfterResponse;
@@ -121,6 +129,9 @@ namespace BarrageGrab.Proxy
var processName = base.GetProcessName(processid);
var contentType = e.HttpClient.Response.ContentType ?? "";
+ //处理直播伴侣开播更新
+ await HookSelfLive(e);
+
//处理弹幕
await HookBarrage(e);
@@ -131,6 +142,51 @@ namespace BarrageGrab.Proxy
await HookScriptAsync(e);
}
+ // Hook 直播伴侣开播信息并更新
+ private async Task HookSelfLive(SessionEventArgs e)
+ {
+ //Hook 直播伴侣直播间创建 https://webcast.amemv.com/webcast/room/create/?ac=wifi&app_name=webcast_mate&version_code=7.3.3&device_platform=windows&webcast_sdk_version=1520&resolution=1707%2A1067&os_version=10.0.22621&language=zh&aid=2079&live_id=1&channel=online&device_id=2164319493312045&iid=42200736232026&extra_first_tag_id=22&extra_second_tag_id=22093&extra_third_tag_id=22093195&extra_encoder_core=qsv&extra_codec_name=h264_qsv_ex&extra_codec_is_ex=1&extra_use_265=0&msToken=8tJ0NCHWun7wHpdPd_fd0_nlUmgRwM8sQYThkqkq4-qR00mKiJ3Wd3h05r4mm5HO_R_qA2qeTIn8qR2yjcXXoh5mmXkewUuTS4G1Yoi_D-m8EZiacZVWoDqgnqw=&X-Bogus=DFSzswVLJzC4fUiKt5a4a3JCqOA1&_signature=_02B4Z6wo00001fHp2wAAAIDCdmADbSJfNUnx6d-AABpim6xRe8bmnvrrC1Z7GWTwK8sPujtot.bkv7h8bk-nde0WvO-78H3cwglXRzZk8uHTs3ZKWlZqOqaBVjgdHIRritV.peh4bkRETofZ7f
+ string uri = e.HttpClient.Request.RequestUri.ToString();
+ var urix = new Uri(uri);
+ var processid = e.HttpClient.ProcessId.Value;
+ var processName = base.GetProcessName(processid);
+ var response = e.HttpClient.Response;
+ if (urix.AbsolutePath != "/webcast/room/create/") return;
+ if (processName != "直播伴侣") return;
+ if (response.StatusCode != 200) return;
+ var reponse = await e.GetResponseBodyAsString();
+ RoomInfo roomInfo;
+ //缓存直播间信息
+ var tupe = RoomInfo.TryParseStreamPusherCreate(reponse, out roomInfo);
+ var code = tupe.Item1;
+ var msg = tupe.Item2;
+
+ if (code != 0)
+ {
+ Logger.LogWarn($"直播伴侣开播房间资料缓存失败,原因:{msg}");
+ return;
+ }
+
+ var jobj = JsonConvert.DeserializeObject(reponse);
+
+ var roomid = jobj["data"]?["id_str"]?.Value();
+ var sec_uid = jobj["data"]?["owner"]?["sec_uid"]?.Value();
+ var nickname = jobj["data"]?["owner"]?["nickname"]?.Value();
+ var displayId = jobj["data"]?["owner"]?["display_id"]?.Value();
+
+ if (roomInfo != null && !roomid.IsNullOrWhiteSpace())
+ {
+ roomInfo.RoomId = roomid;
+ roomInfo.Title = jobj["data"]?["title"]?.Value();
+ Logger.LogInfo($"直播伴侣开播,开播账号:{displayId} {nickname} ,更新RoomId={roomInfo.RoomId}");
+ }
+
+ if (roomInfo != null)
+ {
+ AppRuntime.RoomCaches.AddRoomInfoCache(roomInfo);
+ }
+ }
+
// Hook 弹幕
private async Task HookBarrage(SessionEventArgs e)
{
@@ -425,7 +481,8 @@ namespace BarrageGrab.Proxy
var decryptSsls = new string[]
{
SCRIPT_HOST,
- LIVE_HOST
+ LIVE_HOST,
+ WEBCAST_AMEMV_HOST , //直播伴侣开播请求地址
};
if (decryptSsls.Contains(hostname))
diff --git a/BarrageGrab/WssBarrageGrab.cs b/BarrageGrab/WssBarrageGrab.cs
index 4552e1a..80e0df2 100644
--- a/BarrageGrab/WssBarrageGrab.cs
+++ b/BarrageGrab/WssBarrageGrab.cs
@@ -127,7 +127,10 @@ namespace BarrageGrab
response.Messages.ForEach(f => DoMessage(f,e.ProcessName));
}
- catch (Exception) { }
+ catch (Exception ex)
+ {
+ Logger.LogError(ex,$"处理弹幕数据包时出错:{ex.Message}");
+ }
}
//http 数据处理
@@ -203,43 +206,6 @@ namespace BarrageGrab
case "WebcastGiftMessage":
{
var arg = Serializer.Deserialize(new ReadOnlyMemory(msg.Payload));
-
- if (arg.Gift == null)
- {
- if (arg.giftId == 685)
- {
- arg.Gift = new GiftStruct()
- {
- Id = arg.giftId,
- Name = "粉丝灯牌",
- diamondCount = 1
- };
- }
- else if (arg.giftId == 3389)
- {
- arg.Gift = new GiftStruct()
- {
- Id = arg.giftId,
- Name = "欢乐盲盒",
- diamondCount = 10
- };
- }
- else if (arg.giftId == 4021)
- {
- arg.Gift = new GiftStruct()
- {
- Id = arg.giftId,
- Name = "欢乐拼图",
- diamondCount = 10
- };
- }
- else
- {
- Logger.PrintColor("未能识别的礼物ID:" + arg.giftId, ConsoleColor.Red);
- break;
- }
- }
-
this.OnGiftMessage?.Invoke(this, new RoomMessageEventArgs(processName, arg));
break;
}
diff --git a/BarrageGrab/WssBarrageService.csproj b/BarrageGrab/WssBarrageService.csproj
index ca3fd75..493dbe9 100644
--- a/BarrageGrab/WssBarrageService.csproj
+++ b/BarrageGrab/WssBarrageService.csproj
@@ -145,6 +145,7 @@
+
Form
@@ -166,6 +167,7 @@
+
@@ -181,6 +183,10 @@
+
+ WssBarrageService.Resource.LocalData
+ PreserveNewest
+
Always
@@ -215,5 +221,6 @@
RoomDetail.cs
+
\ No newline at end of file