Files
usenet-indexer/database/migrations/1768620765280_spot_listing_reads.ts
T
Daan MeijerandClaude Opus 5.5 ee898be8c8
Test and deploy / test (push) Successful in 57s
Test and deploy / deploy (push) Successful in 4m18s
Spots: more password phrasings; read listed spots' articles and NZBs
passwordFromSpot finds 30 more passwords in the stored descriptions (480
→ 510): words between keyword and separator, trailing "!!", the value on
the next line, "wachtwoord is x", "… wachtwoord. Deze is: x", "WW x" as a
whole line.

Listed spots were read from their overview only, so the NZB's own
password and the description were unknown for 2.27M of them.
SpotService.readListing reads the spot's article and NZB without
importing files: details, the NZB password (over a spot-text one), the
spot-text password, placeholder NZBs. worker:spots does a batch when
idle; spot:postprocess works through the history (nzb_read_at).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:46:32 +02:00

24 lines
965 B
TypeScript

import { BaseSchema } from '@adonisjs/lucid/schema'
/**
* Listed spots (D29) were only read from their overview: no description, no
* NZB, so neither a password in the spot's text nor the NZB's own
* `<meta type="password">` was known (LOG.md 2026-10-08 (10)). nzb_read_at:
* when the spot's article and NZB were read for that (SpotService.readListing),
* also set while a reader holds it. The index finds the ones still to read,
* newest first.
*/
export default class extends BaseSchema {
async up() {
await this.db.rawQuery(`ALTER TABLE spots ADD COLUMN IF NOT EXISTS nzb_read_at timestamptz`)
await this.db.rawQuery(
`CREATE INDEX IF NOT EXISTS spots_listing_unread_idx ON spots (posted_at DESC) WHERE status = 'listed' AND nzb_read_at IS NULL`
)
}
async down() {
await this.db.rawQuery(`DROP INDEX IF EXISTS spots_listing_unread_idx`)
await this.db.rawQuery(`ALTER TABLE spots DROP COLUMN IF EXISTS nzb_read_at`)
}
}