zzupy 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
zzupy-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.1
2
+ Name: zzupy
3
+ Version: 0.1.0
4
+ Summary: ZZU.Py is a Python library for interacting with the Zhengzhou University (ZZU) Supwisdom Course Management Information System API.
5
+ Author-email: Illustar0 <me@illustar0.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
9
+ Requires-Dist: httpx
10
+ Requires-Dist: rich
11
+ Project-URL: Source, https://github.com/Illustar0/ZZU.Py
12
+
13
+ # ZZU.Py
14
+ <font color=gray size=3>a Python library for interacting with the Zhengzhou University (ZZU) Supwisdom Course Management Information System API.</font>
15
+
16
+ ## Install
17
+
18
+ ```shell
19
+ pip install zzupy --upgrade
20
+ ```
21
+
22
+ ## Use
23
+
24
+ Web documentation is not available at this time, please use PyCharm for a better in-development documentation experience.
25
+
26
+ ## Example
27
+
28
+ ```Py
29
+ from zzupy import *
30
+ import datetime
31
+
32
+
33
+ def this_monday():
34
+ today = datetime.datetime.strptime(str(datetime.datetime.now().strftime('%Y-%m-%d')), "%Y-%m-%d")
35
+ return datetime.datetime.strftime(today - datetime.timedelta(today.weekday()), "%Y-%m-%d")
36
+
37
+
38
+ # 设置为 True 以避免触发“建议设置设备参数”的警告。如果有能力,你也可以通过 setDeviceParams() 设置设备参数
39
+ me = ZZUPy(True)
40
+ # me.setDeviceParams()
41
+ info = me.loginByPassword("fakeusercode", "fakepassword")
42
+ print(f"{info[0]} {info[1]} 登录成功")
43
+ print("校园卡余额:", str(me.getBalance()))
44
+ print("剩余照明电费:", str(me.getRemainingPower("yourroomid")))
45
+ print("课表JSON:", me.getCoursesJson(this_monday()))
46
+ ```
47
+
48
+ ## License
49
+
50
+ License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
zzupy-0.1.0/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # ZZU.Py
2
+ <font color=gray size=3>a Python library for interacting with the Zhengzhou University (ZZU) Supwisdom Course Management Information System API.</font>
3
+
4
+ ## Install
5
+
6
+ ```shell
7
+ pip install zzupy --upgrade
8
+ ```
9
+
10
+ ## Use
11
+
12
+ Web documentation is not available at this time, please use PyCharm for a better in-development documentation experience.
13
+
14
+ ## Example
15
+
16
+ ```Py
17
+ from zzupy import *
18
+ import datetime
19
+
20
+
21
+ def this_monday():
22
+ today = datetime.datetime.strptime(str(datetime.datetime.now().strftime('%Y-%m-%d')), "%Y-%m-%d")
23
+ return datetime.datetime.strftime(today - datetime.timedelta(today.weekday()), "%Y-%m-%d")
24
+
25
+
26
+ # 设置为 True 以避免触发“建议设置设备参数”的警告。如果有能力,你也可以通过 setDeviceParams() 设置设备参数
27
+ me = ZZUPy(True)
28
+ # me.setDeviceParams()
29
+ info = me.loginByPassword("fakeusercode", "fakepassword")
30
+ print(f"{info[0]} {info[1]} 登录成功")
31
+ print("校园卡余额:", str(me.getBalance()))
32
+ print("剩余照明电费:", str(me.getRemainingPower("yourroomid")))
33
+ print("课表JSON:", me.getCoursesJson(this_monday()))
34
+ ```
35
+
36
+ ## License
37
+
38
+ License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["flit_core >=3.2,<4"]
3
+ build-backend = "flit_core.buildapi"
4
+ [project]
5
+ name = "zzupy"
6
+ version = "0.1.0"
7
+ readme = "README.md"
8
+ requires-python = ">=3.8"
9
+ description = "ZZU.Py is a Python library for interacting with the Zhengzhou University (ZZU) Supwisdom Course Management Information System API."
10
+ authors = [
11
+ { name="Illustar0", email="me@illustar0.com" },
12
+ ]
13
+ classifiers = [
14
+ "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
15
+ ]
16
+ dependencies = [
17
+ "httpx",
18
+ "rich",
19
+ ]
20
+ [project.urls]
21
+ Source = "https://github.com/Illustar0/ZZU.Py"
zzupy-0.1.0/zzupy.py ADDED
@@ -0,0 +1,924 @@
1
+ import random
2
+ import httpx
3
+ import json
4
+ import base64
5
+ import datetime
6
+ import hashlib
7
+ import time
8
+ from rich import print
9
+
10
+
11
+ def info(text):
12
+ print(f"[bold green][INFO]:[/bold green] {text}")
13
+
14
+
15
+ def error(text):
16
+ print(f"[bold red][ERROR]:[/bold red] {text}")
17
+ quit()
18
+
19
+
20
+ def warn(text):
21
+ print(f"[bold yellow][WARN]:[/bold yellow] {text}")
22
+
23
+
24
+ def getSign(dynamicSecret, params):
25
+ """
26
+ 获取sign值
27
+ :param str dynamicSecret: login后自动获取,来自 login-token 请求
28
+ :param str params: URL请求参数
29
+ :return: sign值
30
+ :return_type: str
31
+ """
32
+ paramsDict = {}
33
+ for param in params.split("&"):
34
+ if param.split("=")[0] == "timestamp":
35
+ timestamp = param.split("=")[1]
36
+ elif param.split("=")[0] == "random":
37
+ random = param.split("=")[1]
38
+ else:
39
+ paramsDict[param.split("=")[0]] = param.split("=")[1]
40
+ paramsDict = dict(sorted(paramsDict.items()))
41
+ original = f"{dynamicSecret}|"
42
+ for key in paramsDict:
43
+ original += f"{paramsDict[key]}|"
44
+ original += f"{timestamp}|{random}"
45
+ sign = hashlib.md5(original.encode("utf-8")).hexdigest().upper()
46
+ return sign
47
+
48
+
49
+ class ZZUPy:
50
+ def __init__(self, forceDeviceParams=False):
51
+ """
52
+ 初始化
53
+ :param bool forceDeviceParams: 是否忽略设备参数的设置。设为 True 将不再触发 "Recommended set device parameters" 的警告
54
+ """
55
+ self.forceDeviceParams = forceDeviceParams
56
+ self.userToken = None
57
+ self.dynamicSecret = "supwisdom_eams_app_secret"
58
+ self.dynamicToken = None
59
+ self.refreshToken = None
60
+ self.name = None
61
+ self.userAgentPrecursor = None
62
+ self.isLogged = False
63
+ self.DeviceParamsSet = False
64
+ self.deviceName = ""
65
+ self.deviceId = ""
66
+ self.deviceInfo = ""
67
+ self.deviceInfos = ""
68
+ self.userAgentPrecursor = ""
69
+ self.userCode = ""
70
+
71
+ def setParamsFromPasswordLogin(self, res):
72
+ try:
73
+ self.userToken = json.loads(res)["data"]["idToken"]
74
+ # 我也不知道 refreshToken 有什么用,但先存着吧
75
+ self.refreshToken = json.loads(res)["data"]["refreshToken"]
76
+ except:
77
+ error("LoginFailed")
78
+
79
+ def setParamsFromLoginToken(self, res):
80
+ try:
81
+ self.dynamicSecret = json.loads(base64.b64decode(json.loads(res)["business_data"]))["secret"]
82
+ self.dynamicToken = json.loads(base64.b64decode(json.loads(res)["business_data"]))["token"]
83
+ self.name = json.loads(base64.b64decode(json.loads(res)["business_data"]))["user_info"]["user_name"]
84
+ except:
85
+ error("LoginFailed")
86
+
87
+ def setDeviceParams(self, deviceName="", deviceId="", deviceInfo="", deviceInfos="", userAgentPrecursor=""):
88
+ """
89
+ 设置设备参数.
90
+ :param str deviceName: 设备名 ,需要抓包获取,位于 "passwordLogin" 请求的 User-Agent 中,组成为 '{appVersion}({deviceName})' ,但也可随便填或空着,目前没有观察到相关风控机制。
91
+ :param str deviceId: 设备 ID ,需要抓包获取,但也可随便填或空着,目前没有观察到相关风控机制
92
+ :param str deviceInfo: 设备信息,需要抓包获取,位于名为 "X-Device-Info" 的请求头中。但也可随便填或空着,目前没有观察到相关风控机制
93
+ :param str deviceInfos: 设备信息,需要抓包获取,位于名为 "X-Device-Infos" 的请求头中。但也可随便填或空着,目前没有观察到相关风控机制
94
+ :param str userAgentPrecursor: 设备 UA 前体 ,需要抓包获取,但也可随便填或空着,目前没有观察到相关风控机制。只需要包含 "SuperApp" 或 "uni-app Html5Plus/1.0 (Immersed/38.666668)" 前面的部分
95
+ """
96
+ self.deviceName = deviceName
97
+ self.deviceId = deviceId
98
+ self.deviceInfo = deviceInfo
99
+ self.deviceInfos = deviceInfos
100
+ if userAgentPrecursor.endswith(" "):
101
+ self.userAgentPrecursor = userAgentPrecursor
102
+ else:
103
+ self.userAgentPrecursor = userAgentPrecursor + " "
104
+ self.DeviceParamsSet = True
105
+
106
+ def loginByPassword(self, userCode, password, appVersion="SWSuperApp/1.0.33",
107
+ appId="com.supwisdom.zzu", osType="android"):
108
+ """
109
+ 通过学号和密码登录
110
+ :param str userCode: 学号
111
+ :param str password: 密码
112
+ :param str appVersion: APP 版本 ,一般类似 "SWSuperApp/1.0.33" ,可自行更新版本号,但详细数据需要抓包获取,位于 "passwordLogin" 请求的 User-Agent 中,也可随便填或空着,目前没有观察到相关风控机制。
113
+ :param str appId: APP 包名,一般不需要修改
114
+ :param str osType: 系统类型,一般不需要修改
115
+ """
116
+ if not self.DeviceParamsSet and not self.forceDeviceParams:
117
+ warn("Recommended set device parameters")
118
+ headers = {
119
+ 'User-Agent': f'{appVersion}({self.deviceName})',
120
+ 'Connection': 'Keep-Alive',
121
+ 'Accept-Encoding': 'gzip',
122
+ }
123
+ response = httpx.post(
124
+ f'https://token.s.zzu.edu.cn/password/passwordLogin?username={userCode}&password={password}&appId={appId}&geo&deviceId={self.deviceId}&osType={osType}&clientId&mfaState',
125
+ headers=headers,
126
+ )
127
+ self.setParamsFromPasswordLogin(response.text)
128
+
129
+ cookies = {
130
+ 'userToken': self.userToken,
131
+ 'Domain': '.zzu.edu.cn',
132
+ 'Path': '/',
133
+ 'SVRNAME': 'ws1',
134
+ }
135
+
136
+ headers = {
137
+ 'User-Agent': self.userAgentPrecursor + "SuperApp",
138
+ 'Accept': 'application/json, text/plain, */*',
139
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
140
+ 'Content-Type': 'application/x-www-form-urlencoded',
141
+ 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Android WebView";v="126"',
142
+ 'sec-ch-ua-mobile': '?1',
143
+ 'sec-ch-ua-platform': '"Android"',
144
+ 'Origin': 'https://jw.v.zzu.edu.cn',
145
+ 'X-Requested-With': 'com.supwisdom.zzu',
146
+ 'Sec-Fetch-Site': 'same-origin',
147
+ 'Sec-Fetch-Mode': 'cors',
148
+ 'Sec-Fetch-Dest': 'empty',
149
+ 'Referer': 'https://jw.v.zzu.edu.cn/app-web/',
150
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
151
+ 'Cookie': f'userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/; SVRNAME=ws1',
152
+ }
153
+ data = {
154
+ 'random': int(random.uniform(10000, 99999)),
155
+ 'timestamp': int(round(time.time() * 1000)),
156
+ 'userToken': self.userToken
157
+ }
158
+ # 计算 sign 并将其加入 data
159
+ params = ""
160
+ for key in data.keys():
161
+ params += f"{key}={data[key]}&"
162
+ params = params[:-1]
163
+ sign = getSign(self.dynamicSecret, params)
164
+ data["sign"] = sign
165
+
166
+ response = httpx.post(
167
+ 'https://jw.v.zzu.edu.cn/app-ws/ws/app-service/super/app/login-token',
168
+ cookies=cookies,
169
+ headers=headers,
170
+ data=data,
171
+ )
172
+ self.setParamsFromLoginToken(response.text)
173
+ self.userCode = userCode
174
+ self.isLogged = True
175
+ return [self.userCode, self.name]
176
+
177
+ def getCoursesJson(self, start_date):
178
+ """
179
+ 获取课程表
180
+ :param str start_date: 课表的开始日期,必需为本周周一,否则课表会时间错乱
181
+ :return: 返回课程表数据,格式为json
182
+ :return_type: str
183
+ """
184
+ if not self.isLogged:
185
+ error("RequireLogined")
186
+ if not self.DeviceParamsSet and not self.forceDeviceParams:
187
+ warn("Recommended set device parameters")
188
+ cookies = {
189
+ 'userToken': self.userToken,
190
+ 'Domain': '.zzu.edu.cn',
191
+ 'Path': '/',
192
+ 'SVRNAME': 'ws1',
193
+ }
194
+
195
+ headers = {
196
+ 'User-Agent': self.userAgentPrecursor + "SuperApp",
197
+ 'Accept': 'application/json, text/plain, */*',
198
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
199
+ 'Content-Type': 'application/x-www-form-urlencoded',
200
+ 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Android WebView";v="126"',
201
+ 'sec-ch-ua-mobile': '?1',
202
+ 'token': self.dynamicToken,
203
+ 'sec-ch-ua-platform': '"Android"',
204
+ 'Origin': 'https://jw.v.zzu.edu.cn',
205
+ 'X-Requested-With': 'com.supwisdom.zzu',
206
+ 'Sec-Fetch-Site': 'same-origin',
207
+ 'Sec-Fetch-Mode': 'cors',
208
+ 'Sec-Fetch-Dest': 'empty',
209
+ 'Referer': 'https://jw.v.zzu.edu.cn/app-web/',
210
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
211
+ 'Cookie': f'userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/; SVRNAME=ws1',
212
+ }
213
+
214
+ data = {
215
+ 'biz_type_id': '1',
216
+ 'end_date': (datetime.datetime.strptime(start_date, "%Y-%m-%d") + datetime.timedelta(days=6)).strftime(
217
+ "%Y-%m-%d"),
218
+ 'random': int(random.uniform(10000, 99999)),
219
+ 'semester_id': '152',
220
+ 'start_date': start_date,
221
+ 'timestamp': int(round(time.time() * 1000)),
222
+ 'token': self.userToken,
223
+ }
224
+ params = ""
225
+ for key in data.keys():
226
+ params += f"{key}={data[key]}&"
227
+ params = params[:-1]
228
+ sign = getSign(self.dynamicSecret, params)
229
+ data["sign"] = sign
230
+
231
+ response = httpx.post(
232
+ 'https://jw.v.zzu.edu.cn/app-ws/ws/app-service/student/course/schedule/get-course-tables',
233
+ cookies=cookies,
234
+ headers=headers,
235
+ data=data,
236
+ )
237
+ coursesJson = (base64.b64decode(json.loads(response.text)["business_data"])).decode('utf-8')
238
+ return coursesJson
239
+
240
+ def getBalance(self):
241
+ """
242
+ 获取校园卡余额
243
+ :return: 校园卡余额
244
+ :return_type: float
245
+ """
246
+ if not self.isLogged:
247
+ error("RequireLogined")
248
+ if not self.DeviceParamsSet and not self.forceDeviceParams:
249
+ warn("Recommended set device parameters")
250
+ headers = {
251
+ 'User-Agent': self.userAgentPrecursor + "uni-app Html5Plus/1.0 (Immersed/38.666668)",
252
+ 'Connection': 'Keep-Alive',
253
+ 'Accept': 'application/json',
254
+ 'Accept-Encoding': 'gzip',
255
+ 'X-Device-Info': self.deviceInfo,
256
+ 'X-Device-Infos': self.deviceInfos,
257
+ 'X-Id-Token': self.userToken,
258
+ 'X-Terminal-Info': 'app',
259
+ 'Content-Type': 'application/x-www-form-urlencoded',
260
+ }
261
+
262
+ response = httpx.get('https://info.s.zzu.edu.cn/portal-api/v1/thrid-adapter/get-person-info-card-list',
263
+ headers=headers)
264
+ return float(json.loads(response.text)["data"][1]["amount"])
265
+
266
+ def getAreaDict(self):
267
+ """
268
+ 获取区域的字典
269
+ :return: 区域字典
270
+ :rtype: dict
271
+ """
272
+ if not self.isLogged:
273
+ error("RequireLogined")
274
+ if not self.DeviceParamsSet and not self.forceDeviceParams and not self.forceDeviceParams:
275
+ warn("Recommended set device parameters")
276
+ cookies = {
277
+ 'userToken': self.userToken,
278
+ 'Domain': '.zzu.edu.cn',
279
+ 'Path': '/',
280
+ }
281
+
282
+ headers = {
283
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
284
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
285
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
286
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
287
+ 'sec-ch-ua-mobile': '?1',
288
+ 'sec-ch-ua-platform': '"Android"',
289
+ 'Upgrade-Insecure-Requests': '1',
290
+ 'x-id-token': self.userToken,
291
+ 'X-Requested-With': 'com.supwisdom.zzu',
292
+ 'Sec-Fetch-Site': 'none',
293
+ 'Sec-Fetch-Mode': 'navigate',
294
+ 'Sec-Fetch-User': '?1',
295
+ 'Sec-Fetch-Dest': 'document',
296
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
297
+ 'Cookie': f'userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
298
+ }
299
+
300
+ params = {
301
+ 'host': '11',
302
+ 'org': '2',
303
+ 'token': self.userToken,
304
+ }
305
+
306
+ response = httpx.get('https://ecard.v.zzu.edu.cn/server/auth/host/open', params=params, cookies=cookies,
307
+ headers=headers, follow_redirects=False)
308
+ JSESSIONID = response.headers['set-cookie'].split("=")[1].split(";")[0]
309
+ tid = response.headers['location'].split('=')[1].split("&")[0]
310
+ cookies = {
311
+ 'JSESSIONID': JSESSIONID,
312
+ 'userToken': self.userToken,
313
+ 'Domain': '.zzu.edu.cn',
314
+ 'Path': '/',
315
+ }
316
+
317
+ headers = {
318
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
319
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
320
+ 'Content-Type': 'application/json',
321
+ 'sec-ch-ua-platform': '"Android"',
322
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
323
+ 'sec-ch-ua-mobile': '?1',
324
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
325
+ 'X-Requested-With': 'com.supwisdom.zzu',
326
+ 'Sec-Fetch-Site': 'same-origin',
327
+ 'Sec-Fetch-Mode': 'cors',
328
+ 'Sec-Fetch-Dest': 'empty',
329
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
330
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
331
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
332
+ }
333
+
334
+ data = {
335
+ 'tid': tid,
336
+ }
337
+
338
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/auth/getToken', cookies=cookies, headers=headers,
339
+ json=data)
340
+ accessToken = json.loads(response.text)["resultData"]["accessToken"]
341
+ cookies = {
342
+ 'JSESSIONID': JSESSIONID,
343
+ 'userToken': self.userToken,
344
+ 'Domain': '.zzu.edu.cn',
345
+ 'Path': '/',
346
+ }
347
+
348
+ headers = {
349
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
350
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
351
+ 'Content-Type': 'application/json',
352
+ 'sec-ch-ua-platform': '"Android"',
353
+ 'Authorization': accessToken,
354
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
355
+ 'sec-ch-ua-mobile': '?1',
356
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
357
+ 'X-Requested-With': 'com.supwisdom.zzu',
358
+ 'Sec-Fetch-Site': 'same-origin',
359
+ 'Sec-Fetch-Mode': 'cors',
360
+ 'Sec-Fetch-Dest': 'empty',
361
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
362
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
363
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
364
+ }
365
+
366
+ data = {
367
+ 'utilityType': 'electric',
368
+ 'locationType': 'bigArea',
369
+ 'bigArea': '',
370
+ 'area': '',
371
+ 'building': '',
372
+ 'unit': '',
373
+ 'level': '',
374
+ 'room': '',
375
+ 'subArea': '',
376
+ }
377
+
378
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/utilities/location', cookies=cookies,
379
+ headers=headers, json=data)
380
+ AreaDict = {}
381
+ for i in range(len(json.loads(response.text)["resultData"]["locationList"])):
382
+ AreaDict[json.loads(response.text)["resultData"]["locationList"][i]["id"]] = \
383
+ json.loads(response.text)["resultData"]["locationList"][i]["name"]
384
+ return AreaDict
385
+
386
+ def getBuildingDict(self, areaid):
387
+ """
388
+ 获取建筑的字典
389
+ :param areaid: 通过getAreaDict()获取
390
+ :return: 建筑字典
391
+ :rtype: dict
392
+ """
393
+ if self.isLogged == False:
394
+ error("RequireLogined")
395
+ if not self.DeviceParamsSet and not self.forceDeviceParams:
396
+ warn("Recommended set device parameters")
397
+ cookies = {
398
+ 'userToken': self.userToken,
399
+ 'Domain': '.zzu.edu.cn',
400
+ 'Path': '/',
401
+ }
402
+
403
+ headers = {
404
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
405
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
406
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
407
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
408
+ 'sec-ch-ua-mobile': '?1',
409
+ 'sec-ch-ua-platform': '"Android"',
410
+ 'Upgrade-Insecure-Requests': '1',
411
+ 'x-id-token': self.userToken,
412
+ 'X-Requested-With': 'com.supwisdom.zzu',
413
+ 'Sec-Fetch-Site': 'none',
414
+ 'Sec-Fetch-Mode': 'navigate',
415
+ 'Sec-Fetch-User': '?1',
416
+ 'Sec-Fetch-Dest': 'document',
417
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
418
+ 'Cookie': f'userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
419
+ }
420
+
421
+ params = {
422
+ 'host': '11',
423
+ 'org': '2',
424
+ 'token': self.userToken,
425
+ }
426
+
427
+ response = httpx.get('https://ecard.v.zzu.edu.cn/server/auth/host/open', params=params, cookies=cookies,
428
+ headers=headers, follow_redirects=False)
429
+ JSESSIONID = response.headers['set-cookie'].split("=")[1].split(";")[0]
430
+ tid = response.headers['location'].split('=')[1].split("&")[0]
431
+ cookies = {
432
+ 'JSESSIONID': JSESSIONID,
433
+ 'userToken': self.userToken,
434
+ 'Domain': '.zzu.edu.cn',
435
+ 'Path': '/',
436
+ }
437
+
438
+ headers = {
439
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
440
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
441
+ 'Content-Type': 'application/json',
442
+ 'sec-ch-ua-platform': '"Android"',
443
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
444
+ 'sec-ch-ua-mobile': '?1',
445
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
446
+ 'X-Requested-With': 'com.supwisdom.zzu',
447
+ 'Sec-Fetch-Site': 'same-origin',
448
+ 'Sec-Fetch-Mode': 'cors',
449
+ 'Sec-Fetch-Dest': 'empty',
450
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
451
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
452
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
453
+ }
454
+
455
+ data = {
456
+ 'tid': tid,
457
+ }
458
+
459
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/auth/getToken', cookies=cookies, headers=headers,
460
+ json=data)
461
+ accessToken = json.loads(response.text)["resultData"]["accessToken"]
462
+ cookies = {
463
+ 'JSESSIONID': JSESSIONID,
464
+ 'userToken': self.userToken,
465
+ 'Domain': '.zzu.edu.cn',
466
+ 'Path': '/',
467
+ }
468
+
469
+ headers = {
470
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
471
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
472
+ 'Content-Type': 'application/json',
473
+ 'sec-ch-ua-platform': '"Android"',
474
+ 'Authorization': accessToken,
475
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
476
+ 'sec-ch-ua-mobile': '?1',
477
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
478
+ 'X-Requested-With': 'com.supwisdom.zzu',
479
+ 'Sec-Fetch-Site': 'same-origin',
480
+ 'Sec-Fetch-Mode': 'cors',
481
+ 'Sec-Fetch-Dest': 'empty',
482
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
483
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
484
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
485
+ }
486
+
487
+ data = {
488
+ 'utilityType': 'electric',
489
+ 'locationType': 'building',
490
+ 'bigArea': '',
491
+ 'area': areaid,
492
+ 'building': '',
493
+ 'unit': '',
494
+ 'level': '',
495
+ 'room': '',
496
+ 'subArea': '',
497
+ }
498
+
499
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/utilities/location', cookies=cookies,
500
+ headers=headers, json=data)
501
+ BuildingDict = {}
502
+ for i in range(len(json.loads(response.text)["resultData"]["locationList"])):
503
+ BuildingDict[json.loads(response.text)["resultData"]["locationList"][i]["id"]] = \
504
+ json.loads(response.text)["resultData"]["locationList"][i]["name"]
505
+ return BuildingDict
506
+
507
+ def getUnitDict(self, areaid, buildingid):
508
+ """
509
+ 获取照明/空调的字典
510
+ :param areaid: 通过getAreaDict()获取
511
+ :param buildingid: 通过getBuildingDict()获取
512
+ :return: 照明/空调字典
513
+ :rtype: dict
514
+ """
515
+ if self.isLogged == False:
516
+ error("RequireLogined")
517
+ if not self.DeviceParamsSet and not self.forceDeviceParams:
518
+ warn("Recommended set device parameters")
519
+ cookies = {
520
+ 'userToken': self.userToken,
521
+ 'Domain': '.zzu.edu.cn',
522
+ 'Path': '/',
523
+ }
524
+
525
+ headers = {
526
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
527
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
528
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
529
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
530
+ 'sec-ch-ua-mobile': '?1',
531
+ 'sec-ch-ua-platform': '"Android"',
532
+ 'Upgrade-Insecure-Requests': '1',
533
+ 'x-id-token': self.userToken,
534
+ 'X-Requested-With': 'com.supwisdom.zzu',
535
+ 'Sec-Fetch-Site': 'none',
536
+ 'Sec-Fetch-Mode': 'navigate',
537
+ 'Sec-Fetch-User': '?1',
538
+ 'Sec-Fetch-Dest': 'document',
539
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
540
+ 'Cookie': f'userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
541
+ }
542
+
543
+ params = {
544
+ 'host': '11',
545
+ 'org': '2',
546
+ 'token': self.userToken,
547
+ }
548
+
549
+ response = httpx.get('https://ecard.v.zzu.edu.cn/server/auth/host/open', params=params, cookies=cookies,
550
+ headers=headers, follow_redirects=False)
551
+ JSESSIONID = response.headers['set-cookie'].split("=")[1].split(";")[0]
552
+ tid = response.headers['location'].split('=')[1].split("&")[0]
553
+ cookies = {
554
+ 'JSESSIONID': JSESSIONID,
555
+ 'userToken': self.userToken,
556
+ 'Domain': '.zzu.edu.cn',
557
+ 'Path': '/',
558
+ }
559
+
560
+ headers = {
561
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
562
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
563
+ 'Content-Type': 'application/json',
564
+ 'sec-ch-ua-platform': '"Android"',
565
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
566
+ 'sec-ch-ua-mobile': '?1',
567
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
568
+ 'X-Requested-With': 'com.supwisdom.zzu',
569
+ 'Sec-Fetch-Site': 'same-origin',
570
+ 'Sec-Fetch-Mode': 'cors',
571
+ 'Sec-Fetch-Dest': 'empty',
572
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
573
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
574
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
575
+ }
576
+
577
+ data = {
578
+ 'tid': tid,
579
+ }
580
+
581
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/auth/getToken', cookies=cookies, headers=headers,
582
+ json=data)
583
+ accessToken = json.loads(response.text)["resultData"]["accessToken"]
584
+ cookies = {
585
+ 'JSESSIONID': JSESSIONID,
586
+ 'userToken': self.userToken,
587
+ 'Domain': '.zzu.edu.cn',
588
+ 'Path': '/',
589
+ }
590
+
591
+ headers = {
592
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
593
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
594
+ 'Content-Type': 'application/json',
595
+ 'sec-ch-ua-platform': '"Android"',
596
+ 'Authorization': accessToken,
597
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
598
+ 'sec-ch-ua-mobile': '?1',
599
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
600
+ 'X-Requested-With': 'com.supwisdom.zzu',
601
+ 'Sec-Fetch-Site': 'same-origin',
602
+ 'Sec-Fetch-Mode': 'cors',
603
+ 'Sec-Fetch-Dest': 'empty',
604
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
605
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
606
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
607
+ }
608
+
609
+ data = {
610
+ 'utilityType': 'electric',
611
+ 'locationType': 'unit',
612
+ 'bigArea': '',
613
+ 'area': areaid,
614
+ 'building': buildingid,
615
+ 'unit': '',
616
+ 'level': '',
617
+ 'room': '',
618
+ 'subArea': '',
619
+ }
620
+
621
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/utilities/location', cookies=cookies,
622
+ headers=headers, json=data)
623
+ UnitDict = {}
624
+ for i in range(len(json.loads(response.text)["resultData"]["locationList"])):
625
+ UnitDict[json.loads(response.text)["resultData"]["locationList"][i]["id"]] = \
626
+ json.loads(response.text)["resultData"]["locationList"][i]["name"]
627
+ return UnitDict
628
+
629
+ def getRoomDict(self, areaid, buildingid, unitid):
630
+ """
631
+ 获取房间的字典
632
+ :param areaid: 通过getAreaDict()获取
633
+ :param buildingid: 通过getBuildingDict()获取
634
+ :param unitid: 通过getUnitDict()获取
635
+ :return: 房间字典
636
+ :rtype: dict
637
+ """
638
+ if self.isLogged == False:
639
+ error("RequireLogined")
640
+ if not self.DeviceParamsSet and not self.forceDeviceParams:
641
+ warn("Recommended set device parameters")
642
+ cookies = {
643
+ 'userToken': self.userToken,
644
+ 'Domain': '.zzu.edu.cn',
645
+ 'Path': '/',
646
+ }
647
+
648
+ headers = {
649
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
650
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
651
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
652
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
653
+ 'sec-ch-ua-mobile': '?1',
654
+ 'sec-ch-ua-platform': '"Android"',
655
+ 'Upgrade-Insecure-Requests': '1',
656
+ 'x-id-token': self.userToken,
657
+ 'X-Requested-With': 'com.supwisdom.zzu',
658
+ 'Sec-Fetch-Site': 'none',
659
+ 'Sec-Fetch-Mode': 'navigate',
660
+ 'Sec-Fetch-User': '?1',
661
+ 'Sec-Fetch-Dest': 'document',
662
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
663
+ 'Cookie': f'userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
664
+ }
665
+
666
+ params = {
667
+ 'host': '11',
668
+ 'org': '2',
669
+ 'token': self.userToken,
670
+ }
671
+
672
+ response = httpx.get('https://ecard.v.zzu.edu.cn/server/auth/host/open', params=params, cookies=cookies,
673
+ headers=headers, follow_redirects=False)
674
+ JSESSIONID = response.headers['set-cookie'].split("=")[1].split(";")[0]
675
+ tid = response.headers['location'].split('=')[1].split("&")[0]
676
+ cookies = {
677
+ 'JSESSIONID': JSESSIONID,
678
+ 'userToken': self.userToken,
679
+ 'Domain': '.zzu.edu.cn',
680
+ 'Path': '/',
681
+ }
682
+
683
+ headers = {
684
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
685
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
686
+ 'Content-Type': 'application/json',
687
+ 'sec-ch-ua-platform': '"Android"',
688
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
689
+ 'sec-ch-ua-mobile': '?1',
690
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
691
+ 'X-Requested-With': 'com.supwisdom.zzu',
692
+ 'Sec-Fetch-Site': 'same-origin',
693
+ 'Sec-Fetch-Mode': 'cors',
694
+ 'Sec-Fetch-Dest': 'empty',
695
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
696
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
697
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
698
+ }
699
+
700
+ data = {
701
+ 'tid': tid,
702
+ }
703
+
704
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/auth/getToken', cookies=cookies, headers=headers,
705
+ json=data)
706
+ accessToken = json.loads(response.text)["resultData"]["accessToken"]
707
+ cookies = {
708
+ 'JSESSIONID': JSESSIONID,
709
+ 'userToken': self.userToken,
710
+ 'Domain': '.zzu.edu.cn',
711
+ 'Path': '/',
712
+ }
713
+
714
+ headers = {
715
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
716
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
717
+ 'Content-Type': 'application/json',
718
+ 'sec-ch-ua-platform': '"Android"',
719
+ 'Authorization': accessToken,
720
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
721
+ 'sec-ch-ua-mobile': '?1',
722
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
723
+ 'X-Requested-With': 'com.supwisdom.zzu',
724
+ 'Sec-Fetch-Site': 'same-origin',
725
+ 'Sec-Fetch-Mode': 'cors',
726
+ 'Sec-Fetch-Dest': 'empty',
727
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
728
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
729
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
730
+ }
731
+
732
+ data = {
733
+ 'utilityType': 'electric',
734
+ 'locationType': 'room',
735
+ 'bigArea': '',
736
+ 'area': areaid,
737
+ 'building': buildingid,
738
+ 'unit': '',
739
+ 'level': unitid,
740
+ 'room': '',
741
+ 'subArea': '',
742
+ }
743
+
744
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/utilities/location', cookies=cookies,
745
+ headers=headers, json=data)
746
+ RoomDict = {}
747
+ for i in range(len(json.loads(response.text)["resultData"]["locationList"])):
748
+ RoomDict[json.loads(response.text)["resultData"]["locationList"][i]["id"]] = \
749
+ json.loads(response.text)["resultData"]["locationList"][i]["name"]
750
+ return RoomDict
751
+
752
+ def getRemainingPower(self, roomid):
753
+ """
754
+ 获取剩余电量
755
+ :param str roomid: 格式应为 “areaid-buildingid--unitid-roomid”,可通过getAreaDict(),getBuildingDict(),getUnitDict(),getRoomDict()获取
756
+ :return: 剩余电量
757
+ :rtype: float
758
+ """
759
+ if self.isLogged == False:
760
+ error("RequireLogined")
761
+ if not self.DeviceParamsSet and not self.forceDeviceParams:
762
+ warn("Recommended set device parameters")
763
+ cookies = {
764
+ 'userToken': self.userToken,
765
+ 'Domain': '.zzu.edu.cn',
766
+ 'Path': '/',
767
+ }
768
+
769
+ headers = {
770
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
771
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
772
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
773
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
774
+ 'sec-ch-ua-mobile': '?1',
775
+ 'sec-ch-ua-platform': '"Android"',
776
+ 'Upgrade-Insecure-Requests': '1',
777
+ 'x-id-token': self.userToken,
778
+ 'X-Requested-With': 'com.supwisdom.zzu',
779
+ 'Sec-Fetch-Site': 'none',
780
+ 'Sec-Fetch-Mode': 'navigate',
781
+ 'Sec-Fetch-User': '?1',
782
+ 'Sec-Fetch-Dest': 'document',
783
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
784
+ 'Cookie': f'userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
785
+ }
786
+
787
+ params = {
788
+ 'host': '11',
789
+ 'org': '2',
790
+ 'token': self.userToken,
791
+ }
792
+
793
+ response = httpx.get('https://ecard.v.zzu.edu.cn/server/auth/host/open', params=params, cookies=cookies,
794
+ headers=headers, follow_redirects=False)
795
+ JSESSIONID = response.headers['set-cookie'].split("=")[1].split(";")[0]
796
+ tid = response.headers['location'].split('=')[1].split("&")[0]
797
+ cookies = {
798
+ 'JSESSIONID': JSESSIONID,
799
+ 'userToken': self.userToken,
800
+ 'Domain': '.zzu.edu.cn',
801
+ 'Path': '/',
802
+ }
803
+
804
+ headers = {
805
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
806
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
807
+ 'Content-Type': 'application/json',
808
+ 'sec-ch-ua-platform': '"Android"',
809
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
810
+ 'sec-ch-ua-mobile': '?1',
811
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
812
+ 'X-Requested-With': 'com.supwisdom.zzu',
813
+ 'Sec-Fetch-Site': 'same-origin',
814
+ 'Sec-Fetch-Mode': 'cors',
815
+ 'Sec-Fetch-Dest': 'empty',
816
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
817
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
818
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
819
+ }
820
+
821
+ data = {
822
+ 'tid': tid,
823
+ }
824
+
825
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/auth/getToken', cookies=cookies, headers=headers,
826
+ json=data)
827
+ accessToken = json.loads(response.text)["resultData"]["accessToken"]
828
+
829
+ # bind 请求,似乎不必要还会花费大量时间
830
+
831
+ '''
832
+ AreaDict=self.getAreaDict()
833
+ BuildingDict=self.getBuildingDict(room.split("--")[0].split("-")[0])
834
+ UnitDict=self.getUnitDict(room.split("--")[0].split("-")[0],room.split("--")[0].split("-")[1])
835
+ RoomDict=self.getRoomDict(room.split("--")[0].split("-")[0],room.split("--")[0].split("-")[1],room.split("--")[1].split("-")[0])
836
+
837
+ cookies = {
838
+ 'JSESSIONID': JSESSIONID,
839
+ 'userToken': self.userToken,
840
+ 'Domain': '.zzu.edu.cn',
841
+ 'Path': '/',
842
+ }
843
+
844
+
845
+ headers = {
846
+ 'User-Agent': self.userAgentPrecursor+'SuperApp',
847
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
848
+ 'Content-Type': 'application/json',
849
+ 'sec-ch-ua-platform': '"Android"',
850
+ 'Authorization': accessToken,
851
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
852
+ 'sec-ch-ua-mobile': '?1',
853
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
854
+ 'X-Requested-With': 'com.supwisdom.zzu',
855
+ 'Sec-Fetch-Site': 'same-origin',
856
+ 'Sec-Fetch-Mode': 'cors',
857
+ 'Sec-Fetch-Dest': 'empty',
858
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
859
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
860
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
861
+ }
862
+
863
+ json_data = {
864
+ 'bigArea': '',
865
+ 'bigAreaName': '',
866
+ 'area': room.split("--")[0].split("-")[0],
867
+ 'areaName': AreaDict[room.split("--")[0].split("-")[0]],
868
+ 'building': room.split("--")[0].split("-")[1],
869
+ 'buildingName': BuildingDict[room.split("--")[0].split("-")[1]],
870
+ 'unit': '',
871
+ 'unitName': None,
872
+ 'level': room.split("--")[1].split("-")[0],
873
+ 'levelName': UnitDict[room.split("--")[1].split("-")[0]],
874
+ 'room': room,
875
+ 'roomName': RoomDict[room],
876
+ 'subArea': '',
877
+ 'subAreaName': None,
878
+ 'utilityType': 'electric',
879
+ 'locationType': 'room',
880
+ }
881
+
882
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/utilities/bind', cookies=cookies, headers=headers,
883
+ json=json_data)
884
+ '''
885
+
886
+ cookies = {
887
+ 'JSESSIONID': JSESSIONID,
888
+ 'userToken': self.userToken,
889
+ 'Domain': '.zzu.edu.cn',
890
+ 'Path': '/',
891
+ }
892
+
893
+ headers = {
894
+ 'User-Agent': self.userAgentPrecursor + 'SuperApp',
895
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
896
+ 'Content-Type': 'application/json',
897
+ 'sec-ch-ua-platform': '"Android"',
898
+ 'Authorization': accessToken,
899
+ 'sec-ch-ua': '"Android WebView";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
900
+ 'sec-ch-ua-mobile': '?1',
901
+ 'Origin': 'https://ecard.v.zzu.edu.cn',
902
+ 'X-Requested-With': 'com.supwisdom.zzu',
903
+ 'Sec-Fetch-Site': 'same-origin',
904
+ 'Sec-Fetch-Mode': 'cors',
905
+ 'Sec-Fetch-Dest': 'empty',
906
+ 'Referer': f'https://ecard.v.zzu.edu.cn/?tid={tid}&orgId=2',
907
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
908
+ 'Cookie': f'JSESSIONID={JSESSIONID}; userToken={self.userToken}; Domain=.zzu.edu.cn; Path=/',
909
+ }
910
+
911
+ data = {
912
+ 'utilityType': 'electric',
913
+ 'bigArea': '',
914
+ 'area': roomid.split("--")[0].split("-")[0],
915
+ 'building': roomid.split("--")[0].split("-")[1],
916
+ 'unit': '',
917
+ 'level': roomid.split("--")[1].split("-")[0],
918
+ 'room': roomid,
919
+ 'subArea': '',
920
+ }
921
+
922
+ response = httpx.post('https://ecard.v.zzu.edu.cn/server/utilities/account', cookies=cookies,
923
+ headers=headers, json=data)
924
+ return json.loads(response.text)["resultData"]["templateList"][3]["value"]