@@ -975,13 +975,9 @@ def __init__(self, jd, device_dict):
975975 self .__direct_connection_consecutive_failures = 0
976976
977977 def __refresh_direct_connections (self ):
978- response = self .myjd .request_api ("/device/getDirectConnectionInfos" ,
979- "POST" , None , self .__action_url ())
980- if response is not None \
981- and 'data' in response \
982- and 'infos' in response ["data" ] \
983- and len (response ["data" ]["infos" ]) != 0 :
984- self .__update_direct_connections (response ["data" ]["infos" ])
978+ infos = self .myjd .get_direct_Connection_infos (self .__action_url ())
979+ if infos :
980+ self .__update_direct_connections (infos )
985981
986982 def __update_direct_connections (self , direct_info ):
987983 """
@@ -1074,7 +1070,10 @@ def action(self, path, params=(), http_action="POST"):
10741070 return response ['data' ]
10751071
10761072 def __action_url (self ):
1077- return "/t_" + self .myjd .get_session_token () + "_" + self .device_id
1073+ if self .myjd .get_session_token ():
1074+ return "/t_" + self .myjd .get_session_token () + "_" + self .device_id
1075+ else :
1076+ return None
10781077
10791078
10801079class Myjdapi :
@@ -1091,6 +1090,7 @@ def __init__(self):
10911090 self .__request_id = int (time .time () * 1000 )
10921091 self .__api_url = "https://api.jdownloader.org"
10931092 self .__app_key = "http://git.io/vmcsk"
1093+ self .__content_type = "application/aesjson-jd; charset=utf-8"
10941094 self .__api_version = 1
10951095 self .__devices = None
10961096 self .__login_secret = None
@@ -1100,6 +1100,8 @@ def __init__(self):
11001100 self .__server_encryption_token = None
11011101 self .__device_encryption_token = None
11021102 self .__connected = False
1103+ self .__dict_as_str = True
1104+ self .__timeout = 3
11031105
11041106 def get_session_token (self ):
11051107 return self .__session_token
@@ -1137,6 +1139,8 @@ def __update_encryption_tokens(self):
11371139 Updates the server_encryption_token and device_encryption_token
11381140
11391141 """
1142+ if self .__connected and not self .__session_token :
1143+ return
11401144 if self .__server_encryption_token is None :
11411145 old_token = self .__login_secret
11421146 else :
@@ -1166,11 +1170,14 @@ def __decrypt(self, secret_token, data):
11661170 :param secret_token:
11671171 :param data:
11681172 """
1169- init_vector = secret_token [:len (secret_token ) // 2 ]
1170- key = secret_token [len (secret_token ) // 2 :]
1171- decryptor = AES .new (key , AES .MODE_CBC , init_vector )
1172- decrypted_data = UNPAD (decryptor .decrypt (base64 .b64decode (data )))
1173- return decrypted_data
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 :
1180+ return data .encode ('utf-8' )
11741181
11751182 def __encrypt (self , secret_token , data ):
11761183 """
@@ -1179,12 +1186,15 @@ def __encrypt(self, secret_token, data):
11791186 :param secret_token:
11801187 :param data:
11811188 """
1182- data = PAD (data .encode ('utf-8' ))
1183- init_vector = secret_token [:len (secret_token ) // 2 ]
1184- key = secret_token [len (secret_token ) // 2 :]
1185- encryptor = AES .new (key , AES .MODE_CBC , init_vector )
1186- encrypted_data = base64 .b64encode (encryptor .encrypt (data ))
1187- return encrypted_data .decode ('utf-8' )
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 :
1197+ return data
11881198
11891199 def update_request_id (self ):
11901200 """
@@ -1208,6 +1218,7 @@ def connect(self, email, password):
12081218 self .__server_encryption_token = None
12091219 self .__device_encryption_token = None
12101220 self .__devices = None
1221+ self .__device_connection = None
12111222 self .__connected = False
12121223
12131224 self .__login_secret = self .__secret_create (email , password , "server" )
@@ -1223,13 +1234,54 @@ def connect(self, email, password):
12231234 self .update_devices ()
12241235 return response
12251236
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
1239+
1240+ :param ip: ip of the divice
1241+ :param port: port of the divice
1242+ :returns: boolean -- True if succesful, False if there was any error.
1243+
1244+ """
1245+ self .update_request_id ()
1246+ self .__login_secret = None
1247+ self .__device_secret = None
1248+ self .__session_token = None
1249+ self .__regain_token = None
1250+ self .__server_encryption_token = None
1251+ self .__device_encryption_token = None
1252+ self .__device_connection = {"ip" :ip ,"port" :port ,"type" :_type }
1253+ self .__dict_as_str = False
1254+ self .__devices = [{
1255+ 'name' : ip ,
1256+ 'id' : 'direct' ,
1257+ 'type' : 'jd'
1258+ }]
1259+ self .__api_url = "http://" + ip + ":" + str (port )
1260+ 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+ response = self .request_api ("/device/ping" , "GET" , [])['data' ]
1270+ self .__connected = response
1271+ self .update_request_id ()
1272+ self .__session_token = None
1273+ self .__regain_token = None
1274+ return response
1275+ 12261276 def reconnect (self ):
12271277 """
12281278 Reestablish connection to API.
12291279
12301280 :returns: boolean -- True if successful, False if there was any error.
12311281
12321282 """
1283+ if self .__connected and (not self .__session_token or not self .__regain_token ):
1284+ return True
12331285 response = self .request_api ("/my/reconnect" , "GET" ,
12341286 [("sessiontoken" , self .__session_token ),
12351287 ("regaintoken" , self .__regain_token )])
@@ -1246,7 +1298,10 @@ def disconnect(self):
12461298 :returns: boolean -- True if successful, False if there was any error.
12471299
12481300 """
1249- response = self .request_api ("/my/disconnect" , "GET" ,
1301+ if self .__connected and not self .__session_token :
1302+ response = True
1303+ else :
1304+ response = self .request_api ("/my/disconnect" , "GET" ,
12501305 [("sessiontoken" , self .__session_token )])
12511306 self .update_request_id ()
12521307 self .__login_secret = None
@@ -1265,6 +1320,8 @@ def update_devices(self):
12651320
12661321 :returns: boolean -- True if successful, False if there was any error.
12671322 """
1323+ if self .__connected and not self .__session_token :
1324+ return
12681325 response = self .request_api ("/my/listdevices" , "GET" ,
12691326 [("sessiontoken" , self .__session_token )])
12701327 self .update_request_id ()
@@ -1303,6 +1360,20 @@ def get_device(self, device_name=None, device_id=None):
13031360 return Jddevice (self , device )
13041361 raise (MYJDDeviceNotFoundException ("Device not found\n " ))
13051362
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
1376+ 13061377 def request_api (self ,
13071378 path ,
13081379 http_method = "GET" ,
@@ -1332,27 +1403,28 @@ def request_api(self,
13321403 else :
13331404 query += ["&%s=%s" % (param [0 ], param [1 ])]
13341405 query += ["rid=" + str (self .__request_id )]
1335- if self .__server_encryption_token is None :
1336- query += [
1337- "signature=" \
1338- + str (self .__signature_create (self .__login_secret ,
1339- query [0 ] + "&" .join (query [1 :])))
1340- ]
1341- else :
1342- query += [
1343- "signature=" \
1344- + str (self .__signature_create (self .__server_encryption_token ,
1345- query [0 ] + "&" .join (query [1 :])))
1346- ]
1406+ if not (self .__connected and not self .__session_token ):
1407+ if self .__server_encryption_token is None :
1408+ query += [
1409+ "signature=" \
1410+ + str (self .__signature_create (self .__login_secret ,
1411+ query [0 ] + "&" .join (query [1 :])))
1412+ ]
1413+ else :
1414+ query += [
1415+ "signature=" \
1416+ + str (self .__signature_create (self .__server_encryption_token ,
1417+ query [0 ] + "&" .join (query [1 :])))
1418+ ]
13471419 query = query [0 ] + "&" .join (query [1 :])
1348- encrypted_response = requests .get (api + query , timeout = 3 )
1420+ encrypted_response = requests .get (api + query , timeout = self . __timeout )
13491421 else :
13501422 params_request = []
13511423 if params is not None :
13521424 for param in params :
1353- if isinstance (param , str ) or isinstance (param , list ):
1425+ if ( isinstance ( param , dict ) and not self . __dict_as_str ) or isinstance (param , str ) or isinstance (param , list ):
13541426 params_request += [param ]
1355- elif isinstance (param , dict ) or isinstance (param , bool ):
1427+ elif ( isinstance (param , dict ) and self . __dict_as_str ) or isinstance (param , bool ):
13561428 params_request += [json .dumps (param )]
13571429 else :
13581430 params_request += [str (param )]
@@ -1376,10 +1448,10 @@ def request_api(self,
13761448 encrypted_response = requests .post (
13771449 request_url ,
13781450 headers = {
1379- "Content-Type" : "application/aesjson-jd; charset=utf-8"
1451+ "Content-Type" : self . __content_type
13801452 },
13811453 data = encrypted_data ,
1382- timeout = 3 )
1454+ timeout = self . __timeout )
13831455 except requests .exceptions .RequestException as e :
13841456 return None
13851457 if encrypted_response .status_code != 200 :
@@ -1410,8 +1482,9 @@ def request_api(self,
14101482 response = self .__decrypt (self .__device_encryption_token ,
14111483 encrypted_response .text )
14121484 jsondata = json .loads (response .decode ('utf-8' ))
1413- if jsondata ['rid' ] != self .__request_id :
1414- self .update_request_id ()
1415- return None
1485+ if 'rid' in jsondata .keys ():
1486+ if jsondata ['rid' ] != self .__request_id :
1487+ self .update_request_id ()
1488+ return None
14161489 self .update_request_id ()
14171490 return jsondata
0 commit comments