1
mirror of https://github.com/qbittorrent/qBittorrent synced 2025-10-14 11:52:15 +02:00

Compare commits

...

13 Commits

Author SHA1 Message Date
Christophe Dumez
df60032134 Bump to v2.8.5 2011-09-12 20:12:29 +03:00
Christophe Dumez
bb0b3ead41 Update Changelog 2011-09-11 21:58:56 +03:00
Christophe Dumez
6d5c16e10f Search: Fix GZip decompression code
(cherry picked from commit eb159c0b18)
2011-09-11 21:56:54 +03:00
Christophe Dumez
6ee385bdd8 Search: Fix torrent download with Python 3
(cherry picked from commit 51b3a5164d)
2011-09-11 21:56:54 +03:00
Christophe Dumez
083cab3118 Search: Fix KickAssTorrents search plugin
(cherry picked from commit fa30d7bd1c)
2011-09-11 21:56:54 +03:00
Christophe Dumez
30b7927ee5 Search: Minor PirateBay fix
(cherry picked from commit ea159c0146)
2011-09-11 21:56:54 +03:00
Christophe Dumez
b09f377e25 Search: Initial support for Python 3.x
(cherry picked from commit f4c2fdd2fd)
2011-09-11 20:24:39 +03:00
Christophe Dumez
54fb4cd758 Update Changelog 2011-09-06 19:10:45 +03:00
Christophe Dumez
adaa2c1ddb Multi-tracker: announce to all trackers to avoid stalling issues
with libtorrent.
(cherry picked from commit 3282e53e93)
2011-09-06 19:10:13 +03:00
Christophe Dumez
f0da72c071 Update Changelog 2011-08-13 11:24:14 +03:00
Christophe Dumez
83932a86a4 Fix "Copy torrents to" setting saving in Web UI
(cherry picked from commit 2e07e911e4)
2011-08-13 11:23:15 +03:00
Christophe Dumez
644a4d0062 Fix saving of encryption setting in the Web UI
(cherry picked from commit e838b515b3)
2011-08-13 11:23:15 +03:00
Christophe Dumez
3b0f80e219 Fix possible warnings related to toggleSelectedTorrentsSuperSeeding()
(cherry picked from commit 7854911d2f)
2011-08-10 21:45:21 +03:00
42 changed files with 1948 additions and 45 deletions

View File

@@ -1,3 +1,11 @@
* Mon Sep 12 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.8.5
- BUGFIX: Fix encryption setting saving in Web UI
- BUGFIX: Fix "Copy torrents to" setting saving in Web UI
- BUGFIX: Announce to all trackers in a tier to avoid stalling issues
- BUGFIX: Make search engine work with Python 3.x
- BUGFIX: Fix search engine plugins update tool
- BUGFIX: Fix KickAssTorrents search plugin
* Tue Aug 09 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.8.4
- BUGFIX: Added back ability to reorder trackers
- BUGFIX: Do not announce to all trackers in the same tier to comply

View File

@@ -47,7 +47,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleGetInfoString</key>
<string>2.8.4</string>
<string>2.8.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleExecutable</key>

View File

@@ -36,6 +36,7 @@
#include <QDateTime>
#include <QByteArray>
#include <QDebug>
#include <QProcess>
#ifdef DISABLE_GUI
#include <QCoreApplication>
@@ -548,9 +549,36 @@ QPoint misc::screenCenter(QWidget *win) {
}
#endif
/**
* Detects the version of python by calling
* "python --version" and parsing the output.
*/
int misc::pythonVersion() {
static int version = -1;
if (version < 0) {
QProcess python_proc;
python_proc.start("python", QStringList() << "--version", QIODevice::ReadOnly);
if (!python_proc.waitForFinished()) return -1;
if (python_proc.exitCode() < 0) return -1;
QByteArray output = python_proc.readAllStandardOutput();
if (output.isEmpty())
output = python_proc.readAllStandardError();
const QByteArray version_str = output.split(' ').last();
qDebug() << "Python version is:" << version_str.trimmed();
if (version_str.startsWith("3."))
version = 3;
else
version = 2;
}
return version;
}
QString misc::searchEngineLocation() {
QString folder = "nova";
if (pythonVersion() >= 3)
folder = "nova3";
const QString location = QDir::cleanPath(QDesktopServicesDataLocation()
+ QDir::separator() + "nova");
+ QDir::separator() + folder);
QDir locationDir(location);
if(!locationDir.exists())
locationDir.mkpath(locationDir.absolutePath());

View File

@@ -151,6 +151,7 @@ public:
// Get screen center
static QPoint screenCenter(QWidget *win);
#endif
static int pythonVersion();
static QString searchEngineLocation();
static QString BTBackupLocation();
static QString cacheLocation();

View File

