add more management capabilities

This commit is contained in:
Garret Patti
2026-04-11 18:33:03 -04:00
parent 1ca90184f5
commit 768c49ef00
16 changed files with 1420 additions and 55 deletions

View File

@@ -5,6 +5,7 @@ import { getLibrary, resolveLibraryRoot, resolveAndJail } from '@/lib/libraries'
import { tvSeriesFromDb, tvSeasonsFromDb, tvEpisodesFromDb } from '@/lib/tv'
import { removeAllAssignmentsForItem } from '@/lib/tags'
import { requireLibraryAccess, requireAdmin } from '@/lib/auth'
import { getDb } from '@/lib/db'
export async function GET(request: NextRequest) {
const { searchParams } = request.nextUrl
@@ -45,6 +46,7 @@ export async function DELETE(request: NextRequest) {
const { searchParams } = request.nextUrl
const libraryId = searchParams.get('libraryId')
const seriesId = searchParams.get('seriesId')
const episodeKey = searchParams.get('episodeKey')
if (!libraryId || !seriesId) {
return NextResponse.json({ error: 'Missing libraryId or seriesId' }, { status: 400 })
@@ -59,6 +61,38 @@ export async function DELETE(request: NextRequest) {
}
const root = resolveLibraryRoot(library)
// Episode-level delete
if (episodeKey) {
const db = getDb()
const row = db.prepare('SELECT file_path FROM media_items WHERE item_key = ?').get(episodeKey) as { file_path: string | null } | undefined
if (!row?.file_path) {
return NextResponse.json({ error: 'Episode not found' }, { status: 404 })
}
let episodePath: string
try {
episodePath = resolveAndJail(root, row.file_path)
} catch {
return NextResponse.json({ error: 'Invalid episode path' }, { status: 400 })
}
try {
fs.unlinkSync(episodePath)
// Also remove sidecar NFO if it exists
const nfoPath = episodePath.replace(path.extname(episodePath), '.nfo')
if (fs.existsSync(nfoPath)) fs.unlinkSync(nfoPath)
} catch {
return NextResponse.json({ error: 'Failed to delete episode file' }, { status: 500 })
}
removeAllAssignmentsForItem(episodeKey)
db.prepare('DELETE FROM media_items WHERE item_key = ?').run(episodeKey)
return new NextResponse(null, { status: 204 })
}
// Series-level delete
const dirName = decodeURIComponent(seriesId)
let seriesDir: string