Skip to content

Commit

Permalink
Get movies/series cover from tmdb if token is set
Browse files Browse the repository at this point in the history
  • Loading branch information
DerouineauNicolas committed Jun 18, 2024
1 parent 0c2fad3 commit 6fcfa4a
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ SUBPROCESS_VERBOSE_OUTPUT=False

#Number of gunicorn worker (should be set accordingly to your hardware)
NUM_GUNICORN_WORKER=4

TMBD_KEY=
17 changes: 14 additions & 3 deletions backend/StreamServerApp/database_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@

from StreamServerApp.media_management.fileinfo import createfileinfo, readfileinfo
from StreamServerApp.media_processing import prepare_video, get_video_type_and_info
from StreamServerApp.tasks import get_subtitles_async
from StreamServerApp.tasks import get_subtitles_async, download_cover_async
from StreamingServer import settings

import logging
from enum import Enum

logger = logging.getLogger("root")



def delete_DB_Infos():
""" delete all videos, movies and series in the db
"""
Expand Down Expand Up @@ -144,6 +146,10 @@ def update_db_from_local_folder(base_path, remote_url, keep_files=False, async_u
cache.set("processing_state", "finished", timeout=None)
cache.delete("processing_file")

class Add_video_return_value(Enum):
NO_SERIES_MOVIES_CREATED = 0
MOVIE_CREATED = 1
SERIES_CREATED = 2

@shared_task
def add_one_video_to_database(full_path,
Expand Down Expand Up @@ -211,17 +217,22 @@ def add_one_video_to_database(full_path,
v.episode = video_type_and_info['episode']

if created:
return_value = 2
return_value = Add_video_return_value.SERIES_CREATED.value

elif video_type_and_info['type'] == 'Movie':
movie, created = Movie.objects.get_or_create(
title=video_type_and_info['title'])
v.movie = movie

if created:
return_value = 1
return_value = Add_video_return_value.MOVIE_CREATED.value

v.save()
if os.getenv('TMBD_KEY'):
if return_value in [Add_video_return_value.SERIES_CREATED.value, Add_video_return_value.MOVIE_CREATED.value]:
download_cover_async.delay(
v.id, video_type_and_info['title'], True if video_type_and_info['type'] == 'Series' else False)

for ov_subtitle_path in video_infos["ov_subtitles"]:
ov_sub = Subtitle()
webvtt_subtitles_relative_path = os.path.relpath(
Expand Down
63 changes: 63 additions & 0 deletions backend/StreamServerApp/media_management/cover_downloader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import requests
import os

import logging
logger = logging.getLogger("root")


class cover_downloader:

def __init__(self):
self.auth_key = ""
env_auth_key = os.getenv('TMBD_KEY')
if not env_auth_key:
logger.error("cover downloader: no auth key")
return
self.auth_key = env_auth_key

configuration_url = 'https://api.themoviedb.org/3/configuration?&api_key={}'.format(
self.auth_key )

response = requests.get(configuration_url)
if response.status_code != 200:
logger.error("cover downloader: Failed to get configuration")
return
value = response.json()

self.base_url = value["images"]["base_url"]
self.poster_size = value["images"]["poster_sizes"][3]

def download_cover(self, name, outputfile, is_tv_show=False):

if self.auth_key:

if is_tv_show:
api_url = 'https://api.themoviedb.org/3/search/tv?query={}&api_key={}'.format(
name.replace(" ", "+"), self.auth_key)
else:
api_url = 'https://api.themoviedb.org/3/search/movie?query={}&api_key={}'.format(
name.replace(" ", "+"), self.auth_key)
response = requests.get(api_url)
if response.status_code != 200:
logger.error("cover downloader: Failed to search movie")
return -1
value = response.json()

if len(value["results"]) > 0:

poster_url = "{}/{}{}".format(self.base_url, self.poster_size,
value["results"][0]["poster_path"])
response = requests.get(poster_url)
if response.status_code != 200:
logger.error("cover downloader: Failed to download cover")
return -1

with open(outputfile, mode="wb") as file:
file.write(response.content)

return 1
else:
return -1
else:
logger.error("cover downloader: No properly initialized")
return -1
46 changes: 46 additions & 0 deletions backend/StreamServerApp/migrations/0026_auto_20240618_0917.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generated by Django 4.2 on 2024-06-18 09:17

from django.db import migrations
from StreamServerApp.models import Video, Series, Movie, Subtitle
from StreamServerApp.media_management.cover_downloader import cover_downloader
import os

cvdwnld = cover_downloader()

def get_cover(apps, schema_editor):

if os.getenv('TMBD_KEY'):

movies = Movie.objects.all()
for movie in movies:
output_file = "/usr/static/{}.jpeg".format(movie.title)
ret = cvdwnld.download_cover(movie.title, output_file, True)
if ret > 0:
videos = movie.video_set.all()
for video in videos:
video.thumbnail = "/static/{}.jpeg".format(movie.title)
video.save()


series = Series.objects.all()
for serie in series:
output_file = "/usr/static/{}.jpeg".format(serie.title)
ret = cvdwnld.download_cover(serie.title, output_file, True)
if ret > 0:
serie.thumbnail = "/static/{}.jpeg".format(serie.title)
serie.save()






class Migration(migrations.Migration):

dependencies = [
('StreamServerApp', '0025_video_audio_path'),
]

operations = [
migrations.RunPython(code=get_cover, reverse_code=migrations.RunPython.noop),
]
22 changes: 20 additions & 2 deletions backend/StreamServerApp/tasks.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from celery import shared_task
from StreamServerApp.models import Video, Series, Movie, Subtitle
import subprocess
import os
from StreamingServer.settings import STATIC_URL
from django.conf import settings
from StreamServerApp.media_management.cover_downloader import cover_downloader

import logging

logger = logging.getLogger("root")
cvdwnld = cover_downloader()


@shared_task
Expand All @@ -24,3 +25,20 @@ def get_subtitles_async(video_id, video_path, remote_url):
except Exception as e:
logger.exception(e)
return 0


@shared_task
def download_cover_async(id, name, is_tv_show=False):
output_file = "/usr/static/{}.jpeg".format(name)
ret = cvdwnld.download_cover(name, output_file, is_tv_show)
if ret > 0:
video = Video.objects.get(id=id)
if is_tv_show:
serie = Series.objects.get(id=video.series_id)
serie.thumbnail = "{}{}.jpeg".format(STATIC_URL, name)
serie.save()
else:
video.thumbnail = "{}{}.jpeg".format(STATIC_URL, name)
video.save()

return 0
17 changes: 17 additions & 0 deletions backend/StreamServerApp/tests/tests_cover_download.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django.test import TestCase
import os
from unittest import TestCase, mock
from StreamServerApp.media_management.cover_downloader import cover_downloader
import optparse

class CoverDownloaderTest(TestCase):

def setUp(self):
pass

@mock.patch.dict(os.environ, {"TMBD_KEY": ""})
def test_ensureErrorWithInvalidToken(self):

cvdwnld = cover_downloader()
self.assertEqual(cvdwnld.download_cover("test", "/test/test.jpeg", True), -1)

2 changes: 2 additions & 0 deletions backend/StreamingServer/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

STATIC_URL = '/static/'
STATIC_ROOT = '/usr/static/'
if os.getenv('DEPLOY_ENV', 'dev') == 'development':
STATIC_URL = 'http://localhost:1337/static/'

ALLOWED_HOSTS = ['web', 'localhost']

Expand Down
7 changes: 6 additions & 1 deletion backend/start_django_server.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
service transmission-daemon start
python3 /usr/src/app/manage.py collectstatic --no-input
python3 /usr/src/app/manage.py clearcache
gunicorn --workers=${NUM_GUNICORN_WORKER} StreamingServer.wsgi:application --bind 0.0.0.0:8000
if [[ "$DEPLOY_ENV" == "development" ]]
then
./wait-for-it.sh db:5432 -- python3 /usr/src/app/manage.py runserver 0.0.0.0:8000
else
gunicorn --workers=${NUM_GUNICORN_WORKER} StreamingServer.wsgi:application --bind 0.0.0.0:8000
fi
10 changes: 7 additions & 3 deletions docker-compose-debug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ services:
- .env
environment:
- DEBUG=1
- DEPLOY_ENV=development
volumes:
- ./backend/:/usr/src/app/
- ./log/:/debug/
- ./Videos/:/usr/src/app/Videos
- progress_volume:/usr/progress/
- static_volume:/usr/src/app/staticfiles
- static_volume:/usr/static/
- /static/
- ipython:/root/.ipython
- torrent:/usr/torrent/:rw
command: bash -c "service transmission-daemon start && ./wait-for-it.sh db:5432 -- python3 /usr/src/app/manage.py runserver 0.0.0.0:8000"
command: bash -c "./start_django_server.sh"
depends_on:
- db
- redis
Expand All @@ -50,7 +51,7 @@ services:
volumes:
- ./backend/:/usr/src/app/
- ./Videos/:/usr/src/app/Videos
- static_volume:/usr/src/app/staticfiles
- static_volume:/usr/static/
- torrent:/usr/torrent/:rw
- secrets_volume:/secrets/
ports:
Expand Down Expand Up @@ -79,11 +80,14 @@ services:
volumes:
- ./backend/:/usr/src/app/
- ./Videos/:/usr/src/app/Videos
- static_volume:/usr/static/
- progress_volume:/usr/progress/
- torrent:/usr/torrent/:rw
- ./log/:/debug/
env_file:
- .env
environment:
- DEPLOY_ENV=development
depends_on:
- db
- redis
Expand Down
1 change: 1 addition & 0 deletions docker-compose-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ services:
- ./Videos/:/usr/src/app/Videos
- torrent:/usr/torrent/:rw
- progress_volume:/usr/progress/
- static_volume:/usr/static/
- ./log/:/debug/
env_file:
- .env
Expand Down

0 comments on commit 6fcfa4a

Please sign in to comment.