Spots: the spotter and the spot inspector, passwords kept apart
Two processes, one NNTP connection each (the coordinator 40 -> 38): - spots:read (service spotter): free.pt's overviews after the last article seen, each spot's full header verified (lib/spotnet from voyager 1, as Spotweb), its description, website and NZB articles; the password its title or text names; delete/dispose messages applied. - spots:inspect (service spot-inspector): each spot's compressed NZB read, its files listed (spot_files), each matched to the header pass's release by the same release identity in one of its groups within 48 h (release_spots); unmatched spots matched again hourly, after 24 h a release of their own (source spot) with the spot's NZB. - release_passwords: per release and password, its source (nzb, spot-title, spot-text) and spot; the catalog keeps only passworded. XoverClient.head(); PROBE_CONNECTIONS default 10. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3fd08b598a
commit
7df5a638ca
20 files changed
+1782
-8
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import { BaseCommand, flags } from '@adonisjs/core/ace'
|
||||
import type { CommandOptions } from '@adonisjs/core/types/ace'
|
||||
import { SpotInspector } from '#services/spot_inspector'
|
||||
|
||||
/** The spot inspector (REBUILD.md, spots): each spot's NZB read, its files listed and matched to releases. */
|
||||
export default class SpotsInspect extends BaseCommand {
|
||||
static commandName = 'spots:inspect'
|
||||
static description = "Reads each listed spot's NZB, lists its files and links them to the releases they match"
|
||||
static options: CommandOptions = { startApp: true, staysAlive: true }
|
||||
|
||||
@flags.boolean({ description: 'One round, then exit' })
|
||||
declare once: boolean
|
||||
|
||||
async run() {
|
||||
const inspector = new SpotInspector()
|
||||
if (this.once) {
|
||||
const round = await inspector.round()
|
||||
this.logger.info(`${round.inspected} spots inspected, ${round.matched} matched releases, ${round.standalone} of their own.`)
|
||||
inspector.stop()
|
||||
await this.terminate()
|
||||
return
|
||||
}
|
||||
let done: () => void
|
||||
const finished = new Promise<void>((resolve) => (done = resolve))
|
||||
this.app.terminating(async () => {
|
||||
inspector.stop()
|
||||
await finished
|
||||
})
|
||||
await inspector.run()
|
||||
this.logger.info('Spot inspector stopped.')
|
||||
done!()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { BaseCommand, flags } from '@adonisjs/core/ace'
|
||||
import type { CommandOptions } from '@adonisjs/core/types/ace'
|
||||
import { Spotter } from '#services/spotter'
|
||||
|
||||
/** The spotter (REBUILD.md, spots): Spotnet's spots from free.pt's headers into `spots`, on one connection. */
|
||||
export default class SpotsRead extends BaseCommand {
|
||||
static commandName = 'spots:read'
|
||||
static description = "Reads Spotnet's spots (free.pt) into the spots table, verified, every few minutes"
|
||||
static options: CommandOptions = { startApp: true, staysAlive: true }
|
||||
|
||||
@flags.boolean({ description: 'One round, then exit' })
|
||||
declare once: boolean
|
||||
|
||||
async run() {
|
||||
const spotter = new Spotter()
|
||||
if (this.once) {
|
||||
const round = await spotter.round()
|
||||
this.logger.info(`${round.read} articles read: ${round.listed} spots listed, ${round.unverified} unverified, ${round.moderation} moderation.`)
|
||||
spotter.stop()
|
||||
await this.terminate()
|
||||
return
|
||||
}
|
||||
let done: () => void
|
||||
const finished = new Promise<void>((resolve) => (done = resolve))
|
||||
this.app.terminating(async () => {
|
||||
spotter.stop()
|
||||
await finished
|
||||
})
|
||||
await spotter.run()
|
||||
this.logger.info('Spotter stopped.')
|
||||
done!()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user