mirror of
https://github.com/timeshiftsauce/CeruMusic.git
synced 2025-11-25 19:37:38 +08:00
feat(plugin service): add check log support
This commit is contained in:
@@ -157,6 +157,15 @@ ipcMain.handle('service-plugin-loadAllPlugins', async (): Promise<any> => {
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('service-plugin-getPluginLog', async (_, pluginId): Promise<any> => {
|
||||
try {
|
||||
return await pluginService.getPluginLog(pluginId)
|
||||
} catch (error: any) {
|
||||
console.error('Error getting plugin log:', error)
|
||||
return { error: error.message }
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('service-plugin-uninstallPlugin', async (_, pluginId): Promise<any> => {
|
||||
try {
|
||||
return await pluginService.uninstallPlugin(pluginId)
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getAppDirPath } from '../../utils/path'
|
||||
|
||||
import CeruMusicPluginHost from './manager/CeruMusicPluginHost'
|
||||
import convertEventDrivenPlugin from './manager/converter-event-driven'
|
||||
import Logger from './logger'
|
||||
import Logger, { getLog } from './logger'
|
||||
|
||||
// 导出类型以解决TypeScript错误
|
||||
|
||||
@@ -84,7 +84,7 @@ const pluginService = {
|
||||
|
||||
// 重新加载插件以确保正确初始化
|
||||
const ceruPluginManager = new CeruMusicPluginHost()
|
||||
await ceruPluginManager.loadPlugin(filePath, new Logger('log/' + pluginId))
|
||||
await ceruPluginManager.loadPlugin(filePath, new Logger(pluginId))
|
||||
|
||||
// 将插件添加到已加载插件列表
|
||||
loadedPlugins[pluginId] = ceruPluginManager
|
||||
@@ -221,6 +221,10 @@ const pluginService = {
|
||||
supportedSources: ceruPluginManager.getSupportedSources()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
async getPluginLog(pluginId: string) {
|
||||
return await getLog(pluginId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,35 +1,103 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import fsPromise from 'fs/promises'
|
||||
|
||||
import { getAppDirPath } from '../../utils/path'
|
||||
import { remove_empty_strings } from '../../utils/array'
|
||||
|
||||
function getLogPath(pluginId: string): string {
|
||||
return path.join(getAppDirPath(), 'plugin', 'logs', `${pluginId}.txt`)
|
||||
}
|
||||
|
||||
const fileLock: Record<string, Promise<any> | undefined> = {}
|
||||
const waitNum: Record<string, number | undefined> = {}
|
||||
|
||||
enum WriteMode {
|
||||
APPEND,
|
||||
OVERWRITE
|
||||
}
|
||||
|
||||
function selectWriteFunc(mode: WriteMode): (...args: any[]) => Promise<any> {
|
||||
switch (mode) {
|
||||
case WriteMode.APPEND:
|
||||
return async (filePath: string, content: string): Promise<void> => {
|
||||
await fsPromise.appendFile(filePath, content)
|
||||
}
|
||||
case WriteMode.OVERWRITE:
|
||||
return async (filePath: string, content: string): Promise<void> => {
|
||||
await fsPromise.writeFile(filePath, content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function writeLog(logPath: string, content: string, mode: WriteMode): Promise<void> {
|
||||
const writeFunc: (filePath: string, content: string) => Promise<void> = selectWriteFunc(mode)
|
||||
return await add_promise(logPath, writeFunc(logPath, content))
|
||||
}
|
||||
|
||||
async function add_promise<T>(key: string, promise: Promise<T>): Promise<T> {
|
||||
const promiseDeleteCheck = async (promise: Promise<T>): Promise<T> => {
|
||||
waitNum[key] = waitNum[key] ? waitNum[key] + 1 : 1
|
||||
try {
|
||||
return await promise
|
||||
} finally {
|
||||
waitNum[key] -= 1
|
||||
if (waitNum[key] === 0) {
|
||||
delete fileLock[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fileLock[key]) {
|
||||
fileLock[key] = promiseDeleteCheck(promise)
|
||||
} else {
|
||||
fileLock[key] = promiseDeleteCheck(
|
||||
(fileLock[key] as Promise<any>).then(async () => {
|
||||
return await promise
|
||||
})
|
||||
)
|
||||
}
|
||||
return fileLock[key]
|
||||
}
|
||||
|
||||
class Logger {
|
||||
private readonly logFilePath: string
|
||||
constructor(pluginId: string) {
|
||||
this.logFilePath = path.join(getAppDirPath(), pluginId, 'log.txt')
|
||||
this.logFilePath = getLogPath(pluginId)
|
||||
fsPromise.mkdir(path.dirname(this.logFilePath), { recursive: true }).then()
|
||||
}
|
||||
|
||||
log(...args: any[]) {
|
||||
log(...args: any[]): void {
|
||||
this.write(`log ${args.join(' ')}`)
|
||||
}
|
||||
|
||||
info(...args: any[]) {
|
||||
info(...args: any[]): void {
|
||||
this.write(`info ${args.join(' ')}`)
|
||||
}
|
||||
|
||||
warn(...args: any[]) {
|
||||
warn(...args: any[]): void {
|
||||
this.write(`warn ${args.join(' ')}`)
|
||||
}
|
||||
|
||||
error(...args: any[]) {
|
||||
error(...args: any[]): void {
|
||||
this.write(`error ${args.join(' ')}`)
|
||||
}
|
||||
|
||||
private write(msg: string) {
|
||||
fs.appendFileSync(this.logFilePath, `${msg}\n`)
|
||||
private write(msg: string): void {
|
||||
writeLog(this.logFilePath, msg, WriteMode.APPEND).then()
|
||||
}
|
||||
}
|
||||
|
||||
async function getLog(pluginId: string) {
|
||||
const logFilePath: string = getLogPath(pluginId)
|
||||
return await add_promise(
|
||||
logFilePath,
|
||||
(async (): Promise<string[]> => {
|
||||
const content: string = await fsPromise.readFile(logFilePath, 'utf-8')
|
||||
const last200Lines: string[] = remove_empty_strings(content.split('\n')).slice(-200)
|
||||
await selectWriteFunc(WriteMode.OVERWRITE)(logFilePath, last200Lines.join('\n'))
|
||||
return last200Lines
|
||||
})()
|
||||
)
|
||||
}
|
||||
|
||||
export default Logger
|
||||
export { Logger, getLog }
|
||||
|
||||
5
src/main/utils/array.ts
Normal file
5
src/main/utils/array.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
function remove_empty_strings(arr: string[]) {
|
||||
return arr.filter((item: string): boolean => item !== '')
|
||||
}
|
||||
|
||||
export { remove_empty_strings }
|
||||
@@ -35,7 +35,8 @@ const api = {
|
||||
getPluginById: (id: string) => ipcRenderer.invoke('service-plugin-getPluginById', id),
|
||||
loadAllPlugins: () => ipcRenderer.invoke('service-plugin-loadAllPlugins'),
|
||||
uninstallPlugin: (pluginId: string) =>
|
||||
ipcRenderer.invoke('service-plugin-uninstallPlugin', pluginId)
|
||||
ipcRenderer.invoke('service-plugin-uninstallPlugin', pluginId),
|
||||
getPluginLog: (pluginId: string) => ipcRenderer.invoke('service-plugin-getPluginLog', pluginId)
|
||||
},
|
||||
|
||||
ai: {
|
||||
|
||||
Reference in New Issue
Block a user