2015-05-04 19:14:29 +00:00
# Author: Nic Wolfe <nic@wolfeden.ca>
2014-03-10 05:18:05 +00:00
# URL: http://code.google.com/p/sickbeard/
#
2014-11-12 16:43:14 +00:00
# This file is part of SickGear.
2014-03-10 05:18:05 +00:00
#
2014-11-12 16:43:14 +00:00
# SickGear is free software: you can redistribute it and/or modify
2014-03-10 05:18:05 +00:00
# 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.
#
2014-11-12 16:43:14 +00:00
# SickGear is distributed in the hope that it will be useful,
2014-03-10 05:18:05 +00:00
# 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
2014-11-12 16:43:14 +00:00
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
2014-03-10 05:18:05 +00:00
from __future__ import with_statement
import traceback
import sickbeard
2015-03-14 19:51:14 +00:00
from sickbeard . common import SKIPPED , WANTED , UNAIRED
2014-03-10 05:18:05 +00:00
from sickbeard . tv import TVShow
from sickbeard import exceptions , logger , ui , db
from sickbeard import generic_queue
from sickbeard import name_cache
from sickbeard . exceptions import ex
2015-01-22 22:53:24 +00:00
from sickbeard . blackandwhitelist import BlackAndWhiteList
2015-07-25 09:19:46 +00:00
from sickbeard . indexers . indexer_config import INDEXER_TVDB
2014-03-10 05:18:05 +00:00
2015-03-14 02:48:38 +00:00
2014-03-10 05:18:05 +00:00
class ShowQueue ( generic_queue . GenericQueue ) :
def __init__ ( self ) :
generic_queue . GenericQueue . __init__ ( self )
2015-05-04 19:14:29 +00:00
self . queue_name = ' SHOWQUEUE '
2014-03-10 05:18:05 +00:00
def _isInQueue ( self , show , actions ) :
2015-05-04 19:14:29 +00:00
with self . lock :
return show in [ x . show for x in self . queue if x . action_id in actions ]
2014-03-10 05:18:05 +00:00
def _isBeingSomethinged ( self , show , actions ) :
2015-05-04 19:14:29 +00:00
with self . lock :
return self . currentItem != None and show == self . currentItem . show and \
self . currentItem . action_id in actions
2014-03-10 05:18:05 +00:00
def isInUpdateQueue ( self , show ) :
return self . _isInQueue ( show , ( ShowQueueActions . UPDATE , ShowQueueActions . FORCEUPDATE ) )
def isInRefreshQueue ( self , show ) :
return self . _isInQueue ( show , ( ShowQueueActions . REFRESH , ) )
def isInRenameQueue ( self , show ) :
return self . _isInQueue ( show , ( ShowQueueActions . RENAME , ) )
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
def isInSubtitleQueue ( self , show ) :
return self . _isInQueue ( show , ( ShowQueueActions . SUBTITLE , ) )
def isBeingAdded ( self , show ) :
return self . _isBeingSomethinged ( show , ( ShowQueueActions . ADD , ) )
def isBeingUpdated ( self , show ) :
return self . _isBeingSomethinged ( show , ( ShowQueueActions . UPDATE , ShowQueueActions . FORCEUPDATE ) )
def isBeingRefreshed ( self , show ) :
return self . _isBeingSomethinged ( show , ( ShowQueueActions . REFRESH , ) )
def isBeingRenamed ( self , show ) :
return self . _isBeingSomethinged ( show , ( ShowQueueActions . RENAME , ) )
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
def isBeingSubtitled ( self , show ) :
return self . _isBeingSomethinged ( show , ( ShowQueueActions . SUBTITLE , ) )
2015-05-04 19:14:29 +00:00
def isShowUpdateRunning ( self ) :
with self . lock :
for x in self . queue + [ self . currentItem ] :
if isinstance ( x , ShowQueueItem ) and x . scheduled_update :
return True
return False
2014-03-10 05:18:05 +00:00
def _getLoadingShowList ( self ) :
2015-05-04 19:14:29 +00:00
with self . lock :
return [ x for x in self . queue + [ self . currentItem ] if x != None and x . isLoading ]
def queue_length ( self ) :
length = { ' add ' : [ ] , ' update ' : [ ] , ' forceupdate ' : [ ] , ' forceupdateweb ' : [ ] , ' refresh ' : [ ] , ' rename ' : [ ] , ' subtitle ' : [ ] }
with self . lock :
for cur_item in [ self . currentItem ] + self . queue :
if isinstance ( cur_item , QueueItemAdd ) :
length [ ' add ' ] . append ( [ cur_item . show_name , cur_item . scheduled_update ] )
elif isinstance ( cur_item , QueueItemUpdate ) :
update_type = ' Normal '
if isinstance ( cur_item , QueueItemForceUpdate ) :
update_type = ' Forced '
elif isinstance ( cur_item , QueueItemForceUpdateWeb ) :
update_type = ' Forced Web '
length [ ' update ' ] . append ( [ cur_item . show_name , cur_item . scheduled_update , update_type ] )
elif isinstance ( cur_item , QueueItemRefresh ) :
length [ ' refresh ' ] . append ( [ cur_item . show_name , cur_item . scheduled_update ] )
elif isinstance ( cur_item , QueueItemRename ) :
length [ ' rename ' ] . append ( [ cur_item . show_name , cur_item . scheduled_update ] )
elif isinstance ( cur_item , QueueItemSubtitle ) :
length [ ' subtitle ' ] . append ( [ cur_item . show_name , cur_item . scheduled_update ] )
return length
2014-03-10 05:18:05 +00:00
loadingShowList = property ( _getLoadingShowList )
2015-05-04 19:14:29 +00:00
def updateShow ( self , show , force = False , web = False , scheduled_update = False ) :
2014-03-10 05:18:05 +00:00
if self . isBeingAdded ( show ) :
2014-03-25 05:57:24 +00:00
raise exceptions . CantUpdateException (
2015-05-04 19:14:29 +00:00
' Show is still being added, wait until it is finished before you update. ' )
2014-03-10 05:18:05 +00:00
if self . isBeingUpdated ( show ) :
2014-03-25 05:57:24 +00:00
raise exceptions . CantUpdateException (
2015-05-04 19:14:29 +00:00
' This show is already being updated, can \' t update again until it \' s done. ' )
2014-03-10 05:18:05 +00:00
if self . isInUpdateQueue ( show ) :
2014-03-25 05:57:24 +00:00
raise exceptions . CantUpdateException (
2015-05-04 19:14:29 +00:00
' This show is already being updated, can \' t update again until it \' s done. ' )
2014-03-10 05:18:05 +00:00
if not force :
2015-05-04 19:14:29 +00:00
queueItemObj = QueueItemUpdate ( show , scheduled_update = scheduled_update )
2015-03-17 00:53:12 +00:00
elif web :
2015-05-04 19:14:29 +00:00
queueItemObj = QueueItemForceUpdateWeb ( show , scheduled_update = scheduled_update )
2014-03-10 05:18:05 +00:00
else :
2015-05-04 19:14:29 +00:00
queueItemObj = QueueItemForceUpdate ( show , scheduled_update = scheduled_update )
2014-03-10 05:18:05 +00:00
self . add_item ( queueItemObj )
return queueItemObj
2015-07-25 09:19:46 +00:00
def refreshShow ( self , show , force = False , scheduled_update = False , after_update = False ) :
2014-03-10 05:18:05 +00:00
if self . isBeingRefreshed ( show ) and not force :
2015-05-04 19:14:29 +00:00
raise exceptions . CantRefreshException ( ' This show is already being refreshed, not refreshing again. ' )
2014-03-10 05:18:05 +00:00
2015-07-25 09:19:46 +00:00
if ( ( not after_update and self . isBeingUpdated ( show ) ) or self . isInUpdateQueue ( show ) ) and not force :
2014-03-25 05:57:24 +00:00
logger . log (
2015-05-04 19:14:29 +00:00
u ' A refresh was attempted but there is already an update queued or in progress. Since updates do a refresh at the end anyway I \' m skipping this request. ' ,
2014-03-25 05:57:24 +00:00
logger . DEBUG )
2014-03-10 05:18:05 +00:00
return
2015-05-04 19:14:29 +00:00
queueItemObj = QueueItemRefresh ( show , force = force , scheduled_update = scheduled_update )
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
self . add_item ( queueItemObj )
return queueItemObj
def renameShowEpisodes ( self , show , force = False ) :
queueItemObj = QueueItemRename ( show )
self . add_item ( queueItemObj )
return queueItemObj
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
def downloadSubtitles ( self , show , force = False ) :
queueItemObj = QueueItemSubtitle ( show )
self . add_item ( queueItemObj )
return queueItemObj
2014-03-25 05:57:24 +00:00
def addShow ( self , indexer , indexer_id , showDir , default_status = None , quality = None , flatten_folders = None ,
2015-05-04 19:14:29 +00:00
lang = ' en ' , subtitles = None , anime = None , scene = None , paused = None , blacklist = None , whitelist = None ,
2015-04-07 03:10:50 +00:00
wanted_begin = None , wanted_latest = None , tag = None ) :
2014-03-25 05:57:24 +00:00
queueItemObj = QueueItemAdd ( indexer , indexer_id , showDir , default_status , quality , flatten_folders , lang ,
2015-03-10 00:13:58 +00:00
subtitles , anime , scene , paused , blacklist , whitelist ,
2015-04-07 03:10:50 +00:00
wanted_begin , wanted_latest , tag )
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
self . add_item ( queueItemObj )
return queueItemObj
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
class ShowQueueActions :
2014-03-25 05:57:24 +00:00
REFRESH = 1
ADD = 2
UPDATE = 3
FORCEUPDATE = 4
RENAME = 5
SUBTITLE = 6
2014-03-10 05:18:05 +00:00
names = { REFRESH : ' Refresh ' ,
2014-03-25 05:57:24 +00:00
ADD : ' Add ' ,
UPDATE : ' Update ' ,
FORCEUPDATE : ' Force Update ' ,
RENAME : ' Rename ' ,
2015-03-14 02:48:38 +00:00
SUBTITLE : ' Subtitle ' }
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
class ShowQueueItem ( generic_queue . QueueItem ) :
"""
Represents an item in the queue waiting to be executed
Can be either :
- show being added ( may or may not be associated with a show object )
- show being refreshed
- show being updated
- show being force updated
- show being subtitled
"""
2014-03-25 05:57:24 +00:00
2015-05-04 19:14:29 +00:00
def __init__ ( self , action_id , show , scheduled_update = False ) :
2014-03-10 05:18:05 +00:00
generic_queue . QueueItem . __init__ ( self , ShowQueueActions . names [ action_id ] , action_id )
self . show = show
2015-05-04 19:14:29 +00:00
self . scheduled_update = scheduled_update
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
def isInQueue ( self ) :
2014-06-12 17:26:09 +00:00
return self in sickbeard . showQueueScheduler . action . queue + [
sickbeard . showQueueScheduler . action . currentItem ] #@UndefinedVariable
2014-03-10 05:18:05 +00:00
def _getName ( self ) :
return str ( self . show . indexerid )
def _isLoading ( self ) :
return False
show_name = property ( _getName )
isLoading = property ( _isLoading )
class QueueItemAdd ( ShowQueueItem ) :
2014-06-12 17:26:09 +00:00
def __init__ ( self , indexer , indexer_id , showDir , default_status , quality , flatten_folders , lang , subtitles , anime ,
2015-05-04 19:14:29 +00:00
scene , paused , blacklist , whitelist , default_wanted_begin , default_wanted_latest , tag , scheduled_update = False ) :
2014-03-10 05:18:05 +00:00
self . indexer = indexer
self . indexer_id = indexer_id
self . showDir = showDir
self . default_status = default_status
2015-03-10 00:13:58 +00:00
self . default_wanted_begin = default_wanted_begin
self . default_wanted_latest = default_wanted_latest
2014-03-10 05:18:05 +00:00
self . quality = quality
self . flatten_folders = flatten_folders
self . lang = lang
self . subtitles = subtitles
2014-05-26 06:29:22 +00:00
self . anime = anime
2014-06-02 03:43:37 +00:00
self . scene = scene
2014-09-24 12:22:56 +00:00
self . paused = paused
2015-01-25 11:58:49 +00:00
self . blacklist = blacklist
self . whitelist = whitelist
2015-04-07 03:10:50 +00:00
self . tag = tag
2014-03-10 05:18:05 +00:00
self . show = None
# this will initialize self.show to None
2015-05-04 19:14:29 +00:00
ShowQueueItem . __init__ ( self , ShowQueueActions . ADD , self . show , scheduled_update )
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
def _getName ( self ) :
"""
Returns the show name if there is a show object created , if not returns
the dir that the show is being added to .
"""
2014-03-20 18:03:22 +00:00
if self . show == None :
2014-03-10 05:18:05 +00:00
return self . showDir
return self . show . name
show_name = property ( _getName )
def _isLoading ( self ) :
"""
Returns True if we ' ve gotten far enough to have a show object, or False
if we still only know the folder name .
"""
2014-03-20 18:03:22 +00:00
if self . show == None :
2014-03-10 05:18:05 +00:00
return True
return False
isLoading = property ( _isLoading )
2014-07-15 02:00:53 +00:00
def run ( self ) :
2014-03-10 05:18:05 +00:00
2014-07-15 02:00:53 +00:00
ShowQueueItem . run ( self )
2014-03-10 05:18:05 +00:00
2015-05-04 19:14:29 +00:00
logger . log ( u ' Starting to add show ' + self . showDir )
2014-04-27 10:58:49 +00:00
# make sure the Indexer IDs are valid
2014-03-10 05:18:05 +00:00
try :
2014-03-18 14:41:46 +00:00
2014-03-26 19:28:46 +00:00
lINDEXER_API_PARMS = sickbeard . indexerApi ( self . indexer ) . api_params . copy ( )
2014-03-18 14:41:46 +00:00
if self . lang :
lINDEXER_API_PARMS [ ' language ' ] = self . lang
2015-05-04 19:14:29 +00:00
logger . log ( u ' ' + str ( sickbeard . indexerApi ( self . indexer ) . name ) + ' : ' + repr ( lINDEXER_API_PARMS ) )
2014-03-18 14:41:46 +00:00
2014-03-26 19:28:46 +00:00
t = sickbeard . indexerApi ( self . indexer ) . indexer ( * * lINDEXER_API_PARMS )
2014-03-18 14:41:46 +00:00
s = t [ self . indexer_id ]
2014-04-27 10:58:49 +00:00
# this usually only happens if they have an NFO in their show dir which gave us a Indexer ID that has no proper english version of the show
2014-03-18 14:41:46 +00:00
if getattr ( s , ' seriesname ' , None ) is None :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Show in ' + self . showDir + ' has no name on ' + str (
sickbeard . indexerApi ( self . indexer ) . name ) + ' , probably the wrong language used to search with. ' ,
2014-06-12 17:26:09 +00:00
logger . ERROR )
2015-05-04 19:14:29 +00:00
ui . notifications . error ( ' Unable to add show ' ,
' Show in ' + self . showDir + ' has no name on ' + str ( sickbeard . indexerApi (
self . indexer ) . name ) + ' , probably the wrong language. Delete .nfo and add manually in the correct language. ' )
2014-03-10 05:18:05 +00:00
self . _finishEarly ( )
return
2014-03-18 14:41:46 +00:00
# if the show has no episodes/seasons
if not s :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Show ' + str ( s [ ' seriesname ' ] ) + ' is on ' + str (
sickbeard . indexerApi ( self . indexer ) . name ) + ' but contains no season/episode data. ' , logger . ERROR )
ui . notifications . error ( ' Unable to add show ' ,
' Show ' + str ( s [ ' seriesname ' ] ) + ' is on ' + str ( sickbeard . indexerApi (
self . indexer ) . name ) + ' but contains no season/episode data. ' )
2014-03-18 14:41:46 +00:00
self . _finishEarly ( )
return
2015-06-08 12:47:01 +00:00
except Exception as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Unable to find show ID: ' + str ( self . indexer_id ) + ' on Indexer: ' + str (
2014-06-12 17:26:09 +00:00
sickbeard . indexerApi ( self . indexer ) . name ) , logger . ERROR )
2015-05-04 19:14:29 +00:00
ui . notifications . error ( ' Unable to add show ' ,
' Unable to look up the show in ' + self . showDir + ' on ' + str ( sickbeard . indexerApi (
self . indexer ) . name ) + ' using ID ' + str (
self . indexer_id ) + ' , not using the NFO. Delete .nfo and try adding manually again. ' )
2014-03-18 14:41:46 +00:00
self . _finishEarly ( )
return
2014-03-10 05:18:05 +00:00
2014-03-18 14:41:46 +00:00
try :
2014-03-10 05:18:05 +00:00
newShow = TVShow ( self . indexer , self . indexer_id , self . lang )
newShow . loadFromIndexer ( )
self . show = newShow
# set up initial values
self . show . location = self . showDir
2015-05-07 02:33:40 +00:00
self . show . subtitles = self . subtitles if None is not self . subtitles else sickbeard . SUBTITLES_DEFAULT
2014-03-10 05:18:05 +00:00
self . show . quality = self . quality if self . quality else sickbeard . QUALITY_DEFAULT
2015-05-07 02:33:40 +00:00
self . show . flatten_folders = self . flatten_folders if None is not self . flatten_folders else sickbeard . FLATTEN_FOLDERS_DEFAULT
self . show . anime = self . anime if None is not self . anime else sickbeard . ANIME_DEFAULT
self . show . scene = self . scene if None is not self . scene else sickbeard . SCENE_DEFAULT
self . show . paused = self . paused if None is not self . paused else False
self . show . tag = self . tag if None is not self . tag else ' Show List '
2014-03-25 05:57:24 +00:00
2015-01-22 22:53:24 +00:00
if self . show . anime :
self . show . release_groups = BlackAndWhiteList ( self . show . indexerid )
2015-01-25 11:58:49 +00:00
if self . blacklist :
self . show . release_groups . set_black_keywords ( self . blacklist )
if self . whitelist :
self . show . release_groups . set_white_keywords ( self . whitelist )
2015-01-22 22:53:24 +00:00
2014-03-10 05:18:05 +00:00
# be smartish about this
2015-05-04 19:14:29 +00:00
if self . show . genre and ' talk show ' in self . show . genre . lower ( ) :
2014-03-10 05:18:05 +00:00
self . show . air_by_date = 1
2015-05-04 19:14:29 +00:00
if self . show . genre and ' documentary ' in self . show . genre . lower ( ) :
2014-05-23 05:02:49 +00:00
self . show . air_by_date = 0
2015-05-04 19:14:29 +00:00
if self . show . classification and ' sports ' in self . show . classification . lower ( ) :
2014-04-28 09:15:29 +00:00
self . show . sports = 1
2014-03-10 05:18:05 +00:00
2015-06-08 12:47:01 +00:00
except sickbeard . indexer_exception as e :
2014-03-25 05:57:24 +00:00
logger . log (
2015-05-04 19:14:29 +00:00
u ' Unable to add show due to an error with ' + sickbeard . indexerApi ( self . indexer ) . name + ' : ' + ex ( e ) ,
2014-03-25 05:57:24 +00:00
logger . ERROR )
2014-03-10 05:18:05 +00:00
if self . show :
2014-03-25 05:57:24 +00:00
ui . notifications . error (
2015-05-04 19:14:29 +00:00
' Unable to add ' + str ( self . show . name ) + ' due to an error with ' + sickbeard . indexerApi (
self . indexer ) . name + ' ' )
2014-03-10 05:18:05 +00:00
else :
2014-03-25 05:57:24 +00:00
ui . notifications . error (
2015-05-04 19:14:29 +00:00
' Unable to add show due to an error with ' + sickbeard . indexerApi ( self . indexer ) . name + ' ' )
2014-03-10 05:18:05 +00:00
self . _finishEarly ( )
return
except exceptions . MultipleShowObjectsException :
2015-05-04 19:14:29 +00:00
logger . log ( u ' The show in ' + self . showDir + ' is already in your show list, skipping ' , logger . ERROR )
ui . notifications . error ( ' Show skipped ' , ' The show in ' + self . showDir + ' is already in your show list ' )
2014-03-10 05:18:05 +00:00
self . _finishEarly ( )
return
2015-06-08 12:47:01 +00:00
except Exception as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Error trying to add show: ' + ex ( e ) , logger . ERROR )
2014-03-10 05:18:05 +00:00
logger . log ( traceback . format_exc ( ) , logger . DEBUG )
self . _finishEarly ( )
raise
2015-03-14 02:48:38 +00:00
self . show . load_imdb_info ( )
2014-03-10 05:18:05 +00:00
try :
self . show . saveToDB ( )
2015-06-08 12:47:01 +00:00
except Exception as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Error saving the show to the database: ' + ex ( e ) , logger . ERROR )
2014-03-10 05:18:05 +00:00
logger . log ( traceback . format_exc ( ) , logger . DEBUG )
self . _finishEarly ( )
raise
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
# add it to the show list
2014-03-25 05:57:24 +00:00
sickbeard . showList . append ( self . show )
2014-03-10 05:18:05 +00:00
try :
self . show . loadEpisodesFromIndexer ( )
2015-06-08 12:47:01 +00:00
except Exception as e :
2014-03-25 05:57:24 +00:00
logger . log (
2015-05-04 19:14:29 +00:00
u ' Error with ' + sickbeard . indexerApi ( self . show . indexer ) . name + ' , not creating episode list: ' + ex ( e ) ,
2014-03-25 05:57:24 +00:00
logger . ERROR )
2014-03-10 05:18:05 +00:00
logger . log ( traceback . format_exc ( ) , logger . DEBUG )
try :
self . show . loadEpisodesFromDir ( )
2015-06-08 12:47:01 +00:00
except Exception as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Error searching directory for episodes: ' + ex ( e ) , logger . ERROR )
2014-03-10 05:18:05 +00:00
logger . log ( traceback . format_exc ( ) , logger . DEBUG )
# if they gave a custom status then change all the eps to it
2015-03-14 19:51:14 +00:00
my_db = db . DBConnection ( )
2014-03-10 05:18:05 +00:00
if self . default_status != SKIPPED :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Setting all episodes to the specified default status: ' + str ( self . default_status ) )
my_db . action ( ' UPDATE tv_episodes SET status = ? WHERE status = ? AND showid = ? AND season != 0 ' ,
2014-06-21 22:46:59 +00:00
[ self . default_status , SKIPPED , self . show . indexerid ] )
2014-03-10 05:18:05 +00:00
2015-03-10 00:13:58 +00:00
# if they gave a number to start or number to end as wanted, then change those eps to it
2015-03-14 19:51:14 +00:00
def get_wanted ( db_obj , wanted_max , latest ) :
2015-03-10 00:13:58 +00:00
actual = 0
if wanted_max :
2015-03-14 19:51:14 +00:00
select_id = ' FROM [tv_episodes] t5 JOIN (SELECT t3.indexerid, t3.status, t3.season*1000000+t3.episode AS t3_se, t2.start_season FROM [tv_episodes] t3 ' \
+ ' JOIN (SELECT t1.showid, M %s (t1.season) AS start_season ' % ( ' IN ' , ' AX ' ) [ latest ] \
+ ' , MAX(t1.airdate) AS airdate, t1.episode, t1.season*1000000+t1.episode AS se FROM [tv_episodes] t1 ' \
+ ' WHERE %s =t1.showid ' % self . show . indexerid \
+ ' AND 0<t1.season AND t1.status NOT IN ( %s )) AS t2 ' % UNAIRED \
+ ' ON t2.showid=t3.showid AND 0<t3.season AND t2.se>=t3_se ORDER BY t3_se %s SC ' % ( ' A ' , ' DE ' ) [ latest ] \
+ ' %s ) as t4 ' % ( ' LIMIT %s ' % wanted_max , ' ' ) [ - 1 == wanted_max ] \
+ ' ON t4.indexerid=t5.indexerid ' \
+ ' %s ' % ( ' ' , ' AND t4.start_season=t5.season ' ) [ - 1 == wanted_max ] \
+ ' AND t4.status NOT IN ( %s ) ' % ' , ' . join ( [ str ( x ) for x in sickbeard . common . Quality . DOWNLOADED + [ WANTED ] ] )
select = ' SELECT t5.indexerid as indexerid, t5.season as season, t5.episode as episode, t5.status as status ' + select_id
update = ' UPDATE [tv_episodes] SET status= %s WHERE indexerid IN (SELECT t5.indexerid %s ) ' % ( WANTED , select_id )
wanted_updates = db_obj . select ( select )
db_obj . action ( update )
2015-05-04 19:14:29 +00:00
result = db_obj . select ( ' SELECT changes() as last FROM [tv_episodes] ' )
2015-03-10 00:13:58 +00:00
for cur_result in result :
actual = cur_result [ ' last ' ]
break
2015-03-14 19:51:14 +00:00
action_log = ' didn \' t find any episodes that need to be set wanted '
if actual :
action_log = ( ' updated %s %s episodes > %s '
% ( ( ( ( ( ' %s of %s ' % ( actual , wanted_max ) ) , ( ' %s of max %s limited ' % ( actual , wanted_max ) ) ) [ 10 == wanted_max ] ) , ( ' max %s available ' % actual ) ) [ - 1 == wanted_max ] ,
( ' first season ' , ' latest ' ) [ latest ] ,
' , ' . join ( [ ( ' S %02d E %02d = %d ' % ( a [ ' season ' ] , a [ ' episode ' ] , a [ ' status ' ] ) ) for a in wanted_updates ] ) ) )
logger . log ( ' Get wanted ' + action_log )
2015-03-10 00:13:58 +00:00
return actual
2015-03-14 19:51:14 +00:00
items_wanted = get_wanted ( my_db , self . default_wanted_begin , latest = False )
items_wanted + = get_wanted ( my_db , self . default_wanted_latest , latest = True )
2015-03-10 00:13:58 +00:00
msg = ' the specified show into ' + self . showDir
# if started with WANTED eps then run the backlog
if WANTED == self . default_status or items_wanted :
logger . log ( u ' Launching backlog for this show since episodes are WANTED ' )
2014-03-25 05:57:24 +00:00
sickbeard . backlogSearchScheduler . action . searchBacklog ( [ self . show ] ) #@UndefinedVariable
2015-03-10 00:13:58 +00:00
ui . notifications . message ( ' Show added/search ' , ' Adding and searching for episodes of ' + msg )
else :
ui . notifications . message ( ' Show added ' , ' Adding ' + msg )
2014-03-10 05:18:05 +00:00
2014-05-14 09:42:08 +00:00
self . show . writeMetadata ( )
self . show . updateMetadata ( )
2014-03-14 03:07:15 +00:00
self . show . populateCache ( )
2014-03-10 05:18:05 +00:00
self . show . flushEpisodes ( )
2014-06-29 03:28:00 +00:00
if sickbeard . USE_TRAKT :
# if there are specific episodes that need to be added by trakt
sickbeard . traktCheckerScheduler . action . manageNewShow ( self . show )
# add show to trakt.tv library
2014-06-29 05:54:29 +00:00
if sickbeard . TRAKT_SYNC :
sickbeard . traktCheckerScheduler . action . addShowToTraktLibrary ( self . show )
2014-03-10 05:18:05 +00:00
2014-05-30 06:49:47 +00:00
# Load XEM data to DB for show
sickbeard . scene_numbering . xem_refresh ( self . show . indexerid , self . show . indexer , force = True )
2015-08-14 23:02:05 +00:00
# check if show has XEM mapping and if user disabled scene numbering during add show, output availability to log
if not self . scene and self . show . indexerid in sickbeard . scene_exceptions . xem_tvdb_ids_list \
+ sickbeard . scene_exceptions . xem_rage_ids_list :
logger . log ( u ' Alternative scene episode numbers were disabled during add show. Edit show to enable them for searching. ' )
2014-05-30 06:49:47 +00:00
2015-05-19 14:38:33 +00:00
# update internal name cache
name_cache . buildNameCache ( self . show )
2014-03-10 05:18:05 +00:00
self . finish ( )
def _finishEarly ( self ) :
2014-03-20 18:03:22 +00:00
if self . show != None :
2014-03-10 05:18:05 +00:00
self . show . deleteShow ( )
self . finish ( )
class QueueItemRefresh ( ShowQueueItem ) :
2015-05-04 19:14:29 +00:00
def __init__ ( self , show = None , force = False , scheduled_update = False ) :
ShowQueueItem . __init__ ( self , ShowQueueActions . REFRESH , show , scheduled_update )
2014-03-10 05:18:05 +00:00
# do refreshes first because they're quick
self . priority = generic_queue . QueuePriorities . HIGH
2014-05-30 05:48:02 +00:00
# force refresh certain items
self . force = force
2014-07-15 02:00:53 +00:00
def run ( self ) :
ShowQueueItem . run ( self )
2014-03-10 05:18:05 +00:00
2015-05-04 19:14:29 +00:00
logger . log ( u ' Performing refresh on ' + self . show . name )
2014-03-10 05:18:05 +00:00
self . show . refreshDir ( )
2014-05-14 04:14:54 +00:00
self . show . writeMetadata ( )
2014-07-18 05:57:35 +00:00
#if self.force:
# self.show.updateMetadata()
2014-03-10 05:18:05 +00:00
self . show . populateCache ( )
2014-05-30 06:49:47 +00:00
# Load XEM data to DB for show
2015-07-25 09:19:46 +00:00
if self . show . indexerid in sickbeard . scene_exceptions . xem_tvdb_ids_list if INDEXER_TVDB == self . show . indexer else sickbeard . scene_exceptions . xem_rage_ids_list :
sickbeard . scene_numbering . xem_refresh ( self . show . indexerid , self . show . indexer )
2014-05-30 06:49:47 +00:00
2014-03-10 05:18:05 +00:00
self . inProgress = False
2015-03-14 02:48:38 +00:00
2014-03-10 05:18:05 +00:00
class QueueItemRename ( ShowQueueItem ) :
2015-05-04 19:14:29 +00:00
def __init__ ( self , show = None , scheduled_update = False ) :
ShowQueueItem . __init__ ( self , ShowQueueActions . RENAME , show , scheduled_update )
2014-03-10 05:18:05 +00:00
2014-07-15 02:00:53 +00:00
def run ( self ) :
2014-03-10 05:18:05 +00:00
2014-07-15 02:00:53 +00:00
ShowQueueItem . run ( self )
2014-03-10 05:18:05 +00:00
2015-05-04 19:14:29 +00:00
logger . log ( u ' Performing rename on ' + self . show . name )
2014-03-10 05:18:05 +00:00
try :
show_loc = self . show . location
except exceptions . ShowDirNotFoundException :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Can \' t perform rename on ' + self . show . name + ' when the show directory is missing. ' , logger . WARNING )
2014-03-10 05:18:05 +00:00
return
ep_obj_rename_list = [ ]
ep_obj_list = self . show . getAllEpisodes ( has_location = True )
for cur_ep_obj in ep_obj_list :
# Only want to rename if we have a location
if cur_ep_obj . location :
if cur_ep_obj . relatedEps :
# do we have one of multi-episodes in the rename list already
have_already = False
for cur_related_ep in cur_ep_obj . relatedEps + [ cur_ep_obj ] :
if cur_related_ep in ep_obj_rename_list :
have_already = True
break
if not have_already :
ep_obj_rename_list . append ( cur_ep_obj )
else :
ep_obj_rename_list . append ( cur_ep_obj )
for cur_ep_obj in ep_obj_rename_list :
cur_ep_obj . rename ( )
self . inProgress = False
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
class QueueItemSubtitle ( ShowQueueItem ) :
2015-05-04 19:14:29 +00:00
def __init__ ( self , show = None , scheduled_update = False ) :
ShowQueueItem . __init__ ( self , ShowQueueActions . SUBTITLE , show , scheduled_update )
2014-03-10 05:18:05 +00:00
2014-07-15 02:00:53 +00:00
def run ( self ) :
ShowQueueItem . run ( self )
2014-03-10 05:18:05 +00:00
2015-05-04 19:14:29 +00:00
logger . log ( u ' Downloading subtitles for ' + self . show . name )
2014-03-10 05:18:05 +00:00
self . show . downloadSubtitles ( )
self . inProgress = False
class QueueItemUpdate ( ShowQueueItem ) :
2015-05-04 19:14:29 +00:00
def __init__ ( self , show = None , scheduled_update = False ) :
ShowQueueItem . __init__ ( self , ShowQueueActions . UPDATE , show , scheduled_update )
2014-03-10 05:18:05 +00:00
self . force = False
2015-03-17 00:53:12 +00:00
self . force_web = False
2014-03-10 05:18:05 +00:00
2014-07-15 02:00:53 +00:00
def run ( self ) :
2014-03-10 05:18:05 +00:00
2014-07-15 02:00:53 +00:00
ShowQueueItem . run ( self )
2014-03-10 05:18:05 +00:00
2015-05-04 19:14:29 +00:00
logger . log ( u ' Beginning update of ' + self . show . name )
2014-03-10 05:18:05 +00:00
2015-05-04 19:14:29 +00:00
logger . log ( u ' Retrieving show info from ' + sickbeard . indexerApi ( self . show . indexer ) . name + ' ' , logger . DEBUG )
2014-03-10 05:18:05 +00:00
try :
2015-03-19 15:34:11 +00:00
result = self . show . loadFromIndexer ( cache = not self . force )
if None is not result :
return
2015-06-08 12:47:01 +00:00
except sickbeard . indexer_error as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Unable to contact ' + sickbeard . indexerApi ( self . show . indexer ) . name + ' , aborting: ' + ex ( e ) ,
2014-03-25 05:57:24 +00:00
logger . WARNING )
2014-03-10 05:18:05 +00:00
return
2015-06-08 12:47:01 +00:00
except sickbeard . indexer_attributenotfound as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Data retrieved from ' + sickbeard . indexerApi (
self . show . indexer ) . name + ' was incomplete, aborting: ' + ex ( e ) , logger . ERROR )
2014-03-10 05:18:05 +00:00
return
2015-03-17 00:53:12 +00:00
if self . force_web :
self . show . load_imdb_info ( )
2014-03-10 05:18:05 +00:00
try :
self . show . saveToDB ( )
2015-06-08 12:47:01 +00:00
except Exception as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Error saving the episode to the database: ' + ex ( e ) , logger . ERROR )
2014-03-10 05:18:05 +00:00
logger . log ( traceback . format_exc ( ) , logger . DEBUG )
2014-03-25 05:57:24 +00:00
2014-03-10 05:18:05 +00:00
# get episode list from DB
2015-05-04 19:14:29 +00:00
logger . log ( u ' Loading all episodes from the database ' , logger . DEBUG )
2014-03-10 05:18:05 +00:00
DBEpList = self . show . loadEpisodesFromDB ( )
# get episode list from TVDB
2015-05-04 19:14:29 +00:00
logger . log ( u ' Loading all episodes from ' + sickbeard . indexerApi ( self . show . indexer ) . name + ' ' , logger . DEBUG )
2014-03-10 05:18:05 +00:00
try :
IndexerEpList = self . show . loadEpisodesFromIndexer ( cache = not self . force )
2015-06-08 12:47:01 +00:00
except sickbeard . indexer_exception as e :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Unable to get info from ' + sickbeard . indexerApi (
self . show . indexer ) . name + ' , the show info will not be refreshed: ' + ex ( e ) , logger . ERROR )
2014-03-10 05:18:05 +00:00
IndexerEpList = None
2014-03-20 18:03:22 +00:00
if IndexerEpList == None :
2015-05-04 19:14:29 +00:00
logger . log ( u ' No data returned from ' + sickbeard . indexerApi (
self . show . indexer ) . name + ' , unable to update this show ' , logger . ERROR )
2014-03-10 05:18:05 +00:00
else :
# for each ep we found on TVDB delete it from the DB list
for curSeason in IndexerEpList :
for curEpisode in IndexerEpList [ curSeason ] :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Removing ' + str ( curSeason ) + ' x ' + str ( curEpisode ) + ' from the DB list ' ,
2014-03-25 05:57:24 +00:00
logger . DEBUG )
2014-03-10 05:18:05 +00:00
if curSeason in DBEpList and curEpisode in DBEpList [ curSeason ] :
del DBEpList [ curSeason ] [ curEpisode ]
# for the remaining episodes in the DB list just delete them from the DB
for curSeason in DBEpList :
for curEpisode in DBEpList [ curSeason ] :
2015-05-04 19:14:29 +00:00
logger . log ( u ' Permanently deleting episode ' + str ( curSeason ) + ' x ' + str (
curEpisode ) + ' from the database ' , logger . MESSAGE )
2014-03-10 05:18:05 +00:00
curEp = self . show . getEpisode ( curSeason , curEpisode )
try :
curEp . deleteEpisode ( )
except exceptions . EpisodeDeletedException :
pass
2015-07-25 09:19:46 +00:00
sickbeard . showQueueScheduler . action . refreshShow ( self . show , self . force , self . scheduled_update , after_update = True )
2014-03-10 05:18:05 +00:00
2014-06-12 17:26:09 +00:00
2014-03-10 05:18:05 +00:00
class QueueItemForceUpdate ( QueueItemUpdate ) :
2015-05-04 19:14:29 +00:00
def __init__ ( self , show = None , scheduled_update = False ) :
ShowQueueItem . __init__ ( self , ShowQueueActions . FORCEUPDATE , show , scheduled_update )
2014-03-10 05:18:05 +00:00
self . force = True
2015-03-17 19:11:44 +00:00
self . force_web = False
2015-03-17 00:53:12 +00:00
class QueueItemForceUpdateWeb ( QueueItemUpdate ) :
2015-05-04 19:14:29 +00:00
def __init__ ( self , show = None , scheduled_update = False ) :
ShowQueueItem . __init__ ( self , ShowQueueActions . FORCEUPDATE , show , scheduled_update )
2015-03-17 00:53:12 +00:00
self . force = True
self . force_web = True