mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-18 06:07:48 +00:00
feat: updates
This commit is contained in:
parent
c6c59b2cd9
commit
7ce516877e
63 changed files with 6591 additions and 1107 deletions
31
packages/desktop/main/appServer/appServer.ts
Normal file
31
packages/desktop/main/appServer/appServer.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import fastify from 'fastify'
|
||||
import fastifyStatic from '@fastify/static'
|
||||
import path from 'path'
|
||||
import fastifyCookie from '@fastify/cookie'
|
||||
import { isProd } from '../env'
|
||||
import log from '../log'
|
||||
import netease from './routes/netease'
|
||||
import appleMusic from './routes/r3play/appleMusic'
|
||||
|
||||
const server = fastify({
|
||||
ignoreTrailingSlash: true,
|
||||
})
|
||||
|
||||
server.register(fastifyCookie)
|
||||
if (isProd) {
|
||||
server.register(fastifyStatic, {
|
||||
root: path.join(__dirname, '../web'),
|
||||
})
|
||||
}
|
||||
|
||||
server.register(netease, { prefix: '/netease' })
|
||||
server.register(appleMusic)
|
||||
|
||||
const port = Number(
|
||||
isProd
|
||||
? process.env.ELECTRON_WEB_SERVER_PORT || 42710
|
||||
: process.env.ELECTRON_DEV_NETEASE_API_PORT || 30001
|
||||
)
|
||||
server.listen({ port })
|
||||
|
||||
log.info(`[appServer] http server listening on port ${port}`)
|
||||
58
packages/desktop/main/appServer/routes/netease.ts
Normal file
58
packages/desktop/main/appServer/routes/netease.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { APIs } from '@/shared/CacheAPIs'
|
||||
import { pathCase, snakeCase } from 'change-case'
|
||||
import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'
|
||||
import NeteaseCloudMusicApi from 'NeteaseCloudMusicApi'
|
||||
import cache from '../../cache'
|
||||
|
||||
async function netease(fastify: FastifyInstance) {
|
||||
const getHandler = (name: string, neteaseApi: (params: any) => any) => {
|
||||
return async (
|
||||
req: FastifyRequest<{ Querystring: { [key: string]: string } }>,
|
||||
reply: FastifyReply
|
||||
) => {
|
||||
// Get track details from cache
|
||||
if (name === APIs.Track) {
|
||||
const cacheData = cache.get(name, req.query)
|
||||
if (cacheData) {
|
||||
return cache
|
||||
}
|
||||
}
|
||||
|
||||
// Request netease api
|
||||
try {
|
||||
const result = await neteaseApi({
|
||||
...req.query,
|
||||
cookie: req.cookies,
|
||||
})
|
||||
|
||||
cache.set(name, result.body, req.query)
|
||||
return reply.send(result.body)
|
||||
} catch (error: any) {
|
||||
if ([400, 301].includes(error.status)) {
|
||||
return reply.status(error.status).send(error.body)
|
||||
}
|
||||
return reply.status(500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 循环注册NeteaseCloudMusicApi所有接口
|
||||
Object.entries(NeteaseCloudMusicApi).forEach(([nameInSnakeCase, neteaseApi]: [string, any]) => {
|
||||
// 例外
|
||||
if (
|
||||
['serveNcmApi', 'getModulesDefinitions', snakeCase(APIs.SongUrl)].includes(nameInSnakeCase)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const name = pathCase(nameInSnakeCase)
|
||||
const handler = getHandler(name, neteaseApi)
|
||||
|
||||
fastify.get(`/${name}`, handler)
|
||||
fastify.post(`/${name}`, handler)
|
||||
})
|
||||
|
||||
fastify.get('/', () => 'NeteaseCloudMusicApi')
|
||||
}
|
||||
|
||||
export default netease
|
||||
12
packages/desktop/main/appServer/routes/r3play/appleMusic.ts
Normal file
12
packages/desktop/main/appServer/routes/r3play/appleMusic.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { FastifyInstance } from 'fastify'
|
||||
import proxy from '@fastify/http-proxy'
|
||||
|
||||
async function appleMusic(fastify: FastifyInstance) {
|
||||
fastify.register(proxy, {
|
||||
upstream: 'http://168.138.174.244:35530/',
|
||||
prefix: '/r3play/apple-music',
|
||||
rewritePrefix: '/apple-music',
|
||||
})
|
||||
}
|
||||
|
||||
export default appleMusic
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
import log from './log'
|
||||
import axios from 'axios'
|
||||
import { AppleMusicAlbum, AppleMusicArtist } from '@/shared/AppleMusic'
|
||||
|
||||
const headers = {
|
||||
Authority: 'amp-api.music.apple.com',
|
||||
Accept: '*/*',
|
||||
Authorization:
|
||||
'Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IldlYlBsYXlLaWQifQ.eyJpc3MiOiJBTVBXZWJQbGF5IiwiaWF0IjoxNjYxNDQwNDMyLCJleHAiOjE2NzY5OTI0MzIsInJvb3RfaHR0cHNfb3JpZ2luIjpbImFwcGxlLmNvbSJdfQ.z4BMv9_O4MpMK2iFhYkDqPsx53soPSnlXXK3jm99pHqGOrZADvTgEUw2U7_B1W0MAtFiWBYhYcGvWrzaOig6Bw',
|
||||
Referer: 'https://music.apple.com/',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Cider/1.5.1 Chrome/100.0.4896.160 Electron/18.3.3 Safari/537.36',
|
||||
'Accept-Encoding': 'gzip',
|
||||
Origin: 'https://music.apple.com',
|
||||
}
|
||||
|
||||
export const getAlbum = async ({
|
||||
name,
|
||||
artist,
|
||||
}: {
|
||||
name: string
|
||||
artist: string
|
||||
}): Promise<AppleMusicAlbum | undefined> => {
|
||||
const keyword = `${artist} ${name}`
|
||||
log.debug(`[appleMusic] getAlbum: ${keyword}`)
|
||||
const searchResult = await axios({
|
||||
method: 'GET',
|
||||
headers,
|
||||
url: 'https://amp-api.music.apple.com/v1/catalog/us/search',
|
||||
params: {
|
||||
term: keyword,
|
||||
types: 'albums',
|
||||
'fields[albums]': 'artistName,name,editorialVideo,editorialNotes',
|
||||
platform: 'web',
|
||||
limit: '5',
|
||||
l: 'en-us', // TODO: get from settings
|
||||
},
|
||||
}).catch(e => {
|
||||
log.debug('[appleMusic] Search album error', e)
|
||||
})
|
||||
|
||||
const albums: AppleMusicAlbum[] | undefined =
|
||||
searchResult?.data?.results?.albums?.data
|
||||
|
||||
const album =
|
||||
albums?.find(
|
||||
a =>
|
||||
a.attributes.name.toLowerCase() === name.toLowerCase() &&
|
||||
a.attributes.artistName.toLowerCase() === artist.toLowerCase()
|
||||
) || albums?.[0]
|
||||
if (!album) {
|
||||
log.debug('[appleMusic] No album found on apple music')
|
||||
return
|
||||
}
|
||||
|
||||
return album
|
||||
}
|
||||
|
||||
export const getArtist = async (
|
||||
name: string
|
||||
): Promise<AppleMusicArtist | undefined> => {
|
||||
const searchResult = await axios({
|
||||
method: 'GET',
|
||||
url: 'https://amp-api.music.apple.com/v1/catalog/us/search',
|
||||
headers,
|
||||
params: {
|
||||
term: name,
|
||||
types: 'artists',
|
||||
'fields[artists]': 'url,name,artwork,editorialVideo,artistBio',
|
||||
'omit[resource:artists]': 'relationships',
|
||||
platform: 'web',
|
||||
limit: '1',
|
||||
l: 'en-us', // TODO: get from settings
|
||||
with: 'serverBubbles',
|
||||
},
|
||||
}).catch(e => {
|
||||
log.debug('[appleMusic] Search artist error', e)
|
||||
})
|
||||
|
||||
const artist = searchResult?.data?.results?.artist?.data?.[0]
|
||||
if (
|
||||
artist &&
|
||||
artist?.attributes?.name?.toLowerCase() === name.toLowerCase()
|
||||
) {
|
||||
return artist
|
||||
}
|
||||
}
|
||||
|
|
@ -147,9 +147,7 @@ class Cache {
|
|||
break
|
||||
}
|
||||
case APIs.Track: {
|
||||
const ids: number[] = params?.ids
|
||||
.split(',')
|
||||
.map((id: string) => Number(id))
|
||||
const ids: number[] = params?.ids.split(',').map((id: string) => Number(id))
|
||||
if (ids.length === 0) return
|
||||
|
||||
if (ids.includes(NaN)) return
|
||||
|
|
@ -252,17 +250,6 @@ class Cache {
|
|||
}
|
||||
}
|
||||
|
||||
getForExpress(api: string, req: Request) {
|
||||
// Get track detail cache
|
||||
if (api === APIs.Track) {
|
||||
const cache = this.get(api, req.query)
|
||||
if (cache) {
|
||||
log.debug(`[cache] Cache hit for ${req.path}`)
|
||||
return cache
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getAudio(fileName: string, res: Response) {
|
||||
if (!fileName) {
|
||||
return res.status(400).send({ error: 'No filename provided' })
|
||||
|
|
@ -281,10 +268,7 @@ class Cache {
|
|||
.status(206)
|
||||
.setHeader('Accept-Ranges', 'bytes')
|
||||
.setHeader('Connection', 'keep-alive')
|
||||
.setHeader(
|
||||
'Content-Range',
|
||||
`bytes 0-${audio.byteLength - 1}/${audio.byteLength}`
|
||||
)
|
||||
.setHeader('Content-Range', `bytes 0-${audio.byteLength - 1}/${audio.byteLength}`)
|
||||
.send(audio)
|
||||
} catch (error) {
|
||||
res.status(500).send({ error })
|
||||
|
|
@ -301,8 +285,7 @@ class Cache {
|
|||
}
|
||||
|
||||
const meta = await musicMetadata.parseBuffer(buffer)
|
||||
const br =
|
||||
meta?.format?.codec === 'OPUS' ? 165000 : meta.format.bitrate ?? 0
|
||||
const br = meta?.format?.codec === 'OPUS' ? 165000 : meta.format.bitrate ?? 0
|
||||
const type =
|
||||
{
|
||||
'MPEG 1 Layer 3': 'mp3',
|
||||
|
|
|
|||
|
|
@ -77,10 +77,7 @@ const readSqlFile = (filename: string) => {
|
|||
|
||||
class DB {
|
||||
sqlite: SQLite3.Database
|
||||
dbFilePath: string = path.resolve(
|
||||
app.getPath('userData'),
|
||||
'./api_cache/db.sqlite'
|
||||
)
|
||||
dbFilePath: string = path.resolve(app.getPath('userData'), './api_cache/db.sqlite')
|
||||
|
||||
constructor() {
|
||||
log.info('[db] Initializing database...')
|
||||
|
|
@ -109,14 +106,8 @@ class DB {
|
|||
`../../bin/better_sqlite3_${os.platform}_${os.arch}.node`
|
||||
)
|
||||
const prodBinPaths = {
|
||||
darwin: path.resolve(
|
||||
app.getPath('exe'),
|
||||
`../../Resources/bin/better_sqlite3.node`
|
||||
),
|
||||
win32: path.resolve(
|
||||
app.getPath('exe'),
|
||||
`../resources/bin/better_sqlite3.node`
|
||||
),
|
||||
darwin: path.resolve(app.getPath('exe'), `../../Resources/bin/better_sqlite3.node`),
|
||||
win32: path.resolve(app.getPath('exe'), `../resources/bin/better_sqlite3.node`),
|
||||
linux: '',
|
||||
}
|
||||
return isProd
|
||||
|
|
@ -128,6 +119,7 @@ class DB {
|
|||
log.info('[db] Initializing database tables...')
|
||||
const init = readSqlFile('init.sql')
|
||||
this.sqlite.exec(init)
|
||||
this.sqlite.pragma('journal_mode=WAL')
|
||||
log.info('[db] Database tables initialized.')
|
||||
}
|
||||
|
||||
|
|
@ -167,9 +159,7 @@ class DB {
|
|||
table: T,
|
||||
key: TablesStructures[T]['id']
|
||||
): TablesStructures[T] | undefined {
|
||||
return this.sqlite
|
||||
.prepare(`SELECT * FROM ${table} WHERE id = ? LIMIT 1`)
|
||||
.get(key)
|
||||
return this.sqlite.prepare(`SELECT * FROM ${table} WHERE id = ? LIMIT 1`).get(key)
|
||||
}
|
||||
|
||||
findMany<T extends TableNames>(
|
||||
|
|
@ -184,11 +174,7 @@ class DB {
|
|||
return this.sqlite.prepare(`SELECT * FROM ${table}`).all()
|
||||
}
|
||||
|
||||
create<T extends TableNames>(
|
||||
table: T,
|
||||
data: TablesStructures[T],
|
||||
skipWhenExist: boolean = true
|
||||
) {
|
||||
create<T extends TableNames>(table: T, data: TablesStructures[T], skipWhenExist: boolean = true) {
|
||||
if (skipWhenExist && db.find(table, data.id)) return
|
||||
return this.sqlite.prepare(`INSERT INTO ${table} VALUES (?)`).run(data)
|
||||
}
|
||||
|
|
@ -202,9 +188,7 @@ class DB {
|
|||
.map(key => `:${key}`)
|
||||
.join(', ')
|
||||
const insert = this.sqlite.prepare(
|
||||
`INSERT ${
|
||||
skipWhenExist ? 'OR IGNORE' : ''
|
||||
} INTO ${table} VALUES (${valuesQuery})`
|
||||
`INSERT ${skipWhenExist ? 'OR IGNORE' : ''} INTO ${table} VALUES (${valuesQuery})`
|
||||
)
|
||||
const insertMany = this.sqlite.transaction((rows: any[]) => {
|
||||
rows.forEach((row: any) => insert.run(row))
|
||||
|
|
@ -216,18 +200,14 @@ class DB {
|
|||
const valuesQuery = Object.keys(data)
|
||||
.map(key => `:${key}`)
|
||||
.join(', ')
|
||||
return this.sqlite
|
||||
.prepare(`INSERT OR REPLACE INTO ${table} VALUES (${valuesQuery})`)
|
||||
.run(data)
|
||||
return this.sqlite.prepare(`INSERT OR REPLACE INTO ${table} VALUES (${valuesQuery})`).run(data)
|
||||
}
|
||||
|
||||
upsertMany<T extends TableNames>(table: T, data: TablesStructures[T][]) {
|
||||
const valuesQuery = Object.keys(data[0])
|
||||
.map(key => `:${key}`)
|
||||
.join(', ')
|
||||
const upsert = this.sqlite.prepare(
|
||||
`INSERT OR REPLACE INTO ${table} VALUES (${valuesQuery})`
|
||||
)
|
||||
const upsert = this.sqlite.prepare(`INSERT OR REPLACE INTO ${table} VALUES (${valuesQuery})`)
|
||||
const upsertMany = this.sqlite.transaction((rows: any[]) => {
|
||||
rows.forEach((row: any) => upsert.run(row))
|
||||
})
|
||||
|
|
@ -238,10 +218,7 @@ class DB {
|
|||
return this.sqlite.prepare(`DELETE FROM ${table} WHERE id = ?`).run(key)
|
||||
}
|
||||
|
||||
deleteMany<T extends TableNames>(
|
||||
table: T,
|
||||
keys: TablesStructures[T]['id'][]
|
||||
) {
|
||||
deleteMany<T extends TableNames>(table: T, keys: TablesStructures[T]['id'][]) {
|
||||
const idsQuery = keys.map(key => `id = ${key}`).join(' OR ')
|
||||
return this.sqlite.prepare(`DELETE FROM ${table} WHERE ${idsQuery}`).run()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@ export const isProd = process.env.NODE_ENV === 'production'
|
|||
export const isWindows = process.platform === 'win32'
|
||||
export const isMac = process.platform === 'darwin'
|
||||
export const isLinux = process.platform === 'linux'
|
||||
export const appName = 'R3Play'
|
||||
export const appName = 'R3PLAY'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import './preload' // must be first
|
||||
import './sentry'
|
||||
import './server'
|
||||
// import './server'
|
||||
import { BrowserWindow, BrowserWindowConstructorOptions, app, shell } from 'electron'
|
||||
import { release } from 'os'
|
||||
import { join } from 'path'
|
||||
|
|
@ -12,8 +12,7 @@ import { createTaskbar, Thumbar } from './windowsTaskbar'
|
|||
import { createMenu } from './menu'
|
||||
import { isDev, isWindows, isLinux, isMac, appName } from './env'
|
||||
import store from './store'
|
||||
// import './surrealdb'
|
||||
// import Airplay from './airplay'
|
||||
import './appServer/appServer'
|
||||
|
||||
class Main {
|
||||
win: BrowserWindow | null = null
|
||||
|
|
@ -83,10 +82,12 @@ class Main {
|
|||
width: store.get('window.width'),
|
||||
height: store.get('window.height'),
|
||||
minWidth: 1240,
|
||||
minHeight: 848,
|
||||
minHeight: 800,
|
||||
titleBarStyle: isMac ? 'customButtonsOnHover' : 'hidden',
|
||||
trafficLightPosition: { x: 24, y: 24 },
|
||||
frame: false,
|
||||
fullscreenable: true,
|
||||
resizable: true,
|
||||
transparent: true,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0)',
|
||||
show: false,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import { Thumbar } from './windowsTaskbar'
|
|||
import fastFolderSize from 'fast-folder-size'
|
||||
import path from 'path'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import { getArtist, getAlbum } from './appleMusic'
|
||||
|
||||
const on = <T extends keyof IpcChannelsParams>(
|
||||
channel: T,
|
||||
|
|
@ -23,10 +22,7 @@ const on = <T extends keyof IpcChannelsParams>(
|
|||
|
||||
const handle = <T extends keyof IpcChannelsParams>(
|
||||
channel: T,
|
||||
listener: (
|
||||
event: Electron.IpcMainInvokeEvent,
|
||||
params: IpcChannelsParams[T]
|
||||
) => void
|
||||
listener: (event: Electron.IpcMainInvokeEvent, params: IpcChannelsParams[T]) => void
|
||||
) => {
|
||||
return ipcMain.handle(channel, listener)
|
||||
}
|
||||
|
|
@ -162,49 +158,46 @@ function initOtherIpcMain() {
|
|||
* 获取音频缓存文件夹大小
|
||||
*/
|
||||
on(IpcChannels.GetAudioCacheSize, event => {
|
||||
fastFolderSize(
|
||||
path.join(app.getPath('userData'), './audio_cache'),
|
||||
(error, bytes) => {
|
||||
if (error) throw error
|
||||
fastFolderSize(path.join(app.getPath('userData'), './audio_cache'), (error, bytes) => {
|
||||
if (error) throw error
|
||||
|
||||
event.returnValue = prettyBytes(bytes ?? 0)
|
||||
}
|
||||
)
|
||||
event.returnValue = prettyBytes(bytes ?? 0)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* 从Apple Music获取专辑信息
|
||||
*/
|
||||
handle(
|
||||
IpcChannels.GetAlbumFromAppleMusic,
|
||||
async (event, { id, name, artist }) => {
|
||||
const fromCache = cache.get(APIs.AppleMusicAlbum, { id })
|
||||
if (fromCache) {
|
||||
return fromCache === 'no' ? undefined : fromCache
|
||||
}
|
||||
// handle(
|
||||
// IpcChannels.GetAlbumFromAppleMusic,
|
||||
// async (event, { id, name, artist }) => {
|
||||
// const fromCache = cache.get(APIs.AppleMusicAlbum, { id })
|
||||
// if (fromCache) {
|
||||
// return fromCache === 'no' ? undefined : fromCache
|
||||
// }
|
||||
|
||||
const fromApple = await getAlbum({ name, artist })
|
||||
cache.set(APIs.AppleMusicAlbum, { id, album: fromApple })
|
||||
return fromApple
|
||||
}
|
||||
)
|
||||
// const fromApple = await getAlbum({ name, artist })
|
||||
// cache.set(APIs.AppleMusicAlbum, { id, album: fromApple })
|
||||
// return fromApple
|
||||
// }
|
||||
// )
|
||||
|
||||
/**
|
||||
* 从Apple Music获取歌手信息
|
||||
**/
|
||||
handle(IpcChannels.GetArtistFromAppleMusic, async (event, { id, name }) => {
|
||||
const fromApple = await getArtist(name)
|
||||
cache.set(APIs.AppleMusicArtist, { id, artist: fromApple })
|
||||
return fromApple
|
||||
})
|
||||
// /**
|
||||
// * 从Apple Music获取歌手信息
|
||||
// **/
|
||||
// handle(IpcChannels.GetArtistFromAppleMusic, async (event, { id, name }) => {
|
||||
// const fromApple = await getArtist(name)
|
||||
// cache.set(APIs.AppleMusicArtist, { id, artist: fromApple })
|
||||
// return fromApple
|
||||
// })
|
||||
|
||||
/**
|
||||
* 从缓存读取Apple Music歌手信息
|
||||
*/
|
||||
on(IpcChannels.GetArtistFromAppleMusic, (event, { id }) => {
|
||||
const artist = cache.get(APIs.AppleMusicArtist, id)
|
||||
event.returnValue = artist === 'no' ? undefined : artist
|
||||
})
|
||||
// /**
|
||||
// * 从缓存读取Apple Music歌手信息
|
||||
// */
|
||||
// on(IpcChannels.GetArtistFromAppleMusic, (event, { id }) => {
|
||||
// const artist = cache.get(APIs.AppleMusicArtist, id)
|
||||
// event.returnValue = artist === 'no' ? undefined : artist
|
||||
// })
|
||||
|
||||
/**
|
||||
* 退出登陆
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { appName, isProd } from './env'
|
|||
import { APIs } from '@/shared/CacheAPIs'
|
||||
import history from 'connect-history-api-fallback'
|
||||
import { db, Tables } from './db'
|
||||
import axios from 'axios'
|
||||
|
||||
class Server {
|
||||
port = Number(
|
||||
|
|
@ -30,12 +31,32 @@ class Server {
|
|||
this.app.use(cookieParser())
|
||||
this.app.use(fileUpload())
|
||||
this.getAudioUrlHandler()
|
||||
this.r3playApiHandler()
|
||||
this.neteaseHandler()
|
||||
this.cacheAudioHandler()
|
||||
this.serveStaticForProduction()
|
||||
this.listen()
|
||||
}
|
||||
|
||||
r3playApiHandler() {
|
||||
this.app.get(`/r3play/apple-music/:endpoint`, async (req: Request, res: Response) => {
|
||||
log.debug(`[server] Handling request: ${req.path}`)
|
||||
const { endpoint } = req.params
|
||||
const { query } = req
|
||||
axios
|
||||
.get(`https://r3play.app/r3play/apple-music/${endpoint}`, {
|
||||
params: query,
|
||||
})
|
||||
.then(response => {
|
||||
console.log(response.data)
|
||||
res.send(response.data)
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
neteaseHandler() {
|
||||
Object.entries(this.netease).forEach(([name, handler]: [string, any]) => {
|
||||
// 例外处理
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "desktop",
|
||||
"productName": "R3Play",
|
||||
"productName": "R3PLAY",
|
||||
"private": true,
|
||||
"version": "2.0.0",
|
||||
"main": "./main/index.js",
|
||||
|
|
@ -20,8 +20,10 @@
|
|||
"node": "^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^8.3.0",
|
||||
"@fastify/http-proxy": "^8.4.0",
|
||||
"@sentry/electron": "^3.0.7",
|
||||
"NeteaseCloudMusicApi": "^4.8.4",
|
||||
"NeteaseCloudMusicApi": "^4.8.7",
|
||||
"better-sqlite3": "8.0.1",
|
||||
"change-case": "^4.1.2",
|
||||
"compare-versions": "^4.1.3",
|
||||
|
|
@ -57,9 +59,9 @@
|
|||
"ora": "^6.1.2",
|
||||
"picocolors": "^1.0.0",
|
||||
"prettier": "*",
|
||||
"tsx": "*",
|
||||
"typescript": "*",
|
||||
"vitest": "^0.20.3",
|
||||
"wait-on": "^7.0.1",
|
||||
"tsx": "*"
|
||||
"wait-on": "^7.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,13 +32,10 @@ const options = {
|
|||
define: envForEsbuild,
|
||||
minify: true,
|
||||
external: [
|
||||
...builtinModules.filter(
|
||||
x => !/^_|^(internal|v8|node-inspect)\/|\//.test(x)
|
||||
),
|
||||
...builtinModules.filter(x => !/^_|^(internal|v8|node-inspect)\/|\//.test(x)),
|
||||
'electron',
|
||||
'NeteaseCloudMusicApi',
|
||||
'better-sqlite3',
|
||||
// '@unblockneteasemusic/rust-napi',
|
||||
],
|
||||
}
|
||||
|
||||
|
|
@ -55,9 +52,7 @@ const runApp = () => {
|
|||
if (argv.watch) {
|
||||
waitOn(
|
||||
{
|
||||
resources: [
|
||||
`http://127.0.0.1:${process.env.ELECTRON_WEB_SERVER_PORT}/index.html`,
|
||||
],
|
||||
resources: [`http://127.0.0.1:${process.env.ELECTRON_WEB_SERVER_PORT}/index.html`],
|
||||
timeout: 5000,
|
||||
},
|
||||
err => {
|
||||
|
|
@ -101,11 +96,7 @@ if (argv.watch) {
|
|||
console.log(TAG, pc.green('Main Process Build Succeeded.'))
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(
|
||||
`\n${TAG} ${pc.red('Main Process Build Failed')}\n`,
|
||||
error,
|
||||
'\n'
|
||||
)
|
||||
console.log(`\n${TAG} ${pc.red('Main Process Build Failed')}\n`, error, '\n')
|
||||
})
|
||||
.finally(() => {
|
||||
spinner.stop()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue