@@ -966,7 +966,6 @@ def __init__(self, jd, device_dict):
966
966
self .extensions = Extension (self )
967
967
self .dialogs = Dialog (self )
968
968
self .update = Update (self )
969
- self .jd = Jd (self )
970
969
self .system = System (self )
971
970
self .__direct_connection_info = None
972
971
self .__refresh_direct_connections ()
@@ -975,9 +974,15 @@ def __init__(self, jd, device_dict):
975
974
self .__direct_connection_consecutive_failures = 0
976
975
977
976
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" ])
981
986
982
987
def __update_direct_connections (self , direct_info ):
983
988
"""
@@ -1017,7 +1022,11 @@ def action(self, path, params=(), http_action="POST"):
1017
1022
/example?param1=ex¶m2=ex2 [("param1","ex"),("param2","ex2")]
1018
1023
:param postparams: List of Params that are send in the post.
1019
1024
"""
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 ()
1021
1030
if not self .__direct_connection_enabled or self .__direct_connection_info is None \
1022
1031
or time .time () < self .__direct_connection_cooldown :
1023
1032
# No direct connection available, we use My.JDownloader api.
@@ -1070,11 +1079,7 @@ def action(self, path, params=(), http_action="POST"):
1070
1079
return response ['data' ]
1071
1080
1072
1081
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
1078
1083
1079
1084
class Myjdapi :
1080
1085
"""
@@ -1100,8 +1105,8 @@ def __init__(self):
1100
1105
self .__server_encryption_token = None
1101
1106
self .__device_encryption_token = None
1102
1107
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.
1105
1110
1106
1111
def get_session_token (self ):
1107
1112
return self .__session_token
@@ -1139,7 +1144,7 @@ def __update_encryption_tokens(self):
1139
1144
Updates the server_encryption_token and device_encryption_token
1140
1145
1141
1146
"""
1142
- if self .__connected and not self . __session_token :
1147
+ if self .__connection_type == "remoteapi" :
1143
1148
return
1144
1149
if self .__server_encryption_token is None :
1145
1150
old_token = self .__login_secret
@@ -1170,14 +1175,13 @@ def __decrypt(self, secret_token, data):
1170
1175
:param secret_token:
1171
1176
:param data:
1172
1177
"""
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" :
1180
1179
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
1181
1185
1182
1186
def __encrypt (self , secret_token , data ):
1183
1187
"""
@@ -1186,15 +1190,14 @@ def __encrypt(self, secret_token, data):
1186
1190
:param secret_token:
1187
1191
:param data:
1188
1192
"""
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" :
1197
1194
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' )
1198
1201
1199
1202
def update_request_id (self ):
1200
1203
"""
@@ -1218,8 +1221,8 @@ def connect(self, email, password):
1218
1221
self .__server_encryption_token = None
1219
1222
self .__device_encryption_token = None
1220
1223
self .__devices = None
1221
- self .__device_connection = None
1222
1224
self .__connected = False
1225
+ self .__connection_type = "myjd"
1223
1226
1224
1227
self .__login_secret = self .__secret_create (email , password , "server" )
1225
1228
self .__device_secret = self .__secret_create (email , password , "device" )
@@ -1234,43 +1237,40 @@ def connect(self, email, password):
1234
1237
self .update_devices ()
1235
1238
return response
1236
1239
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.
1239
1246
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.
1242
1250
:returns: boolean -- True if succesful, False if there was any error.
1243
1251
1244
1252
"""
1245
1253
self .update_request_id ()
1254
+ # This direct connection doesn't use auth nor encryption so all secrets and tokens are invalid.
1246
1255
self .__login_secret = None
1247
1256
self .__device_secret = None
1248
1257
self .__session_token = None
1249
1258
self .__regain_token = None
1250
1259
self .__server_encryption_token = None
1251
1260
self .__device_encryption_token = None
1252
- self .__device_connection = {"ip" :ip ,"port" :port ,"type" :_type }
1253
- self .__dict_as_str = False
1254
1261
self .__devices = [{
1255
1262
'name' : ip ,
1256
1263
'id' : 'direct' ,
1257
1264
'type' : 'jd'
1258
1265
}]
1266
+ self .__connection_type = "remoteapi"
1259
1267
self .__api_url = "http://" + ip + ":" + str (port )
1260
1268
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.
1269
1271
response = self .request_api ("/device/ping" , "GET" , [])['data' ]
1270
1272
self .__connected = response
1271
1273
self .update_request_id ()
1272
- self .__session_token = None
1273
- self .__regain_token = None
1274
1274
return response
1275
1275
1276
1276
def reconnect (self ):
@@ -1280,8 +1280,9 @@ def reconnect(self):
1280
1280
:returns: boolean -- True if successful, False if there was any error.
1281
1281
1282
1282
"""
1283
- if self .__connected and ( not self . __session_token or not self . __regain_token ) :
1283
+ if self .__connection_type == "remoteapi" :
1284
1284
return True
1285
+
1285
1286
response = self .request_api ("/my/reconnect" , "GET" ,
1286
1287
[("sessiontoken" , self .__session_token ),
1287
1288
("regaintoken" , self .__regain_token )])
@@ -1298,7 +1299,7 @@ def disconnect(self):
1298
1299
:returns: boolean -- True if successful, False if there was any error.
1299
1300
1300
1301
"""
1301
- if self .__connected and not self . __session_token :
1302
+ if self .__connection_type == "remoteapi" :
1302
1303
response = True
1303
1304
else :
1304
1305
response = self .request_api ("/my/disconnect" , "GET" ,
@@ -1320,7 +1321,7 @@ def update_devices(self):
1320
1321
1321
1322
:returns: boolean -- True if successful, False if there was any error.
1322
1323
"""
1323
- if self .__connected and not self . __session_token :
1324
+ if self .__connection_type == "remoteapi" :
1324
1325
return
1325
1326
response = self .request_api ("/my/listdevices" , "GET" ,
1326
1327
[("sessiontoken" , self .__session_token )])
@@ -1358,21 +1359,10 @@ def get_device(self, device_name=None, device_id=None):
1358
1359
for device in self .__devices :
1359
1360
if device ["name" ] == device_name :
1360
1361
return Jddevice (self , device )
1362
+ elif len (self .__devices ) > 0 :
1363
+ return Jddevice (self , self .__devices [0 ])
1361
1364
raise (MYJDDeviceNotFoundException ("Device not found\n " ))
1362
1365
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
1366
1377
1367
def request_api (self ,
1378
1368
path ,
@@ -1403,8 +1393,8 @@ def request_api(self,
1403
1393
else :
1404
1394
query += ["&%s=%s" % (param [0 ], param [1 ])]
1405
1395
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.
1408
1398
query += [
1409
1399
"signature=" \
1410
1400
+ str (self .__signature_create (self .__login_secret ,
@@ -1419,19 +1409,10 @@ def request_api(self,
1419
1409
query = query [0 ] + "&" .join (query [1 :])
1420
1410
encrypted_response = requests .get (api + query , timeout = self .__timeout )
1421
1411
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 )]
1431
1412
params_request = {
1432
1413
"apiVer" : self .__api_version ,
1433
1414
"url" : path ,
1434
- "params" : params_request ,
1415
+ "params" : self . __adapt_params_for_request ( params ) ,
1435
1416
"rid" : self .__request_id
1436
1417
}
1437
1418
data = json .dumps (params_request )
@@ -1488,3 +1469,26 @@ def request_api(self,
1488
1469
return None
1489
1470
self .update_request_id ()
1490
1471
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