Rebuild: NZBs from the chunk store, and a catalog search
lib/nzb (buildNzb, parseNzb) from the current app; NzbService builds a release's NZB from its chunks; GET /api/v1/releases?q= (every word of the name) and GET /api/v1/releases/:id/nzb behind the api guard. A test stores a batch, finds the release and reads its NZB back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e9592dfd33
commit
fde1e6cc90
15 files changed
+446
-2
No files matched your search
@@ -0,0 +1,27 @@
|
||||
import type { HttpContext } from '@adonisjs/core/http'
|
||||
import db from '@adonisjs/lucid/services/db'
|
||||
import NzbService from '#services/nzb_service'
|
||||
|
||||
/** The catalog (REBUILD.md, part 9): a name search and a release's NZB. */
|
||||
export default class ReleasesController {
|
||||
/** Releases whose name has every word of `q` (dots, dashes, underscores and spaces alike), newest first. */
|
||||
async index({ request }: HttpContext) {
|
||||
const q = String(request.input('q', '')).trim()
|
||||
const limit = Math.min(Number(request.input('limit', 50)) || 50, 200)
|
||||
const query = db
|
||||
.from('releases')
|
||||
.select('id', 'name', 'poster', 'groups', 'posted_at', 'files', 'file_total', 'bytes', 'complete', 'readable')
|
||||
.orderBy('posted_at', 'desc')
|
||||
.limit(limit)
|
||||
for (const word of q.split(/[\s._-]+/).filter(Boolean)) query.whereILike('name', `%${word.replace(/[\\%_]/g, '\\$&')}%`)
|
||||
return { releases: await query }
|
||||
}
|
||||
|
||||
async nzb({ params, response }: HttpContext) {
|
||||
const nzb = await NzbService.build(Number(params.id))
|
||||
if (!nzb) return response.notFound({ error: 'No such release' })
|
||||
response.header('Content-Type', 'application/x-nzb')
|
||||
response.header('Content-Disposition', `attachment; filename="${nzb.name.replace(/["\\/]/g, '_')}.nzb"`)
|
||||
return nzb.xml
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user