@@ -1056,7 +1056,7 @@ public:
QSettings reg_python("HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore", QIniSettings::NativeFormat);
QStringList versions = reg_python.childGroups();
qDebug("Python versions nb: %d", versions.size());
versions = versions.filter(QRegExp("2\\..*"));
//versions = versions.filter(QRegExp("2\\..*"));
versions.sort();
while(!versions.empty()) {
const QString version = versions.takeLast();
@@ -1067,17 +1067,14 @@ public:
return path;
}
}
if(QFile::exists("C:/Python27/python.exe")) {
reg_python.setValue("2.7/InstallPath/Default", "C:\\Python27");
return "C:\\Python27";
}
if(QFile::exists("C:/Python26/python.exe")) {
reg_python.setValue("2.6/InstallPath/Default", "C:\\Python26");
return "C:\\Python26";
}
if(QFile::exists("C:/Python25/python.exe")) {
reg_python.setValue("2.5/InstallPath/Default", "C:\\Python25");
return "C:\\Python25";
// Fallback: Detect python from default locations
QStringList supported_versions;
supported_versions << "32" << "31" << "30" << "27" << "26" << "25";
foreach(const v, supported_versions) {
if(QFile::exists("C:/Python"+v+"/python.exe")) {
reg_python.setValue(v[0]+"."+v[1]+"/InstallPath/Default", "C:\\Python"+v);
return "C:\\Python"+v;
}
}
return QString::null;
}

View File

@@ -392,8 +392,9 @@ void QBtSession::configureSession() {
//sessionSettings.announce_to_all_trackers = true;
sessionSettings.auto_scrape_interval = 1200; // 20 minutes
#if LIBTORRENT_VERSION_MINOR > 14
// Comply with the multi-tracker specification
sessionSettings.announce_to_all_trackers = false;
// XXX: Does not comply with the multi-tracker specification
// but avoids stalling issues with libtorrent
sessionSettings.announce_to_all_trackers = true;
sessionSettings.announce_to_all_tiers = false;
sessionSettings.auto_scrape_min_interval = 900; // 15 minutes
#endif

View File

@@ -45,7 +45,7 @@
#include <QTemporaryFile>
enum EngineColumns {ENGINE_NAME, ENGINE_URL, ENGINE_STATE, ENGINE_ID};
#define UPDATE_URL "http://qbittorrent.svn.sourceforge.net/viewvc/qbittorrent/trunk/src/searchengine/nova/engines/"
const QString UPDATE_URL = QString("https://gitorious.org/qbittorrent/qbittorrent/blobs/raw/master/src/searchengine/") + (misc::pythonVersion() >= 3 ? "nova3" : "nova") + "/engines/";
engineSelectDlg::engineSelectDlg(QWidget *parent, SupportedEngines *supported_engines) : QDialog(parent), supported_engines(supported_engines) {
setupUi(this);

View File

@@ -1,4 +1,4 @@
#VERSION: 1.2
#VERSION: 1.21
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
@@ -31,9 +31,9 @@ from helpers import retrieve_url, download_file
import json
class kickasstorrents(object):
url = 'http://www.kickasstorrents.com'
url = 'http://www.kat.ph'
name = 'kickasstorrents'
supported_categories = {'all': 'all', 'movies': 'movies', 'tv': 'tv', 'music': 'music', 'games': 'games', 'software': 'applications'}
supported_categories = {'all': '', 'movies': 'Movies', 'tv': 'TV', 'music': 'Music', 'games': 'Games', 'software': 'Applications'}
def __init__(self):
self.results = []
@@ -46,16 +46,17 @@ class kickasstorrents(object):
i = 1
while True and i<11:
results = []
json_data = retrieve_url(self.url+'/search/%s/%d/?categories[]=%s&field=seeders&sorder=desc&json=1'%(what, i, self.supported_categories[cat]))
json_data = retrieve_url(self.url+'/json.php?q=%s&page=%d'%(what, i))
try:
json_dict = json.loads(json_data)
except:
i += 1
continue
if json_dict['total_results'] <= 0: return
if int(json_dict['total_results']) <= 0: return
results = json_dict['list']
for r in results:
try:
if cat != 'all' and self.supported_categories[cat] != r['category']: continue
res_dict = dict()
res_dict['name'] = r['title']
res_dict['size'] = str(r['size'])

View File

@@ -1,4 +1,4 @@
#VERSION: 1.40
#VERSION: 1.41
#AUTHORS: Fabien Devaux (fab@gnux.info)
#CONTRIBUTORS: Christophe Dumez (chris@qbittorrent.org)
@@ -105,8 +105,7 @@ class piratebay(object):
while True and i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url)
dat = retrieve_url(self.url+'/search/%s/%u/7/%s' % (what, i, self.supported_categories[cat]))
print self.url+'/search/%s/%u/7/%s' % (what, i, self.supported_categories[cat])
dat = retrieve_url(self.url+'/search/%s/%d/7/%s' % (what, i, self.supported_categories[cat]))
parser.feed(dat)
parser.close()
if len(results) <= 0:

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#VERSION: 1.1
#AUTHORS: BTDigg team (research@btdigg.org)
#
# GNU GENERAL PUBLIC LICENSE
# Version 3, 29 June 2007
#
# <http://www.gnu.org/licenses/>
#
# 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, either version 3 of the License, or
# (at your option) any later version.
#
# 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.
import urllib.request, urllib.parse, urllib.error
import urllib.request, urllib.error, urllib.parse
import sys
from novaprinter import prettyPrinter
class btdigg(object):
url = 'http://btdigg.org'
name = 'BTDigg'
supported_categories = {'all': ''}
def __init__(self):
pass
def search(self, what, cat='all'):
req = what.replace('+', ' ')
u = urllib.request.urlopen('http://api.btdigg.org/api/public-8e9a50f8335b964f/s01?%s' % (urllib.parse.urlencode(dict(q = req)),))
try:
for line in u:
if line.startswith('#'):
continue
info_hash, name, files, size, dl, seen = line.strip().split('\t')[:6]
res = dict(link = 'magnet:?xt=urn:btih:%s' % (info_hash,),
name = name.translate(None, '|'),
size = size,
seeds = int(dl),
leech = int(dl),
engine_url = self.url,
desc_link = 'http://btdigg.org/search?%s' % (urllib.parse.urlencode(dict(info_hash = info_hash, q = req)),))
prettyPrinter(res)
finally:
u.close()
if __name__ == "__main__":
s = btdigg()
s.search(sys.argv[1])

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

View File

@@ -0,0 +1,122 @@
#VERSION: 2.31
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
from helpers import retrieve_url, download_file
import sgmllib3
import re
class btjunkie(object):
url = 'http://btjunkie.org'
name = 'btjunkie'
supported_categories = {'all': '0', 'movies': '6', 'tv': '4', 'music': '1', 'games': '2', 'anime': '7', 'software': '3'}
def __init__(self):
self.results = []
self.parser = self.SimpleSGMLParser(self.results, self.url)
def download_torrent(self, info):
print(download_file(info))
class SimpleSGMLParser(sgmllib3.SGMLParser):
def __init__(self, results, url, *args):
sgmllib3.SGMLParser.__init__(self)
self.url = url
self.th_counter = None
self.current_item = None
self.results = results
def start_a(self, attr):
params = dict(attr)
#print params
if 'href' in params:
if params['href'].startswith("http://dl.btjunkie.org/torrent"):
self.current_item = {}
self.th_counter = 0
self.current_item['link']=params['href'].strip()
elif self.th_counter == 0 and params['href'].startswith("/torrent/") and params['href'].find('/files/') == -1:
self.current_item['desc_link'] = 'http://btjunkie.org'+params['href'].strip()
def handle_data(self, data):
if self.th_counter == 0:
if 'name' not in self.current_item:
self.current_item['name'] = ''
self.current_item['name']+= data.strip()
elif self.th_counter == 3:
if 'size' not in self.current_item:
self.current_item['size'] = ''
self.current_item['size']+= data.strip()
elif self.th_counter == 5:
if 'seeds' not in self.current_item:
self.current_item['seeds'] = ''
self.current_item['seeds']+= data.strip()
elif self.th_counter == 6:
if 'leech' not in self.current_item:
self.current_item['leech'] = ''
self.current_item['leech']+= data.strip()
def start_th(self,attr):
if isinstance(self.th_counter,int):
self.th_counter += 1
if self.th_counter > 6:
self.th_counter = None
# Display item
if self.current_item:
self.current_item['engine_url'] = self.url
if not self.current_item['seeds'].isdigit():
self.current_item['seeds'] = 0
if not self.current_item['leech'].isdigit():
self.current_item['leech'] = 0
prettyPrinter(self.current_item)
self.results.append('a')
def search(self, what, cat='all'):
# Remove {} since btjunkie does not seem
# to handle those very well
what = what.replace('{', '').replace('}', '')
ret = []
i = 1
while True and i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url)
dat = retrieve_url(self.url+'/search?q=%s&c=%s&o=52&p=%d'%(what, self.supported_categories[cat], i))
# Remove <font> tags from page
p = re.compile( '<[/]?font.*?>')
dat = p.sub('', dat)
#print dat
#return
results_re = re.compile('(?s)class="tab_results">.*')
for match in results_re.finditer(dat):
res_tab = match.group(0)
parser.feed(res_tab)
parser.close()
break
if len(results) <= 0:
break
i += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

View File

