From 5c1169ba9d3a7bbb4fcd966a77fe9d44bd679d4f Mon Sep 17 00:00:00 2001 From: delphiactual Date: Tue, 6 May 2014 21:38:28 -0600 Subject: [PATCH 1/3] Removed leftover DownloadStation [beta] changes --- headphones/notifiers.py | 2 +- headphones/searcher.py | 32 +++----------------------------- headphones/utorrent.py | 19 +++++++------------ 3 files changed, 11 insertions(+), 42 deletions(-) diff --git a/headphones/notifiers.py b/headphones/notifiers.py index 4bd7c366..1537323b 100644 --- a/headphones/notifiers.py +++ b/headphones/notifiers.py @@ -388,6 +388,7 @@ class NMA: logger.debug(u"NMA title: " + title) logger.debug(u"NMA API: " + api) logger.debug(u"NMA Priority: " + str(nma_priority)) + if snatched: event = snatched + " snatched!" message = "Headphones has snatched: " + snatched @@ -395,7 +396,6 @@ class NMA: event = artist + ' - ' + album + ' complete!' message = "Headphones has downloaded and postprocessed: " + artist + ' [' + album + ']' - logger.debug(u"NMA event: " + event) logger.debug(u"NMA message: " + message) diff --git a/headphones/searcher.py b/headphones/searcher.py index 48483b0d..0a33df12 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -699,7 +699,7 @@ def send_to_downloader(data, bestqual, album): except Exception, e: logger.exception("Unhandled exception") - elif headphones.TORRENT_DOWNLOADER == 2: + else:# if headphones.TORRENT_DOWNLOADER == 2: logger.info("Sending torrent to uTorrent") # rutracker needs cookies to be set, pass the .torrent file instead of url @@ -725,32 +725,6 @@ def send_to_downloader(data, bestqual, album): except Exception, e: logger.exception("Unhandled exception") - else: - logger.info("Sending torrent to DownloadStation") - - # rutracker needs cookies to be set, pass the .torrent file instead of url - if bestqual[3] == 'rutracker.org': - file_or_url = rutracker.get_torrent(bestqual[2]) - else: - file_or_url = bestqual[2] - - _hash = CalculateTorrentHash(file_or_url, data) - - folder_name = download_station.addTorrent(file_or_url) - - if folder_name: - logger.info('Torrent folder name: %s' % folder_name) - else: - logger.error('Torrent folder name could not be determined') - return - - # remove temp .torrent file created above - if bestqual[3] == 'rutracker.org': - try: - shutil.rmtree(os.path.split(file_or_url)[0]) - except Exception, e: - logger.exception("Unhandled exception") - myDB = db.DBConnection() myDB.action('UPDATE albums SET status = "Snatched" WHERE AlbumID=?', [album['AlbumID']]) myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)', [album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Snatched", folder_name, kind]) @@ -1431,7 +1405,7 @@ def preprocess(resultlist): for result in resultlist: if result[4] == 'torrent': - #Get out of here if we're using Transmission or uTorrent + #Get out of here if we're using Transmission if headphones.TORRENT_DOWNLOADER == 1: ## if not a magnet link still need the .torrent to generate hash... uTorrent support labeling return True, result # get outta here if rutracker @@ -1495,6 +1469,6 @@ def CalculateTorrentHash(link, data): info = bdecode(data)["info"] tor_hash = sha1(bencode(info)).hexdigest() - logger.info('Torrent Hash: ' + str(tor_hash)) + logger.debug('Torrent Hash: ' + str(tor_hash)) return tor_hash \ No newline at end of file diff --git a/headphones/utorrent.py b/headphones/utorrent.py index 3ce07906..848cf6f9 100644 --- a/headphones/utorrent.py +++ b/headphones/utorrent.py @@ -13,17 +13,12 @@ # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . -import urllib -import urllib2 -import urlparse -import cookielib -import json -import re -import os -import time +import urllib, urllib2, urlparse, cookielib +import json, re, os, time + import headphones -from headphones import logger, notifiers +from headphones import logger class utorrentclient(object): TOKEN_REGEX = "" @@ -77,7 +72,7 @@ class utorrentclient(object): return self._action(params) def add_url(self, url): - #can recieve magnet or normal .torrent link + #can receive magnet or normal .torrent link params = [('action', 'add-url'), ('s', url)] return self._action(params) @@ -146,8 +141,8 @@ def addTorrent(link, hash): label = headphones.UTORRENT_LABEL uTorrentClient = utorrentclient() uTorrentClient.add_url(link) - time.sleep(1) #need to ensure file is loaded uTorrent... - uTorrentClient.setprops(hash,'label', label) + time.sleep(1) #ensure file is loaded in uTorrent... + uTorrentClient.setprops(hash,'label',label) torrentList = uTorrentClient.list() for torrent in torrentList[1].get('torrents'): if (torrent[0].lower()==hash): From 62a6be26af288434d8ddecc8f33dbce2f1dd04ff Mon Sep 17 00:00:00 2001 From: delphiactual Date: Wed, 7 May 2014 08:19:08 -0600 Subject: [PATCH 2/3] PyNMA lib --- lib/pynma/__init__.py | 4 ++ lib/pynma/pynma.py | 137 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 lib/pynma/__init__.py create mode 100644 lib/pynma/pynma.py diff --git a/lib/pynma/__init__.py b/lib/pynma/__init__.py new file mode 100644 index 00000000..f90424eb --- /dev/null +++ b/lib/pynma/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/python + +from pynma import PyNMA + diff --git a/lib/pynma/pynma.py b/lib/pynma/pynma.py new file mode 100644 index 00000000..fc7d8de2 --- /dev/null +++ b/lib/pynma/pynma.py @@ -0,0 +1,137 @@ +#!/usr/bin/python + +from xml.dom.minidom import parseString +from httplib import HTTPSConnection +from urllib import urlencode + +__version__ = "0.1" + +API_SERVER = 'nma.usk.bz' +ADD_PATH = '/publicapi/notify' + +USER_AGENT="PyNMA/v%s"%__version__ + +def uniq_preserve(seq): # Dave Kirby + # Order preserving + seen = set() + return [x for x in seq if x not in seen and not seen.add(x)] + +def uniq(seq): + # Not order preserving + return {}.fromkeys(seq).keys() + +class PyNMA(object): + """PyNMA(apikey=[], developerkey=None) + takes 2 optional arguments: + - (opt) apykey: might me a string containing 1 key or an array of keys + - (opt) developerkey: where you can store your developer key + """ + + def __init__(self, apikey=[], developerkey=None): + self._developerkey = None + self.developerkey(developerkey) + if apikey: + if type(apikey) == str: + apikey = [apikey] + self._apikey = uniq(apikey) + + def addkey(self, key): + "Add a key (register ?)" + if type(key) == str: + if not key in self._apikey: + self._apikey.append(key) + elif type(key) == list: + for k in key: + if not k in self._apikey: + self._apikey.append(k) + + def delkey(self, key): + "Removes a key (unregister ?)" + if type(key) == str: + if key in self._apikey: + self._apikey.remove(key) + elif type(key) == list: + for k in key: + if key in self._apikey: + self._apikey.remove(k) + + def developerkey(self, developerkey): + "Sets the developer key (and check it has the good length)" + if type(developerkey) == str and len(developerkey) == 48: + self._developerkey = developerkey + + def push(self, application="", event="", description="", url="", priority=0, batch_mode=False): + """Pushes a message on the registered API keys. + takes 5 arguments: + - (req) application: application name [256] + - (req) event: event name [1000] + - (req) description: description [10000] + - (opt) url: url [512] + - (opt) priority: from -2 (lowest) to 2 (highest) (def:0) + - (opt) batch_mode: call API 5 by 5 (def:False) + + Warning: using batch_mode will return error only if all API keys are bad + cf: http://nma.usk.bz/api.php + """ + datas = { + 'application': application[:256].encode('utf8'), + 'event': event[:1024].encode('utf8'), + 'description': description[:10000].encode('utf8'), + 'priority': priority + } + + if url: + datas['url'] = url[:512] + + if self._developerkey: + datas['developerkey'] = self._developerkey + + results = {} + + if not batch_mode: + for key in self._apikey: + datas['apikey'] = key + res = self.callapi('POST', ADD_PATH, datas) + results[key] = res + else: + for i in range(0, len(self._apikey), 5): + datas['apikey'] = ",".join(self._apikey[i:i+5]) + res = self.callapi('POST', ADD_PATH, datas) + results[datas['apikey']] = res + return results + + def callapi(self, method, path, args): + headers = { 'User-Agent': USER_AGENT } + if method == "POST": + headers['Content-type'] = "application/x-www-form-urlencoded" + http_handler = HTTPSConnection(API_SERVER) + http_handler.request(method, path, urlencode(args), headers) + resp = http_handler.getresponse() + + try: + res = self._parse_reponse(resp.read()) + except Exception, e: + res = {'type': "pynmaerror", + 'code': 600, + 'message': str(e) + } + pass + + return res + + def _parse_reponse(self, response): + root = parseString(response).firstChild + for elem in root.childNodes: + if elem.nodeType == elem.TEXT_NODE: continue + if elem.tagName == 'success': + res = dict(elem.attributes.items()) + res['message'] = "" + res['type'] = elem.tagName + return res + if elem.tagName == 'error': + res = dict(elem.attributes.items()) + res['message'] = elem.firstChild.nodeValue + res['type'] = elem.tagName + return res + + From e972a86233fc9a72ef4b9ca7ac482dd600c85511 Mon Sep 17 00:00:00 2001 From: delphiactual Date: Sun, 11 May 2014 21:26:58 -0600 Subject: [PATCH 3/3] Easier to follow logic for uTorrent --- headphones/utorrent.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/headphones/utorrent.py b/headphones/utorrent.py index 848cf6f9..b03acdf2 100644 --- a/headphones/utorrent.py +++ b/headphones/utorrent.py @@ -136,16 +136,31 @@ class utorrentclient(object): logger.debug('URL: ' + str(url)) logger.debug('uTorrent webUI raised the following error: ' + str(err)) -def addTorrent(link, hash): +def labelTorrent(hash): label = headphones.UTORRENT_LABEL uTorrentClient = utorrentclient() - uTorrentClient.add_url(link) - time.sleep(1) #ensure file is loaded in uTorrent... - uTorrentClient.setprops(hash,'label',label) + settinglabel = True + while settinglabel: + torrentList = uTorrentClient.list() + for torrent in torrentList[1].get('torrents'): + if (torrent[0].lower() == hash): + uTorrentClient.setprops(hash,'label',label) + settinglabel = False + return True + + +def dirTorrent(hash): + uTorrentClient = utorrentclient() torrentList = uTorrentClient.list() for torrent in torrentList[1].get('torrents'): - if (torrent[0].lower()==hash): + if (torrent[0].lower() == hash): return torrent[26] + return False - return False \ No newline at end of file + +def addTorrent(link, hash): + uTorrentClient = utorrentclient() + uTorrentClient.add_url(link) + labelTorrent(hash) + return dirTorrent(hash)