mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
add stream lottery
This commit is contained in:
5
default.d.ts
vendored
5
default.d.ts
vendored
@@ -5,3 +5,8 @@ declare module 'vue3-aplayer' {
|
|||||||
declare module 'file-saver' {
|
declare module 'file-saver' {
|
||||||
export function saveAs(blob: Blob | null | undefined, fileName: string): void
|
export function saveAs(blob: Blob | null | undefined, fileName: string): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.js' {
|
||||||
|
const content: any
|
||||||
|
export = content
|
||||||
|
}
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
"naive-ui": "^2.34.3",
|
"naive-ui": "^2.34.3",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"stylus": "^0.55.0",
|
"stylus": "^0.55.0",
|
||||||
"typescript": "~4.5.5"
|
"typescript": "~4.5.5",
|
||||||
|
"vite-plugin-mkcert": "^1.16.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,3 +207,24 @@ export interface VideoCollectDetail {
|
|||||||
table: VideoCollectTable
|
table: VideoCollectTable
|
||||||
videos: { info: VideoInfo; video: VideoCollectVideo }[]
|
videos: { info: VideoInfo; video: VideoCollectVideo }[]
|
||||||
}
|
}
|
||||||
|
export interface GameInfo {
|
||||||
|
game_id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebsocketInfo {
|
||||||
|
auth_body: string
|
||||||
|
wss_link: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AnchorInfo {
|
||||||
|
room_id: number
|
||||||
|
uname: string
|
||||||
|
uface: string
|
||||||
|
uid: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OpenLiveInfo {
|
||||||
|
game_info: GameInfo
|
||||||
|
websocket_info: WebsocketInfo
|
||||||
|
anchor_info: AnchorInfo
|
||||||
|
}
|
||||||
|
|||||||
147
src/data/chat/ChatClientDirectOpenLive.js
Normal file
147
src/data/chat/ChatClientDirectOpenLive.js
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import * as base from './ChatClientOfficialBase'
|
||||||
|
import ChatClientOfficialBase from './ChatClientOfficialBase'
|
||||||
|
|
||||||
|
|
||||||
|
export default class ChatClientDirectOpenLive extends ChatClientOfficialBase {
|
||||||
|
constructor(authInfo) {
|
||||||
|
super()
|
||||||
|
this.CMD_CALLBACK_MAP = CMD_CALLBACK_MAP
|
||||||
|
|
||||||
|
this.auth = authInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
super.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
async initRoom() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async onBeforeWsConnect() {
|
||||||
|
return super.onBeforeWsConnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
getWsUrl() {
|
||||||
|
return this.auth.websocket_info.wss_link[this.retryCount % this.auth.websocket_info.wss_link.length]
|
||||||
|
}
|
||||||
|
|
||||||
|
sendAuth() {
|
||||||
|
this.websocket.send(this.makePacket(this.auth.websocket_info.auth_body, base.OP_AUTH))
|
||||||
|
}
|
||||||
|
|
||||||
|
async dmCallback(command) {
|
||||||
|
if (!this.onAddText) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let data = command.data
|
||||||
|
|
||||||
|
let authorType
|
||||||
|
if (data.uid === this.roomOwnerUid) {
|
||||||
|
authorType = 3
|
||||||
|
} else if (data.guard_level !== 0) {
|
||||||
|
authorType = 1
|
||||||
|
} else {
|
||||||
|
authorType = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let emoticon = null
|
||||||
|
if (data.dm_type === 1) {
|
||||||
|
emoticon = data.emoji_img_url
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
avatarUrl: chat.processAvatarUrl(data.uface),
|
||||||
|
timestamp: data.timestamp,
|
||||||
|
authorName: data.uname,
|
||||||
|
authorType: authorType,
|
||||||
|
content: data.msg,
|
||||||
|
privilegeType: data.guard_level,
|
||||||
|
isGiftDanmaku: false,
|
||||||
|
authorLevel: 1,
|
||||||
|
isNewbie: false,
|
||||||
|
isMobileVerified: true,
|
||||||
|
medalLevel: data.fans_medal_wearing_status ? data.fans_medal_level : 0,
|
||||||
|
id: data.msg_id,
|
||||||
|
translation: '',
|
||||||
|
emoticon: emoticon,
|
||||||
|
}
|
||||||
|
this.onAddText(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
sendGiftCallback(command) {
|
||||||
|
if (!this.onAddGift) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let data = command.data
|
||||||
|
if (!data.paid) {
|
||||||
|
// 丢人
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
id: data.msg_id,
|
||||||
|
avatarUrl: chat.processAvatarUrl(data.uface),
|
||||||
|
timestamp: data.timestamp,
|
||||||
|
authorName: data.uname,
|
||||||
|
totalCoin: data.price,
|
||||||
|
giftName: data.gift_name,
|
||||||
|
num: data.gift_num,
|
||||||
|
}
|
||||||
|
this.onAddGift(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async guardCallback(command) {
|
||||||
|
if (!this.onAddMember) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = command.data
|
||||||
|
data = {
|
||||||
|
id: data.msg_id,
|
||||||
|
avatarUrl: chat.processAvatarUrl(data.user_info.uface),
|
||||||
|
timestamp: data.timestamp,
|
||||||
|
authorName: data.user_info.uname,
|
||||||
|
privilegeType: data.guard_level,
|
||||||
|
}
|
||||||
|
this.onAddMember(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
superChatCallback(command) {
|
||||||
|
if (!this.onAddSuperChat) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = command.data
|
||||||
|
data = {
|
||||||
|
id: data.message_id.toString(),
|
||||||
|
avatarUrl: chat.processAvatarUrl(data.uface),
|
||||||
|
timestamp: data.start_time,
|
||||||
|
authorName: data.uname,
|
||||||
|
price: data.rmb,
|
||||||
|
content: data.message,
|
||||||
|
translation: '',
|
||||||
|
}
|
||||||
|
this.onAddSuperChat(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
superChatDelCallback(command) {
|
||||||
|
if (!this.onDelSuperChat) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let ids = []
|
||||||
|
for (let id of command.data.message_ids) {
|
||||||
|
ids.push(id.toString())
|
||||||
|
}
|
||||||
|
this.onDelSuperChat({ ids })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CMD_CALLBACK_MAP = {
|
||||||
|
LIVE_OPEN_PLATFORM_DM: ChatClientDirectOpenLive.prototype.dmCallback,
|
||||||
|
LIVE_OPEN_PLATFORM_SEND_GIFT: ChatClientDirectOpenLive.prototype.sendGiftCallback,
|
||||||
|
LIVE_OPEN_PLATFORM_GUARD: ChatClientDirectOpenLive.prototype.guardCallback,
|
||||||
|
LIVE_OPEN_PLATFORM_SUPER_CHAT: ChatClientDirectOpenLive.prototype.superChatCallback,
|
||||||
|
LIVE_OPEN_PLATFORM_SUPER_CHAT_DEL: ChatClientDirectOpenLive.prototype.superChatDelCallback,
|
||||||
|
}
|
||||||
2287
src/data/chat/ChatClientOfficialBase/brotli_decode.js
Normal file
2287
src/data/chat/ChatClientOfficialBase/brotli_decode.js
Normal file
File diff suppressed because one or more lines are too long
312
src/data/chat/ChatClientOfficialBase/index.js
Normal file
312
src/data/chat/ChatClientOfficialBase/index.js
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
import { BrotliDecode } from './brotli_decode'
|
||||||
|
|
||||||
|
const HEADER_SIZE = 16
|
||||||
|
|
||||||
|
export const WS_BODY_PROTOCOL_VERSION_NORMAL = 0
|
||||||
|
export const WS_BODY_PROTOCOL_VERSION_HEARTBEAT = 1
|
||||||
|
export const WS_BODY_PROTOCOL_VERSION_DEFLATE = 2
|
||||||
|
export const WS_BODY_PROTOCOL_VERSION_BROTLI = 3
|
||||||
|
|
||||||
|
export const OP_HANDSHAKE = 0
|
||||||
|
export const OP_HANDSHAKE_REPLY = 1
|
||||||
|
export const OP_HEARTBEAT = 2
|
||||||
|
export const OP_HEARTBEAT_REPLY = 3
|
||||||
|
export const OP_SEND_MSG = 4
|
||||||
|
export const OP_SEND_MSG_REPLY = 5
|
||||||
|
export const OP_DISCONNECT_REPLY = 6
|
||||||
|
export const OP_AUTH = 7
|
||||||
|
export const OP_AUTH_REPLY = 8
|
||||||
|
export const OP_RAW = 9
|
||||||
|
export const OP_PROTO_READY = 10
|
||||||
|
export const OP_PROTO_FINISH = 11
|
||||||
|
export const OP_CHANGE_ROOM = 12
|
||||||
|
export const OP_CHANGE_ROOM_REPLY = 13
|
||||||
|
export const OP_REGISTER = 14
|
||||||
|
export const OP_REGISTER_REPLY = 15
|
||||||
|
export const OP_UNREGISTER = 16
|
||||||
|
export const OP_UNREGISTER_REPLY = 17
|
||||||
|
// B站业务自定义OP
|
||||||
|
// export const MinBusinessOp = 1000
|
||||||
|
// export const MaxBusinessOp = 10000
|
||||||
|
|
||||||
|
export const AUTH_REPLY_CODE_OK = 0
|
||||||
|
export const AUTH_REPLY_CODE_TOKEN_ERROR = -101
|
||||||
|
|
||||||
|
const HEARTBEAT_INTERVAL = 10 * 1000
|
||||||
|
const RECEIVE_TIMEOUT = HEARTBEAT_INTERVAL + 5 * 1000
|
||||||
|
|
||||||
|
let textEncoder = new TextEncoder()
|
||||||
|
let textDecoder = new TextDecoder()
|
||||||
|
|
||||||
|
export default class ChatClientOfficialBase {
|
||||||
|
constructor() {
|
||||||
|
this.CMD_CALLBACK_MAP = {}
|
||||||
|
|
||||||
|
this.onAddText = null
|
||||||
|
this.onAddGift = null
|
||||||
|
this.onAddMember = null
|
||||||
|
this.onAddSuperChat = null
|
||||||
|
this.onDelSuperChat = null
|
||||||
|
this.onUpdateTranslation = null
|
||||||
|
|
||||||
|
this.onFatalError = null
|
||||||
|
|
||||||
|
this.needInitRoom = true
|
||||||
|
this.websocket = null
|
||||||
|
this.retryCount = 0
|
||||||
|
this.isDestroying = false
|
||||||
|
this.heartbeatTimerId = null
|
||||||
|
this.receiveTimeoutTimerId = null
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.wsConnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.isDestroying = true
|
||||||
|
if (this.websocket) {
|
||||||
|
this.websocket.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async initRoom() {
|
||||||
|
throw Error('Not implemented')
|
||||||
|
}
|
||||||
|
|
||||||
|
makePacket(data, operation) {
|
||||||
|
let body
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
body = textEncoder.encode(JSON.stringify(data))
|
||||||
|
} else {
|
||||||
|
// string
|
||||||
|
body = textEncoder.encode(data)
|
||||||
|
}
|
||||||
|
let header = new ArrayBuffer(HEADER_SIZE)
|
||||||
|
let headerView = new DataView(header)
|
||||||
|
headerView.setUint32(0, HEADER_SIZE + body.byteLength) // pack_len
|
||||||
|
headerView.setUint16(4, HEADER_SIZE) // raw_header_size
|
||||||
|
headerView.setUint16(6, 1) // ver
|
||||||
|
headerView.setUint32(8, operation) // operation
|
||||||
|
headerView.setUint32(12, 1) // seq_id
|
||||||
|
return new Blob([header, body])
|
||||||
|
}
|
||||||
|
|
||||||
|
sendAuth() {
|
||||||
|
throw Error('Not implemented')
|
||||||
|
}
|
||||||
|
|
||||||
|
async wsConnect() {
|
||||||
|
if (this.isDestroying) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.onBeforeWsConnect()
|
||||||
|
if (this.isDestroying) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.websocket = new WebSocket(this.getWsUrl())
|
||||||
|
this.websocket.binaryType = 'arraybuffer'
|
||||||
|
this.websocket.onopen = this.onWsOpen.bind(this)
|
||||||
|
this.websocket.onclose = this.onWsClose.bind(this)
|
||||||
|
this.websocket.onmessage = this.onWsMessage.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async onBeforeWsConnect() {
|
||||||
|
if (!this.needInitRoom) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let res
|
||||||
|
try {
|
||||||
|
res = await this.initRoom()
|
||||||
|
} catch (e) {
|
||||||
|
res = false
|
||||||
|
console.error('initRoom exception:', e)
|
||||||
|
if (this.onFatalError) {
|
||||||
|
this.onFatalError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
this.onWsClose()
|
||||||
|
throw Error('initRoom failed')
|
||||||
|
}
|
||||||
|
this.needInitRoom = false
|
||||||
|
}
|
||||||
|
|
||||||
|
getWsUrl() {
|
||||||
|
throw Error('Not implemented')
|
||||||
|
}
|
||||||
|
|
||||||
|
onWsOpen() {
|
||||||
|
this.sendAuth()
|
||||||
|
this.heartbeatTimerId = window.setInterval(this.sendHeartbeat.bind(this), HEARTBEAT_INTERVAL)
|
||||||
|
this.refreshReceiveTimeoutTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
sendHeartbeat() {
|
||||||
|
this.websocket.send(this.makePacket({}, OP_HEARTBEAT))
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshReceiveTimeoutTimer() {
|
||||||
|
if (this.receiveTimeoutTimerId) {
|
||||||
|
window.clearTimeout(this.receiveTimeoutTimerId)
|
||||||
|
}
|
||||||
|
this.receiveTimeoutTimerId = window.setTimeout(this.onReceiveTimeout.bind(this), RECEIVE_TIMEOUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
onReceiveTimeout() {
|
||||||
|
console.warn('接收消息超时')
|
||||||
|
this.discardWebsocket()
|
||||||
|
}
|
||||||
|
|
||||||
|
discardWebsocket() {
|
||||||
|
if (this.receiveTimeoutTimerId) {
|
||||||
|
window.clearTimeout(this.receiveTimeoutTimerId)
|
||||||
|
this.receiveTimeoutTimerId = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接丢弃阻塞的websocket,不等onclose回调了
|
||||||
|
this.websocket.onopen = this.websocket.onclose = this.websocket.onmessage = null
|
||||||
|
this.websocket.close()
|
||||||
|
this.onWsClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
onWsClose() {
|
||||||
|
this.websocket = null
|
||||||
|
if (this.heartbeatTimerId) {
|
||||||
|
window.clearInterval(this.heartbeatTimerId)
|
||||||
|
this.heartbeatTimerId = null
|
||||||
|
}
|
||||||
|
if (this.receiveTimeoutTimerId) {
|
||||||
|
window.clearTimeout(this.receiveTimeoutTimerId)
|
||||||
|
this.receiveTimeoutTimerId = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isDestroying) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.retryCount++
|
||||||
|
console.warn('掉线重连中', this.retryCount)
|
||||||
|
window.setTimeout(this.wsConnect.bind(this), 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
onWsMessage(event) {
|
||||||
|
if (!(event.data instanceof ArrayBuffer)) {
|
||||||
|
console.warn('未知的websocket消息类型,data=', event.data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = new Uint8Array(event.data)
|
||||||
|
this.parseWsMessage(data)
|
||||||
|
|
||||||
|
// 至少成功处理1条消息
|
||||||
|
this.retryCount = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
parseWsMessage(data) {
|
||||||
|
let offset = 0
|
||||||
|
let dataView = new DataView(data.buffer)
|
||||||
|
let packLen = dataView.getUint32(0)
|
||||||
|
let rawHeaderSize = dataView.getUint16(4)
|
||||||
|
// let ver = dataView.getUint16(6)
|
||||||
|
let operation = dataView.getUint32(8)
|
||||||
|
// let seqId = dataView.getUint32(12)
|
||||||
|
|
||||||
|
switch (operation) {
|
||||||
|
case OP_AUTH_REPLY:
|
||||||
|
case OP_SEND_MSG_REPLY: {
|
||||||
|
// 业务消息,可能有多个包一起发,需要分包
|
||||||
|
while (true) {
|
||||||
|
// eslint-disable-line no-constant-condition
|
||||||
|
let body = new Uint8Array(data.buffer, offset + rawHeaderSize, packLen - rawHeaderSize)
|
||||||
|
this.parseBusinessMessage(dataView, body)
|
||||||
|
|
||||||
|
offset += packLen
|
||||||
|
if (offset >= data.byteLength) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dataView = new DataView(data.buffer, offset)
|
||||||
|
packLen = dataView.getUint32(0)
|
||||||
|
rawHeaderSize = dataView.getUint16(4)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case OP_HEARTBEAT_REPLY: {
|
||||||
|
// 服务器心跳包,包含人气值,这里没用
|
||||||
|
this.refreshReceiveTimeoutTimer()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// 未知消息
|
||||||
|
let body = new Uint8Array(data.buffer, offset + rawHeaderSize, packLen - rawHeaderSize)
|
||||||
|
console.warn('未知包类型,operation=', operation, dataView, body)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseBusinessMessage(dataView, body) {
|
||||||
|
let ver = dataView.getUint16(6)
|
||||||
|
let operation = dataView.getUint32(8)
|
||||||
|
|
||||||
|
switch (operation) {
|
||||||
|
case OP_SEND_MSG_REPLY: {
|
||||||
|
// 业务消息
|
||||||
|
if (ver == WS_BODY_PROTOCOL_VERSION_BROTLI) {
|
||||||
|
// 压缩过的先解压
|
||||||
|
body = BrotliDecode(body)
|
||||||
|
this.parseWsMessage(body)
|
||||||
|
} /*else if (ver == WS_BODY_PROTOCOL_VERSION_DEFLATE) {
|
||||||
|
// web端已经不用zlib压缩了,但是开放平台会用
|
||||||
|
body = inflate(body)
|
||||||
|
this.parseWsMessage(body)
|
||||||
|
}*/ else {
|
||||||
|
// 没压缩过的直接反序列化
|
||||||
|
if (body.length !== 0) {
|
||||||
|
try {
|
||||||
|
body = JSON.parse(textDecoder.decode(body))
|
||||||
|
this.handlerCommand(body)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('body=', body)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case OP_AUTH_REPLY: {
|
||||||
|
// 认证响应
|
||||||
|
body = JSON.parse(textDecoder.decode(body))
|
||||||
|
if (body.code !== AUTH_REPLY_CODE_OK) {
|
||||||
|
console.error('认证响应错误,body=', body)
|
||||||
|
this.needInitRoom = true
|
||||||
|
this.discardWebsocket()
|
||||||
|
throw new Error('认证响应错误')
|
||||||
|
}
|
||||||
|
this.sendHeartbeat()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// 未知消息
|
||||||
|
console.warn('未知包类型,operation=', operation, dataView, body)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handlerCommand(command) {
|
||||||
|
let cmd = command.cmd || ''
|
||||||
|
let pos = cmd.indexOf(':')
|
||||||
|
if (pos != -1) {
|
||||||
|
cmd = cmd.substr(0, pos)
|
||||||
|
}
|
||||||
|
let callback = this.CMD_CALLBACK_MAP[cmd]
|
||||||
|
if (callback) {
|
||||||
|
callback.call(this, command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ export const LOTTERY_API_URL = `${BASE_API}lottery/`
|
|||||||
export const HISTORY_API_URL = `${BASE_API}history/`
|
export const HISTORY_API_URL = `${BASE_API}history/`
|
||||||
export const SCHEDULE_API_URL = `${BASE_API}schedule/`
|
export const SCHEDULE_API_URL = `${BASE_API}schedule/`
|
||||||
export const VIDEO_COLLECT_API_URL = `${BASE_API}video-collect/`
|
export const VIDEO_COLLECT_API_URL = `${BASE_API}video-collect/`
|
||||||
|
export const OPEN_LIVE_API_URL = `${BASE_API}open-live/`
|
||||||
|
|
||||||
export const ScheduleTemplateMap = {
|
export const ScheduleTemplateMap = {
|
||||||
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/DefaultScheduleTemplate.vue')) },
|
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/DefaultScheduleTemplate.vue')) },
|
||||||
|
|||||||
@@ -6,21 +6,33 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
path: '/',
|
path: '/',
|
||||||
name: 'index',
|
name: 'index',
|
||||||
component: IndexView,
|
component: IndexView,
|
||||||
|
meta: {
|
||||||
|
title: '你好',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/verify',
|
path: '/verify',
|
||||||
name: 'verify',
|
name: 'verify',
|
||||||
component: () => import('@/views/VerifyView.vue'),
|
component: () => import('@/views/VerifyView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '认证',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
name: 'about',
|
name: 'about',
|
||||||
component: () => import('@/views/AboutView.vue'),
|
component: () => import('@/views/AboutView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '关于',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/reset-password',
|
path: '/reset-password',
|
||||||
name: 'resetPassword',
|
name: 'resetPassword',
|
||||||
component: () => import('@/views/ChangePasswordView.vue'),
|
component: () => import('@/views/ChangePasswordView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '重置密码',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/video-collect/:id',
|
path: '/video-collect/:id',
|
||||||
@@ -178,6 +190,20 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/open-live',
|
||||||
|
name: 'open-live',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'lottery',
|
||||||
|
name: 'open-live-lottery',
|
||||||
|
component: () => import('@/views/open_live/OpenLottery.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '直播抽奖',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
name: 'notfound',
|
name: 'notfound',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { NCard, NDivider, NGradientText, NSpace, NText, NIcon, NGrid, NGridItem,
|
|||||||
import vtb from '@/svgs/ic_vtuber.svg'
|
import vtb from '@/svgs/ic_vtuber.svg'
|
||||||
import { AnalyticsSharp, Calendar, Chatbox, MusicalNote } from '@vicons/ionicons5'
|
import { AnalyticsSharp, Calendar, Chatbox, MusicalNote } from '@vicons/ionicons5'
|
||||||
import { useWindowSize } from '@vueuse/core'
|
import { useWindowSize } from '@vueuse/core'
|
||||||
import { Lottery24Filled, MoreHorizontal24Filled, VehicleShip24Filled } from '@vicons/fluent'
|
import { Lottery24Filled, MoreHorizontal24Filled, VehicleShip24Filled, VideoAdd20Filled } from '@vicons/fluent'
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
|
|
||||||
@@ -33,10 +33,15 @@ const functions = [
|
|||||||
desc: '从动态评论区抽取评论或者转发的用户',
|
desc: '从动态评论区抽取评论或者转发的用户',
|
||||||
icon: Lottery24Filled,
|
icon: Lottery24Filled,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: '直播抽奖',
|
||||||
|
desc: '从直播间弹幕或礼物抽取用户',
|
||||||
|
icon: Lottery24Filled,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '视频征集',
|
name: '视频征集',
|
||||||
desc: '创建用来收集视频链接的页面, 可以从动态爬取, 也可以提前对视频进行筛选',
|
desc: '创建用来收集视频链接的页面, 可以从动态爬取, 也可以提前对视频进行筛选',
|
||||||
icon: Lottery24Filled,
|
icon: VideoAdd20Filled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '数据跟踪',
|
name: '数据跟踪',
|
||||||
|
|||||||
503
src/views/open_live/OpenLottery.vue
Normal file
503
src/views/open_live/OpenLottery.vue
Normal file
@@ -0,0 +1,503 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, h, onMounted, ref } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { QueryPostAPI } from '@/api/query'
|
||||||
|
import { OPEN_LIVE_API_URL } from '@/data/constants'
|
||||||
|
import { LotteryUserInfo, OpenLiveInfo } from '@/api/api-models'
|
||||||
|
import {
|
||||||
|
NAvatar,
|
||||||
|
NButton,
|
||||||
|
NCard,
|
||||||
|
NCheckbox,
|
||||||
|
NCollapseTransition,
|
||||||
|
NDivider,
|
||||||
|
NEmpty,
|
||||||
|
NGrid,
|
||||||
|
NGridItem,
|
||||||
|
NIcon,
|
||||||
|
NInput,
|
||||||
|
NInputGroup,
|
||||||
|
NInputGroupLabel,
|
||||||
|
NInputNumber,
|
||||||
|
NLayoutContent,
|
||||||
|
NList,
|
||||||
|
NListItem,
|
||||||
|
NModal,
|
||||||
|
NRadioButton,
|
||||||
|
NRadioGroup,
|
||||||
|
NResult,
|
||||||
|
NScrollbar,
|
||||||
|
NSpace,
|
||||||
|
NSpin,
|
||||||
|
NTag,
|
||||||
|
NTime,
|
||||||
|
NTooltip,
|
||||||
|
useMessage,
|
||||||
|
useNotification,
|
||||||
|
} from 'naive-ui'
|
||||||
|
import { useAccount } from '@/api/account'
|
||||||
|
import ChatClientDirectOpenLive from '@/data/chat/ChatClientDirectOpenLive.js'
|
||||||
|
import { useLocalStorage, useStorage } from '@vueuse/core'
|
||||||
|
import { format } from 'date-fns'
|
||||||
|
import { Delete24Filled, Info24Filled } from '@vicons/fluent'
|
||||||
|
|
||||||
|
interface AuthInfo {
|
||||||
|
Timestamp: string
|
||||||
|
Code: string
|
||||||
|
Mid: string
|
||||||
|
Caller: string
|
||||||
|
CodeSign: string
|
||||||
|
}
|
||||||
|
interface OpenLiveLotteryBaseUserInfo {
|
||||||
|
name: string
|
||||||
|
uId: number
|
||||||
|
level?: number
|
||||||
|
avatar: string
|
||||||
|
}
|
||||||
|
interface OpenLiveLotteryUserInfo extends OpenLiveLotteryBaseUserInfo {
|
||||||
|
fans_medal_level: number
|
||||||
|
fans_medal_name: string //粉丝勋章名
|
||||||
|
fans_medal_wearing_status: boolean //该房间粉丝勋章佩戴情况
|
||||||
|
guard_level: number
|
||||||
|
}
|
||||||
|
interface LotteryOption {
|
||||||
|
resultCount: number
|
||||||
|
lotteryType: 'single' | 'half'
|
||||||
|
type: 'danmaku' | 'gift'
|
||||||
|
danmakuFilterType: 'all' | 'contains' | 'regex'
|
||||||
|
danmakuKeyword: string
|
||||||
|
needFanMedal: boolean
|
||||||
|
needWearFanMedal: false
|
||||||
|
needGuard: boolean
|
||||||
|
fanCardLevel?: number
|
||||||
|
giftMinPrice?: number
|
||||||
|
giftName?: string
|
||||||
|
}
|
||||||
|
interface LotteryHistory {
|
||||||
|
users: OpenLiveLotteryBaseUserInfo[]
|
||||||
|
time: number
|
||||||
|
}
|
||||||
|
const CMD_CALLBACK_MAP = {
|
||||||
|
LIVE_OPEN_PLATFORM_DM: onDanmaku,
|
||||||
|
LIVE_OPEN_PLATFORM_SEND_GIFT: onGift,
|
||||||
|
}
|
||||||
|
const defaultOption = {
|
||||||
|
resultCount: 1,
|
||||||
|
type: 'danmaku',
|
||||||
|
lotteryType: 'single',
|
||||||
|
danmakuFilterType: 'all',
|
||||||
|
needFanMedal: false,
|
||||||
|
needWearFanMedal: false,
|
||||||
|
needGuard: false,
|
||||||
|
fanCardLevel: 1,
|
||||||
|
} as LotteryOption
|
||||||
|
const lotteryOption = useLocalStorage('Settings.OpenLive.LotteryOption', defaultOption)
|
||||||
|
const lotteryHistory = useStorage<LotteryHistory[]>('OpenLive.LotteryHistory', [])
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const message = useMessage()
|
||||||
|
const accountInfo = useAccount()
|
||||||
|
const notification = useNotification()
|
||||||
|
|
||||||
|
const authInfo = ref<AuthInfo>()
|
||||||
|
const authResult = ref<OpenLiveInfo | null>(null)
|
||||||
|
|
||||||
|
const originUsers = ref<OpenLiveLotteryUserInfo[]>([])
|
||||||
|
const currentUsers = ref<OpenLiveLotteryUserInfo[]>([])
|
||||||
|
const resultUsers = ref<OpenLiveLotteryUserInfo[]>([])
|
||||||
|
const isStartLottery = ref(false)
|
||||||
|
const isLottering = ref(false)
|
||||||
|
const isLotteried = ref(false)
|
||||||
|
const isConnected = ref(false)
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
let chatClient: any
|
||||||
|
|
||||||
|
async function get() {
|
||||||
|
try {
|
||||||
|
const data = await QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'start', authInfo.value)
|
||||||
|
if (data.code == 200) {
|
||||||
|
console.log('[OPEN-LIVE] 已获取场次信息')
|
||||||
|
return data.data
|
||||||
|
} else {
|
||||||
|
message.error('无法获取场次数据: ' + data.message)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
async function start() {
|
||||||
|
if (!chatClient) {
|
||||||
|
const auth = await get()
|
||||||
|
if (auth) {
|
||||||
|
authResult.value = auth
|
||||||
|
} else {
|
||||||
|
message.error('无法获取场次数据, 请刷新重试')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
initChatClient()
|
||||||
|
isConnected.value = true
|
||||||
|
setInterval(() => {
|
||||||
|
QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat', authInfo.value)
|
||||||
|
}, 20 * 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function initChatClient() {
|
||||||
|
chatClient = new ChatClientDirectOpenLive(authResult.value)
|
||||||
|
|
||||||
|
//chatClient.msgHandler = this;
|
||||||
|
chatClient.CMD_CALLBACK_MAP = CMD_CALLBACK_MAP
|
||||||
|
chatClient.start()
|
||||||
|
console.log('[OPEN-LIVE] 已连接房间: ' + authResult.value?.anchor_info.room_id)
|
||||||
|
}
|
||||||
|
function addUser(user: OpenLiveLotteryUserInfo, danmu: any) {
|
||||||
|
if (originUsers.value.find((u) => u.uId == user.uId)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (isUserValid(user, danmu)) {
|
||||||
|
originUsers.value.push(user)
|
||||||
|
currentUsers.value.push(user)
|
||||||
|
console.log(`[OPEN-LIVE-Lottery] ${user.name} 添加到队列中`)
|
||||||
|
} else {
|
||||||
|
console.log(`[OPEN-LIVE-Lottery] ${user.name} 因不符合条件而被忽略`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isUserValid(u: OpenLiveLotteryUserInfo, danmu: any) {
|
||||||
|
const cmd = danmu.cmd
|
||||||
|
const data = danmu.data
|
||||||
|
if (lotteryOption.value.needWearFanMedal) {
|
||||||
|
if (!u.fans_medal_wearing_status) return false
|
||||||
|
}
|
||||||
|
if (lotteryOption.value.needFanMedal) {
|
||||||
|
if (u.fans_medal_level == 0) return false
|
||||||
|
}
|
||||||
|
if (lotteryOption.value.needGuard) {
|
||||||
|
if (u.guard_level == 0) return false
|
||||||
|
}
|
||||||
|
if (lotteryOption.value.danmakuKeyword && cmd === 'LIVE_OPEN_PLATFORM_DM') {
|
||||||
|
if (lotteryOption.value.danmakuFilterType == 'contains') {
|
||||||
|
if (!data.msg.includes(lotteryOption.value.danmakuKeyword)) return false
|
||||||
|
} else if (lotteryOption.value.danmakuFilterType == 'regex') {
|
||||||
|
if (!data.msg.match(lotteryOption.value.danmakuKeyword)) return false
|
||||||
|
} else {
|
||||||
|
if (data.msg != lotteryOption.value.danmakuKeyword) return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((lotteryOption.value.giftMinPrice ?? 0) > 0 && cmd == 'LIVE_OPEN_PLATFORM_SEND_GIFT') {
|
||||||
|
if ((data.price * data.gift_num) / 1000 < (lotteryOption.value.giftMinPrice ?? 0)) return false
|
||||||
|
}
|
||||||
|
if (lotteryOption.value.giftName && cmd == 'LIVE_OPEN_PLATFORM_SEND_GIFT') {
|
||||||
|
if (data.gift_name != lotteryOption.value.giftName) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
function startLottery() {
|
||||||
|
if (!isLottering.value && originUsers.value) {
|
||||||
|
isLottering.value = true
|
||||||
|
try {
|
||||||
|
if (originUsers.value.length < lotteryOption.value.resultCount) {
|
||||||
|
message.warning('符合条件的抽奖人数达不到抽选人数')
|
||||||
|
isLottering.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lotteryOption.value.lotteryType) {
|
||||||
|
case 'single': {
|
||||||
|
console.log('开始抽取单个用户')
|
||||||
|
removeSingleUser()
|
||||||
|
function removeSingleUser() {
|
||||||
|
if (currentUsers.value.length > lotteryOption.value.resultCount) {
|
||||||
|
console.log(`[${currentUsers.value.length}] 移除` + currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name)
|
||||||
|
setTimeout(() => {
|
||||||
|
removeSingleUser()
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
onFinishLottery()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'half': {
|
||||||
|
//每次点击随机减少一半的用户, 如果人数减半后达不到最低用户, 则减少至最低用户
|
||||||
|
if (currentUsers.value.length / 2 <= lotteryOption.value.resultCount) {
|
||||||
|
console.log(`[OPEN-LIVE-Lottery] 人数减半至${lotteryOption.value.resultCount}人`)
|
||||||
|
while (currentUsers.value.length > lotteryOption.value.resultCount) {
|
||||||
|
console.log(`[${currentUsers.value.length}] 移除` + currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name)
|
||||||
|
}
|
||||||
|
onFinishLottery()
|
||||||
|
} else {
|
||||||
|
const half = Math.floor(currentUsers.value.length / 2)
|
||||||
|
console.log(`[OPEN-LIVE-Lottery] 人数减半至${half}人`)
|
||||||
|
message.success('人数减半至 ' + half + ' 人')
|
||||||
|
while (currentUsers.value.length > half) {
|
||||||
|
console.log(`[${currentUsers.value.length}] 移除` + currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isLottering.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
message.error('发生错误')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getRandomInt(max: number) {
|
||||||
|
return Math.floor(Math.random() * max)
|
||||||
|
}
|
||||||
|
function onFinishLottery() {
|
||||||
|
resultUsers.value = JSON.parse(JSON.stringify(currentUsers.value))
|
||||||
|
isLottering.value = false
|
||||||
|
isLotteried.value = true
|
||||||
|
notification.create({
|
||||||
|
title: '抽奖完成',
|
||||||
|
description: '共' + resultUsers.value?.length + '人',
|
||||||
|
duration: 3000,
|
||||||
|
content: () =>
|
||||||
|
h(NSpace, { vertical: true }, () =>
|
||||||
|
resultUsers.value?.map((user) => h(NSpace, null, () => [h(NAvatar, { src: user.avatar + '@32w_32h', imgProps: { referrerpolicy: 'no-referrer' } }), h('span', user.name)]))
|
||||||
|
),
|
||||||
|
meta: format(new Date(), 'yyyy-MM-dd HH:mm:ss'),
|
||||||
|
onAfterLeave: () => {
|
||||||
|
message.success('已保存至历史')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
lotteryHistory.value.push({
|
||||||
|
users: currentUsers.value ?? [],
|
||||||
|
time: Date.now(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function reset() {
|
||||||
|
currentUsers.value = JSON.parse(JSON.stringify(originUsers.value))
|
||||||
|
isLotteried.value = false
|
||||||
|
}
|
||||||
|
function clear() {
|
||||||
|
originUsers.value = []
|
||||||
|
isLotteried.value = false
|
||||||
|
resultUsers.value = []
|
||||||
|
currentUsers.value = []
|
||||||
|
message.success('已清空队列')
|
||||||
|
}
|
||||||
|
function removeUser(user: OpenLiveLotteryUserInfo) {
|
||||||
|
currentUsers.value = currentUsers.value.filter((u) => u.uId != user.uId)
|
||||||
|
originUsers.value = originUsers.value.filter((u) => u.uId != user.uId)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDanmaku(command: any) {
|
||||||
|
const data = command.data
|
||||||
|
addUser(
|
||||||
|
{
|
||||||
|
uId: data.uid,
|
||||||
|
name: data.uname,
|
||||||
|
avatar: data.uface,
|
||||||
|
fans_medal_level: data.fans_medal_level,
|
||||||
|
fans_medal_name: data.fans_medal_name,
|
||||||
|
fans_medal_wearing_status: data.fans_medal_wearing_status,
|
||||||
|
guard_level: data.guard_level,
|
||||||
|
},
|
||||||
|
command
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function onGift(command: any) {
|
||||||
|
const data = command.data
|
||||||
|
addUser(
|
||||||
|
{
|
||||||
|
uId: data.uid,
|
||||||
|
name: data.uname,
|
||||||
|
avatar: data.uface,
|
||||||
|
fans_medal_level: data.fans_medal_level,
|
||||||
|
fans_medal_name: data.fans_medal_name,
|
||||||
|
fans_medal_wearing_status: data.fans_medal_wearing_status,
|
||||||
|
guard_level: data.guard_level,
|
||||||
|
},
|
||||||
|
command
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function pause() {
|
||||||
|
isStartLottery.value = false
|
||||||
|
message.info('已暂停新用户加入')
|
||||||
|
}
|
||||||
|
function continueLottery() {
|
||||||
|
isStartLottery.value = true
|
||||||
|
message.info('开始监听')
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
authInfo.value = route.query as unknown as AuthInfo
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NLayoutContent style="height: 100vh">
|
||||||
|
<NResult v-if="false" status="403" title="403" description="该页面只能从饭贩访问" />
|
||||||
|
<template v-else>
|
||||||
|
<NCard style="margin: 20px">
|
||||||
|
<template #header>
|
||||||
|
直播抽奖
|
||||||
|
<NDivider vertical />
|
||||||
|
<NButton text type="primary" tag="a" href="https://vtsuru.live" target="_blank"> 前往 VTsuru.live 主站 </NButton>
|
||||||
|
</template>
|
||||||
|
<NCard>
|
||||||
|
<NSpace align="center">
|
||||||
|
连接状态:
|
||||||
|
<NTag :type="isConnected ? 'success' : 'warning'"> {{ isConnected ? `已连接 | ${authResult?.anchor_info.uname}` : '未连接' }} </NTag>
|
||||||
|
<NButton v-if="!isConnected" type="primary" @click="start" size="small"> 连接直播间 </NButton>
|
||||||
|
<NButton type="info" @click="showModal = true" size="small"> 抽奖历史</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
<NCard size="small" embedded title="抽奖选项">
|
||||||
|
<template #header-extra>
|
||||||
|
<NButton size="small" secondary @click="lotteryOption = defaultOption" :disabled="isStartLottery"> 恢复默认 </NButton>
|
||||||
|
</template>
|
||||||
|
<NSpace justify="center" align="center">
|
||||||
|
<NTag :bordered="false"> 抽奖类型 </NTag>
|
||||||
|
<NRadioGroup v-model:value="lotteryOption.type" :disabled="isLottering" size="small">
|
||||||
|
<NRadioButton value="danmaku" :disabled="isStartLottery"> 弹幕 </NRadioButton>
|
||||||
|
<NRadioButton value="gift" :disabled="isStartLottery"> 礼物 </NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
</NSpace>
|
||||||
|
<NDivider style="margin: 10px 0 10px 0"></NDivider>
|
||||||
|
<NSpace align="center">
|
||||||
|
<NInputGroup style="max-width: 200px">
|
||||||
|
<NInputGroupLabel> 抽选人数 </NInputGroupLabel>
|
||||||
|
<NInputNumber :disabled="isStartLottery" v-model:value="lotteryOption.resultCount" placeholder="" min="1" />
|
||||||
|
</NInputGroup>
|
||||||
|
<NCheckbox :disabled="isStartLottery" v-model:checked="lotteryOption.needGuard"> 需要上舰 </NCheckbox>
|
||||||
|
<NCheckbox :disabled="isStartLottery" v-model:checked="lotteryOption.needFanMedal"> 需要粉丝牌 </NCheckbox>
|
||||||
|
<template v-if="lotteryOption.type == 'danmaku'">
|
||||||
|
<NCollapseTransition>
|
||||||
|
<NInputGroup v-if="lotteryOption.needFanMedal" style="max-width: 200px">
|
||||||
|
<NInputGroupLabel> 最低粉丝牌等级 </NInputGroupLabel>
|
||||||
|
<NInputNumber v-model:value="lotteryOption.fanCardLevel" min="1" max="50" :default-value="1" :disabled="isLottering || isStartLottery" />
|
||||||
|
</NInputGroup>
|
||||||
|
</NCollapseTransition>
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NInputGroup style="max-width: 250px">
|
||||||
|
<NInputGroupLabel> 弹幕内容 </NInputGroupLabel>
|
||||||
|
<NInput :disabled="isStartLottery" v-model:value="lotteryOption.danmakuKeyword" placeholder="留空则任何弹幕都可以" />
|
||||||
|
</NInputGroup>
|
||||||
|
</template>
|
||||||
|
符合规则的弹幕才会被添加到抽奖队列中
|
||||||
|
</NTooltip>
|
||||||
|
<NRadioGroup v-model:value="lotteryOption.danmakuFilterType" name="判定类型" :disabled="isLottering" size="small">
|
||||||
|
<NRadioButton :disabled="isStartLottery" value="all"> 完全一致 </NRadioButton>
|
||||||
|
<NRadioButton :disabled="isStartLottery" value="contains"> 包含 </NRadioButton>
|
||||||
|
<NRadioButton :disabled="isStartLottery" value="regex"> 正则 </NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="lotteryOption.type == 'gift'">
|
||||||
|
<NInputGroup style="max-width: 250px">
|
||||||
|
<NInputGroupLabel> 最低价格 </NInputGroupLabel>
|
||||||
|
<NInputNumber :disabled="isStartLottery" v-model:value="lotteryOption.giftMinPrice" placeholder="留空则不限制" />
|
||||||
|
</NInputGroup>
|
||||||
|
<NInputGroup style="max-width: 200px">
|
||||||
|
<NInputGroupLabel> 礼物名称 </NInputGroupLabel>
|
||||||
|
<NInput :disabled="isStartLottery" v-model:value="lotteryOption.giftName" placeholder="留空则不限制" />
|
||||||
|
</NInputGroup>
|
||||||
|
</template>
|
||||||
|
</NSpace>
|
||||||
|
<NDivider style="margin: 10px 0 10px 0"></NDivider>
|
||||||
|
<NSpace justify="center" align="center">
|
||||||
|
<NTag :bordered="false"> 抽取方式 </NTag>
|
||||||
|
<NRadioGroup v-model:value="lotteryOption.lotteryType" name="抽取类型" size="small" :disabled="isLottering">
|
||||||
|
<NRadioButton value="single">
|
||||||
|
单个
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NIcon :component="Info24Filled" />
|
||||||
|
</template>
|
||||||
|
一个一个减少
|
||||||
|
</NTooltip>
|
||||||
|
</NRadioButton>
|
||||||
|
<NRadioButton value="half">
|
||||||
|
减半
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NIcon :component="Info24Filled" />
|
||||||
|
</template>
|
||||||
|
点一次减少一半
|
||||||
|
</NTooltip>
|
||||||
|
</NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
<NCard v-if="originUsers" size="small">
|
||||||
|
<NSpace justify="center" align="center">
|
||||||
|
<NTag :bordered="false" type="warning" v-if="!isConnected"> 开始前需要先连接直播间 </NTag>
|
||||||
|
<NSpin v-if="isStartLottery" size="small" />
|
||||||
|
<NButton type="primary" @click="continueLottery" :loading="isLottering" :disabled="isStartLottery || isLotteried || !isConnected"> 开始 </NButton>
|
||||||
|
<NButton type="warning" :disabled="!isStartLottery" @click="pause"> 停止 </NButton>
|
||||||
|
<NButton type="error" :disabled="isLottering || originUsers.length == 0" @click="clear"> 清空 </NButton>
|
||||||
|
</NSpace>
|
||||||
|
<NDivider style="margin: 20px 0 20px 0"> <template v-if="isStartLottery"> 进行抽取前需要先停止 </template> </NDivider>
|
||||||
|
<NSpace justify="center">
|
||||||
|
<NButton type="primary" secondary @click="startLottery" :loading="isLottering" :disabled="isStartLottery || isLotteried"> 进行抽取 </NButton>
|
||||||
|
<NButton type="info" secondary :disabled="isStartLottery || isLottering || !isLotteried" @click="reset"> 重置 </NButton>
|
||||||
|
</NSpace>
|
||||||
|
<NDivider style="margin: 10px 0 10px 0"> 共 {{ currentUsers?.length }} 人</NDivider>
|
||||||
|
<NGrid v-if="currentUsers.length > 0" cols="1 500:2 800:3 1000:4" :x-gap="12" :y-gap="8">
|
||||||
|
<NGridItem v-for="item in currentUsers" v-bind:key="item.uId">
|
||||||
|
<NCard size="small" :title="item.name" style="height: 155px">
|
||||||
|
<template #header>
|
||||||
|
<NSpace align="center" vertical :size="5">
|
||||||
|
<NAvatar round lazy borderd :size="64" :src="item.avatar + '@64w_64h'" :img-props="{ referrerpolicy: 'no-referrer' }" style="box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2)" />
|
||||||
|
<NSpace>
|
||||||
|
<NTag size="tiny" round>
|
||||||
|
<NTag size="tiny" round :bordered="false">
|
||||||
|
{{ item.fans_medal_level }}
|
||||||
|
</NTag>
|
||||||
|
<span style="color: #577fb8">
|
||||||
|
{{ item.fans_medal_name }}
|
||||||
|
</span>
|
||||||
|
</NTag>
|
||||||
|
</NSpace>
|
||||||
|
{{ item.name }}
|
||||||
|
</NSpace>
|
||||||
|
|
||||||
|
<NButton style="position: absolute; right: 5px; top: 5px; color: #753e3e" @click="removeUser(item)" size="small" circle>
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="Delete24Filled" />
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
</NCard>
|
||||||
|
</NGridItem>
|
||||||
|
</NGrid>
|
||||||
|
<NEmpty v-else description="暂无用户" />
|
||||||
|
</NCard>
|
||||||
|
<NSpace justify="center" style="margin-top: 20px">
|
||||||
|
<NButton type="info" text tag="a" href="https://vtsuru.live" target="_blank"> vtsuru.live </NButton>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
</template>
|
||||||
|
<NModal v-model:show="showModal" preset="card" title="抽奖结果" style="max-width: 90%; width: 800px" closable>
|
||||||
|
<template #header-extra>
|
||||||
|
<NButton type="error" size="small" @click="lotteryHistory = []"> 清空 </NButton>
|
||||||
|
</template>
|
||||||
|
<NScrollbar v-if="lotteryHistory.length > 0" style="max-height: 80vh">
|
||||||
|
<NList>
|
||||||
|
<NListItem v-for="item in lotteryHistory" :key="item.time">
|
||||||
|
<NCard size="small">
|
||||||
|
<template #header>
|
||||||
|
<NTime :time="item.time" />
|
||||||
|
</template>
|
||||||
|
<template #header-extra>
|
||||||
|
<NButton type="error" size="small" @click="lotteryHistory.splice(lotteryHistory.indexOf(item), 1)"> 删除 </NButton>
|
||||||
|
</template>
|
||||||
|
<NSpace vertical>
|
||||||
|
<NSpace v-for="user in item.users" :key="user.uId">
|
||||||
|
<NAvatar round lazy :src="user.avatar + '@64w_64h'" :img-props="{ referrerpolicy: 'no-referrer' }" />
|
||||||
|
{{ user.name }}
|
||||||
|
</NSpace>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
</NListItem>
|
||||||
|
</NList>
|
||||||
|
</NScrollbar>
|
||||||
|
<NEmpty v-else description="暂无记录" />
|
||||||
|
</NModal>
|
||||||
|
</NLayoutContent>
|
||||||
|
</template>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"src/**/*.vue",
|
"src/**/*.vue",
|
||||||
"tests/**/*.ts",
|
"tests/**/*.ts",
|
||||||
"tests/**/*.tsx"
|
"tests/**/*.tsx"
|
||||||
, "env.d.ts", "default.d.ts" ],
|
, "env.d.ts", "default.d.ts", "src/data/chat/ChatClientDirectOpenLive.js" ],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -3,9 +3,15 @@ import { defineConfig } from 'vite'
|
|||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import svgLoader from 'vite-svg-loader'
|
import svgLoader from 'vite-svg-loader'
|
||||||
|
import mkcert from 'vite-plugin-mkcert'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue(), svgLoader()],
|
server: {
|
||||||
|
https: true, // 需要开启https服务
|
||||||
|
},
|
||||||
|
plugins: [vue(), svgLoader(), mkcert({
|
||||||
|
source: 'coding'
|
||||||
|
})],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': path.resolve(__dirname, 'src'),
|
'@': path.resolve(__dirname, 'src'),
|
||||||
@@ -15,4 +21,3 @@ export default defineConfig({
|
|||||||
'process.env': {},
|
'process.env': {},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const { defineConfig } = require('@vue/cli-service');
|
const { defineConfig } = require('@vue/cli-service')
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
transpileDependencies: true,
|
transpileDependencies: true,
|
||||||
});
|
})
|
||||||
|
|||||||
225
yarn.lock
225
yarn.lock
@@ -264,6 +264,117 @@
|
|||||||
"@nodelib/fs.scandir" "2.1.5"
|
"@nodelib/fs.scandir" "2.1.5"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
|
"@octokit/auth-token@^3.0.0":
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.4.tgz#70e941ba742bdd2b49bdb7393e821dea8520a3db"
|
||||||
|
integrity sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==
|
||||||
|
|
||||||
|
"@octokit/core@^4.2.1":
|
||||||
|
version "4.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.2.4.tgz#d8769ec2b43ff37cc3ea89ec4681a20ba58ef907"
|
||||||
|
integrity sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/auth-token" "^3.0.0"
|
||||||
|
"@octokit/graphql" "^5.0.0"
|
||||||
|
"@octokit/request" "^6.0.0"
|
||||||
|
"@octokit/request-error" "^3.0.0"
|
||||||
|
"@octokit/types" "^9.0.0"
|
||||||
|
before-after-hook "^2.2.0"
|
||||||
|
universal-user-agent "^6.0.0"
|
||||||
|
|
||||||
|
"@octokit/endpoint@^7.0.0":
|
||||||
|
version "7.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.6.tgz#791f65d3937555141fb6c08f91d618a7d645f1e2"
|
||||||
|
integrity sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types" "^9.0.0"
|
||||||
|
is-plain-object "^5.0.0"
|
||||||
|
universal-user-agent "^6.0.0"
|
||||||
|
|
||||||
|
"@octokit/graphql@^5.0.0":
|
||||||
|
version "5.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.6.tgz#9eac411ac4353ccc5d3fca7d76736e6888c5d248"
|
||||||
|
integrity sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/request" "^6.0.0"
|
||||||
|
"@octokit/types" "^9.0.0"
|
||||||
|
universal-user-agent "^6.0.0"
|
||||||
|
|
||||||
|
"@octokit/openapi-types@^18.0.0":
|
||||||
|
version "18.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-18.1.1.tgz#09bdfdabfd8e16d16324326da5148010d765f009"
|
||||||
|
integrity sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==
|
||||||
|
|
||||||
|
"@octokit/plugin-paginate-rest@^6.1.2":
|
||||||
|
version "6.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz#f86456a7a1fe9e58fec6385a85cf1b34072341f8"
|
||||||
|
integrity sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/tsconfig" "^1.0.2"
|
||||||
|
"@octokit/types" "^9.2.3"
|
||||||
|
|
||||||
|
"@octokit/plugin-request-log@^1.0.4":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
|
||||||
|
integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
|
||||||
|
|
||||||
|
"@octokit/plugin-rest-endpoint-methods@^7.1.2":
|
||||||
|
version "7.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz#37a84b171a6cb6658816c82c4082ac3512021797"
|
||||||
|
integrity sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types" "^10.0.0"
|
||||||
|
|
||||||
|
"@octokit/request-error@^3.0.0":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.3.tgz#ef3dd08b8e964e53e55d471acfe00baa892b9c69"
|
||||||
|
integrity sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types" "^9.0.0"
|
||||||
|
deprecation "^2.0.0"
|
||||||
|
once "^1.4.0"
|
||||||
|
|
||||||
|
"@octokit/request@^6.0.0":
|
||||||
|
version "6.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.2.8.tgz#aaf480b32ab2b210e9dadd8271d187c93171d8eb"
|
||||||
|
integrity sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/endpoint" "^7.0.0"
|
||||||
|
"@octokit/request-error" "^3.0.0"
|
||||||
|
"@octokit/types" "^9.0.0"
|
||||||
|
is-plain-object "^5.0.0"
|
||||||
|
node-fetch "^2.6.7"
|
||||||
|
universal-user-agent "^6.0.0"
|
||||||
|
|
||||||
|
"@octokit/rest@^19.0.5":
|
||||||
|
version "19.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.13.tgz#e799393264edc6d3c67eeda9e5bd7832dcf974e4"
|
||||||
|
integrity sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/core" "^4.2.1"
|
||||||
|
"@octokit/plugin-paginate-rest" "^6.1.2"
|
||||||
|
"@octokit/plugin-request-log" "^1.0.4"
|
||||||
|
"@octokit/plugin-rest-endpoint-methods" "^7.1.2"
|
||||||
|
|
||||||
|
"@octokit/tsconfig@^1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/tsconfig/-/tsconfig-1.0.2.tgz#59b024d6f3c0ed82f00d08ead5b3750469125af7"
|
||||||
|
integrity sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==
|
||||||
|
|
||||||
|
"@octokit/types@^10.0.0":
|
||||||
|
version "10.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-10.0.0.tgz#7ee19c464ea4ada306c43f1a45d444000f419a4a"
|
||||||
|
integrity sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/openapi-types" "^18.0.0"
|
||||||
|
|
||||||
|
"@octokit/types@^9.0.0", "@octokit/types@^9.2.3":
|
||||||
|
version "9.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-9.3.2.tgz#3f5f89903b69f6a2d196d78ec35f888c0013cac5"
|
||||||
|
integrity sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/openapi-types" "^18.0.0"
|
||||||
|
|
||||||
"@trysound/sax@0.2.0":
|
"@trysound/sax@0.2.0":
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
|
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
|
||||||
@@ -737,6 +848,11 @@ async-validator@^4.2.5:
|
|||||||
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
|
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
|
||||||
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
|
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
|
||||||
|
|
||||||
|
asynckit@^0.4.0:
|
||||||
|
version "0.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||||
|
|
||||||
atob@^2.1.2:
|
atob@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
@@ -747,6 +863,15 @@ available-typed-arrays@^1.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
||||||
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
||||||
|
|
||||||
|
axios@^1.2.2:
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102"
|
||||||
|
integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.15.0"
|
||||||
|
form-data "^4.0.0"
|
||||||
|
proxy-from-env "^1.1.0"
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
@@ -757,6 +882,11 @@ base64-arraybuffer@^1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
|
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
|
||||||
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
|
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
|
||||||
|
|
||||||
|
before-after-hook@^2.2.0:
|
||||||
|
version "2.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c"
|
||||||
|
integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==
|
||||||
|
|
||||||
big.js@^5.2.2:
|
big.js@^5.2.2:
|
||||||
version "5.2.2"
|
version "5.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||||
@@ -867,6 +997,13 @@ colorette@^2.0.16:
|
|||||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
|
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
|
||||||
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
|
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
|
||||||
|
|
||||||
|
combined-stream@^1.0.8:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
dependencies:
|
||||||
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
commander@^7.2.0:
|
commander@^7.2.0:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
|
||||||
@@ -1056,6 +1193,16 @@ define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0:
|
|||||||
has-property-descriptors "^1.0.0"
|
has-property-descriptors "^1.0.0"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
|
delayed-stream@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||||
|
|
||||||
|
deprecation@^2.0.0:
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
|
||||||
|
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
|
||||||
|
|
||||||
dequal@^2.0.3:
|
dequal@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
|
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
|
||||||
@@ -1589,6 +1736,11 @@ flatted@^3.2.9:
|
|||||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
|
||||||
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
|
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
|
||||||
|
|
||||||
|
follow-redirects@^1.15.0:
|
||||||
|
version "1.15.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
|
||||||
|
integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
|
||||||
|
|
||||||
for-each@^0.3.3:
|
for-each@^0.3.3:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||||
@@ -1596,6 +1748,15 @@ for-each@^0.3.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-callable "^1.1.3"
|
is-callable "^1.1.3"
|
||||||
|
|
||||||
|
form-data@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||||
|
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "^1.0.8"
|
||||||
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
@@ -1939,6 +2100,11 @@ is-path-inside@^3.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
||||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||||
|
|
||||||
|
is-plain-object@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
|
||||||
|
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
|
||||||
|
|
||||||
is-regex@^1.1.4:
|
is-regex@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
|
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
|
||||||
@@ -2193,6 +2359,18 @@ micromatch@^4.0.4:
|
|||||||
braces "^3.0.2"
|
braces "^3.0.2"
|
||||||
picomatch "^2.3.1"
|
picomatch "^2.3.1"
|
||||||
|
|
||||||
|
mime-db@1.52.0:
|
||||||
|
version "1.52.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||||
|
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||||
|
|
||||||
|
mime-types@^2.1.12:
|
||||||
|
version "2.1.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||||
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
|
dependencies:
|
||||||
|
mime-db "1.52.0"
|
||||||
|
|
||||||
mimic-fn@^2.1.0:
|
mimic-fn@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
@@ -2274,6 +2452,13 @@ natural-compare@^1.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||||
|
|
||||||
|
node-fetch@^2.6.7:
|
||||||
|
version "2.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||||
|
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||||
|
dependencies:
|
||||||
|
whatwg-url "^5.0.0"
|
||||||
|
|
||||||
normalize-path@^3.0.0:
|
normalize-path@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||||
@@ -2350,7 +2535,7 @@ object.values@^1.1.7:
|
|||||||
define-properties "^1.2.0"
|
define-properties "^1.2.0"
|
||||||
es-abstract "^1.22.1"
|
es-abstract "^1.22.1"
|
||||||
|
|
||||||
once@^1.3.0:
|
once@^1.3.0, once@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||||
@@ -2490,6 +2675,11 @@ prettier@^2.8.8:
|
|||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
|
||||||
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
|
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
|
||||||
|
|
||||||
|
proxy-from-env@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||||
|
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||||
|
|
||||||
punycode@^2.1.0:
|
punycode@^2.1.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||||
@@ -2893,6 +3083,11 @@ to-regex-range@^5.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-number "^7.0.0"
|
is-number "^7.0.0"
|
||||||
|
|
||||||
|
tr46@~0.0.3:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||||
|
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||||
|
|
||||||
treemate@^0.3.11:
|
treemate@^0.3.11:
|
||||||
version "0.3.11"
|
version "0.3.11"
|
||||||
resolved "https://registry.yarnpkg.com/treemate/-/treemate-0.3.11.tgz#7d52f8f69ab9ce326f8d139e0a3d1ffb25e48222"
|
resolved "https://registry.yarnpkg.com/treemate/-/treemate-0.3.11.tgz#7d52f8f69ab9ce326f8d139e0a3d1ffb25e48222"
|
||||||
@@ -3014,6 +3209,11 @@ universal-cookie@^4.0.4:
|
|||||||
"@types/cookie" "^0.3.3"
|
"@types/cookie" "^0.3.3"
|
||||||
cookie "^0.4.0"
|
cookie "^0.4.0"
|
||||||
|
|
||||||
|
universal-user-agent@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
|
||||||
|
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
|
||||||
|
|
||||||
uri-js@^4.2.2:
|
uri-js@^4.2.2:
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||||
@@ -3040,6 +3240,16 @@ vdirs@^0.1.4, vdirs@^0.1.8:
|
|||||||
dependencies:
|
dependencies:
|
||||||
evtd "^0.2.2"
|
evtd "^0.2.2"
|
||||||
|
|
||||||
|
vite-plugin-mkcert@^1.16.0:
|
||||||
|
version "1.16.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vite-plugin-mkcert/-/vite-plugin-mkcert-1.16.0.tgz#f02cce5747295dd3d8b1958b920bb6b9b7fdace8"
|
||||||
|
integrity sha512-5r+g8SB9wZzLNUFekGwZo3e0P6QlS6rbxK5p9z/itxNAimsYohgjK/YfVPVxM9EuglP9hjridq0lUejo9v1nVg==
|
||||||
|
dependencies:
|
||||||
|
"@octokit/rest" "^19.0.5"
|
||||||
|
axios "^1.2.2"
|
||||||
|
debug "^4.3.4"
|
||||||
|
picocolors "^1.0.0"
|
||||||
|
|
||||||
vite-svg-loader@^4.0.0:
|
vite-svg-loader@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/vite-svg-loader/-/vite-svg-loader-4.0.0.tgz#1cec4337dba3c23ab13bcabb111896e251b047ac"
|
resolved "https://registry.yarnpkg.com/vite-svg-loader/-/vite-svg-loader-4.0.0.tgz#1cec4337dba3c23ab13bcabb111896e251b047ac"
|
||||||
@@ -3183,6 +3393,19 @@ vuex@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@vue/devtools-api" "^6.0.0-beta.11"
|
"@vue/devtools-api" "^6.0.0-beta.11"
|
||||||
|
|
||||||
|
webidl-conversions@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
|
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||||
|
|
||||||
|
whatwg-url@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||||
|
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
||||||
|
dependencies:
|
||||||
|
tr46 "~0.0.3"
|
||||||
|
webidl-conversions "^3.0.0"
|
||||||
|
|
||||||
which-boxed-primitive@^1.0.2:
|
which-boxed-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||||
|
|||||||
Reference in New Issue
Block a user