add web-fetcher

This commit is contained in:
2024-02-28 16:28:21 +08:00
parent 40fdc93fec
commit f1c06deffd
18 changed files with 527 additions and 84 deletions

View File

@@ -159,6 +159,7 @@ interface DanmakuEventsMap {
gift: (arg1: GiftInfo, arg2?: any) => void
sc: (arg1: SCInfo, arg2?: any) => void
guard: (arg1: GuardInfo, arg2?: any) => void
all: (arg1: any) => void
}
export default class DanmakuClient {
@@ -167,54 +168,83 @@ export default class DanmakuClient {
}
private client: any
private authInfo: AuthInfo | null
private timer: any | undefined
private isStarting = false
public authInfo: AuthInfo | null
public roomAuthInfo = ref<RoomAuthInfo>({} as RoomAuthInfo)
public authCode: string | undefined
public isRunning: boolean = false
private events: {
danmaku: ((arg1: DanmakuInfo, arg2?: any) => void)[]
gift: ((arg1: GiftInfo, arg2?: any) => void)[]
sc: ((arg1: SCInfo, arg2?: any) => void)[]
guard: ((arg1: GuardInfo, arg2?: any) => void)[]
all: ((arg1: any) => void)[]
} = {
danmaku: [],
gift: [],
sc: [],
guard: [],
all: [],
}
private eventsAsModel: {
danmaku: ((arg1: EventModel, arg2?: any) => void)[]
gift: ((arg1: EventModel, arg2?: any) => void)[]
sc: ((arg1: EventModel, arg2?: any) => void)[]
guard: ((arg1: EventModel, arg2?: any) => void)[]
all: ((arg1: any) => void)[]
} = {
danmaku: [],
gift: [],
sc: [],
guard: [],
all: [],
}
public async Start(): Promise<{ success: boolean; message: string }> {
if (!this.client) {
console.log('[OPEN-LIVE] 正在启动弹幕客户端')
const result = await this.initClient()
if (result.success) {
this.timer = setInterval(() => {
this.sendHeartbeat()
}, 20 * 1000)
}
return result
} else {
console.warn('[OPEN-LIVE] 弹幕客户端已被启动过')
if (this.isRunning) {
return {
success: false,
message: '弹幕客户端已启动',
message: '弹幕客户端已启动',
}
}
if (this.isStarting) {
return {
success: false,
message: '弹幕客户端正在启动',
}
}
this.isStarting = true
try {
if (!this.client) {
console.log('[OPEN-LIVE] 正在启动弹幕客户端')
const result = await this.initClient()
if (result.success) {
this.isRunning = true
this.timer ??= setInterval(() => {
this.sendHeartbeat()
}, 20 * 1000)
}
return result
} else {
console.warn('[OPEN-LIVE] 弹幕客户端已被启动过')
return {
success: false,
message: '弹幕客户端已被启动过',
}
}
} finally {
this.isStarting = false
}
}
public Stop() {
if (!this.isRunning) {
return
}
this.isRunning = false
if (this.client) {
console.log('[OPEN-LIVE] 正在停止弹幕客户端')
this.client.stop()
@@ -223,35 +253,51 @@ export default class DanmakuClient {
}
if (this.timer) {
clearInterval(this.timer)
this.timer = undefined
}
this.events = {
danmaku: [],
gift: [],
sc: [],
guard: [],
all: [],
}
this.eventsAsModel = {
danmaku: [],
gift: [],
sc: [],
guard: [],
all: [],
}
}
private sendHeartbeat() {
if (this.client) {
const query = this.authInfo
? QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat', this.authInfo)
: QueryGetAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat-internal')
query.then((data) => {
if (data.code != 200) {
console.error('[OPEN-LIVE] 心跳失败')
this.client.stop()
this.client = null
this.initClient()
}
})
if (!this.isRunning) {
clearInterval(this.timer)
this.timer = undefined
return
}
const query = this.authInfo
? QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat', this.authInfo)
: QueryGetAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat-internal')
query.then((data) => {
if (data.code != 200) {
console.error('[OPEN-LIVE] 心跳失败, 将重新连接')
this.client?.stop()
this.client = null
this.initClient()
}
})
}
private onRawMessage = (command: any) => {
this.eventsAsModel.all?.forEach((d) => {
d(command)
})
this.events.all?.forEach((d) => {
d(command)
})
}
private onDanmaku = (command: any) => {
const data = command.data as DanmakuInfo
@@ -378,7 +424,8 @@ export default class DanmakuClient {
public onEvent(eventName: 'gift', listener: (arg1: EventModel, arg2?: any) => void): this
public onEvent(eventName: 'sc', listener: (arg1: EventModel, arg2?: any) => void): this
public onEvent(eventName: 'guard', listener: (arg1: EventModel, arg2?: any) => void): this
public onEvent(eventName: 'danmaku' | 'gift' | 'sc' | 'guard', listener: (...args: any[]) => void): this {
public onEvent(eventName: 'all', listener: (arg1: any) => void): this
public onEvent(eventName: 'danmaku' | 'gift' | 'sc' | 'guard' | 'all', listener: (...args: any[]) => void): this {
if (!this.eventsAsModel[eventName]) {
this.eventsAsModel[eventName] = []
}
@@ -418,7 +465,7 @@ export default class DanmakuClient {
message: '',
}
} else {
console.log('[OPEN-LIVE] 无法开启场次')
console.log('[OPEN-LIVE] 无法开启场次: ' + auth.message)
return {
success: false,
message: auth.message,
@@ -456,5 +503,6 @@ export default class DanmakuClient {
LIVE_OPEN_PLATFORM_SEND_GIFT: this.onGift.bind(this),
LIVE_OPEN_PLATFORM_SUPER_CHAT: this.onSC.bind(this),
LIVE_OPEN_PLATFORM_GUARD: this.onGuard.bind(this),
RAW_MESSAGE: this.onRawMessage.bind(this),
}
}

View File

@@ -134,6 +134,13 @@ export default class ChatClientDirectOpenLive extends ChatClientOfficialBase {
}
this.onDelSuperChat({ ids })
}
rawMessageCallback(command) {
if (!this.onRawMessage) {
return
}
this.onRawMessage(command)
}
}
const CMD_CALLBACK_MAP = {
@@ -142,4 +149,5 @@ const CMD_CALLBACK_MAP = {
LIVE_OPEN_PLATFORM_GUARD: ChatClientDirectOpenLive.prototype.guardCallback,
LIVE_OPEN_PLATFORM_SUPER_CHAT: ChatClientDirectOpenLive.prototype.superChatCallback,
LIVE_OPEN_PLATFORM_SUPER_CHAT_DEL: ChatClientDirectOpenLive.prototype.superChatDelCallback,
RAW_MESSAGE: ChatClientDirectOpenLive.prototype.rawMessageCallback,
}

View File

@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
// @ts-nocheck
import { BrotliDecode } from './brotli_decode'
import { setInterval, clearInterval, setTimeout, clearTimeout } from 'worker-timers'
@@ -145,7 +147,7 @@ export default class ChatClientOfficialBase {
this.sendAuth()
this.heartbeatTimerId = setInterval(this.sendHeartbeat.bind(this), HEARTBEAT_INTERVAL)
this.refreshReceiveTimeoutTimer()
console.log('ws 已连接')
//console.log('ws 已连接')
}
sendHeartbeat() {
@@ -270,7 +272,10 @@ export default class ChatClientOfficialBase {
// 没压缩过的直接反序列化
if (body.length !== 0) {
try {
body = JSON.parse(textDecoder.decode(body))
const text = textDecoder.decode(body)
this.onRawMessage(text)
this.CMD_CALLBACK_MAP['RAW_MESSAGE']?.call(this, text)
body = JSON.parse(text)
this.handlerCommand(body)
} catch (e) {
console.error('body=', body)
@@ -299,6 +304,7 @@ export default class ChatClientOfficialBase {
}
}
}
onRawMessage(command) {}
handlerCommand(command) {
let cmd = command.cmd || ''

View File

@@ -2,8 +2,8 @@ import DefaultIndexTemplateVue from '@/views/view/indexTemplate/DefaultIndexTemp
import { defineAsyncComponent, ref } from 'vue'
const debugAPI = import.meta.env.VITE_DEBUG_API
const releseAPI = `https://vtsuru.suki.club/api/`
const failoverAPI = `https://failover-api.vtsuru.suki.club/api/`
const releseAPI = `https://vtsuru.suki.club/`
const failoverAPI = `https://failover-api.vtsuru.suki.club/`
export const isBackendUsable = ref(true)
@@ -13,32 +13,38 @@ export const IMGUR_URL = FILE_BASE_URL + '/imgur/'
export const THINGS_URL = FILE_BASE_URL + '/things/'
export const apiFail = ref(false)
export const BASE_API = () =>
process.env.NODE_ENV === 'development' ? debugAPI : apiFail.value ? failoverAPI : releseAPI
export const BASE_API = {
toString: () =>
(process.env.NODE_ENV === 'development' ? debugAPI : apiFail.value ? failoverAPI : releseAPI) + 'api/',
}
export const FETCH_API = 'https://fetch.vtsuru.live/'
export const BASE_HUB_URL = {
toString: () =>
(process.env.NODE_ENV === 'development' ? debugAPI : apiFail.value ? failoverAPI : releseAPI) + 'hub/',
}
export const TURNSTILE_KEY = '0x4AAAAAAAETUSAKbds019h0'
export const USER_API_URL = { toString: () => `${BASE_API()}user/` }
export const ACCOUNT_API_URL = { toString: () => `${BASE_API()}account/` }
export const BILI_API_URL = { toString: () => `${BASE_API()}bili/` }
export const SONG_API_URL = { toString: () => `${BASE_API()}song-list/` }
export const NOTIFACTION_API_URL = { toString: () => `${BASE_API()}notifaction/` }
export const QUESTION_API_URL = { toString: () => `${BASE_API()}qa/` }
export const LOTTERY_API_URL = { toString: () => `${BASE_API()}lottery/` }
export const HISTORY_API_URL = { toString: () => `${BASE_API()}history/` }
export const SCHEDULE_API_URL = { toString: () => `${BASE_API()}schedule/` }
export const VIDEO_COLLECT_API_URL = { toString: () => `${BASE_API()}video-collect/` }
export const OPEN_LIVE_API_URL = { toString: () => `${BASE_API()}open-live/` }
export const SONG_REQUEST_API_URL = { toString: () => `${BASE_API()}song-request/` }
export const QUEUE_API_URL = { toString: () => `${BASE_API()}queue/` }
export const EVENT_API_URL = { toString: () => `${BASE_API()}event/` }
export const LIVE_API_URL = { toString: () => `${BASE_API()}live/` }
export const FEEDBACK_API_URL = { toString: () => `${BASE_API()}feedback/` }
export const MUSIC_REQUEST_API_URL = { toString: () => `${BASE_API()}music-request/` }
export const VTSURU_API_URL = { toString: () => `${BASE_API()}vtsuru/` }
export const POINT_API_URL = { toString: () => `${BASE_API()}point/` }
export const BILI_AUTH_API_URL = { toString: () => `${BASE_API()}bili-auth/` }
export const USER_API_URL = { toString: () => `${BASE_API}user/` }
export const ACCOUNT_API_URL = { toString: () => `${BASE_API}account/` }
export const BILI_API_URL = { toString: () => `${BASE_API}bili/` }
export const SONG_API_URL = { toString: () => `${BASE_API}song-list/` }
export const NOTIFACTION_API_URL = { toString: () => `${BASE_API}notifaction/` }
export const QUESTION_API_URL = { toString: () => `${BASE_API}qa/` }
export const LOTTERY_API_URL = { toString: () => `${BASE_API}lottery/` }
export const HISTORY_API_URL = { toString: () => `${BASE_API}history/` }
export const SCHEDULE_API_URL = { toString: () => `${BASE_API}schedule/` }
export const VIDEO_COLLECT_API_URL = { toString: () => `${BASE_API}video-collect/` }
export const OPEN_LIVE_API_URL = { toString: () => `${BASE_API}open-live/` }
export const SONG_REQUEST_API_URL = { toString: () => `${BASE_API}song-request/` }
export const QUEUE_API_URL = { toString: () => `${BASE_API}queue/` }
export const EVENT_API_URL = { toString: () => `${BASE_API}event/` }
export const LIVE_API_URL = { toString: () => `${BASE_API}live/` }
export const FEEDBACK_API_URL = { toString: () => `${BASE_API}feedback/` }
export const MUSIC_REQUEST_API_URL = { toString: () => `${BASE_API}music-request/` }
export const VTSURU_API_URL = { toString: () => `${BASE_API}vtsuru/` }
export const POINT_API_URL = { toString: () => `${BASE_API}point/` }
export const BILI_AUTH_API_URL = { toString: () => `${BASE_API}bili-auth/` }
export const ScheduleTemplateMap = {
'': {