sermo 0.3.2__tar.gz → 0.5.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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sermo
3
- Version: 0.3.2
4
- Summary: Command-line Sermo client
3
+ Version: 0.5.0
4
+ Summary: Command-line client for Sermo 言浪
5
5
  Author: Sermo
6
6
  Project-URL: Homepage, https://sermo.jyonn.space
7
7
  Keywords: sermo,chat,cli
@@ -18,16 +18,17 @@ Classifier: Topic :: Communications :: Chat
18
18
  Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
20
 
21
- # sermo
21
+ # Sermo 言浪 CLI
22
22
 
23
- Sermo 的命令行客户端。它直接接入 `sermo-backend` API,适合在终端里快速查看会话、发送文字消息和检查好友信息。
23
+ Sermo 言浪的命令行客户端。它直接接入 `sermo-backend` API,适合在终端里快速查看会话、发送文字消息和检查好友信息。
24
24
 
25
25
  当前版本覆盖日常终端使用:
26
26
 
27
27
  - 支持进入空间并保存登录状态。
28
28
  - 支持查看当前账户、空间成员、聊天列表、好友列表、好友申请。
29
29
  - 支持查看聊天记录、发送文字消息、持续刷新新消息、监听全局新消息。
30
- - 支持 `sermo tui` 打开终端聊天界面,会话列表、消息流和输入框集中展示。
30
+ - 默认提供不清屏的局部窗口选择器,会话、好友、成员和申请列表只展示光标附近 5 项。
31
+ - 保留 `sermo tui` 全屏终端聊天界面,会话列表、消息流和输入框集中展示。
31
32
  - 支持好友申请处理、好友邀请链接、私聊打开、群聊创建和成员管理。
32
33
  - 支持账号资料、联系方式绑定、通知偏好、空间创建和管理员基础操作。
33
34
  - 图片、视频、语音、文件等多媒体消息在终端中展示为 `[图片]`、`[视频]`、`[语音]`、`[文件]`;也支持上传发送图片、视频和语音文件。
@@ -92,6 +93,20 @@ sermo me
92
93
  sermo chats
93
94
  ```
94
95
 
96
+ 终端中会显示光标附近 5 个会话。使用 `↑/↓` 选择、`Enter` 打开、`Esc` 返回;也支持 `j/k` 和 `Ctrl+N/Ctrl+P`。
97
+
98
+ 直接输出完整列表,适合管道和脚本:
99
+
100
+ ```bash
101
+ sermo chats --list
102
+ ```
103
+
104
+ 调整局部窗口行数:
105
+
106
+ ```bash
107
+ sermo chats --window 7
108
+ ```
109
+
95
110
  打开 TUI:
96
111
 
97
112
  ```bash
@@ -100,11 +115,14 @@ sermo tui
100
115
 
101
116
  在 TUI 里:
102
117
 
103
- - `↑/↓` 切换会话。
104
- - 直接输入文字,按 `Enter` 发送。
105
- - `F5` 手动刷新。
106
- - `Ctrl+U` 清空输入。
107
- - `Esc` 或 `F10` 退出;输入框为空时也可以按 `q` 退出。
118
+ - `Tab/Shift+Tab` 在会话、消息和输入框之间切换焦点。
119
+ - 会话焦点下使用 `↑/↓` 或 `j/k` 切换会话。
120
+ - 消息焦点下使用 `↑/↓` 滚动,`PageUp/PageDown` 翻页,滑到顶部自动加载历史。
121
+ - 查看历史时不会强制跳到底部;标题会提示新消息数量,`End` 回到最新消息。
122
+ - 输入框支持左右移动、`Home/End`、退格与 Delete,并按会话保存草稿。
123
+ - 发送消息会立即展示“发送中”;失败后保留消息,在消息焦点按 `r` 重试。
124
+ - `Enter` 发送,`F5` 手动刷新,`Ctrl+U` 清空输入。
125
+ - `Esc` 或 `F10` 退出。
108
126
 
109
127
  打开聊天:
110
128
 
@@ -136,6 +154,17 @@ sermo chat 1 --follow
136
154
  sermo friends
137
155
  ```
138
156
 
157
+ 好友、空间成员、好友申请和群聊邀请使用同一套局部窗口交互:
158
+
159
+ ```bash
160
+ sermo friends
161
+ sermo users
162
+ sermo requests
163
+ sermo group invites
164
+ ```
165
+
166
+ 这些命令也都支持 `--list` 和 `--window`。
167
+
139
168
  查看好友申请:
140
169
 
141
170
  ```bash