@@ -0,0 +1,116 @@
#VERSION: 1.1
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
from helpers import retrieve_url, download_file
import sgmllib3
import re
class extratorrent(object):
url = 'http://extratorrent.com'
name = 'extratorrent'
supported_categories = {'all': '', 'movies': '4', 'tv': '8', 'music': '5', 'games': '3', 'anime': '1', 'software': '7', 'books': '2', 'pictures': '6'}
def __init__(self):
self.results = []
self.parser = self.SimpleSGMLParser(self.results, self.url)
def download_torrent(self, info):
print(download_file(info))
class SimpleSGMLParser(sgmllib3.SGMLParser):
def __init__(self, results, url, *args):
sgmllib3.SGMLParser.__init__(self)
self.url = url
self.td_counter = None
self.current_item = None
self.start_name = False
self.results = results
def start_a(self, attr):
params = dict(attr)
#print params
if 'href' in params and params['href'].startswith("/torrent_download/"):
self.current_item = {}
self.td_counter = 0
self.start_name = False
torrent_id = '/'.join(params['href'].split('/')[2:])
self.current_item['link']=self.url+'/download/'+torrent_id
elif 'href' in params and params['href'].startswith("/torrent/") and params['href'].endswith(".html"):
self.current_item['desc_link'] = self.url + params['href'].strip()
self.start_name = True
def handle_data(self, data):
if self.td_counter == 2:
if 'name' not in self.current_item and self.start_name:
self.current_item['name'] = data.strip()
elif self.td_counter == 3:
if 'size' not in self.current_item:
self.current_item['size'] = ''
self.current_item['size']+= data.replace("&nbsp;", " ").strip()
elif self.td_counter == 4:
if 'seeds' not in self.current_item:
self.current_item['seeds'] = ''
self.current_item['seeds']+= data.strip()
elif self.td_counter == 5:
if 'leech' not in self.current_item:
self.current_item['leech'] = ''
self.current_item['leech']+= data.strip()
def start_td(self,attr):
if isinstance(self.td_counter,int):
self.td_counter += 1
if self.td_counter > 5:
self.td_counter = None
# Display item
if self.current_item:
self.current_item['engine_url'] = self.url
if not self.current_item['seeds'].isdigit():
self.current_item['seeds'] = 0
if not self.current_item['leech'].isdigit():
self.current_item['leech'] = 0
prettyPrinter(self.current_item)
self.results.append('a')
def search(self, what, cat='all'):
ret = []
i = 1
while True and i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url)
dat = retrieve_url(self.url+'/advanced_search/?with=%s&s_cat=%s&page=%d'%(what, self.supported_categories[cat], i))
results_re = re.compile('(?s)<table class="tl"><thead>.*')
for match in results_re.finditer(dat):
res_tab = match.group(0)
parser.feed(res_tab)
parser.close()
break
if len(results) <= 0:
break
i += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

View File

@@ -0,0 +1,69 @@
#VERSION: 1.4
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
import re
from helpers import retrieve_url, download_file
class isohunt(object):
url = 'http://isohunt.com'
name = 'isoHunt'
supported_categories = {'all': '', 'movies': '1', 'tv': '3', 'music': '2', 'games': '4', 'anime': '7', 'software': '5', 'pictures': '6', 'books': '9'}
def download_torrent(self, info):
print(download_file(info))
def search(self, what, cat='all'):
# Remove {} since isohunt does not seem
# to handle those very well
what = what.replace('{', '').replace('}', '')
i = 1
while True and i<11:
res = 0
dat = retrieve_url(self.url+'/torrents.php?ihq=%s&iht=%s&ihp=%s&ihs1=2&iho1=d'%(what, self.supported_categories[cat],i))
# I know it's not very readable, but the SGML parser feels in pain
section_re = re.compile('(?s)id=link.*?</tr><tr')
torrent_re = re.compile('(?s)torrent_details/(?P<link>.*?[^/]+).*?'
'>(?P<name>.*?)</a>.*?'
'>(?P<size>[\d,\.]+\s+MB)</td>.*?'
'>(?P<seeds>\d+)</td>.*?'
'>(?P<leech>\d+)</td>')
for match in section_re.finditer(dat):
txt = match.group(0)
m = torrent_re.search(txt)
if m:
torrent_infos = m.groupdict()
torrent_infos['name'] = re.sub('<.*?>', '', torrent_infos['name'])
torrent_infos['engine_url'] = self.url
torrent_code = torrent_infos['link']
torrent_infos['link'] = 'http://isohunt.com/download/'+torrent_code
torrent_infos['desc_link'] = 'http://isohunt.com/torrent_details/'+torrent_code+'/dvdrip?tab=summary'
prettyPrinter(torrent_infos)
res = res + 1
if res == 0:
break
i = i + 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

