@@ -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,6 +974,8 @@ def __init__(self, jd, device_dict):
975
974
self .__direct_connection_consecutive_failures = 0
976
975
977
976
def __refresh_direct_connections (self ):
977
+ if self .myjd .get_connection_type () == "remoteapi" :
978
+ return
978
979
response = self .myjd .request_api ("/device/getDirectConnectionInfos" ,
979
980
"POST" , None , self .__action_url ())
980
981
if response is not None \
@@ -1021,7 +1022,11 @@ def action(self, path, params=(), http_action="POST"):
1021
1022
/example?param1=ex¶m2=ex2 [("param1","ex"),("param2","ex2")]
1022
1023
:param postparams: List of Params that are send in the post.
1023
1024
"""
1024
- 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 ()
1025
1030
if not self .__direct_connection_enabled or self .__direct_connection_info is None \
1026
1031
or time .time () < self .__direct_connection_cooldown :
1027
1032
# No direct connection available, we use My.JDownloader api.
@@ -1076,7 +1081,6 @@ def action(self, path, params=(), http_action="POST"):
1076
1081
def __action_url (self ):
1077
1082
return "/t_" + self .myjd .get_session_token () + "_" + self .device_id
1078
1083
1079
-
1080
1084
class Myjdapi :
1081
1085
"""
1082
1086
Main class for connecting to JD API.
@@ -1091,6 +1095,7 @@ def __init__(self):
1091
1095
self .__request_id = int (time .time () * 1000 )
1092
1096
self .__api_url = "https://api.jdownloader.org"
1093
1097
self .__app_key = "http://git.io/vmcsk"
1098
+ self .__content_type = "application/aesjson-jd; charset=utf-8"
1094
1099
self .__api_version = 1
1095
1100
self .__devices = None
1096
1101
self .__login_secret = None
@@ -1100,6 +1105,8 @@ def __init__(self):
1100
1105
self .__server_encryption_token = None
1101
1106
self .__device_encryption_token = None
1102
1107
self .__connected = False
1108
+ self .__timeout = 3
1109
+ self .__connection_type = "myjd" # myjd -> MyJdownloader API, remoteapi -> Deprecated Direct RemoteAPI connection.
1103
1110
1104
1111
def get_session_token (self ):
1105
1112
return self .__session_token
@@ -1137,6 +1144,8 @@ def __update_encryption_tokens(self):
1137
1144
Updates the server_encryption_token and device_encryption_token
1138
1145
1139
1146
"""
1147
+ if self .__connection_type == "remoteapi" :
1148
+ return
1140
1149
if self .__server_encryption_token is None :
1141
1150
old_token = self .__login_secret
1142
1151
else :
@@ -1166,6 +1175,8 @@ def __decrypt(self, secret_token, data):
1166
1175
:param secret_token:
1167
1176
:param data:
1168
1177
"""
1178
+ if self .__connection_type == "remoteapi" :
1179
+ return data .encode ('utf-8' )
1169
1180
init_vector = secret_token [:len (secret_token ) // 2 ]
1170
1181
key = secret_token [len (secret_token ) // 2 :]
1171
1182
decryptor = AES .new (key , AES .MODE_CBC , init_vector )
@@ -1179,6 +1190,8 @@ def __encrypt(self, secret_token, data):
1179
1190
:param secret_token:
1180
1191
:param data:
1181
1192
"""
1193
+ if self .__connection_type == "remoteapi" :
1194
+ return data
1182
1195
data = PAD (data .encode ('utf-8' ))
1183
1196
init_vector = secret_token [:len (secret_token ) // 2 ]
1184
1197
key = secret_token [len (secret_token ) // 2 :]
@@ -1209,6 +1222,7 @@ def connect(self, email, password):
1209
1222
self .__device_encryption_token = None
1210
1223
self .__devices = None
1211
1224
self .__connected = False
1225
+ self .__connection_type = "myjd"
1212
1226
1213
1227
self .__login_secret = self .__secret_create (email , password , "server" )
1214
1228
self .__device_secret = self .__secret_create (email , password , "device" )
@@ -1223,13 +1237,52 @@ def connect(self, email, password):
1223
1237
self .update_devices ()
1224
1238
return response
1225
1239
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.
1246
+
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.
1250
+ :returns: boolean -- True if succesful, False if there was any error.
1251
+
1252
+ """
1253
+ self .update_request_id ()
1254
+ # This direct connection doesn't use auth nor encryption so all secrets and tokens are invalid.
1255
+ self .__login_secret = None
1256
+ self .__device_secret = None
1257
+ self .__session_token = None
1258
+ self .__regain_token = None
1259
+ self .__server_encryption_token = None
1260
+ self .__device_encryption_token = None
1261
+ self .__devices = [{
1262
+ 'name' : ip ,
1263
+ 'id' : 'direct' ,
1264
+ 'type' : 'jd'
1265
+ }]
1266
+ self .__connection_type = "remoteapi"
1267
+ self .__api_url = "http://" + ip + ":" + str (port )
1268
+ self .__content_type = "application/json; charset=utf-8"
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.
1271
+ response = self .request_api ("/device/ping" , "GET" , [])['data' ]
1272
+ self .__connected = response
1273
+ self .update_request_id ()
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 .__connection_type == "remoteapi" :
1284
+ return True
1285
+
1233
1286
response = self .request_api ("/my/reconnect" , "GET" ,
1234
1287
[("sessiontoken" , self .__session_token ),
1235
1288
("regaintoken" , self .__regain_token )])
@@ -1246,7 +1299,10 @@ def disconnect(self):
1246
1299
:returns: boolean -- True if successful, False if there was any error.
1247
1300
1248
1301
"""
1249
- response = self .request_api ("/my/disconnect" , "GET" ,
1302
+ if self .__connection_type == "remoteapi" :
1303
+ response = True
1304
+ else :
1305
+ response = self .request_api ("/my/disconnect" , "GET" ,
1250
1306
[("sessiontoken" , self .__session_token )])
1251
1307
self .update_request_id ()
1252
1308
self .__login_secret = None
@@ -1265,6 +1321,8 @@ def update_devices(self):
1265
1321
1266
1322
:returns: boolean -- True if successful, False if there was any error.
1267
1323
"""
1324
+ if self .__connection_type == "remoteapi" :
1325
+ return
1268
1326
response = self .request_api ("/my/listdevices" , "GET" ,
1269
1327
[("sessiontoken" , self .__session_token )])
1270
1328
self .update_request_id ()
@@ -1301,8 +1359,11 @@ def get_device(self, device_name=None, device_id=None):
1301
1359
for device in self .__devices :
1302
1360
if device ["name" ] == device_name :
1303
1361
return Jddevice (self , device )
1362
+ elif len (self .__devices ) > 0 :
1363
+ return Jddevice (self , self .__devices [0 ])
1304
1364
raise (MYJDDeviceNotFoundException ("Device not found\n " ))
1305
1365
1366
+
1306
1367
def request_api (self ,
1307
1368
path ,
1308
1369
http_method = "GET" ,
@@ -1332,34 +1393,26 @@ def request_api(self,
1332
1393
else :
1333
1394
query += ["&%s=%s" % (param [0 ], param [1 ])]
1334
1395
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
- ]
1396
+ if self .__connection_type == "myjd" :
1397
+ if self .__server_encryption_token is None : # Requests pre-auth.
1398
+ query += [
1399
+ "signature=" \
1400
+ + str (self .__signature_create (self .__login_secret ,
1401
+ query [0 ] + "&" .join (query [1 :])))
1402
+ ]
1403
+ else :
1404
+ query += [
1405
+ "signature=" \
1406
+ + str (self .__signature_create (self .__server_encryption_token ,
1407
+ query [0 ] + "&" .join (query [1 :])))
1408
+ ]
1347
1409
query = query [0 ] + "&" .join (query [1 :])
1348
- encrypted_response = requests .get (api + query , timeout = 3 )
1410
+ encrypted_response = requests .get (api + query , timeout = self . __timeout )
1349
1411
else :
1350
- params_request = []
1351
- if params is not None :
1352
- for param in params :
1353
- if isinstance (param , str ) or isinstance (param , list ):
1354
- params_request += [param ]
1355
- elif isinstance (param , dict ) or isinstance (param , bool ):
1356
- params_request += [json .dumps (param )]
1357
- else :
1358
- params_request += [str (param )]
1359
1412
params_request = {
1360
1413
"apiVer" : self .__api_version ,
1361
1414
"url" : path ,
1362
- "params" : params_request ,
1415
+ "params" : self . __adapt_params_for_request ( params ) ,
1363
1416
"rid" : self .__request_id
1364
1417
}
1365
1418
data = json .dumps (params_request )
@@ -1376,10 +1429,10 @@ def request_api(self,
1376
1429
encrypted_response = requests .post (
1377
1430
request_url ,
1378
1431
headers = {
1379
- "Content-Type" : "application/aesjson-jd; charset=utf-8"
1432
+ "Content-Type" : self . __content_type
1380
1433
},
1381
1434
data = encrypted_data ,
1382
- timeout = 3 )
1435
+ timeout = self . __timeout )
1383
1436
except requests .exceptions .RequestException as e :
1384
1437
return None
1385
1438
if encrypted_response .status_code != 200 :
@@ -1410,8 +1463,32 @@ def request_api(self,
1410
1463
response = self .__decrypt (self .__device_encryption_token ,
1411
1464
encrypted_response .text )
1412
1465
jsondata = json .loads (response .decode ('utf-8' ))
1413
- if jsondata ['rid' ] != self .__request_id :
1414
- self .update_request_id ()
1415
- return None
1466
+ if 'rid' in jsondata .keys ():
1467
+ if jsondata ['rid' ] != self .__request_id :
1468
+ self .update_request_id ()
1469
+ return None
1416
1470
self .update_request_id ()
1417
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