Permalink
Switch branches/tags
Find file Copy path
26a6e97 May 18, 2017
1 contributor

Users who have contributed to this file

267 lines (234 sloc) 9 KB
# -*- coding: utf-8 -*-
#VERSION: 1.3
#AUTHORS: Joost Bremmer (toost.b@gmail.com)
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
import os
import tempfile
try:
import urllib2 as request
from urllib import urlencode
from cookielib import CookieJar
from HTMLParser import HTMLParser
except ImportError:
import urllib.request as request
from urllib.parse import urlencode
from http.cookiejar import CookieJar
from html.parser import HTMLParser
# import qBT modules
try:
from novaprinter import prettyPrinter
from helpers import htmlentitydecode
except:
pass
class bakabt(object):
"""Class used by qBittorrent to search bakabt.me for torrents
It is important to replace the username and password values with your
personal login information. Without this, this plugin will *not* work.
"""
# Login information ######################################################
#
# SET THESE VALUES!!
#
username = "username"
password = "password"
###########################################################################
url = 'https://bakabt.me'
name = 'BakaBT'
# defines which search categories are supported by this search engine
# and their corresponding id. Possible categories are:
# 'all', 'movies', 'tv', 'music', 'games', 'anime', 'software', 'pictures',
# 'books'
supported_categories = {
'all': 0,
'anime': 1,
'music': 3, # Soundtracks
'books': 4, # Manga
'movies': 5,
'tv': 6, # Live Action
'pictures': 7} # Artbooks
class BakaDownloadParser(HTMLParser):
"""Parses BakaBT torrent page for download link"""
def __init__(self):
try:
super().__init__()
except:
# See: http://stackoverflow.com/questions/9698614/
HTMLParser.__init__(self)
self.download = None
def handle_starttag(self, tag, attr):
if tag == 'a':
self.start_a(attr)
def start_a(self, attr):
params = dict(attr)
if 'class' in params and params['class'] == 'download_link':
self.download = params['href']
class BakaSearchParser(HTMLParser):
""" Parses BakaBT browse page for search results and prints them"""
def __init__(self, res, url):
try:
super().__init__()
except:
# See: http://stackoverflow.com/questions/9698614/
HTMLParser.__init__(self)
self.download = None
self.results = res
self.engine_url = url
self.curr = None
self.wait_for_title = False
self.wait_for_date = False
self.wait_for_size = False
self.wait_for_seeds = False
self.wait_for_peers = False
def handle_starttag(self, tag, attr):
if tag == 'a':
self.start_a(attr)
elif tag == 'td':
self.start_td(attr)
def start_a(self, attr):
params = dict(attr)
if 'class' in params and 'title' in params['class']:
hit = {
'link': self.engine_url + '/' + params['href'],
'desc_link': self.engine_url + '/' + params['href']}
self.curr = hit
self.wait_for_title = True
elif 'style' in params and params['style'] == "color: #00cc00":
self.wait_for_seeds = True
elif self.curr is not None and 'seeds' in self.curr:
self.wait_for_peers = True
def start_td(self, attr):
params = dict(attr)
if 'class' in params and self.curr is not None:
if params['class'] == 'added':
pass
# self.wait_for_date = True
elif params['class'] == 'size':
self.wait_for_size = True
def handle_data(self, data):
if self.wait_for_title:
self.curr['name'] = data.strip()
self.wait_for_title = False
elif self.wait_for_date:
try:
date = datetime.datetime.strptime(data.strip(),
"%d %b '%y")
except ValueError:
date = datetime.datetime.now()
self.curr['date'] = date.strftime("%Y-%m-%d")
self.wait_for_date = False
elif self.wait_for_size:
self.curr['size'] = data.strip()
self.wait_for_size = False
elif self.wait_for_seeds:
self.curr['seeds'] = int(data.strip())
self.wait_for_seeds = False
elif self.wait_for_peers:
self.curr['leech'] = int(data.strip())
self.curr['engine_url'] = self.engine_url
prettyPrinter(self.curr)
self.results.append(self.curr)
self.curr = None
self.wait_for_peers = False
def __init__(self):
"""class initialization, requires personal login information"""
self.ua = \
'Mozilla/5.0 (X11; Linux i686; rv:38.0) ' + \
'Gecko/20100101 Firefox/38.0'
self.sesh = None
self._login(self.username, self.password)
def _login(self, username, password):
"""Initiate a session and log into BakaBT"""
# Build opener
cj = CookieJar()
params = {
'username': self.username,
'password': self.password,
'returnto': 'browse.php'}
sesh = request.build_opener(request.HTTPCookieProcessor(cj))
# change user-agent
sesh.addheaders.pop()
sesh.addheaders.append(('User-Agent', self.ua))
# send request
try:
sesh.open(
self.url + '/splash.php',
urlencode(params).encode('utf-8'))
self.sesh = sesh
except request.URLError as errorno:
print("Connection Error: {}".format(errorno.reason))
def _retreive_url(self, url):
"""Return the HTML content of url page as a string """
try:
res = self.sesh.open(url)
except request.URLError as errorno:
print("Connection Error: {}".format(errorno.reason))
return ""
charset = 'utf-8'
info = res.info()
try:
_, charset = info['Content-Type'].split('charset=')
except:
pass
dat = res.read()
dat = dat.decode(charset, 'replace')
dat = htmlentitydecode(dat)
return dat
def download_torrent(self, info):
"""Retrieve and save url as a temporary file."""
file, path = tempfile.mkstemp()
url = info
parser = self.BakaDownloadParser()
res = self._retreive_url(url)
parser.feed(res)
download = self.url + '/' + parser.download
parser.close()
torrent = self.sesh.open(download)
with os.fdopen(file, "wb") as f:
f.write(torrent.read())
f.close()
# Print file path and url.
print(path+" "+download)
parser.close()
# DO NOT CHANGE the name and parameters of this function
# This function will be the one called by nova2.py
def search(self, what, cat='all'):
"""
Retreive and parse all BakaBT search results by category and query.
Parameters:
:param what: a string with the search tokens, already escaped
(e.g. "Ubuntu+Linux")
:param cat: the name of a search category, see supported_categories.
"""
if cat in self.supported_categories:
url = "{0}/browse.php?limit=100&ordertype=seeders&q={1}&cat={2}"\
.format(
self.url,
what,
self.supported_categories[cat])
else:
url = "{0}/browse.php?limit=100&ordertype=seeders&q={1}"\
.format(self.url, what)
hits = []
parser = self.BakaSearchParser(hits, self.url)
i = 0
while True:
res = self._retreive_url(url + "&page={}".format(i))
parser.feed(res)
if len(hits) < 100:
break
del hits[:]
i += 1
parser.close()