View File

@@ -0,0 +1,72 @@
#VERSION: 1.21
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
from helpers import retrieve_url, download_file
import json
class kickasstorrents(object):
url = 'http://www.kat.ph'
name = 'kickasstorrents'
supported_categories = {'all': '', 'movies': 'Movies', 'tv': 'TV', 'music': 'Music', 'games': 'Games', 'software': 'Applications'}
def __init__(self):
self.results = []
def download_torrent(self, info):
print(download_file(info))
def search(self, what, cat='all'):
ret = []
i = 1
while True and i<11:
results = []
json_data = retrieve_url(self.url+'/json.php?q=%s&page=%d'%(what, i))
try:
json_dict = json.loads(json_data)
except:
i += 1
continue
if int(json_dict['total_results']) <= 0: return
results = json_dict['list']
for r in results:
try:
if cat != 'all' and self.supported_categories[cat] != r['category']: continue
res_dict = dict()
res_dict['name'] = r['title']
res_dict['size'] = str(r['size'])
res_dict['seeds'] = r['seeds']
res_dict['leech'] = r['leechs']
res_dict['link'] = r['torrentLink']
res_dict['desc_link'] = r['link']
res_dict['engine_url'] = self.url
prettyPrinter(res_dict)
except:
pass
i += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

View File

@@ -0,0 +1,114 @@
#VERSION: 1.50
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
from helpers import retrieve_url, download_file
import sgmllib3
import re
class mininova(object):
# Mandatory properties
url = 'http://www.mininova.org'
name = 'Mininova'
supported_categories = {'all': '0', 'movies': '4', 'tv': '8', 'music': '5', 'games': '3', 'anime': '1', 'software': '7', 'pictures': '6', 'books': '2'}
def __init__(self):
self.results = []
self.parser = self.SimpleSGMLParser(self.results, self.url)
def download_torrent(self, info):
print(download_file(info))
class SimpleSGMLParser(sgmllib3.SGMLParser):
def __init__(self, results, url, *args):
sgmllib3.SGMLParser.__init__(self)
self.url = url
self.td_counter = None
self.current_item = None
self.results = results
def start_a(self, attr):
params = dict(attr)
#print params
if 'href' in params:
if params['href'].startswith("/get/"):
self.current_item = {}
self.td_counter = 0
self.current_item['link']=self.url+params['href'].strip()
elif params['href'].startswith("/tor/"):
self.current_item['desc_link']=self.url+params['href'].strip()
def handle_data(self, data):
if self.td_counter == 0:
if 'name' not in self.current_item:
self.current_item['name'] = ''
self.current_item['name']+= data
elif self.td_counter == 1:
if 'size' not in self.current_item:
self.current_item['size'] = ''
self.current_item['size']+= data.strip()
elif self.td_counter == 2:
if 'seeds' not in self.current_item:
self.current_item['seeds'] = ''
self.current_item['seeds']+= data.strip()
elif self.td_counter == 3:
if 'leech' not in self.current_item:
self.current_item['leech'] = ''
self.current_item['leech']+= data.strip()
def start_td(self,attr):
if isinstance(self.td_counter,int):
self.td_counter += 1
if self.td_counter > 4:
self.td_counter = None
# Display item
if self.current_item:
self.current_item['engine_url'] = self.url
if not self.current_item['seeds'].isdigit():
self.current_item['seeds'] = 0
if not self.current_item['leech'].isdigit():
self.current_item['leech'] = 0
prettyPrinter(self.current_item)
self.results.append('a')
def search(self, what, cat='all'):
ret = []
i = 1
while True and i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url)
dat = retrieve_url(self.url+'/search/%s/%s/seeds/%d'%(what, self.supported_categories[cat], i))
results_re = re.compile('(?s)<h1>Search results for.*')
for match in results_re.finditer(dat):
res_tab = match.group(0)
parser.feed(res_tab)
parser.close()
break
if len(results) <= 0:
break
i += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

View File

