mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2025-02-21 08:25:54 +08:00
feat: 增加初始化sqlite的逻辑和其他更新
This commit is contained in:
parent
1b86cbbee1
commit
46fe2d734e
@ -14,7 +14,6 @@ export async function setCache(api: string, data: any, query: any) {
|
||||
case 'recommend/resource':
|
||||
case 'likelist': {
|
||||
if (!data) return
|
||||
console.log(api)
|
||||
db.upsert(Tables.ACCOUNT_DATA, {
|
||||
id: api,
|
||||
json: JSON.stringify(data),
|
||||
@ -23,7 +22,6 @@ export async function setCache(api: string, data: any, query: any) {
|
||||
break
|
||||
}
|
||||
case 'song/detail': {
|
||||
console.log('dsdadasdas')
|
||||
if (!data.songs) return
|
||||
const tracks = (data as FetchTracksResponse).songs.map(t => ({
|
||||
id: t.id,
|
||||
@ -35,10 +33,10 @@ export async function setCache(api: string, data: any, query: any) {
|
||||
}
|
||||
case 'album': {
|
||||
if (!data.album) return
|
||||
data.album.songs = (data as FetchTracksResponse).songs
|
||||
data.album.songs = data.songs
|
||||
db.upsert(Tables.ALBUM, {
|
||||
id: data.album.id,
|
||||
json: JSON.stringify(data),
|
||||
json: JSON.stringify(data.album),
|
||||
updatedAt: Date.now(),
|
||||
})
|
||||
break
|
||||
@ -63,9 +61,21 @@ export async function setCache(api: string, data: any, query: any) {
|
||||
}
|
||||
case 'artist/album': {
|
||||
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, {
|
||||
id: data.artist.id,
|
||||
json: JSON.stringify(data),
|
||||
json: JSON.stringify(modifiedData),
|
||||
updatedAt: Date.now(),
|
||||
})
|
||||
break
|
||||
@ -113,8 +123,13 @@ export function getCache(api: string, query: any): any {
|
||||
case 'album': {
|
||||
if (isNaN(Number(query?.id))) return
|
||||
const data = db.find(Tables.ALBUM, query.id)
|
||||
console.log(data)
|
||||
if (data?.json) return JSON.parse(data.json)
|
||||
if (data?.json)
|
||||
return {
|
||||
resourceState: true,
|
||||
songs: [],
|
||||
code: 200,
|
||||
album: JSON.parse(data.json),
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'playlist/detail': {
|
||||
@ -131,9 +146,19 @@ export function getCache(api: string, query: any): any {
|
||||
}
|
||||
case 'artist/album': {
|
||||
if (isNaN(Number(query?.id))) return
|
||||
const data = db.find(Tables.ARTIST_ALBUMS, query.id)
|
||||
if (data?.json) return JSON.parse(data.json)
|
||||
break
|
||||
|
||||
const artistAlbumsRaw = db.find(Tables.ARTIST_ALBUMS, query.id)
|
||||
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',
|
||||
PLAYLIST = 'playlist',
|
||||
ARTIST_ALBUMS = 'artist_album',
|
||||
USER_PLAYLISTS = 'user_playlist',
|
||||
|
||||
// Special tables
|
||||
ACCOUNT_DATA = 'account_data',
|
||||
@ -19,6 +18,19 @@ export enum Tables {
|
||||
const sqlite = new SQLite3(
|
||||
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 = {
|
||||
find: (table: Tables, key: number | string) => {
|
||||
@ -33,6 +45,24 @@ export const db = {
|
||||
findAll: (table: Tables) => {
|
||||
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) => {
|
||||
const valuesQuery = Object.keys(data)
|
||||
.map(key => `:${key}`)
|
||||
@ -63,26 +93,32 @@ export const db = {
|
||||
truncate: (table: Tables) => {
|
||||
return sqlite.prepare(`DELETE FROM ${table}`).run()
|
||||
},
|
||||
vacuum: () => {
|
||||
return sqlite.prepare('VACUUM').run()
|
||||
},
|
||||
}
|
||||
|
||||
ipcMain.on('db-export-json', () => {
|
||||
const tables = [
|
||||
Tables.ARTIST_ALBUMS,
|
||||
Tables.PLAYLIST,
|
||||
Tables.ALBUM,
|
||||
Tables.TRACK,
|
||||
Tables.ARTIST,
|
||||
Tables.AUDIO,
|
||||
Tables.ACCOUNT_DATA,
|
||||
]
|
||||
tables.forEach(table => {
|
||||
const data = db.findAll(table)
|
||||
// 导出tables到json文件,方便查看table大小
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
ipcMain.on('db-export-json', () => {
|
||||
const tables = [
|
||||
Tables.ARTIST_ALBUMS,
|
||||
Tables.PLAYLIST,
|
||||
Tables.ALBUM,
|
||||
Tables.TRACK,
|
||||
Tables.ARTIST,
|
||||
Tables.AUDIO,
|
||||
Tables.ACCOUNT_DATA,
|
||||
]
|
||||
tables.forEach(table => {
|
||||
const data = db.findAll(table)
|
||||
|
||||
fs.writeFile(`./tmp/${table}.json`, JSON.stringify(data), function (err) {
|
||||
if (err) {
|
||||
return console.log(err)
|
||||
}
|
||||
console.log('The file was saved!')
|
||||
fs.writeFile(`./tmp/${table}.json`, JSON.stringify(data), function (err) {
|
||||
if (err) {
|
||||
return console.log(err)
|
||||
}
|
||||
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
|
||||
onClick={() => setKeywords('')}
|
||||
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'
|
||||
)}
|
||||
>
|
||||
|
@ -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 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]' />
|
||||
</>
|
||||
)}
|
||||
<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 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'>
|
||||
<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 className='grid grid-cols-[17rem_auto] items-center gap-9'>
|
||||
|
Loading…
x
Reference in New Issue
Block a user