mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Merge pull request #5176 from pencilqaq/preview-features
feat(components): 添加下载up主专属表情包功能
This commit is contained in:
commit
373fd29b02
64
registry/lib/components/utils/download-emoticons/Widget.vue
Normal file
64
registry/lib/components/utils/download-emoticons/Widget.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<DefaultWidget
|
||||
:disabled="downloading"
|
||||
name="下载up主表情包"
|
||||
icon="mdi-emoticon-outline"
|
||||
@click="download()"
|
||||
></DefaultWidget>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { DefaultWidget } from '@/ui'
|
||||
import { logError } from '@/core/utils/log'
|
||||
import { Emoticons } from './emoticons'
|
||||
import { DownloadPackage } from '@/core/download'
|
||||
import { Toast } from '@/core/toast'
|
||||
|
||||
const downloader = new Emoticons()
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
DefaultWidget,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
downloading: false,
|
||||
midRegex: /mid=(\d+)/,
|
||||
roomIdRegex: /^https:\/\/live\.bilibili\.com\/(\d+)(?:\?.*)?$/,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async download() {
|
||||
this.downloading = true
|
||||
try {
|
||||
const url = window.location.href
|
||||
if (url.startsWith('https://live.bilibili.com/')) {
|
||||
const rid = this.roomIdRegex.exec(url)[1]
|
||||
const emoticonsArray = await downloader.getEmoticonsArray(rid)
|
||||
if (emoticonsArray.length === 0) {
|
||||
Toast.info('该up主没有专属表情包', '表情包下载')
|
||||
return
|
||||
}
|
||||
const downloadPromises = await downloader.downloadEmoticons(emoticonsArray)
|
||||
const results = await downloader.batchDownload(downloadPromises)
|
||||
const dpackage = new DownloadPackage()
|
||||
dpackage.noEscape = true
|
||||
for (const result of results) {
|
||||
if (result !== null) {
|
||||
for (const emoticon of result.emoticons) {
|
||||
dpackage.add(`${result.pkg_name}/${emoticon.emoji}.png`, emoticon.blob)
|
||||
}
|
||||
}
|
||||
}
|
||||
await dpackage.emit(`emoticons-${rid}.zip`)
|
||||
}
|
||||
} catch (error) {
|
||||
Toast.error('下载失败详情查看控制台', '表情包下载')
|
||||
logError(error)
|
||||
} finally {
|
||||
this.downloading = false
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
106
registry/lib/components/utils/download-emoticons/emoticons.ts
Normal file
106
registry/lib/components/utils/download-emoticons/emoticons.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import { monkey } from '@/core/ajax'
|
||||
import { useScopedConsole } from '@/core/utils/log'
|
||||
|
||||
const logger = useScopedConsole('表情包下载')
|
||||
|
||||
interface DownloadPromise {
|
||||
pkg_name: string // 表情包名称
|
||||
emoticons: { emoji: string; blob: Promise<Blob> }[]
|
||||
}
|
||||
|
||||
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<Array<any>> {
|
||||
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<string> {
|
||||
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<any> => {
|
||||
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<Blob>(details)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
## 下载up主专属表情包
|
||||
|
||||
支持下载up主专属表情包,处于任意直播间页面时,下载按钮会在`功能`面板显示,以压缩包形式保存。
|
||||
16
registry/lib/components/utils/download-emoticons/index.ts
Normal file
16
registry/lib/components/utils/download-emoticons/index.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { defineComponentMetadata } from '@/components/define'
|
||||
|
||||
export const component = defineComponentMetadata({
|
||||
name: 'downloadEmoticons',
|
||||
displayName: '下载表情',
|
||||
tags: [componentsTags.utils, componentsTags.live],
|
||||
entry: none,
|
||||
author: {
|
||||
name: 'Pencilqaq',
|
||||
link: 'https://github.com/pencilqaq',
|
||||
},
|
||||
widget: {
|
||||
component: () => import('./Widget.vue').then(m => m.default),
|
||||
},
|
||||
urlInclude: [/^https:\/\/live\.bilibili\.com\/(\d+)/],
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user