ChatECNU 0.2.0__tar.gz → 0.2.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.
- chatecnu-0.2.2/MANIFEST.in +1 -0
- chatecnu-0.2.2/PKG-INFO +113 -0
- chatecnu-0.2.2/README.md +77 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/pyproject.toml +4 -1
- chatecnu-0.2.2/src/ChatECNU.egg-info/PKG-INFO +113 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/ChatECNU.egg-info/SOURCES.txt +2 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/ChatECNU.egg-info/requires.txt +1 -1
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/__init__.py +1 -1
- chatecnu-0.2.2/src/chatecnu/bin/linux-x86_64/auth_client +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/ecnu/cli.py +135 -11
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/network_auth.py +133 -9
- chatecnu-0.2.2/tests/test_cli.py +114 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/tests/test_network_auth.py +76 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/tests/test_version.py +2 -2
- chatecnu-0.2.0/PKG-INFO +0 -92
- chatecnu-0.2.0/README.md +0 -56
- chatecnu-0.2.0/src/ChatECNU.egg-info/PKG-INFO +0 -92
- chatecnu-0.2.0/tests/test_cli.py +0 -59
- {chatecnu-0.2.0 → chatecnu-0.2.2}/LICENSE +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/setup.cfg +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/ChatECNU.egg-info/dependency_links.txt +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/ChatECNU.egg-info/entry_points.txt +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/ChatECNU.egg-info/top_level.txt +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/cli.py +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/config.py +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/ecnu/__init__.py +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/ecnu/captcha.py +0 -0
- {chatecnu-0.2.0 → chatecnu-0.2.2}/src/chatecnu/ecnu/portal.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include src/chatecnu/bin/linux-x86_64/auth_client
|
chatecnu-0.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ChatECNU
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: ChatArch ECNU campus portal automation CLI
|
|
5
|
+
Author-email: ChatArch <1073853456@qq.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ChatArch/ChatECNU
|
|
8
|
+
Project-URL: Repository, https://github.com/ChatArch/ChatECNU
|
|
9
|
+
Project-URL: Documentation, https://arch.gh.wzhecnu.cn/ChatECNU/
|
|
10
|
+
Keywords: chatecnu,chatarch,ecnu,campus,portal
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: click>=8.0
|
|
17
|
+
Requires-Dist: chatstyle<0.2.0,>=0.1.0
|
|
18
|
+
Requires-Dist: chatenv<0.3.0,>=0.2.4
|
|
19
|
+
Requires-Dist: ChatNet<0.3.0,>=0.2.0
|
|
20
|
+
Requires-Dist: requests>=2.0
|
|
21
|
+
Requires-Dist: pycryptodome>=3.0
|
|
22
|
+
Provides-Extra: captcha
|
|
23
|
+
Requires-Dist: ddddocr; extra == "captcha"
|
|
24
|
+
Requires-Dist: numpy; extra == "captcha"
|
|
25
|
+
Requires-Dist: pillow; extra == "captcha"
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest; extra == "dev"
|
|
29
|
+
Requires-Dist: twine; extra == "dev"
|
|
30
|
+
Provides-Extra: docs
|
|
31
|
+
Requires-Dist: mkdocs<2.0,>=1.6; extra == "docs"
|
|
32
|
+
Requires-Dist: mkdocs-material<9.7,>=9.5; extra == "docs"
|
|
33
|
+
Requires-Dist: mkdocs-static-i18n<2.0,>=1.2; extra == "docs"
|
|
34
|
+
Requires-Dist: mike<3.0,>=2.0; extra == "docs"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# ChatECNU
|
|
38
|
+
|
|
39
|
+
ChatECNU 是 ECNU 门户与校园网联网工具包。安装包名仍是 `ChatECNU`,日常命令主推 `ecnu`。
|
|
40
|
+
|
|
41
|
+
## 文档入口
|
|
42
|
+
|
|
43
|
+
| 任务 | 链接 |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| 安装和最小验证 | https://arch.gh.wzhecnu.cn/ChatECNU/quickstart/ |
|
|
46
|
+
| 命令树 | https://arch.gh.wzhecnu.cn/ChatECNU/cli-tree/ |
|
|
47
|
+
| ChatEnv 变量 | https://arch.gh.wzhecnu.cn/ChatECNU/chatenv/ |
|
|
48
|
+
| ECNU 使用 | https://arch.gh.wzhecnu.cn/ChatECNU/ecnu/ |
|
|
49
|
+
|
|
50
|
+
## 安装
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install ChatECNU
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
如需验证码识别能力:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install "ChatECNU[captcha]"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 命令结构
|
|
63
|
+
|
|
64
|
+
ChatECNU 的命令面可用 `ecnu --tree` 从当前 Click 注册表直接回读:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
ecnu
|
|
68
|
+
├── --help # Show this message and exit.
|
|
69
|
+
├── --version # Show the installed ChatECNU version.
|
|
70
|
+
├── --tree # Print this registered command tree and exit.
|
|
71
|
+
├── --env ENV-PROFILE # ChatEnv 配置名。
|
|
72
|
+
├── home # ECNU 门户。
|
|
73
|
+
│ ├── info [--json] # 门户首页摘要。
|
|
74
|
+
│ ├── login [--username USERNAME] [--password PASSWORD] [--sms-code SMS-CODE] [--json] [--interactive] # 登录门户。
|
|
75
|
+
│ ├── logout [--json] # 退出门户会话。
|
|
76
|
+
│ ├── status [--json] # 门户会话状态。
|
|
77
|
+
│ └── user [--json] # 门户用户信息。
|
|
78
|
+
├── net # 校园网联网。
|
|
79
|
+
│ ├── check [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--json] # 检查在线状态。
|
|
80
|
+
│ ├── ensure-login [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--password PASSWORD] [--allow-argv-password] [--json] [--interactive] # 离线时登录。
|
|
81
|
+
│ ├── login [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--password PASSWORD] [--allow-argv-password] [--json] [--interactive] # 登录。
|
|
82
|
+
│ └── logout [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--json] [--interactive] # 退出校园网。
|
|
83
|
+
└── visitor # 访客账号。
|
|
84
|
+
├── create [--remark REMARK] [--dry-run] [--json] [--interactive] # 创建访客账号。
|
|
85
|
+
├── default [--password1 PASSWORD1] [--password2 PASSWORD2] [--remark REMARK] [--json] [--interactive] # 维护默认访客账号。
|
|
86
|
+
├── delete [--id VISITOR-ID] [--dry-run] [--json] [--interactive] # 删除访客账号。
|
|
87
|
+
├── get [--id VISITOR-ID] [--account ACCOUNT] [--json] # 查询访客账号。
|
|
88
|
+
├── list [--json] # 列出访客账号。
|
|
89
|
+
└── update [--id VISITOR-ID] [--remark REMARK] [--password PASSWORD] [--dry-run] [--json] [--interactive] # 更新访客备注和密码。
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
门户命令统一放在 `home` 下:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
ecnu home login -i
|
|
96
|
+
ecnu home info
|
|
97
|
+
ecnu home status
|
|
98
|
+
ecnu home user
|
|
99
|
+
ecnu home logout
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
校园网联网统一放在 `net` 下:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
ecnu net check --json
|
|
106
|
+
ecnu net login -I --allow-argv-password
|
|
107
|
+
ecnu net logout -I
|
|
108
|
+
ecnu net ensure-login -I --allow-argv-password
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
ChatECNU 的 PyPI wheel/sdist 内置 Linux x86_64 `auth_client`,默认 `ecnu net ...` 会优先使用该内置二进制;如需覆盖,可用 `--auth-client` 或 `ECNU_AUTH_CLIENT` 指定路径。账号密码使用同一组 `ECNU_USERNAME` / `ECNU_PASSWORD`。`net check` 会显示当前 `online/account/username`;`net logout` 未提供用户名时会先从 `auth_client check` 的 `Username=...` 自动提取。
|
|
112
|
+
|
|
113
|
+
敏感值(密码、Cookie、短信码、会话)不要打印或提交。
|
chatecnu-0.2.2/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# ChatECNU
|
|
2
|
+
|
|
3
|
+
ChatECNU 是 ECNU 门户与校园网联网工具包。安装包名仍是 `ChatECNU`,日常命令主推 `ecnu`。
|
|
4
|
+
|
|
5
|
+
## 文档入口
|
|
6
|
+
|
|
7
|
+
| 任务 | 链接 |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| 安装和最小验证 | https://arch.gh.wzhecnu.cn/ChatECNU/quickstart/ |
|
|
10
|
+
| 命令树 | https://arch.gh.wzhecnu.cn/ChatECNU/cli-tree/ |
|
|
11
|
+
| ChatEnv 变量 | https://arch.gh.wzhecnu.cn/ChatECNU/chatenv/ |
|
|
12
|
+
| ECNU 使用 | https://arch.gh.wzhecnu.cn/ChatECNU/ecnu/ |
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install ChatECNU
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
如需验证码识别能力:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install "ChatECNU[captcha]"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 命令结构
|
|
27
|
+
|
|
28
|
+
ChatECNU 的命令面可用 `ecnu --tree` 从当前 Click 注册表直接回读:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
ecnu
|
|
32
|
+
├── --help # Show this message and exit.
|
|
33
|
+
├── --version # Show the installed ChatECNU version.
|
|
34
|
+
├── --tree # Print this registered command tree and exit.
|
|
35
|
+
├── --env ENV-PROFILE # ChatEnv 配置名。
|
|
36
|
+
├── home # ECNU 门户。
|
|
37
|
+
│ ├── info [--json] # 门户首页摘要。
|
|
38
|
+
│ ├── login [--username USERNAME] [--password PASSWORD] [--sms-code SMS-CODE] [--json] [--interactive] # 登录门户。
|
|
39
|
+
│ ├── logout [--json] # 退出门户会话。
|
|
40
|
+
│ ├── status [--json] # 门户会话状态。
|
|
41
|
+
│ └── user [--json] # 门户用户信息。
|
|
42
|
+
├── net # 校园网联网。
|
|
43
|
+
│ ├── check [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--json] # 检查在线状态。
|
|
44
|
+
│ ├── ensure-login [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--password PASSWORD] [--allow-argv-password] [--json] [--interactive] # 离线时登录。
|
|
45
|
+
│ ├── login [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--password PASSWORD] [--allow-argv-password] [--json] [--interactive] # 登录。
|
|
46
|
+
│ └── logout [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--json] [--interactive] # 退出校园网。
|
|
47
|
+
└── visitor # 访客账号。
|
|
48
|
+
├── create [--remark REMARK] [--dry-run] [--json] [--interactive] # 创建访客账号。
|
|
49
|
+
├── default [--password1 PASSWORD1] [--password2 PASSWORD2] [--remark REMARK] [--json] [--interactive] # 维护默认访客账号。
|
|
50
|
+
├── delete [--id VISITOR-ID] [--dry-run] [--json] [--interactive] # 删除访客账号。
|
|
51
|
+
├── get [--id VISITOR-ID] [--account ACCOUNT] [--json] # 查询访客账号。
|
|
52
|
+
├── list [--json] # 列出访客账号。
|
|
53
|
+
└── update [--id VISITOR-ID] [--remark REMARK] [--password PASSWORD] [--dry-run] [--json] [--interactive] # 更新访客备注和密码。
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
门户命令统一放在 `home` 下:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
ecnu home login -i
|
|
60
|
+
ecnu home info
|
|
61
|
+
ecnu home status
|
|
62
|
+
ecnu home user
|
|
63
|
+
ecnu home logout
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
校园网联网统一放在 `net` 下:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
ecnu net check --json
|
|
70
|
+
ecnu net login -I --allow-argv-password
|
|
71
|
+
ecnu net logout -I
|
|
72
|
+
ecnu net ensure-login -I --allow-argv-password
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
ChatECNU 的 PyPI wheel/sdist 内置 Linux x86_64 `auth_client`,默认 `ecnu net ...` 会优先使用该内置二进制;如需覆盖,可用 `--auth-client` 或 `ECNU_AUTH_CLIENT` 指定路径。账号密码使用同一组 `ECNU_USERNAME` / `ECNU_PASSWORD`。`net check` 会显示当前 `online/account/username`;`net logout` 未提供用户名时会先从 `auth_client check` 的 `Username=...` 自动提取。
|
|
76
|
+
|
|
77
|
+
敏感值(密码、Cookie、短信码、会话)不要打印或提交。
|
|
@@ -12,7 +12,7 @@ license = "MIT"
|
|
|
12
12
|
dependencies = [
|
|
13
13
|
"click>=8.0",
|
|
14
14
|
"chatstyle>=0.1.0,<0.2.0",
|
|
15
|
-
"chatenv>=0.2.
|
|
15
|
+
"chatenv>=0.2.4,<0.3.0",
|
|
16
16
|
"ChatNet>=0.2.0,<0.3.0",
|
|
17
17
|
"requests>=2.0",
|
|
18
18
|
"pycryptodome>=3.0",
|
|
@@ -54,3 +54,6 @@ where = ["src"]
|
|
|
54
54
|
|
|
55
55
|
[tool.setuptools]
|
|
56
56
|
include-package-data = true
|
|
57
|
+
|
|
58
|
+
[tool.setuptools.package-data]
|
|
59
|
+
chatecnu = ["bin/linux-x86_64/auth_client"]
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ChatECNU
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: ChatArch ECNU campus portal automation CLI
|
|
5
|
+
Author-email: ChatArch <1073853456@qq.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ChatArch/ChatECNU
|
|
8
|
+
Project-URL: Repository, https://github.com/ChatArch/ChatECNU
|
|
9
|
+
Project-URL: Documentation, https://arch.gh.wzhecnu.cn/ChatECNU/
|
|
10
|
+
Keywords: chatecnu,chatarch,ecnu,campus,portal
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: click>=8.0
|
|
17
|
+
Requires-Dist: chatstyle<0.2.0,>=0.1.0
|
|
18
|
+
Requires-Dist: chatenv<0.3.0,>=0.2.4
|
|
19
|
+
Requires-Dist: ChatNet<0.3.0,>=0.2.0
|
|
20
|
+
Requires-Dist: requests>=2.0
|
|
21
|
+
Requires-Dist: pycryptodome>=3.0
|
|
22
|
+
Provides-Extra: captcha
|
|
23
|
+
Requires-Dist: ddddocr; extra == "captcha"
|
|
24
|
+
Requires-Dist: numpy; extra == "captcha"
|
|
25
|
+
Requires-Dist: pillow; extra == "captcha"
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest; extra == "dev"
|
|
29
|
+
Requires-Dist: twine; extra == "dev"
|
|
30
|
+
Provides-Extra: docs
|
|
31
|
+
Requires-Dist: mkdocs<2.0,>=1.6; extra == "docs"
|
|
32
|
+
Requires-Dist: mkdocs-material<9.7,>=9.5; extra == "docs"
|
|
33
|
+
Requires-Dist: mkdocs-static-i18n<2.0,>=1.2; extra == "docs"
|
|
34
|
+
Requires-Dist: mike<3.0,>=2.0; extra == "docs"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# ChatECNU
|
|
38
|
+
|
|
39
|
+
ChatECNU 是 ECNU 门户与校园网联网工具包。安装包名仍是 `ChatECNU`,日常命令主推 `ecnu`。
|
|
40
|
+
|
|
41
|
+
## 文档入口
|
|
42
|
+
|
|
43
|
+
| 任务 | 链接 |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| 安装和最小验证 | https://arch.gh.wzhecnu.cn/ChatECNU/quickstart/ |
|
|
46
|
+
| 命令树 | https://arch.gh.wzhecnu.cn/ChatECNU/cli-tree/ |
|
|
47
|
+
| ChatEnv 变量 | https://arch.gh.wzhecnu.cn/ChatECNU/chatenv/ |
|
|
48
|
+
| ECNU 使用 | https://arch.gh.wzhecnu.cn/ChatECNU/ecnu/ |
|
|
49
|
+
|
|
50
|
+
## 安装
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install ChatECNU
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
如需验证码识别能力:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install "ChatECNU[captcha]"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 命令结构
|
|
63
|
+
|
|
64
|
+
ChatECNU 的命令面可用 `ecnu --tree` 从当前 Click 注册表直接回读:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
ecnu
|
|
68
|
+
├── --help # Show this message and exit.
|
|
69
|
+
├── --version # Show the installed ChatECNU version.
|
|
70
|
+
├── --tree # Print this registered command tree and exit.
|
|
71
|
+
├── --env ENV-PROFILE # ChatEnv 配置名。
|
|
72
|
+
├── home # ECNU 门户。
|
|
73
|
+
│ ├── info [--json] # 门户首页摘要。
|
|
74
|
+
│ ├── login [--username USERNAME] [--password PASSWORD] [--sms-code SMS-CODE] [--json] [--interactive] # 登录门户。
|
|
75
|
+
│ ├── logout [--json] # 退出门户会话。
|
|
76
|
+
│ ├── status [--json] # 门户会话状态。
|
|
77
|
+
│ └── user [--json] # 门户用户信息。
|
|
78
|
+
├── net # 校园网联网。
|
|
79
|
+
│ ├── check [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--json] # 检查在线状态。
|
|
80
|
+
│ ├── ensure-login [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--password PASSWORD] [--allow-argv-password] [--json] [--interactive] # 离线时登录。
|
|
81
|
+
│ ├── login [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--password PASSWORD] [--allow-argv-password] [--json] [--interactive] # 登录。
|
|
82
|
+
│ └── logout [--auth-client AUTH-CLIENT-PATH] [--setting-file SETTING-FILE] [--username USERNAME] [--json] [--interactive] # 退出校园网。
|
|
83
|
+
└── visitor # 访客账号。
|
|
84
|
+
├── create [--remark REMARK] [--dry-run] [--json] [--interactive] # 创建访客账号。
|
|
85
|
+
├── default [--password1 PASSWORD1] [--password2 PASSWORD2] [--remark REMARK] [--json] [--interactive] # 维护默认访客账号。
|
|
86
|
+
├── delete [--id VISITOR-ID] [--dry-run] [--json] [--interactive] # 删除访客账号。
|
|
87
|
+
├── get [--id VISITOR-ID] [--account ACCOUNT] [--json] # 查询访客账号。
|
|
88
|
+
├── list [--json] # 列出访客账号。
|
|
89
|
+
└── update [--id VISITOR-ID] [--remark REMARK] [--password PASSWORD] [--dry-run] [--json] [--interactive] # 更新访客备注和密码。
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
门户命令统一放在 `home` 下:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
ecnu home login -i
|
|
96
|
+
ecnu home info
|
|
97
|
+
ecnu home status
|
|
98
|
+
ecnu home user
|
|
99
|
+
ecnu home logout
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
校园网联网统一放在 `net` 下:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
ecnu net check --json
|
|
106
|
+
ecnu net login -I --allow-argv-password
|
|
107
|
+
ecnu net logout -I
|
|
108
|
+
ecnu net ensure-login -I --allow-argv-password
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
ChatECNU 的 PyPI wheel/sdist 内置 Linux x86_64 `auth_client`,默认 `ecnu net ...` 会优先使用该内置二进制;如需覆盖,可用 `--auth-client` 或 `ECNU_AUTH_CLIENT` 指定路径。账号密码使用同一组 `ECNU_USERNAME` / `ECNU_PASSWORD`。`net check` 会显示当前 `online/account/username`;`net logout` 未提供用户名时会先从 `auth_client check` 的 `Username=...` 自动提取。
|
|
112
|
+
|
|
113
|
+
敏感值(密码、Cookie、短信码、会话)不要打印或提交。
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
2
3
|
README.md
|
|
3
4
|
pyproject.toml
|
|
4
5
|
src/ChatECNU.egg-info/PKG-INFO
|
|
@@ -11,6 +12,7 @@ src/chatecnu/__init__.py
|
|
|
11
12
|
src/chatecnu/cli.py
|
|
12
13
|
src/chatecnu/config.py
|
|
13
14
|
src/chatecnu/network_auth.py
|
|
15
|
+
src/chatecnu/bin/linux-x86_64/auth_client
|
|
14
16
|
src/chatecnu/ecnu/__init__.py
|
|
15
17
|
src/chatecnu/ecnu/captcha.py
|
|
16
18
|
src/chatecnu/ecnu/cli.py
|
|
Binary file
|
|
@@ -21,6 +21,7 @@ from chatecnu.network_auth import (
|
|
|
21
21
|
NetworkAuthCredentials,
|
|
22
22
|
NetworkAuthResult,
|
|
23
23
|
redact_text,
|
|
24
|
+
resolve_auth_client_path,
|
|
24
25
|
)
|
|
25
26
|
from .portal import BASE_URL
|
|
26
27
|
|
|
@@ -80,8 +81,115 @@ VISITOR_DEFAULT_SCHEMA = CommandSchema(
|
|
|
80
81
|
)
|
|
81
82
|
|
|
82
83
|
|
|
84
|
+
def _format_metavar(name: str) -> str:
|
|
85
|
+
return name.replace("_", "-").upper()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _format_argument(param: click.Argument) -> str:
|
|
89
|
+
metavar = _format_metavar(param.name or "ARG")
|
|
90
|
+
if param.nargs == -1:
|
|
91
|
+
metavar = f"{metavar}..."
|
|
92
|
+
if not param.required:
|
|
93
|
+
return f"[{metavar}]"
|
|
94
|
+
return f"<{metavar}>"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _format_option(param: click.Option) -> str:
|
|
98
|
+
visible_opts = [opt for opt in param.opts if opt.startswith("--")]
|
|
99
|
+
visible_opts.extend(opt for opt in param.secondary_opts if opt.startswith("--"))
|
|
100
|
+
flag = visible_opts[0] if visible_opts else (param.opts[0] if param.opts else param.name or "OPTION")
|
|
101
|
+
if param.is_flag:
|
|
102
|
+
return f"[{flag}]"
|
|
103
|
+
return f"[{flag} {_format_metavar(param.name or 'VALUE')}]"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _command_signature(command: click.Command) -> str:
|
|
107
|
+
parts: list[str] = []
|
|
108
|
+
for param in command.params:
|
|
109
|
+
if getattr(param, "hidden", False):
|
|
110
|
+
continue
|
|
111
|
+
if isinstance(param, click.Argument):
|
|
112
|
+
parts.append(_format_argument(param))
|
|
113
|
+
elif isinstance(param, click.Option):
|
|
114
|
+
parts.append(_format_option(param))
|
|
115
|
+
return " ".join(parts)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _command_summary(command: click.Command) -> str:
|
|
119
|
+
return (command.short_help or command.help or "").strip().splitlines()[0]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _root_option_items(group: click.Group) -> list[tuple[str, str]]:
|
|
123
|
+
items = [
|
|
124
|
+
("--help", "Show this message and exit."),
|
|
125
|
+
("--version", "Show the installed ChatECNU version."),
|
|
126
|
+
("--tree", "Print this registered command tree and exit."),
|
|
127
|
+
]
|
|
128
|
+
for param in group.params:
|
|
129
|
+
if getattr(param, "hidden", False) or not isinstance(param, click.Option):
|
|
130
|
+
continue
|
|
131
|
+
if param.name in {"version", "tree"}:
|
|
132
|
+
continue
|
|
133
|
+
items.append((_format_option(param).strip("[]"), param.help or ""))
|
|
134
|
+
return items
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _group_items(group: click.Group) -> list[tuple[str, str | click.Command]]:
|
|
138
|
+
items: list[tuple[str, str | click.Command]] = []
|
|
139
|
+
if group is cli:
|
|
140
|
+
items.extend(_root_option_items(group))
|
|
141
|
+
for name in group.list_commands(click.Context(group)):
|
|
142
|
+
command = group.get_command(click.Context(group), name)
|
|
143
|
+
if command is None or command.hidden:
|
|
144
|
+
continue
|
|
145
|
+
items.append((name, command))
|
|
146
|
+
return items
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def render_cli_tree(root: click.Group | None = None) -> str:
|
|
150
|
+
"""Render the registered Click command tree for `ecnu --tree`."""
|
|
151
|
+
if root is None:
|
|
152
|
+
root = cli
|
|
153
|
+
lines = [root.name or "ecnu"]
|
|
154
|
+
|
|
155
|
+
def walk(items: list[tuple[str, str | click.Command]], prefix: str = "") -> None:
|
|
156
|
+
for index, (name, item) in enumerate(items):
|
|
157
|
+
last = index == len(items) - 1
|
|
158
|
+
branch = "└── " if last else "├── "
|
|
159
|
+
child_prefix = prefix + (" " if last else "│ ")
|
|
160
|
+
if isinstance(item, str):
|
|
161
|
+
summary = f" # {item}" if item else ""
|
|
162
|
+
lines.append(f"{prefix}{branch}{name}{summary}")
|
|
163
|
+
continue
|
|
164
|
+
signature = _command_signature(item)
|
|
165
|
+
label = f"{name} {signature}".strip()
|
|
166
|
+
lines.append(f"{prefix}{branch}{label} # {_command_summary(item)}")
|
|
167
|
+
if isinstance(item, click.Group):
|
|
168
|
+
walk(_group_items(item), child_prefix)
|
|
169
|
+
|
|
170
|
+
walk(_group_items(root))
|
|
171
|
+
return "\n".join(lines)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _tree_callback(ctx: click.Context, param: click.Option, value: bool) -> None:
|
|
175
|
+
if not value or ctx.resilient_parsing:
|
|
176
|
+
return
|
|
177
|
+
if not isinstance(ctx.command, click.Group):
|
|
178
|
+
raise click.ClickException("--tree is only available on command groups")
|
|
179
|
+
click.echo(render_cli_tree(ctx.command))
|
|
180
|
+
ctx.exit()
|
|
181
|
+
|
|
182
|
+
|
|
83
183
|
@click.group(name="ecnu")
|
|
84
184
|
@click.version_option(__version__)
|
|
185
|
+
@click.option(
|
|
186
|
+
"--tree",
|
|
187
|
+
is_flag=True,
|
|
188
|
+
is_eager=True,
|
|
189
|
+
expose_value=False,
|
|
190
|
+
callback=_tree_callback,
|
|
191
|
+
help="Print the registered CLI command tree and exit.",
|
|
192
|
+
)
|
|
85
193
|
@click.option(
|
|
86
194
|
"--base-url",
|
|
87
195
|
default=None,
|
|
@@ -436,16 +544,17 @@ def network_auth_logout(
|
|
|
436
544
|
"""退出校园网。"""
|
|
437
545
|
|
|
438
546
|
prefer_loaded_chatenv = network_auth_prefers_loaded_chatenv(ctx)
|
|
439
|
-
resolved_username =
|
|
440
|
-
|
|
441
|
-
|
|
547
|
+
resolved_username = username or resolve_ecnu_config_value(
|
|
548
|
+
"ECNU_USERNAME",
|
|
549
|
+
ECNUConfig.ECNU_USERNAME,
|
|
442
550
|
prefer_loaded_chatenv=prefer_loaded_chatenv,
|
|
443
551
|
)
|
|
444
|
-
|
|
552
|
+
client = make_network_auth_client(
|
|
445
553
|
auth_client_path=auth_client_path,
|
|
446
554
|
setting_file=setting_file,
|
|
447
555
|
prefer_loaded_chatenv=prefer_loaded_chatenv,
|
|
448
|
-
)
|
|
556
|
+
)
|
|
557
|
+
result = client.logout(resolved_username) if resolved_username else client.logout_current()
|
|
449
558
|
emit_network_auth_result(result, json_output=json_output)
|
|
450
559
|
|
|
451
560
|
|
|
@@ -688,11 +797,12 @@ def make_network_auth_client(
|
|
|
688
797
|
allow_argv_password: bool = False,
|
|
689
798
|
prefer_loaded_chatenv: bool = False,
|
|
690
799
|
) -> NetworkAuthClient:
|
|
691
|
-
|
|
800
|
+
configured_auth_client = auth_client_path or resolve_ecnu_config_value(
|
|
692
801
|
"ECNU_AUTH_CLIENT",
|
|
693
802
|
ECNUConfig.ECNU_AUTH_CLIENT,
|
|
694
803
|
prefer_loaded_chatenv=prefer_loaded_chatenv,
|
|
695
|
-
)
|
|
804
|
+
)
|
|
805
|
+
resolved_auth_client = resolve_auth_client_path(configured_auth_client)
|
|
696
806
|
resolved_setting_file = setting_file or resolve_ecnu_config_value(
|
|
697
807
|
"ECNU_AUTH_SETTING_FILE",
|
|
698
808
|
ECNUConfig.ECNU_AUTH_SETTING_FILE,
|
|
@@ -795,10 +905,24 @@ def redact_network_auth_payload(payload: dict[str, object], *, secret_values: tu
|
|
|
795
905
|
|
|
796
906
|
def format_network_auth_result(result: NetworkAuthResult) -> str:
|
|
797
907
|
if result.action == "ensure-login" and result.skipped:
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
908
|
+
base = "Already online; skipped."
|
|
909
|
+
elif result.action == "logout" and result.skipped:
|
|
910
|
+
base = "Already offline; skipped."
|
|
911
|
+
elif result.success:
|
|
912
|
+
base = "Login OK." if result.action in {"login", "ensure-login"} else "auth_client OK."
|
|
913
|
+
else:
|
|
914
|
+
return "auth_client failed."
|
|
915
|
+
|
|
916
|
+
details: list[str] = []
|
|
917
|
+
if result.online is not None:
|
|
918
|
+
details.append(f"Online: {str(result.online).lower()}")
|
|
919
|
+
if result.account:
|
|
920
|
+
details.append(f"Account: {result.account}")
|
|
921
|
+
if result.username and result.username != result.account:
|
|
922
|
+
details.append(f"Username: {result.username}")
|
|
923
|
+
elif result.username and result.action == "check":
|
|
924
|
+
details.append(f"Username: {result.username}")
|
|
925
|
+
return " ".join([base, *details]) if details else base
|
|
802
926
|
|
|
803
927
|
|
|
804
928
|
def make_client(ctx: click.Context) -> Any:
|