@@ -1,13 +1,14 @@
1
- # sermo
1
+ # Sermo 言浪 CLI
2
2
 
3
- Sermo 的命令行客户端。它直接接入 `sermo-backend` API,适合在终端里快速查看会话、发送文字消息和检查好友信息。
3
+ Sermo 言浪的命令行客户端。它直接接入 `sermo-backend` API,适合在终端里快速查看会话、发送文字消息和检查好友信息。
4
4
 
5
5
  当前版本覆盖日常终端使用:
6
6
 
7
7
  - 支持进入空间并保存登录状态。
8
8
  - 支持查看当前账户、空间成员、聊天列表、好友列表、好友申请。
9
9
  - 支持查看聊天记录、发送文字消息、持续刷新新消息、监听全局新消息。
10
- - 支持 `sermo tui` 打开终端聊天界面,会话列表、消息流和输入框集中展示。
10
+ - 默认提供不清屏的局部窗口选择器,会话、好友、成员和申请列表只展示光标附近 5 项。
11
+ - 保留 `sermo tui` 全屏终端聊天界面,会话列表、消息流和输入框集中展示。
11
12
  - 支持好友申请处理、好友邀请链接、私聊打开、群聊创建和成员管理。
12
13
  - 支持账号资料、联系方式绑定、通知偏好、空间创建和管理员基础操作。
13
14
  - 图片、视频、语音、文件等多媒体消息在终端中展示为 `[图片]`、`[视频]`、`[语音]`、`[文件]`;也支持上传发送图片、视频和语音文件。
@@ -72,6 +73,20 @@ sermo me
72
73
  sermo chats
73
74
  ```
74
75
 
76
+ 终端中会显示光标附近 5 个会话。使用 `↑/↓` 选择、`Enter` 打开、`Esc` 返回;也支持 `j/k` 和 `Ctrl+N/Ctrl+P`。
77
+
78
+ 直接输出完整列表,适合管道和脚本:
79
+
80
+ ```bash
81
+ sermo chats --list
82
+ ```
83
+
84
+ 调整局部窗口行数:
85
+
86
+ ```bash
87
+ sermo chats --window 7
88
+ ```
89
+
75
90
  打开 TUI:
76
91
 
77
92
  ```bash
@@ -80,11 +95,14 @@ sermo tui
80
95
 
81
96
  在 TUI 里:
82
97
 
83
- - `↑/↓` 切换会话。
84
- - 直接输入文字,按 `Enter` 发送。
85
- - `F5` 手动刷新。
86
- - `Ctrl+U` 清空输入。
87
- - `Esc` 或 `F10` 退出;输入框为空时也可以按 `q` 退出。
98
+ - `Tab/Shift+Tab` 在会话、消息和输入框之间切换焦点。
99
+ - 会话焦点下使用 `↑/↓` 或 `j/k` 切换会话。
100
+ - 消息焦点下使用 `↑/↓` 滚动,`PageUp/PageDown` 翻页,滑到顶部自动加载历史。
101
+ - 查看历史时不会强制跳到底部;标题会提示新消息数量,`End` 回到最新消息。
102
+ - 输入框支持左右移动、`Home/End`、退格与 Delete,并按会话保存草稿。
103
+ - 发送消息会立即展示“发送中”;失败后保留消息,在消息焦点按 `r` 重试。
104
+ - `Enter` 发送,`F5` 手动刷新,`Ctrl+U` 清空输入。
105
+ - `Esc` 或 `F10` 退出。
88
106
 
89
107
  打开聊天:
90
108
 
@@ -116,6 +134,17 @@ sermo chat 1 --follow
116
134
  sermo friends
117
135
  ```
118
136
 
137
+ 好友、空间成员、好友申请和群聊邀请使用同一套局部窗口交互:
138
+
139
+ ```bash
140
+ sermo friends
141
+ sermo users
142
+ sermo requests
143
+ sermo group invites
144
+ ```
145
+
146
+ 这些命令也都支持 `--list` 和 `--window`。
147
+
119
148
  查看好友申请:
120
149
 
121
150
  ```bash
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sermo"
7
- version = "0.3.2"
8
- description = "Command-line Sermo client"
7
+ version = "0.5.0"
8
+ description = "Command-line client for Sermo 言浪"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  dependencies = []
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sermo
3
- Version: 0.3.2
4
- Summary: Command-line Sermo client
3
+ Version: 0.5.0
4
+ Summary: Command-line client for Sermo 言浪
5
5
  Author: Sermo
