From ef658fe7257cb61bc790d4cd35fba828bb59ce0b Mon Sep 17 00:00:00 2001 From: mystycs Date: Fri, 3 May 2019 05:03:47 -0400 Subject: [PATCH] Add gimmepeers torrent provider (#6635) * Create gimmepeers.py * Update __init__.py * Update __init__.py * Add files via upload * Add files via upload * Update gimmepeers.py * run isort * Update gimmepeers.py * Update gimmepeers.py * make pep8 compliant for flake8 check * Update gimmepeers.py * pep8 fixes * Update gimmepeers.py * pep8 fixes * pep8 fix import order * revert isort * revert isort * Add files via upload * pr fixes * pr fix minseed * fix logger * remove logger since unused * Update gimmepeers.py * remove whitespace * replace format with urljoin * pr fixes + add pubdate * pep8 whitespace fix * pep8 whitespace fix * fix size * whitespace fix * remove trailing whitespace * Small changes * Optimize icon * Update gimmepeers.py * Update CHANGELOG.md --- CHANGELOG.md | 1 + medusa/providers/__init__.py | 3 +- medusa/providers/torrent/__init__.py | 3 +- medusa/providers/torrent/html/gimmepeers.py | 174 ++++++++++++++++++ .../static/images/providers/gimmepeers.png | Bin 0 -> 1335 bytes .../dark/assets/img/providers/gimmepeers.png | Bin 0 -> 323 bytes .../light/assets/img/providers/gimmepeers.png | Bin 0 -> 323 bytes 7 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 medusa/providers/torrent/html/gimmepeers.py create mode 100644 themes-default/slim/static/images/providers/gimmepeers.png create mode 100644 themes/dark/assets/img/providers/gimmepeers.png create mode 100644 themes/light/assets/img/providers/gimmepeers.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fd2dd67638..8d6e75759e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### New Features - Added nCore torrent provider ([#6537](https://github.com/pymedusa/Medusa/pull/6537)) +- Added Gimmepeers torrent provider (credits to @mystycs) ([#6635](https://github.com/pymedusa/Medusa/pull/6635)) #### Improvements diff --git a/medusa/providers/__init__.py b/medusa/providers/__init__.py index 31f15ea09ec..033a5ba6041 100644 --- a/medusa/providers/__init__.py +++ b/medusa/providers/__init__.py @@ -28,6 +28,7 @@ cinemaz, danishbits, elitetracker, + gimmepeers, hdbits, hdspace, hdtorrents, @@ -69,7 +70,7 @@ 'abnormal', 'scenetime', 'nebulance', 'tvchaosuk', 'bitcannon', 'torrentz2', 'pretome', 'anizb', 'hdspace', 'nordicbits', 'danishbits', 'limetorrents', 'norbits', 'bithdtv', 'ncore', 'zooqle', 'animebytes', 'animetorrents', 'anidex', 'shanaproject', 'torrenting', - 'yggtorrent', 'elitetracker', 'archetorrent', 'privatehd', 'cinemaz', 'avistaz', 'bjshare' + 'yggtorrent', 'elitetracker', 'archetorrent', 'privatehd', 'cinemaz', 'avistaz', 'bjshare', 'gimmepeers' ] diff --git a/medusa/providers/torrent/__init__.py b/medusa/providers/torrent/__init__.py index 0a61823b322..42697ef398a 100644 --- a/medusa/providers/torrent/__init__.py +++ b/medusa/providers/torrent/__init__.py @@ -14,6 +14,7 @@ bjshare, cinemaz, elitetracker, + gimmepeers, hdspace, hdtorrents, hebits, @@ -69,5 +70,5 @@ 'torrentbytes', 'torrentleech', 'nebulance', 'tvchaosuk', 'xthor', 'zooqle', 'bitcannon', 'btn', 'hdbits', 'norbits', 'rarbg', 'torrentday', 'nyaa', 'rsstorrent', 'shazbat', 'hebits', 'torrentz2', 'animetorrents', 'anidex', 'shanaproject', 'torrenting', 'yggtorrent', - 'elitetracker', 'privatehd', 'cinemaz', 'avistaz', 'bjshare', 'ncore' + 'elitetracker', 'privatehd', 'cinemaz', 'avistaz', 'bjshare', 'ncore', 'gimmepeers' ] diff --git a/medusa/providers/torrent/html/gimmepeers.py b/medusa/providers/torrent/html/gimmepeers.py new file mode 100644 index 00000000000..57642d63ede --- /dev/null +++ b/medusa/providers/torrent/html/gimmepeers.py @@ -0,0 +1,174 @@ +# coding=utf-8 + +"""Provider code for GimmePeers.""" + +from __future__ import unicode_literals + +import logging +import re + +from medusa import tv +from medusa.bs4_parser import BS4Parser +from medusa.helper.common import convert_size +from medusa.logger.adapters.style import BraceAdapter +from medusa.providers.torrent.torrent_provider import TorrentProvider + +from requests.compat import urljoin +from requests.utils import dict_from_cookiejar + +log = BraceAdapter(logging.getLogger(__name__)) +log.logger.addHandler(logging.NullHandler()) + + +class GimmePeersProvider(TorrentProvider): + """GimmePeers Torrent provider.""" + + def __init__(self): + """Initialize the class.""" + super(GimmePeersProvider, self).__init__('GimmePeers') + + self.username = None + self.password = None + + self.url = 'https://www.gimmepeers.com' + self.urls = { + 'login': urljoin(self.url, 'takelogin.php'), + 'search': urljoin(self.url, 'browse.php'), + } + + # Proper Strings + self.proper_strings = ['PROPER', 'REPACK', 'REAL', 'RERIP'] + + self.cache = tv.Cache(self) + + def search(self, search_strings, age=0, ep_obj=None, **kwargs): + """ + Search a provider and parse the results. + + :param search_strings: A dict with mode (key) and the search value (value) + :param age: Not used + :param ep_obj: Not used + :returns: A list of search results (structure) + """ + results = [] + if not self.login(): + return results + + search_params = { + 'c20': 1, + 'c21': 1, + 'c25': 1, + 'c24': 1, + 'c23': 1, + 'c22': 1, + 'c1': 1, + } + + for mode in search_strings: + log.debug('Search Mode: {0}', mode) + + for search_string in search_strings[mode]: + + if mode != 'RSS': + log.debug('Search string: {search}', + {'search': search_string}) + + search_params['search'] = search_string + + response = self.session.get(self.urls['search'], params=search_params) + if not response or not response.text: + log.debug('No data returned from provider') + continue + + results += self.parse(response.text, mode) + + return results + + def parse(self, data, mode): + """ + Parse search results for items. + + :param data: The raw response from a search + :param mode: The current mode used to search, e.g. RSS + :return: A list of items found + """ + items = [] + + with BS4Parser(data, 'html5lib') as html: + torrent_table = html.find('table', class_='browsetable') + torrent_rows = torrent_table('tr') if torrent_table else [] + + # Continue only if one release is found + if len(torrent_rows) < 2: + log.debug('Data returned from provider does not contain any torrents') + return items + + for result in torrent_rows[1:]: + cells = result('td') + + try: + link = cells[1].find('a') + download_url = urljoin(self.url, cells[2].find('a')['href']) + title = link.get_text() + if not all([title, download_url]): + continue + + seeders = int(cells[10].get_text().replace(',', '')) + leechers = int(cells[11].get_text().replace(',', '')) + + # Filter unseeded torrent + if seeders < self.minseed: + if mode != 'RSS': + log.debug("Discarding torrent because it doesn't meet the" + ' minimum seeders: {0}. Seeders: {1}', + title, seeders) + continue + + torrent_size = cells[5].get_text(' ') + size = convert_size(torrent_size) or -1 + + pubdate_raw = cells[6].get_text() + pubdate = self.parse_pubdate(pubdate_raw) + + item = { + 'title': title, + 'link': download_url, + 'size': size, + 'seeders': seeders, + 'leechers': leechers, + 'pubdate': pubdate, + } + if mode != 'RSS': + log.debug('Found result: {0} with {1} seeders and {2} leechers', + title, seeders, leechers) + + items.append(item) + except (AttributeError, TypeError, KeyError, ValueError, IndexError): + log.exception('Failed parsing provider.') + + return items + + def login(self): + """Login method used for logging in before doing search and torrent downloads.""" + if any(dict_from_cookiejar(self.session.cookies).values()): + return True + + login_params = { + 'username': self.username, + 'password': self.password, + 'ssl': 'yes', + } + + response = self.session.post(self.urls['login'], data=login_params) + if not response or not response.text: + log.debug('Unable to connect to provider') + return False + + if re.search('Username or password incorrect!', response.text): + log.debug('Invalid username or password. Check your settings') + return False + + return True + + +provider = GimmePeersProvider() diff --git a/themes-default/slim/static/images/providers/gimmepeers.png b/themes-default/slim/static/images/providers/gimmepeers.png new file mode 100644 index 0000000000000000000000000000000000000000..2d154f5343baedc5624178bcc03bd1a907956f80 GIT binary patch literal 1335 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+nAI{vB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuk*h0bFQqR!T z(!$6@N5ROz&`jUJQs2--*TB%qz|zXVPyq^*fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7I$DAddqG{Q6U zQu51-HNkp(eXTt6ic1pnl2bihY?Xkf=w)W6SXo$Fni!iHS(v$)I~y9hS~?oJxLGQV@TPa-o7k4%ONLW z%XIOt~l$p>yB&w{`#B#^j9*Ebl>0m7t$85Hu?O6cfw?wp3p{> zfUR8$+cz)Mneg}9>F=h~p(@Br>mdKI;Vst04Q(c A2LJ#7 literal 0 HcmV?d00001 diff --git a/themes/dark/assets/img/providers/gimmepeers.png b/themes/dark/assets/img/providers/gimmepeers.png new file mode 100644 index 0000000000000000000000000000000000000000..8b250049e656887028f28690915d7f4536f30e71 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}LV!<*D}zrtgD((OF!+@-_yNgE z2EQr>{|W~GN(TQbmDpyLxMusDUi;i$`@G(es%atB)6?4*q<1W=n7p!L3J|SopTDVn z{^rG74{z9i`sC%?SMNN2@buN|cOSog|MCC-|JJe@HbA@PdAc};NJz3CjLbV^Ai{8< za+{}@mevvez5jm(gl?Ro`|Y*QmO!_ui(ai2&sE^OvbBwA0kbHphF6Noo8>32zptD2 z-dn8j&lz{Us5R4EyHj_~U-87>*028Tqb+lv%=~k~R5f?nitw+y*NN-S|6H{9-9Cx! z{}xsB{k_IkS@~_<&iUo+VG}MYYkdAw*Yoz-G$)qSj;0BV6g(P&mdFLNtNdehwsWpL TC){|W~GN(TQbmDpyLxMusDUi;i$`@G(es%atB)6?4*q<1W=n7p!L3J|SopTDVn z{^rG74{z9i`sC%?SMNN2@buN|cOSog|MCC-|JJe@HbA@PdAc};NJz3CjLbV^Ai{8< za+{}@mevvez5jm(gl?Ro`|Y*QmO!_ui(ai2&sE^OvbBwA0kbHphF6Noo8>32zptD2 z-dn8j&lz{Us5R4EyHj_~U-87>*028Tqb+lv%=~k~R5f?nitw+y*NN-S|6H{9-9Cx! z{}xsB{k_IkS@~_<&iUo+VG}MYYkdAw*Yoz-G$)qSj;0BV6g(P&mdFLNtNdehwsWpL TC)