Goon — self-hosted aggregator for adult-content scene metadata. Indexes scenes from TPDB, StashDB, and 30+ public adult tube sites. Cross-source deduplication via perceptual hash + Levenshtein distance. FastAPI backend + APScheduler worker + React Native (Expo) mobile client. FOSS, ad-free, donation-funded. See README for details.
66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
"""RawMovie → NormalizedMovie. Reuse normalize_studio/performer/tag z scenes.py."""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import date
|
|
|
|
from app.connectors.base import RawMovie, RawMovieChapter, RawPlaybackSource
|
|
from app.normalize.scenes import (
|
|
NormalizedPerformer,
|
|
NormalizedStudio,
|
|
NormalizedTag,
|
|
normalize_performer,
|
|
normalize_studio,
|
|
normalize_tag,
|
|
)
|
|
from app.normalize.text import normalize, slugify
|
|
|
|
|
|
@dataclass
|
|
class NormalizedMovie:
|
|
external_id: str
|
|
title: str
|
|
title_normalized: str
|
|
slug: str
|
|
release_year: int | None
|
|
release_date: date | None
|
|
description: str | None
|
|
duration_sec: int | None
|
|
director: str | None
|
|
country: str | None
|
|
rating: float | None
|
|
poster_url: str | None
|
|
backdrop_url: str | None
|
|
url: str | None
|
|
|
|
studio: NormalizedStudio | None = None
|
|
performers: list[NormalizedPerformer] = field(default_factory=list)
|
|
tags: list[NormalizedTag] = field(default_factory=list)
|
|
chapters: list[RawMovieChapter] = field(default_factory=list)
|
|
playback_sources: list[RawPlaybackSource] = field(default_factory=list)
|
|
cross_source_refs: dict[str, str] = field(default_factory=dict)
|
|
|
|
|
|
def normalize_movie(raw: RawMovie) -> NormalizedMovie:
|
|
return NormalizedMovie(
|
|
external_id=raw.external_id,
|
|
title=raw.title,
|
|
title_normalized=normalize(raw.title),
|
|
slug=slugify(raw.title),
|
|
release_year=raw.release_year,
|
|
release_date=raw.release_date,
|
|
description=raw.description,
|
|
duration_sec=raw.duration_sec,
|
|
director=raw.director,
|
|
country=raw.country,
|
|
rating=raw.rating,
|
|
poster_url=raw.poster_url,
|
|
backdrop_url=raw.backdrop_url,
|
|
url=raw.url,
|
|
studio=normalize_studio(raw.studio) if raw.studio else None,
|
|
performers=[normalize_performer(p) for p in raw.performers],
|
|
tags=[normalize_tag(t) for t in raw.tags],
|
|
chapters=list(raw.chapters),
|
|
playback_sources=list(raw.playback_sources),
|
|
cross_source_refs=dict(raw.cross_source_refs),
|
|
)
|