6
6
  Project-URL: Homepage, https://sermo.jyonn.space
7
7
  Keywords: sermo,chat,cli
@@ -18,16 +18,17 @@ Classifier: Topic :: Communications :: Chat
18
18
  Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
20
 
21
- # sermo
21
+ # Sermo 言浪 CLI
22
22
 
23
- Sermo 的命令行客户端。它直接接入 `sermo-backend` API,适合在终端里快速查看会话、发送文字消息和检查好友信息。
23
+ Sermo 言浪的命令行客户端。它直接接入 `sermo-backend` API,适合在终端里快速查看会话、发送文字消息和检查好友信息。
24
24
 
25
25
  当前版本覆盖日常终端使用:
26
26
 
27
27
  - 支持进入空间并保存登录状态。
28
28
  - 支持查看当前账户、空间成员、聊天列表、好友列表、好友申请。
29
29
  - 支持查看聊天记录、发送文字消息、持续刷新新消息、监听全局新消息。
30
- - 支持 `sermo tui` 打开终端聊天界面,会话列表、消息流和输入框集中展示。
30
+ - 默认提供不清屏的局部窗口选择器,会话、好友、成员和申请列表只展示光标附近 5 项。
31
+ - 保留 `sermo tui` 全屏终端聊天界面,会话列表、消息流和输入框集中展示。
31
32
  - 支持好友申请处理、好友邀请链接、私聊打开、群聊创建和成员管理。
32
33
  - 支持账号资料、联系方式绑定、通知偏好、空间创建和管理员基础操作。
33
34
  - 图片、视频、语音、文件等多媒体消息在终端中展示为 `[图片]`、`[视频]`、`[语音]`、`[文件]`;也支持上传发送图片、视频和语音文件。
@@ -92,6 +93,20 @@ sermo me
92
93
  sermo chats
93
94
  ```
94
95
 
96
+ 终端中会显示光标附近 5 个会话。使用 `↑/↓` 选择、`Enter` 打开、`Esc` 返回;也支持 `j/k` 和 `Ctrl+N/Ctrl+P`。
97
+
98
+ 直接输出完整列表,适合管道和脚本:
99
+
100
+ ```bash
101
+ sermo chats --list
102
+ ```
103
+
104
+ 调整局部窗口行数:
105
+
106
+ ```bash
107
+ sermo chats --window 7
108
+ ```
109
+
95
110
  打开 TUI:
96
111
 
97
112
  ```bash
@@ -100,11 +115,14 @@ sermo tui
100
115
 
101
116
  在 TUI 里:
102
117
 
103
- - `↑/↓` 切换会话。
104
- - 直接输入文字,按 `Enter` 发送。
105
- - `F5` 手动刷新。
106
- - `Ctrl+U` 清空输入。
107
- - `Esc` 或 `F10` 退出;输入框为空时也可以按 `q` 退出。
118
+ - `Tab/Shift+Tab` 在会话、消息和输入框之间切换焦点。
119
+ - 会话焦点下使用 `↑/↓` 或 `j/k` 切换会话。
120
+ - 消息焦点下使用 `↑/↓` 滚动,`PageUp/PageDown` 翻页,滑到顶部自动加载历史。
121
+ - 查看历史时不会强制跳到底部;标题会提示新消息数量,`End` 回到最新消息。
122
+ - 输入框支持左右移动、`Home/End`、退格与 Delete,并按会话保存草稿。
123
+ - 发送消息会立即展示“发送中”;失败后保留消息,在消息焦点按 `r` 重试。
124
+ - `Enter` 发送,`F5` 手动刷新,`Ctrl+U` 清空输入。
125
+ - `Esc` 或 `F10` 退出。
108
126
 
109
127
  打开聊天:
110
128
 
@@ -136,6 +154,17 @@ sermo chat 1 --follow
136
154
  sermo friends
137
155
  ```
138
156
 
157
+ 好友、空间成员、好友申请和群聊邀请使用同一套局部窗口交互:
158
+
159
+ ```bash
160
+ sermo friends
161
+ sermo users
162
+ sermo requests
163
+ sermo group invites
164
+ ```
165
+
166
+ 这些命令也都支持 `--list` 和 `--window`。
167
+
139
168
  查看好友申请:
140
169
 
141
170
  ```bash
