goon/app/normalize/movies.py
goon-foss ad0284585b Initial commit
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.
2026-05-20 10:10:22 +02:00

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),
)