mirror of
https://github.com/timeshiftsauce/CeruMusic.git
synced 2025-11-25 11:29:42 +08:00
fix:qqLyric
This commit is contained in:
@@ -8,4 +8,5 @@
|
|||||||
- [ ] ai功能完善
|
- [ ] ai功能完善
|
||||||
- [ ] 支持歌词隐藏
|
- [ ] 支持歌词隐藏
|
||||||
- [x] 兼容多平台歌单导入
|
- [x] 兼容多平台歌单导入
|
||||||
|
- [ ] 软件能不能记住上次打开的窗口大小,每次都要手动拉
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ceru-music",
|
"name": "ceru-music",
|
||||||
"version": "1.3.3",
|
"version": "1.3.4",
|
||||||
"description": "一款简洁优雅的音乐播放器",
|
"description": "一款简洁优雅的音乐播放器",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "sqj,wldss,star",
|
"author": "sqj,wldss,star",
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
"homepage": "https://ceru.docs.shiqianjiang.cn",
|
"homepage": "https://ceru.docs.shiqianjiang.cn",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"lint": "eslint --cache . --fix",
|
"lint": "eslint --cache . --fix && yarn typecheck",
|
||||||
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
||||||
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
|
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
|
||||||
"typecheck": "yarn run typecheck:node && yarn run typecheck:web",
|
"typecheck": "yarn run typecheck:node && yarn run typecheck:web",
|
||||||
|
|||||||
BIN
src/main/utils/musicSdk/tx/__pycache__/des.cpython-313.pyc
Normal file
BIN
src/main/utils/musicSdk/tx/__pycache__/des.cpython-313.pyc
Normal file
Binary file not shown.
@@ -1,10 +1,29 @@
|
|||||||
|
import qrcDecrypt from './qrc-decrypt'
|
||||||
import { httpFetch } from '../../request'
|
import { httpFetch } from '../../request'
|
||||||
import getMusicInfo from './musicInfo'
|
import getMusicInfo from './musicInfo'
|
||||||
|
|
||||||
const songIdMap = new Map()
|
const songIdMap = new Map()
|
||||||
const promises = new Map()
|
const promises = new Map()
|
||||||
|
const decode = qrcDecrypt()
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
rxps: {
|
||||||
|
info: /^{"/,
|
||||||
|
lineTime: /^\[(\d+),\d+\]/,
|
||||||
|
lineTime2: /^\[([\d:.]+)\]/,
|
||||||
|
wordTime: /\(\d+,\d+,\d+\)/,
|
||||||
|
wordTimeAll: /(\(\d+,\d+,\d+\))/g,
|
||||||
|
timeLabelFixRxp: /(?:\.0+|0+)$/,
|
||||||
|
},
|
||||||
|
msFormat(timeMs) {
|
||||||
|
if (Number.isNaN(timeMs)) return ''
|
||||||
|
let ms = timeMs % 1000
|
||||||
|
timeMs /= 1000
|
||||||
|
let m = parseInt(timeMs / 60).toString().padStart(2, '0')
|
||||||
|
timeMs %= 60
|
||||||
|
let s = parseInt(timeMs).toString().padStart(2, '0')
|
||||||
|
return `[${m}:${s}.${String(ms).padStart(3, '0')}]`
|
||||||
|
},
|
||||||
successCode: 0,
|
successCode: 0,
|
||||||
async getSongId({ songId, songmid }) {
|
async getSongId({ songId, songmid }) {
|
||||||
if (songId) return songId
|
if (songId) return songId
|
||||||
@@ -17,6 +36,185 @@ export default {
|
|||||||
promises.delete(songmid)
|
promises.delete(songmid)
|
||||||
return info.songId
|
return info.songId
|
||||||
},
|
},
|
||||||
|
removeTag(str) {
|
||||||
|
return str.replace(/^[\S\s]*?LyricContent="/, '').replace(/"\/>[\S\s]*?$/, '')
|
||||||
|
},
|
||||||
|
parseCeru(lrc) {
|
||||||
|
lrc = lrc.trim()
|
||||||
|
lrc = lrc.replace(/\r/g, '')
|
||||||
|
if (!lrc) return { lyric: '', lxlyric: '' }
|
||||||
|
const lines = lrc.split('\n')
|
||||||
|
|
||||||
|
const lxlrcLines = []
|
||||||
|
const lrcLines = []
|
||||||
|
|
||||||
|
for (let line of lines) {
|
||||||
|
line = line.trim()
|
||||||
|
let result = this.rxps.lineTime.exec(line)
|
||||||
|
if (!result) {
|
||||||
|
if (line.startsWith('[offset')) {
|
||||||
|
lxlrcLines.push(line)
|
||||||
|
lrcLines.push(line)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (this.rxps.lineTime2.test(line)) {
|
||||||
|
// lxlrcLines.push(line)
|
||||||
|
lrcLines.push(line)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const startMsTime = parseInt(result[1])
|
||||||
|
const startTimeStr = this.msFormat(startMsTime)
|
||||||
|
if (!startTimeStr) continue
|
||||||
|
|
||||||
|
let words = line.replace(this.rxps.lineTime, '')
|
||||||
|
|
||||||
|
lrcLines.push(`${startTimeStr}${words.replace(this.rxps.wordTimeAll, '')}`)
|
||||||
|
|
||||||
|
let times = words.match(this.rxps.wordTimeAll)
|
||||||
|
if (!times) continue
|
||||||
|
|
||||||
|
let currentStart = startMsTime
|
||||||
|
const processedTimes = []
|
||||||
|
|
||||||
|
times.forEach(time => {
|
||||||
|
const result = /\((\d+),(\d+),(\d+)\)/.exec(time)
|
||||||
|
const duration = parseInt(result[2])
|
||||||
|
processedTimes.push(`(${currentStart},${duration},0)`)
|
||||||
|
currentStart += duration
|
||||||
|
})
|
||||||
|
|
||||||
|
const wordArr = words.split(this.rxps.wordTime)
|
||||||
|
const newWords = processedTimes.map((time, index) => `${time}${wordArr[index]}`).join('')
|
||||||
|
lxlrcLines.push(`${startTimeStr}${newWords}`)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
lyric: lrcLines.join('\n'),
|
||||||
|
lxlyric: lxlrcLines.join('\n'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getIntv(interval) {
|
||||||
|
if (!interval) return 0
|
||||||
|
if (!interval.includes('.')) interval += '.0'
|
||||||
|
let arr = interval.split(/:|\./)
|
||||||
|
while (arr.length < 3) arr.unshift('0')
|
||||||
|
const [m, s, ms] = arr
|
||||||
|
return parseInt(m) * 3600000 + parseInt(s) * 1000 + parseInt(ms)
|
||||||
|
},
|
||||||
|
fixRlrcTimeTag(rlrc, lrc) {
|
||||||
|
// console.log(lrc)
|
||||||
|
// console.log(rlrc)
|
||||||
|
const rlrcLines = rlrc.split('\n')
|
||||||
|
let lrcLines = lrc.split('\n')
|
||||||
|
// let temp = []
|
||||||
|
let newLrc = []
|
||||||
|
rlrcLines.forEach((line) => {
|
||||||
|
const result = this.rxps.lineTime2.exec(line)
|
||||||
|
if (!result) return
|
||||||
|
const words = line.replace(this.rxps.lineTime2, '')
|
||||||
|
if (!words.trim()) return
|
||||||
|
const t1 = this.getIntv(result[1])
|
||||||
|
|
||||||
|
while (lrcLines.length) {
|
||||||
|
const lrcLine = lrcLines.shift()
|
||||||
|
const lrcLineResult = this.rxps.lineTime2.exec(lrcLine)
|
||||||
|
if (!lrcLineResult) continue
|
||||||
|
const t2 = this.getIntv(lrcLineResult[1])
|
||||||
|
if (Math.abs(t1 - t2) < 100) {
|
||||||
|
newLrc.push(line.replace(this.rxps.lineTime2, lrcLineResult[0]))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// temp.push(line)
|
||||||
|
}
|
||||||
|
// lrcLines = [...temp, ...lrcLines]
|
||||||
|
// temp = []
|
||||||
|
})
|
||||||
|
return newLrc.join('\n')
|
||||||
|
},
|
||||||
|
fixTlrcTimeTag(tlrc, lrc) {
|
||||||
|
// console.log(lrc)
|
||||||
|
// console.log(tlrc)
|
||||||
|
const tlrcLines = tlrc.split('\n')
|
||||||
|
let lrcLines = lrc.split('\n')
|
||||||
|
// let temp = []
|
||||||
|
let newLrc = []
|
||||||
|
tlrcLines.forEach((line) => {
|
||||||
|
const result = this.rxps.lineTime2.exec(line)
|
||||||
|
if (!result) return
|
||||||
|
const words = line.replace(this.rxps.lineTime2, '')
|
||||||
|
if (!words.trim()) return
|
||||||
|
let time = result[1]
|
||||||
|
if (time.includes('.')) {
|
||||||
|
time += ''.padStart(3 - time.split('.')[1].length, '0')
|
||||||
|
}
|
||||||
|
const t1 = this.getIntv(time)
|
||||||
|
|
||||||
|
while (lrcLines.length) {
|
||||||
|
const lrcLine = lrcLines.shift()
|
||||||
|
const lrcLineResult = this.rxps.lineTime2.exec(lrcLine)
|
||||||
|
if (!lrcLineResult) continue
|
||||||
|
const t2 = this.getIntv(lrcLineResult[1])
|
||||||
|
if (Math.abs(t1 - t2) < 100) {
|
||||||
|
newLrc.push(line.replace(this.rxps.lineTime2, lrcLineResult[0]))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// temp.push(line)
|
||||||
|
}
|
||||||
|
// lrcLines = [...temp, ...lrcLines]
|
||||||
|
// temp = []
|
||||||
|
})
|
||||||
|
return newLrc.join('\n')
|
||||||
|
},
|
||||||
|
parse(lrc, tlrc, rlrc) {
|
||||||
|
const info = {
|
||||||
|
lyric: '',
|
||||||
|
tlyric: '',
|
||||||
|
rlyric: '',
|
||||||
|
crlyric: '',
|
||||||
|
|
||||||
|
}
|
||||||
|
if (lrc) {
|
||||||
|
let { lyric } = this.parseCeru(this.removeTag(lrc))
|
||||||
|
console.log(lyric, lrc)
|
||||||
|
info.lyric = lyric
|
||||||
|
info.crlyric = lrc
|
||||||
|
}
|
||||||
|
if (rlrc) info.rlyric = this.fixRlrcTimeTag(this.parseRlyric(this.removeTag(rlrc)), info.lyric)
|
||||||
|
if (tlrc) info.tlyric = this.fixTlrcTimeTag(tlrc, info.lyric)
|
||||||
|
|
||||||
|
return info
|
||||||
|
},
|
||||||
|
parseRlyric(lrc) {
|
||||||
|
lrc = lrc.trim()
|
||||||
|
lrc = lrc.replace(/\r/g, '')
|
||||||
|
if (!lrc) return { lyric: '', lxlyric: '' }
|
||||||
|
const lines = lrc.split('\n')
|
||||||
|
|
||||||
|
const lrcLines = []
|
||||||
|
|
||||||
|
for (let line of lines) {
|
||||||
|
line = line.trim()
|
||||||
|
let result = this.rxps.lineTime.exec(line)
|
||||||
|
if (!result) continue
|
||||||
|
|
||||||
|
const startMsTime = parseInt(result[1])
|
||||||
|
const startTimeStr = this.msFormat(startMsTime)
|
||||||
|
if (!startTimeStr) continue
|
||||||
|
|
||||||
|
let words = line.replace(this.rxps.lineTime, '')
|
||||||
|
|
||||||
|
lrcLines.push(`${startTimeStr}${words.replace(this.rxps.wordTimeAll, '')}`)
|
||||||
|
}
|
||||||
|
return lrcLines.join('\n')
|
||||||
|
},
|
||||||
|
parseLyric(lrc, tlrc, rlrc) {
|
||||||
|
return this.parse(
|
||||||
|
decode(lrc),
|
||||||
|
decode(tlrc),
|
||||||
|
decode(rlrc)
|
||||||
|
)
|
||||||
|
},
|
||||||
getLyric(mInfo, retryNum = 0) {
|
getLyric(mInfo, retryNum = 0) {
|
||||||
if (retryNum > 3) return Promise.reject(new Error('Get lyric failed'))
|
if (retryNum > 3) return Promise.reject(new Error('Get lyric failed'))
|
||||||
|
|
||||||
|
|||||||
522
src/main/utils/musicSdk/tx/qrc-decrypt.js
Normal file
522
src/main/utils/musicSdk/tx/qrc-decrypt.js
Normal file
@@ -0,0 +1,522 @@
|
|||||||
|
|
||||||
|
import zlib from 'zlib'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const ENCRYPT = 1
|
||||||
|
const DECRYPT = 0
|
||||||
|
|
||||||
|
const sbox = [
|
||||||
|
// sbox1
|
||||||
|
[
|
||||||
|
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12,
|
||||||
|
11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1,
|
||||||
|
7, 5, 11, 3, 14, 10, 0, 6, 13
|
||||||
|
],
|
||||||
|
// sbox2
|
||||||
|
[
|
||||||
|
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 15, 12, 0, 1, 10,
|
||||||
|
6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2,
|
||||||
|
11, 6, 7, 12, 0, 5, 14, 9
|
||||||
|
],
|
||||||
|
// sbox3
|
||||||
|
[
|
||||||
|
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14,
|
||||||
|
12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7,
|
||||||
|
4, 15, 14, 3, 11, 5, 2, 12
|
||||||
|
],
|
||||||
|
// sbox4
|
||||||
|
[
|
||||||
|
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12,
|
||||||
|
1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 10, 13,
|
||||||
|
8, 9, 4, 5, 11, 12, 7, 2, 14
|
||||||
|
],
|
||||||
|
// sbox5
|
||||||
|
[
|
||||||
|
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15,
|
||||||
|
10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2,
|
||||||
|
13, 6, 15, 0, 9, 10, 4, 5, 3
|
||||||
|
],
|
||||||
|
// sbox6
|
||||||
|
[
|
||||||
|
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14,
|
||||||
|
0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10,
|
||||||
|
11, 14, 1, 7, 6, 0, 8, 13
|
||||||
|
],
|
||||||
|
// sbox7
|
||||||
|
[
|
||||||
|
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12,
|
||||||
|
2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7,
|
||||||
|
9, 5, 0, 15, 14, 2, 3, 12
|
||||||
|
],
|
||||||
|
// sbox8
|
||||||
|
[
|
||||||
|
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11,
|
||||||
|
0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13,
|
||||||
|
15, 12, 9, 0, 3, 5, 6, 11
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 Buffer 中提取指定位置的位,并左移指定偏移量
|
||||||
|
* @param {Buffer} a - Buffer
|
||||||
|
* @param {number} b - 要提取的位索引
|
||||||
|
* @param {number} c - 位提取后的偏移量
|
||||||
|
* @returns {number} 提取后的位
|
||||||
|
*/
|
||||||
|
function bitnum(a, b, c) {
|
||||||
|
const byteIndex = Math.floor(b / 32) * 4 + 3 - Math.floor((b % 32) / 8)
|
||||||
|
const bitInByte = 7 - (b % 8)
|
||||||
|
const bit = (a[byteIndex] >> bitInByte) & 1
|
||||||
|
return bit << c
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从整数中提取指定位置的位,并左移指定偏移量
|
||||||
|
* @param {number} a - 整数
|
||||||
|
* @param {number} b - 要提取的位索引
|
||||||
|
* @param {number} c - 位提取后的偏移量
|
||||||
|
* @returns {number} 提取后的位
|
||||||
|
*/
|
||||||
|
function bitnum_intr(a, b, c) {
|
||||||
|
return (((a >>> (31 - b)) & 1) << c) | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从整数中提取指定位置的位,并右移指定偏移量
|
||||||
|
* @param {number} a - 整数
|
||||||
|
* @param {number} b - 要提取的位索引
|
||||||
|
* @param {number} c - 位提取后的偏移量
|
||||||
|
* @returns {number} 提取后的位
|
||||||
|
*/
|
||||||
|
function bitnum_intl(a, b, c) {
|
||||||
|
return (((a << b) & 0x80000000) >>> c) | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对输入整数进行位运算,重新组合位
|
||||||
|
* @param {number} a - 整数
|
||||||
|
* @returns {number} 重新组合后的位
|
||||||
|
*/
|
||||||
|
function sbox_bit(a) {
|
||||||
|
return (a & 32) | ((a & 31) >> 1) | ((a & 1) << 4) | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始置换
|
||||||
|
* @param {Buffer} input_data - 输入 Buffer
|
||||||
|
* @returns {[number, number]} 初始置换后的两个32位整数
|
||||||
|
*/
|
||||||
|
function initial_permutation(input_data) {
|
||||||
|
const s0 =
|
||||||
|
bitnum(input_data, 57, 31) |
|
||||||
|
bitnum(input_data, 49, 30) |
|
||||||
|
bitnum(input_data, 41, 29) |
|
||||||
|
bitnum(input_data, 33, 28) |
|
||||||
|
bitnum(input_data, 25, 27) |
|
||||||
|
bitnum(input_data, 17, 26) |
|
||||||
|
bitnum(input_data, 9, 25) |
|
||||||
|
bitnum(input_data, 1, 24) |
|
||||||
|
bitnum(input_data, 59, 23) |
|
||||||
|
bitnum(input_data, 51, 22) |
|
||||||
|
bitnum(input_data, 43, 21) |
|
||||||
|
bitnum(input_data, 35, 20) |
|
||||||
|
bitnum(input_data, 27, 19) |
|
||||||
|
bitnum(input_data, 19, 18) |
|
||||||
|
bitnum(input_data, 11, 17) |
|
||||||
|
bitnum(input_data, 3, 16) |
|
||||||
|
bitnum(input_data, 61, 15) |
|
||||||
|
bitnum(input_data, 53, 14) |
|
||||||
|
bitnum(input_data, 45, 13) |
|
||||||
|
bitnum(input_data, 37, 12) |
|
||||||
|
bitnum(input_data, 29, 11) |
|
||||||
|
bitnum(input_data, 21, 10) |
|
||||||
|
bitnum(input_data, 13, 9) |
|
||||||
|
bitnum(input_data, 5, 8) |
|
||||||
|
bitnum(input_data, 63, 7) |
|
||||||
|
bitnum(input_data, 55, 6) |
|
||||||
|
bitnum(input_data, 47, 5) |
|
||||||
|
bitnum(input_data, 39, 4) |
|
||||||
|
bitnum(input_data, 31, 3) |
|
||||||
|
bitnum(input_data, 23, 2) |
|
||||||
|
bitnum(input_data, 15, 1) |
|
||||||
|
bitnum(input_data, 7, 0) |
|
||||||
|
0
|
||||||
|
|
||||||
|
const s1 =
|
||||||
|
bitnum(input_data, 56, 31) |
|
||||||
|
bitnum(input_data, 48, 30) |
|
||||||
|
bitnum(input_data, 40, 29) |
|
||||||
|
bitnum(input_data, 32, 28) |
|
||||||
|
bitnum(input_data, 24, 27) |
|
||||||
|
bitnum(input_data, 16, 26) |
|
||||||
|
bitnum(input_data, 8, 25) |
|
||||||
|
bitnum(input_data, 0, 24) |
|
||||||
|
bitnum(input_data, 58, 23) |
|
||||||
|
bitnum(input_data, 50, 22) |
|
||||||
|
bitnum(input_data, 42, 21) |
|
||||||
|
bitnum(input_data, 34, 20) |
|
||||||
|
bitnum(input_data, 26, 19) |
|
||||||
|
bitnum(input_data, 18, 18) |
|
||||||
|
bitnum(input_data, 10, 17) |
|
||||||
|
bitnum(input_data, 2, 16) |
|
||||||
|
bitnum(input_data, 60, 15) |
|
||||||
|
bitnum(input_data, 52, 14) |
|
||||||
|
bitnum(input_data, 44, 13) |
|
||||||
|
bitnum(input_data, 36, 12) |
|
||||||
|
bitnum(input_data, 28, 11) |
|
||||||
|
bitnum(input_data, 20, 10) |
|
||||||
|
bitnum(input_data, 12, 9) |
|
||||||
|
bitnum(input_data, 4, 8) |
|
||||||
|
bitnum(input_data, 62, 7) |
|
||||||
|
bitnum(input_data, 54, 6) |
|
||||||
|
bitnum(input_data, 46, 5) |
|
||||||
|
bitnum(input_data, 38, 4) |
|
||||||
|
bitnum(input_data, 30, 3) |
|
||||||
|
bitnum(input_data, 22, 2) |
|
||||||
|
bitnum(input_data, 14, 1) |
|
||||||
|
bitnum(input_data, 6, 0) |
|
||||||
|
0
|
||||||
|
|
||||||
|
return [s0, s1]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逆初始置换
|
||||||
|
* @param {number} s0 - 32位整数
|
||||||
|
* @param {number} s1 - 32位整数
|
||||||
|
* @returns {Buffer} 逆初始置换后的 Buffer
|
||||||
|
*/
|
||||||
|
function inverse_permutation(s0, s1) {
|
||||||
|
const data = Buffer.alloc(8)
|
||||||
|
data[3] =
|
||||||
|
bitnum_intr(s1, 7, 7) |
|
||||||
|
bitnum_intr(s0, 7, 6) |
|
||||||
|
bitnum_intr(s1, 15, 5) |
|
||||||
|
bitnum_intr(s0, 15, 4) |
|
||||||
|
bitnum_intr(s1, 23, 3) |
|
||||||
|
bitnum_intr(s0, 23, 2) |
|
||||||
|
bitnum_intr(s1, 31, 1) |
|
||||||
|
bitnum_intr(s0, 31, 0) |
|
||||||
|
0
|
||||||
|
data[2] =
|
||||||
|
bitnum_intr(s1, 6, 7) |
|
||||||
|
bitnum_intr(s0, 6, 6) |
|
||||||
|
bitnum_intr(s1, 14, 5) |
|
||||||
|
bitnum_intr(s0, 14, 4) |
|
||||||
|
bitnum_intr(s1, 22, 3) |
|
||||||
|
bitnum_intr(s0, 22, 2) |
|
||||||
|
bitnum_intr(s1, 30, 1) |
|
||||||
|
bitnum_intr(s0, 30, 0) |
|
||||||
|
0
|
||||||
|
data[1] =
|
||||||
|
bitnum_intr(s1, 5, 7) |
|
||||||
|
bitnum_intr(s0, 5, 6) |
|
||||||
|
bitnum_intr(s1, 13, 5) |
|
||||||
|
bitnum_intr(s0, 13, 4) |
|
||||||
|
bitnum_intr(s1, 21, 3) |
|
||||||
|
bitnum_intr(s0, 21, 2) |
|
||||||
|
bitnum_intr(s1, 29, 1) |
|
||||||
|
bitnum_intr(s0, 29, 0) |
|
||||||
|
0
|
||||||
|
data[0] =
|
||||||
|
bitnum_intr(s1, 4, 7) |
|
||||||
|
bitnum_intr(s0, 4, 6) |
|
||||||
|
bitnum_intr(s1, 12, 5) |
|
||||||
|
bitnum_intr(s0, 12, 4) |
|
||||||
|
bitnum_intr(s1, 20, 3) |
|
||||||
|
bitnum_intr(s0, 20, 2) |
|
||||||
|
bitnum_intr(s1, 28, 1) |
|
||||||
|
bitnum_intr(s0, 28, 0) |
|
||||||
|
0
|
||||||
|
data[7] =
|
||||||
|
bitnum_intr(s1, 3, 7) |
|
||||||
|
bitnum_intr(s0, 3, 6) |
|
||||||
|
bitnum_intr(s1, 11, 5) |
|
||||||
|
bitnum_intr(s0, 11, 4) |
|
||||||
|
bitnum_intr(s1, 19, 3) |
|
||||||
|
bitnum_intr(s0, 19, 2) |
|
||||||
|
bitnum_intr(s1, 27, 1) |
|
||||||
|
bitnum_intr(s0, 27, 0) |
|
||||||
|
0
|
||||||
|
data[6] =
|
||||||
|
bitnum_intr(s1, 2, 7) |
|
||||||
|
bitnum_intr(s0, 2, 6) |
|
||||||
|
bitnum_intr(s1, 10, 5) |
|
||||||
|
bitnum_intr(s0, 10, 4) |
|
||||||
|
bitnum_intr(s1, 18, 3) |
|
||||||
|
bitnum_intr(s0, 18, 2) |
|
||||||
|
bitnum_intr(s1, 26, 1) |
|
||||||
|
bitnum_intr(s0, 26, 0) |
|
||||||
|
0
|
||||||
|
data[5] =
|
||||||
|
bitnum_intr(s1, 1, 7) |
|
||||||
|
bitnum_intr(s0, 1, 6) |
|
||||||
|
bitnum_intr(s1, 9, 5) |
|
||||||
|
bitnum_intr(s0, 9, 4) |
|
||||||
|
bitnum_intr(s1, 17, 3) |
|
||||||
|
bitnum_intr(s0, 17, 2) |
|
||||||
|
bitnum_intr(s1, 25, 1) |
|
||||||
|
bitnum_intr(s0, 25, 0) |
|
||||||
|
0
|
||||||
|
data[4] =
|
||||||
|
bitnum_intr(s1, 0, 7) |
|
||||||
|
bitnum_intr(s0, 0, 6) |
|
||||||
|
bitnum_intr(s1, 8, 5) |
|
||||||
|
bitnum_intr(s0, 8, 4) |
|
||||||
|
bitnum_intr(s1, 16, 3) |
|
||||||
|
bitnum_intr(s0, 16, 2) |
|
||||||
|
bitnum_intr(s1, 24, 1) |
|
||||||
|
bitnum_intr(s0, 24, 0) |
|
||||||
|
0
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triple-DES F函数
|
||||||
|
* @param {number} state - 输入
|
||||||
|
* @param {number[]} key - 密钥
|
||||||
|
* @returns {number} 输出
|
||||||
|
*/
|
||||||
|
function f(state, key) {
|
||||||
|
state = state | 0
|
||||||
|
const t1 =
|
||||||
|
bitnum_intl(state, 31, 0) |
|
||||||
|
(((state & 0xf0000000) >>> 1) | 0) |
|
||||||
|
bitnum_intl(state, 4, 5) |
|
||||||
|
bitnum_intl(state, 3, 6) |
|
||||||
|
(((state & 0x0f000000) >>> 3) | 0) |
|
||||||
|
bitnum_intl(state, 8, 11) |
|
||||||
|
bitnum_intl(state, 7, 12) |
|
||||||
|
(((state & 0x00f00000) >>> 5) | 0) |
|
||||||
|
bitnum_intl(state, 12, 17) |
|
||||||
|
bitnum_intl(state, 11, 18) |
|
||||||
|
(((state & 0x000f0000) >>> 7) | 0) |
|
||||||
|
bitnum_intl(state, 16, 23) |
|
||||||
|
0
|
||||||
|
|
||||||
|
const t2 =
|
||||||
|
bitnum_intl(state, 15, 0) |
|
||||||
|
(((state & 0x0000f000) << 15) | 0) |
|
||||||
|
bitnum_intl(state, 20, 5) |
|
||||||
|
bitnum_intl(state, 19, 6) |
|
||||||
|
(((state & 0x00000f00) << 13) | 0) |
|
||||||
|
bitnum_intl(state, 24, 11) |
|
||||||
|
bitnum_intl(state, 23, 12) |
|
||||||
|
(((state & 0x000000f0) << 11) | 0) |
|
||||||
|
bitnum_intl(state, 28, 17) |
|
||||||
|
bitnum_intl(state, 27, 18) |
|
||||||
|
(((state & 0x0000000f) << 9) | 0) |
|
||||||
|
bitnum_intl(state, 0, 23) |
|
||||||
|
0
|
||||||
|
|
||||||
|
const _lrgstate = [
|
||||||
|
(t1 >>> 24) & 0xff,
|
||||||
|
(t1 >>> 16) & 0xff,
|
||||||
|
(t1 >>> 8) & 0xff,
|
||||||
|
(t2 >>> 24) & 0xff,
|
||||||
|
(t2 >>> 16) & 0xff,
|
||||||
|
(t2 >>> 8) & 0xff
|
||||||
|
]
|
||||||
|
|
||||||
|
const lrgstate = _lrgstate.map((val, i) => val ^ key[i])
|
||||||
|
|
||||||
|
const newState =
|
||||||
|
(sbox[0][sbox_bit(lrgstate[0] >>> 2)] << 28) |
|
||||||
|
(sbox[1][sbox_bit(((lrgstate[0] & 0x03) << 4) | (lrgstate[1] >>> 4))] << 24) |
|
||||||
|
(sbox[2][sbox_bit(((lrgstate[1] & 0x0f) << 2) | (lrgstate[2] >>> 6))] << 20) |
|
||||||
|
(sbox[3][sbox_bit(lrgstate[2] & 0x3f)] << 16) |
|
||||||
|
(sbox[4][sbox_bit(lrgstate[3] >>> 2)] << 12) |
|
||||||
|
(sbox[5][sbox_bit(((lrgstate[3] & 0x03) << 4) | (lrgstate[4] >>> 4))] << 8) |
|
||||||
|
(sbox[6][sbox_bit(((lrgstate[4] & 0x0f) << 2) | (lrgstate[5] >>> 6))] << 4) |
|
||||||
|
sbox[7][sbox_bit(lrgstate[5] & 0x3f)] |
|
||||||
|
0
|
||||||
|
|
||||||
|
return (
|
||||||
|
bitnum_intl(newState, 15, 0) |
|
||||||
|
bitnum_intl(newState, 6, 1) |
|
||||||
|
bitnum_intl(newState, 19, 2) |
|
||||||
|
bitnum_intl(newState, 20, 3) |
|
||||||
|
bitnum_intl(newState, 28, 4) |
|
||||||
|
bitnum_intl(newState, 11, 5) |
|
||||||
|
bitnum_intl(newState, 27, 6) |
|
||||||
|
bitnum_intl(newState, 16, 7) |
|
||||||
|
bitnum_intl(newState, 0, 8) |
|
||||||
|
bitnum_intl(newState, 14, 9) |
|
||||||
|
bitnum_intl(newState, 22, 10) |
|
||||||
|
bitnum_intl(newState, 25, 11) |
|
||||||
|
bitnum_intl(newState, 4, 12) |
|
||||||
|
bitnum_intl(newState, 17, 13) |
|
||||||
|
bitnum_intl(newState, 30, 14) |
|
||||||
|
bitnum_intl(newState, 9, 15) |
|
||||||
|
bitnum_intl(newState, 1, 16) |
|
||||||
|
bitnum_intl(newState, 7, 17) |
|
||||||
|
bitnum_intl(newState, 23, 18) |
|
||||||
|
bitnum_intl(newState, 13, 19) |
|
||||||
|
bitnum_intl(newState, 31, 20) |
|
||||||
|
bitnum_intl(newState, 26, 21) |
|
||||||
|
bitnum_intl(newState, 2, 22) |
|
||||||
|
bitnum_intl(newState, 8, 23) |
|
||||||
|
bitnum_intl(newState, 18, 24) |
|
||||||
|
bitnum_intl(newState, 12, 25) |
|
||||||
|
bitnum_intl(newState, 29, 26) |
|
||||||
|
bitnum_intl(newState, 5, 27) |
|
||||||
|
bitnum_intl(newState, 21, 28) |
|
||||||
|
bitnum_intl(newState, 10, 29) |
|
||||||
|
bitnum_intl(newState, 3, 30) |
|
||||||
|
bitnum_intl(newState, 24, 31) |
|
||||||
|
0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TripleDES 加密/解密算法 (单块)
|
||||||
|
* @param {Buffer} input_data - 输入 Buffer
|
||||||
|
* @param {number[][]} key - 密钥
|
||||||
|
* @returns {Buffer} 加/解密后的 Buffer
|
||||||
|
*/
|
||||||
|
function crypt(input_data, key) {
|
||||||
|
let [s0, s1] = initial_permutation(input_data)
|
||||||
|
|
||||||
|
for (let idx = 0; idx < 15; idx++) {
|
||||||
|
const previous_s1 = s1
|
||||||
|
s1 = (f(s1, key[idx]) ^ s0) | 0
|
||||||
|
s0 = previous_s1
|
||||||
|
}
|
||||||
|
s0 = (f(s1, key[15]) ^ s0) | 0
|
||||||
|
|
||||||
|
return inverse_permutation(s0, s1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TripleDES 密钥扩展算法
|
||||||
|
* @param {Buffer} key - 密钥
|
||||||
|
* @param {number} mode - 模式 (ENCRYPT/DECRYPT)
|
||||||
|
* @returns {number[][]} 密钥扩展
|
||||||
|
*/
|
||||||
|
function key_schedule(key, mode) {
|
||||||
|
const schedule = Array.from({ length: 16 }, () => Array(6).fill(0))
|
||||||
|
const key_rnd_shift = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
|
||||||
|
const key_perm_c = [
|
||||||
|
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59,
|
||||||
|
51, 43, 35
|
||||||
|
]
|
||||||
|
const key_perm_d = [
|
||||||
|
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4,
|
||||||
|
27, 19, 11, 3
|
||||||
|
]
|
||||||
|
const key_compression = [
|
||||||
|
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51,
|
||||||
|
30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
|
||||||
|
]
|
||||||
|
|
||||||
|
let c = 0,
|
||||||
|
d = 0
|
||||||
|
for (let i = 0; i < 28; i++) {
|
||||||
|
c |= bitnum(key, key_perm_c[i], 31 - i)
|
||||||
|
d |= bitnum(key, key_perm_d[i], 31 - i)
|
||||||
|
}
|
||||||
|
c = c | 0
|
||||||
|
d = d | 0
|
||||||
|
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
const shift = key_rnd_shift[i]
|
||||||
|
c = (((c << shift) | (c >>> (28 - shift))) & 0xfffffff0) | 0
|
||||||
|
d = (((d << shift) | (d >>> (28 - shift))) & 0xfffffff0) | 0
|
||||||
|
|
||||||
|
const togen = mode === DECRYPT ? 15 - i : i
|
||||||
|
|
||||||
|
schedule[togen] = Array(6).fill(0)
|
||||||
|
|
||||||
|
for (let j = 0; j < 24; j++) {
|
||||||
|
schedule[togen][Math.floor(j / 8)] |= bitnum_intr(c, key_compression[j], 7 - (j % 8))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 24; j < 48; j++) {
|
||||||
|
schedule[togen][Math.floor(j / 8)] |= bitnum_intr(d, key_compression[j] - 27, 7 - (j % 8))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return schedule
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TripleDES 密钥设置
|
||||||
|
* @param {Buffer} key - 密钥
|
||||||
|
* @param {number} mode - 模式
|
||||||
|
* @returns {number[][][]} 密钥设置
|
||||||
|
*/
|
||||||
|
function tripledes_key_setup(key, mode) {
|
||||||
|
if (mode === ENCRYPT) {
|
||||||
|
return [
|
||||||
|
key_schedule(key.slice(0, 8), ENCRYPT),
|
||||||
|
key_schedule(key.slice(8, 16), DECRYPT),
|
||||||
|
key_schedule(key.slice(16, 24), ENCRYPT)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
key_schedule(key.slice(16, 24), DECRYPT),
|
||||||
|
key_schedule(key.slice(8, 16), ENCRYPT),
|
||||||
|
key_schedule(key.slice(0, 8), DECRYPT)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TripleDES 加密/解密算法 (完整)
|
||||||
|
* @param {Buffer} data - 输入 Buffer
|
||||||
|
* @param {number[][][]} key - 密钥
|
||||||
|
* @returns {Buffer} 加/解密后的 Buffer
|
||||||
|
*/
|
||||||
|
function tripledes_crypt(data, key) {
|
||||||
|
let result = data
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
result = crypt(result, key[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QRC解密主函数
|
||||||
|
* @param {string | Buffer} encrypted_qrc - 加密的QRC内容 (十六进制字符串或Buffer)
|
||||||
|
* @returns {string} 解密后的UTF-8字符串
|
||||||
|
*/
|
||||||
|
function qrc_decrypt(encrypted_qrc) {
|
||||||
|
if (!encrypted_qrc) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
let input_buffer
|
||||||
|
if (typeof encrypted_qrc === 'string') {
|
||||||
|
input_buffer = Buffer.from(encrypted_qrc, 'hex')
|
||||||
|
} else if (Buffer.isBuffer(encrypted_qrc)) {
|
||||||
|
input_buffer = encrypted_qrc
|
||||||
|
} else {
|
||||||
|
throw new Error('无效的加密数据类型')
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const decrypted_chunks = []
|
||||||
|
const key = Buffer.from('!@#)(*$%123ZXC!@!@#)(NHL')
|
||||||
|
const schedule = tripledes_key_setup(key, DECRYPT)
|
||||||
|
|
||||||
|
for (let i = 0; i < input_buffer.length; i += 8) {
|
||||||
|
const chunk = input_buffer.slice(i, i + 8)
|
||||||
|
if (chunk.length < 8) {
|
||||||
|
// 如果最后一块不足8字节,DES无法处理,但QRC格式应该是8的倍数
|
||||||
|
// 这里可以根据实际情况决定如何处理,例如抛出错误或填充
|
||||||
|
// 根据原始代码行为,这里假设输入总是8字节的倍数
|
||||||
|
console.warn('警告: 数据末尾存在不足8字节的块,可能导致解密不完整。')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
decrypted_chunks.push(tripledes_crypt(chunk, schedule))
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = Buffer.concat(decrypted_chunks)
|
||||||
|
const decompressed = zlib.unzipSync(data)
|
||||||
|
return decompressed.toString('utf-8')
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`解密失败: ${e.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出主函数
|
||||||
|
return qrc_decrypt
|
||||||
|
}
|
||||||
9
src/renderer/components.d.ts
vendored
9
src/renderer/components.d.ts
vendored
@@ -26,19 +26,28 @@ declare module 'vue' {
|
|||||||
ShaderBackground: typeof import('./src/components/Play/ShaderBackground.vue')['default']
|
ShaderBackground: typeof import('./src/components/Play/ShaderBackground.vue')['default']
|
||||||
SongVirtualList: typeof import('./src/components/Music/SongVirtualList.vue')['default']
|
SongVirtualList: typeof import('./src/components/Music/SongVirtualList.vue')['default']
|
||||||
TAlert: typeof import('tdesign-vue-next')['Alert']
|
TAlert: typeof import('tdesign-vue-next')['Alert']
|
||||||
|
TAside: typeof import('tdesign-vue-next')['Aside']
|
||||||
|
TBadge: typeof import('tdesign-vue-next')['Badge']
|
||||||
TButton: typeof import('tdesign-vue-next')['Button']
|
TButton: typeof import('tdesign-vue-next')['Button']
|
||||||
|
TCard: typeof import('tdesign-vue-next')['Card']
|
||||||
|
TContent: typeof import('tdesign-vue-next')['Content']
|
||||||
TDialog: typeof import('tdesign-vue-next')['Dialog']
|
TDialog: typeof import('tdesign-vue-next')['Dialog']
|
||||||
|
TDivider: typeof import('tdesign-vue-next')['Divider']
|
||||||
TDropdown: typeof import('tdesign-vue-next')['Dropdown']
|
TDropdown: typeof import('tdesign-vue-next')['Dropdown']
|
||||||
TForm: typeof import('tdesign-vue-next')['Form']
|
TForm: typeof import('tdesign-vue-next')['Form']
|
||||||
TFormItem: typeof import('tdesign-vue-next')['FormItem']
|
TFormItem: typeof import('tdesign-vue-next')['FormItem']
|
||||||
ThemeSelector: typeof import('./src/components/ThemeSelector.vue')['default']
|
ThemeSelector: typeof import('./src/components/ThemeSelector.vue')['default']
|
||||||
TIcon: typeof import('tdesign-vue-next')['Icon']
|
TIcon: typeof import('tdesign-vue-next')['Icon']
|
||||||
|
TImage: typeof import('tdesign-vue-next')['Image']
|
||||||
TInput: typeof import('tdesign-vue-next')['Input']
|
TInput: typeof import('tdesign-vue-next')['Input']
|
||||||
TitleBarControls: typeof import('./src/components/TitleBarControls.vue')['default']
|
TitleBarControls: typeof import('./src/components/TitleBarControls.vue')['default']
|
||||||
|
TLayout: typeof import('tdesign-vue-next')['Layout']
|
||||||
TLoading: typeof import('tdesign-vue-next')['Loading']
|
TLoading: typeof import('tdesign-vue-next')['Loading']
|
||||||
TRadioButton: typeof import('tdesign-vue-next')['RadioButton']
|
TRadioButton: typeof import('tdesign-vue-next')['RadioButton']
|
||||||
TRadioGroup: typeof import('tdesign-vue-next')['RadioGroup']
|
TRadioGroup: typeof import('tdesign-vue-next')['RadioGroup']
|
||||||
TSlider: typeof import('tdesign-vue-next')['Slider']
|
TSlider: typeof import('tdesign-vue-next')['Slider']
|
||||||
|
TSwitch: typeof import('tdesign-vue-next')['Switch']
|
||||||
|
TTag: typeof import('tdesign-vue-next')['Tag']
|
||||||
TTextarea: typeof import('tdesign-vue-next')['Textarea']
|
TTextarea: typeof import('tdesign-vue-next')['Textarea']
|
||||||
TTooltip: typeof import('tdesign-vue-next')['Tooltip']
|
TTooltip: typeof import('tdesign-vue-next')['Tooltip']
|
||||||
UpdateExample: typeof import('./src/components/UpdateExample.vue')['default']
|
UpdateExample: typeof import('./src/components/UpdateExample.vue')['default']
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ import { shouldUseBlackText } from '@renderer/utils/color/contrastColor'
|
|||||||
import { ControlAudioStore } from '@renderer/store/ControlAudio'
|
import { ControlAudioStore } from '@renderer/store/ControlAudio'
|
||||||
import { Fullscreen1Icon, FullscreenExit1Icon, ChevronDownIcon } from 'tdesign-icons-vue-next'
|
import { Fullscreen1Icon, FullscreenExit1Icon, ChevronDownIcon } from 'tdesign-icons-vue-next'
|
||||||
// 直接从包路径导入,避免 WebAssembly 导入问题
|
// 直接从包路径导入,避免 WebAssembly 导入问题
|
||||||
import { parseYrc, parseLrc, parseTTML } from '@applemusic-like-lyrics/lyric/pkg/amll_lyric.js'
|
import {
|
||||||
|
parseYrc,
|
||||||
|
parseLrc,
|
||||||
|
parseTTML,
|
||||||
|
parseQrc
|
||||||
|
} from '@applemusic-like-lyrics/lyric/pkg/amll_lyric.js'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
@@ -151,7 +156,11 @@ watch(
|
|||||||
if (lyricData.crlyric) {
|
if (lyricData.crlyric) {
|
||||||
// 使用逐字歌词
|
// 使用逐字歌词
|
||||||
lyricText = lyricData.crlyric
|
lyricText = lyricData.crlyric
|
||||||
parsedLyrics = parseYrc(lyricText)
|
if (source === 'tx') {
|
||||||
|
parsedLyrics = parseQrc(lyricText)
|
||||||
|
} else {
|
||||||
|
parsedLyrics = parseYrc(lyricText)
|
||||||
|
}
|
||||||
console.log(`使用${source}逐字歌词`, parsedLyrics)
|
console.log(`使用${source}逐字歌词`, parsedLyrics)
|
||||||
} else if (lyricData.lyric) {
|
} else if (lyricData.lyric) {
|
||||||
lyricText = lyricData.lyric
|
lyricText = lyricData.lyric
|
||||||
|
|||||||
Reference in New Issue
Block a user