ezKit 1.11.0__tar.gz → 1.11.2__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.
- {ezkit-1.11.0/ezKit.egg-info → ezkit-1.11.2}/PKG-INFO +1 -1
- ezkit-1.11.2/ezKit/_file.py +36 -0
- ezkit-1.11.2/ezKit/qywx.py +296 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/utils.py +9 -16
- {ezkit-1.11.0 → ezkit-1.11.2/ezKit.egg-info}/PKG-INFO +1 -1
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit.egg-info/SOURCES.txt +1 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/setup.py +1 -1
- ezkit-1.11.0/ezKit/qywx.py +0 -189
- {ezkit-1.11.0 → ezkit-1.11.2}/LICENSE +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/MANIFEST.in +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/README.md +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/__init__.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/bottle.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/bottle_extensions.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/cipher.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/database.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/http.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/mongo.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/redis.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/sendemail.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/token.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit/xftp.py +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit.egg-info/dependency_links.txt +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit.egg-info/requires.txt +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/ezKit.egg-info/top_level.txt +0 -0
- {ezkit-1.11.0 → ezkit-1.11.2}/setup.cfg +0 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
from loguru import logger
|
2
|
+
|
3
|
+
from . import utils
|
4
|
+
|
5
|
+
|
6
|
+
def markdown_to_html(markdown_file: str, html_file: str, header_file: str = "markdown.html") -> bool:
|
7
|
+
"""Markdown to HTML"""
|
8
|
+
|
9
|
+
# Markdown to HTML
|
10
|
+
# 使用 MacDown 生成 HTML, 然后提取样式到 markdown.html
|
11
|
+
# pandoc 生成的 HTML 默认 max-width: 36em, 如果表格内容很长, 会导致表格样式难看
|
12
|
+
# 所以在 markdown.html 的 body{...} 中添加配置 max-width: unset, 解决内容过长的样式问题
|
13
|
+
# 所有 a 标签添加 text-decoration: none; 去除链接下划线
|
14
|
+
# pandoc --no-highlight -s --quiet -f markdown -t html -H markdown.html -o data.html data.md
|
15
|
+
|
16
|
+
info: str = "markdown to html"
|
17
|
+
|
18
|
+
logger.info(f"{info} ......")
|
19
|
+
|
20
|
+
try:
|
21
|
+
|
22
|
+
result = utils.shell(
|
23
|
+
f"pandoc --no-highlight -s --quiet -f markdown -t html -H {header_file} -o {html_file} {markdown_file}"
|
24
|
+
)
|
25
|
+
|
26
|
+
if result is None or result.returncode != 0:
|
27
|
+
logger.error(f"{info} [failure]")
|
28
|
+
return False
|
29
|
+
|
30
|
+
logger.success(f"{info} [success]")
|
31
|
+
return True
|
32
|
+
|
33
|
+
except Exception as e:
|
34
|
+
logger.error(f"{info} [failure]")
|
35
|
+
logger.exception(e)
|
36
|
+
return False
|
@@ -0,0 +1,296 @@
|
|
1
|
+
"""企业微信"""
|
2
|
+
#
|
3
|
+
# 企业微信开发者中心
|
4
|
+
# https://developer.work.weixin.qq.com/
|
5
|
+
# https://developer.work.weixin.qq.com/document/path/90313 (全局错误码)
|
6
|
+
# 参考文档:
|
7
|
+
# https://www.gaoyuanqi.cn/python-yingyong-qiyewx/
|
8
|
+
# https://www.jianshu.com/p/020709b130d3
|
9
|
+
#
|
10
|
+
# 应用管理
|
11
|
+
# https://work.weixin.qq.com/wework_admin/frame#apps
|
12
|
+
# 自建 -> 创建应用
|
13
|
+
# https://work.weixin.qq.com/wework_admin/frame#apps/createApiApp
|
14
|
+
# 上传 Logo -> 应用名称 -> 选择部门 / 成员 -> 创建应用
|
15
|
+
#
|
16
|
+
# 服务端API
|
17
|
+
# https://developer.work.weixin.qq.com/document/path/90664
|
18
|
+
# 基本概念
|
19
|
+
# https://developer.work.weixin.qq.com/document/path/90665
|
20
|
+
# 企业ID:
|
21
|
+
# https://work.weixin.qq.com/wework_admin/frame#profile
|
22
|
+
# AgentId 和 Secret:
|
23
|
+
# 进入已创建的应用, 即可获取
|
24
|
+
#
|
25
|
+
# 应用管理 -> 应用 -> 开发者接口 -> 网页授权及JS-SDK
|
26
|
+
#
|
27
|
+
# 可作为应用OAuth2.0网页授权功能的回调域名
|
28
|
+
# 下载 配置可信域名需完成域名归属认证 的文件
|
29
|
+
# 保存到域名下
|
30
|
+
# 配置可信域名需完成域名归属认证 已验证
|
31
|
+
#
|
32
|
+
# 应用管理 -> 应用 -> 开发者接口 -> 企业可信IP
|
33
|
+
#
|
34
|
+
# 添加IP
|
35
|
+
#
|
36
|
+
import json
|
37
|
+
import time
|
38
|
+
|
39
|
+
import requests
|
40
|
+
from loguru import logger
|
41
|
+
|
42
|
+
from . import utils
|
43
|
+
|
44
|
+
|
45
|
+
class QYWX:
|
46
|
+
"""企业微信"""
|
47
|
+
|
48
|
+
# API前缀
|
49
|
+
api_prefix = "https://qyapi.weixin.qq.com"
|
50
|
+
|
51
|
+
# 企业ID: https://developer.work.weixin.qq.com/document/path/90665#corpid
|
52
|
+
work_id: str = ""
|
53
|
+
|
54
|
+
# 应用ID: https://developer.work.weixin.qq.com/document/path/90665#agentid
|
55
|
+
agent_id: str = ""
|
56
|
+
|
57
|
+
# 应用Secret: https://developer.work.weixin.qq.com/document/path/90665#secret
|
58
|
+
agent_secret: str = ""
|
59
|
+
|
60
|
+
# Token: https://developer.work.weixin.qq.com/document/path/90665#access-token
|
61
|
+
access_token: str = ""
|
62
|
+
|
63
|
+
def __init__(self, work_id: str, agent_id: str, agent_secret: str):
|
64
|
+
"""Initiation"""
|
65
|
+
self.work_id = work_id
|
66
|
+
self.agent_id = agent_id
|
67
|
+
self.agent_secret = agent_secret
|
68
|
+
|
69
|
+
"""获取 Token"""
|
70
|
+
self.get_access_token()
|
71
|
+
|
72
|
+
def get_access_token(self) -> bool:
|
73
|
+
"""获取Token"""
|
74
|
+
|
75
|
+
info: str = "获取 Token"
|
76
|
+
|
77
|
+
try:
|
78
|
+
|
79
|
+
logger.info(f"{info} ......")
|
80
|
+
|
81
|
+
response = requests.get(f"{self.api_prefix}/cgi-bin/gettoken?corpid={self.work_id}&corpsecret={self.agent_secret}", timeout=10)
|
82
|
+
|
83
|
+
if response.status_code != 200:
|
84
|
+
logger.error(f"{info} [状态码错误]")
|
85
|
+
return False
|
86
|
+
|
87
|
+
result: dict = response.json()
|
88
|
+
|
89
|
+
self.access_token = result.get("access_token", "")
|
90
|
+
|
91
|
+
if not utils.isTrue(self.access_token, str):
|
92
|
+
logger.error(f"{info} [失败]")
|
93
|
+
return False
|
94
|
+
|
95
|
+
logger.success(f"{info} [成功]")
|
96
|
+
return True
|
97
|
+
|
98
|
+
except Exception as e:
|
99
|
+
logger.success(f"{info} [失败]")
|
100
|
+
logger.exception(e)
|
101
|
+
return False
|
102
|
+
|
103
|
+
# def get_agent_list(self) -> dict | str | None:
|
104
|
+
# try:
|
105
|
+
# if not utils.isTrue(self.access_token, str):
|
106
|
+
# self.get_access_token()
|
107
|
+
# response = requests.get(f"{self.api_prefix}/cgi-bin/agent/list?access_token={self.access_token}", timeout=10)
|
108
|
+
# if response.status_code == 200:
|
109
|
+
# response_data: dict = response.json()
|
110
|
+
# if response_data.get('errcode') == 42001:
|
111
|
+
# self.get_access_token()
|
112
|
+
# time.sleep(1)
|
113
|
+
# self.get_agent_list()
|
114
|
+
# return response_data
|
115
|
+
# return response.text
|
116
|
+
# except Exception as e:
|
117
|
+
# logger.exception(e)
|
118
|
+
# return None
|
119
|
+
|
120
|
+
# def get_department_list(self, eid: str | None = None) -> dict | str | None:
|
121
|
+
# """eid: Enterprise ID"""
|
122
|
+
# try:
|
123
|
+
# if self.access_token is None:
|
124
|
+
# self.get_access_token()
|
125
|
+
# response = requests.get(f"{self.api_prefix}/cgi-bin/department/list?access_token={self.access_token}&id={eid}", timeout=10)
|
126
|
+
# if response.status_code == 200:
|
127
|
+
# response_data: dict = response.json()
|
128
|
+
# if response_data.get('errcode') == 42001:
|
129
|
+
# self.get_access_token()
|
130
|
+
# time.sleep(1)
|
131
|
+
# self.get_department_list(eid)
|
132
|
+
# return response_data
|
133
|
+
# return response.text
|
134
|
+
# except Exception as e:
|
135
|
+
# logger.exception(e)
|
136
|
+
# return None
|
137
|
+
|
138
|
+
# def get_user_list(self, eid: str | None = None) -> dict | str | None:
|
139
|
+
# """eid: Enterprise ID"""
|
140
|
+
# try:
|
141
|
+
# if self.access_token is None:
|
142
|
+
# self.get_access_token()
|
143
|
+
# response = requests.get(f"{self.api_prefix}/cgi-bin/user/list?access_token={self.access_token}&department_id={eid}", timeout=10)
|
144
|
+
# if response.status_code == 200:
|
145
|
+
# response_data: dict = response.json()
|
146
|
+
# if response_data.get('errcode') == 42001:
|
147
|
+
# self.get_access_token()
|
148
|
+
# time.sleep(1)
|
149
|
+
# self.get_user_list(eid)
|
150
|
+
# return response_data
|
151
|
+
# return response.text
|
152
|
+
# except Exception as e:
|
153
|
+
# logger.exception(e)
|
154
|
+
# return None
|
155
|
+
|
156
|
+
def get_user_id_by_mobile(self, mobile: str) -> dict | None:
|
157
|
+
"""根据电话号码获取用户ID"""
|
158
|
+
|
159
|
+
info: str = f"根据电话号码获取用户ID: {mobile}"
|
160
|
+
|
161
|
+
if not utils.check_arguments([(mobile, str, "mobile")]):
|
162
|
+
logger.error(f"{info} [错误]")
|
163
|
+
return None
|
164
|
+
|
165
|
+
try:
|
166
|
+
|
167
|
+
logger.info(f"{info} ......")
|
168
|
+
|
169
|
+
if not utils.isTrue(self.access_token, str):
|
170
|
+
self.get_access_token()
|
171
|
+
|
172
|
+
json_string = json.dumps({'mobile': mobile})
|
173
|
+
|
174
|
+
response = requests.post(f"{self.api_prefix}/cgi-bin/user/getuserid?access_token={self.access_token}", data=json_string, timeout=10)
|
175
|
+
|
176
|
+
if response.status_code != 200:
|
177
|
+
logger.error(f"{info} [接口请求错误]")
|
178
|
+
return None
|
179
|
+
|
180
|
+
response_data: dict = response.json()
|
181
|
+
|
182
|
+
if response_data.get('errcode') == 42001:
|
183
|
+
self.get_access_token()
|
184
|
+
time.sleep(1)
|
185
|
+
self.get_user_id_by_mobile(mobile)
|
186
|
+
|
187
|
+
logger.success(f"{info} [成功]")
|
188
|
+
|
189
|
+
return response_data
|
190
|
+
|
191
|
+
# return response.text
|
192
|
+
|
193
|
+
except Exception as e:
|
194
|
+
logger.error(f"{info} [失败]")
|
195
|
+
logger.exception(e)
|
196
|
+
return None
|
197
|
+
|
198
|
+
# def get_user_info(self, eid: str | None = None) -> dict | str | None:
|
199
|
+
# """eid: Enterprise ID"""
|
200
|
+
# try:
|
201
|
+
# if self.access_token is None:
|
202
|
+
# self.get_access_token()
|
203
|
+
# response = requests.get(f"{self.api_prefix}/cgi-bin/user/get?access_token={self.access_token}&userid={eid}", timeout=10)
|
204
|
+
# if response.status_code == 200:
|
205
|
+
# response_data: dict = response.json()
|
206
|
+
# if response_data.get('errcode') == 42001:
|
207
|
+
# self.get_access_token()
|
208
|
+
# time.sleep(1)
|
209
|
+
# self.get_user_info(eid)
|
210
|
+
# return response_data
|
211
|
+
# return response.text
|
212
|
+
# except Exception as e:
|
213
|
+
# logger.exception(e)
|
214
|
+
# return None
|
215
|
+
|
216
|
+
def send_message_by_mobile(self, mobile: str | list, message: str) -> bool:
|
217
|
+
"""发送消息"""
|
218
|
+
|
219
|
+
# 参考文档:
|
220
|
+
# https://developer.work.weixin.qq.com/document/path/90235
|
221
|
+
|
222
|
+
info: str = "发送消息"
|
223
|
+
|
224
|
+
if not utils.check_arguments([(mobile, (str, list), "mobile"), (message, str, "message")]):
|
225
|
+
logger.error(f"{info} [失败]")
|
226
|
+
return False
|
227
|
+
|
228
|
+
try:
|
229
|
+
|
230
|
+
logger.info(f"{info} ......")
|
231
|
+
|
232
|
+
if not utils.isTrue(self.access_token, str):
|
233
|
+
if not self.get_access_token():
|
234
|
+
logger.error(f"{info} [失败]")
|
235
|
+
return False
|
236
|
+
|
237
|
+
users: list = []
|
238
|
+
|
239
|
+
if isinstance(mobile, str) and utils.isTrue(mobile, str):
|
240
|
+
users.append(mobile)
|
241
|
+
elif isinstance(mobile, list) and utils.isTrue(mobile, list):
|
242
|
+
users += mobile
|
243
|
+
else:
|
244
|
+
logger.error(f"{info} [电话号码错误]")
|
245
|
+
return False
|
246
|
+
|
247
|
+
for user in users:
|
248
|
+
|
249
|
+
logger.info(f"{info} [用户 {user}]")
|
250
|
+
|
251
|
+
user_object = self.get_user_id_by_mobile(user)
|
252
|
+
|
253
|
+
if not (isinstance(user_object, dict) and utils.isTrue(user_object, dict)):
|
254
|
+
logger.error(f"{info} [获取用户ID错误: {user}]")
|
255
|
+
continue
|
256
|
+
|
257
|
+
if user_object.get("errcode", -1) != 0 or user_object.get("errmsg", "") != "ok":
|
258
|
+
logger.error(f"{user_object.get('errcode')}: {user_object.get('errmsg')}")
|
259
|
+
continue
|
260
|
+
|
261
|
+
json_dict = {
|
262
|
+
'touser': user_object.get('userid'),
|
263
|
+
'msgtype': 'text',
|
264
|
+
'agentid': self.agent_id,
|
265
|
+
'text': {'content': message},
|
266
|
+
'safe': 0,
|
267
|
+
'enable_id_trans': 0,
|
268
|
+
'enable_duplicate_check': 0,
|
269
|
+
'duplicate_check_interval': 1800
|
270
|
+
}
|
271
|
+
|
272
|
+
json_string = json.dumps(json_dict)
|
273
|
+
|
274
|
+
response = requests.post(f"{self.api_prefix}/cgi-bin/message/send?access_token={self.access_token}", data=json_string, timeout=10)
|
275
|
+
|
276
|
+
if response.status_code != 200:
|
277
|
+
logger.error(f"{info} [发送消息失败: {user}]")
|
278
|
+
continue
|
279
|
+
|
280
|
+
response_data: dict = response.json()
|
281
|
+
|
282
|
+
if response_data.get('errcode') == 42001:
|
283
|
+
self.get_access_token()
|
284
|
+
time.sleep(1)
|
285
|
+
self.send_message_by_mobile(mobile, message)
|
286
|
+
|
287
|
+
logger.success(f"{info} [成功: 用户 {user}]")
|
288
|
+
|
289
|
+
logger.success(f"{info} [完成]")
|
290
|
+
|
291
|
+
return True
|
292
|
+
|
293
|
+
except Exception as e:
|
294
|
+
logger.error(f"{info} [失败]")
|
295
|
+
logger.exception(e)
|
296
|
+
return False
|
@@ -418,26 +418,19 @@ def list_print_by_step(
|
|
418
418
|
|
419
419
|
try:
|
420
420
|
|
421
|
-
# result: list = []
|
422
|
-
|
423
|
-
# if len(data) <= step:
|
424
|
-
# result.append(data)
|
425
|
-
# else:
|
426
|
-
# data_list = list_split(data, step, debug=debug)
|
427
|
-
# if data_list is None or isTrue(data_list, list) is False:
|
428
|
-
# return False
|
429
|
-
# result = data_list
|
430
|
-
|
431
|
-
# for item in result:
|
432
|
-
# print(*item, sep=separator)
|
433
|
-
|
434
|
-
# return True
|
435
|
-
|
436
421
|
# 打印
|
437
422
|
for i, v in enumerate(data):
|
423
|
+
|
438
424
|
if i > 0 and i % step == 0:
|
439
425
|
print()
|
440
|
-
|
426
|
+
|
427
|
+
# print(v, end=separator)
|
428
|
+
|
429
|
+
# 每行最后一个 或者 所有数据最后一个, 不打印分隔符
|
430
|
+
if ((i % step) == (step - 1)) or ((i + 1) == len(data)):
|
431
|
+
print(v, end='')
|
432
|
+
else:
|
433
|
+
print(v, end=separator)
|
441
434
|
|
442
435
|
print()
|
443
436
|
|
ezkit-1.11.0/ezKit/qywx.py
DELETED
@@ -1,189 +0,0 @@
|
|
1
|
-
"""企业微信"""
|
2
|
-
# 企业微信开发者中心
|
3
|
-
# https://developer.work.weixin.qq.com/
|
4
|
-
# https://developer.work.weixin.qq.com/document/path/90313 (全局错误码)
|
5
|
-
# 参考文档:
|
6
|
-
# https://www.gaoyuanqi.cn/python-yingyong-qiyewx/
|
7
|
-
# https://www.jianshu.com/p/020709b130d3
|
8
|
-
import json
|
9
|
-
import time
|
10
|
-
|
11
|
-
import requests
|
12
|
-
from loguru import logger
|
13
|
-
|
14
|
-
from . import utils
|
15
|
-
|
16
|
-
|
17
|
-
class QYWX:
|
18
|
-
"""企业微信"""
|
19
|
-
|
20
|
-
url_prefix = "https://qyapi.weixin.qq.com"
|
21
|
-
work_id: str | None = None
|
22
|
-
agent_id: str | None = None
|
23
|
-
agent_secret: str | None = None
|
24
|
-
access_token: str | None = None
|
25
|
-
|
26
|
-
def __init__(self, work_id: str | None, agent_id: str | None, agent_secret: str | None):
|
27
|
-
"""Initiation"""
|
28
|
-
self.work_id = work_id
|
29
|
-
self.agent_id = agent_id
|
30
|
-
self.agent_secret = agent_secret
|
31
|
-
|
32
|
-
"""获取 Token"""
|
33
|
-
self.getaccess_token()
|
34
|
-
|
35
|
-
def getaccess_token(self) -> str | None:
|
36
|
-
try:
|
37
|
-
response = requests.get(f"{self.url_prefix}/cgi-bin/gettoken?corpid={self.work_id}&corpsecret={self.agent_secret}", timeout=10)
|
38
|
-
|
39
|
-
if response.status_code != 200:
|
40
|
-
self.access_token = None
|
41
|
-
return None
|
42
|
-
|
43
|
-
result: dict = response.json()
|
44
|
-
self.access_token = result.get('access_token')
|
45
|
-
return result.get('access_token')
|
46
|
-
|
47
|
-
except Exception as e:
|
48
|
-
logger.exception(e)
|
49
|
-
return None
|
50
|
-
|
51
|
-
def get_agent_list(self) -> dict | str | None:
|
52
|
-
try:
|
53
|
-
if self.access_token is None:
|
54
|
-
self.getaccess_token()
|
55
|
-
response = requests.get(f"{self.url_prefix}/cgi-bin/agent/list?access_token={self.access_token}", timeout=10)
|
56
|
-
if response.status_code == 200:
|
57
|
-
response_data: dict = response.json()
|
58
|
-
if response_data.get('errcode') == 42001:
|
59
|
-
self.getaccess_token()
|
60
|
-
time.sleep(1)
|
61
|
-
self.get_agent_list()
|
62
|
-
return response_data
|
63
|
-
return response.text
|
64
|
-
except Exception as e:
|
65
|
-
logger.exception(e)
|
66
|
-
return None
|
67
|
-
|
68
|
-
def get_department_list(self, eid: str | None = None) -> dict | str | None:
|
69
|
-
"""eid: Enterprise ID"""
|
70
|
-
try:
|
71
|
-
if self.access_token is None:
|
72
|
-
self.getaccess_token()
|
73
|
-
response = requests.get(f"{self.url_prefix}/cgi-bin/department/list?access_token={self.access_token}&id={eid}", timeout=10)
|
74
|
-
if response.status_code == 200:
|
75
|
-
response_data: dict = response.json()
|
76
|
-
if response_data.get('errcode') == 42001:
|
77
|
-
self.getaccess_token()
|
78
|
-
time.sleep(1)
|
79
|
-
self.get_department_list(eid)
|
80
|
-
return response_data
|
81
|
-
return response.text
|
82
|
-
except Exception as e:
|
83
|
-
logger.exception(e)
|
84
|
-
return None
|
85
|
-
|
86
|
-
def get_user_list(self, eid: str | None = None) -> dict | str | None:
|
87
|
-
"""eid: Enterprise ID"""
|
88
|
-
try:
|
89
|
-
if self.access_token is None:
|
90
|
-
self.getaccess_token()
|
91
|
-
response = requests.get(f"{self.url_prefix}/cgi-bin/user/list?access_token={self.access_token}&department_id={eid}", timeout=10)
|
92
|
-
if response.status_code == 200:
|
93
|
-
response_data: dict = response.json()
|
94
|
-
if response_data.get('errcode') == 42001:
|
95
|
-
self.getaccess_token()
|
96
|
-
time.sleep(1)
|
97
|
-
self.get_user_list(eid)
|
98
|
-
return response_data
|
99
|
-
return response.text
|
100
|
-
except Exception as e:
|
101
|
-
logger.exception(e)
|
102
|
-
return None
|
103
|
-
|
104
|
-
def get_user_id_by_mobile(self, mobile: str | None = None) -> dict | str | None:
|
105
|
-
try:
|
106
|
-
if self.access_token is None:
|
107
|
-
self.getaccess_token()
|
108
|
-
json_string = json.dumps({'mobile': mobile})
|
109
|
-
response = requests.post(f"{self.url_prefix}/cgi-bin/user/getuserid?access_token={self.access_token}", data=json_string, timeout=10)
|
110
|
-
if response.status_code == 200:
|
111
|
-
response_data: dict = response.json()
|
112
|
-
if response_data.get('errcode') == 42001:
|
113
|
-
self.getaccess_token()
|
114
|
-
time.sleep(1)
|
115
|
-
self.get_user_id_by_mobile(mobile)
|
116
|
-
return response_data
|
117
|
-
return response.text
|
118
|
-
except Exception as e:
|
119
|
-
logger.exception(e)
|
120
|
-
return None
|
121
|
-
|
122
|
-
def get_user_info(self, eid: str | None = None) -> dict | str | None:
|
123
|
-
"""eid: Enterprise ID"""
|
124
|
-
try:
|
125
|
-
if self.access_token is None:
|
126
|
-
self.getaccess_token()
|
127
|
-
response = requests.get(f"{self.url_prefix}/cgi-bin/user/get?access_token={self.access_token}&userid={eid}", timeout=10)
|
128
|
-
if response.status_code == 200:
|
129
|
-
response_data: dict = response.json()
|
130
|
-
if response_data.get('errcode') == 42001:
|
131
|
-
self.getaccess_token()
|
132
|
-
time.sleep(1)
|
133
|
-
self.get_user_info(eid)
|
134
|
-
return response_data
|
135
|
-
return response.text
|
136
|
-
except Exception as e:
|
137
|
-
logger.exception(e)
|
138
|
-
return None
|
139
|
-
|
140
|
-
def send_message_by_mobile(self, mobile: str | list, message: str) -> bool:
|
141
|
-
"""发送消息"""
|
142
|
-
|
143
|
-
# 参考文档:
|
144
|
-
# https://developer.work.weixin.qq.com/document/path/90235
|
145
|
-
|
146
|
-
try:
|
147
|
-
if self.access_token is None:
|
148
|
-
self.getaccess_token()
|
149
|
-
|
150
|
-
users: list = []
|
151
|
-
|
152
|
-
match True:
|
153
|
-
case True if isinstance(mobile, list) and utils.isTrue(mobile, list):
|
154
|
-
users = mobile
|
155
|
-
case True if isinstance(mobile, str) and utils.isTrue(mobile, str):
|
156
|
-
users.append(mobile)
|
157
|
-
case _:
|
158
|
-
return False
|
159
|
-
|
160
|
-
for user in users:
|
161
|
-
user_object = self.get_user_id_by_mobile(user)
|
162
|
-
|
163
|
-
if not isinstance(user_object, dict):
|
164
|
-
continue
|
165
|
-
|
166
|
-
json_dict = {
|
167
|
-
'touser': user_object.get('userid'),
|
168
|
-
'msgtype': 'text',
|
169
|
-
'agentid': self.agent_id,
|
170
|
-
'text': {'content': message},
|
171
|
-
'safe': 0,
|
172
|
-
'enable_id_trans': 0,
|
173
|
-
'enable_duplicate_check': 0,
|
174
|
-
'duplicate_check_interval': 1800
|
175
|
-
}
|
176
|
-
json_string = json.dumps(json_dict)
|
177
|
-
response = requests.post(f"{self.url_prefix}/cgi-bin/message/send?access_token={self.access_token}", data=json_string, timeout=10)
|
178
|
-
if response.status_code == 200:
|
179
|
-
response_data: dict = response.json()
|
180
|
-
if response_data.get('errcode') == 42001:
|
181
|
-
self.getaccess_token()
|
182
|
-
time.sleep(1)
|
183
|
-
self.send_message_by_mobile(mobile, message)
|
184
|
-
|
185
|
-
return True
|
186
|
-
|
187
|
-
except Exception as e:
|
188
|
-
logger.exception(e)
|
189
|
-
return False
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|