@@ -10,5 +10,8 @@ sermo_cli/__main__.py
10
10
  sermo_cli/api.py
11
11
  sermo_cli/cli.py
12
12
  sermo_cli/formatting.py
13
+ sermo_cli/interactive.py
13
14
  sermo_cli/store.py
14
- sermo_cli/tui.py
15
+ sermo_cli/tui.py
16
+ tests/test_interactive.py
17
+ tests/test_tui.py
@@ -1,3 +1,3 @@
1
1
  """Command-line client for Sermo."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.5.0"
@@ -10,6 +10,7 @@ from typing import Any
10
10
 
11
11
  from .api import ApiClient, SermoApiError
12
12
  from .formatting import chat_title, format_time, message_text, print_header, style, user_name
13
+ from .interactive import choose
13
14
  from .store import SessionStore
14
15
 
15
16
 
@@ -151,6 +152,30 @@ def command_chats(args: argparse.Namespace) -> int:
151
152
  if not chats:
152
153
  print("暂无会话。")
153
154
  return 0
155
+ if sys.stdin.isatty() and not args.list:
156
+ def render_chat_choice(chat: dict[str, Any]) -> str:
157
+ unread = f" · {chat.get('unread_count')} 条新消息" if chat.get("unread_count") else ""
158
+ preview = message_text(chat.get("last_message") or {}) if chat.get("last_message") else "暂无消息"
159
+ return f"{chat_title(chat, self_user_id)}{unread} {preview}"
160
+
161
+ selected = choose(
162
+ chats,
163
+ render_chat_choice,
164
+ title="选择会话",
165
+ window_size=args.window,
166
+ )
167
+ if selected is None:
168
+ return 0
169
+ print(style.muted(f"进入 {chat_title(selected, self_user_id)}"))
170
+ return command_chat(argparse.Namespace(**{
171
+ **vars(args),
172
+ "chat_id": int(selected["chat_id"]),
173
+ "limit": args.limit,
174
+ "before": None,
175
+ "follow": False,
176
+ "interval": 5.0,
177
+ "no_mark_read": False,
178
+ }))
154
179
  print_header("聊天")
155
180
  for chat in chats:
156
181
  last = chat.get("last_message")
@@ -268,11 +293,43 @@ def command_send(args: argparse.Namespace) -> int:
268
293
 
269
294
  def command_friends(args: argparse.Namespace) -> int:
270
295
  client = build_client(args)
271
- require_session(client)
296
+ session = require_session(client)
272
297
  friends = client.friends()
273
298
  if not friends:
274
299
  print("暂无好友。")
275
300
  return 0
301
+ if sys.stdin.isatty() and not args.list:
302
+ selected = choose(
303
+ friends,
304
+ lambda friend: f"{user_name(friend)} {'在线' if friend.get('is_alive') else '离线'}",
305
+ title="选择好友",
306
+ window_size=args.window,
307
+ )
308
+ if selected is None:
309
+ return 0
310
+ action = choose(
311
+ ("chat", "profile", "back"),
312
+ lambda item: {"chat": "发消息", "profile": "查看资料", "back": "返回"}[item],
313
+ title=user_name(selected),
314
+ window_size=3,
315
+ )
316
+ if action == "chat":
317
+ chat = client.direct_chat(int(selected["user_id"]))
318
+ return command_chat(argparse.Namespace(**{
319
+ **vars(args),
320
+ "chat_id": int(chat["chat_id"]),
321
+ "limit": 30,
322
+ "before": None,
323
+ "follow": False,
324
+ "interval": 5.0,
325
+ "no_mark_read": False,
326
+ }))
327
+ if action == "profile":
328
+ print_header(user_name(selected), "好友")
329
+ print(f"用户 ID: {selected.get('user_id')}")
330
+ print(f"状态: {'在线' if selected.get('is_alive') else '离线'}")
331
+ print(f"认证: {'已认证' if selected.get('verified') else '未认证'}")
332
+ return 0
276
333
  print_header("好友")
277
334
  for friend in friends:
278
335
  online = style.green("在线") if friend.get("is_alive") else style.muted("离线")
@@ -286,6 +343,44 @@ def command_requests(args: argparse.Namespace) -> int:
286
343
  payload = client.friend_requests()
287
344
  incoming = payload.get("incoming") or []
288
345
  outgoing = payload.get("outgoing") or []
346
+ if sys.stdin.isatty() and not args.list and (incoming or outgoing):
347
+ rows = [("incoming", item) for item in incoming] + [("outgoing", item) for item in outgoing]
348
+ selected = choose(
349
+ rows,
350
+ lambda row: (
351
+ f"{'收到' if row[0] == 'incoming' else '发出'} · "
352
+ f"{user_name(row[1].get('from_user') if row[0] == 'incoming' else row[1].get('to_user'))}"
353
+ ),
354
+ title="好友申请",
355
+ window_size=args.window,
356
+ )
357
+ if selected is None:
358
+ return 0
359
+ direction, item = selected
360
+ user = item.get("from_user") if direction == "incoming" else item.get("to_user")
361
+ user_id = int((user or {}).get("user_id"))
362
+ actions = ("accept", "ignore", "back") if direction == "incoming" else ("withdraw", "back")
363
+ action = choose(
364
+ actions,
365
+ lambda value: {
366
+ "accept": "接受申请",
367
+ "ignore": "忽略申请",
368
+ "withdraw": "撤回申请",
369
+ "back": "返回",
370
+ }[value],
371
+ title=user_name(user),
372
+ window_size=3,
373
+ )
374
+ if action == "accept":
375
+ client.respond_friend_request(user_id, True)
376
+ print("已接受好友申请。")
377
+ elif action == "ignore":
378
+ client.respond_friend_request(user_id, False)
379
+ print("已忽略好友申请。")
380
+ elif action == "withdraw":
381
+ client.remove_friend(user_id)
382
+ print("已撤回好友申请。")
383
+ return 0
289
384
  print_header("好友申请")
290
385
  print(style.bold("收到的"))
291
386
  if incoming:
@@ -309,6 +404,46 @@ def command_users(args: argparse.Namespace) -> int:
309
404
  if not users:
310
405
  print("没有找到用户。")
311
406
  return 0
407
+ if sys.stdin.isatty() and not args.list:
408
+ selected = choose(
409
+ users,
410
+ lambda user: f"{user_name(user)} {'在线' if user.get('is_alive') else '离线'} {'已认证' if user.get('verified') else '未认证'}",
411
+ title="选择空间成员",
412
+ window_size=args.window,
413
+ )
414
+ if selected is None:
415
+ return 0
416
+ action = choose(
417
+ ("chat", "friend", "profile", "back"),
418
+ lambda value: {
419
+ "chat": "发起私聊",
420
+ "friend": "发送好友申请",
421
+ "profile": "查看资料",
422
+ "back": "返回",
423
+ }[value],
424
+ title=user_name(selected),
425
+ window_size=4,
426
+ )
427
+ if action == "chat":
428
+ chat = client.direct_chat(int(selected["user_id"]))
429
+ return command_chat(argparse.Namespace(**{
430
+ **vars(args),
431
+ "chat_id": int(chat["chat_id"]),
432
+ "limit": 30,
433
+ "before": None,
434
+ "follow": False,
435
+ "interval": 5.0,
436
+ "no_mark_read": False,
437
+ }))
438
+ if action == "friend":
439
+ client.create_friend_request(int(selected["user_id"]))
440
+ print("好友申请已发送。")
441
+ elif action == "profile":
442
+ print_header(user_name(selected), "空间成员")
443
+ print(f"用户 ID: {selected.get('user_id')}")
444
+ print(f"状态: {'在线' if selected.get('is_alive') else '离线'}")
445
+ print(f"认证: {'已认证' if selected.get('verified') else '未认证'}")
446
+ return 0
312
447
  print_header("空间成员")
313
448
  for user in users:
314
449
  online = style.green("在线") if user.get("is_alive") else style.muted("离线")
@@ -486,6 +621,27 @@ def command_group_invites(args: argparse.Namespace) -> int:
486
621
  if not invites:
487
622
  print("暂无群聊邀请。")
488
623
  return 0
624
+ if sys.stdin.isatty() and not args.list:
625
+ selected = choose(
626
+ invites,
627
+ lambda item: chat_title(item.get("chat") if isinstance(item, dict) and item.get("chat") else item),
628
+ title="群聊邀请",
629
+ window_size=args.window,
630
+ )
631
+ if selected is None:
632
+ return 0
633
+ chat = selected.get("chat") if isinstance(selected, dict) else None
634
+ chat_id = selected.get("chat_id") or (chat or {}).get("chat_id")
635
+ action = choose(
636
+ ("accept", "reject", "back"),
637
+ lambda value: {"accept": "接受邀请", "reject": "拒绝邀请", "back": "返回"}[value],
638
+ title=chat_title(chat or selected),
639
+ window_size=3,
640
+ )
641
+ if action in {"accept", "reject"}:
642
+ client.respond_group_invite(int(chat_id), action == "accept")
643
+ print("已接受群聊邀请。" if action == "accept" else "已拒绝群聊邀请。")
644
+ return 0
489
645
  print_header("群聊邀请")
490
646
  for item in invites:
491
647
  chat = item.get("chat") if isinstance(item, dict) else None
@@ -770,7 +926,7 @@ def command_admin_logout(args: argparse.Namespace) -> int:
770
926
 
771
927
 
772
928
  def build_parser() -> argparse.ArgumentParser:
773
- parser = argparse.ArgumentParser(prog="sermo", description="Sermo 命令行客户端")
929
+ parser = argparse.ArgumentParser(prog="sermo", description="Sermo 言浪命令行客户端")
774
930
  parser.add_argument("--api", help="Sermo API 地址,默认读取 SERMO_API_BASE 或 https://api.sermo.jyonn.space")
775
931
  subparsers = parser.add_subparsers(dest="command", required=True)
776
932
 
@@ -788,6 +944,9 @@ def build_parser() -> argparse.ArgumentParser:
788
944
  me.set_defaults(func=command_me)
789
945
 
790
946
  chats = subparsers.add_parser("chats", help="查看聊天列表")
947
+ chats.add_argument("--list", action="store_true", help="直接输出完整列表,不进入选择器")
948
+ chats.add_argument("--window", type=int, default=5, help="选择器可见行数")
949
+ chats.add_argument("-n", "--limit", type=int, default=30, help="进入会话后加载的消息数")
791
950
  chats.set_defaults(func=command_chats)
792
951
 
793
952
  chat = subparsers.add_parser("chat", help="打开聊天并发送文字")
@@ -810,9 +969,13 @@ def build_parser() -> argparse.ArgumentParser:
810
969
  send.set_defaults(func=command_send)
811
970
 
812
971
  friends = subparsers.add_parser("friends", help="查看好友")
972
+ friends.add_argument("--list", action="store_true", help="直接输出完整列表")
973
+ friends.add_argument("--window", type=int, default=5, help="选择器可见行数")
813
974
  friends.set_defaults(func=command_friends)
814
975
 
815
976
  requests = subparsers.add_parser("requests", help="查看好友申请")
977
+ requests.add_argument("--list", action="store_true", help="直接输出完整列表")
978
+ requests.add_argument("--window", type=int, default=5, help="选择器可见行数")
816
979
  requests.set_defaults(func=command_requests)
817
980
 
818
981
  users = subparsers.add_parser("users", help="搜索/查看空间成员")
@@ -820,6 +983,8 @@ def build_parser() -> argparse.ArgumentParser:
820
983
  users.add_argument("--online", action="store_true", help="只看在线成员")
821
984
  users.add_argument("--limit", type=int, default=50)
822
985
  users.add_argument("--offset", type=int, default=0)
986
+ users.add_argument("--list", action="store_true", help="直接输出完整列表")
987
+ users.add_argument("--window", type=int, default=5, help="选择器可见行数")
823
988
  users.set_defaults(func=command_users)
824
989
 
825
990
  direct = subparsers.add_parser("direct", help="打开一个私聊")
@@ -892,6 +1057,8 @@ def build_parser() -> argparse.ArgumentParser:
892
1057
  group_delete.add_argument("-y", "--yes", action="store_true")
893
1058
  group_delete.set_defaults(func=command_group_delete)
894
1059
  group_invites = group_sub.add_parser("invites", help="查看群聊邀请")
1060
+ group_invites.add_argument("--list", action="store_true", help="直接输出完整列表")
1061
+ group_invites.add_argument("--window", type=int, default=5, help="选择器可见行数")
895
1062
  group_invites.set_defaults(func=command_group_invites)
896
1063
  group_accept = group_sub.add_parser("accept", help="接受群聊邀请")
897
1064
  group_accept.add_argument("chat_id", type=int)