def torrent_add_data( self, torrent_data, download_dir = None, filename = "default.torrent" ): prev_dir = self._handle_download_dir( download_dir ) res = self.do_action( "add-file", data = self._create_torrent_upload( torrent_data, filename ) ) self._handle_prev_dir( prev_dir ) if "error" in res: raise utorrent.uTorrentError( res["error"] ) return self.get_info_hash( torrent_data )
def utorrent( self, api = None ): if api == "linux": return utorrent.uTorrent.LinuxServer( self ) elif api == "desktop": return utorrent.uTorrent.Desktop( self ) elif api == "falcon": return utorrent.uTorrent.Falcon( self ) else: # auto-detect try: ver = utorrent.uTorrent.Version( self.do_action( "getversion", retry = False ) ) except utorrent.uTorrentError as e: if e.args[0] == "invalid request": # windows desktop uTorrent client ver = utorrent.uTorrent.Version.detect_from_settings( self.do_action( "getsettings" ) ) else: raise e if ver.product == "server": return utorrent.uTorrent.LinuxServer( self, ver ) elif ver.product == "desktop" or ver.product == "PRODUCT_CODE": if ver.major == 3: return utorrent.uTorrent.Falcon( self, ver ) else: return utorrent.uTorrent.Desktop( self, ver ) else: print(ver.product) raise utorrent.uTorrentError( "Unsupported WebUI API" )
def _handle_download_dir( self, download_dir ): out = None if download_dir: if "dir_active_download" not in self.settings_get( ): raise utorrent.uTorrentError( "A default directory MUST be set and enabled in uTorrent to use this option.") out = self.settings_get( )["dir_active_download"] if not self._pathmodule.isabs( download_dir ): download_dir = out + self._pathmodule.sep + download_dir self.settings_set( { "dir_active_download": download_dir } ) return out
def torrent_add_url( self, url, download_dir = None ): prev_dir = self._handle_download_dir( download_dir ) res = self.do_action( "add-url", { "s": url } ) self._handle_prev_dir( prev_dir ) if "error" in res: raise utorrent.uTorrentError( res["error"] ) if url[0:7] == "magnet:": m = re.search( "urn:btih:([0-9A-F]{40})", url, re.IGNORECASE ) if m: return m.group( 1 ).upper( ) return None
def torrent_add_url(self, url, download_dir=None): prev_dir = self._handle_download_dir(download_dir) res = self.do_action("add-url", {"s": url}) self._handle_prev_dir(prev_dir) if "error" in res: raise utorrent.uTorrentError(res["error"]) if url[0:7] == "magnet:": m = re.search("urn:btih:([0-9A-F]{40})", url, re.IGNORECASE) if m: return m.group(1).upper() return None
def torrent_add_data(self, torrent_data, download_dir=None, filename="default.torrent"): prev_dir = self._handle_download_dir(download_dir) res = self.do_action("add-file", data=self._create_torrent_upload( torrent_data, filename)) self._handle_prev_dir(prev_dir) if "error" in res: raise utorrent.uTorrentError(res["error"]) return self.get_info_hash(torrent_data)
def _handle_download_dir(self, download_dir): out = None if download_dir: if "dir_active_download" not in self.settings_get(): raise utorrent.uTorrentError( "A default directory MUST be set and enabled in uTorrent to use this option." ) out = self.settings_get()["dir_active_download"] if not self._pathmodule.isabs(download_dir): download_dir = out + self._pathmodule.sep + download_dir self.settings_set({"dir_active_download": download_dir}) return out
def _make_request( self, loc, headers, data = None, retry = True ): last_e = None utserver_retry = False retries = 0 max_retries = self._retry_max if retry else 1 try: while retries < max_retries or utserver_retry: try: self._request.data = data self._connection.request( self._request.get_method( ), self._request.selector + loc, self._request.data, headers ) resp = self._connection.getresponse( ) if resp.status == 400: last_e = utorrent.uTorrentError( resp.read( ).decode( "utf8" ).strip( ) ) # if uTorrent server alpha is bound to the same port as WebUI then it will respond with "invalid request" to the first request in the connection # apparently this is no longer the case, TODO: remove this hack if ( not self._utorrent or type( self._utorrent ) == utorrent.uTorrent.LinuxServer ) and not utserver_retry: utserver_retry = True continue raise last_e elif resp.status == 404 or resp.status == 401: raise utorrent.uTorrentError( "Request {}: {}".format( loc, resp.reason ) ) elif resp.status != 200 and resp.status != 206: raise utorrent.uTorrentError( "{}: {}".format( resp.reason, resp.status ) ) self._cookies.extract_cookies( resp, self._request ) if len( self._cookies ) > 0: self._request.add_header( "Cookie", "; ".join( ["{}={}".format( utorrent._url_quote( c.name ), utorrent._url_quote( c.value ) ) for c in self._cookies] ) ) return resp # retry when utorrent returns bad data except ( http.client.CannotSendRequest, http.client.BadStatusLine ) as e: last_e = e self._connection.close( ) # name resolution failed except socket.gaierror as e: raise utorrent.uTorrentError( e.strerror ) # socket errors except socket.error as e: # retry on timeout if str( e ) == "timed out": # some peculiar handling for timeout error last_e = utorrent.uTorrentError( "Timeout after {} tries".format( max_retries ) ) self._connection.close( ) # retry after pause on specific windows errors elif e.errno == 10053 or e.errno == 10054: # Windows specific socket errors: # 10053 - An established connection was aborted by the software in your host machine # 10054 - An existing connection was forcibly closed by the remote host last_e = e self._connection.close( ) time.sleep( 2 ) elif e.errno == errno.ECONNREFUSED or e.errno == errno.ECONNRESET or errno == errno.EHOSTUNREACH: raise utorrent.uTorrentError( e.strerror ) else: raise e retries += 1 if last_e: raise last_e except Exception as e: self._connection.close( ) raise e return None
def _get_hashes( self, torrents ): if not utorrent.is_list_type( torrents ): torrents = ( torrents, ) out = [] for t in torrents: if isinstance( t, self._TorrentClass ): hsh = t.hash_code elif isinstance( t, str ): hsh = t else: raise utorrent.uTorrentError( "Hash designation only supported via Torrent class or string" ) self.check_hash( hsh ) out.append( hsh ) return out
def _get_hashes(self, torrents): if not utorrent.is_list_type(torrents): torrents = (torrents, ) out = [] for t in torrents: if isinstance(t, self._TorrentClass): hsh = t.hash_code elif isinstance(t, str): hsh = t else: raise utorrent.uTorrentError( "Hash designation only supported via Torrent class or string" ) self.check_hash(hsh) out.append(hsh) return out
def __init__( self, res ): if "version" in res: # server returns full data self.product = res["version"]["product_code"] self.major = res["version"]["major_version"] self.middle = 0 self.minor = res["version"]["minor_version"] self.build = res["build"] self.engine = res["version"]["engine_version"] self.ui = res["version"]["ui_version"] date = res["version"]["version_date"].split( " " ) self.date = datetime.datetime( *map( int, date[0].split( "-" ) + date[1].split( ":" ) ) ) self.user_agent = res["version"]["user_agent"] self.peer_id = res["version"]["peer_id"] self.device_id = res["version"]["device_id"] elif "build" in res: # fill some partially made up values as desktop client doesn't provide full info, only build self.product = "desktop" self.build = self.engine = self.ui = res["build"] else: raise utorrent.uTorrentError( "Cannot detect version from the supplied server response" )
def __init__(self, res): if "version" in res: # server returns full data self.product = res["version"]["product_code"] self.major = res["version"]["major_version"] self.middle = 0 self.minor = res["version"]["minor_version"] self.build = res["build"] self.engine = res["version"]["engine_version"] self.ui = res["version"]["ui_version"] date = res["version"]["version_date"].split(" ") self.date = datetime.datetime( *map(int, date[0].split("-") + date[1].split(":"))) self.user_agent = res["version"]["user_agent"] self.peer_id = res["version"]["peer_id"] self.device_id = res["version"]["device_id"] elif "build" in res: # fill some partially made up values as desktop client doesn't provide full info, only build self.product = "desktop" self.build = self.engine = self.ui = res["build"] else: raise utorrent.uTorrentError( "Cannot detect version from the supplied server response")
def check_hash( cls, torrent_hash ): if not cls.is_hash( torrent_hash ): raise utorrent.uTorrentError( "Incorrect hash: {}".format( torrent_hash ) )
if opts.verbose: torrs = utorrent.resolve_torrent_hashes(args, torr_list) else: torrs = args print_console("Pausing " + ", ".join(torrs) + "...") utorrent.torrent_pause(args) elif opts.action == "torrent_recheck": torr_list = utorrent.torrent_list() if opts.all: if opts.force: args = torr_list.keys() print_console("Rechecking all torrents...") else: raise uTorrentError( "Refusing to recheck all torrents! Please specify --force to override" ) else: if opts.verbose: torrs = utorrent.resolve_torrent_hashes(args, torr_list) else: torrs = args print_console("Rechecking " + ", ".join(torrs) + "...") for hsh in args: if hsh in torr_list: torr = torr_list[hsh] torr.stop() torr.recheck() if (torr.status.started and not torr.status.paused) or torr.status.error: torr.start(not (torr.status.queued or torr.status.error))
else: if opts.verbose: torrs = utorrent.resolve_torrent_hashes( args, torr_list ) else: torrs = args print_console( "Pausing " + ", ".join( torrs ) + "..." ) utorrent.torrent_pause( args ) elif opts.action == "torrent_recheck": torr_list = utorrent.torrent_list( ) if opts.all: if opts.force: args = torr_list.keys( ) print_console( "Rechecking all torrents..." ) else: raise uTorrentError( "Refusing to recheck all torrents! Please specify --force to override" ) else: if opts.verbose: torrs = utorrent.resolve_torrent_hashes( args, torr_list ) else: torrs = args print_console( "Rechecking " + ", ".join( torrs ) + "..." ) for hsh in args: if hsh in torr_list: torr = torr_list[hsh] torr.stop( ) torr.recheck( ) if ( torr.status.started and not torr.status.paused ) or torr.status.error: torr.start( not ( torr.status.queued or torr.status.error ) ) elif opts.action == "torrent_remove":
def check_hash(cls, torrent_hash): if not cls.is_hash(torrent_hash): raise utorrent.uTorrentError( "Incorrect hash: {}".format(torrent_hash))
def _fetch_token( self ): data = self._get_data( "gui/token.html" ) match = re.search( "<div .*?id='token'.*?>(.+?)</div>", data ) if match is None: raise utorrent.uTorrentError( "Can't fetch security token" ) self._token = match.group( 1 )