Compare commits
2 Commits
ab9222811e
...
c3a1fbd24d
Author | SHA1 | Date |
---|---|---|
nullptr-0 | c3a1fbd24d | |
nullptr-0 | c972b66aa2 |
|
@ -14,7 +14,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="歌手">
|
<el-table-column label="歌手">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<p>{{ scope.row.artist }}</p>
|
<p>{{ scope.row.artist.join('/') }}</p>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="专辑">
|
<el-table-column label="专辑">
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe('decrypt/joox', () => {
|
||||||
title: 'unused',
|
title: 'unused',
|
||||||
album: 'unused',
|
album: 'unused',
|
||||||
blob: blob,
|
blob: blob,
|
||||||
artist: 'unused',
|
artist: ['unused'],
|
||||||
imgUrl: 'https://example.unlock-music.dev/',
|
imgUrl: 'https://example.unlock-music.dev/',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export interface DecryptResult {
|
export interface DecryptResult {
|
||||||
title: string;
|
title: string;
|
||||||
album?: string;
|
album?: string;
|
||||||
artist?: string;
|
artist?: string[];
|
||||||
|
|
||||||
mime: string;
|
mime: string;
|
||||||
ext: string;
|
ext: string;
|
||||||
|
|
|
@ -43,7 +43,7 @@ export async function Decrypt(file: File, raw_filename: string, raw_ext: string)
|
||||||
const mime = AudioMimeType[ext];
|
const mime = AudioMimeType[ext];
|
||||||
let musicBlob = new Blob([musicDecoded], { type: mime });
|
let musicBlob = new Blob([musicDecoded], { type: mime });
|
||||||
const musicMeta = await metaParseBlob(musicBlob);
|
const musicMeta = await metaParseBlob(musicBlob);
|
||||||
const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, String(musicMeta.common.artists || musicMeta.common.artist || ""));
|
const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artists || [musicMeta.common.artist || ""]);
|
||||||
return {
|
return {
|
||||||
album: musicMeta.common.album,
|
album: musicMeta.common.album,
|
||||||
picture: GetCoverFromFile(musicMeta),
|
picture: GetCoverFromFile(musicMeta),
|
||||||
|
|
|
@ -42,7 +42,7 @@ export async function Decrypt(file: File, raw_filename: string, _: string): Prom
|
||||||
let musicBlob = new Blob([audioData], { type: mime });
|
let musicBlob = new Blob([audioData], { type: mime });
|
||||||
|
|
||||||
const musicMeta = await metaParseBlob(musicBlob);
|
const musicMeta = await metaParseBlob(musicBlob);
|
||||||
const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, String(musicMeta.common.artists || musicMeta.common.artist || ""));
|
const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artists || [musicMeta.common.artist || ""]);
|
||||||
return {
|
return {
|
||||||
album: musicMeta.common.album,
|
album: musicMeta.common.album,
|
||||||
picture: GetCoverFromFile(musicMeta),
|
picture: GetCoverFromFile(musicMeta),
|
||||||
|
|
|
@ -175,7 +175,6 @@ class NcmDecrypt {
|
||||||
|
|
||||||
if (artists.length === 0 && info.artist) {
|
if (artists.length === 0 && info.artist) {
|
||||||
artists = info.artist
|
artists = info.artist
|
||||||
.split(',')
|
|
||||||
.map((val) => val.trim())
|
.map((val) => val.trim())
|
||||||
.filter((val) => val != '');
|
.filter((val) => val != '');
|
||||||
}
|
}
|
||||||
|
@ -219,7 +218,7 @@ class NcmDecrypt {
|
||||||
if (!this.newMeta || !this.blob) throw Error('bad sequence');
|
if (!this.newMeta || !this.blob) throw Error('bad sequence');
|
||||||
return {
|
return {
|
||||||
title: this.newMeta.title,
|
title: this.newMeta.title,
|
||||||
artist: this.newMeta.artists?.join('; '),
|
artist: this.newMeta.artists,
|
||||||
ext: this.format,
|
ext: this.format,
|
||||||
album: this.newMeta.album,
|
album: this.newMeta.album,
|
||||||
picture: this.image?.url,
|
picture: this.image?.url,
|
||||||
|
|
|
@ -13,7 +13,7 @@ export async function Decrypt(file: Blob, raw_filename: string, raw_ext: string)
|
||||||
const ext = SniffAudioExt(buffer, raw_ext);
|
const ext = SniffAudioExt(buffer, raw_ext);
|
||||||
if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] });
|
if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] });
|
||||||
const tag = await metaParseBlob(file);
|
const tag = await metaParseBlob(file);
|
||||||
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, String(tag.common.artists || tag.common.artist || ""));
|
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, tag.common.artists || [tag.common.artist || ""]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
|
|
|
@ -43,7 +43,7 @@ export async function Decrypt(file: Blob, raw_filename: string, raw_ext: string)
|
||||||
throw '不支持的QQ音乐缓存格式';
|
throw '不支持的QQ音乐缓存格式';
|
||||||
}
|
}
|
||||||
const tag = await metaParseBlob(audioBlob);
|
const tag = await metaParseBlob(audioBlob);
|
||||||
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, String(tag.common.artists || tag.common.artist || ""));
|
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, tag.common.artists || [tag.common.artist || ""]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
|
|
|
@ -17,7 +17,7 @@ export async function Decrypt(
|
||||||
if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] });
|
if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] });
|
||||||
}
|
}
|
||||||
const tag = await metaParseBlob(file);
|
const tag = await metaParseBlob(file);
|
||||||
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, String(tag.common.artists || tag.common.artist || ''));
|
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, tag.common.artists || [tag.common.artist || '']);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
|
|
|
@ -80,13 +80,13 @@ export function GetCoverFromFile(metadata: IAudioMetadata): string {
|
||||||
|
|
||||||
export interface IMusicMetaBasic {
|
export interface IMusicMetaBasic {
|
||||||
title: string;
|
title: string;
|
||||||
artist?: string;
|
artist?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GetMetaFromFile(
|
export function GetMetaFromFile(
|
||||||
filename: string,
|
filename: string,
|
||||||
exist_title?: string,
|
exist_title?: string,
|
||||||
exist_artist?: string,
|
exist_artist?: string[],
|
||||||
separator = '-',
|
separator = '-',
|
||||||
): IMusicMetaBasic {
|
): IMusicMetaBasic {
|
||||||
const meta: IMusicMetaBasic = { title: exist_title ?? '', artist: exist_artist };
|
const meta: IMusicMetaBasic = { title: exist_title ?? '', artist: exist_artist };
|
||||||
|
@ -94,7 +94,7 @@ export function GetMetaFromFile(
|
||||||
const items = filename.split(separator);
|
const items = filename.split(separator);
|
||||||
if (items.length > 1) {
|
if (items.length > 1) {
|
||||||
//由文件名和原metadata共同决定歌手tag(有时从文件名看有多个歌手,而metadata只有一个)
|
//由文件名和原metadata共同决定歌手tag(有时从文件名看有多个歌手,而metadata只有一个)
|
||||||
if (!meta.artist || meta.artist.split(split_regex).length < items[0].trim().split(split_regex).length) meta.artist = items[0].trim();
|
if (!meta.artist || meta.artist.length < items[0].trim().split(split_regex).length) meta.artist = items[0].trim().split(split_regex);
|
||||||
if (!meta.title) meta.title = items[1].trim();
|
if (!meta.title) meta.title = items[1].trim();
|
||||||
} else if (items.length === 1) {
|
} else if (items.length === 1) {
|
||||||
if (!meta.title) meta.title = items[0].trim();
|
if (!meta.title) meta.title = items[0].trim();
|
||||||
|
|
|
@ -20,7 +20,7 @@ export async function Decrypt(file: File, raw_filename: string, raw_ext: string)
|
||||||
|
|
||||||
const musicMeta = await metaParseBlob(musicBlob);
|
const musicMeta = await metaParseBlob(musicBlob);
|
||||||
|
|
||||||
const info = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artist);
|
const info = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artists || [musicMeta.common.artist || '']);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
picture: '',
|
picture: '',
|
||||||
|
|
|
@ -49,7 +49,7 @@ export async function Decrypt(file: File, raw_filename: string, raw_ext: string)
|
||||||
const { title, artist } = GetMetaFromFile(
|
const { title, artist } = GetMetaFromFile(
|
||||||
raw_filename,
|
raw_filename,
|
||||||
musicMeta.common.title,
|
musicMeta.common.title,
|
||||||
String(musicMeta.common.artists || musicMeta.common.artist || ""),
|
musicMeta.common.artists || [musicMeta.common.artist || ""],
|
||||||
raw_filename.indexOf('_') === -1 ? '-' : '_',
|
raw_filename.indexOf('_') === -1 ? '-' : '_',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { getQMImageURLFromPMID, queryAlbumCover, querySongInfoById } from '@/uti
|
||||||
|
|
||||||
interface MetaResult {
|
interface MetaResult {
|
||||||
title: string;
|
title: string;
|
||||||
artist: string;
|
artist: string[];
|
||||||
album: string;
|
album: string;
|
||||||
imgUrl: string;
|
imgUrl: string;
|
||||||
blob: Blob;
|
blob: Blob;
|
||||||
|
@ -44,6 +44,7 @@ export async function extractQQMusicMeta(
|
||||||
musicMeta.common.artist = '';
|
musicMeta.common.artist = '';
|
||||||
if (!musicMeta.common.artists) {
|
if (!musicMeta.common.artists) {
|
||||||
musicMeta.common.artist = fromGBK(musicMeta.common.artist);
|
musicMeta.common.artist = fromGBK(musicMeta.common.artist);
|
||||||
|
musicMeta.common.artists = [musicMeta.common.artist];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
musicMeta.common.artist = musicMeta.common.artists.map(fromGBK).join();
|
musicMeta.common.artist = musicMeta.common.artists.map(fromGBK).join();
|
||||||
|
@ -61,8 +62,8 @@ export async function extractQQMusicMeta(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const info = GetMetaFromFile(name, musicMeta.common.title, musicMeta.common.artist);
|
const info = GetMetaFromFile(name, musicMeta.common.title, musicMeta.common.artists);
|
||||||
info.artist = info.artist || '';
|
info.artist = info.artist || [''];
|
||||||
|
|
||||||
let imageURL = GetCoverFromFile(musicMeta);
|
let imageURL = GetCoverFromFile(musicMeta);
|
||||||
if (!imageURL) {
|
if (!imageURL) {
|
||||||
|
@ -76,7 +77,7 @@ export async function extractQQMusicMeta(
|
||||||
imgUrl: imageURL,
|
imgUrl: imageURL,
|
||||||
blob: await writeMetaToAudioFile({
|
blob: await writeMetaToAudioFile({
|
||||||
title: info.title,
|
title: info.title,
|
||||||
artists: info.artist.split(split_regex),
|
artists: info.artist,
|
||||||
ext,
|
ext,
|
||||||
imageURL,
|
imageURL,
|
||||||
musicMeta,
|
musicMeta,
|
||||||
|
@ -97,7 +98,7 @@ async function fetchMetadataFromSongId(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: info.track_info.title,
|
title: info.track_info.title,
|
||||||
artist: artists.join(','),
|
artist: artists,
|
||||||
album: info.track_info.album.name,
|
album: info.track_info.album.name,
|
||||||
imgUrl: imageURL,
|
imgUrl: imageURL,
|
||||||
|
|
||||||
|
@ -112,9 +113,9 @@ async function fetchMetadataFromSongId(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getCoverImage(title: string, artist?: string, album?: string): Promise<string> {
|
async function getCoverImage(title: string, artist?: string[], album?: string): Promise<string> {
|
||||||
try {
|
try {
|
||||||
const data = await queryAlbumCover(title, artist, album);
|
const data = await queryAlbumCover(title, artist?.join(), album);
|
||||||
return getQMImageURLFromPMID(data.Id, data.Type);
|
return getQMImageURLFromPMID(data.Id, data.Type);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
|
|
|
@ -217,10 +217,13 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
async editFile(data) {
|
async editFile(data) {
|
||||||
this.editing_data = data;
|
this.editing_data.picture = data.picture;
|
||||||
const musicMeta = await metaParseBlob(this.editing_data.blob);
|
this.editing_data.title = data.title
|
||||||
|
this.editing_data.artist = data.artist.join()
|
||||||
|
this.editing_data.album = data.album
|
||||||
|
const musicMeta = await metaParseBlob(data.blob);
|
||||||
this.editing_data.albumartist = musicMeta.common.albumartist || '';
|
this.editing_data.albumartist = musicMeta.common.albumartist || '';
|
||||||
this.editing_data.genre = musicMeta.common.genre?.toString() || '';
|
this.editing_data.genre = musicMeta.common.genre?.join() || '';
|
||||||
this.showEditDialog = true;
|
this.showEditDialog = true;
|
||||||
},
|
},
|
||||||
async saveFile(data) {
|
async saveFile(data) {
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
"scripthost"
|
"scripthost"
|
||||||
],
|
],
|
||||||
"resolveJsonModule": true
|
"resolveJsonModule": true,
|
||||||
|
"outDir": "build"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
"tests/**/*.tsx"
|
"tests/**/*.tsx"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules",
|
||||||
|
"build/**/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue