[M] Move files

This commit is contained in:
2025-11-22 12:06:03 +08:00
parent e15c7eb641
commit 161c13734c
31 changed files with 86 additions and 41 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
import type { ResultDocument, UserData } from "../shared/types";
import type { ResultDocument, UserData } from "./types";
export async function post(endpoint: string, data: any) {
+1 -1
View File
@@ -1,5 +1,5 @@
import { MongoClient } from "mongodb"
import type { UserDocument, ResultDocument } from "../../shared/types"
import type { UserDocument, ResultDocument } from "../types"
export const mongo = new MongoClient(process.env.MONGO_URL || "mongodb://cat:meow@localhost:27017/")
mongo.connect()
+1 -1
View File
@@ -1,4 +1,4 @@
import type { ResultDocument } from "../../shared/types"
import type { ResultDocument } from "../types"
import { dbs } from "./db"
import { ObjectId } from "mongodb"
+26 -2
View File
@@ -1,11 +1,11 @@
import * as ne from '@neteasecloudmusicapienhanced/api'
import { aiParseLyrics } from './tools/lyrics'
import type { NeteaseSong, UserDocument } from '../../shared/types'
import type { NeteaseSong, UserDocument } from '../types'
import { dbs } from './db'
import { franc } from 'franc'
import { error } from '@sveltejs/kit'
import type { ObjectId } from 'mongodb'
import '../../shared/ext'
import '../ext'
import { promises as fs } from 'fs'
import path from 'path'
@@ -168,6 +168,30 @@ export const prepareSong = async (songId: number) => {
const taskAudio = addTask('从网易云获取音乐')
await getSongUrl(songId)
taskAudio.progress = 1
// 4. Source Separation
const taskSeparation = addTask('AI 人声分离')
const vocalsPath = path.join(CACHE_DIR, `${songId}/vocals.mp3`)
let retries = 0
// Wait up to 10 minutes (separation can be slow on CPU)
while (retries < 600) {
try {
await fs.access(vocalsPath)
taskSeparation.progress = 1
break
} catch {
// File doesn't exist yet
await new Promise(r => setTimeout(r, 1000))
retries++
// Update progress to show it's alive
if (retries % 5 === 0) taskSeparation.progress = Math.min(0.99, retries / 600)
}
}
if (taskSeparation.progress < 1) {
addTask('警告: AI 人声分离超时,请检查后台脚本').progress = -1
}
state.status = 'done'
+1 -1
View File
@@ -1,5 +1,5 @@
import { OpenRouter } from '@openrouter/sdk'
import type { LyricLine, LyricSegment } from '../../../shared/types'
import type { LyricLine, LyricSegment } from '../../types'
import { isKana, isKanji } from 'wanakana'
// Please put OPENROUTER_API_KEY in your environment variables.
+1 -1
View File
@@ -1,5 +1,5 @@
import { dbs } from "./db"
import { type UserDocument, type UserData } from "../../shared/types.ts";
import { type UserDocument, type UserData } from "$lib/types.ts";
import { error } from "@sveltejs/kit";
const users = dbs.users
@@ -1,6 +1,6 @@
<script lang="ts">
import { artistAndAlbum } from "../../shared/tools.ts";
import type { NeteaseSong } from "../../shared/types.ts";
import type { NeteaseSong } from "$lib/types.ts";
import ImageListItem from "./ImageListItem.svelte";
let { info }: { info: NeteaseSong } = $props();
+24
View File
@@ -0,0 +1,24 @@
import type { NeteaseSong } from "../lib/types";
export const artistAndAlbum = (song: NeteaseSong) => `${song.ar.map(it => it.name).join(', ')} - ${song.al.name}`
/**
* Waits for a condition to become true.
* @param condition A function that returns a boolean or a Promise<boolean>.
* @param options Optional configuration for interval and timeout.
* @returns A Promise that resolves when the condition becomes true.
* @throws Error if the timeout is reached.
*/
export async function waitFor(
condition: () => boolean | Promise<boolean>,
options: { interval?: number; timeout?: number } = {}
): Promise<void> {
const { interval = 100, timeout = 5000 } = options;
const startTime = Date.now();
while (true) {
if (await condition()) return
if (Date.now() - startTime > timeout) throw new Error(`Timeout of ${timeout}ms waiting for condition`)
await new Promise((resolve) => setTimeout(resolve, interval))
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ This page is vibe-coded. It's not a part of the regular UI intended for users an
import { onDestroy, onMount } from 'svelte';
import { API } from '$lib/client';
import { fade, scale } from 'svelte/transition';
import AppBar from "../../../components/appbar/AppBar.svelte";
import AppBar from "$lib/ui/appbar/AppBar.svelte";
import { Layer } from "m3-svelte";
let status = $state<'loading' | 'waiting_scan' | 'waiting_confirm' | 'success' | 'error'>('loading');
+5 -5
View File
@@ -1,10 +1,10 @@
<script lang="ts">
import { TextFieldOutlined } from "m3-svelte"
import AppBar from "../../../components/appbar/AppBar.svelte"
import Button from "../../../components/Button.svelte"
import type { NeteaseSong } from "../../../shared/types"
import { API } from "../../../lib/client"
import ErrorDialog from "../../../components/status/ErrorDialog.svelte";
import AppBar from "$lib/ui/appbar/AppBar.svelte"
import Button from "$lib/ui/button/Button.svelte"
import type { NeteaseSong } from "$lib/types"
import { API } from "$lib/client"
import ErrorDialog from "$lib/ui/status/ErrorDialog.svelte";
import ProgressList from "./ProgressList.svelte";
let link = $state('')
+3 -3
View File
@@ -1,9 +1,9 @@
<script lang="ts">
import type { PageProps } from "./$types"
import { goto } from "$app/navigation";
import AppBar from "../../../components/appbar/AppBar.svelte";
import Button from "../../../components/Button.svelte";
import SongInfo from "../../../components/listitem/SongInfo.svelte";
import AppBar from "$lib/ui/appbar/AppBar.svelte";
import Button from "$lib/ui/button/Button.svelte";
import SongInfo from "$lib/ui/listitem/SongInfo.svelte";
import { API } from "$lib/client";
let { data }: PageProps = $props()
+3 -3
View File
@@ -1,8 +1,8 @@
<script lang="ts">
import { goto } from "$app/navigation"
import AppBar from "../../../components/appbar/AppBar.svelte"
import ImageListItem from "../../../components/listitem/ImageListItem.svelte"
import MenuItem from "../../../components/material3/MenuItem.svelte"
import AppBar from "$lib/ui/appbar/AppBar.svelte"
import ImageListItem from "$lib/ui/listitem/ImageListItem.svelte"
import MenuItem from "$lib/ui/material3/MenuItem.svelte"
import type { PageProps } from "./$types"
let { data }: PageProps = $props()
+4 -4
View File
@@ -1,14 +1,14 @@
<script lang="ts">
import type { PageProps } from "./$types"
import { goto } from "$app/navigation"
import AppBar from "../../../components/appbar/AppBar.svelte"
import { artistAndAlbum } from "../../../shared/tools"
import Button from "../../../components/Button.svelte"
import AppBar from "$lib/ui/appbar/AppBar.svelte"
import { artistAndAlbum } from "$lib/utils"
import Button from "$lib/ui/Button.svelte"
import Chart from "chart.js/auto"
import { API } from "$lib/client"
import type { NeteaseSong, UserData } from "../../../shared/types"
import type { NeteaseSong, UserData } from "../../../lib/types"
let { data }: PageProps = $props()
+3 -3
View File
@@ -1,10 +1,10 @@
<script lang="ts">
import { API } from "$lib/client"
import { onMount } from "svelte"
import Button from "../../../components/Button.svelte"
import AppBar from "../../../components/appbar/AppBar.svelte"
import Button from "$lib/ui/Button.svelte"
import AppBar from "$lib/ui/appbar/AppBar.svelte"
import { goto } from "$app/navigation"
import { artistAndAlbum } from "../../../shared/tools.ts"
import { artistAndAlbum } from "$lib/utils"
import ProgressList from "../../import/netease/ProgressList.svelte"
let { data } = $props()
+5 -5
View File
@@ -1,17 +1,17 @@
<script lang="ts">
import AppBar from "../../../../components/appbar/AppBar.svelte"
import AppBar from "$lib/ui/appbar/AppBar.svelte"
import type { PageProps } from "./$types"
import { LinearProgress } from "m3-svelte"
import { onMount, tick } from "svelte"
import { typingSettingsDefault, type LyricSegment } from "../../../../shared/types.ts"
import { typingSettingsDefault, type LyricSegment } from "$lib/types.ts"
import { isKana, isKanji, toHiragana, toKatakana, toRomaji } from "wanakana"
import { composeList, fuzzyEquals, processLrcLine, dedupLines, type ProcLrcLine, type ProcLrcSeg } from "./IMEHelper.ts"
import MenuItem from "../../../../components/material3/MenuItem.svelte"
import "../../../../shared/ext.ts"
import MenuItem from "$lib/ui/material3/MenuItem.svelte"
import "$lib/ext.ts"
import { API } from "$lib/client.ts"
import { animateCaret } from "./animation.ts"
import { goto } from '$app/navigation'
import { artistAndAlbum } from "../../../../shared/tools.ts"
import { artistAndAlbum } from "$lib/utils.ts"
import { MusicControl } from "./MusicControl.ts"
let { data }: PageProps = $props()
+1 -1
View File
@@ -1,5 +1,5 @@
import { toHiragana } from "wanakana";
import type { LyricLine, LyricSegment } from "../../../../shared/types";
import type { LyricLine, LyricSegment } from "$lib/types";
export type ProcLrcSeg = { swi: number, kanji?: string, kana: string }
export type ProcLrcLine = { parts: ProcLrcSeg[], totalLen: number }
+1 -1
View File
@@ -1,5 +1,5 @@
import * as Tone from 'tone'
import type { LyricLine } from '../../../../shared/types'
import type { LyricLine } from '$lib/types'
export class MusicControl {
player: Tone.Player
+4 -4
View File
@@ -1,10 +1,10 @@
<script lang="ts">
import { TextFieldOutlined } from "m3-svelte"
import AppBar from "../../components/appbar/AppBar.svelte"
import Button from "../../components/Button.svelte"
import Dialog from "../../components/status/Dialog.svelte"
import AppBar from "$lib/ui/appbar/AppBar.svelte"
import Button from "$lib/ui/Button.svelte"
import Dialog from "$lib/ui/status/Dialog.svelte"
import { API } from "$lib/client"
import ErrorDialog from "../../components/status/ErrorDialog.svelte"
import ErrorDialog from "$lib/ui/status/ErrorDialog.svelte"
let showCodeOpen = $state(false)
let loginSuccessOpen = $state(false)
-3
View File
@@ -1,3 +0,0 @@
import type { NeteaseSong } from "./types";
export const artistAndAlbum = (song: NeteaseSong) => `${song.ar.map(it => it.name).join(', ')} - ${song.al.name}`