Files
Daan MeijerandClaude Opus 5.5 1322e42fb7
Test and deploy / test (push) Successful in 47s
Test and deploy / edge (push) Successful in 1m44s
Test and deploy / deploy (push) Skipped
Accounts with limits: a Newznab key and a tier per user, daily API and NZB counts, invites
ACCESS=accounts (config/access.ts; open stays the default and behaves as
before): Newznab and the catalog's releases routes name a user (apikey or
the web interface's token), whose tier sets searches and NZBs per UTC day
(Newznab 500/501, the catalog 429) and how far back they see (102/403).
Counted in one upsert per use, so the last one can't be taken twice;
caps, stats and refused requests aren't counted. Signup takes an invite
(SIGNUP), which may give a tier; ace access:invite, access:tier (extends a
running tier), access:suspend. The web interface signs in and shows the
day's usage and the Newznab key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:16:45 +02:00

84 lines
3.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
|--------------------------------------------------------------------------
| Routes file
|--------------------------------------------------------------------------
|
| The routes file is used for defining the HTTP routes.
|
*/
import { middleware } from '#start/kernel'
import router from '@adonisjs/core/services/router'
import { controllers } from '#generated/controllers'
import env from '#start/env'
/**
* Which routes this process serves (HTTP_ROUTES): `node`, the edge workers'
* API only (its own service: hour-long streams and batches of up to 256 MB
* parsed in-process don't hold up the web interface; LOG.md 2026-10-11 (3));
* `public`, everything else; `all` (the default, for development and tests).
*/
const routes = env.get('HTTP_ROUTES', 'all')
const publicRoutes = routes !== 'node'
const nodeRoutes = routes !== 'public'
router.get('/health', () => ({ ok: true, routes }))
if (publicRoutes) {
// The web interface is public/index.html (static middleware).
// Newznab API for Prowlarr, Sonarr, Radarr (from voyager 1).
router.get('/api', [controllers.Newznab, 'handle'])
}
router
.group(() => {
if (publicRoutes) {
router
.group(() => {
router.post('signup', [controllers.NewAccount, 'store'])
router.post('login', [controllers.AccessTokens, 'store'])
})
.prefix('auth')
.as('auth')
router
.group(() => {
router.get('profile', [controllers.Profile, 'show'])
router.post('api-key', [controllers.Profile, 'resetApiKey'])
router.post('logout', [controllers.AccessTokens, 'destroy'])
})
.prefix('account')
.as('profile')
.use(middleware.auth())
// How the web interface signs in: open, or accounts with limits (config/access.ts).
router.get('access', [controllers.Releases, 'access'])
// The catalog (REBUILD.md, part 9): open, as voyager 1's (the web interface uses it), unless ACCESS
// is `accounts`: then a user's token or apikey, counted as Newznab's are (AccessService).
router.get('releases', [controllers.Releases, 'index'])
router.get('releases/:id', [controllers.Releases, 'show']).where('id', router.matchers.number())
router.get('releases/:id/nzb', [controllers.Releases, 'nzb']).where('id', router.matchers.number())
router.get('stats', [controllers.Releases, 'stats'])
}
if (nodeRoutes) {
// Edge workers (REBUILD.md, parts 1–2).
router
.group(() => {
router.post('lease', [controllers.Node, 'lease'])
router.get('ranges/:id/stream', [controllers.Node, 'stream'])
router.post('ranges/:id/batches', [controllers.Node, 'batch'])
router.post('ranges/:id/heartbeat', [controllers.Node, 'heartbeat'])
router.post('ranges/:id/finish', [controllers.Node, 'finish'])
router.post('ranges/:id/release', [controllers.Node, 'release'])
router.post('ranges/:id/corrupt', [controllers.Node, 'corrupt'])
})
.prefix('node')
.as('node')
.use(middleware.auth({ guards: ['node'] }))
}
})
.prefix('/api/v1')