mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 13:17:46 +00:00
feat: 增加初始化sqlite的逻辑和其他更新
This commit is contained in:
parent
1b86cbbee1
commit
46fe2d734e
9 changed files with 118 additions and 158 deletions
|
|
@ -14,7 +14,6 @@ export async function setCache(api: string, data: any, query: any) {
|
||||||
case 'recommend/resource':
|
case 'recommend/resource':
|
||||||
case 'likelist': {
|
case 'likelist': {
|
||||||
if (!data) return
|
if (!data) return
|
||||||
console.log(api)
|
|
||||||
db.upsert(Tables.ACCOUNT_DATA, {
|
db.upsert(Tables.ACCOUNT_DATA, {
|
||||||
id: api,
|
id: api,
|
||||||
json: JSON.stringify(data),
|
json: JSON.stringify(data),
|
||||||
|
|
@ -23,7 +22,6 @@ export async function setCache(api: string, data: any, query: any) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'song/detail': {
|
case 'song/detail': {
|
||||||
console.log('dsdadasdas')
|
|
||||||
if (!data.songs) return
|
if (!data.songs) return
|
||||||
const tracks = (data as FetchTracksResponse).songs.map(t => ({
|
const tracks = (data as FetchTracksResponse).songs.map(t => ({
|
||||||
id: t.id,
|
id: t.id,
|
||||||
|
|
@ -35,10 +33,10 @@ export async function setCache(api: string, data: any, query: any) {
|
||||||
}
|
}
|
||||||
case 'album': {
|
case 'album': {
|
||||||
if (!data.album) return
|
if (!data.album) return
|
||||||
data.album.songs = (data as FetchTracksResponse).songs
|
data.album.songs = data.songs
|
||||||
db.upsert(Tables.ALBUM, {
|
db.upsert(Tables.ALBUM, {
|
||||||
id: data.album.id,
|
id: data.album.id,
|
||||||
json: JSON.stringify(data),
|
json: JSON.stringify(data.album),
|
||||||
updatedAt: Date.now(),
|
updatedAt: Date.now(),
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|
@ -63,9 +61,21 @@ export async function setCache(api: string, data: any, query: any) {
|
||||||
}
|
}
|
||||||
case 'artist/album': {
|
case 'artist/album': {
|
||||||
if (!data.hotAlbums) return
|
if (!data.hotAlbums) return
|
||||||
|
db.createMany(
|
||||||
|
Tables.ALBUM,
|
||||||
|
data.hotAlbums.map((a: Album) => ({
|
||||||
|
id: a.id,
|
||||||
|
json: JSON.stringify(a),
|
||||||
|
updatedAt: Date.now(),
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
const modifiedData = {
|
||||||
|
...data,
|
||||||
|
hotAlbums: data.hotAlbums.map((a: Album) => a.id),
|
||||||
|
}
|
||||||
db.upsert(Tables.ARTIST_ALBUMS, {
|
db.upsert(Tables.ARTIST_ALBUMS, {
|
||||||
id: data.artist.id,
|
id: data.artist.id,
|
||||||
json: JSON.stringify(data),
|
json: JSON.stringify(modifiedData),
|
||||||
updatedAt: Date.now(),
|
updatedAt: Date.now(),
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|
@ -113,8 +123,13 @@ export function getCache(api: string, query: any): any {
|
||||||
case 'album': {
|
case 'album': {
|
||||||
if (isNaN(Number(query?.id))) return
|
if (isNaN(Number(query?.id))) return
|
||||||
const data = db.find(Tables.ALBUM, query.id)
|
const data = db.find(Tables.ALBUM, query.id)
|
||||||
console.log(data)
|
if (data?.json)
|
||||||
if (data?.json) return JSON.parse(data.json)
|
return {
|
||||||
|
resourceState: true,
|
||||||
|
songs: [],
|
||||||
|
code: 200,
|
||||||
|
album: JSON.parse(data.json),
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'playlist/detail': {
|
case 'playlist/detail': {
|
||||||
|
|
@ -131,9 +146,19 @@ export function getCache(api: string, query: any): any {
|
||||||
}
|
}
|
||||||
case 'artist/album': {
|
case 'artist/album': {
|
||||||
if (isNaN(Number(query?.id))) return
|
if (isNaN(Number(query?.id))) return
|
||||||
const data = db.find(Tables.ARTIST_ALBUMS, query.id)
|
|
||||||
if (data?.json) return JSON.parse(data.json)
|
const artistAlbumsRaw = db.find(Tables.ARTIST_ALBUMS, query.id)
|
||||||
break
|
if (!artistAlbumsRaw?.json) return
|
||||||
|
const artistAlbums = JSON.parse(artistAlbumsRaw.json)
|
||||||
|
|
||||||
|
const albumsRaw = db.findMany(Tables.ALBUM, artistAlbums.hotAlbums)
|
||||||
|
if (albumsRaw.length !== artistAlbums.hotAlbums.length) return
|
||||||
|
const albums = albumsRaw.map(a => JSON.parse(a.json))
|
||||||
|
|
||||||
|
artistAlbums.hotAlbums = artistAlbums.hotAlbums.map((id: number) =>
|
||||||
|
albums.find(a => a.id === id)
|
||||||
|
)
|
||||||
|
return artistAlbums
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
import Realm from 'realm'
|
|
||||||
import path from 'path'
|
|
||||||
import { app, ipcMain } from 'electron'
|
|
||||||
import fs from 'fs'
|
|
||||||
|
|
||||||
export enum ModelNames {
|
|
||||||
ACCOUNT_DATA = 'AccountData',
|
|
||||||
TRACK = 'Track',
|
|
||||||
ALBUM = 'Album',
|
|
||||||
ARTIST = 'Artist',
|
|
||||||
PLAYLIST = 'Playlist',
|
|
||||||
ARTIST_ALBUMS = 'ArtistAlbums',
|
|
||||||
USER_PLAYLISTS = 'UserPlaylists',
|
|
||||||
AUDIO = 'Audio',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum AudioSources {
|
|
||||||
NETEASE = 'netease',
|
|
||||||
KUWO = 'kuwo',
|
|
||||||
QQ = 'qq',
|
|
||||||
KUGOU = 'kugou',
|
|
||||||
YOUTUBE = 'youtube',
|
|
||||||
MIGU = 'migu',
|
|
||||||
JOOX = 'joox',
|
|
||||||
BILIBILI = 'bilibili',
|
|
||||||
}
|
|
||||||
|
|
||||||
const RegularSchemas = [
|
|
||||||
ModelNames.USER_PLAYLISTS,
|
|
||||||
ModelNames.ARTIST_ALBUMS,
|
|
||||||
ModelNames.PLAYLIST,
|
|
||||||
ModelNames.ALBUM,
|
|
||||||
ModelNames.TRACK,
|
|
||||||
ModelNames.ARTIST,
|
|
||||||
].map(name => ({
|
|
||||||
primaryKey: 'id',
|
|
||||||
name,
|
|
||||||
properties: {
|
|
||||||
id: 'int',
|
|
||||||
json: 'string',
|
|
||||||
updateAt: 'int',
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const realm = new Realm({
|
|
||||||
path: path.resolve(app.getPath('userData'), './api_cache/db.realm'),
|
|
||||||
shouldCompactOnLaunch: (totalSize, usedSize) => {
|
|
||||||
console.log(totalSize, usedSize)
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
schema: [
|
|
||||||
...RegularSchemas,
|
|
||||||
{
|
|
||||||
name: ModelNames.ACCOUNT_DATA,
|
|
||||||
properties: {
|
|
||||||
id: 'string',
|
|
||||||
json: 'string',
|
|
||||||
updateAt: 'int',
|
|
||||||
},
|
|
||||||
primaryKey: 'id',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: ModelNames.AUDIO,
|
|
||||||
properties: {
|
|
||||||
id: 'int',
|
|
||||||
br: 'int',
|
|
||||||
type: 'string',
|
|
||||||
source: 'string',
|
|
||||||
updateAt: 'int',
|
|
||||||
},
|
|
||||||
primaryKey: 'id',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
export const db = {
|
|
||||||
get: (model: ModelNames, key: number | string) => {
|
|
||||||
return realm.objectForPrimaryKey(model, key)
|
|
||||||
},
|
|
||||||
set: (model: ModelNames, key: number | string, value: any) => {
|
|
||||||
realm.write(() => {
|
|
||||||
realm.create(
|
|
||||||
model,
|
|
||||||
{
|
|
||||||
id: key,
|
|
||||||
updateAt: Date.now(),
|
|
||||||
json: JSON.stringify(value),
|
|
||||||
},
|
|
||||||
'modified'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
batchSet: (model: ModelNames, items: any[]) => {
|
|
||||||
realm.write(() => {
|
|
||||||
items.forEach(item => {
|
|
||||||
realm.create(model, item, 'modified')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
delete: (model: ModelNames, key: number) => {
|
|
||||||
realm.delete(realm.objectForPrimaryKey(model, key))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ipcMain.on('test', () => {
|
|
||||||
;[
|
|
||||||
ModelNames.USER_PLAYLISTS,
|
|
||||||
ModelNames.ARTIST_ALBUMS,
|
|
||||||
ModelNames.PLAYLIST,
|
|
||||||
ModelNames.ALBUM,
|
|
||||||
ModelNames.TRACK,
|
|
||||||
ModelNames.ARTIST,
|
|
||||||
ModelNames.AUDIO,
|
|
||||||
ModelNames.ACCOUNT_DATA,
|
|
||||||
].forEach(name => {
|
|
||||||
const data = realm.objects(name)
|
|
||||||
|
|
||||||
fs.writeFile(`./tmp/${name}.json`, JSON.stringify(data), function (err) {
|
|
||||||
if (err) {
|
|
||||||
return console.log(err)
|
|
||||||
}
|
|
||||||
console.log('The file was saved!')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
@ -9,7 +9,6 @@ export enum Tables {
|
||||||
ARTIST = 'artist',
|
ARTIST = 'artist',
|
||||||
PLAYLIST = 'playlist',
|
PLAYLIST = 'playlist',
|
||||||
ARTIST_ALBUMS = 'artist_album',
|
ARTIST_ALBUMS = 'artist_album',
|
||||||
USER_PLAYLISTS = 'user_playlist',
|
|
||||||
|
|
||||||
// Special tables
|
// Special tables
|
||||||
ACCOUNT_DATA = 'account_data',
|
ACCOUNT_DATA = 'account_data',
|
||||||
|
|
@ -19,6 +18,19 @@ export enum Tables {
|
||||||
const sqlite = new SQLite3(
|
const sqlite = new SQLite3(
|
||||||
path.resolve(app.getPath('userData'), './api_cache/db.sqlite')
|
path.resolve(app.getPath('userData'), './api_cache/db.sqlite')
|
||||||
)
|
)
|
||||||
|
sqlite.pragma('auto_vacuum = FULL')
|
||||||
|
|
||||||
|
// Init tables if not exist
|
||||||
|
const trackTable = sqlite
|
||||||
|
.prepare("SELECT * FROM sqlite_master WHERE name='track' and type='table'")
|
||||||
|
.get()
|
||||||
|
if (!trackTable) {
|
||||||
|
const migration = fs.readFileSync(
|
||||||
|
path.join(process.cwd(), './src/main/migrations/init.sql'),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
sqlite.exec(migration)
|
||||||
|
}
|
||||||
|
|
||||||
export const db = {
|
export const db = {
|
||||||
find: (table: Tables, key: number | string) => {
|
find: (table: Tables, key: number | string) => {
|
||||||
|
|
@ -33,6 +45,24 @@ export const db = {
|
||||||
findAll: (table: Tables) => {
|
findAll: (table: Tables) => {
|
||||||
return sqlite.prepare(`SELECT * FROM ${table}`).all()
|
return sqlite.prepare(`SELECT * FROM ${table}`).all()
|
||||||
},
|
},
|
||||||
|
create: (table: Tables, data: any, skipWhenExist: boolean = true) => {
|
||||||
|
if (skipWhenExist && db.find(table, data.id)) return
|
||||||
|
return sqlite.prepare(`INSERT INTO ${table} VALUES (?)`).run(data)
|
||||||
|
},
|
||||||
|
createMany: (table: Tables, data: any[], skipWhenExist: boolean = true) => {
|
||||||
|
const valuesQuery = Object.keys(data[0])
|
||||||
|
.map(key => `:${key}`)
|
||||||
|
.join(', ')
|
||||||
|
const insert = sqlite.prepare(
|
||||||
|
`INSERT ${
|
||||||
|
skipWhenExist ? 'OR IGNORE' : ''
|
||||||
|
} INTO ${table} VALUES (${valuesQuery})`
|
||||||
|
)
|
||||||
|
const insertMany = sqlite.transaction((rows: any[]) => {
|
||||||
|
rows.forEach((row: any) => insert.run(row))
|
||||||
|
})
|
||||||
|
insertMany(data)
|
||||||
|
},
|
||||||
upsert: (table: Tables, data: any) => {
|
upsert: (table: Tables, data: any) => {
|
||||||
const valuesQuery = Object.keys(data)
|
const valuesQuery = Object.keys(data)
|
||||||
.map(key => `:${key}`)
|
.map(key => `:${key}`)
|
||||||
|
|
@ -63,26 +93,32 @@ export const db = {
|
||||||
truncate: (table: Tables) => {
|
truncate: (table: Tables) => {
|
||||||
return sqlite.prepare(`DELETE FROM ${table}`).run()
|
return sqlite.prepare(`DELETE FROM ${table}`).run()
|
||||||
},
|
},
|
||||||
|
vacuum: () => {
|
||||||
|
return sqlite.prepare('VACUUM').run()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcMain.on('db-export-json', () => {
|
// 导出tables到json文件,方便查看table大小
|
||||||
const tables = [
|
if (process.env.NODE_ENV === 'development') {
|
||||||
Tables.ARTIST_ALBUMS,
|
ipcMain.on('db-export-json', () => {
|
||||||
Tables.PLAYLIST,
|
const tables = [
|
||||||
Tables.ALBUM,
|
Tables.ARTIST_ALBUMS,
|
||||||
Tables.TRACK,
|
Tables.PLAYLIST,
|
||||||
Tables.ARTIST,
|
Tables.ALBUM,
|
||||||
Tables.AUDIO,
|
Tables.TRACK,
|
||||||
Tables.ACCOUNT_DATA,
|
Tables.ARTIST,
|
||||||
]
|
Tables.AUDIO,
|
||||||
tables.forEach(table => {
|
Tables.ACCOUNT_DATA,
|
||||||
const data = db.findAll(table)
|
]
|
||||||
|
tables.forEach(table => {
|
||||||
|
const data = db.findAll(table)
|
||||||
|
|
||||||
fs.writeFile(`./tmp/${table}.json`, JSON.stringify(data), function (err) {
|
fs.writeFile(`./tmp/${table}.json`, JSON.stringify(data), function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return console.log(err)
|
return console.log(err)
|
||||||
}
|
}
|
||||||
console.log('The file was saved!')
|
console.log('The file was saved!')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
|
|
||||||
17
src/main/ipcMain.ts
Normal file
17
src/main/ipcMain.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { ipcMain } from 'electron'
|
||||||
|
import { db, Tables } from './db'
|
||||||
|
|
||||||
|
export enum Events {
|
||||||
|
ClearAPICache = 'clear-api-cache',
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcMain.on(Events.ClearAPICache, () => {
|
||||||
|
db.truncate(Tables.TRACK)
|
||||||
|
db.truncate(Tables.ALBUM)
|
||||||
|
db.truncate(Tables.ARTIST)
|
||||||
|
db.truncate(Tables.PLAYLIST)
|
||||||
|
db.truncate(Tables.ARTIST_ALBUMS)
|
||||||
|
db.truncate(Tables.ACCOUNT_DATA)
|
||||||
|
db.truncate(Tables.AUDIO)
|
||||||
|
db.vacuum()
|
||||||
|
})
|
||||||
7
src/main/migrations/init.sql
Normal file
7
src/main/migrations/init.sql
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE "artist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
|
||||||
|
CREATE TABLE "album" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
|
||||||
|
CREATE TABLE "playlist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
|
||||||
|
CREATE TABLE "track" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
|
||||||
|
CREATE TABLE "artist_album" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
|
||||||
|
CREATE TABLE "audio" ("id" integer NOT NULL,"br" int NOT NULL,"type" text NOT NULL,"srouce" text NOT NULL,"updateAt" int NOT NULL, PRIMARY KEY (id));
|
||||||
|
CREATE TABLE "account_data" ("id" text NOT NULL,"json" text NOT NULL,"updateAt" int NOT NULL, PRIMARY KEY (id));
|
||||||
|
|
@ -56,7 +56,7 @@ const SearchBox = () => {
|
||||||
<div
|
<div
|
||||||
onClick={() => setKeywords('')}
|
onClick={() => setKeywords('')}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'cursor-default rounded-full p-1 transition after:bg-gray-300 hover:bg-white/20 dark:text-white/50',
|
'cursor-default rounded-full p-1 text-gray-600 transition hover:bg-gray-400/20 dark:text-white/50 dark:hover:bg-white/20',
|
||||||
!keywords && 'hidden'
|
!keywords && 'hidden'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ const Header = ({
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/80 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/[.85] to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='grid grid-cols-[17rem_auto] items-center gap-9'>
|
<div className='grid grid-cols-[17rem_auto] items-center gap-9'>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const Header = ({ artist }: { artist: Artist | undefined }) => {
|
||||||
<img src={coverImage} className='absolute w-full blur-[100px]' />
|
<img src={coverImage} className='absolute w-full blur-[100px]' />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/80 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/[.85] to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='relative mt-6 overflow-hidden rounded-2xl bg-gray-500/10 dark:bg-gray-800/20'>
|
<div className='relative mt-6 overflow-hidden rounded-2xl bg-gray-500/10 dark:bg-gray-800/20'>
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ const Header = memo(
|
||||||
<div className='absolute top-0 left-0 z-0 h-[24rem] w-full overflow-hidden'>
|
<div className='absolute top-0 left-0 z-0 h-[24rem] w-full overflow-hidden'>
|
||||||
<img src={coverUrl} className='absolute top-0 w-full blur-[100px]' />
|
<img src={coverUrl} className='absolute top-0 w-full blur-[100px]' />
|
||||||
<img src={coverUrl} className='absolute top-0 w-full blur-[100px]' />
|
<img src={coverUrl} className='absolute top-0 w-full blur-[100px]' />
|
||||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/80 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/[.85] to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='grid grid-cols-[17rem_auto] items-center gap-9'>
|
<div className='grid grid-cols-[17rem_auto] items-center gap-9'>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue