#!/usr/bin/env python3.6 import logging import re import xml.etree.ElementTree as ET from xml.etree.ElementTree import fromstring from http_utils import build_url, fetch_url from torrent import Torrent from utils import humansize, representsInteger logger = logging.getLogger('torrentSearch') class Jackett(object): """docstring for Jackett""" def __init__(self, apikey, host, path, limit, ssl): super(Jackett, self).__init__() self.apikey = apikey self.host = host self.path = path self.page_limit = limit self.ssl = ssl def get_apikey(self): logger.debug('Using api key: {}'.format(self.apikey)) return self.apikey def get_path(self): return self.path def get_page_limit(self): logger.debug('Current page limit: {} pages'.format(self.page_limit)) return self.page_limit def search(self, query): """ Starts the call to getting result from our indexer :param jackett.Jackett self: object instance :param str query: query we want to search for :return: list of results we found from scraping jackett output based on query :rtype: list """ baseUrl = 'http://' + self.host path = self.get_path().split('/') url_args = { 'apikey': self.get_apikey(), 'limit': self.get_page_limit(), 'q': query } logger.debug('Url arguments for jackett search: {}'.format(url_args)) url = build_url(self.ssl, baseUrl, path, url_args) url = url.replace('+', '%20') res = fetch_url(url) return self.parse_xml_for_torrents(res.read()) def find_xml_attribute(self, xml_element, attr): """ Finds a specific XML attribute given a element name :param jackett.Jackett self: object instance :param xml.etree.ElementTree.Element xml_element: the xml tree we want to search :param str attr: the attribute/element name we want to find in the xml tree :return: the value of the element fiven the attr/element name :rtype: str """ value = xml_element.find(attr) if (value != None): logger.debug('Found attribute: {}'.format(attr)) return value.text else: logger.warning('Could not find attribute: {}'.format(attr)) return '' def parse_xml_for_torrents(self, raw_xml): """ Finds a specific XML attribute given a element name :param jackett.Jackett self: object instance :param bytes raw_xml: the xml page returned by querying jackett :return: all the torrents we found in the xml page :rtype: list """ tree = ET.fromstring(raw_xml) channel = tree.find('channel') results = [] for child in channel.findall('item'): title = self.find_xml_attribute(child, 'title') date = self.find_xml_attribute(child, 'pubDate') magnet = self.find_xml_attribute(child, 'link') size = self.find_xml_attribute(child, 'size') files = self.find_xml_attribute(child, 'files') foundUploader = re.findall('-1? *\w*', title) if len(foundUploader) > 0: uploader = str(foundUploader[-1][1:]) else: uploader = None seeders = 0 peers = 0 for elm in child.findall('{http://torznab.com/schemas/2015/feed}attr'): if elm.get('name') == 'seeders': seeders = elm.get('value') if elm.get('name') == 'peers': peers = elm.get('value') if size != '' and representsInteger(size): size = humansize(int(size)) logger.debug('Found torrent with info: \n\ttitle: {}\n\tmagnet: {}\n\tsize: {}\n\tdate: {}\ \n\tseeders: {}\n\tpeers: {}'.format(title, magnet, size, date, seeders, peers)) torrent = Torrent(title, magnet=magnet, size=size, uploader=uploader, date=date, seed_count=seeders, leech_count=peers) results.append(torrent) return results