@@ -966,7 +966,6 @@ def __init__(self, jd, device_dict):
966966 self .extensions = Extension (self )
967967 self .dialogs = Dialog (self )
968968 self .update = Update (self )
969- self .jd = Jd (self )
970969 self .system = System (self )
971970 self .__direct_connection_info = None
972971 self .__refresh_direct_connections ()
@@ -975,9 +974,15 @@ def __init__(self, jd, device_dict):
975974 self .__direct_connection_consecutive_failures = 0
976975
977976 def __refresh_direct_connections (self ):
978- infos = self .myjd .get_direct_Connection_infos (self .__action_url ())
979- if infos :
980- self .__update_direct_connections (infos )
977+ if self .myjd .get_connection_type () == "remoteapi" :
978+ return
979+ response = self .myjd .request_api ("/device/getDirectConnectionInfos" ,
980+ "POST" , None , self .__action_url ())
981+ if response is not None \
982+ and 'data' in response \
983+ and 'infos' in response ["data" ] \
984+ and len (response ["data" ]["infos" ]) != 0 :
985+ self .__update_direct_connections (response ["data" ]["infos" ])
981986
982987 def __update_direct_connections (self , direct_info ):
983988 """
@@ -1017,7 +1022,11 @@ def action(self, path, params=(), http_action="POST"):
10171022 /example?param1=ex¶m2=ex2 [("param1","ex"),("param2","ex2")]
10181023 :param postparams: List of Params that are send in the post.
10191024 """
1020- action_url = self .__action_url ()
1025+ 1026+ if self .myjd .get_connection_type () == "remoteapi" :
1027+ action_url = None
1028+ else :
1029+ action_url = self .__action_url ()
10211030 if not self .__direct_connection_enabled or self .__direct_connection_info is None \
10221031 or time .time () < self .__direct_connection_cooldown :
10231032 # No direct connection available, we use My.JDownloader api.
@@ -1070,11 +1079,7 @@ def action(self, path, params=(), http_action="POST"):
10701079 return response ['data' ]
10711080
10721081 def __action_url (self ):
1073- if self .myjd .get_session_token ():
1074- return "/t_" + self .myjd .get_session_token () + "_" + self .device_id
1075- else :
1076- return None
1077- 1082+ return "/t_" + self .myjd .get_session_token () + "_" + self .device_id
10781083
10791084class Myjdapi :
10801085 """
@@ -1100,8 +1105,8 @@ def __init__(self):
11001105 self .__server_encryption_token = None
11011106 self .__device_encryption_token = None
11021107 self .__connected = False
1103- self .__dict_as_str = True
1104- self .__timeout = 3
1108+ self .__timeout = 3
1109+ self .__connection_type = "myjd" # myjd -> MyJdownloader API, remoteapi -> Deprecated Direct RemoteAPI connection.
11051110
11061111 def get_session_token (self ):
11071112 return self .__session_token
@@ -1139,7 +1144,7 @@ def __update_encryption_tokens(self):
11391144 Updates the server_encryption_token and device_encryption_token
11401145
11411146 """
1142- if self .__connected and not self . __session_token :
1147+ if self .__connection_type == "remoteapi" :
11431148 return
11441149 if self .__server_encryption_token is None :
11451150 old_token = self .__login_secret
@@ -1170,14 +1175,13 @@ def __decrypt(self, secret_token, data):
11701175 :param secret_token:
11711176 :param data:
11721177 """
1173- if secret_token :
1174- init_vector = secret_token [:len (secret_token ) // 2 ]
1175- key = secret_token [len (secret_token ) // 2 :]
1176- decryptor = AES .new (key , AES .MODE_CBC , init_vector )
1177- decrypted_data = UNPAD (decryptor .decrypt (base64 .b64decode (data )))
1178- return decrypted_data
1179- else :
1178+ if self .__connection_type == "remoteapi" :
11801179 return data .encode ('utf-8' )
1180+ init_vector = secret_token [:len (secret_token ) // 2 ]
1181+ key = secret_token [len (secret_token ) // 2 :]
1182+ decryptor = AES .new (key , AES .MODE_CBC , init_vector )
1183+ decrypted_data = UNPAD (decryptor .decrypt (base64 .b64decode (data )))
1184+ return decrypted_data
11811185
11821186 def __encrypt (self , secret_token , data ):
11831187 """
@@ -1186,15 +1190,14 @@ def __encrypt(self, secret_token, data):
11861190 :param secret_token:
11871191 :param data:
11881192 """
1189- if secret_token :
1190- data = PAD (data .encode ('utf-8' ))
1191- init_vector = secret_token [:len (secret_token ) // 2 ]
1192- key = secret_token [len (secret_token ) // 2 :]
1193- encryptor = AES .new (key , AES .MODE_CBC , init_vector )
1194- encrypted_data = base64 .b64encode (encryptor .encrypt (data ))
1195- return encrypted_data .decode ('utf-8' )
1196- else :
1193+ if self .__connection_type == "remoteapi" :
11971194 return data
1195+ data = PAD (data .encode ('utf-8' ))
1196+ init_vector = secret_token [:len (secret_token ) // 2 ]
1197+ key = secret_token [len (secret_token ) // 2 :]
1198+ encryptor = AES .new (key , AES .MODE_CBC , init_vector )
1199+ encrypted_data = base64 .b64encode (encryptor .encrypt (data ))
1200+ return encrypted_data .decode ('utf-8' )
11981201
11991202 def update_request_id (self ):
12001203 """
@@ -1218,8 +1221,8 @@ def connect(self, email, password):
12181221 self .__server_encryption_token = None
12191222 self .__device_encryption_token = None
12201223 self .__devices = None
1221- self .__device_connection = None
12221224 self .__connected = False
1225+ self .__connection_type = "myjd"
12231226
12241227 self .__login_secret = self .__secret_create (email , password , "server" )
12251228 self .__device_secret = self .__secret_create (email , password , "device" )
@@ -1234,43 +1237,40 @@ def connect(self, email, password):
12341237 self .update_devices ()
12351238 return response
12361239
1237- def connect_device (self , ip , port , _type = 'jd' , username = None , password = None , timeout = None ):
1238- """Establish a direct connection to api of a device
1240+ def direct_connect (self , ip , port = 3128 , timeout = 3 ):
1241+ """
1242+ Direct connect to a single device/app instance using the deprecated RemoteAPI.
1243+ This RemoteAPI has to be enabled on JDownloader beforehand.
1244+ Beaware this connection is not authenticated nor encrypted, so do not enable
1245+ it publicly.
12391246
1240- :param ip: ip of the divice
1241- :param port: port of the divice
1247+ :param ip: ip of the device
1248+ :param port: port of the device, 3128 by default.
1249+ :param port: optional timeout of the connection, 3 seconds by default.
12421250 :returns: boolean -- True if succesful, False if there was any error.
12431251
12441252 """
12451253 self .update_request_id ()
1254+ # This direct connection doesn't use auth nor encryption so all secrets and tokens are invalid.
12461255 self .__login_secret = None
12471256 self .__device_secret = None
12481257 self .__session_token = None
12491258 self .__regain_token = None
12501259 self .__server_encryption_token = None
12511260 self .__device_encryption_token = None
1252- self .__device_connection = {"ip" :ip ,"port" :port ,"type" :_type }
1253- self .__dict_as_str = False
12541261 self .__devices = [{
12551262 'name' : ip ,
12561263 'id' : 'direct' ,
12571264 'type' : 'jd'
12581265 }]
1266+ self .__connection_type = "remoteapi"
12591267 self .__api_url = "http://" + ip + ":" + str (port )
12601268 self .__content_type = "application/json; charset=utf-8"
1261- self .__login_secret = None
1262- if username and password :
1263- self .__device_secret = self .__secret_create (username , password , "device" )
1264- else :
1265- self .__device_secret = None
1266- if not (timeout is None ):
1267- self .__timeout = timeout
1268- self .__connected = True
1269+ self .__timeout = timeout
1270+ self .__connected = True # Set as already connected to use the request_api to ping the instance. Will set correct after that if the connection works.
12691271 response = self .request_api ("/device/ping" , "GET" , [])['data' ]
12701272 self .__connected = response
12711273 self .update_request_id ()
1272- self .__session_token = None
1273- self .__regain_token = None
12741274 return response
12751275
12761276 def reconnect (self ):
@@ -1280,8 +1280,9 @@ def reconnect(self):
12801280 :returns: boolean -- True if successful, False if there was any error.
12811281
12821282 """
1283- if self .__connected and ( not self . __session_token or not self . __regain_token ) :
1283+ if self .__connection_type == "remoteapi" :
12841284 return True
1285+ 12851286 response = self .request_api ("/my/reconnect" , "GET" ,
12861287 [("sessiontoken" , self .__session_token ),
12871288 ("regaintoken" , self .__regain_token )])
@@ -1298,7 +1299,7 @@ def disconnect(self):
12981299 :returns: boolean -- True if successful, False if there was any error.
12991300
13001301 """
1301- if self .__connected and not self . __session_token :
1302+ if self .__connection_type == "remoteapi" :
13021303 response = True
13031304 else :
13041305 response = self .request_api ("/my/disconnect" , "GET" ,
@@ -1320,7 +1321,7 @@ def update_devices(self):
13201321
13211322 :returns: boolean -- True if successful, False if there was any error.
13221323 """
1323- if self .__connected and not self . __session_token :
1324+ if self .__connection_type == "remoteapi" :
13241325 return
13251326 response = self .request_api ("/my/listdevices" , "GET" ,
13261327 [("sessiontoken" , self .__session_token )])
@@ -1358,21 +1359,10 @@ def get_device(self, device_name=None, device_id=None):
13581359 for device in self .__devices :
13591360 if device ["name" ] == device_name :
13601361 return Jddevice (self , device )
1362+ elif len (self .__devices ) > 0 :
1363+ return Jddevice (self , self .__devices [0 ])
13611364 raise (MYJDDeviceNotFoundException ("Device not found\n " ))
13621365
1363- def get_direct_Connection_infos (self ,action_url ):
1364- if self .__connected and not self .__session_token :
1365- return [self .__device_connection ]
1366- else :
1367- response = self .request_api ("/device/getDirectConnectionInfos" ,
1368- "POST" , None , action_url )
1369- if response is not None \
1370- and 'data' in response \
1371- and 'infos' in response ["data" ] \
1372- and len (response ["data" ]["infos" ]) != 0 :
1373- return response ["data" ]["infos" ]
1374- else :
1375- return None
13761366
13771367 def request_api (self ,
13781368 path ,
@@ -1403,8 +1393,8 @@ def request_api(self,
14031393 else :
14041394 query += ["&%s=%s" % (param [0 ], param [1 ])]
14051395 query += ["rid=" + str (self .__request_id )]
1406- if not ( self .__connected and not self . __session_token ) :
1407- if self .__server_encryption_token is None :
1396+ if self .__connection_type == "myjd" :
1397+ if self .__server_encryption_token is None :# Requests pre-auth.
14081398 query += [
14091399 "signature=" \
14101400 + str (self .__signature_create (self .__login_secret ,
@@ -1419,19 +1409,10 @@ def request_api(self,
14191409 query = query [0 ] + "&" .join (query [1 :])
14201410 encrypted_response = requests .get (api + query , timeout = self .__timeout )
14211411 else :
1422- params_request = []
1423- if params is not None :
1424- for param in params :
1425- if (isinstance (param , dict ) and not self .__dict_as_str ) or isinstance (param , str ) or isinstance (param , list ):
1426- params_request += [param ]
1427- elif (isinstance (param , dict ) and self .__dict_as_str ) or isinstance (param , bool ):
1428- params_request += [json .dumps (param )]
1429- else :
1430- params_request += [str (param )]
14311412 params_request = {
14321413 "apiVer" : self .__api_version ,
14331414 "url" : path ,
1434- "params" : params_request ,
1415+ "params" : self . __adapt_params_for_request ( params ) ,
14351416 "rid" : self .__request_id
14361417 }
14371418 data = json .dumps (params_request )
@@ -1488,3 +1469,26 @@ def request_api(self,
14881469 return None
14891470 self .update_request_id ()
14901471 return jsondata
1472+ 1473+ def get_connection_type (self ):
1474+ return self .__connection_type
1475+ 1476+ def __adapt_params_for_request (self , params ):
1477+ if params is None :
1478+ return None
1479+ params_request = []
1480+ for param in params :
1481+ if isinstance (param , str ):
1482+ params_request += [param ]
1483+ elif isinstance (param , list ):
1484+ params_request += [self .__adapt_params_for_request (param )]
1485+ elif isinstance (param , dict ) and self .__connection_type == "remoteapi" :
1486+ params_request += [param ]
1487+ elif isinstance (param , dict ):
1488+ params_request += [json .dumps (param )]
1489+ elif isinstance (param , bool ) or isinstance (param , object ):
1490+ params_request += [json .dumps (param )]
1491+ else :
1492+ params_request += [str (param )]
1493+ return params_request
1494+
0 commit comments