diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 066b2d920..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/README.md b/README.md index f37589825..ef15757bf 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ You can reach us for support on [Discord](https://discord.gg/MH2e2eb). If you find a bug, please open an issue on [Github](https://github.com/morpheus65535/bazarr/issues). # Feature Requests -If you need something that is not already part of Bazarr, feel free to create a feature request on [Github](https://github.com/morpheus65535/bazarr/issues). +If you need something that is not already part of Bazarr, feel free to create a feature request on [Feature Upvote](http://features.bazarr.media). ## Major Features Include: diff --git a/bazarr.py b/bazarr.py index 12a3e382b..04ef801e7 100644 --- a/bazarr.py +++ b/bazarr.py @@ -7,6 +7,7 @@ import time import os import sys import platform +import re from bazarr.get_args import args @@ -22,7 +23,7 @@ def check_python_version(): print("Python " + minimum_python3_version + " or greater required. Current version is " + platform.python_version() + ". Please upgrade Python.") os._exit(0) - elif int(python_version[0]) == minimum_python_version_tuple[0] and (int(python_version[1]) < minimum_python_version_tuple[1] or int(python_version[2].rstrip('+')) < minimum_python_version_tuple[2]): + elif int(python_version[1]) < minimum_python_version_tuple[1] or int(re.search(r'\d+', python_version[2]).group()) < minimum_python_version_tuple[2]: print("Python " + minimum_python_version + " or greater required. Current version is " + platform.python_version() + ". Please upgrade Python.") os._exit(0) diff --git a/bazarr/get_subtitle.py b/bazarr/get_subtitle.py index 980bf9b35..4aea94aca 100644 --- a/bazarr/get_subtitle.py +++ b/bazarr/get_subtitle.py @@ -75,7 +75,7 @@ def get_video(path, title, sceneName, use_scenename, providers=None, media_type= refine_from_db(original_path, video) refine_from_ffprobe(original_path, video) - logging.debug('BAZARR is using those video object properties: %s', vars(video)) + logging.debug('BAZARR is using these video object properties: %s', vars(video)) return video except Exception as e: @@ -205,7 +205,7 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce path_decoder=None ) except Exception as e: - logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) + logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path) pass else: saved_any = True @@ -275,12 +275,12 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score, subtitle.language.forced 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 subliminal.region.backend.sync() - logging.debug('BAZARR Ended searching subtitles for file: ' + path) + logging.debug('BAZARR Ended searching Subtitles for file: ' + path) def manual_search(path, language, hi, forced, providers, providers_auth, sceneName, title, media_type): @@ -343,7 +343,7 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa logging.info("BAZARR All providers are throttled") return None 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: subtitles_list = [] @@ -378,8 +378,8 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa url=s.page_link, matches=list(matches), dont_matches=list(not_matched))) 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 Ended searching subtitles 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) subliminal.region.backend.sync() @@ -388,7 +388,7 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa def manual_download_subtitle(path, language, hi, forced, subtitle, provider, providers_auth, sceneName, title, media_type): - logging.debug('BAZARR Manually downloading subtitles for this file: ' + path) + logging.debug('BAZARR Manually downloading Subtitles for this file: ' + path) if settings.general.getboolean('utf8_encode'): os.environ["SZ_KEEP_ENCODING"] = "" @@ -413,11 +413,11 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro logging.info("BAZARR All providers are throttled") return None except Exception as e: - logging.exception('BAZARR Error downloading subtitles for this file ' + path) + logging.exception('BAZARR Error downloading Subtitles for this file ' + path) return None else: if not subtitle.is_valid(): - logging.exception('BAZARR No valid subtitles file found for this file: ' + path) + logging.exception('BAZARR No valid Subtitles file found for this file: ' + path) return try: score = round(subtitle.score / max_score * 100, 2) @@ -432,7 +432,7 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro path_decoder=None) except Exception as e: - logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) + logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path) return else: if saved_subtitles: @@ -447,7 +447,7 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro downloaded_path = saved_subtitle.storage_path logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) is_forced_string = " forced" if subtitle.language.forced else "" - message = downloaded_language + is_forced_string + " subtitles downloaded from " + downloaded_provider + " with a score of " + six.text_type( + message = downloaded_language + is_forced_string + " Subtitles downloaded from " + downloaded_provider + " with a score of " + six.text_type( score) + "% using manual search." if use_postprocessing is True: @@ -493,13 +493,13 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score, subtitle.language.forced else: logging.error( - "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.") + "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.") return None subliminal.region.backend.sync() - logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path) + logging.debug('BAZARR Ended manually downloading Subtitles for file: ' + path) def manual_upload_subtitle(path, language, forced, title, scene_name, media_type, subtitle): @@ -537,7 +537,7 @@ def manual_upload_subtitle(path, language, forced, title, scene_name, media_type if chmod: os.chmod(subtitle_path, chmod) - message = language_from_alpha3(language) + (" forced" if forced else "") + " subtitles manually uploaded." + message = language_from_alpha3(language) + (" forced" if forced else "") + " Subtitles manually uploaded." if media_type == 'series': reversed_path = path_replace_reverse(path) @@ -583,7 +583,7 @@ def series_download_subtitles(no): if providers_list: for language in ast.literal_eval(episode.missing_subtitles): if language is not None: - notifications.write(msg='Searching for series subtitles...', queue='get_subtitle', item=i, + notifications.write(msg='Searching for Series Subtitles...', queue='get_subtitle', item=i, length=count_episodes_details) result = download_subtitle(path_replace(episode.path), str(alpha3_from_alpha2(language.split(':'))), @@ -611,7 +611,7 @@ def series_download_subtitles(no): list_missing_subtitles(no) if count_episodes_details: - notifications.write(msg='Searching completed. Please reload the page.', type='success', duration='permanent', + notifications.write(msg='Search Complete. Please Reload The Page.', type='success', duration='permanent', button='refresh', queue='get_subtitle') @@ -647,7 +647,7 @@ def episode_download_subtitles(no): for language in ast.literal_eval(episode.missing_subtitles): if language is not None: notifications.write(msg='Searching for ' + str( - language_from_alpha2(language)) + ' subtitles for this episode: ' + path_replace(episode.path), + language_from_alpha2(language)) + ' Subtitles for this episode: ' + path_replace(episode.path), queue='get_subtitle') result = download_subtitle(path_replace(episode.path), str(alpha3_from_alpha2(language.split(':')[0])), @@ -696,7 +696,7 @@ def movies_download_subtitles(no): for i, language in enumerate(ast.literal_eval(movie.missing_subtitles), 1): if providers_list: if language is not None: - notifications.write(msg='Searching for movies subtitles', queue='get_subtitle', item=i, + notifications.write(msg='Searching for Movie Subtitles', queue='get_subtitle', item=i, length=count_movie) result = download_subtitle(path_replace_movie(movie.path), str(alpha3_from_alpha2(language.split(':')[0])), @@ -724,7 +724,7 @@ def movies_download_subtitles(no): list_missing_subtitles_movies(no) if count_movie: - notifications.write(msg='Searching completed. Please reload the page.', type='success', duration='permanent', + notifications.write(msg='Search Complete. Please Reload The Page.', type='success', duration='permanent', button='refresh', queue='get_subtitle') @@ -774,7 +774,7 @@ def wanted_download_subtitles(path, l, count_episodes): for i in range(len(attempt)): if attempt[i][0] == language: if search_active(attempt[i][1]): - notifications.write(msg='Searching for series subtitles...', queue='get_subtitle', item=l, + notifications.write(msg='Searching for Series Subtitles...', queue='get_subtitle', item=l, length=count_episodes) result = download_subtitle(path_replace(episode.path), str(alpha3_from_alpha2(language.split(':')[0])), @@ -843,7 +843,7 @@ def wanted_download_subtitles_movie(path, l, count_movies): for i in range(len(attempt)): if attempt[i][0] == language: if search_active(attempt[i][1]) is True: - notifications.write(msg='Searching for movies subtitles...', queue='get_subtitle', item=l, + notifications.write(msg='Searching for Movie Subtitles...', queue='get_subtitle', item=l, length=count_movies) result = download_subtitle(path_replace_movie(movie.path), str(alpha3_from_alpha2(language.split(':')[0])), @@ -867,7 +867,7 @@ def wanted_download_subtitles_movie(path, l, count_movies): send_notifications_movie(movie.radarr_id, message) else: logging.info( - 'BAZARR Search is not active for movie ' + movie.path + ' Language: ' + attempt[i][0]) + 'BAZARR Search is not active for this Movie ' + movie.path + ' Language: ' + attempt[i][0]) def wanted_search_missing_subtitles(): @@ -920,7 +920,7 @@ def wanted_search_missing_subtitles(): 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 History for more information.') notifications.write(msg='Searching completed. Please reload the page.', type='success', duration='permanent', button='refresh', queue='get_subtitle') @@ -1187,7 +1187,7 @@ def upgrade_subtitles(): forced_languages = desired_languages if episode['language'] in forced_languages: - notifications.write(msg='Upgrading series subtitles...', + notifications.write(msg='Upgrading Series Subtitles...', queue='upgrade_subtitle', item=i, length=count_episode_to_upgrade) if episode['language'].endswith('forced'): @@ -1236,7 +1236,7 @@ def upgrade_subtitles(): forced_languages = desired_languages if movie['language'] in forced_languages: - notifications.write(msg='Upgrading movie subtitles...', + notifications.write(msg='Upgrading Movie Subtitles...', queue='upgrade_subtitle', item=i, length=count_movie_to_upgrade) if movie['language'].endswith('forced'): diff --git a/bazarr/scheduler.py b/bazarr/scheduler.py index dee28bfbb..727a68d86 100644 --- a/bazarr/scheduler.py +++ b/bazarr/scheduler.py @@ -28,16 +28,16 @@ def sonarr_full_update(): if full_update == "Daily": scheduler.add_job(update_all_episodes, CronTrigger(hour=settings.sonarr.full_update_hour), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', - name='Update all episodes subtitles from disk', replace_existing=True) + name='Update all Episode Subtitles from disk', replace_existing=True) elif full_update == "Weekly": scheduler.add_job(update_all_episodes, CronTrigger(day_of_week=settings.sonarr.full_update_day, hour=settings.sonarr.full_update_hour), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', - name='Update all episodes subtitles from disk', replace_existing=True) + name='Update all Episode Subtitles from disk', replace_existing=True) elif full_update == "Manually": scheduler.add_job(update_all_episodes, CronTrigger(year='2100'), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', - name='Update all episodes subtitles from disk', replace_existing=True) + name='Update all Episode Subtitles from disk', replace_existing=True) def radarr_full_update(): @@ -46,17 +46,17 @@ def radarr_full_update(): if full_update == "Daily": scheduler.add_job(update_all_movies, CronTrigger(hour=settings.radarr.full_update_hour), max_instances=1, coalesce=True, misfire_grace_time=15, - id='update_all_movies', name='Update all movies subtitles from disk', + id='update_all_movies', name='Update all Movie Subtitles from disk', replace_existing=True) elif full_update == "Weekly": scheduler.add_job(update_all_movies, CronTrigger(day_of_week=settings.radarr.full_update_day, hour=settings.radarr.full_update_hour), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_movies', - name='Update all movies subtitles from disk', + name='Update all Movie Subtitles from disk', replace_existing=True) elif full_update == "Manually": scheduler.add_job(update_all_movies, CronTrigger(year='2100'), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_movies', - name='Update all movies subtitles from disk', + name='Update all Movie Subtitles from disk', replace_existing=True) @@ -88,38 +88,38 @@ def schedule_update_job(): if settings.general.getboolean('auto_update'): scheduler.add_job(check_and_apply_update, IntervalTrigger(hours=6), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_bazarr', - name='Update bazarr from source on Github' if not args.release_update else 'Update bazarr from release on Github', + name='Update Bazarr from source on Github' if not args.release_update else 'Update Bazarr from release on Github', replace_existing=True) else: scheduler.add_job(check_and_apply_update, CronTrigger(year='2100'), hour=4, id='update_bazarr', - name='Update bazarr from source on Github' if not args.release_update else 'Update bazarr from release on Github', + name='Update Bazarr from source on Github' if not args.release_update else 'Update Bazarr from release on Github', replace_existing=True) scheduler.add_job(check_releases, IntervalTrigger(hours=6), max_instances=1, coalesce=True, - misfire_grace_time=15, id='update_release', name='Update release info', + misfire_grace_time=15, id='update_release', name='Update Release Info', replace_existing=True) else: scheduler.add_job(check_releases, IntervalTrigger(hours=6), max_instances=1, coalesce=True, misfire_grace_time=15, - id='update_release', name='Update release info', replace_existing=True) + id='update_release', name='Update Release Info', replace_existing=True) if settings.general.getboolean('use_sonarr'): scheduler.add_job(update_series, IntervalTrigger(minutes=1), max_instances=1, coalesce=True, misfire_grace_time=15, - id='update_series', name='Update series list from Sonarr') + id='update_series', name='Update Series list from Sonarr') scheduler.add_job(sync_episodes, IntervalTrigger(minutes=5), max_instances=1, coalesce=True, misfire_grace_time=15, id='sync_episodes', name='Sync episodes with Sonarr') if settings.general.getboolean('use_radarr'): scheduler.add_job(update_movies, IntervalTrigger(minutes=5), max_instances=1, coalesce=True, misfire_grace_time=15, - id='update_movies', name='Update movies list from Radarr') + id='update_movies', name='Update Movie list from Radarr') def schedule_wanted_search(): if settings.general.getboolean('use_sonarr') or settings.general.getboolean('use_radarr'): scheduler.add_job(wanted_search_missing_subtitles, IntervalTrigger(hours=int(settings.general.wanted_search_frequency)), max_instances=1, coalesce=True, misfire_grace_time=15, id='wanted_search_missing_subtitles', - name='Search for wanted subtitles', replace_existing=True) + name='Search for wanted Subtitles', replace_existing=True) def schedule_upgrade_subs(): @@ -127,7 +127,7 @@ def schedule_upgrade_subs(): settings.general.getboolean('use_radarr')): scheduler.add_job(upgrade_subtitles, IntervalTrigger(hours=int(settings.general.upgrade_frequency)), max_instances=1, coalesce=True, misfire_grace_time=15, id='upgrade_subtitles', - name='Upgrade previously downloaded subtitles', replace_existing=True) + name='Upgrade previously downloaded Subtitles', replace_existing=True) scheduler.add_job(cache_maintenance, IntervalTrigger(hours=24), max_instances=1, coalesce=True, misfire_grace_time=15, id='cache_cleanup', name='Cache maintenance') diff --git a/libs/subliminal_patch/providers/subdivx.py b/libs/subliminal_patch/providers/subdivx.py index a9174ff15..9493777aa 100644 --- a/libs/subliminal_patch/providers/subdivx.py +++ b/libs/subliminal_patch/providers/subdivx.py @@ -24,16 +24,15 @@ class SubdivxSubtitle(Subtitle): provider_name = 'subdivx' hash_verifiable = False - def __init__(self, language, page_link, download_link, description, title): + def __init__(self, language, page_link, description, title): super(SubdivxSubtitle, self).__init__(language, hearing_impaired=False, page_link=page_link) - self.download_link = download_link self.description = description.lower() self.title = title @property def id(self): - return self.download_link + return self.page_link def get_matches(self, video): matches = set() @@ -144,10 +143,8 @@ class SubdivxSubtitlesProvider(Provider): # body description = body_soup.find("div", {'id': 'buscador_detalle_sub'}).text - download_link = body_soup.find("div", {'id': 'buscador_detalle_sub_datos'} - ).find("a", {'target': 'new'})["href"].replace('http://', 'https://') - subtitle = self.subtitle_class(language, page_link, download_link, description, title) + subtitle = self.subtitle_class(language, page_link, description, title) logger.debug('Found subtitle %r', subtitle) subtitles.append(subtitle) @@ -180,12 +177,28 @@ class SubdivxSubtitlesProvider(Provider): return subtitles + def get_download_link(self, subtitle): + r = self.session.get(subtitle.page_link, timeout=10) + r.raise_for_status() + + if r.content: + page_soup = ParserBeautifulSoup(r.content.decode('iso-8859-1', 'ignore'), ['lxml', 'html.parser']) + links_soup = page_soup.find_all("a", {'class': 'detalle_link'}) + for link_soup in links_soup: + if link_soup['href'].startswith('bajar'): + return self.server_url + link_soup['href'] + + logger.debug('No data returned from provider') + return None + def download_subtitle(self, subtitle): if isinstance(subtitle, SubdivxSubtitle): # download the subtitle logger.info('Downloading subtitle %r', subtitle) - r = self.session.get(subtitle.download_link, headers={'Referer': subtitle.page_link}, - timeout=30) + + # get download link + download_link = self.get_download_link(subtitle) + r = self.session.get(download_link, headers={'Referer': subtitle.page_link}, timeout=30) r.raise_for_status() if not r.content: diff --git a/views/episodes.tpl b/views/episodes.tpl index 7c2cb4260..5b07673de 100644 --- a/views/episodes.tpl +++ b/views/episodes.tpl @@ -114,8 +114,8 @@
- - + + <% subs_languages = ast.literal_eval(str(details.languages)) subs_languages_list = [] @@ -157,7 +157,7 @@ %if len(seasons) == 0:
-

No episode files available for this series or Bazarr is still synchronizing with Sonarr. Please come back later.

+

No episode files available for this Series or Bazarr is still synchronizing with Sonarr. Please come back later.

%else: %for season in seasons: @@ -196,10 +196,10 @@ Episode Title - Existing
subtitles - Missing
subtitles - Manual
search - Manual
upload + Existing
Subtitles + Missing
Subtitles + Manual
Search + Manual
Upload @@ -323,7 +323,7 @@
- +
@@ -331,7 +331,7 @@
- +
@@ -299,7 +299,7 @@
- +
@@ -342,9 +342,9 @@ Score: Language: - Hearing-impaired: + Hearing-Impaired: Provider: - Based on: + Based On: @@ -413,7 +413,7 @@ \ No newline at end of file + diff --git a/views/movies.tpl b/views/movies.tpl index 96f3b2ca5..ccd8f057a 100644 --- a/views/movies.tpl +++ b/views/movies.tpl @@ -58,9 +58,9 @@ Name Path - Audio
language - Subtitles
languages - Hearing-
impaired + Audio
Language + Subtitles
Languages + Hearing-
Impaired Forced @@ -87,7 +87,7 @@ %if os.path.isfile(row.path): %else: - + %end {{row.path}} @@ -111,7 +111,7 @@ end end %> -
+
@@ -149,7 +149,7 @@ %end fast forward icon">
-
Total records: {{missing_count}}
+
Total Records: {{missing_count}}
%end @@ -170,7 +170,7 @@
- +
@@ -178,7 +178,7 @@
- +
- +
- +
- +
@@ -186,4 +186,4 @@ }); $('.select').dropdown(); - \ No newline at end of file + diff --git a/views/providers.tpl b/views/providers.tpl index 90b7b2370..bea3abec8 100644 --- a/views/providers.tpl +++ b/views/providers.tpl @@ -3,7 +3,7 @@
- +
@@ -35,7 +35,7 @@
- +
@@ -45,7 +45,7 @@