Skip to content

Commit

Permalink
Merge development into master
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] authored Dec 24, 2024
2 parents d6b74c9 + 2247c55 commit 6ec304d
Show file tree
Hide file tree
Showing 90 changed files with 2,067 additions and 910 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/schedule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Execute
uses: benc-uk/workflow-dispatch@v1.2.3
uses: benc-uk/workflow-dispatch@v1.2.4
with:
workflow: "release_beta_to_dev"
token: ${{ secrets.WF_GITHUB_TOKEN }}
Expand Down
4 changes: 2 additions & 2 deletions bazarr.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ def check_python_version():
print("Python " + minimum_py3_str + " or greater required. "
"Current version is " + platform.python_version() + ". Please upgrade Python.")
exit_program(EXIT_PYTHON_UPGRADE_NEEDED)
elif int(python_version[0]) == 3 and int(python_version[1]) > 11:
print("Python version greater than 3.11.x is unsupported. Current version is " + platform.python_version() +
elif int(python_version[0]) == 3 and int(python_version[1]) > 12:
print("Python version greater than 3.12.x is unsupported. Current version is " + platform.python_version() +
". Keep in mind that even if it works, you're on your own.")
elif (int(python_version[0]) == minimum_py3_tuple[0] and int(python_version[1]) < minimum_py3_tuple[1]) or \
(int(python_version[0]) != minimum_py3_tuple[0]):
Expand Down
21 changes: 12 additions & 9 deletions bazarr/api/episodes/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,10 @@ def get(self):
TableHistory.matched,
TableHistory.not_matched,
TableEpisodes.subtitles.label('external_subtitles'),
upgradable_episodes_not_perfect.c.id.label('upgradable'),
blacklisted_subtitles.c.subs_id.label('blacklisted')) \
.select_from(TableHistory) \
.join(TableShows, onclause=TableHistory.sonarrSeriesId == TableShows.sonarrSeriesId) \
.join(TableEpisodes, onclause=TableHistory.sonarrEpisodeId == TableEpisodes.sonarrEpisodeId) \
.join(upgradable_episodes_not_perfect, onclause=TableHistory.id == upgradable_episodes_not_perfect.c.id,
isouter=True) \
.join(blacklisted_subtitles, onclause=TableHistory.subs_id == blacklisted_subtitles.c.subs_id,
isouter=True) \
.where(reduce(operator.and_, query_conditions)) \
Expand All @@ -120,6 +117,7 @@ def get(self):
'sonarrSeriesId': x.sonarrSeriesId,
'path': x.path,
'language': x.language,
'profileId': x.profileId,
'score': x.score,
'tags': x.tags,
'action': x.action,
Expand All @@ -130,24 +128,29 @@ def get(self):
'matches': x.matched,
'dont_matches': x.not_matched,
'external_subtitles': [y[1] for y in ast.literal_eval(x.external_subtitles) if y[1]],
'upgradable': bool(x.upgradable) if _language_still_desired(x.language, x.profileId) else False,
'blacklisted': bool(x.blacklisted),
} for x in database.execute(stmt).all()]

for item in episode_history:
original_video_path = item['path']
original_subtitle_path = item['subtitles_path']
# is this language still desired or should we simply skip this subtitles from upgrade logic?
still_desired = _language_still_desired(item['language'], item['profileId'])

item.update(postprocess(item))

# Mark not upgradable if score is perfect or if video/subtitles file doesn't exist anymore
# Mark upgradable and get original_id
item.update({'original_id': upgradable_episodes_not_perfect.get(item['id'])})
item.update({'upgradable': bool(item['original_id'])})

# Mark not upgradable if video/subtitles file doesn't exist anymore or if language isn't desired anymore
if item['upgradable']:
if original_subtitle_path not in item['external_subtitles'] or \
not item['video_path'] == original_video_path:
if (item['subtitles_path'] not in item['external_subtitles'] or item['video_path'] != item['path'] or
not still_desired):
item.update({"upgradable": False})

del item['path']
del item['video_path']
del item['external_subtitles']
del item['profileId']

if item['score']:
item['score'] = f"{round((int(item['score']) * 100 / 360), 2)}%"
Expand Down
3 changes: 2 additions & 1 deletion bazarr/api/episodes/wanted.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def get(self):
args = self.get_request_parser.parse_args()
episodeid = args.get('episodeid[]')

