[videos] Switch to TMDB for scraping videos
This commit is contained in:
@ -25,6 +25,7 @@ class VideoMetadata:
|
||||
60 # Silly default, but things break if this is 0 or null
|
||||
)
|
||||
imdb_id: Optional[str]
|
||||
tmdb_id: Optional[str]
|
||||
youtube_id: Optional[str]
|
||||
|
||||
# IMDB specific
|
||||
@ -35,6 +36,7 @@ class VideoMetadata:
|
||||
tv_series_id: Optional[int]
|
||||
plot: Optional[str]
|
||||
imdb_rating: Optional[str]
|
||||
tmdb_rating: Optional[str]
|
||||
cover_url: Optional[str]
|
||||
overview: Optional[str]
|
||||
|
||||
@ -59,6 +61,6 @@ class VideoMetadata:
|
||||
video_dict = vars(self)
|
||||
cover = None
|
||||
if "cover_url" in video_dict.keys():
|
||||
cover = video_dict.pop("cover_url")
|
||||
genres = video_dict.pop("genres")
|
||||
cover = video_dict.pop("cover_url", "")
|
||||
genres = video_dict.pop("genres", [])
|
||||
return video_dict, cover, genres
|
||||
|
||||
18
vrobbler/apps/videos/migrations/0023_video_tmdb_rating.py
Normal file
18
vrobbler/apps/videos/migrations/0023_video_tmdb_rating.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.19 on 2025-06-13 15:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('videos', '0022_alter_video_run_time_seconds'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='video',
|
||||
name='tmdb_rating',
|
||||
field=models.FloatField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@ -20,6 +20,7 @@ from scrobbles.mixins import (
|
||||
from taggit.managers import TaggableManager
|
||||
from videos.metadata import VideoMetadata
|
||||
from videos.sources.imdb import lookup_video_from_imdb
|
||||
from videos.sources.tmdb import lookup_video_from_tmdb
|
||||
from videos.sources.youtube import lookup_video_from_youtube
|
||||
|
||||
YOUTUBE_VIDEO_URL = "https://www.youtube.com/watch?v="
|
||||
@ -206,6 +207,7 @@ class Video(ScrobblableMixin):
|
||||
next_imdb_id = models.CharField(max_length=20, **BNULL)
|
||||
imdb_id = models.CharField(max_length=20, **BNULL)
|
||||
imdb_rating = models.FloatField(**BNULL)
|
||||
tmdb_rating = models.FloatField(**BNULL)
|
||||
cover_image = models.ImageField(upload_to="videos/video/", **BNULL)
|
||||
cover_image_small = ImageSpecField(
|
||||
source="cover_image",
|
||||
@ -307,11 +309,13 @@ class Video(ScrobblableMixin):
|
||||
def get_from_imdb_id(
|
||||
cls, imdb_id: str, overwrite: bool = False
|
||||
) -> "Video":
|
||||
if "tt" in imdb_id:
|
||||
imdb_id = imdb_id[2:]
|
||||
video, created = cls.objects.get_or_create(imdb_id=imdb_id)
|
||||
if not created and not overwrite:
|
||||
return video
|
||||
|
||||
vdict, cover, genres = lookup_video_from_imdb(
|
||||
vdict, cover, genres = lookup_video_from_tmdb(
|
||||
imdb_id
|
||||
).as_dict_with_cover_and_genres()
|
||||
if created or overwrite:
|
||||
|
||||
77
vrobbler/apps/videos/sources/tmdb.py
Normal file
77
vrobbler/apps/videos/sources/tmdb.py
Normal file
@ -0,0 +1,77 @@
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from themoviedb import TMDb
|
||||
from tmdbv3api import TV, TMDb as TMDb_direct
|
||||
from videos.metadata import VideoMetadata, VideoType
|
||||
|
||||
key = getattr(settings, "TMDB_API_KEY", "33de8d24785931068ae356510dcfbac8")
|
||||
key = "33de8d24785931068ae356510dcfbac8"
|
||||
|
||||
tmdb_direct = TMDb_direct()
|
||||
tmdb_direct.api_key = "33de8d24785931068ae356510dcfbac8"
|
||||
|
||||
tmdb = TMDb(key=key, language="en-US", region="US")
|
||||
|
||||
TMDB_STILL_URL = "https://image.tmdb.org/t/p/original"
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def lookup_video_from_tmdb(
|
||||
name_or_id: str, kind: str = "movie"
|
||||
) -> VideoMetadata:
|
||||
from videos.models import Series
|
||||
|
||||
imdb_id = name_or_id
|
||||
if name_or_id.startswith("tt"):
|
||||
imdb_id = name_or_id[2:]
|
||||
|
||||
video_metadata = VideoMetadata(imdb_id=imdb_id)
|
||||
imdb_result: dict = {}
|
||||
|
||||
tmdb_result = tmdb.find().by_imdb("tt" + imdb_id)
|
||||
|
||||
if not tmdb_result:
|
||||
logger.info(
|
||||
"[lookup_video_from_tmdb] no video found on tmdb",
|
||||
extra={"name_or_id": name_or_id},
|
||||
)
|
||||
return None
|
||||
|
||||
video_metadata = VideoMetadata(imdb_id=imdb_id)
|
||||
|
||||
media = None
|
||||
show = None
|
||||
if len(tmdb_result.movie_results) > 0:
|
||||
media = tmdb_result.movie_results[0]
|
||||
video_metadata.video_type = VideoType.MOVIE.value
|
||||
if len(tmdb_result.tv_episode_results) > 0:
|
||||
video_metadata.video_type = VideoType.TV_EPISODE.value
|
||||
media = tmdb_result.tv_episode_results[0]
|
||||
series_imdb_id = TV().external_ids(media.show_id).imdb_id[2:]
|
||||
|
||||
series, created = Series.objects.get_or_create(imdb_id=series_imdb_id)
|
||||
if created:
|
||||
show_data = TV().details(tv_id=media.show_id)
|
||||
series.name = show_data.name
|
||||
series.save()
|
||||
video_metadata.tv_series_id = series.id
|
||||
|
||||
if not media:
|
||||
logger.warning("Video not found on TMDB", extra={"imdb_id":imdb_id})
|
||||
return video_metadata
|
||||
|
||||
video_metadata.tmdb_id = media.id
|
||||
video_metadata.cover_url = TMDB_STILL_URL + media.still_path # TODO: enrich this with TMDB url
|
||||
video_metadata.run_time_seconds = media.runtime * 60
|
||||
video_metadata.title = media.name
|
||||
video_metadata.episode_number = media.episode_number
|
||||
video_metadata.season_number = media.season_number
|
||||
#video_metadata.next_imdb_id = imdb_result.get("next episode", None)
|
||||
video_metadata.year = media.air_date.year
|
||||
video_metadata.plot = media.overview
|
||||
video_metadata.imdb_rating = media.vote_average
|
||||
#video_metadata.genres = imdb_result.get("genres", [])
|
||||
|
||||
return video_metadata
|
||||
Reference in New Issue
Block a user