import { getPref } from "../../../../utils/prefs"; import { getString } from "../../../../utils/locale"; import { joinPath, normalizeStoragePath, sanitizePathSegment, } from "../platform/paths"; function resolveProfileDir(): string { const dir = (Zotero as any).Profile?.dir; if (typeof dir === "string" && dir.trim()) { return dir.trim(); } throw new Error("Cannot resolve Zotero profile directory"); } function customLectureDataDir(): string { return String(getPref("lectureDataDir") || "").trim(); } /** Map logical cacheKey (may contain `|`) to a filesystem-safe directory/file stem. */ export function cacheKeyDirName(cacheKey: string): string { return sanitizePathSegment(cacheKey, 100); } /** Resolved voice-lecture data root (custom pref or `{Profile}/chatpapers/lecture/`). */ export function lectureDataRoot(): string { const custom = customLectureDataDir(); if (custom) { return normalizeStoragePath(custom); } return joinPath(resolveProfileDir(), "chatpapers", "lecture"); } export function lectureDbPath(): string { return joinPath(lectureDataRoot(), "lecture.db"); } /** Interim JSON index until SQLite POC lands */ export function lectureIndexPath(): string { return joinPath(lectureDataRoot(), "cache-index.json"); } export function lectureDataFilePath(cacheKey: string): string { return joinPath(lectureDataRoot(), "data", `${cacheKeyDirName(cacheKey)}.json`); } export function audioRootDir(): string { return joinPath(lectureDataRoot(), "audio"); } export function audioDirForPaper(cacheKey: string): string { return joinPath(audioRootDir(), cacheKeyDirName(cacheKey)); } export function audioFilePath( cacheKey: string, unitId: string, ext: "wav" | "mp3" = "wav", ): string { return joinPath( audioDirForPaper(cacheKey), `${sanitizePathSegment(unitId, 80)}.${ext}`, ); } export function lectureSamplePath(name: string): string { return joinPath(lectureDataRoot(), "samples", sanitizePathSegment(name, 80)); } export async function ensureSampleDir(): Promise { const dir = joinPath(lectureDataRoot(), "samples"); await ensureDir(dir); return dir; } async function ensureDir(path: string): Promise { await IOUtils.makeDirectory(path, { createAncestors: true, ignoreExisting: true, }); } export async function ensureLectureDirs(): Promise { const root = lectureDataRoot(); try { await ensureDir(root); await ensureDir(joinPath(root, "data")); await ensureDir(audioRootDir()); } catch (e) { const detail = e instanceof Error ? e.message : String(e); throw new Error( getString("lecture-storage-write-failed", { args: { path: root, detail }, }), ); } }