import { monkey } from '@/core/ajax' import { useScopedConsole } from '@/core/utils/log' const logger = useScopedConsole('表情包下载') interface DownloadPromise { pkg_name: string // 表情包名称 emoticons: { emoji: string; blob: Promise }[] } export class Emoticons { private async getEmoticonsByRoomId(roomId: string) { const response = await this.apiRequest( `https://api.live.bilibili.com/xlive/web-ucenter/v2/emoticon/GetEmoticons?platform=pc&room_id=${roomId}`, ) return response } async downloadEmoticons(emoticonsArray) { const downloadPromises: DownloadPromise[] = emoticonsArray.map(obj => { const emoticons = obj.emoticons.map(item => { try { const blob = this.getImageBlob(item.url) return { emoji: item.emoji, blob, } } catch (error) { logger.error(`下载表情 ${item.emoji} 失败:`, error) return null } }) return { emoticons, pkg_name: obj.pkg_name, } }) return downloadPromises } async getEmoticonsArray(roomId: string): Promise> { try { let response = await this.getEmoticonsByRoomId(roomId) if (response.data.data.length === 0) { logger.log('获取表情包失败,尝试获取真实roomId') const realRoomId = await this.getRealRoomId(roomId) response = await this.getEmoticonsByRoomId(realRoomId) } return response.data.data.slice(2) } catch (error) { throw new Error('获取表情包失败') } } async batchDownload(tasks: DownloadPromise[]) { const results: any[] = [] for (const task of tasks) { const promise = (async () => { const blobs: Blob[] = [] const blobPromises = task.emoticons.map(e => e.blob) for (const blobPromise of blobPromises) { const blob = await blobPromise blobs.push(blob) } return { pkg_name: task.pkg_name, emoticons: task.emoticons.map((e, i) => ({ emoji: e.emoji, blob: blobs[i] })), } })() results.push(promise) } return Promise.all(results) } // 有的直播间id是超短id,需要获取到原始的roomid才能通过api获取到表情包 async getRealRoomId(rid: string): Promise { try { const response = await this.apiRequest( `https://api.live.bilibili.com/room/v1/Room/get_info?room_id=${rid}`, ) if (Object.keys(response.data).length === 0) { throw new Error('获取直播间id失败') } return response.data.room_id } catch (error) { throw new Error('获取直播间id失败') } } apiRequest = (url: string): Promise => { const details: MonkeyXhrBasicDetails = { url, method: 'GET', responseType: 'json', } return monkey(details) } getImageBlob = async (url: string) => { const details: MonkeyXhrBasicDetails = { url, method: 'GET', responseType: 'blob', } return monkey(details) } }