mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-23 15:47:23 +08:00
Merge branch 'main' into feat/search-suggestions
This commit is contained in:
+101
-11
@@ -9,7 +9,8 @@ import * as mm from 'music-metadata';
|
||||
import * as NodeID3 from 'node-id3';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
import { FlacTagMap, writeFlacTags } from 'flac-tagger';
|
||||
import sharp from 'sharp';
|
||||
import { getStore } from './config';
|
||||
|
||||
const MAX_CONCURRENT_DOWNLOADS = 3;
|
||||
@@ -275,6 +276,39 @@ export function initializeFileManager() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 处理导入自定义API插件的请求
|
||||
ipcMain.handle('import-custom-api-plugin', async () => {
|
||||
const result = await dialog.showOpenDialog({
|
||||
title: '选择自定义音源配置文件',
|
||||
filters: [{ name: 'JSON Files', extensions: ['json'] }],
|
||||
properties: ['openFile']
|
||||
});
|
||||
|
||||
if (result.canceled || result.filePaths.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const filePath = result.filePaths[0];
|
||||
try {
|
||||
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
||||
|
||||
// 基础验证,确保它是个合法的JSON并且包含关键字段
|
||||
const pluginData = JSON.parse(fileContent);
|
||||
if (!pluginData.name || !pluginData.apiUrl) {
|
||||
throw new Error('无效的插件文件,缺少 name 或 apiUrl 字段。');
|
||||
}
|
||||
|
||||
return {
|
||||
name: pluginData.name,
|
||||
content: fileContent // 返回完整的JSON字符串
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.error('读取或解析插件文件失败:', error);
|
||||
// 向渲染进程抛出错误,以便UI可以显示提示
|
||||
throw new Error(`文件读取或解析失败: ${error.message}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +420,7 @@ async function downloadMusic(
|
||||
let formattedFilename = filename;
|
||||
if (songInfo) {
|
||||
// 准备替换变量
|
||||
const artistName = songInfo.ar?.map((a: any) => a.name).join('/') || '未知艺术家';
|
||||
const artistName = songInfo.ar?.map((a: any) => a.name).join('、') || '未知艺术家';
|
||||
const songName = songInfo.name || filename;
|
||||
const albumName = songInfo.al?.name || '未知专辑';
|
||||
|
||||
@@ -576,8 +610,39 @@ async function downloadMusic(
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
// 获取封面图片的buffer
|
||||
coverImageBuffer = Buffer.from(coverResponse.data);
|
||||
const originalCoverBuffer = Buffer.from(coverResponse.data);
|
||||
const TWO_MB = 2 * 1024 * 1024;
|
||||
// 检查图片大小是否超过2MB
|
||||
if (originalCoverBuffer.length > TWO_MB) {
|
||||
const originalSizeMB = (originalCoverBuffer.length / (1024 * 1024)).toFixed(2);
|
||||
console.log(`封面图大于2MB (${originalSizeMB} MB),开始压缩...`);
|
||||
try {
|
||||
// 使用 sharp 进行压缩
|
||||
coverImageBuffer = await sharp(originalCoverBuffer)
|
||||
.resize({
|
||||
width: 1600,
|
||||
height: 1600,
|
||||
fit: 'inside',
|
||||
withoutEnlargement: true
|
||||
})
|
||||
.jpeg({
|
||||
quality: 80,
|
||||
mozjpeg: true
|
||||
})
|
||||
.toBuffer();
|
||||
|
||||
const compressedSizeMB = (coverImageBuffer.length / (1024 * 1024)).toFixed(2);
|
||||
console.log(`封面图压缩完成,新大小: ${compressedSizeMB} MB`);
|
||||
|
||||
} catch (compressionError) {
|
||||
console.error('封面图压缩失败,将使用原图:', compressionError);
|
||||
coverImageBuffer = originalCoverBuffer; // 如果压缩失败,则回退使用原始图片
|
||||
}
|
||||
} else {
|
||||
// 如果图片不大于2MB,直接使用原图
|
||||
coverImageBuffer = originalCoverBuffer;
|
||||
}
|
||||
|
||||
console.log('封面已准备好,将写入元数据');
|
||||
}
|
||||
}
|
||||
@@ -588,7 +653,7 @@ async function downloadMusic(
|
||||
|
||||
const fileFormat = fileExtension.toLowerCase();
|
||||
const artistNames =
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('/ ') || '未知艺术家';
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('、') || '未知艺术家';
|
||||
|
||||
// 根据文件类型处理元数据
|
||||
if (['.mp3'].includes(fileFormat)) {
|
||||
@@ -598,7 +663,7 @@ async function downloadMusic(
|
||||
NodeID3.removeTags(finalFilePath);
|
||||
|
||||
const tags = {
|
||||
title: filename,
|
||||
title: songInfo?.name,
|
||||
artist: artistNames,
|
||||
TPE1: artistNames,
|
||||
TPE2: artistNames,
|
||||
@@ -634,10 +699,35 @@ async function downloadMusic(
|
||||
} catch (err) {
|
||||
console.error('Error writing ID3 tags:', err);
|
||||
}
|
||||
} else {
|
||||
// 对于非MP3文件,使用music-metadata来写入元数据可能需要专门的库
|
||||
// 或者根据不同文件类型使用专用工具,暂时只记录但不处理
|
||||
console.log(`文件类型 ${fileFormat} 不支持使用NodeID3写入标签,跳过元数据写入`);
|
||||
} else if (['.flac'].includes(fileFormat)) {
|
||||
try {
|
||||
const tagMap: FlacTagMap = {
|
||||
TITLE: songInfo?.name,
|
||||
ARTIST: artistNames,
|
||||
ALBUM: songInfo?.al?.name || songInfo?.song?.album?.name || songInfo?.name || filename,
|
||||
LYRICS: lyricsContent || '',
|
||||
TRACKNUMBER: songInfo?.no ? String(songInfo.no) : undefined,
|
||||
DATE: songInfo?.publishTime
|
||||
? new Date(songInfo.publishTime).getFullYear().toString()
|
||||
: undefined
|
||||
};
|
||||
|
||||
await writeFlacTags(
|
||||
{
|
||||
tagMap,
|
||||
picture: coverImageBuffer
|
||||
? {
|
||||
buffer: coverImageBuffer,
|
||||
mime: 'image/jpeg'
|
||||
}
|
||||
: undefined
|
||||
},
|
||||
finalFilePath
|
||||
);
|
||||
console.log('FLAC tags written successfully');
|
||||
} catch (err) {
|
||||
console.error('Error writing FLAC tags:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存下载信息
|
||||
@@ -683,7 +773,7 @@ async function downloadMusic(
|
||||
// 发送桌面通知
|
||||
try {
|
||||
const artistNames =
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('/') ||
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('、') ||
|
||||
'未知艺术家';
|
||||
const notification = new Notification({
|
||||
title: '下载完成',
|
||||
|
||||
Reference in New Issue
Block a user