diff --git a/apps/cli/src/commands/data_fix.ts b/apps/cli/src/commands/data_fix.ts new file mode 100644 index 00000000..50e23b8f --- /dev/null +++ b/apps/cli/src/commands/data_fix.ts @@ -0,0 +1,55 @@ +import { getDataVersionPath, updateConfig } from '@/config'; +import exitWithMessage from '@/utils/exit_with_message'; +import fs from 'fs'; +import { getDB } from '@/db'; +import { createSpinner, Spinner } from 'nanospinner'; +import { MusicProperty, MUSIC_TABLE_NAME } from '@/constants/db_definition'; + +async function fixMusicYear() { + let yearColumnExist = true; + try { + await getDB().get( + ` + SELECT ${MusicProperty.YEAR} FROM ${MUSIC_TABLE_NAME} + LIMIT 1 + `, + ); + } catch (error) { + yearColumnExist = false; + } + + if (!yearColumnExist) { + await getDB().run( + ` + ALTER TABLE music ADD year INTEGER + `, + ); + } +} + +export default async ({ data }: { data: string }) => { + updateConfig({ data }); + + if (!fs.existsSync(getDataVersionPath())) { + return exitWithMessage(`[ ${data} ] isn't a valid datadirectory`); + } + const dataVersion = Number( + fs.readFileSync(getDataVersionPath()).toString().replace(/\s/gm, ''), + ); + if (dataVersion !== 1) { + return exitWithMessage( + `This version of cicada can fix data only v1, your data version is v${dataVersion}`, + ); + } + + let spinner: Spinner; + + // eslint-disable-next-line prefer-const + spinner = createSpinner(); + spinner.start({ text: "Fixing music's year..." }); + await fixMusicYear(); + spinner.success({ text: "Music's year fixed" }); + + createSpinner().success({ text: 'Fixing data succeed' }); + return process.exit(); +}; diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index aff959af..2164e7a4 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -6,6 +6,7 @@ import definition from './definition'; import startServer from './commands/start_server'; import importMusic from './commands/import_music'; import dataUpgrade from './commands/data_upgrade'; +import dataFix from './commands/data_fix'; import { FIRST_USER_ID } from './constants'; const program = new Command() @@ -66,6 +67,24 @@ program return dataUpgrade({ data: absoluteData }); }); +/** + * 数据修复 + * @author mebtte + */ +program + .command('data-fix') + .description('fix data') + .argument('', 'cicada data directory') + .action((data: string) => { + const absoluteData = path.isAbsolute(data) + ? data + : path.resolve(process.cwd(), data); + if (!fs.existsSync(absoluteData)) { + return exitWithMessage(`[ ${absoluteData} ] not exist`); + } + return dataFix({ data: absoluteData }); + }); + /** * 导入音乐 * @author mebtte diff --git a/readme.md b/readme.md index d5e850a8..e153e9eb 100644 --- a/readme.md +++ b/readme.md @@ -120,20 +120,35 @@ cicada import --data /path_to/cicada_data music v0 升级到 v1 需要对数据进行升级后才能启动服务: -```bash +```sh # 进行数据升级前请先备份 cicada data-upgrade ``` 也可以通过 Docker 执行: -```bash +```sh # 默认使用 root 用户, 也可以使用 --user {uid}:{gid} 指定 docker run -it --rm -v :/data mebtte/cicada cicada data-upgrade /data ``` 如果不想升级到 v1, 请继续使用 [v0](https://github.com/mebtte/cicada/releases/tag/0.78.1) 版本的包或 Docker 镜像使用标签 `mebtte/cicada:v0`. +## 数据修复 + +由于已知问题的存在, 旧版本的知了一定情况下会导致数据出错, 可以通过 `data-fix` 命令进行修复: + +```sh +cicada data-fix +``` + +也可以通过 Docker 执行: + +```sh +# 默认使用 root 用户, 也可以使用 --user {uid}:{gid} 指定 +docker run -it --rm -v :/data mebtte/cicada cicada data-fix /data +``` + ## 常见问题