From 1e4562a39d7f5aa7360ec4dec11a6296b43f75a5 Mon Sep 17 00:00:00 2001 From: JackDandy Date: Thu, 24 Aug 2017 12:36:23 +0100 Subject: [PATCH] Add SceneHD torrent provider. --- CHANGES.md | 1 + gui/slick/images/providers/scenehd.png | Bin 0 -> 287 bytes .../interfaces/default/config_providers.tmpl | 5 +- sickbeard/providers/__init__.py | 3 +- sickbeard/providers/scenehd.py | 120 ++++++++++++++++++ 5 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 gui/slick/images/providers/scenehd.png create mode 100644 sickbeard/providers/scenehd.py diff --git a/CHANGES.md b/CHANGES.md index 10bdfe15..930192f8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -51,6 +51,7 @@ * Change add IPv4 config option when enabling IPv6. * Add autoProcessTV/onTxComplete.bat to improve Windows clients Deluge, qBittorrent, Tranmission, and uTorrent * Add MagnetDL torrent provider +* Add SceneHD torrent provider * Add Skytorrents torrent provider * Change do not have shows checked by default on import page. To re-enable import shows checked by default, 1) On config page 'Save' 2) Stop SG 3) Find 'import_default_checked_shows' in config.ini and set '1' 4) Start SG diff --git a/gui/slick/images/providers/scenehd.png b/gui/slick/images/providers/scenehd.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f4da4881e0ba2d0d906336a86ec52a9a36d161 GIT binary patch literal 287 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP2=EDUW!-Lj?#a5vXVdFeiS->8 z`ugkr*6S@ZkB7G}b$a~aLhm7`fB*hXI^wdF^!HDnzI482(!mSG`@F3G zoS7-iW6NIu_udw^BNo;6RrWIqHA=pp3pI5(_HoOLfQ8l$$7Y6ZW@b%w=n1|VU7DrP zb9eK(2FXji4M*~!z6GDx01F5ar&wQ^&^g9eMmj0|_$eX6H1 S@1G2G1cRrmpUXO@geCwqbbtf^ literal 0 HcmV?d00001 diff --git a/gui/slick/interfaces/default/config_providers.tmpl b/gui/slick/interfaces/default/config_providers.tmpl index aec036c3..de618229 100644 --- a/gui/slick/interfaces/default/config_providers.tmpl +++ b/gui/slick/interfaces/default/config_providers.tmpl @@ -558,7 +558,8 @@ name = '' if not client else get_client_instance(sickbeard.TORRENT_METHOD)().nam Confirmed download /> -

only download torrents from trusted or verified uploaders ?

+ #set $confirm_label = callable(getattr(cur_torrent_provider, 'ui_string', None)) and cur_torrent_provider.ui_string(cur_torrent_provider.get_id() + '_confirm') or 'only download torrents from trusted or verified uploaders ?' +

$confirm_label

@@ -622,7 +623,7 @@ name = '' if not client else get_client_instance(sickbeard.TORRENT_METHOD)().nam Episode search fallback /> -

use the alternate episode search mode if no match is found -- warning; may result in duplicates or a heavy ratio hit -- best use: manually collect a season, disable after.

+

use alternate episode search mode if no match is found -- warning; may result in duplicates or a heavy ratio hit -- best use: manually collect a season, disable after

diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index 18b1db3c..628a32e2 100755 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -29,7 +29,7 @@ from . import newznab, omgwtfnzbs from . import alpharatio, beyondhd, bithdtv, bitmetv, btn, btscene, dh, \ fano, filelist, funfile, gftracker, grabtheinfo, hd4free, hdbits, hdspace, hdtorrents, \ iptorrents, limetorrents, magnetdl, morethan, nebulance, ncore, nyaa, pisexy, pretome, privatehd, ptf, \ - rarbg, revtt, scenetime, shazbat, skytorrents, speedcd, \ + rarbg, revtt, scenehd, scenetime, shazbat, skytorrents, speedcd, \ thepiratebay, torlock, torrentday, torrenting, torrentleech, \ torrentz2, tvchaosuk, zooqle # anime @@ -72,6 +72,7 @@ __all__ = ['omgwtfnzbs', 'ptf', 'rarbg', 'revtt', + 'scenehd', 'scenetime', 'shazbat', 'skytorrents', diff --git a/sickbeard/providers/scenehd.py b/sickbeard/providers/scenehd.py new file mode 100644 index 00000000..e599c015 --- /dev/null +++ b/sickbeard/providers/scenehd.py @@ -0,0 +1,120 @@ +# coding=utf-8 +# +# 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 . + +import re +import traceback + +from . import generic +from sickbeard import logger +from sickbeard.bs4_parser import BS4Parser +from sickbeard.helpers import tryInt +from lib.unidecode import unidecode + + +class SceneHDProvider(generic.TorrentProvider): + + def __init__(self): + generic.TorrentProvider.__init__(self, 'SceneHD', cache_update_freq=20) + + self.url_home = ['https://scenehd.org/'] + + self.url_vars = {'login_action': 'login.php', 'search': 'browse.php?search=%s&cat=%s&sort=5', 'get': '%s'} + self.url_tmpl = {'config_provider_home_uri': '%(home)s', 'login_action': '%(home)s%(vars)s', + 'search': '%(home)s%(vars)s', 'get': '%(home)s%(vars)s'} + + self.categories = {'shows': [5, 6, 7]} + + self.username, self.password, self.freeleech, self.minseed, self.minleech = 5 * [None] + self.confirmed = False + + def _authorised(self, **kwargs): + + return super(SceneHDProvider, self)._authorised(post_params={'form_tmpl': True}) + + def _search_provider(self, search_params, **kwargs): + + results = [] + if not self._authorised(): + return results + + items = {'Cache': [], 'Season': [], 'Episode': [], 'Propers': []} + + rc = dict((k, re.compile('(?i)' + v)) for (k, v) in {'info': 'detail', 'get': 'download', + 'nuked': 'nuke', 'filter': 'free'}.items()) + for mode in search_params.keys(): + for search_string in search_params[mode]: + search_string = isinstance(search_string, unicode) and unidecode(search_string) or search_string + search_url = self.urls['search'] % (search_string, self._categories_string(mode, '%s', ',')) + + html = self.get_url(search_url, timeout=90) + + cnt = len(items[mode]) + try: + if not html or self._has_no_results(html): + raise generic.HaltParseException + + with BS4Parser(html, features=['html5lib', 'permissive'], attr='cellpadding="5"') as soup: + torrent_table = soup.find('table', class_='browse') + torrent_rows = [] if not torrent_table else torrent_table.find_all('tr') + + if 2 > len(torrent_rows): + raise generic.HaltParseException + + head = None + for tr in torrent_rows[1:]: + cells = tr.find_all('td') + if 5 > len(cells): + continue + try: + info = tr.find('a', href=rc['info']) + head = head if None is not head else self._header_row(tr) + seeders, leechers, size = [n for n in [ + cells[head[x]].get_text().strip() for x in 'leech', 'leech', 'size']] + seeders, leechers, size = [tryInt(n, n) for n in + list(re.findall('^(\d+)[^\d]+?(\d+)', leechers)[0]) + + re.findall('^[^\n\t]+', size)] + if (self.confirmed and + any([tr.find('img', alt=rc['nuked']), tr.find('img', class_=rc['nuked'])])) \ + or (self.freeleech and not tr.find('a', class_=rc['filter'])) \ + or self._peers_fail(mode, seeders, leechers): + continue + + title = (info.attrs.get('title') or info.get_text()).strip() + download_url = self._link(tr.find('a', href=rc['get'])['href']) + except (AttributeError, TypeError, ValueError, KeyError): + continue + + if title and download_url: + items[mode].append((title, download_url, seeders, self._bytesizer(size))) + + except generic.HaltParseException: + pass + except (StandardError, Exception): + logger.log(u'Failed to parse. Traceback: %s' % traceback.format_exc(), logger.ERROR) + + self._log_search(mode, len(items[mode]) - cnt, search_url) + + results = self._sort_seeding(mode, results + items[mode]) + + return results + + @staticmethod + def ui_string(key): + return 'scenehd_confirm' == key and 'skip releases marked as bad/nuked' or '' + + +provider = SceneHDProvider()