diff --git a/gui/slick/views/snatchSelection.mako b/gui/slick/views/snatchSelection.mako
index 21341ca2fd..39f65a4b85 100644
--- a/gui/slick/views/snatchSelection.mako
+++ b/gui/slick/views/snatchSelection.mako
@@ -214,7 +214,7 @@
${pretty_file_size(hItem["size"]) if hItem["size"] > -1 else 'N/A'} |
${hItem["provider_type"]} |
${datetime.datetime.fromtimestamp(hItem["time"]).strftime(sickbeard.DATE_PRESET+" "+sickbeard.TIME_PRESET)} |
- ![Download selected episode search](${srRoot}/images/download.png) |
+ ![Download selected episode search](${srRoot}/images/download.png) |
% endfor
diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py
index d48336042e..09e957a2fe 100644
--- a/sickbeard/search_queue.py
+++ b/sickbeard/search_queue.py
@@ -56,7 +56,7 @@ def is_in_queue(self, show, segment):
def is_ep_in_queue(self, segment):
for cur_item in self.queue:
- if isinstance(cur_item, (ManualSearchQueueItem, FailedQueueItem)) and cur_item.segment == segment:
+ if isinstance(cur_item, (ManualSearchQueueItem, FailedQueueItem, ManualSnatchQueueItem)) and cur_item.segment == segment:
return True
return False
@@ -126,7 +126,7 @@ def add_item(self, item):
elif isinstance(item, (ManualSearchQueueItem, FailedQueueItem)) and not self.is_ep_in_queue(item.segment):
# manual and failed searches
generic_queue.GenericQueue.add_item(self, item)
- elif isinstance(item, ManualSnatchQueueItem):
+ elif isinstance(item, ManualSnatchQueueItem) and not self.is_ep_in_queue(item.segment):
# manual and failed searches
generic_queue.GenericQueue.add_item(self, item)
else:
@@ -203,7 +203,7 @@ def run(self):
# just use the first result for now
if searchResult[0].seeders not in (-1, None) and searchResult[0].leechers not in (-1, None):
logger.log(u"Downloading {0} with {1} seeders and {2} leechers from {3}".
- format(searchResult[0].name,
+ format(searchResult[0].name,
searchResult[0].seeders, searchResult[0].leechers, searchResult[0].provider.name))
else:
logger.log(u"Downloading {0} from {1}".format(searchResult[0].name, searchResult[0].provider.name))
@@ -234,32 +234,57 @@ def run(self):
class ManualSnatchQueueItem(generic_queue.QueueItem):
- def __init__(self, searchResult):
+ """
+ A queue item that can be used to queue the snatch of a search result.
+ Currently used for the snatchSelection feature.
+
+ @param show: A show object
+ @param segment: A list of episode objects
+ @param provider: The provider id. For example nyaatorrent and not NyaaTorrent. Or usernet_crawler and not Usenet-Crawler
+ @param cached_result: An sql result of the searched result retrieved from the provider cache table.
+
+ @return: The run() methods snatches the episode(s) if possible.
+ """
+ def __init__(self, show, segment, provider, cached_result):
generic_queue.QueueItem.__init__(self, u'Manual Snatch', MANUAL_SNATCH)
self.priority = generic_queue.QueuePriorities.HIGH
self.success = None
self.started = None
self.results = None
- self.searchResult = searchResult
+ self.provider = provider
+ self.segment = segment
+ self.show = show
+ self.cached_result = cached_result
def run(self):
generic_queue.QueueItem.run(self)
self.started = True
+ search_result = sickbeard.providers.getProviderClass(self.provider).get_result(self.segment)
+ search_result.show = self.show
+ search_result.url = self.cached_result['url']
+ search_result.quality = int(self.cached_result['quality'])
+ search_result.name = self.cached_result['name']
+ search_result.size = int(self.cached_result['size'])
+ search_result.seeders = int(self.cached_result['seeders'])
+ search_result.leechers = int(self.cached_result['leechers'])
+ search_result.release_group = self.cached_result['release_group']
+ search_result.version = int(self.cached_result['version'])
+
try:
- logger.log(u"Beginning to manual snatch release: {}".format(self.searchResult.name))
+ logger.log(u"Beginning to manual snatch release: {0}".format(search_result.name))
- if self.searchResult:
- if self.searchResult.seeders not in (-1, None) and self.searchResult.leechers not in (-1, None):
+ if search_result:
+ if search_result.seeders not in (-1, None) and search_result.leechers not in (-1, None):
logger.log(u"Downloading {0} with {1} seeders and {2} leechers from {3}".
- format(self.searchResult.name,
- self.searchResult.seeders, self.searchResult.seeders, self.searchResult.provider.name))
+ format(search_result.name,
+ search_result.seeders, search_result.leechers, search_result.provider.name))
else:
- logger.log(u"Downloading {0} from {1}".format(self.searchResult.name, self.searchResult.provider.name))
- self.success = search.snatchEpisode(self.searchResult)
+ logger.log(u"Downloading {0} from {1}".format(search_result.name, search_result.provider.name))
+ self.success = search.snatchEpisode(search_result)
else:
- logger.log(u"Unable to snatch release: {}".format(self.searchResult.name))
+ logger.log(u"Unable to snatch release: {0}".format(search_result.name))
# give the CPU a break
time.sleep(common.cpu_presets[sickbeard.CPU_PRESET])
@@ -267,7 +292,8 @@ def run(self):
except Exception:
self.success = False
logger.log(traceback.format_exc(), logger.DEBUG)
- ui.notifications.message('Error while snatching selected result', "Couldn't snatch the result for %s".format(self.searchResult.name))
+ ui.notifications.message('Error while snatching selected result',
+ "Couldn't snatch the result for {0}".format(search_result.name))
if self.success is None:
self.success = False
@@ -300,8 +326,9 @@ def run(self):
for result in searchResult:
# just use the first result for now
if result.seeders not in (-1, None) and result.leechers not in (-1, None):
- logger.log(u"Downloading {0} with {1} seeders and {2} leechers from {3}".format(result.name,
- result.seeders, result.leechers, result.provider.name))
+ logger.log(u"Downloading {0} with {1} seeders and {2} leechers from {3}".
+ format(result.name,
+ result.seeders, result.leechers, result.provider.name))
else:
logger.log(u"Downloading {0} from {1}".format(result.name, result.provider.name))
self.success = search.snatchEpisode(result)
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index f682d036f4..5ad44d207e 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -1401,55 +1401,61 @@ def titler(x):
action="displayShow"
)
- def pickManualSnatch(self, show=None, season=None, episode=None, provider=None, rowid=None):
+ def pickManualSnatch(self, provider=None, rowid=None):
+ """
+ Tries to Perform the snatch for a manualSelected episode, episodes or season pack.
+
+ @param provider: The provider id, passed as usenet_crawler and not the provider name (Usenet-Crawler)
+ @param rowid: The provider's cache table's rowid. (currently the implicit sqlites rowid is used, needs to be replaced in future)
+
+ @return: A json with a {'success': true} or false.
+ """
# Try to retrieve the cached result from the providers cache table.
# TODO: the implicit sqlite rowid is used, should be replaced with an explicit PK column
try:
main_db_con = db.DBConnection('cache.db')
- sql_return = main_db_con.action("SELECT * FROM '%s' WHERE rowid = ?" %
- (sickbeard.providers.getProviderClass(provider).get_id()), [rowid], fetchone=True)
+ cached_result = main_db_con.action("SELECT * FROM '%s' WHERE rowid = ?" %
+ provider, [rowid], fetchone=True)
except Exception as e:
return self._genericMessage("Error", "Couldn't read cached results. Error: {}".format(e))
- if not (sql_return['url'] or sql_return['quality'] or sql_return['name'] or provider or episode):
+ if not all([cached_result['url'],
+ cached_result['quality'],
+ cached_result['name'],
+ cached_result['indexerid'],
+ cached_result['season'],
+ provider]):
return self._genericMessage("Error", "Cached result doesn't have all needed info to snatch episode")
try:
- show = int(show) # fails if show id ends in a period SickRage/sickrage-issues#65
+ show = int(cached_result['indexerid']) # fails if show id ends in a period SickRage/sickrage-issues#65
show_obj = Show.find(sickbeard.showList, show)
except (ValueError, TypeError):
- return self._genericMessage("Error", "Invalid show ID: {}".format(show))
+ return self._genericMessage("Error", "Invalid show ID: {0}".format(show))
+
+ if not show_obj:
+ return self._genericMessage("Error", "Could not find a show with id {0} in the list of shows, did you remove the show?".format(show))
# Create a list of episode object(s)
# if multi-episode: |1|2|
# if single-episode: |1|
# TODO: Handle Season Packs: || (no episode)
- episodes = sql_return['episodes'].strip("|").split("|")
+ episodes = cached_result['episodes'].strip("|").split("|")
ep_objs = []
for episode in episodes:
if episode:
- ep_objs.append(TVEpisode(show_obj, int(season), int(episode)))
-
- # TODO: Can this be moved to the ManualSnatchQueueItem?
- search_result = sickbeard.providers.getProviderClass(provider).get_result(ep_objs)
- search_result.show = show_obj
- search_result.url = sql_return['url']
- search_result.quality = int(sql_return['quality'])
- search_result.name = sql_return['name']
- search_result.size = int(sql_return['size'])
- search_result.seeders = int(sql_return['seeders'])
- search_result.leechers = int(sql_return['leechers'])
- search_result.release_group = sql_return['release_group']
- search_result.version = int(sql_return['version'])
-
- ep_queue_item = search_queue.ManualSnatchQueueItem(search_result)
+ ep_objs.append(TVEpisode(show_obj, int(cached_result['season']), int(episode)))
- sickbeard.searchQueueScheduler.action.add_item(ep_queue_item)
+ # Create the queue item
+ snatch_queue_item = search_queue.ManualSnatchQueueItem(show_obj, ep_objs, provider, cached_result)
+
+ # Add the queue item to the queue
+ sickbeard.searchQueueScheduler.action.add_item(snatch_queue_item)
- while ep_queue_item.success is not False:
- if ep_queue_item.started and ep_queue_item.success:
+ while snatch_queue_item.success is not False:
+ if snatch_queue_item.started and snatch_queue_item.success:
return json.dumps({'result': 'success'})
time.sleep(1)