Optimize provider throttling.

pull/511/head
Halali 5 years ago
parent e023e82e44
commit 8303cb94dc

@ -4,6 +4,7 @@ import datetime
import logging import logging
import subliminal_patch import subliminal_patch
import pretty import pretty
import time
from get_args import args from get_args import args
from config import settings from config import settings
@ -33,6 +34,8 @@ PROVIDER_THROTTLE_MAP = {
PROVIDERS_FORCED_OFF = ["addic7ed", "tvsubtitles", "legendastv", "napiprojekt", "shooter", "hosszupuska", PROVIDERS_FORCED_OFF = ["addic7ed", "tvsubtitles", "legendastv", "napiprojekt", "shooter", "hosszupuska",
"supersubtitles", "titlovi", "argenteam", "assrt", "subscene"] "supersubtitles", "titlovi", "argenteam", "assrt", "subscene"]
throttle_count = {}
if not settings.general.throtteled_providers: if not settings.general.throtteled_providers:
tp = {} tp = {}
else: else:
@ -44,7 +47,7 @@ def provider_pool():
return subliminal_patch.core.SZAsyncProviderPool return subliminal_patch.core.SZAsyncProviderPool
return subliminal_patch.core.SZProviderPool return subliminal_patch.core.SZProviderPool
def get_providers(): def get_providers():
changed = False changed = False
providers_list = [] providers_list = []
@ -52,23 +55,23 @@ def get_providers():
for provider in settings.general.enabled_providers.lower().split(','): for provider in settings.general.enabled_providers.lower().split(','):
reason, until, throttle_desc = tp.get(provider, (None, None, None)) reason, until, throttle_desc = tp.get(provider, (None, None, None))
providers_list.append(provider) providers_list.append(provider)
if reason: if reason:
now = datetime.datetime.now() now = datetime.datetime.now()
if now < until: if now < until:
logging.debug("Not using %s until %s, because of: %s", provider, logging.debug("Not using %s until %s, because of: %s", provider,
until.strftime("%y/%m/%d %H:%M"), reason) until.strftime("%y/%m/%d %H:%M"), reason)
providers_list.remove(provider) providers_list.remove(provider)
else: else:
logging.info("Using %s again after %s, (disabled because: %s)", provider, throttle_desc, reason) logging.info("Using %s again after %s, (disabled because: %s)", provider, throttle_desc, reason)
del tp[provider] del tp[provider]
settings.general.throtteled_providers = str(tp) settings.general.throtteled_providers = str(tp)
changed = True changed = True
if changed: if changed:
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle: with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle:
settings.write(handle) settings.write(handle)
# if forced only is enabled: # fixme: Prepared for forced only implementation to remove providers with don't support forced only subtitles # if forced only is enabled: # fixme: Prepared for forced only implementation to remove providers with don't support forced only subtitles
# for provider in providers_list: # for provider in providers_list:
# if provider in PROVIDERS_FORCED_OFF: # if provider in PROVIDERS_FORCED_OFF:
@ -109,7 +112,7 @@ def get_providers_auth():
}, },
'xsubs': {'username': settings.xsubs.username, 'xsubs': {'username': settings.xsubs.username,
'password': settings.xsubs.password, 'password': settings.xsubs.password,
}, },
'assrt': {'token': settings.assrt.token, }, 'assrt': {'token': settings.assrt.token, },
'napisy24': {'username': settings.napisy24.username, 'napisy24': {'username': settings.napisy24.username,
'password': settings.napisy24.password, 'password': settings.napisy24.password,
@ -137,21 +140,52 @@ def provider_throttle(name, exception):
throttle_delta, throttle_description = throttle_data throttle_delta, throttle_description = throttle_data
throttle_until = datetime.datetime.now() + throttle_delta throttle_until = datetime.datetime.now() + throttle_delta
tp[name] = (cls_name, throttle_until, throttle_description) if throttled_count(name):
tp[name] = (cls_name, throttle_until, throttle_description)
settings.general.throtteled_providers = str(tp)
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle:
settings.write(handle)
logging.info("Throttling %s for %s, until %s, because of: %s. Exception info: %r", name, throttle_description,
throttle_until.strftime("%y/%m/%d %H:%M"), cls_name, exception.message)
def throttled_count(name):
global throttle_count
if name in throttle_count.keys():
if 'count' in throttle_count[name].keys():
for key, value in throttle_count[name].items():
if key == 'count':
value += 1
throttle_count[name]['count'] = value
else:
throttle_count[name] = {"count": 1, "time": (datetime.datetime.now() + datetime.timedelta(seconds=120))}
settings.general.throtteled_providers = str(tp) else:
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle: throttle_count[name] = {"count": 1, "time": (datetime.datetime.now() + datetime.timedelta(seconds=120))}
settings.write(handle)
logging.info("Throttling %s for %s, until %s, because of: %s. Exception info: %r", name, throttle_description, if throttle_count[name]['count'] < 5:
throttle_until.strftime("%y/%m/%d %H:%M"), cls_name, exception.message) if throttle_count[name]['time'] > datetime.datetime.now():
logging.info("Provider %s throttle count %s of 5, waiting 5sec and trying again", name,
throttle_count[name]['count'])
time.sleep(5)
return False
else:
throttle_count[name] = {"count": 1, "time": (datetime.datetime.now() + datetime.timedelta(seconds=120))}
logging.info("Provider %s throttle count %s of 5, waiting 5sec and trying again", name,
throttle_count[name]['count'])
time.sleep(5)
return False
else:
return True
def update_throttled_provider(): def update_throttled_provider():
changed = False changed = False
if settings.general.enabled_providers: if settings.general.enabled_providers:
for provider in settings.general.enabled_providers.lower().split(','): for provider in settings.general.enabled_providers.lower().split(','):
reason, until, throttle_desc = tp.get(provider, (None, None, None)) reason, until, throttle_desc = tp.get(provider, (None, None, None))
if reason: if reason:
now = datetime.datetime.now() now = datetime.datetime.now()
if now < until: if now < until:
@ -161,7 +195,7 @@ def update_throttled_provider():
del tp[provider] del tp[provider]
settings.general.throtteled_providers = str(tp) settings.general.throtteled_providers = str(tp)
changed = True changed = True
if changed: if changed:
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle: with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle:
settings.write(handle) settings.write(handle)

@ -5,7 +5,6 @@ import sys
import sqlite3 import sqlite3
import ast import ast
import logging import logging
import operator
import subprocess import subprocess
import time import time
import cPickle as pickle import cPickle as pickle
@ -13,7 +12,6 @@ import codecs
import types import types
import re import re
import subliminal import subliminal
import subliminal_patch
from datetime import datetime, timedelta from datetime import datetime, timedelta
from subzero.language import Language from subzero.language import Language
from subzero.video import parse_video from subzero.video import parse_video
@ -58,26 +56,23 @@ def get_video(path, title, sceneName, use_scenename, use_mediainfo, providers=No
path = os.path.join(os.path.dirname(path), sceneName + os.path.splitext(path)[1]) path = os.path.join(os.path.dirname(path), sceneName + os.path.splitext(path)[1])
used_scene_name = True used_scene_name = True
hash_from = original_path hash_from = original_path
if providers:
try: try:
video = parse_video(path, hints=hints, providers=providers, dry_run=used_scene_name, video = parse_video(path, hints=hints, providers=providers, dry_run=used_scene_name,
hash_from=hash_from) hash_from=hash_from)
video.used_scene_name = used_scene_name video.used_scene_name = used_scene_name
video.original_name = original_name video.original_name = original_name
video.original_path = original_path video.original_path = original_path
refine_from_db(original_path, video) refine_from_db(original_path, video)
if use_mediainfo:
refine_from_mediainfo(original_path, video)
logging.debug('BAZARR is using those video object properties: %s', vars(video))
return video
except: if use_mediainfo:
logging.exception("BAZARR Error trying to get video information for this file: " + path) refine_from_mediainfo(original_path, video)
else:
logging.info("BAZARR All providers are throttled") logging.debug('BAZARR is using those video object properties: %s', vars(video))
return None return video
except:
logging.exception("BAZARR Error trying to get video information for this file: " + path)
def get_scores(video, media_type, min_score_movie_perc=60 * 100 / 120.0, min_score_series_perc=240 * 100 / 360.0, def get_scores(video, media_type, min_score_movie_perc=60 * 100 / 120.0, min_score_series_perc=240 * 100 / 360.0,
@ -125,9 +120,9 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce
language = [language] language = [language]
if forced == "True": if forced == "True":
providers_auth['podnapisi']['only_foreign'] = True providers_auth['podnapisi']['only_foreign'] = True ## fixme: This is also in get_providers_auth()
providers_auth['subscene']['only_foreign'] = True providers_auth['subscene']['only_foreign'] = True ## fixme: This is also in get_providers_auth()
providers_auth['opensubtitles']['only_foreign'] = True providers_auth['opensubtitles']['only_foreign'] = True ## fixme: This is also in get_providers_auth()
else: else:
providers_auth['podnapisi']['only_foreign'] = False providers_auth['podnapisi']['only_foreign'] = False
providers_auth['subscene']['only_foreign'] = False providers_auth['subscene']['only_foreign'] = False
@ -161,8 +156,8 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce
post_download_hook=None, post_download_hook=None,
language_hook=None language_hook=None
""" """
video = get_video(force_unicode(path), title, sceneName, use_scenename, use_mediainfo, providers=providers,
video = get_video(force_unicode(path), title, sceneName, use_scenename, use_mediainfo, providers=providers, media_type=media_type) media_type=media_type)
if video: if video:
min_score, max_score, scores = get_scores(video, media_type, min_score_movie_perc=int(minimum_score_movie), min_score, max_score, scores = get_scores(video, media_type, min_score_movie_perc=int(minimum_score_movie),
min_score_series_perc=int(minimum_score)) min_score_series_perc=int(minimum_score))
@ -184,6 +179,7 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce
else: else:
downloaded_subtitles = None downloaded_subtitles = None
logging.info("BAZARR All providers are throttled") logging.info("BAZARR All providers are throttled")
return None
saved_any = False saved_any = False
if downloaded_subtitles: if downloaded_subtitles:
@ -273,9 +269,9 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce
if not saved_any: if not saved_any:
logging.debug('BAZARR No subtitles were found for this file: ' + path) logging.debug('BAZARR No subtitles were found for this file: ' + path)
return None return None
subliminal.region.backend.sync() subliminal.region.backend.sync()
logging.debug('BAZARR Ended searching subtitles for file: ' + path) logging.debug('BAZARR Ended searching subtitles for file: ' + path)
@ -317,8 +313,12 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa
minimum_score_movie = settings.general.minimum_score_movie minimum_score_movie = settings.general.minimum_score_movie
use_postprocessing = settings.general.getboolean('use_postprocessing') use_postprocessing = settings.general.getboolean('use_postprocessing')
postprocessing_cmd = settings.general.postprocessing_cmd postprocessing_cmd = settings.general.postprocessing_cmd
if providers:
video = get_video(force_unicode(path), title, sceneName, use_scenename, use_mediainfo, providers=providers, media_type=media_type) video = get_video(force_unicode(path), title, sceneName, use_scenename, use_mediainfo, providers=providers,
media_type=media_type)
else:
logging.info("BAZARR All providers are throttled")
return None
if video: if video:
min_score, max_score, scores = get_scores(video, media_type, min_score_movie_perc=int(minimum_score_movie), min_score, max_score, scores = get_scores(video, media_type, min_score_movie_perc=int(minimum_score_movie),
min_score_series_perc=int(minimum_score)) min_score_series_perc=int(minimum_score))
@ -333,6 +333,7 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa
else: else:
subtitles = [] subtitles = []
logging.info("BAZARR All providers are throttled") logging.info("BAZARR All providers are throttled")
return None
except Exception as e: except Exception as e:
logging.exception("BAZARR Error trying to get subtitle list from provider for this file: " + path) logging.exception("BAZARR Error trying to get subtitle list from provider for this file: " + path)
else: else:
@ -368,9 +369,9 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa
final_subtitles = sorted(subtitles_list, key=lambda x: x['score'], reverse=True) final_subtitles = sorted(subtitles_list, key=lambda x: x['score'], reverse=True)
logging.debug('BAZARR ' + str(len(final_subtitles)) + " subtitles have been found for this file: " + path) logging.debug('BAZARR ' + str(len(final_subtitles)) + " subtitles have been found for this file: " + path)
logging.debug('BAZARR Ended searching subtitles for this file: ' + path) logging.debug('BAZARR Ended searching subtitles for this file: ' + path)
subliminal.region.backend.sync() subliminal.region.backend.sync()
return final_subtitles return final_subtitles
@ -389,7 +390,8 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro
use_postprocessing = settings.general.getboolean('use_postprocessing') use_postprocessing = settings.general.getboolean('use_postprocessing')
postprocessing_cmd = settings.general.postprocessing_cmd postprocessing_cmd = settings.general.postprocessing_cmd
single = settings.general.getboolean('single_language') single = settings.general.getboolean('single_language')
video = get_video(force_unicode(path), title, sceneName, use_scenename, use_mediainfo, providers={provider}, media_type=media_type) video = get_video(force_unicode(path), title, sceneName, use_scenename, use_mediainfo, providers={provider},
media_type=media_type)
if video: if video:
min_score, max_score, scores = get_scores(video, media_type) min_score, max_score, scores = get_scores(video, media_type)
try: try:
@ -483,9 +485,9 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro
"BAZARR Tried to manually download a subtitles for file: " + path + " but we weren't able to do (probably throttled by " + str( "BAZARR Tried to manually download a subtitles for file: " + path + " but we weren't able to do (probably throttled by " + str(
subtitle.provider_name) + ". Please retry later or select a subtitles from another provider.") subtitle.provider_name) + ". Please retry later or select a subtitles from another provider.")
return None return None
subliminal.region.backend.sync() subliminal.region.backend.sync()
logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path) logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path)
@ -510,23 +512,29 @@ def series_download_subtitles(no):
count_episodes_details = len(episodes_details) count_episodes_details = len(episodes_details)
for i, episode in enumerate(episodes_details, 1): for i, episode in enumerate(episodes_details, 1):
for language in ast.literal_eval(episode[1]): if providers_list:
if language is not None: for language in ast.literal_eval(episode[1]):
notifications.write(msg='Searching for series subtitles...', queue='get_subtitle', item=i, if language is not None:
length=count_episodes_details) notifications.write(msg='Searching for series subtitles...', queue='get_subtitle', item=i,
result = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), length=count_episodes_details)
series_details[0], series_details[2], providers_list, result = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)),
providers_auth, str(episode[3]), series_details[1], 'series') series_details[0], series_details[2], providers_list,
if result is not None: providers_auth, str(episode[3]), series_details[1],
message = result[0] 'series')
path = result[1] if result is not None:
forced = result[5] message = result[0]
language_code = result[2] + ":forced" if forced else result[2] path = result[1]
provider = result[3] forced = result[5]
score = result[4] language_code = result[2] + ":forced" if forced else result[2]
store_subtitles(path_replace(episode[0])) provider = result[3]
history_log(1, no, episode[2], message, path, language_code, provider, score) score = result[4]
send_notifications(no, episode[2], message) store_subtitles(path_replace(episode[0]))
history_log(1, no, episode[2], message, path, language_code, provider, score)
send_notifications(no, episode[2], message)
else:
notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long')
logging.info("BAZARR All providers are throttled")
break
list_missing_subtitles(no) list_missing_subtitles(no)
if count_episodes_details: if count_episodes_details:
@ -551,26 +559,30 @@ def episode_download_subtitles(no):
providers_auth = get_providers_auth() providers_auth = get_providers_auth()
for episode in episodes_details: for episode in episodes_details:
for language in ast.literal_eval(episode[1]): if providers_list:
if language is not None: for language in ast.literal_eval(episode[1]):
notifications.write(msg='Searching for ' + str( if language is not None:
language_from_alpha2(language)) + ' subtitles for this episode: ' + path_replace(episode[0]), notifications.write(msg='Searching for ' + str(
queue='get_subtitle') language_from_alpha2(language)) + ' subtitles for this episode: ' + path_replace(episode[0]),
result = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), queue='get_subtitle')
episode[4], episode[7], providers_list, providers_auth, str(episode[3]), result = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)),
episode[5], 'series') episode[4], episode[7], providers_list, providers_auth, str(episode[3]),
if result is not None: episode[5], 'series')
message = result[0] if result is not None:
path = result[1] message = result[0]
forced = result[5] path = result[1]
language_code = result[2] + ":forced" if forced else result[2] forced = result[5]
provider = result[3] language_code = result[2] + ":forced" if forced else result[2]
score = result[4] provider = result[3]
store_subtitles(path_replace(episode[0])) score = result[4]
history_log(1, episode[6], episode[2], message, path, language_code, provider, score) store_subtitles(path_replace(episode[0]))
send_notifications(episode[6], episode[2], message) history_log(1, episode[6], episode[2], message, path, language_code, provider, score)
send_notifications(episode[6], episode[2], message)
list_missing_subtitles(episode[6]) else:
notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long')
logging.info("BAZARR All providers are throttled")
list_missing_subtitles(episode[6])
break
def movies_download_subtitles(no): def movies_download_subtitles(no):
@ -587,20 +599,26 @@ def movies_download_subtitles(no):
count_movie = len(ast.literal_eval(movie[1])) count_movie = len(ast.literal_eval(movie[1]))
for i, language in enumerate(ast.literal_eval(movie[1]), 1): for i, language in enumerate(ast.literal_eval(movie[1]), 1):
if language is not None: if providers_list:
notifications.write(msg='Searching for movies subtitles', queue='get_subtitle', item=i, length=count_movie) if language is not None:
result = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), movie[4], notifications.write(msg='Searching for movies subtitles', queue='get_subtitle', item=i,
movie[6], providers_list, providers_auth, str(movie[3]), movie[5], 'movie') length=count_movie)
if result is not None: result = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), movie[4],
message = result[0] movie[6], providers_list, providers_auth, str(movie[3]), movie[5], 'movie')
path = result[1] if result is not None:
forced = result[5] message = result[0]
language_code = result[2] + ":forced" if forced else result[2] path = result[1]
provider = result[3] forced = result[5]
score = result[4] language_code = result[2] + ":forced" if forced else result[2]
store_subtitles_movie(path_replace_movie(movie[0])) provider = result[3]
history_log_movie(1, no, message, path, language_code, provider, score) score = result[4]
send_notifications_movie(no, message) store_subtitles_movie(path_replace_movie(movie[0]))
history_log_movie(1, no, message, path, language_code, provider, score)
send_notifications_movie(no, message)
else:
notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long')
logging.info("BAZARR All providers are throttled")
break
list_missing_subtitles_movies(no) list_missing_subtitles_movies(no)
if count_movie: if count_movie:
@ -744,24 +762,28 @@ def wanted_search_missing_subtitles():
movies = c.fetchall() movies = c.fetchall()
c.close() c.close()
providers = get_providers()
if settings.general.getboolean('use_sonarr'): if settings.general.getboolean('use_sonarr'):
if providers:
count_episodes = len(episodes) count_episodes = len(episodes)
for i, episode in enumerate(episodes, 1): for i, episode in enumerate(episodes, 1):
providers = get_providers()
if providers:
wanted_download_subtitles(episode[0], i, count_episodes) wanted_download_subtitles(episode[0], i, count_episodes)
else: else:
notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long') notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long')
logging.info("BAZARR All providers are throttled") logging.info("BAZARR All providers are throttled")
return
if settings.general.getboolean('use_radarr'): if settings.general.getboolean('use_radarr'):
if providers: count_movies = len(movies)
count_movies = len(movies) for i, movie in enumerate(movies, 1):
for i, movie in enumerate(movies, 1): providers = get_providers()
if providers:
wanted_download_subtitles_movie(movie[0], i, count_movies) wanted_download_subtitles_movie(movie[0], i, count_movies)
else: else:
notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long') notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long')
logging.info("BAZARR All providers are throttled") logging.info("BAZARR All providers are throttled")
return
logging.info('BAZARR Finished searching for missing subtitles. Check histories for more information.') logging.info('BAZARR Finished searching for missing subtitles. Check histories for more information.')
@ -841,23 +863,23 @@ def refine_from_db(path, video):
def refine_from_mediainfo(path, video): def refine_from_mediainfo(path, video):
if video.fps: if video.fps:
return return
exe = get_binary('mediainfo') exe = get_binary('mediainfo')
if not exe: if not exe:
logging.debug('BAZARR MediaInfo library not found!') logging.debug('BAZARR MediaInfo library not found!')
return return
else: else:
logging.debug('BAZARR MediaInfo library used is %s', exe) logging.debug('BAZARR MediaInfo library used is %s', exe)
media_info = MediaInfo.parse(path, library_file=exe) media_info = MediaInfo.parse(path, library_file=exe)
video_track = next((t for t in media_info.tracks if t.track_type == 'Video'), None) video_track = next((t for t in media_info.tracks if t.track_type == 'Video'), None)
if not video_track: if not video_track:
logging.debug('BAZARR MediaInfo was unable to find video tracks in the file!') logging.debug('BAZARR MediaInfo was unable to find video tracks in the file!')
return return
logging.debug('MediaInfo found: %s', video_track.to_data()) logging.debug('MediaInfo found: %s', video_track.to_data())
if not video.fps: if not video.fps:
if video_track.frame_rate: if video_track.frame_rate:
video.fps = float(video_track.frame_rate) video.fps = float(video_track.frame_rate)
@ -920,6 +942,11 @@ def upgrade_subtitles():
if settings.general.getboolean('use_sonarr'): if settings.general.getboolean('use_sonarr'):
for i, episode in enumerate(episodes_to_upgrade, 1): for i, episode in enumerate(episodes_to_upgrade, 1):
providers = get_providers()
if not providers:
notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long')
logging.info("BAZARR All providers are throttled")
return
if episode[9] != "None": if episode[9] != "None":
desired_languages = ast.literal_eval(str(episode[9])) desired_languages = ast.literal_eval(str(episode[9]))
if episode[10] == "True": if episode[10] == "True":
@ -957,6 +984,11 @@ def upgrade_subtitles():
if settings.general.getboolean('use_radarr'): if settings.general.getboolean('use_radarr'):
for i, movie in enumerate(movies_to_upgrade, 1): for i, movie in enumerate(movies_to_upgrade, 1):
providers = get_providers()
if not providers:
notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long')
logging.info("BAZARR All providers are throttled")
return
if movie[8] != "None": if movie[8] != "None":
desired_languages = ast.literal_eval(str(movie[8])) desired_languages = ast.literal_eval(str(movie[8]))
if movie[9] == "True": if movie[9] == "True":

Loading…
Cancel
Save