Files
obsidian-vault/personal/projects/media-pipeline-tracker-parsers.md
T

5.8 KiB

title, aliases, created, updated, status, tags, related
title aliases created updated status tags related
Media Pipeline — Roadmap
Медиа пайплайн роадмап
Media Pipeline roadmap
tracker parsers roadmap
2026-05-17 2026-05-24 active
media-pipeline
rutracker
rutor
nnm-club
personal/projects/media-pipeline-file-routing
family/projects/media-toolbox-kraken

Media Pipeline — Roadmap

Сделано

Шаг A — Transmission flow + Rutracker парсинг

  • TrackerPageParserRegistry — dispatch по url.host
  • RutrackerPageParser — CP1251/iconv, SwiftSoup, жанры из заголовка топика, KP/IMDb IDs
  • TrackerMediaKind — enum: movie/series/cartoon/documentary/music/audiobook/game/book/unknown
  • extractMediaKind — детект по BB.catId / FORUM_ID на странице Rutracker (100+ forum IDs)
  • TorrentPageMetadataFact.mediaKind + TorrentLocator.torrentId — пробрасывается через весь стек
  • QueryBuilderStrategytorrentTitle как предпочитаемый source для поиска
  • Fallback NFO при unresolved + torrentPageMetadata.hasRichData

Шаг B — Структура парсеров других трекеров

  • RutorPageParser, NNMClubPageParser, PirateBayPageParser, NyaaPageParser — структура реализована
  • Требуют верификации на живых HTML (нет тестовых fixture)

Шаг C — DirectoryPolicy + transmissionMove

  • DirectoryPolicy / MatchPolicy / MoveStrategy в конфиге — backward-compatible
  • FileAction.transmissionMove(torrentId:, from:, to:) — Codable
  • ApplyPhase — async execute, RPC → fallback filesystem
  • buildMovieActions — читает policy, needsSymlink, needsNFO, effectiveOutputDir
  • kindKey из реального TrackerMediaKinddestination_by_kind
  • transmissionMove когда есть torrentId, иначе move
  • config.json на Кракене — directory_policies для всех директорий
  • Canonical маркер .media-pipeline-canonical для music/books/games пишется в output директорию рядом с файлом

⚠️ Частично работает

Фильмы из downloads

  • .mkv/.mp4 → scanner видит → регион → transmissionMove/media/movies/ → canonical marker → повторный run скипает
  • TrackerMediaKind детектится по forum_id → правильная destination_by_kind

Музыка/книги/игры из downloads

  • Scanner не видит .mp3/.flac/.epub/.zip — нет videoExtensions для аудио
  • Регион не создаётся → buildMovieActions не вызывается → файл остаётся в downloads

📋 Следующие шаги

Шаг D — Audio/non-video scanner (приоритет)

Чтобы музыка/книги/игры из downloads реально перекладывались:

  1. AudioClassifierisAudioFile() для .mp3/.flac/.m4a/.ogg/.aac/.wav/.opus
  2. NonVideoRegionBuilder — создаёт регионы для директорий без video но с audio/doc файлами
  3. FileScanner — при наличии TrackerMediaKind != .movie/.series (из Transmission метаданных) создавать регион даже без video
  4. buildAudioActions в MediaFinalizer — move + NFO рядом, без symlink, canonical marker рядом
  5. Альтернатива (проще): unsorted fallback — отдельный pass по unsorted_dir через Transmission API, для торрентов без региона вызывать torrent-set-location на основе mediaKind из страницы трекера

Шаг E — Верификация парсеров

  • HTML fixture тесты для rutor, nnm-club на живых страницах
  • Проверить extractMediaKind на реальных forum_id

Шаг F — Series из downloads

  • buildSeriesActions сейчас не читает policy → нет move для сериалов из downloads
  • Нужно прокинуть torrentURLFacts/torrentPageFacts аналогично movie

Ключевые питфоллы

  • CP1251: /usr/bin/iconv через temp files — единственный способ на Linux
  • extractGenres — из заголовка топика [YEAR, жанр, ...], не из тела поста
  • transmissionMove генерируется только если scanner создал регион (нужен video файл)
  • Canonical marker для music/books: output == source dir → повторный run скипает через agentResolvedInLibrary
  • allOutputDirs в PipelineRunner не включает directoryPolicies[].output → нужно обновить

Файлы

  • Sources/MediaSources/APIs/TrackerParsers.swift — парсеры + registry + extractMediaKind
  • Sources/MediaDomain/Facts/TorrentPageMetadataFact.swiftTrackerMediaKind, поля
  • Sources/MediaDomain/Facts/TorrentInfoURLFact.swifttorrentId: Int?
  • Sources/MediaSources/Protocol/TorrentInfoProvider.swiftTorrentLocator.torrentId
  • Sources/MediaPipeline/Config/Config.swiftDirectoryPolicy, MatchPolicy, MoveStrategy
  • Sources/MediaPipeline/Apply/FileAction.swifttransmissionMove case
  • Sources/MediaPipeline/Apply/ApplyPhase.swift — async execute, RPC fallback
  • Sources/MediaPipeline/Apply/MediaFinalizer.swift — policy-aware routing, torrent extractors

Связанные заметки