@@ -975,13 +975,9 @@ def __init__(self, jd, device_dict):
975
975
self .__direct_connection_consecutive_failures = 0
976
976
977
977
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 )
985
981
986
982
def __update_direct_connections (self , direct_info ):
987
983
"""
@@ -1074,7 +1070,10 @@ def action(self, path, params=(), http_action="POST"):
1074
1070
return response ['data' ]
1075
1071
1076
1072
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
1078
1077
1079
1078
1080
1079
class Myjdapi :
@@ -1091,6 +1090,7 @@ def __init__(self):
1091
1090
self .__request_id = int (time .time () * 1000 )
1092
1091
self .__api_url = "https://api.jdownloader.org"
1093
1092
self .__app_key = "http://git.io/vmcsk"
1093
+ self .__content_type = "application/aesjson-jd; charset=utf-8"
1094
1094
self .__api_version = 1
1095
1095
self .__devices = None
1096
1096
self .__login_secret = None
@@ -1100,6 +1100,8 @@ def __init__(self):
1100
1100
self .__server_encryption_token = None
1101
1101
self .__device_encryption_token = None
1102
1102
self .__connected = False
1103
+ self .__dict_as_str = True
1104
+ self .__timeout = 3
1103
1105
1104
1106
def get_session_token (self ):
1105
1107
return self .__session_token
@@ -1137,6 +1139,8 @@ def __update_encryption_tokens(self):
1137
1139
Updates the server_encryption_token and device_encryption_token
1138
1140
1139
1141
"""
1142
+ if self .__connected and not self .__session_token :
1143
+ return
1140
1144
if self .__server_encryption_token is None :
1141
1145
old_token = self .__login_secret
1142
1146
else :
@@ -1166,11 +1170,14 @@ def __decrypt(self, secret_token, data):
1166
1170
:param secret_token:
1167
1171
:param data:
1168
1172
"""
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' )
1174
1181
1175
1182
def __encrypt (self , secret_token , data ):
1176
1183
"""
@@ -1179,12 +1186,15 @@ def __encrypt(self, secret_token, data):
1179
1186
:param secret_token:
1180
1187
:param data:
1181
1188
"""
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
1188
1198
1189
1199
def update_request_id (self ):
1190
1200
"""
@@ -1208,6 +1218,7 @@ def connect(self, email, password):
1208
1218
self .__server_encryption_token = None
1209
1219
self .__device_encryption_token = None
1210
1220
self .__devices = None
1221
+ self .__device_connection = None
1211
1222
self .__connected = False
1212
1223
1213
1224
self .__login_secret = self .__secret_create (email , password , "server" )
@@ -1223,13 +1234,54 @@ def connect(self, email, password):
1223
1234
self .update_devices ()
1224
1235
return response
1225
1236
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
+
1226
1276
def reconnect (self ):
1227
1277
"""
1228
1278
Reestablish connection to API.
1229
1279
1230
1280
:returns: boolean -- True if successful, False if there was any error.
1231
1281
1232
1282
"""
1283
+ if self .__connected and (not self .__session_token or not self .__regain_token ):
1284
+ return True
1233
1285
response = self .request_api ("/my/reconnect" , "GET" ,
1234
1286
[("sessiontoken" , self .__session_token ),
1235
1287
("regaintoken" , self .__regain_token )])
@@ -1246,7 +1298,10 @@ def disconnect(self):
1246
1298
:returns: boolean -- True if successful, False if there was any error.
1247
1299
1248
1300
"""
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" ,
1250
1305
[("sessiontoken" , self .__session_token )])
1251
1306
self .update_request_id ()
1252
1307
self .__login_secret = None
@@ -1265,6 +1320,8 @@ def update_devices(self):
1265
1320
1266
1321
:returns: boolean -- True if successful, False if there was any error.
1267
1322
"""
1323
+ if self .__connected and not self .__session_token :
1324
+ return
1268
1325
response = self .request_api ("/my/listdevices" , "GET" ,
1269
1326
[("sessiontoken" , self .__session_token )])
1270
1327
self .update_request_id ()
@@ -1303,6 +1360,20 @@ def get_device(self, device_name=None, device_id=None):
1303
1360
return Jddevice (self , device )
1304
1361
raise (MYJDDeviceNotFoundException ("Device not found\n " ))
1305
1362
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
+
1306
1377
def request_api (self ,
1307
1378
path ,
1308
1379
http_method = "GET" ,
@@ -1332,27 +1403,28 @@ def request_api(self,
1332
1403
else :
1333
1404
query += ["&%s=%s" % (param [0 ], param [1 ])]
1334
1405
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
+ ]
1347
1419
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 )
1349
1421
else :
1350
1422
params_request = []
1351
1423
if params is not None :
1352
1424
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 ):
1354
1426
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 ):
1356
1428
params_request += [json .dumps (param )]
1357
1429
else :
1358
1430
params_request += [str (param )]
@@ -1376,10 +1448,10 @@ def request_api(self,
1376
1448
encrypted_response = requests .post (
1377
1449
request_url ,
1378
1450
headers = {
1379
- "Content-Type" : "application/aesjson-jd; charset=utf-8"
1451
+ "Content-Type" : self . __content_type
1380
1452
},
1381
1453
data = encrypted_data ,
1382
- timeout = 3 )
1454
+ timeout = self . __timeout )
1383
1455
except requests .exceptions .RequestException as e :
1384
1456
return None
1385
1457
if encrypted_response .status_code != 200 :
@@ -1410,8 +1482,9 @@ def request_api(self,
1410
1482
response = self .__decrypt (self .__device_encryption_token ,
1411
1483
encrypted_response .text )
1412
1484
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
1416
1489
self .update_request_id ()
1417
1490
return jsondata
0 commit comments