2026-02-03 12:59:04 +08:00
|
|
|
import { app } from 'electron'
|
|
|
|
|
import path from 'path'
|
|
|
|
|
import fs from 'fs'
|
|
|
|
|
import { createRequire } from 'node:module'
|
2026-02-06 14:50:33 +08:00
|
|
|
import { MessagePlugin } from "tdesign-vue-next";
|
2026-02-03 12:59:04 +08:00
|
|
|
|
|
|
|
|
const require = createRequire(import.meta.url)
|
|
|
|
|
|
|
|
|
|
export interface UrlResponse {
|
|
|
|
|
success: boolean
|
|
|
|
|
url?: string
|
|
|
|
|
error?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PluginModule = {
|
2026-02-05 23:44:51 +08:00
|
|
|
getUrl?: (id: string, quality: string) => Promise<string> | string,
|
|
|
|
|
musicSearch?: {
|
|
|
|
|
search: (query: string, page: number, limit: number) => Promise<any> | any
|
2026-02-06 14:50:33 +08:00
|
|
|
},
|
|
|
|
|
getLyric?: (id: string) => Promise<string> | object
|
2026-02-03 12:59:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class PluginSystem {
|
|
|
|
|
private pluginId: string
|
|
|
|
|
private plugin: PluginModule | null = null
|
|
|
|
|
constructor(pluginId: string) {
|
|
|
|
|
this.pluginId = pluginId
|
|
|
|
|
this.loadPlugin()
|
|
|
|
|
}
|
2026-02-05 23:44:51 +08:00
|
|
|
|
2026-02-03 12:59:04 +08:00
|
|
|
private loadPlugin() {
|
|
|
|
|
try {
|
|
|
|
|
const pluginPath = path.join(
|
|
|
|
|
app.getPath('userData'),
|
|
|
|
|
'plugins',
|
|
|
|
|
this.pluginId,
|
|
|
|
|
'index.js'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if (!fs.existsSync(pluginPath)) {
|
|
|
|
|
throw new Error(`Plugin ${this.pluginId} not found`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete require.cache[require.resolve(pluginPath)]
|
|
|
|
|
|
|
|
|
|
this.plugin = require(pluginPath)
|
|
|
|
|
|
|
|
|
|
} catch (e: any) {
|
|
|
|
|
console.error(`[PluginSystem] load failed:`, e)
|
|
|
|
|
this.plugin = null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
async getUrl(id: string, quality: string): Promise<UrlResponse> {
|
|
|
|
|
if (!this.plugin?.getUrl) {
|
|
|
|
|
return {
|
|
|
|
|
success: false,
|
|
|
|
|
error: 'getUrl not implemented'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
2026-02-05 23:44:51 +08:00
|
|
|
// New behavior: plugin returns raw url string or throws
|
|
|
|
|
const url = await this.plugin.getUrl(id, quality)
|
|
|
|
|
|
|
|
|
|
if (typeof url !== 'string' || !url.startsWith('http')) {
|
|
|
|
|
return {
|
|
|
|
|
success: false,
|
|
|
|
|
error: 'Invalid URL scheme'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
url
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-03 12:59:04 +08:00
|
|
|
} catch (e: any) {
|
|
|
|
|
return {
|
|
|
|
|
success: false,
|
|
|
|
|
error: e.message || 'plugin error'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-06 14:50:33 +08:00
|
|
|
|
|
|
|
|
async search(query: string, page: number, limit: number): Promise<any> {
|
|
|
|
|
if (!this.plugin?.musicSearch?.search) {
|
|
|
|
|
return {
|
|
|
|
|
list: [],
|
|
|
|
|
total: 0,
|
|
|
|
|
allPage: 0,
|
|
|
|
|
error: 'Search not implemented'
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-06 17:01:45 +08:00
|
|
|
return await this.plugin.musicSearch.search(query, page, limit)
|
2026-02-06 14:50:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async getLyric(id: string): Promise<any> {
|
|
|
|
|
console.log("getLyric not implemented");
|
|
|
|
|
if (!this.plugin?.getLyric) {
|
|
|
|
|
console.log("getLyric not implemented2");
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const result = await this.plugin.getLyric(id)
|
|
|
|
|
console.log(result)
|
|
|
|
|
return result
|
|
|
|
|
} catch (e: any) {
|
|
|
|
|
console.log(e)
|
|
|
|
|
MessagePlugin.error(e).then()
|
|
|
|
|
return {}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-03 12:59:04 +08:00
|
|
|
}
|