Skip to content

Commit df7c12b

Browse files
hfrmmarquezs
authored andcommitted
direct device access
1 parent 7e0a290 commit df7c12b

File tree

1 file changed

+113
-40
lines changed

1 file changed

+113
-40
lines changed

myjdapi/myjdapi.py

Lines changed: 113 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

10801079
class 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

Comments
 (0)