From 85d78e9bdfaeb6dd7bae046fbb2dac30d17edae7 Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Sat, 1 May 2010 16:46:43 +0200 Subject: [PATCH] new 'gazelle' backend (bittorrent trackers), implementing ICapTorrent --- weboob/backends/gazelle/__init__.py | 1 + weboob/backends/gazelle/backend.py | 57 ++++++++++++++ weboob/backends/gazelle/browser.py | 69 +++++++++++++++++ weboob/backends/gazelle/pages/__init__.py | 0 weboob/backends/gazelle/pages/index.py | 36 +++++++++ weboob/backends/gazelle/pages/torrents.py | 94 +++++++++++++++++++++++ weboob/capabilities/torrent.py | 2 +- 7 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 weboob/backends/gazelle/__init__.py create mode 100644 weboob/backends/gazelle/backend.py create mode 100644 weboob/backends/gazelle/browser.py create mode 100644 weboob/backends/gazelle/pages/__init__.py create mode 100644 weboob/backends/gazelle/pages/index.py create mode 100644 weboob/backends/gazelle/pages/torrents.py diff --git a/weboob/backends/gazelle/__init__.py b/weboob/backends/gazelle/__init__.py new file mode 100644 index 00000000..4bb00a62 --- /dev/null +++ b/weboob/backends/gazelle/__init__.py @@ -0,0 +1 @@ +from .backend import GazelleBackend diff --git a/weboob/backends/gazelle/backend.py b/weboob/backends/gazelle/backend.py new file mode 100644 index 00000000..1a62af69 --- /dev/null +++ b/weboob/backends/gazelle/backend.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +""" +Copyright(C) 2010 Romain Bignon + +This program 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, version 3 of the License. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +""" + +from weboob.backend import BaseBackend +from weboob.capabilities.torrent import ICapTorrent + +from .browser import GazelleBrowser + + +__all__ = ['GazelleBackend'] + + +class GazelleBackend(BaseBackend, ICapTorrent): + NAME = 'gazelle' + MAINTAINER = 'Romain Bignon' + EMAIL = 'romain@peerfuse.org' + VERSION = '0.1' + DESCRIPTION = 'gazelle bittorrent tracker' + LICENSE = 'GPLv3' + + CONFIG = {'username': BaseBackend.ConfigField(description='Username on website'), + 'password': BaseBackend.ConfigField(description='Password of account', is_masked=True), + 'protocol': BaseBackend.ConfigField(description='Protocol to use', default='https'), + 'domain': BaseBackend.ConfigField(description='Domain', default='ssl.what.cd'), + } + _browser = None + + def __getattr__(self, name): + if name == 'browser': + if not self._browser: + self._browser = GazelleBrowser(self.config['protocol'], self.config['domain'], + self.config['username'], self.config['password']) + return self._browser + raise AttributeError, name + + def get_torrent(self, id): + return self.browser.get_torrent(id) + + def iter_torrents(self, pattern): + return self.browser.iter_torrents(pattern) diff --git a/weboob/backends/gazelle/browser.py b/weboob/backends/gazelle/browser.py new file mode 100644 index 00000000..9d5884de --- /dev/null +++ b/weboob/backends/gazelle/browser.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +""" +Copyright(C) 2010 Romain Bignon + +This program 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, version 3 of the License. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +""" + +from weboob.tools.browser import BaseBrowser + +from .pages.index import IndexPage, LoginPage +from .pages.torrents import TorrentsPage + + +__all__ = ['GazelleBrowser'] + + +class GazelleBrowser(BaseBrowser): + DOMAIN = 'ssl.what.cd' + PROTOCOL = 'https' + PAGES = {'https?://%s/?(index.php)?': IndexPage, + 'https?://%s/login.php': LoginPage, + 'https?://%s/torrents.php.*': TorrentsPage, + } + + def __init__(self, protocol, domain, *args, **kwargs): + self.DOMAIN = domain + self.PROTOCOL = protocol + self.PAGES = {} + for key, value in GazelleBrowser.PAGES.iteritems(): + self.PAGES[key % domain] = value + + BaseBrowser.__init__(self, *args, **kwargs) + + def login(self): + if not self.is_on_page(LoginPage): + self.home() + self.page.login(self.username, self.password) + + def is_logged(self): + if not self.page or self.is_on_page(LoginPage): + return False + if self.is_on_page(IndexPage): + return self.page.is_logged() + return True + + def home(self): + return self.location('%s://%s/login.php' % (self.PROTOCOL, self.DOMAIN)) + + def iter_torrents(self, pattern): + self.location('/torrents.php?searchstr=%s' % pattern) + + assert self.is_on_page(TorrentsPage) + return self.page.iter_torrents() + + def get_torrent(self, id): + pass diff --git a/weboob/backends/gazelle/pages/__init__.py b/weboob/backends/gazelle/pages/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/weboob/backends/gazelle/pages/index.py b/weboob/backends/gazelle/pages/index.py new file mode 100644 index 00000000..b20da83e --- /dev/null +++ b/weboob/backends/gazelle/pages/index.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +""" +Copyright(C) 2010 Romain Bignon + +This program 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, version 3 of the License. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +""" + +from weboob.tools.browser import BasePage + + +__all__ = ['IndexPage', 'LoginPage'] + + +class IndexPage(BasePage): + def is_logged(self): + return 'id' in self.document.find('body').attrib + +class LoginPage(BasePage): + def login(self, login, password): + self.browser.select_form(nr=0) + self.browser['username'] = login + self.browser['password'] = password + self.browser.submit() diff --git a/weboob/backends/gazelle/pages/torrents.py b/weboob/backends/gazelle/pages/torrents.py new file mode 100644 index 00000000..be7e050f --- /dev/null +++ b/weboob/backends/gazelle/pages/torrents.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +""" +Copyright(C) 2010 Romain Bignon + +This program 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, version 3 of the License. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +""" + +import re + +from weboob.tools.browser import BasePage +from weboob.capabilities.torrent import Torrent + + +__all__ = ['TorrentsPage'] + + +class TorrentsPage(BasePage): + TORRENTID_REGEXP = re.compile('torrents\.php\?action=download&id=(\d+)') + def unit(self, n, u): + m = {'KB': 1024, + 'MB': 1024*1024, + 'GB': 1024*1024*1024, + 'TB': 1024*1024*1024*1024, + } + return float(n.replace(',', '')) * m.get(u, 1) + + def iter_torrents(self): + table = self.document.getroot().cssselect('table#torrent_table') + if not table: + table = self.document.getroot().cssselect('table#browse_torrent_table') + if table: + table = table[0] + current_group = None + for tr in table.findall('tr'): + if tr.attrib.get('class', '') == 'group': + tds = tr.findall('td') + current_group = u'' + div = tds[-6] + if div.getchildren()[0].tag == 'div': + div = div.getchildren()[0] + for a in div.findall('a'): + if not a.text: + continue + if current_group: + current_group += ' - ' + current_group += a.text + elif tr.attrib.get('class', '').startswith('group_torrent ') or \ + tr.attrib.get('class', '').startswith('torrent'): + tds = tr.findall('td') + + title = current_group + if len(tds) == 7: + # Under a group + i = 0 + elif len(tds) in (8,9): + # An alone torrent + i = len(tds) - 7 + else: + # Useless title + continue + + if title: + title += u' (%s)' % tds[i].find('a').text + else: + title = tds[i].find('a').text + url = tds[i].find('span').find('a').attrib['href'] + id = self.TORRENTID_REGEXP.match(url) + if not id: + continue + id = id.group(1) + size = self.unit(*tds[i+3].text.split()) + seeders = int(tds[i+5].text) + leechers = int(tds[i+6].text) + + torrent = Torrent(id, + title, + url=url, + size=size, + seeders=seeders, + leechers=leechers) + yield torrent diff --git a/weboob/capabilities/torrent.py b/weboob/capabilities/torrent.py index c0f40774..014df559 100644 --- a/weboob/capabilities/torrent.py +++ b/weboob/capabilities/torrent.py @@ -24,7 +24,7 @@ from .cap import ICap __all__ = ['ICapTorrent'] class Torrent(object): - def __init__(self, id, name, date=None, size=0.0, url=u'', seeders=0, leechers=0, files=[]) + def __init__(self, id, name, date=None, size=0.0, url=u'', seeders=0, leechers=0, files=[]): self.id = id self.name = name self.date = date