wanted_conditions = [(TableEpisodes.missing_subtitles != '[]')]
wanted_conditions = [(TableEpisodes.missing_subtitles.is_not(None)),
(TableEpisodes.missing_subtitles != '[]')]
if len(episodeid) > 0:
wanted_conditions.append((TableEpisodes.sonarrEpisodeId in episodeid))
start = 0
Expand Down
21 changes: 12 additions & 9 deletions bazarr/api/movies/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,9 @@ def get(self):
TableHistoryMovie.not_matched,
TableMovies.profileId,
TableMovies.subtitles.label('external_subtitles'),
upgradable_movies_not_perfect.c.id.label('upgradable'),
blacklisted_subtitles.c.subs_id.label('blacklisted')) \
.select_from(TableHistoryMovie) \
.join(TableMovies) \
.join(upgradable_movies_not_perfect, onclause=TableHistoryMovie.id == upgradable_movies_not_perfect.c.id,
isouter=True) \
.join(blacklisted_subtitles, onclause=TableHistoryMovie.subs_id == blacklisted_subtitles.c.subs_id,
isouter=True) \
.where(reduce(operator.and_, query_conditions)) \
Expand All @@ -112,6 +109,7 @@ def get(self):
'monitored': x.monitored,
'path': x.path,
'language': x.language,
'profileId': x.profileId,
'tags': x.tags,
'score': x.score,
'subs_id': x.subs_id,
Expand All @@ -121,24 +119,29 @@ def get(self):
'matches': x.matched,
'dont_matches': x.not_matched,
'external_subtitles': [y[1] for y in ast.literal_eval(x.external_subtitles) if y[1]],
'upgradable': bool(x.upgradable) if _language_still_desired(x.language, x.profileId) else False,
'blacklisted': bool(x.blacklisted),
} for x in database.execute(stmt).all()]

for item in movie_history:
original_video_path = item['path']
original_subtitle_path = item['subtitles_path']
# is this language still desired or should we simply skip this subtitles from upgrade logic?
still_desired = _language_still_desired(item['language'], item['profileId'])

item.update(postprocess(item))

# Mark not upgradable if score or if video/subtitles file doesn't exist anymore
# Mark upgradable and get original_id
item.update({'original_id': upgradable_movies_not_perfect.get(item['id'])})
item.update({'upgradable': bool(item['original_id'])})

# Mark not upgradable if video/subtitles file doesn't exist anymore or if language isn't desired anymore
if item['upgradable']:
if original_subtitle_path not in item['external_subtitles'] or \
not item['video_path'] == original_video_path:
if (item['subtitles_path'] not in item['external_subtitles'] or item['video_path'] != item['path'] or
not still_desired):
item.update({"upgradable": False})

del item['path']
del item['video_path']
del item['external_subtitles']
del item['profileId']

if item['score']:
item['score'] = f"{round((int(item['score']) * 100 / 120), 2)}%"
Expand Down
3 changes: 2 additions & 1 deletion bazarr/api/movies/wanted.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def get(self):
args = self.get_request_parser.parse_args()
radarrid = args.get("radarrid[]")

wanted_conditions = [(TableMovies.missing_subtitles != '[]')]
wanted_conditions = [(TableMovies.missing_subtitles.is_not(None)),
(TableMovies.missing_subtitles != '[]')]
if len(radarrid) > 0:
wanted_conditions.append((TableMovies.radarrId.in_(radarrid)))
start = 0
Expand Down
29 changes: 19 additions & 10 deletions bazarr/api/providers/providers_episodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from sonarr.history import history_log
from app.config import settings
from app.notifier import send_notifications
from subtitles.indexer.series import store_subtitles
from subtitles.indexer.series import store_subtitles, list_missing_subtitles
from subtitles.processing import ProcessSubtitlesResult

