feat: 增加初始化sqlite的逻辑和其他更新

This commit is contained in:
qier222 2022-03-30 16:54:11 +08:00
parent 1b86cbbee1
commit 46fe2d734e
No known key found for this signature in database
GPG Key ID: 9C85007ED905F14D
9 changed files with 118 additions and 158 deletions

View File

@ -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
}
}
}

View File

@ -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!')
})
})
})

View File

@ -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
View 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()
})

View 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));

View File

@ -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'
)}
>

View File

@ -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'>

View File

@ -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'>

View File

@ -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'>