@@ -0,0 +1,113 @@
#VERSION: 1.40
#AUTHORS: Fabien Devaux (fab@gnux.info)
#CONTRIBUTORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
import sgmllib3
from helpers import retrieve_url, download_file
class piratebay(object):
url = 'http://thepiratebay.org'
name = 'The Pirate Bay'
supported_categories = {'all': '0', 'movies': '200', 'music': '100', 'games': '400', 'software': '300'}
def __init__(self):
self.results = []
self.parser = self.SimpleSGMLParser(self.results, self.url)
def download_torrent(self, info):
print(download_file(info))
class SimpleSGMLParser(sgmllib3.SGMLParser):
def __init__(self, results, url, *args):
sgmllib3.SGMLParser.__init__(self)
self.td_counter = None
self.current_item = None
self.results = results
self.url = url
self.code = 0
self.in_name = None
def start_a(self, attr):
params = dict(attr)
if params['href'].startswith('/torrent/'):
self.current_item = {}
self.td_counter = 0
self.code = params['href'].split('/')[2]
self.current_item['desc_link'] = 'http://thepiratebay.org'+params['href'].strip()
self.in_name = True
elif params['href'].startswith('http://torrents.thepiratebay.org/%s'%self.code):
self.current_item['link']=params['href'].strip()
self.in_name = False
def handle_data(self, data):
if self.td_counter == 0:
if self.in_name:
if 'name' not in self.current_item:
self.current_item['name'] = ''
self.current_item['name']+= data.strip()
else:
#Parse size
if 'Size' in data:
self.current_item['size'] = data[data.index("Size")+5:]
self.current_item['size'] = self.current_item['size'][:self.current_item['size'].index(',')]
elif self.td_counter == 1:
if 'seeds' not in self.current_item:
self.current_item['seeds'] = ''
self.current_item['seeds']+= data.strip()
elif self.td_counter == 2:
if 'leech' not in self.current_item:
self.current_item['leech'] = ''
self.current_item['leech']+= data.strip()
def start_td(self,attr):
if isinstance(self.td_counter,int):
self.td_counter += 1
if self.td_counter > 3:
self.td_counter = None
# Display item
if self.current_item:
self.current_item['engine_url'] = self.url
if not self.current_item['seeds'].isdigit():
self.current_item['seeds'] = 0
if not self.current_item['leech'].isdigit():
self.current_item['leech'] = 0
prettyPrinter(self.current_item)
self.results.append('a')
def search(self, what, cat='all'):
ret = []
i = 0
order = 'se'
while True and i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url)
dat = retrieve_url(self.url+'/search/%s/%d/7/%s' % (what, i, self.supported_categories[cat]))
parser.feed(dat)
parser.close()
if len(results) <= 0:
break
i += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

View File

@@ -0,0 +1,141 @@
#VERSION: 1.1
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
from helpers import retrieve_url
import io, gzip, urllib.request, urllib.error, urllib.parse, tempfile
import sgmllib3
import re
import os
class torrentdownloads(object):
url = 'http://www.torrentdownloads.net'
name = 'TorrentDownloads'
supported_categories = {'all': '0', 'movies': '4', 'tv': '8', 'music': '5', 'games': '3', 'anime': '1', 'software': '7', 'books': '2'}
def __init__(self):
self.results = []
#self.parser = self.SimpleSGMLParser(self.results, self.url)
def download_torrent(self, url):
""" Download file at url and write it to a file, return the path to the file and the url """
file, path = tempfile.mkstemp()
file = os.fdopen(file, "w")
# Download url
req = urllib.request.Request(url)
response = urllib.request.urlopen(req)
dat = response.read()
# Check if it is gzipped
if dat[:2] == '\037\213':
# Data is gzip encoded, decode it
compressedstream = io.StringIO(dat)
gzipper = gzip.GzipFile(fileobj=compressedstream)
extracted_data = gzipper.read()
dat = extracted_data
# Write it to a file
file.write(dat.strip())
file.close()
# return file path
print(path+" "+url)
class SimpleSGMLParser(sgmllib3.SGMLParser):
def __init__(self, results, url, what, *args):
sgmllib3.SGMLParser.__init__(self)
self.url = url
self.li_counter = None
self.current_item = None
self.results = results
self.what = what.upper().split('+')
if len(self.what) == 0:
self.what = None
def start_a(self, attr):
params = dict(attr)
#print params
if 'href' in params and params['href'].startswith("http://www.torrentdownloads.net/torrent/"):
self.current_item = {}
self.li_counter = 0
self.current_item['desc_link'] = params['href'].strip()
self.current_item['link']=params['href'].strip().replace('/torrent', '/download', 1)
def handle_data(self, data):
if self.li_counter == 0:
if 'name' not in self.current_item:
self.current_item['name'] = ''
self.current_item['name']+= data
elif self.li_counter == 1:
if 'size' not in self.current_item:
self.current_item['size'] = ''
self.current_item['size']+= data.strip().replace("&nbsp;", " ")
elif self.li_counter == 2:
if 'seeds' not in self.current_item:
self.current_item['seeds'] = ''
self.current_item['seeds']+= data.strip()
elif self.li_counter == 3:
if 'leech' not in self.current_item:
self.current_item['leech'] = ''
self.current_item['leech']+= data.strip()
def start_li(self,attr):
if isinstance(self.li_counter,int):
self.li_counter += 1
if self.li_counter > 3:
self.li_counter = None
# Display item
if self.current_item:
self.current_item['engine_url'] = self.url
if not self.current_item['seeds'].isdigit():
self.current_item['seeds'] = 0
if not self.current_item['leech'].isdigit():
self.current_item['leech'] = 0
# Search should use AND operator as a default
tmp = self.current_item['name'].upper();
if self.what is not None:
for w in self.what:
if tmp.find(w) < 0: return
prettyPrinter(self.current_item)
self.results.append('a')
def search(self, what, cat='all'):
ret = []
i = 1
while i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url, what)
dat = retrieve_url(self.url+'/search/?page=%d&search=%s&s_cat=%s&srt=seeds&pp=50&order=desc'%(i, what, self.supported_categories[cat]))
results_re = re.compile('(?s)<div class="torrentlist">.*')
for match in results_re.finditer(dat):
res_tab = match.group(0)
parser.feed(res_tab)
parser.close()
break
if len(results) <= 0:
break
i += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