from ..utils import authenticate
Expand Down Expand Up @@ -50,18 +50,27 @@ def get(self):
"""Search manually for an episode subtitles"""
args = self.get_request_parser.parse_args()
sonarrEpisodeId = args.get('episodeid')
episodeInfo = database.execute(
select(TableEpisodes.path,
TableEpisodes.sceneName,
TableShows.title,
TableShows.profileId)
.select_from(TableEpisodes)
.join(TableShows)
.where(TableEpisodes.sonarrEpisodeId == sonarrEpisodeId)) \
.first()
stmt = select(TableEpisodes.path,
TableEpisodes.sceneName,
TableShows.title,
TableShows.profileId,
TableEpisodes.subtitles,
TableEpisodes.missing_subtitles) \
.select_from(TableEpisodes) \
.join(TableShows) \
.where(TableEpisodes.sonarrEpisodeId == sonarrEpisodeId)
episodeInfo = database.execute(stmt).first()

if not episodeInfo:
return 'Episode not found', 404
elif episodeInfo.subtitles is None:
# subtitles indexing for this episode is incomplete, we'll do it again
store_subtitles(episodeInfo.path, path_mappings.path_replace(episodeInfo.path))
episodeInfo = database.execute(stmt).first()
elif episodeInfo.missing_subtitles is None:
# missing subtitles calculation for this episode is incomplete, we'll do it again
list_missing_subtitles(epno=sonarrEpisodeId)
episodeInfo = database.execute(stmt).first()

title = episodeInfo.title
episodePath = path_mappings.path_replace(episodeInfo.path)
Expand Down
25 changes: 17 additions & 8 deletions bazarr/api/providers/providers_movies.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from radarr.history import history_log_movie
from app.config import settings
from app.notifier import send_notifications_movie
from subtitles.indexer.movies import store_subtitles_movie
from subtitles.indexer.movies import store_subtitles_movie, list_missing_subtitles_movies
from subtitles.processing import ProcessSubtitlesResult

from ..utils import authenticate
Expand Down Expand Up @@ -51,16 +51,25 @@ def get(self):
"""Search manually for a movie subtitles"""
args = self.get_request_parser.parse_args()
radarrId = args.get('radarrid')
movieInfo = database.execute(
select(TableMovies.title,
TableMovies.path,
TableMovies.sceneName,
TableMovies.profileId)
.where(TableMovies.radarrId == radarrId)) \
.first()
stmt = select(TableMovies.title,
TableMovies.path,
TableMovies.sceneName,
TableMovies.profileId,
TableMovies.subtitles,
TableMovies.missing_subtitles) \
.where(TableMovies.radarrId == radarrId)
movieInfo = database.execute(stmt).first()

if not movieInfo:
return 'Movie not found', 404
elif movieInfo.subtitles is None:
# subtitles indexing for this movie is incomplete, we'll do it again
store_subtitles_movie(movieInfo.path, path_mappings.path_replace_movie(movieInfo.path))
movieInfo = database.execute(stmt).first()
elif movieInfo.missing_subtitles is None:
# missing subtitles calculation for this movie is incomplete, we'll do it again
list_missing_subtitles_movies(no=radarrId)
movieInfo = database.execute(stmt).first()

title = movieInfo.title
moviePath = path_mappings.path_replace_movie(movieInfo.path)
Expand Down
9 changes: 8 additions & 1 deletion bazarr/api/series/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ class Series(Resource):
'alternativeTitles': fields.List(fields.String),
'audio_language': fields.Nested(get_audio_language_model),
'episodeFileCount': fields.Integer(default=0),
'ended': fields.Boolean(),
'episodeMissingCount': fields.Integer(default=0),
'fanart': fields.String(),
'imdbId': fields.String(),
'lastAired': fields.String(),
'monitored': fields.Boolean(),
'overview': fields.String(),
'path': fields.String(),
Expand Down Expand Up @@ -73,7 +75,8 @@ def get(self):
.group_by(TableShows.sonarrSeriesId)\
.subquery()

episodes_missing_conditions = [(TableEpisodes.missing_subtitles != '[]')]
episodes_missing_conditions = [(TableEpisodes.missing_subtitles.is_not(None)),
(TableEpisodes.missing_subtitles != '[]')]
episodes_missing_conditions += get_exclusion_clause('series')

episodeMissingCount = select(TableShows.sonarrSeriesId,
Expand All @@ -99,6 +102,8 @@ def get(self):
TableShows.tags,
TableShows.title,
TableShows.year,
TableShows.ended,
TableShows.lastAired,
episodeFileCount.c.episodeFileCount,
episodeMissingCount.c.episodeMissingCount) \
.select_from(TableShows) \
Expand Down Expand Up @@ -127,6 +132,8 @@ def get(self):
'tags': x.tags,
'title': x.title,
'year': x.year,
'ended': x.ended,
'lastAired': x.lastAired,
'episodeFileCount': x.episodeFileCount,
'episodeMissingCount': x.episodeMissingCount,
}) for x in database.execute(stmt).all()]
Expand Down
7 changes: 6 additions & 1 deletion bazarr/api/system/searches.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from flask_restx import Resource, Namespace, reqparse
from unidecode import unidecode

