Commit bdf74b0e authored by echel0n's avatar echel0n

Added code to check_requirements core function to compare install requirement...

Added code to check_requirements core function to compare install requirement versions to requirements.txt, if installed version older then update or if not installed then install
Added code to cleanup dupe scene season/episode/absolute numbering from main database
Added code to prevent dupe scene numbering being set on episodes
Fixed #SICKRAGE-APP-5HH - KeyError in sickrage.providers.torrent.torrentz in search method
Fixed #SICKRAGE-APP-5JC - IndexError in sickrage.providers.torrent.hdspace in parse method
Fixed #SICKRAGE-APP-5HW - AttributeError in sickrage.core.tv.show in want_episode method
Fixed MultipleResultsFound when using scene_numbering get_indexer_numbering method to map scene season/episode to indexer season/episode numbering
Fixed #SICKRAGE-APP-5K7 - RuntimeError in sickrage.core.websocket in push method
Fixed #SICKRAGE-APP-5MH - AttributeError in sickrage.providers in <listcomp>
Fixed #SICKRAGE-APP-5J2 - AttributeError in sickrage.clients.torrent.transmission in _get_auth method
Removed unrequired scene_numbering table from main database
Fixed issue with nulled booleans being stored in main database TV shows table
Fixed issue with add existing shows and show object not being populated into core show cache
parent 3d285692
APScheduler == 3.6.3
babelfish == 0.5.5
bencode3 == 0.1.0
CacheControl == 0.12.6
cloudscraper == 1.2.42
configobj == 5.0.6
feedparser == 6.0.0b3
guessit == 3.1.1
hachoir == 3.1.1
Mako == 1.1.3
markdown2 == 2.3.9
oauth2 == 1.9.0.post1
profilehooks == 1.11.2
Send2Trash == 1.6.0b1
six == 1.15.0
subliminal == 2.1.0
tornado == 6.0.4
xmltodict == 0.12.0
MultipartPostHandler == 0.1.0
beautifulsoup4 == 4.9.1
python_dateutil == 2.7.5
pynzb == 0.1.0
future == 0.18.2
gntp == 1.0.3
python_twitter == 3.5
pyxdg == 0.26
urllib3 == 1.25.9
rarfile == 3.1
lockfile == 0.12.2
requests == 2.24.0
fake-useragent == 0.1.11
html5lib == 1.1
arrow == 0.15.7
unidecode == 1.1.1
twilio == 6.43.0
chardet == 3.0.4
pytz == 2020.1
tzlocal == 2.1
raven == 6.10.0
python-keycloak-client == 0.2.3
simplejson == 3.17.0
service_identity == 18.1.0
knowit == 0.2.4
sqlalchemy == 1.3.18
sqlalchemy-migrate == 0.13.0
mutagen == 1.44.0
deluge-client == 1.9.0
APScheduler==3.6.3
babelfish==0.5.5
bencode3==0.1.0
CacheControl==0.12.6
cloudscraper==1.2.42
configobj==5.0.6
feedparser==6.0.0b3
guessit==3.1.1
hachoir==3.1.1
Mako==1.1.3
markdown2==2.3.9
oauth2==1.9.0.post1
profilehooks==1.11.2
Send2Trash==1.6.0b1
six==1.15.0
subliminal==2.1.0
tornado==6.0.4
xmltodict==0.12.0
MultipartPostHandler==0.1.0
beautifulsoup4==4.9.1
python_dateutil==2.7.5
pynzb==0.1.0
future==0.18.2
gntp==1.0.3
python_twitter==3.5
pyxdg==0.26
urllib3==1.25.9
rarfile==3.1
lockfile==0.12.2
requests==2.24.0
fake-useragent==0.1.11
html5lib==1.1
arrow==0.15.7
unidecode==1.1.1
twilio==6.43.0
chardet==3.0.4
pytz==2020.1
tzlocal==2.1
raven==6.10.0
python-keycloak-client==0.2.3
simplejson==3.17.0
service_identity==18.1.0
knowit==0.2.4
sqlalchemy==1.3.18
sqlalchemy-migrate==0.13.0
mutagen==1.44.0
deluge-client==1.9.0
PyMySQL
certifi
pyasn1
......
......@@ -32,6 +32,8 @@ import time
import traceback
from signal import SIGTERM
import pkg_resources
app = None
MAIN_DIR = os.path.abspath(os.path.realpath(os.path.expanduser(os.path.dirname(os.path.dirname(__file__)))))
......@@ -174,6 +176,20 @@ def check_requirements():
if sys.version_info < (3, 5, 0):
sys.exit("Sorry, SiCKRAGE requires Python 3.5+")
# install/update requirements
with open(REQS_FILE) as f:
for line in f.readlines():
try:
req_name, req_version = line.strip().split('==')
if not pkg_resources.get_distribution(req_name).version == req_version:
print('Updating requirement {} to {}'.format(req_name, req_version))
subprocess.check_call([sys.executable, "-m", "pip", "install", "--no-cache-dir", line.strip()])
except pkg_resources.DistributionNotFound:
print('Installing requirement {}'.format(line.strip()))
subprocess.check_call([sys.executable, "-m", "pip", "install", "--no-cache-dir", line.strip()])
except ValueError:
continue
try:
import OpenSSL
......@@ -181,11 +197,9 @@ def check_requirements():
v_needed = '0.15'
if not v >= v_needed:
print('OpenSSL installed but {} is needed while {} is installed. '
'Run `pip install -U pyopenssl`'.format(v_needed, v))
print('OpenSSL installed but {} is needed while {} is installed. Run `pip3 install -U pyopenssl`'.format(v_needed, v))
except ImportError:
print('OpenSSL not available, please install for better requests validation: '
'`https://pyopenssl.readthedocs.org/en/latest/install.html`')
print('OpenSSL not available, please install for better requests validation: `https://pyopenssl.readthedocs.org/en/latest/install.html`')
def version():
......@@ -218,6 +232,9 @@ def main():
# set system default language
gettext.install('messages', LOCALE_DIR, codeset='UTF-8', names=["ngettext"])
# check lib requirements
check_requirements()
try:
try:
from sickrage.core import Core
......@@ -320,9 +337,6 @@ def main():
if not os.path.isabs(pid_file):
pid_file = os.path.join(app.data_dir, pid_file)
# check lib requirements
check_requirements()
# add sickrage module to python system path
if not (PROG_DIR in sys.path):
sys.path, remainder = sys.path[:1], sys.path[1:]
......
......@@ -53,15 +53,19 @@ class TransmissionAPI(TorrentClient):
verify=bool(sickrage.app.config.torrent_verify_cert))
if self.response is not None and self.response.text:
self.auth = re.search(r'X-Transmission-Session-Id:\s*(\w+)', self.response.text).group(1)
self.session.headers.update({'x-transmission-session-id': self.auth})
# Validating Transmission authorization
success = self._request(method='post',
json={'arguments': {}, 'method': 'session-get'},
headers={'x-transmission-session-id': self.auth})
if not success:
auth_match = re.search(r'X-Transmission-Session-Id:\s*(\w+)', self.response.text)
if auth_match:
self.auth = auth_match.group(1)
self.session.headers.update({'x-transmission-session-id': self.auth})
# Validating Transmission authorization
success = self._request(method='post',
json={'arguments': {}, 'method': 'session-get'},
headers={'x-transmission-session-id': self.auth})
if not success:
self.auth = None
else:
self.auth = None
return self.auth
......
......@@ -1215,8 +1215,8 @@ class Config(object):
sickrage.app.scheduler.reschedule_job(sickrage.app.version_updater.name, trigger='interval', hours=self.version_updater_freq)
def change_showupdate_hour(self, freq):
"""Change frequency of show updater thread
"""
Change frequency of show updater thread
:param freq: New frequency
"""
......@@ -1225,7 +1225,7 @@ class Config(object):
self.showupdate_hour = 0
sickrage.app.scheduler.reschedule_job(sickrage.app.show_updater.name, trigger='interval', hours=1,
start_date=datetime.datetime.now().replace(hour=self.showupdate_hour))
start_date=datetime.datetime.utcnow().replace(hour=self.showupdate_hour))
def change_subtitle_searcher_freq(self, freq):
"""
......
......@@ -21,6 +21,7 @@ from sqlalchemy import Column, Integer, Text, ForeignKeyConstraint, String, Date
from sqlalchemy.ext.declarative import as_declarative
from sqlalchemy.orm import relationship
import sickrage
from sickrage.core import common
from sickrage.core.common import SearchFormats
from sickrage.core.databases import SRDatabase, SRDatabaseBase
......@@ -52,8 +53,12 @@ class MainDB(SRDatabase):
).having(literal_column('count') > 1).all()
for cur_duplicate in duplicates:
session.query(self.TVShow).filter_by(showid=cur_duplicate['indexer_id']).limit(int(cur_duplicate['count']) - 1).delete()
session.commit()
sickrage.app.log.debug("Duplicate show detected! indexer_id: {dupe_id} count: {dupe_count}".format(dupe_id=cur_duplicate.indexer_id,
dupe_count=cur_duplicate.count))
for result in session.query(self.TVShow).filter_by(indexer_id=cur_duplicate.indexer_id).limit(cur_duplicate.count - 1):
session.query(self.TVShow).filter_by(indexer_id=result.indexer_id).delete()
session.commit()
def remove_duplicate_episodes():
session = self.session()
......@@ -83,10 +88,52 @@ class MainDB(SRDatabase):
).having(literal_column('count') > 1).all()
for cur_duplicate in duplicates:
session.query(self.TVEpisode). \
filter_by(showid=cur_duplicate['showid'], season=cur_duplicate['season'], episode=cur_duplicate['episode']). \
limit(int(cur_duplicate['count']) - 1).delete()
session.commit()
sickrage.app.log.debug("Duplicate episode detected! "
"showid: {dupe_id} "
"season: {dupe_season} "
"episode {dupe_episode} count: {dupe_count}".format(dupe_id=cur_duplicate.showid,
dupe_season=cur_duplicate.season,
dupe_episode=cur_duplicate.episode,
dupe_count=cur_duplicate.count))
for result in session.query(self.TVEpisode).filter_by(showid=cur_duplicate.showid,
season=cur_duplicate.season,
episode=cur_duplicate.episode).limit(cur_duplicate.count - 1):
session.query(self.TVEpisode).filter_by(indexer_id=result.indexer_id).delete()
session.commit()
def fix_duplicate_episode_scene_numbering():
session = self.session()
duplicates = session.query(
self.TVEpisode.showid,
self.TVEpisode.scene_season,
self.TVEpisode.scene_episode,
func.count(self.TVEpisode.showid).label('count')
).group_by(
self.TVEpisode.showid,
self.TVEpisode.scene_season,
self.TVEpisode.scene_episode
).filter(
self.TVEpisode.scene_season != -1,
self.TVEpisode.scene_episode != -1
).having(literal_column('count') > 1)
for cur_duplicate in duplicates:
sickrage.app.log.debug("Duplicate episode scene numbering detected! "
"showid: {dupe_id} "
"scene season: {dupe_scene_season} "
"scene episode {dupe_scene_episode} count: {dupe_count}".format(dupe_id=cur_duplicate.showid,
dupe_scene_season=cur_duplicate.scene_season,
dupe_scene_episode=cur_duplicate.scene_episode,
dupe_count=cur_duplicate.count))
for result in session.query(self.TVEpisode).filter_by(showid=cur_duplicate.showid,
scene_season=cur_duplicate.scene_season,
scene_episode=cur_duplicate.scene_episode).limit(cur_duplicate.count - 1):
result.scene_season = -1
result.scene_episode = -1
session.commit()
def remove_invalid_episodes():
session = self.session()
......@@ -124,10 +171,25 @@ class MainDB(SRDatabase):
session.commit()
def fix_tvshow_table_columns():
session = self.session()
session.query(self.TVShow).filter_by(sub_use_sr_metadata=None).update({'sub_use_sr_metadata': False})
session.query(self.TVShow).filter_by(skip_downloaded=None).update({'skip_downloaded': False})
session.query(self.TVShow).filter_by(dvdorder=None).update({'dvdorder': False})
session.query(self.TVShow).filter_by(subtitles=None).update({'subtitles': False})
session.query(self.TVShow).filter_by(anime=None).update({'anime': False})
session.query(self.TVShow).filter_by(flatten_folders=None).update({'flatten_folders': False})
session.query(self.TVShow).filter_by(paused=None).update({'paused': False})
session.commit()
remove_duplicate_shows()
remove_duplicate_episodes()
remove_invalid_episodes()
fix_invalid_scene_numbering()
fix_duplicate_episode_scene_numbering()
fix_tvshow_table_columns()
class TVShow(MainDBBase):
__tablename__ = 'tv_shows'
......@@ -144,21 +206,21 @@ class MainDB(SRDatabase):
quality = Column(Integer, default=-1)
airs = Column(Text, default='')
status = Column(Text, default='')
flatten_folders = Column(Boolean, default=0)
paused = Column(Boolean, default=0)
flatten_folders = Column(Boolean, nullable=False, default=0)
paused = Column(Boolean, nullable=False, default=0)
search_format = Column(Integer, default=SearchFormats.STANDARD)
scene = Column(Boolean, default=0)
anime = Column(Boolean, default=0)
subtitles = Column(Boolean, default=0)
dvdorder = Column(Boolean, default=0)
skip_downloaded = Column(Boolean, default=0)
scene = Column(Boolean, nullable=False, default=0)
anime = Column(Boolean, nullable=False, default=0)
subtitles = Column(Boolean, nullable=False, default=0)
dvdorder = Column(Boolean, nullable=False, default=0)
skip_downloaded = Column(Boolean, nullable=False, default=0)
startyear = Column(Integer, default=0)
lang = Column(Text, default='')
imdb_id = Column(Text, default='')
rls_ignore_words = Column(Text, default='')
rls_require_words = Column(Text, default='')
default_ep_status = Column(Integer, default=common.SKIPPED)
sub_use_sr_metadata = Column(Boolean, default=0)
sub_use_sr_metadata = Column(Boolean, nullable=False, default=0)
notify_list = Column(Text, default='')
search_delay = Column(Integer, default=0)
scene_exceptions = Column(Text, default='')
......@@ -201,13 +263,13 @@ class MainDB(SRDatabase):
subtitles_searchcount = Column(Integer, default=0)
subtitles_lastsearch = Column(Integer, default=0)
airdate = Column(Date, default=datetime.datetime.min)
hasnfo = Column(Boolean, default=False)
hastbn = Column(Boolean, default=False)
hasnfo = Column(Boolean, nullable=False, default=False)
hastbn = Column(Boolean, nullable=False, default=False)
status = Column(Integer, default=common.UNKNOWN)
location = Column(Text, default='')
file_size = Column(BigInteger, default=0)
release_name = Column(Text, default='')
is_proper = Column(Boolean, default=False)
is_proper = Column(Boolean, nullable=False, default=False)
version = Column(Integer, default=-1)
release_group = Column(Text, default='')
......@@ -244,18 +306,6 @@ class MainDB(SRDatabase):
plot = Column(Text)
last_update = Column(Integer, nullable=False)
class SceneNumbering(MainDBBase):
__tablename__ = 'scene_numbering'
indexer = Column(Integer, primary_key=True)
indexer_id = Column(Integer, primary_key=True)
season = Column(Integer, primary_key=True)
episode = Column(Integer, primary_key=True)
scene_season = Column(Integer, nullable=False)
scene_episode = Column(Integer, nullable=False)
absolute_number = Column(Integer, nullable=False)
scene_absolute_number = Column(Integer, nullable=False)
class IndexerMapping(MainDBBase):
__tablename__ = 'indexer_mapping'
......
......@@ -282,8 +282,11 @@ class NameParser(object):
show_obj.indexer,
season_number,
epNo)
new_episode_numbers.append(e)
new_season_numbers.append(s)
if s != -1:
new_season_numbers.append(s)
if e != -1:
new_episode_numbers.append(e)
elif show_obj.is_anime and best_result.ab_episode_numbers:
for epAbsNo in best_result.ab_episode_numbers:
......@@ -298,9 +301,11 @@ class NameParser(object):
(s, e) = show_obj.get_all_episodes_from_absolute_number([a])
new_absolute_numbers.append(a)
new_episode_numbers.extend(e)
if a != -1:
new_absolute_numbers.append(a)
new_season_numbers.append(s)
new_episode_numbers.extend(e)
elif best_result.season_number and best_result.episode_numbers:
for epNo in best_result.episode_numbers:
......@@ -314,11 +319,14 @@ class NameParser(object):
epNo)
if show_obj.is_anime:
a = get_absolute_number_from_season_and_episode(show_obj.indexer_id, s, e)
if a:
if a != -1:
new_absolute_numbers.append(a)
new_episode_numbers.append(e)
new_season_numbers.append(s)
if s != -1:
new_season_numbers.append(s)
if e != -1:
new_episode_numbers.append(e)
# need to do a quick sanity check here. It's possible that we now have episodes
# from more than one season (by tvdb numbering), and this is just too much
......
......@@ -256,8 +256,6 @@ class Queue(object):
if task_id in self.tasks:
sickrage.app.log.debug("Removing {} task {}".format(self.name, task_id))
task = self.tasks.get(task_id)
if task.status == TaskStatus.FAILED and task.error_message:
sickrage.app.log.error("{} task {} failed: {}".format(task.name, task_id, task.error_message))
if task in self.queue:
self.queue.remove(self.tasks.get(task_id))
del self.tasks[task_id]
......@@ -336,6 +334,7 @@ class Worker(object):
if self.task is not None:
self.task.status = TaskStatus.FAILED
self.task.error_message = str(e)
sickrage.app.log.error("{} task failed: {}".format(self.task.name, self.task.error_message))
else:
sickrage.app.log.debug("Worker " + str(self.id) + " without task.")
finally:
......
......@@ -306,20 +306,19 @@ class ShowTaskAdd(ShowTask):
show_obj = TVShow(self.indexer_id, self.indexer, lang=self.lang, location=self.showDir)
# set up initial values
show_obj.subtitles = self.subtitles or sickrage.app.config.subtitles_default
show_obj.sub_use_sr_metadata = self.sub_use_sr_metadata
show_obj.quality = self.quality or sickrage.app.config.quality_default
show_obj.flatten_folders = self.flatten_folders or sickrage.app.config.flatten_folders_default
show_obj.anime = self.anime or sickrage.app.config.anime_default
show_obj.dvdorder = self.dvdorder
show_obj.search_format = self.search_format or sickrage.app.config.search_format_default
show_obj.scene = self.scene or sickrage.app.config.scene_default
show_obj.skip_downloaded = self.skip_downloaded or sickrage.app.config.skip_downloaded_default
show_obj.paused = self.paused
show_obj.subtitles = self.subtitles if self.subtitles is not None else sickrage.app.config.subtitles_default
show_obj.sub_use_sr_metadata = self.sub_use_sr_metadata if self.sub_use_sr_metadata is not None else False
show_obj.quality = self.quality if self.quality is not None else sickrage.app.config.quality_default
show_obj.flatten_folders = self.flatten_folders if self.flatten_folders is not None else sickrage.app.config.flatten_folders_default
show_obj.scene = self.scene if self.scene is not None else sickrage.app.config.scene_default
show_obj.anime = self.anime if self.anime is not None else sickrage.app.config.anime_default
show_obj.dvdorder = self.dvdorder if self.dvdorder is not None else False
show_obj.search_format = self.search_format if self.search_format is not None else sickrage.app.config.search_format_default
show_obj.skip_downloaded = self.skip_downloaded if self.skip_downloaded is not None else sickrage.app.config.skip_downloaded_default
show_obj.paused = self.paused if self.paused is not None else False
# set up default new/missing episode status
sickrage.app.log.info("Setting all current episodes to the specified default status: " + str(self.default_status))
show_obj.default_ep_status = self.default_status
# save to database
......
......@@ -26,6 +26,7 @@ from sqlalchemy import orm
import sickrage
from sickrage.core.databases.main import MainDB
from sickrage.core.exceptions import EpisodeNotFoundException, MultipleEpisodesInDatabaseException
from sickrage.core.tv.show.helpers import find_show
from sickrage.core.websession import WebSession
from sickrage.indexers import IndexerApi
......@@ -45,7 +46,7 @@ def get_scene_numbering(indexer_id, indexer, season, episode, fallback_to_xem=Tr
:return: (int, int) a tuple with (season, episode)
"""
show_obj = find_show(indexer_id)
if not show_obj or show_obj and not show_obj.scene:
if not show_obj:
return -1, -1
result = find_scene_numbering(indexer_id, indexer, season, episode)
......@@ -73,7 +74,7 @@ def get_scene_absolute_numbering(indexer_id, indexer, absolute_number, fallback_
:return: int absolute number
"""
show_obj = find_show(indexer_id)
if not show_obj or show_obj and not show_obj.scene:
if not show_obj:
return -1
result = find_scene_absolute_numbering(indexer_id, indexer, absolute_number)
......@@ -132,7 +133,7 @@ def get_indexer_absolute_numbering(indexer_id, indexer, scene_absolute_number, f
scene_season=scene_season
).one()
return dbData.absolute_number
except orm.exc.NoResultFound:
except orm.exc.MultipleResultsFound:
if fallback_to_xem:
return get_indexer_absolute_numbering_from_xem_numbering(indexer_id, indexer, scene_absolute_number, scene_season)
return -1
......@@ -367,23 +368,33 @@ def find_xem_absolute_numbering(indexer_id, indexer, absolute_number):
return
def set_scene_numbering(indexer_id, indexer, season=None, episode=None, absolute_number=None, scene_season=-1, scene_episode=-1, scene_absolute=-1):
def set_scene_numbering(indexer_id, indexer, season=None, episode=None, absolute_number=None, scene_season=None, scene_episode=None, scene_absolute=None):
"""
Set scene numbering for a season/episode.
To clear the scene numbering, leave both sceneSeason and sceneEpisode as None.
Set scene numbering for a season/episode or absolute.
To clear the scene numbering, leave both scene_season and scene_episode or scene_absolute as None.
"""
session = sickrage.app.main_db.session()
if season and episode:
if scene_season is not None and scene_episode is not None:
if session.query(MainDB.TVEpisode).filter_by(showid=indexer_id, indexer=indexer, scene_season=scene_season, scene_episode=scene_episode).count():
return False
dbData = session.query(MainDB.TVEpisode).filter_by(showid=indexer_id, indexer=indexer, season=season, episode=episode).one()
dbData.scene_season = scene_season
dbData.scene_episode = scene_episode
dbData.scene_season = scene_season if scene_season is not None else -1
dbData.scene_episode = scene_episode if scene_episode is not None else -1
elif absolute_number:
if scene_absolute is not None:
if session.query(MainDB.TVEpisode).filter_by(showid=indexer_id, indexer=indexer, scene_absolute_number=scene_absolute).count():
return False
dbData = session.query(MainDB.TVEpisode).filter_by(showid=indexer_id, indexer=indexer, absolute_number=absolute_number).one()
dbData.scene_absolute_number = scene_absolute
dbData.scene_absolute_number = scene_absolute if scene_absolute is not None else -1
session.commit()
return True
def xem_refresh(indexer_id, indexer, force=False):
"""
......@@ -441,13 +452,10 @@ def xem_refresh(indexer_id, indexer, force=False):
return
for entry in parsed_json['data']:
episode_object = show_object.get_episode(
season=entry[IndexerApi(indexer).config['xem_origin']]['season'],
episode=entry[IndexerApi(indexer).config['xem_origin']]['episode'],
no_create=True
)
if not episode_object:
try:
episode_object = show_object.get_episode(season=entry[IndexerApi(indexer).config['xem_origin']]['season'],
episode=entry[IndexerApi(indexer).config['xem_origin']]['episode'])
except EpisodeNotFoundException:
continue
if 'scene' in entry:
......
......@@ -68,7 +68,8 @@ class TVShow(object):
self.load_from_indexer()
sickrage.app.shows.update({(self.indexer_id, self.indexer): self})
sickrage.app.shows.update({(self.indexer_id, self.indexer): self})
@property
def indexer_id(self):
......@@ -1194,7 +1195,7 @@ class TVShow(object):
def want_episode(self, season, episode, quality, manualSearch=False, downCurQuality=False):
try:
episode_object = self.get_episode(season, episode, no_create=True)
episode_object = self.get_episode(season, episode)
except EpisodeNotFoundException:
sickrage.app.log.debug("Unable to find a matching episode in database, ignoring found episode")
return False
......
......@@ -1638,23 +1638,20 @@ class SetSceneNumberingHandler(BaseHandler, ABC):
result = {
'success': True,
'forAbsolute': for_absolute,
'sceneAbsolute': 0
}
else:
result = {
'success': True,
'forSeason': for_season,
'forEpisode': for_episode,
'sceneSeason': 0,
'sceneEpisode': 0
}
# retrieve the episode object and fail if we can't get one
try:
if show_obj.is_anime:
show_obj.get_episode(absolute=for_absolute)
else:
show_obj.get_episode(season=for_season, episode=for_episode)
if show_obj.is_anime:
sickrage.app.log.debug("setAbsoluteSceneNumbering for %s from %s to %s" % (show, for_absolute, scene_absolute))
if for_absolute is not None:
show_obj.get_episode(absolute_number=for_absolute)
show = int(show)
indexer = int(indexer)
......@@ -1662,10 +1659,15 @@ class SetSceneNumberingHandler(BaseHandler, ABC):
if scene_absolute is not None:
scene_absolute = int(scene_absolute)
set_scene_numbering(show, indexer, absolute_number=for_absolute, scene_absolute=scene_absolute)
result['sceneAbsolute'] = get_scene_absolute_numbering(show, indexer, for_absolute)
if set_scene_numbering(show, indexer, absolute_number=for_absolute, scene_absolute=scene_absolute):
sickrage.app.log.debug("setAbsoluteSceneNumbering for %s from %s to %s" % (show, for_absolute, scene_absolute))
if scene_absolute is not None:
result['sceneAbsolute'] = get_scene_absolute_numbering(show, indexer, for_absolute)
else:
result['errorMessage'] = _("Another episode already has the same scene absolute numbering")
result['success'] = False
else:
sickrage.app.log.debug("setEpisodeSceneNumbering for %s from %sx%s to %sx%s" % (show, for_season, for_episode, scene_season, scene_episode))
show_obj.get_episode(season=for_season, episode=for_episode)
show = int(show)
indexer = int(indexer)
......@@ -1676,9 +1678,15 @@ class SetSceneNumberingHandler(BaseHandler, ABC):
if scene_episode is not None:
scene_episode = int(scene_episode)
set_scene_numbering(show, indexer, season=for_season, episode=for_episode, scene_season=scene_season, scene_episode=scene_episode)
(result['sceneSeason'], result['sceneEpisode']) = get_scene_numbering(show, indexer, for_season, for_episode)
except (EpisodeNotFoundException, MultipleEpisodesInDatabaseException):
if set_scene_numbering(show, indexer, season=for_season, episode=for_episode, scene_season=scene_season, scene_episode=scene_episode):
sickrage.app.log.debug(
"setEpisodeSceneNumbering for %s from %sx%s to %sx%s" % (show, for_season, for_episode, scene_season, scene_episode))
if scene_season is not None and scene_episode is not None:
result['sceneSeason'], result['sceneEpisode'] = get_scene_numbering(show, indexer, for_season, for_episode)
else:
result['errorMessage'] = _("Another episode already has the same scene numbering")
result['success'] = False
except EpisodeNotFoundException:
result['errorMessage'] = _("Episode couldn't be retrieved")
result['success'] = False
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
......@@ -66,5 +66,5 @@ class WebSocketMessage(object):
def push(self):
"""Push the message to all connected WebSocket clients."""
message_queue.put(self.json())
for client in clients:
for client in clients.copy():
sickrage.app.wserver.io_loop.add_callback(client.write_message, message_queue.get())
......@@ -218,7 +218,7 @@ class GenericProvider(object):
episode_string += 'Series {season} {episode}of{episodes}'.format(season=episode_object.get_season_episode_numbering()[0],
episode=episode_object.get_season_episode_numbering()[1],
episodes=len([x for x in show_object.episodes if
x.episode_object.get_season_episode_numbering()[0] == season]))
x.get_season_episode_numbering()[0] == season]))
episode_string_fallback = '{show_name}{search_separator}Series {season} Part {episode}'.format(show_name=show_name,
search_separator=self.search_separator,
season=episode_object.get_season_episode_numbering()[0],
......