新增HTTP开放API服务
This commit is contained in:
@@ -234,6 +234,18 @@ export const initAppSetting = async() => {
|
||||
colors: {},
|
||||
},
|
||||
},
|
||||
player_status: {
|
||||
status: 'stoped',
|
||||
name: '',
|
||||
singer: '',
|
||||
albumName: '',
|
||||
picUrl: '',
|
||||
progress: 0,
|
||||
duration: 0,
|
||||
lyricLineText: '',
|
||||
lyric: '',
|
||||
collect: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,14 @@ export class Event extends EventEmitter {
|
||||
this.emit('deeplink', link)
|
||||
}
|
||||
|
||||
player_status(status: Partial<LX.Player.Status>) {
|
||||
for (const [key, value] of Object.entries(status)) {
|
||||
// @ts-expect-error
|
||||
global.lx.player_status[key] = value
|
||||
}
|
||||
this.emit('player_status', status)
|
||||
}
|
||||
|
||||
hot_key_down(keyInfo: LX.HotKeyDownInfo) {
|
||||
this.emit('hot_key_down', keyInfo)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import http from 'node:http'
|
||||
|
||||
let status: LX.OpenAPI.Status = {
|
||||
status: false,
|
||||
message: '',
|
||||
address: '',
|
||||
}
|
||||
|
||||
let httpServer: http.Server
|
||||
|
||||
const handleStartServer = async(port = 9000, ip = '127.0.0.1') => new Promise<void>((resolve, reject) => {
|
||||
httpServer = http.createServer((req, res) => {
|
||||
// console.log(req.url)
|
||||
const endUrl = `/${req.url?.split('/').at(-1) ?? ''}`
|
||||
let code
|
||||
let msg
|
||||
switch (endUrl) {
|
||||
case '/status':
|
||||
code = 200
|
||||
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
||||
msg = JSON.stringify({
|
||||
status: global.lx.player_status.status,
|
||||
name: global.lx.player_status.name,
|
||||
singer: global.lx.player_status.singer,
|
||||
albumName: global.lx.player_status.albumName,
|
||||
duration: global.lx.player_status.duration,
|
||||
progress: global.lx.player_status.progress,
|
||||
picUrl: global.lx.player_status.picUrl,
|
||||
lyricLineText: global.lx.player_status.lyricLineText,
|
||||
})
|
||||
break
|
||||
case '/lyric':
|
||||
code = 200
|
||||
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
|
||||
msg = global.lx.player_status.lyric
|
||||
break
|
||||
default:
|
||||
code = 401
|
||||
msg = 'Forbidden'
|
||||
break
|
||||
}
|
||||
if (!code) return
|
||||
res.writeHead(code)
|
||||
res.end(msg)
|
||||
})
|
||||
httpServer.on('error', error => {
|
||||
console.log(error)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
httpServer.on('listening', () => {
|
||||
const addr = httpServer.address()
|
||||
// console.log(addr)
|
||||
if (!addr) {
|
||||
reject(new Error('address is null'))
|
||||
return
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
httpServer.listen(port, ip)
|
||||
})
|
||||
|
||||
const handleStopServer = async() => new Promise<void>((resolve, reject) => {
|
||||
if (!httpServer) return
|
||||
httpServer.close((err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
export const stopServer = async() => {
|
||||
if (!status.status) {
|
||||
status.status = false
|
||||
status.message = ''
|
||||
status.address = ''
|
||||
return status
|
||||
}
|
||||
await handleStopServer().then(() => {
|
||||
status.status = false
|
||||
status.message = ''
|
||||
status.address = ''
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
status.message = err.message
|
||||
})
|
||||
return status
|
||||
}
|
||||
export const startServer = async(port: number) => {
|
||||
if (status.status) await handleStopServer()
|
||||
await handleStartServer(port).then(() => {
|
||||
status.status = true
|
||||
status.message = ''
|
||||
status.address = `http://localhost${port == 80 ? '' : ':' + port}`
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
status.status = false
|
||||
status.message = err.message
|
||||
status.address = ''
|
||||
})
|
||||
return status
|
||||
}
|
||||
|
||||
export const getStatus = (): LX.OpenAPI.Status => status
|
||||
@@ -1,7 +1,7 @@
|
||||
import initRendererEvent, { handleKeyDown, hotKeyConfigUpdate } from './rendererEvent'
|
||||
|
||||
import { APP_EVENT_NAMES } from '@common/constants'
|
||||
import { createWindow, minimize, toggleHide, toggleMinimize } from './main'
|
||||
import { createWindow, minimize, setProgressBar, setThumbarButtons, toggleHide, toggleMinimize } from './main'
|
||||
import initUpdate from './autoUpdate'
|
||||
import { HOTKEY_COMMON } from '@common/hotKey'
|
||||
import { quitApp } from '@main/app'
|
||||
@@ -38,6 +38,78 @@ export default () => {
|
||||
global.lx.event_app.on('app_inited', () => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
const keys = (['status', 'collect'] as const) satisfies Array<keyof LX.Player.Status>
|
||||
const taskBarButtonFlags: LX.TaskBarButtonFlags = {
|
||||
empty: true,
|
||||
collect: false,
|
||||
play: false,
|
||||
next: true,
|
||||
prev: true,
|
||||
}
|
||||
const progressStatus = {
|
||||
progress: 0,
|
||||
status: 'none' as Electron.ProgressBarOptions['mode'],
|
||||
}
|
||||
let showProgress = global.lx.appSetting['player.isShowTaskProgess']
|
||||
global.lx.event_app.on('player_status', (status) => {
|
||||
if (status.status) {
|
||||
switch (status.status) {
|
||||
case 'paused':
|
||||
taskBarButtonFlags.play = false
|
||||
taskBarButtonFlags.empty &&= false
|
||||
progressStatus.status = 'paused'
|
||||
break
|
||||
case 'error':
|
||||
taskBarButtonFlags.play = false
|
||||
taskBarButtonFlags.empty &&= false
|
||||
progressStatus.status = 'error'
|
||||
break
|
||||
case 'playing':
|
||||
taskBarButtonFlags.play = true
|
||||
taskBarButtonFlags.empty &&= false
|
||||
progressStatus.status = 'normal'
|
||||
break
|
||||
case 'stoped':
|
||||
taskBarButtonFlags.play &&= false
|
||||
taskBarButtonFlags.empty = true
|
||||
progressStatus.status = 'none'
|
||||
progressStatus.progress = 0
|
||||
break
|
||||
}
|
||||
if (showProgress) {
|
||||
setProgressBar(progressStatus.progress, {
|
||||
mode: progressStatus.status,
|
||||
})
|
||||
}
|
||||
}
|
||||
if (keys.some(k => status[k] != null)) {
|
||||
if (status.collect != null) taskBarButtonFlags.collect = status.collect
|
||||
setThumbarButtons(taskBarButtonFlags)
|
||||
}
|
||||
if (status.progress) {
|
||||
const progress = status.progress / global.lx.player_status.duration
|
||||
if (progress.toFixed(2) == progressStatus.progress.toFixed(2)) return
|
||||
progressStatus.progress = progress
|
||||
if (showProgress) {
|
||||
setProgressBar(progress, {
|
||||
mode: progressStatus.status,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
global.lx.event_app.on('updated_config', (keys, setting) => {
|
||||
if (keys.includes('player.isShowTaskProgess')) {
|
||||
showProgress = setting['player.isShowTaskProgess']!
|
||||
if (showProgress) {
|
||||
setProgressBar(progressStatus.progress, {
|
||||
mode: progressStatus.status,
|
||||
})
|
||||
} else {
|
||||
setProgressBar(-1, { mode: 'none' })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export * from './main'
|
||||
|
||||
@@ -14,10 +14,8 @@ import {
|
||||
getCacheSize,
|
||||
toggleDevTools,
|
||||
setWindowBounds,
|
||||
setProgressBar,
|
||||
setIgnoreMouseEvents,
|
||||
// setThumbnailClip,
|
||||
setThumbarButtons,
|
||||
toggleMinimize,
|
||||
toggleHide,
|
||||
showSelectDialog,
|
||||
@@ -106,13 +104,6 @@ export default () => {
|
||||
setWindowBounds(params)
|
||||
})
|
||||
|
||||
mainOn<LX.Player.ProgressBarOptions>(WIN_MAIN_RENDERER_EVENT_NAME.progress, ({ params }) => {
|
||||
// console.log(params)
|
||||
setProgressBar(params.progress, {
|
||||
mode: params.mode ?? 'normal',
|
||||
})
|
||||
})
|
||||
|
||||
mainOn<boolean>(WIN_MAIN_RENDERER_EVENT_NAME.set_ignore_mouse_events, ({ params: isIgnored }) => {
|
||||
isIgnored
|
||||
? setIgnoreMouseEvents(isIgnored, { forward: true })
|
||||
@@ -123,8 +114,9 @@ export default () => {
|
||||
// return setThumbnailClip(params)
|
||||
// })
|
||||
|
||||
mainOn<LX.TaskBarButtonFlags>(WIN_MAIN_RENDERER_EVENT_NAME.player_action_set_buttons, ({ params }) => {
|
||||
setThumbarButtons(params)
|
||||
mainOn<LX.Player.Status>(WIN_MAIN_RENDERER_EVENT_NAME.player_status, ({ params }) => {
|
||||
// setThumbarButtons(params)
|
||||
global.lx.event_app.player_status(params)
|
||||
})
|
||||
|
||||
mainOn(WIN_MAIN_RENDERER_EVENT_NAME.inited, () => {
|
||||
|
||||
@@ -11,6 +11,7 @@ import data from './data'
|
||||
import music from './music'
|
||||
import download from './download'
|
||||
import soundEffect from './soundEffect'
|
||||
import openAPI from './openAPI'
|
||||
import { sendEvent } from '../main'
|
||||
|
||||
export * from './app'
|
||||
@@ -37,6 +38,7 @@ export default () => {
|
||||
music()
|
||||
download()
|
||||
soundEffect()
|
||||
openAPI()
|
||||
|
||||
global.lx.event_app.on('updated_config', (keys, setting) => {
|
||||
sendConfigChange(setting)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { mainHandle } from '@common/mainIpc'
|
||||
import { WIN_MAIN_RENDERER_EVENT_NAME } from '@common/ipcNames'
|
||||
import {
|
||||
startServer,
|
||||
stopServer,
|
||||
getStatus,
|
||||
} from '@main/modules/openApi'
|
||||
|
||||
|
||||
export default () => {
|
||||
mainHandle<LX.OpenAPI.Actions, any>(WIN_MAIN_RENDERER_EVENT_NAME.open_api_action, async({ params: data }) => {
|
||||
switch (data.action) {
|
||||
case 'enable':
|
||||
return data.data.enable ? await startServer(parseInt(data.data.port)) : await stopServer()
|
||||
case 'status': return getStatus()
|
||||
}
|
||||
})
|
||||
}
|
||||
Vendored
+1
@@ -30,6 +30,7 @@ interface Lx {
|
||||
dbService: DBSeriveTypes
|
||||
}
|
||||
theme: LX.ThemeSetting
|
||||
player_status: LX.Player.Status
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
Vendored
+1
@@ -14,3 +14,4 @@ import '@common/types/ipc_main'
|
||||
import '@common/types/sound_effect'
|
||||
import '@common/types/dislike_list'
|
||||
import '@common/types/dislike_list_sync'
|
||||
import '@common/types/open_api'
|
||||
|
||||
Reference in New Issue
Block a user