from app.config import settings
from app.config import base_url, settings
from app.database import TableShows, TableMovies, database, select

from ..utils import authenticate
Expand Down Expand Up @@ -34,6 +34,7 @@ def get(self):
search_list += database.execute(
select(TableShows.title,
TableShows.sonarrSeriesId,
TableShows.poster,
TableShows.year)
.order_by(TableShows.title)) \
.all()
Expand All @@ -43,6 +44,7 @@ def get(self):
search_list += database.execute(
select(TableMovies.title,
TableMovies.radarrId,
TableMovies.poster,
TableMovies.year)
.order_by(TableMovies.title)) \
.all()
Expand All @@ -58,8 +60,11 @@ def get(self):

if hasattr(x, 'sonarrSeriesId'):
result['sonarrSeriesId'] = x.sonarrSeriesId
result['poster'] = f"{base_url}/images/series{x.poster}" if x.poster else None

else:
result['radarrId'] = x.radarrId
result['poster'] = f"{base_url}/images/movies{x.poster}" if x.poster else None

results.append(result)

Expand Down
11 changes: 11 additions & 0 deletions bazarr/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,21 @@ def postprocess(item):
if item.get('path'):
item['path'] = path_replace(item['path'])

if item.get('video_path'):
# Provide mapped video path for history
item['video_path'] = path_replace(item['video_path'])

if item.get('subtitles_path'):
# Provide mapped subtitles path
item['subtitles_path'] = path_replace(item['subtitles_path'])

if item.get('external_subtitles'):
# Provide mapped external subtitles paths for history
if isinstance(item['external_subtitles'], str):
item['external_subtitles'] = ast.literal_eval(item['external_subtitles'])
for i, subs in enumerate(item['external_subtitles']):
item['external_subtitles'][i] = path_replace(subs)

# map poster and fanart to server proxy
if item.get('poster') is not None:
poster = item['poster']
Expand Down
6 changes: 6 additions & 0 deletions bazarr/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ def check_parser_binary(value):
Validator('opensubtitlescom.use_hash', must_exist=True, default=True, is_type_of=bool),
Validator('opensubtitlescom.include_ai_translated', must_exist=True, default=False, is_type_of=bool),

# napiprojekt section
Validator('napiprojekt.only_authors', must_exist=True, default=False, is_type_of=bool),
Validator('napiprojekt.only_real_names', must_exist=True, default=False, is_type_of=bool),

# addic7ed section
Validator('addic7ed.username', must_exist=True, default='', is_type_of=str, cast=str),
Validator('addic7ed.password', must_exist=True, default='', is_type_of=str, cast=str),
Expand Down Expand Up @@ -274,6 +278,7 @@ def check_parser_binary(value):
Validator('whisperai.endpoint', must_exist=True, default='http://127.0.0.1:9000', is_type_of=str),
Validator('whisperai.response', must_exist=True, default=5, is_type_of=int, gte=1),
Validator('whisperai.timeout', must_exist=True, default=3600, is_type_of=int, gte=1),
Validator('whisperai.pass_video_name', must_exist=True, default=False, is_type_of=bool),
Validator('whisperai.loglevel', must_exist=True, default='INFO', is_type_of=str,
is_in=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']),

Expand Down Expand Up @@ -328,6 +333,7 @@ def check_parser_binary(value):
Validator('titulky.username', must_exist=True, default='', is_type_of=str, cast=str),
Validator('titulky.password', must_exist=True, default='', is_type_of=str, cast=str),
Validator('titulky.approved_only', must_exist=True, default=False, is_type_of=bool),
Validator('titulky.skip_wrong_fps', must_exist=True, default=False, is_type_of=bool),

# embeddedsubtitles section
Validator('embeddedsubtitles.included_codecs', must_exist=True, default=[], is_type_of=list),
Expand Down
Loading

0 comments on commit 6ec304d

Please sign in to comment.