View File

@@ -0,0 +1,107 @@
#VERSION: 1.31
#AUTHORS: Gekko Dam Beer (gekko04@users.sourceforge.net)
#CONTRIBUTORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
import sgmllib3
from helpers import retrieve_url, download_file
class torrentreactor(object):
url = 'http://www.torrentreactor.net'
name = 'TorrentReactor.Net'
supported_categories = {'all': '', 'movies': '5', 'tv': '8', 'music': '6', 'games': '3', 'anime': '1', 'software': '2'}
def download_torrent(self, info):
print(download_file(info))
class SimpleSGMLParser(sgmllib3.SGMLParser):
def __init__(self, results, url, *args):
sgmllib3.SGMLParser.__init__(self)
self.td_counter = None
self.current_item = None
self.results = results
self.id = None
self.url = url
def start_a(self, attr):
params = dict(attr)
if 'torrentreactor.net/download.php' in params['href']:
self.current_item = {}
self.td_counter = 0
self.current_item['link'] = params['href'].strip()
elif params['href'].startswith('/torrents/'):
self.current_item['desc_link'] = 'http://www.torrentreactor.net'+params['href'].strip()
def handle_data(self, data):
if self.td_counter == 0:
if 'name' not in self.current_item:
self.current_item['name'] = ''
self.current_item['name']+= data.strip()
if self.td_counter == 1:
if 'size' not in self.current_item:
self.current_item['size'] = ''
self.current_item['size']+= data.strip()
elif self.td_counter == 2:
if 'seeds' not in self.current_item:
self.current_item['seeds'] = ''
self.current_item['seeds']+= data.strip()
elif self.td_counter == 3:
if 'leech' not in self.current_item:
self.current_item['leech'] = ''
self.current_item['leech']+= data.strip()
def start_td(self,attr):
if isinstance(self.td_counter,int):
self.td_counter += 1
if self.td_counter > 3:
self.td_counter = None
# add item to results
if self.current_item:
self.current_item['engine_url'] = self.url
if not self.current_item['seeds'].isdigit():
self.current_item['seeds'] = 0
if not self.current_item['leech'].isdigit():
self.current_item['leech'] = 0
prettyPrinter(self.current_item)
self.has_results = True
self.results.append('a')
def __init__(self):
self.results = []
self.parser = self.SimpleSGMLParser(self.results, self.url)
def search(self, what, cat='all'):
i = 0
while True and i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url)
dat = retrieve_url(self.url+'/search.php?search=&words=%s&cid=%s&sid=&type=1&orderby=a.seeds&asc=0&skip=%s'%(what, self.supported_categories[cat], (i*35)))
parser.feed(dat)
parser.close()
if len(results) <= 0:
break
i += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

View File

