fix: 修复直播间状态检测的多项bug - 状态值扩展为1或2,API异常时用页面HTML兜底,页面解析增加转义清理,前端移除选中阻断自动刷新
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useViewport } from "@/composables/useViewport";
|
import { useViewport } from "@/composables/useViewport";
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ function shouldAutoRefreshRooms() {
|
|||||||
!recordDialogVisible.value &&
|
!recordDialogVisible.value &&
|
||||||
!settingsDialogVisible.value &&
|
!settingsDialogVisible.value &&
|
||||||
!deleteDialogVisible.value &&
|
!deleteDialogVisible.value &&
|
||||||
selectedRooms.value.length === 0 &&
|
|
||||||
!submitLoading.value &&
|
!submitLoading.value &&
|
||||||
!importLoading.value &&
|
!importLoading.value &&
|
||||||
!exportLoading.value &&
|
!exportLoading.value &&
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
|
import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { ElMessage, ElNotification } from "element-plus";
|
import { ElMessage, ElNotification } from "element-plus";
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public sealed class DouyinHttpClient
|
|||||||
RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
|
||||||
private static readonly Regex HtmlStatusRegex = new(
|
private static readonly Regex HtmlStatusRegex = new(
|
||||||
"\"roomStore\":{[\\s\\S]*?\"roomInfo\":{[\\s\\S]*?\"room\":{[\\s\\S]*?\"status\":(?<status>\\d+)",
|
"\"roomStore\":{[\\s\\S]*?\"roomInfo\":{[\\s\\S]*?\"room\":{[\\s\\S]*?\"status\":\"?(?<status>\\d+)\"?",
|
||||||
RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
|
||||||
private readonly PlatformHttpClientFactory _platformHttpClientFactory;
|
private readonly PlatformHttpClientFactory _platformHttpClientFactory;
|
||||||
@@ -141,6 +141,8 @@ public sealed class DouyinHttpClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normalized = EscapedQuoteRegex.Replace(normalized, "\"");
|
||||||
|
|
||||||
var match = HtmlStatusRegex.Match(normalized);
|
var match = HtmlStatusRegex.Match(normalized);
|
||||||
if (match.Success && int.TryParse(match.Groups["status"].Value, out var status))
|
if (match.Success && int.TryParse(match.Groups["status"].Value, out var status))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -89,31 +89,36 @@ public sealed class DouyinLivePlatformAdapter : ILivePlatformAdapter
|
|||||||
|
|
||||||
public async Task<LiveStatusSnapshot> GetLiveStatusAsync(string roomId, CancellationToken cancellationToken = default)
|
public async Task<LiveStatusSnapshot> GetLiveStatusAsync(string roomId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
using var document = await _douyinHttpClient.GetRoomEnterAsync(roomId, cancellationToken);
|
try
|
||||||
var room = GetRoomNode(document.RootElement);
|
|
||||||
|
|
||||||
var statusCode = GetInt(room, "status") ?? GetInt(room, "live_status");
|
|
||||||
var (anchorMatch, titleMatch) = TryExtractAnchorAndTitleFromHtml(document.RootElement);
|
|
||||||
var title = titleMatch ?? GetString(room, "title");
|
|
||||||
var anchorName = anchorMatch ?? GetNestedString(room, "owner", "nickname")
|
|
||||||
?? GetNestedString(room, "anchor", "nickname")
|
|
||||||
?? GetNestedString(room, "user", "nickname");
|
|
||||||
var anchorId = GetAnchorId(room);
|
|
||||||
var avatarUrl = GetAvatarUrl(room);
|
|
||||||
var coverUrl = GetCoverUrl(room);
|
|
||||||
|
|
||||||
var isLive = statusCode == 2 || GetInt(room, "live_status") is 1 or 2;
|
|
||||||
if (!isLive)
|
|
||||||
{
|
{
|
||||||
|
using var document = await _douyinHttpClient.GetRoomEnterAsync(roomId, cancellationToken);
|
||||||
|
var room = GetRoomNode(document.RootElement);
|
||||||
|
|
||||||
|
var statusCode = GetInt(room, "status") ?? GetInt(room, "live_status");
|
||||||
|
var (anchorMatch, titleMatch) = TryExtractAnchorAndTitleFromHtml(document.RootElement);
|
||||||
|
var title = titleMatch ?? GetString(room, "title");
|
||||||
|
var anchorName = anchorMatch ?? GetNestedString(room, "owner", "nickname")
|
||||||
|
?? GetNestedString(room, "anchor", "nickname")
|
||||||
|
?? GetNestedString(room, "user", "nickname");
|
||||||
|
var anchorId = GetAnchorId(room);
|
||||||
|
var avatarUrl = GetAvatarUrl(room);
|
||||||
|
var coverUrl = GetCoverUrl(room);
|
||||||
|
|
||||||
|
var isLive = statusCode is 1 or 2 || GetInt(room, "live_status") is 1 or 2;
|
||||||
var pageStatus = await TryDetectLiveStatusFromPageAsync(roomId, cancellationToken);
|
var pageStatus = await TryDetectLiveStatusFromPageAsync(roomId, cancellationToken);
|
||||||
if (pageStatus is 1 or 2)
|
if (pageStatus is 1 or 2)
|
||||||
{
|
{
|
||||||
isLive = true;
|
isLive = true;
|
||||||
statusCode ??= pageStatus;
|
statusCode ??= pageStatus;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return new LiveStatusSnapshot(isLive, title, anchorName, anchorId, avatarUrl, coverUrl, statusCode, statusCode?.ToString());
|
return new LiveStatusSnapshot(isLive, title, anchorName, anchorId, avatarUrl, coverUrl, statusCode, statusCode?.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
var pageStatus = await TryDetectLiveStatusFromPageAsync(roomId, cancellationToken);
|
||||||
|
return new LiveStatusSnapshot(pageStatus is 1 or 2, null, null, null, null, null, pageStatus, pageStatus?.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<int?> TryDetectLiveStatusFromPageAsync(string roomId, CancellationToken cancellationToken)
|
private async Task<int?> TryDetectLiveStatusFromPageAsync(string roomId, CancellationToken cancellationToken)
|
||||||
|
|||||||
Reference in New Issue
Block a user