# # This file is part of SickGear. # # SickGear is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # SickGear is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with SickGear. If not, see <http://www.gnu.org/licenses/>. from __future__ import with_statement import traceback # noinspection PyPep8Naming from exceptions_helper import ex from . import db, generic_queue, logger, helpers, ui # noinspection PyUnreachableCode if False: from six import integer_types from typing import AnyStr, Dict, List, Optional from .tv import TVShow from lib.tvinfo_base import CastList class PeopleQueue(generic_queue.GenericQueue): def __init__(self): generic_queue.GenericQueue.__init__(self, cache_db_tables=['people_queue']) self.queue_name = 'PEOPLEQUEUE' # type: AnyStr def load_queue(self): try: my_db = db.DBConnection('cache.db') queue_sql = my_db.select('SELECT * FROM people_queue') for q in queue_sql: if PeopleQueueActions.SHOWCAST == q['action_id']: try: show_obj = helpers.find_show_by_id({q['indexer']: q['indexer_id']}) except (BaseException, Exception): continue if not show_obj: continue self.add_cast_update(show_obj=show_obj, show_info_cast=None, uid=q['uid'], force=bool(q['forced']), scheduled_update=bool(q['scheduled']), add_to_db=False) except (BaseException, Exception) as e: logger.error('Exception loading queue %s: %s' % (self.__class__.__name__, ex(e))) try: my_db = db.DBConnection() if not my_db.has_flag('cast_loaded'): import sickgear [self.add_cast_update(s, show_info_cast=None, scheduled_update=True) for s in sickgear.showList if not s.cast_list] my_db.set_flag('cast_loaded') except (BaseException, Exception): pass def _clear_sql(self): return [ ['DELETE FROM people_queue'] ] def _get_item_sql(self, item): # type: (PeopleQueueItem) -> List[List] return [ ['INSERT OR IGNORE INTO people_queue (indexer, indexer_id, action_id, forced, scheduled, uid)' ' VALUES (?,?,?,?,?,?)', [item.show_obj.tvid, item.show_obj.prodid, item.action_id, int(item.force), int(item.scheduled_update), item.uid]] ] def _delete_item_from_db_sql(self, item): # type: (PeopleQueueItem) -> List[List] return [ ['DELETE FROM people_queue WHERE uid = ?', [item.uid]] ] def queue_data(self): # type: (...) -> Dict[AnyStr, List[AnyStr, Dict]] data = {'main_cast': []} with self.lock: for cur_item in [self.currentItem] + self.queue: # type: PeopleQueueItem if not cur_item or not cur_item.show_obj: continue result_item = {'name': cur_item.show_obj.name, 'tvid_prodid': cur_item.show_obj.tvid_prodid, 'uid': cur_item.uid, 'forced': cur_item.force} if isinstance(cur_item, CastQueueItem): data['main_cast'].append(result_item) return data def show_in_queue(self, show_obj, check_inprogress=False): # type: (TVShow, Optional[bool]) -> bool with self.lock: return any(1 for q in ((self.currentItem and [self.currentItem]) or []) + self.queue if show_obj == q.show_obj and (True, q.inProgress)[check_inprogress]) def abort_cast_update(self, show_obj): # type: (TVShow) -> None if show_obj: with self.lock: to_remove = [] for c in ((self.currentItem and [self.currentItem]) or []) + self.queue: if show_obj == c.show_obj: try: to_remove.append(c.uid) except (BaseException, Exception): pass try: c.stop.set() except (BaseException, Exception): pass if to_remove: try: self.remove_from_queue(to_remove) except (BaseException, Exception): pass def add_cast_update(self, show_obj, show_info_cast, uid=None, add_to_db=True, force=False, scheduled_update=False, switch=False): # type: (TVShow, Optional[CastList], AnyStr, bool, bool, bool, bool) -> CastQueueItem """ :param show_obj: TV Show object :param show_info_cast: TV Info object :param uid: unique id :param add_to_db: add to queue db table :param force: :param scheduled_update: suppresses ui notifications :param switch: part of id switch """ with self.lock: if not self.show_in_queue(show_obj): cast_item = CastQueueItem(show_obj=show_obj, show_info_cast=show_info_cast, uid=uid, force=force, scheduled_update=scheduled_update, switch=switch) self.add_item(cast_item, add_to_db=add_to_db) return cast_item class PeopleQueueActions(object): SHOWCAST = 1 names = { SHOWCAST: 'Show Cast', } class PeopleQueueItem(generic_queue.QueueItem): def __init__(self, action_id, show_obj, uid=None, force=False, **kwargs): # type: (integer_types, TVShow, AnyStr, bool, Dict) -> PeopleQueueItem """ :param action_id: :param show_obj: show object """ generic_queue.QueueItem.__init__(self, PeopleQueueActions.names[action_id], action_id, uid=uid) self.show_obj = show_obj # type: TVShow self.force = force # type: bool def finish(self): self.show_obj = None super(PeopleQueueItem, self).finish() class CastQueueItem(PeopleQueueItem): def __init__(self, show_obj, show_info_cast=None, uid=None, force=False, scheduled_update=False, switch=False, **kwargs): # type: (TVShow, CastList, AnyStr, bool, bool, bool, Dict) -> CastQueueItem """ :param show_obj: show obj :param show_info_cast: show info cast list :param scheduled_update: suppresses ui notifications :param switch: part of id switch """ PeopleQueueItem.__init__(self, PeopleQueueActions.SHOWCAST, show_obj, uid=uid, force=force, **kwargs) self.show_info_cast = show_info_cast # type: Optional[CastList] self.scheduled_update = scheduled_update # type: bool self.switch = switch # type: bool def run(self): PeopleQueueItem.run(self) if self.show_obj: logger.log('Starting cast update for show %s' % self.show_obj.unique_name) old_cast = self.show_obj.cast_list_id() if not self.scheduled_update and not self.switch: ui.notifications.message('Starting cast update for show %s' % self.show_obj.unique_name) try: self.show_obj.load_cast_from_tvinfo(self.show_info_cast, force=self.force, stop_event=self.stop) update_success = True except (BaseException, Exception) as e: update_success = False logger.error('Exception in cast update queue: %s' % ex(e)) logger.debug('Traceback: %s' % traceback.format_exc()) if update_success and (old_cast != self.show_obj.cast_list_id()): logger.debug('Update show nfo with new cast data') self.show_obj.write_show_nfo(force=True) logger.log('Finished cast update for show %s' % self.show_obj.unique_name) if not self.scheduled_update and not self.switch: ui.notifications.message('Finished cast update for show %s' % self.show_obj.unique_name) self.finish() def finish(self): self.show_info_cast = None super(CastQueueItem, self).finish() def __str__(self): return '<Cast Queue Item (%s)%s>' % (self.show_obj.unique_name, ('', ' - forced')[self.force]) def __repr__(self): return self.__str__()