@@ -0,0 +1,129 @@
#VERSION: 1.3
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from novaprinter import prettyPrinter
from helpers import retrieve_url, download_file
import sgmllib3
import re
class vertor(object):
url = 'http://www.vertor.com'
name = 'vertor'
supported_categories = {'all': '0', 'movies': '5', 'tv': '8', 'music': '6', 'games': '3', 'anime': '1', 'software': '2'}
def __init__(self):
self.results = []
self.parser = self.SimpleSGMLParser(self.results, self.url)
def download_torrent(self, info):
print(download_file(info))
class SimpleSGMLParser(sgmllib3.SGMLParser):
def __init__(self, results, url, *args):
sgmllib3.SGMLParser.__init__(self)
self.url = url
self.td_counter = None
self.current_item = None
self.results = results
self.in_name = False
self.outside_td = True;
def start_tr(self, attr):
self.td_counter = -1
self.current_item = {}
def end_tr(self):
if self.td_counter == 5:
self.td_counter = None
# Display item
if self.current_item and 'link' in self.current_item:
self.current_item['engine_url'] = self.url
if not self.current_item['seeds'].isdigit():
self.current_item['seeds'] = 0
if not self.current_item['leech'].isdigit():
self.current_item['leech'] = 0
prettyPrinter(self.current_item)
self.results.append('a')
def start_a(self, attr):
#if self.td_counter is None or self.td_counter < 0: return
params = dict(attr)
if 'href' in params and params['href'].startswith("http://www.vertor.com/index.php?mod=download"):
self.current_item['link']=params['href'].strip()
elif self.td_counter == 0 and 'href' in params and params['href'].startswith("/torrents/") \
and 'name' not in self.current_item:
self.current_item['desc_link']='http://www.vertor.com'+params['href'].strip()
self.in_name = True
def end_a(self):
if self.in_name:
self.in_name = False
def handle_data(self, data):
if self.in_name:
if 'name' not in self.current_item:
self.current_item['name'] = ''
self.current_item['name']+= data.strip()
elif self.td_counter == 2 and not self.outside_td:
if 'size' not in self.current_item:
self.current_item['size'] = ''
self.current_item['size']+= data.strip()
elif self.td_counter == 4 and not self.outside_td:
if 'seeds' not in self.current_item:
self.current_item['seeds'] = ''
self.current_item['seeds']+= data.strip()
elif self.td_counter == 5 and not self.outside_td:
if 'leech' not in self.current_item:
self.current_item['leech'] = ''
self.current_item['leech']+= data.strip()
def end_td(self):
self.outside_td = True
def start_td(self,attr):
if isinstance(self.td_counter,int):
self.outside_td = False
self.td_counter += 1
def search(self, what, cat='all'):
ret = []
i = 0
while True and i<11:
results = []
parser = self.SimpleSGMLParser(results, self.url)
dat = retrieve_url(self.url+'/index.php?mod=search&words=%s&cid=%s&orderby=a.seeds&asc=0&search=&exclude=&p=%d'%(what, self.supported_categories[cat], i))
results_re = re.compile('(?s)<table class="listing">.*')
for match in results_re.finditer(dat):
res_tab = match.group(0)
parser.feed(res_tab)
parser.close()
break
if len(results) <= 0:
break
i += 1

View File

@@ -0,0 +1,99 @@
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#VERSION: 1.31
# Author:
# Christophe DUMEZ (chris@qbittorrent.org)
import re, html.entities
import tempfile
import os
import io, gzip, urllib.request, urllib.error, urllib.parse
import socket
import socks
import re
# SOCKS5 Proxy support
if "sock_proxy" in os.environ and len(os.environ["sock_proxy"].strip()) > 0:
proxy_str = os.environ["sock_proxy"].strip()
m=re.match(r"^(?:(?P<username>[^:]+):(?P<password>[^@]+)@)?(?P<host>[^:]+):(?P<port>\w+)$", proxy_str)
if m is not None:
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, m.group('host'), int(m.group('port')), True, m.group('username'), m.group('password'))
socket.socket = socks.socksocket
def htmlentitydecode(s):
# First convert alpha entities (such as &eacute;)
# (Inspired from http://mail.python.org/pipermail/python-list/2007-June/443813.html)
def entity2char(m):
entity = m.group(1)
if entity in html.entities.name2codepoint:
return chr(html.entities.name2codepoint[entity])
return " " # Unknown entity: We replace with a space.
t = re.sub('&(%s);' % '|'.join(html.entities.name2codepoint), entity2char, s)
# Then convert numerical entities (such as &#233;)
t = re.sub('&#(\d+);', lambda x: chr(int(x.group(1))), t)
# Then convert hexa entities (such as &#x00E9;)
return re.sub('&#x(\w+);', lambda x: chr(int(x.group(1),16)), t)
def retrieve_url(url):
""" Return the content of the url page as a string """
response = urllib.request.urlopen(url)
dat = response.read()
info = response.info()
charset = 'utf-8'
try:
ignore, charset = info['Content-Type'].split('charset=')
except:
pass
dat = dat.decode(charset, 'replace')
dat = htmlentitydecode(dat)
#return dat.encode('utf-8', 'replace')
return dat
def download_file(url, referer=None):
""" Download file at url and write it to a file, return the path to the file and the url """
file, path = tempfile.mkstemp()
file = os.fdopen(file, "wb")
# Download url
req = urllib.request.Request(url)
if referer is not None:
req.add_header('referer', referer)
response = urllib.request.urlopen(req)
dat = response.read()
# Check if it is gzipped
if dat[:2] == b'\x1f\x8b':
# Data is gzip encoded, decode it
compressedstream = io.BytesIO(dat)
gzipper = gzip.GzipFile(fileobj=compressedstream)
extracted_data = gzipper.read()
dat = extracted_data
# Write it to a file
file.write(dat)
file.close()
# return file path
return path+" "+url

Some files were not shown because too many files have changed in this diff Show More