Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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) andnotself.__dict_as_str) orisinstance(param, str) or isinstance(param, list):
13541426
params_request += [param]
1355-
elif isinstance(param, dict) or isinstance(param, bool):
1427+
elif (isinstance(param, dict) andself.__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)

AltStyle によって変換されたページ (->オリジナル) /