The previous flow required the operator to manually install yt-dlp on the server. Now the server downloads the correct binary for the current OS/arch from GitHub Releases (latest) the first time a playlist fetch is requested, caches it under %appdata%/.mc_custom (resolved per-OS), chmod +x's it on POSIX, and skips the download on every subsequent call. - shared/paths.ts: add getAppDataDir() + getMcCustomDir() that map %appdata% to ~/.config (Linux), ~/Library/Application Support (macOS), or process.env.APPDATA (Windows) so the path is OS-agnostic. - server/youtube.ts: replace the old "probe PATH and bail" probeYtDlp with ensureYtDlp(): picks the right GitHub asset name per platform.arch (yt-dlp.exe / yt-dlp_macos / yt-dlp_linux / yt-dlp_linux_aarch64 / yt-dlp_linux_armv7l), downloads it with redirect-following https.get to the install path, chmods +x, then verifies with `--version` before reporting success. Uses an installPromise singleton so concurrent requests don't race the download. On any failure it cleans up the partial file and throws YtDlpUnavailableError with a real reason. - docs/yt-dlp-setup.md: note that auto-install is now the default; manual install is only for environments where the auto-download fails. Smoke-tested on this Linux x64 box: first call downloads to ~/.config/.mc_custom/yt-dlp_linux and reports `2026.03.17`; second call takes ~700ms (just the version probe) and reuses the cached file.
34 lines
1.4 KiB
TypeScript
34 lines
1.4 KiB
TypeScript
import path from 'node:path'
|
|
import os from 'node:os'
|
|
|
|
// 컴파일 후 dist/shared/paths.js → 2단계 상위가 프로젝트 루트.
|
|
export const projectRoot = path.resolve(__dirname, '..', '..')
|
|
export const manifestRootPath = path.join(projectRoot, 'manifest.json')
|
|
export const manifestDirPath = path.join(projectRoot, 'manifest')
|
|
export const accountFilePath = path.join(projectRoot, 'account.json')
|
|
export const fileDirPath = path.join(projectRoot, 'file')
|
|
export const fileListDirPath = path.join(fileDirPath, 'list')
|
|
export const viewsDirPath = path.join(projectRoot, 'views')
|
|
export const publicDirPath = path.join(projectRoot, 'public')
|
|
|
|
/**
|
|
* 사용자 환경의 "%appdata%" 디렉터리(OS별 표준 사용자 데이터 경로)를 반환.
|
|
* - Windows : %APPDATA% (보통 C:\Users\<user>\AppData\Roaming)
|
|
* - macOS : ~/Library/Application Support
|
|
* - Linux 등 : $XDG_CONFIG_HOME 또는 ~/.config
|
|
*/
|
|
export function getAppDataDir(): string {
|
|
if (process.platform === 'win32') {
|
|
return process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming')
|
|
}
|
|
if (process.platform === 'darwin') {
|
|
return path.join(os.homedir(), 'Library', 'Application Support')
|
|
}
|
|
return process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config')
|
|
}
|
|
|
|
/** %appdata%/.mc_custom — 음악퀴즈 관련 외부 도구/캐시 보관 디렉터리. */
|
|
export function getMcCustomDir(): string {
|
|
return path.join(getAppDataDir(), '.mc_custom')
|
|
}
|