def _sendjson(self, host, method, params={}): data = [{ 'id': 0, 'jsonrpc': '2.0', 'method': method, 'params': params }] headers = {'Content-Type': 'application/json'} url = host + '/jsonrpc' if self.password: response = request.request_json(url, method="post", data=json.dumps(data), headers=headers, auth=(self.username, self.password)) else: response = request.request_json(url, method="post", data=json.dumps(data), headers=headers) if response: return response[0]['result']
def _sendjson(self, host, method, params={}): data = [{'id': 0, 'jsonrpc': '2.0', 'method': method, 'params': params}] headers = {'Content-Type': 'application/json'} url = host + '/jsonrpc' if self.password: response = request.request_json(url, method="POST", data=simplejson.dumps(data), headers=headers, auth=(self.username, self.password)) else: response = request.request_json(url, method="POST", data=simplejson.dumps(data), headers=headers) if response: return response[0]['result']
def checkGithub(): headphones.COMMITS_BEHIND = 0 # Get the latest version available from github logger.info("Retrieving latest version information from GitHub") url = "https://api.github.com/repos/%s/headphones/commits/%s" % ( headphones.CONFIG.GIT_USER, headphones.CONFIG.GIT_BRANCH, ) version = request.request_json(url, timeout=20, validator=lambda x: type(x) == dict) if version is None: logger.warn("Could not get the latest version from GitHub. Are you running a local development version?") return headphones.CURRENT_VERSION headphones.LATEST_VERSION = version["sha"] logger.debug("Latest version is %s", headphones.LATEST_VERSION) # See how many commits behind we are if not headphones.CURRENT_VERSION: logger.info("You are running an unknown version of Headphones. Run the updater to identify your version") return headphones.LATEST_VERSION if headphones.LATEST_VERSION == headphones.CURRENT_VERSION: logger.info("Headphones is up to date") return headphones.LATEST_VERSION logger.info("Comparing currently installed version with latest GitHub version") url = "https://api.github.com/repos/%s/headphones/compare/%s...%s" % ( headphones.CONFIG.GIT_USER, headphones.LATEST_VERSION, headphones.CURRENT_VERSION, ) commits = request.request_json(url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == dict) if commits is None: logger.warn("Could not get commits behind from GitHub.") return headphones.LATEST_VERSION try: headphones.COMMITS_BEHIND = int(commits["behind_by"]) logger.debug("In total, %d commits behind", headphones.COMMITS_BEHIND) except KeyError: logger.info("Cannot compare versions. Are you running a local development version?") headphones.COMMITS_BEHIND = 0 if headphones.COMMITS_BEHIND > 0: logger.info("New version is available. You are %s commits behind" % headphones.COMMITS_BEHIND) elif headphones.COMMITS_BEHIND == 0: logger.info("Headphones is up to date") return headphones.LATEST_VERSION
def checkGithub(): headphones.COMMITS_BEHIND = 0 # Get the latest version available from github logger.info('Retrieving latest version information from GitHub') url = 'https://api.github.com/repos/%s/headphones/commits/%s' % ( headphones.CONFIG.GIT_USER, headphones.CONFIG.GIT_BRANCH) version = request.request_json(url, timeout=20, validator=lambda x: type(x) == dict) if version is None: logger.warn( 'Could not get the latest version from GitHub. Are you running a local development version?') return headphones.CURRENT_VERSION headphones.LATEST_VERSION = version['sha'] logger.debug("Latest version is %s", headphones.LATEST_VERSION) # See how many commits behind we are if not headphones.CURRENT_VERSION: logger.info( 'You are running an unknown version of Headphones. Run the updater to identify your version') return headphones.LATEST_VERSION if headphones.LATEST_VERSION == headphones.CURRENT_VERSION: logger.info('Headphones is up to date') return headphones.LATEST_VERSION logger.info('Comparing currently installed version with latest GitHub version') url = 'https://api.github.com/repos/%s/headphones/compare/%s...%s' % ( headphones.CONFIG.GIT_USER, headphones.LATEST_VERSION, headphones.CURRENT_VERSION) commits = request.request_json(url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == dict) if commits is None: logger.warn('Could not get commits behind from GitHub.') return headphones.LATEST_VERSION try: headphones.COMMITS_BEHIND = int(commits['behind_by']) logger.debug("In total, %d commits behind", headphones.COMMITS_BEHIND) except KeyError: logger.info('Cannot compare versions. Are you running a local development version?') headphones.COMMITS_BEHIND = 0 if headphones.COMMITS_BEHIND > 0: logger.info( 'New version is available. You are %s commits behind' % headphones.COMMITS_BEHIND) elif headphones.COMMITS_BEHIND == 0: logger.info('Headphones is up to date') return headphones.LATEST_VERSION
def _sendjson(self, host, method, params={}): data = [{"id": 0, "jsonrpc": "2.0", "method": method, "params": params}] headers = {"Content-Type": "application/json"} url = host + "/jsonrpc" if self.password: response = request.request_json( url, method="post", data=json.dumps(data), headers=headers, auth=(self.username, self.password) ) else: response = request.request_json(url, method="post", data=json.dumps(data), headers=headers) if response: return response[0]["result"]
def notify(self, message, status): if not headphones.CONFIG.PUSHBULLET_ENABLED: return url = "https://api.pushbullet.com/v2/pushes" data = {'type': "note", 'title': "Headphones", 'body': message + ': ' + status} if self.deviceid: data['device_iden'] = self.deviceid headers = {'Content-type': "application/json", 'Authorization': 'Bearer ' + headphones.CONFIG.PUSHBULLET_APIKEY} response = request.request_json(url, method="post", headers=headers, data=json.dumps(data)) if response: logger.info(u"PushBullet notifications sent.") return True else: logger.info(u"PushBullet notification failed.") return False
def notify(self, message, status): if not headphones.CONFIG.PUSHBULLET_ENABLED: return url = "https://api.pushbullet.com/v2/pushes" data = { 'type': "note", 'title': "Headphones", 'body': message + ': ' + status } if self.deviceid: data['device_iden'] = self.deviceid headers = { 'Content-type': "application/json", 'Authorization': 'Bearer ' + headphones.CONFIG.PUSHBULLET_APIKEY } response = request.request_json(url, method="post", headers=headers, data=json.dumps(data)) if response: logger.info(u"PushBullet notifications sent.") return True else: logger.info(u"PushBullet notification failed.") return False
def request_lastfm(method, **kwargs): """ Call a Last.FM API method. Automatically sets the method and API key. Method will return the result if no error occured. By default, this method will request the JSON format, since it is more lightweight than XML. """ # Prepare request kwargs["method"] = method kwargs.setdefault("api_key", API_KEY) kwargs.setdefault("format", "json") # Send request logger.debug("Calling Last.FM method: %s", method) logger.debug("Last.FM call parameters: %s", kwargs) data = request.request_json(ENTRY_POINT, timeout=TIMEOUT, params=kwargs, rate_limit=(lock, REQUEST_LIMIT)) # Parse response and check for errors. if not data: logger.error("Error calling Last.FM method: %s", method) return if "error" in data: logger.error("Last.FM returned an error: %s", data["message"]) return return data
def request_lastfm(method, **kwargs): """ Call a Last.FM API method. Automatically sets the method and API key. Method will return the result if no error occured. By default, this method will request the JSON format, since it is more lightweight than XML. """ # Prepare request kwargs["method"] = method kwargs.setdefault("api_key", API_KEY) kwargs.setdefault("format", "json") # Send request logger.debug("Calling Last.FM method: %s", method) logger.debug("Last.FM call parameters: %s", kwargs) data = request.request_json(ENTRY_POINT, timeout=TIMEOUT, params=kwargs, lock=lastfm_lock) # Parse response and check for errors. if not data: logger.error("Error calling Last.FM method: %s", method) return if "error" in data: logger.error("Last.FM returned an error: %s", data["message"]) return return data
def torrentAction(method, arguments): host = headphones.CONFIG.TRANSMISSION_HOST username = headphones.CONFIG.TRANSMISSION_USERNAME password = headphones.CONFIG.TRANSMISSION_PASSWORD if not host.startswith("http"): host = "http://" + host if host.endswith("/"): host = host[:-1] # Fix the URL. We assume that the user does not point to the RPC endpoint, # so add it if it is missing. parts = list(urlparse.urlparse(host)) if not parts[0] in ("http", "https"): parts[0] = "http" if not parts[2].endswith("/rpc"): parts[2] += "/transmission/rpc" host = urlparse.urlunparse(parts) # Retrieve session id auth = (username, password) if username and password else None response = request.request_response(host, auth=auth, whitelist_status_code=[401, 409]) if response is None: logger.error("Error gettings Transmission session ID") return # Parse response if response.status_code == 401: if auth: logger.error("Username and/or password not accepted by " "Transmission") else: logger.error("Transmission authorization required") return elif response.status_code == 409: session_id = response.headers["x-transmission-session-id"] if not session_id: logger.error("Expected a Session ID from Transmission") return # Prepare next request headers = {"x-transmission-session-id": session_id} data = {"method": method, "arguments": arguments} response = request.request_json(host, method="POST", data=json.dumps(data), headers=headers, auth=auth) print response if not response: logger.error("Error sending torrent to Transmission") return return response
def sab_api_call(request_type=None, params={}, **kwargs): if not headphones.CONFIG.SAB_HOST.startswith('http'): headphones.CONFIG.SAB_HOST = 'http://' + headphones.CONFIG.SAB_HOST if headphones.CONFIG.SAB_HOST.endswith('/'): headphones.CONFIG.SAB_HOST = headphones.CONFIG.SAB_HOST[ 0:len(headphones.CONFIG.SAB_HOST) - 1] url = headphones.CONFIG.SAB_HOST + "/" + "api?" if headphones.CONFIG.SAB_USERNAME: params['ma_username'] = headphones.CONFIG.SAB_USERNAME if headphones.CONFIG.SAB_PASSWORD: params['ma_password'] = headphones.CONFIG.SAB_PASSWORD if headphones.CONFIG.SAB_APIKEY: params['apikey'] = headphones.CONFIG.SAB_APIKEY if request_type == 'send_nzb' and headphones.CONFIG.SAB_CATEGORY: params['cat'] = headphones.CONFIG.SAB_CATEGORY params['output'] = 'json' response = request.request_json(url, params=params, **kwargs) if not response: logger.error("Error connecting to SABnzbd on url: %s" % headphones.CONFIG.SAB_HOST) return False else: logger.debug("Successfully connected to SABnzbd on url: %s" % headphones.CONFIG.SAB_HOST) return response
def request_lastfm(method, **kwargs): """ Call a Last.FM API method. Automatically sets the method and API key. Method will return the result if no error occured. By default, this method will request the JSON format, since it is more lightweight than XML. """ if headphones.CONFIG.LASTFM_PERSONAL_KEY: API_KEY = headphones.CONFIG.LASTFM_PERSONAL_KEY else: API_KEY = "395e6ec6bb557382fc41fde867bce66f" # Prepare request kwargs["method"] = method kwargs.setdefault("api_key", API_KEY) kwargs.setdefault("format", "json") # Send request logger.debug("Calling Last.FM method: %s", method) logger.debug("Last.FM API Key is: %s" % API_KEY) logger.debug("Last.FM call parameters: %s", kwargs) data = request.request_json(ENTRY_POINT, timeout=TIMEOUT, params=kwargs, lock=lastfm_lock) # Parse response and check for errors. if not data: logger.error("Error calling Last.FM method: %s", method) # when there is a last.fm api fail, this return prevents artist artwork from loading # return if "error" in data: logger.debug("Last.FM returned an error: %s", data["message"]) # when there is a last.fm api fail, this return prevents artist artwork from loading # return return data
def get_image_links(self, ArtistID=None, AlbumID=None): """ Here we're just going to open up the last.fm url, grab the image links and return them Won't save any image urls, or save the artwork in the cache. Useful for search results, etc. """ if ArtistID: self.id_type = 'artist' # 2019 last.fm no longer allows access to artist images, try fanart.tv instead image_url = None thumb_url = None data = request.request_json(FANART_URL + ArtistID, whitelist_status_code=404, headers={ 'api-key': FANART_PROJECT_KEY, 'client-key': FANART_CLIENT_KEY }) if not data: return if data.get('artistthumb'): image_url = data['artistthumb'][0]['url'] elif data.get('artistbackground'): image_url = data['artistbackground'][0]['url'] # elif data.get('hdmusiclogo'): # image_url = data['hdmusiclogo'][0]['url'] # fallback to 1st album cover if none of the above elif 'albums' in data: for mbid, art in data.get('albums', dict()).items(): if 'albumcover' in art: image_url = art['albumcover'][0]['url'] break if image_url: thumb_url = image_url else: logger.debug( 'No artist image found on fanart.tv for Artist Id: %s', self.id) else: self.id_type = 'album' data = lastfm.request_lastfm("album.getinfo", mbid=AlbumID, api_key=LASTFM_API_KEY) if not data: return try: image_url = data['album']['image'][-1]['#text'] except (KeyError, IndexError): logger.debug('No album image found on last.fm') image_url = None thumb_url = self._get_thumb_url(data) if not thumb_url: logger.debug('No album thumbnail image found on last.fm') return {'artwork': image_url, 'thumbnail': thumb_url}
def torrentAction(method, arguments): host = headphones.TRANSMISSION_HOST username = headphones.TRANSMISSION_USERNAME password = headphones.TRANSMISSION_PASSWORD sessionid = None if not host.startswith('http'): host = 'http://' + host if host.endswith('/'): host = host[:-1] # Either the host ends with a port, or some directory, or rpc # If it ends with /rpc we don't have to do anything # If it ends with a port we add /transmission/rpc # anything else we just add rpc if not host.endswith('/rpc'): # Check if it ends in a port number i = host.rfind(':') if i >= 0: possible_port = host[i + 1:] try: port = int(possible_port) host = host + "/transmission/rpc" except ValueError: host = host + "/rpc" else: logger.error('Transmission port missing') return # Retrieve session id auth = (username, password) if username and password else None response = request.request_response(host, auth=auth, whitelist_status_code=[401, 409]) if response is None: logger.error("Error gettings Transmission session ID") return # Parse response if response.status_code == 401: if auth: logger.error( "Username and/or password not accepted by Transmission") else: logger.error("Transmission authorization required") return elif response.status_code == 409: sessionid = response.headers['x-transmission-session-id'] if not sessionid: logger.error("Error getting Session ID from Transmission") return # Prepare next request headers = {'x-transmission-session-id': sessionid} data = {'method': method, 'arguments': arguments} response = request.request_json(host, method="post", data=json.dumps(data), headers=headers, auth=auth) if not response: logger.error("Error sending torrent to Transmission") return return response
def torrentAction(method, arguments): host = headphones.TRANSMISSION_HOST username = headphones.TRANSMISSION_USERNAME password = headphones.TRANSMISSION_PASSWORD sessionid = None if not host.startswith('http'): host = 'http://' + host if host.endswith('/'): host = host[:-1] # Either the host ends with a port, or some directory, or rpc # If it ends with /rpc we don't have to do anything # If it ends with a port we add /transmission/rpc # anything else we just add rpc if not host.endswith('/rpc'): # Check if it ends in a port number i = host.rfind(':') if i >= 0: possible_port = host[i+1:] try: port = int(possible_port) host = host + "/transmission/rpc" except ValueError: host = host + "/rpc" else: logger.error('Transmission port missing') return # Retrieve session id auth = (username, password) if username and password else None response = request.request_response(host, auth=auth, whitelist_status_code=[401, 409]) if response is None: logger.error("Error gettings Transmission session ID") return # Parse response if response.status_code == 401: if auth: logger.error("Username and/or password not accepted by Transmission") else: logger.error("Transmission authorization required") return elif response.status_code == 409: sessionid = response.headers['x-transmission-session-id'] if not sessionid: logger.error("Error getting Session ID from Transmission") return # Prepare next request headers = { 'x-transmission-session-id': sessionid } data = { 'method': method, 'arguments': arguments } response = request.request_json(host, method="post", data=json.dumps(data), headers=headers, auth=auth) if not response: logger.error("Error sending torrent to Transmission") return return response
def _update_cache(self): """ Since we call the same url for both info and artwork, we'll update both at the same time """ myDB = db.DBConnection() fanart = False # Since lastfm uses release ids rather than release group ids for albums, we have to do a artist + album search for albums # Exception is when adding albums manually, then we should use release id if self.id_type == 'artist': data = lastfm.request_lastfm("artist.getinfo", mbid=self.id, api_key=LASTFM_API_KEY) # Try with name if not found if not data: dbartist = myDB.action( 'SELECT ArtistName, Type FROM artists WHERE ArtistID=?', [self.id]).fetchone() if dbartist: data = lastfm.request_lastfm( "artist.getinfo", artist=helpers.clean_musicbrainz_name( dbartist['ArtistName']), api_key=LASTFM_API_KEY) if not data: return try: self.info_summary = data['artist']['bio']['summary'] except KeyError: logger.debug('No artist bio summary found') self.info_summary = None try: self.info_content = data['artist']['bio']['content'] except KeyError: logger.debug('No artist bio found') self.info_content = None # 2019 last.fm no longer allows access to artist images, try fanart.tv instead image_url = None thumb_url = None data = request.request_json(FANART_URL + self.id, whitelist_status_code=404, headers={ 'api-key': FANART_PROJECT_KEY, 'client-key': FANART_CLIENT_KEY }) if data.get('artistthumb'): image_url = data['artistthumb'][0]['url'] elif data.get('artistbackground'): image_url = data['artistbackground'][0]['url'] # elif data.get('hdmusiclogo'): # image_url = data['hdmusiclogo'][0]['url'] # fallback to 1st album cover if none of the above elif 'albums' in data: for mbid, art in data.get('albums', dict()).items(): if 'albumcover' in art: image_url = art['albumcover'][0]['url'] break # finally, use 1st album cover from last.fm if image_url: fanart = True thumb_url = image_url else: dbalbum = myDB.action( 'SELECT ArtworkURL, ThumbURL FROM albums WHERE ArtworkURL IS NOT NULL AND ArtistID=?', [self.id]).fetchone() if dbalbum: fanart = True image_url = dbalbum['ArtworkURL'] thumb_url = dbalbum['ThumbURL'] if not image_url: logger.debug( 'No artist image found on fanart.tv for Artist Id: %s', self.id) else: dbalbum = myDB.action( 'SELECT ArtistName, AlbumTitle, ReleaseID, Type FROM albums WHERE AlbumID=?', [self.id]).fetchone() if dbalbum['ReleaseID'] != self.id: data = lastfm.request_lastfm("album.getinfo", mbid=dbalbum['ReleaseID'], api_key=LASTFM_API_KEY) if not data: data = lastfm.request_lastfm( "album.getinfo", artist=helpers.clean_musicbrainz_name( dbalbum['ArtistName']), album=helpers.clean_musicbrainz_name( dbalbum['AlbumTitle']), api_key=LASTFM_API_KEY) else: if dbalbum['Type'] != "part of": data = lastfm.request_lastfm( "album.getinfo", artist=helpers.clean_musicbrainz_name( dbalbum['ArtistName']), album=helpers.clean_musicbrainz_name( dbalbum['AlbumTitle']), api_key=LASTFM_API_KEY) else: # Series, use actual artist for the release-group artist = mb.getArtistForReleaseGroup(self.id) if artist: data = lastfm.request_lastfm( "album.getinfo", artist=helpers.clean_musicbrainz_name(artist), album=helpers.clean_musicbrainz_name( dbalbum['AlbumTitle']), api_key=LASTFM_API_KEY) if not data: return try: self.info_summary = data['album']['wiki']['summary'] except KeyError: logger.debug('No album summary found') self.info_summary = None try: self.info_content = data['album']['wiki']['content'] except KeyError: logger.debug('No album infomation found') self.info_content = None try: image_url = data['album']['image'][-1]['#text'] except KeyError: logger.debug('No album image link found') image_url = None thumb_url = self._get_thumb_url(data) if not thumb_url: logger.debug('No album thumbnail image found') # Save the content & summary to the database no matter what if we've # opened up the url if self.id_type == 'artist': controlValueDict = {"ArtistID": self.id} else: controlValueDict = {"ReleaseGroupID": self.id} newValueDict = { "Summary": self.info_summary, "Content": self.info_content, "LastUpdated": helpers.today() } myDB.upsert("descriptions", newValueDict, controlValueDict) # Save the image URL to the database if image_url: if self.id_type == 'artist': myDB.action('UPDATE artists SET ArtworkURL=? WHERE ArtistID=?', [image_url, self.id]) else: myDB.action('UPDATE albums SET ArtworkURL=? WHERE AlbumID=?', [image_url, self.id]) # Save the thumb URL to the database if thumb_url: if self.id_type == 'artist': myDB.action('UPDATE artists SET ThumbURL=? WHERE ArtistID=?', [thumb_url, self.id]) else: myDB.action('UPDATE albums SET ThumbURL=? WHERE AlbumID=?', [thumb_url, self.id]) # Should we grab the artwork here if we're just grabbing thumbs or # info? Probably not since the files can be quite big if image_url and self.query_type == 'artwork': artwork = request.request_content(image_url, timeout=20) if artwork: # Make sure the artwork dir exists: if not os.path.isdir(self.path_to_art_cache): try: os.makedirs(self.path_to_art_cache) os.chmod(self.path_to_art_cache, int(headphones.CONFIG.FOLDER_PERMISSIONS, 8)) except OSError as e: logger.error( 'Unable to create artwork cache dir. Error: %s', e) self.artwork_errors = True self.artwork_url = image_url # Delete the old stuff for artwork_file in self.artwork_files: try: os.remove(artwork_file) except: logger.error('Error deleting file from the cache: %s', artwork_file) ext = os.path.splitext(image_url)[1] if fanart: artwork_path = os.path.join( self.path_to_art_cache, self.id + '_fanart_' + '.' + helpers.today() + ext) else: artwork_path = os.path.join( self.path_to_art_cache, self.id + '.' + helpers.today() + ext) try: with open(artwork_path, 'wb') as f: f.write(artwork) os.chmod(artwork_path, int(headphones.CONFIG.FILE_PERMISSIONS, 8)) except (OSError, IOError) as e: logger.error('Unable to write to the cache dir: %s', e) self.artwork_errors = True self.artwork_url = image_url # Grab the thumbnail as well if we're getting the full artwork (as long # as it's missing/outdated. if thumb_url and self.query_type in [ 'thumb', 'artwork' ] and not (self.thumb_files and self._is_current(self.thumb_files[0])): if not (self.query_type == 'artwork' and 'fanart' in thumb_url and artwork): artwork = request.request_content(thumb_url, timeout=20) if artwork: # Make sure the artwork dir exists: if not os.path.isdir(self.path_to_art_cache): try: os.makedirs(self.path_to_art_cache) os.chmod(self.path_to_art_cache, int(headphones.CONFIG.FOLDER_PERMISSIONS, 8)) except OSError as e: logger.error( 'Unable to create artwork cache dir. Error: %s' + e) self.thumb_errors = True self.thumb_url = thumb_url # Delete the old stuff for thumb_file in self.thumb_files: try: os.remove(thumb_file) except OSError as e: logger.error('Error deleting file from the cache: %s', thumb_file) ext = os.path.splitext(image_url)[1] if fanart: thumb_path = os.path.join( self.path_to_art_cache, 'T_' + self.id + '_fanart_' + '.' + helpers.today() + ext) else: thumb_path = os.path.join( self.path_to_art_cache, 'T_' + self.id + '.' + helpers.today() + ext) try: if self.id_type != 'artist': with open(thumb_path, 'wb') as f: f.write(artwork) else: # 2019 last.fm no longer allows access to artist images, use the fanart.tv image to create a thumb artwork_thumb = None if 'fanart' in thumb_url: # Create thumb using image resizing service artwork_path = '{0}?{1}'.format( 'http://images.weserv.nl/', urlencode({ 'url': thumb_url.replace('http://', ''), 'w': 300, })) artwork_thumb = request.request_content( artwork_path, timeout=20, whitelist_status_code=404) if artwork_thumb: with open(thumb_path, 'wb') as f: f.write(artwork_thumb) else: with open(thumb_path, 'wb') as f: f.write(artwork) os.chmod(thumb_path, int(headphones.CONFIG.FILE_PERMISSIONS, 8)) except (OSError, IOError) as e: logger.error('Unable to write to the cache dir: %s', e) self.thumb_errors = True self.thumb_url = image_url
def torrentAction(method, arguments): host = headphones.CONFIG.TRANSMISSION_HOST username = headphones.CONFIG.TRANSMISSION_USERNAME password = headphones.CONFIG.TRANSMISSION_PASSWORD if not host.startswith('http'): host = 'http://' + host if host.endswith('/'): host = host[:-1] # Fix the URL. We assume that the user does not point to the RPC endpoint, # so add it if it is missing. parts = list(urlparse.urlparse(host)) if not parts[0] in ("http", "https"): parts[0] = "http" if not parts[2].endswith("/rpc"): parts[2] += "/transmission/rpc" host = urlparse.urlunparse(parts) # Retrieve session id auth = (username, password) if username and password else None response = request.request_response(host, auth=auth, whitelist_status_code=[401, 409]) if response is None: logger.error("Error gettings Transmission session ID") return # Parse response if response.status_code == 401: if auth: logger.error("Username and/or password not accepted by " \ "Transmission") else: logger.error("Transmission authorization required") return elif response.status_code == 409: session_id = response.headers['x-transmission-session-id'] if not session_id: logger.error("Expected a Session ID from Transmission") return # Prepare next request headers = {'x-transmission-session-id': session_id} data = {'method': method, 'arguments': arguments} response = request.request_json(host, method="POST", data=json.dumps(data), headers=headers, auth=auth) print response if not response: logger.error("Error sending torrent to Transmission") return return response
def addTorrent(link): host = headphones.UTORRENT_HOST username = headphones.UTORRENT_USERNAME password = headphones.UTORRENT_PASSWORD label = headphones.UTORRENT_LABEL token = '' if not host.startswith('http'): host = 'http://' + host if host.endswith('/'): host = host[:-1] if host.endswith('/gui'): host = host + '/' else: host = host + '/gui/' # Retrieve session id auth = (username, password) if username and password else None token_request = request.request_response(host + 'token.html', auth=auth) token = re.findall('<div.*?>(.*?)</', token_request.content)[0] guid = token_request.cookies['GUID'] cookies = dict(GUID = guid) if link.startswith("magnet") or link.startswith("http") or link.endswith(".torrent"): params = {'action':'add-url', 's':link, 'token':token} response = request.request_json(host, params=params, auth=auth, cookies=cookies) else: params = {'action':'add-file', 'token':token} files = {'torrent_file':{'music.torrent' : link}} response = request.request_json(host, method="post", params=params, files=files, auth=auth, cookies=cookies) if not response: logger.error("Error sending torrent to uTorrent") return if link.startswith('magnet'): tor_hash = re.findall('urn:btih:([\w]{32,40})', link)[0] if len(tor_hash) == 32: tor_hash = b16encode(b32decode(tor_hash)).lower() else: info = bdecode(link.content)["info"] tor_hash = sha1(bencode(info)).hexdigest() params = {'action':'setprops', 'hash':tor_hash,'s':'label', 'v':label, 'token':token} response = request.request_json(host, params=params, auth=auth, cookies=cookies) if not response: logger.error("Error setting torrent label in uTorrent") return # folder info can probably be cleaned up with getprops folder = None params = {'list':'1', 'token':token} response = request.request_json(host, params=params, auth=auth, cookies=cookies) if not response: logger.error("Error getting torrent information from uTorrent") return for torrent in response['torrents']: folder = os.path.basename(torrent[26]) return folder