lockbot 2.9.4__tar.gz → 2.9.5__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.
- {lockbot-2.9.4/python/lockbot.egg-info → lockbot-2.9.5}/PKG-INFO +1 -1
- {lockbot-2.9.4 → lockbot-2.9.5}/pyproject.toml +1 -1
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/bots/schemas.py +4 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/config.py +2 -1
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/device_bot.py +1 -6
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/device_usage_utils.py +2 -1
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/i18n/en.py +13 -12
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/i18n/zh.py +13 -12
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/node_bot.py +1 -1
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/queue_bot.py +1 -1
- {lockbot-2.9.4 → lockbot-2.9.5/python/lockbot.egg-info}/PKG-INFO +1 -1
- {lockbot-2.9.4 → lockbot-2.9.5}/LICENSE +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/MANIFEST.in +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/README.md +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/admin/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/admin/router.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/audit/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/audit/models.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/audit/router.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/audit/service.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/auth/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/auth/dependencies.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/auth/models.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/auth/router.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/auth/schemas.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/backup/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/backup/router.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/backup/scheduler.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/backup/service.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/bots/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/bots/encryption.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/bots/manager.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/bots/models.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/bots/router.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/bots/webhook_handler.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/database.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/logs/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/main.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/rate_limit.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/settings/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/settings/models.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/backend/app/settings/router.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/base_bot.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/bot_instance.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/config.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/device_usage_alert.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/entry.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/env.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/handler.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/i18n/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/io.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/message_adapter.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/msg_utils.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/platforms/__init__.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/platforms/infoflow.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/request.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/scheduler.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot/core/utils.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot.egg-info/SOURCES.txt +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot.egg-info/dependency_links.txt +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot.egg-info/requires.txt +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/python/lockbot.egg-info/top_level.txt +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/setup.cfg +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/tools/create_super_admin.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/tools/gen_keys.py +0 -0
- {lockbot-2.9.4 → lockbot-2.9.5}/tools/reset_super_admin_password.py +0 -0
|
@@ -72,6 +72,10 @@ def _validate_config_overrides(v: dict | None) -> dict | None:
|
|
|
72
72
|
if allow_alias is not None and not isinstance(allow_alias, bool):
|
|
73
73
|
errors.append("ALLOW_USER_ALIAS must be a boolean")
|
|
74
74
|
|
|
75
|
+
display_model = v.get("DISPLAY_DEVICE_MODEL")
|
|
76
|
+
if display_model is not None and not isinstance(display_model, bool):
|
|
77
|
+
errors.append("DISPLAY_DEVICE_MODEL must be a boolean")
|
|
78
|
+
|
|
75
79
|
max_dur = v.get("MAX_LOCK_DURATION")
|
|
76
80
|
default_dur = v.get("DEFAULT_DURATION")
|
|
77
81
|
if isinstance(max_dur, int) and isinstance(default_dur, int) and max_dur != -1 and default_dur > max_dur:
|
|
@@ -8,7 +8,8 @@ from pathlib import Path
|
|
|
8
8
|
# Project root directory (lockbot/)
|
|
9
9
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
|
10
10
|
|
|
11
|
-
DATA_DIR = os.environ.get("DATA_DIR", "
|
|
11
|
+
DATA_DIR = os.environ.get("DATA_DIR", str(BASE_DIR.parent / "data"))
|
|
12
|
+
os.makedirs(DATA_DIR, exist_ok=True)
|
|
12
13
|
|
|
13
14
|
# Database
|
|
14
15
|
DATABASE_URL = os.environ.get(
|
|
@@ -474,19 +474,14 @@ class DeviceBot(BaseLockBot):
|
|
|
474
474
|
text = t("help.rule3_lock_modes", config=self.config)
|
|
475
475
|
text += t("help.lock_all_devices_example", config=self.config, node=example_node)
|
|
476
476
|
text += t("help.lock_device_example", config=self.config, node=example_node)
|
|
477
|
-
text += t("help.lock_device_duration_example", config=self.config, node=example_node)
|
|
478
|
-
text += t("help.lock_device_range_example", config=self.config, node=example_node)
|
|
479
477
|
text += t("help.slock_device_range_example", config=self.config, node=example_node)
|
|
480
478
|
text += t("help.section2_title", config=self.config)
|
|
481
479
|
text += t("help.unlock_device_example", config=self.config, node=example_node)
|
|
482
|
-
text += t("help.unlock_device_range_example", config=self.config, node=example_node)
|
|
483
480
|
text += t("help.free_device_range_example", config=self.config, node=example_node)
|
|
484
|
-
text += t("help.free_node_all_example", config=self.config, node=example_node)
|
|
485
481
|
text += t("help.free_all", config=self.config)
|
|
486
482
|
text += t("help.section3_title", config=self.config)
|
|
487
483
|
text += t("help.kickout_device_example", config=self.config, node=example_node)
|
|
488
484
|
text += t("help.kickout_device_range_example", config=self.config, node=example_node)
|
|
489
|
-
text += t("help.kickout_device_range2_example", config=self.config, node=example_node)
|
|
490
485
|
text += t("help.section4_title", config=self.config)
|
|
491
486
|
text += t("help.section5_title", config=self.config)
|
|
492
487
|
text += t("help.query_at_bot", config=self.config)
|
|
@@ -494,7 +489,7 @@ class DeviceBot(BaseLockBot):
|
|
|
494
489
|
text += "\n"
|
|
495
490
|
|
|
496
491
|
if self.config.get_val("ALLOW_USER_ALIAS"):
|
|
497
|
-
text +=
|
|
492
|
+
text += t("alias.help_section", config=self.config, node=example_node, num=6)
|
|
498
493
|
|
|
499
494
|
return text
|
|
500
495
|
|
|
@@ -115,7 +115,8 @@ def render_device_lines(node_status, grouped_usage, idle_groups, config=None):
|
|
|
115
115
|
Generate display lines from locked and idle device groups.
|
|
116
116
|
"""
|
|
117
117
|
lines = []
|
|
118
|
-
|
|
118
|
+
force_show = config.get_val("DISPLAY_DEVICE_MODEL") if config else False
|
|
119
|
+
show_model = force_show or _is_heterogeneous(node_status)
|
|
119
120
|
all_segments = []
|
|
120
121
|
|
|
121
122
|
has_merged = any(len(dev_ids) > 1 for (_, dev_ids) in grouped_usage) or any(
|
|
@@ -102,18 +102,18 @@ MESSAGES = {
|
|
|
102
102
|
"help.kickout_example": " kickout {node} (force-release node {node})\n",
|
|
103
103
|
"help.query_node_example": " query {node} (query node {node})\n",
|
|
104
104
|
# ── Help text (DEVICE) command examples ──
|
|
105
|
-
"help.lock_all_devices_example": " lock {node}
|
|
106
|
-
"help.lock_device_example": " lock {node} dev0
|
|
107
|
-
"help.lock_device_duration_example": " lock {node} dev0 2h
|
|
108
|
-
"help.lock_device_range_example": " lock {node} dev0-3
|
|
109
|
-
"help.slock_device_range_example": " slock {node} dev0-3
|
|
110
|
-
"help.unlock_device_example": " unlock {node}
|
|
111
|
-
"help.unlock_device_range_example": " unlock {node} dev0-3
|
|
112
|
-
"help.free_device_range_example": " free {node} dev0-3
|
|
113
|
-
"help.free_node_all_example": " free {node}
|
|
114
|
-
"help.kickout_device_example": " kickout {node}
|
|
115
|
-
"help.kickout_device_range_example": " kickout {node} dev0-3
|
|
116
|
-
"help.kickout_device_range2_example": " kickout {node} dev0
|
|
105
|
+
"help.lock_all_devices_example": " lock {node}\n",
|
|
106
|
+
"help.lock_device_example": " lock {node} dev0\n",
|
|
107
|
+
"help.lock_device_duration_example": " lock {node} dev0 2h\n",
|
|
108
|
+
"help.lock_device_range_example": " lock {node} dev0-3\n",
|
|
109
|
+
"help.slock_device_range_example": " slock {node} dev0-3 2h\n",
|
|
110
|
+
"help.unlock_device_example": " unlock {node}\n",
|
|
111
|
+
"help.unlock_device_range_example": " unlock {node} dev0-3\n",
|
|
112
|
+
"help.free_device_range_example": " free {node} dev0-3\n",
|
|
113
|
+
"help.free_node_all_example": " free {node}\n",
|
|
114
|
+
"help.kickout_device_example": " kickout {node}\n",
|
|
115
|
+
"help.kickout_device_range_example": " kickout {node} dev0-3\n",
|
|
116
|
+
"help.kickout_device_range2_example": " kickout {node} dev0\n",
|
|
117
117
|
"help.resource_list_title": "Resource list:\n",
|
|
118
118
|
"help.resource_list_item": " {node_key}: dev_id 0~{max_dev}\n",
|
|
119
119
|
# ── Help text (QUEUE) extras ──
|
|
@@ -174,6 +174,7 @@ MESSAGES = {
|
|
|
174
174
|
"opkick.notify_kicked": "⚠️ [Operator Release]\n\nNode: {node_key}\n",
|
|
175
175
|
"opkick.notify_kicked_reason": "Reason: {reason}\n\n",
|
|
176
176
|
# ── Alias command ──
|
|
177
|
+
"alias.help_section": "{num}. Alias: alias {node} <label>\n Clear: alias {node}\n",
|
|
177
178
|
"alias.usage": "Usage: alias <node_key> [label]\nExample: alias node0 10.10.10.56\nClear: alias node0",
|
|
178
179
|
"alias.invalid_node": "Node {node_key} does not exist. Available: {valid_keys}\n",
|
|
179
180
|
"alias.invalid_alias": "Alias cannot contain line breaks; please enter a single-line label",
|
|
@@ -96,18 +96,18 @@ MESSAGES = {
|
|
|
96
96
|
"help.kickout_example": " kickout {node} (强制释放{node}节点)\n",
|
|
97
97
|
"help.query_node_example": " query {node} (查询{node}节点)\n",
|
|
98
98
|
# ── Help text (DEVICE) command examples ──
|
|
99
|
-
"help.lock_all_devices_example": " lock {node}
|
|
100
|
-
"help.lock_device_example": " lock {node} dev0
|
|
101
|
-
"help.lock_device_duration_example": " lock {node} dev0 2h
|
|
102
|
-
"help.lock_device_range_example": " lock {node} dev0-3
|
|
103
|
-
"help.slock_device_range_example": " slock {node} dev0-3
|
|
104
|
-
"help.unlock_device_example": " unlock {node}
|
|
105
|
-
"help.unlock_device_range_example": " unlock {node} dev0-3
|
|
106
|
-
"help.free_device_range_example": " free {node} dev0-3
|
|
107
|
-
"help.free_node_all_example": " free {node}
|
|
108
|
-
"help.kickout_device_example": " kickout {node}
|
|
109
|
-
"help.kickout_device_range_example": " kickout {node} dev0-3
|
|
110
|
-
"help.kickout_device_range2_example": " kickout {node} dev0
|
|
99
|
+
"help.lock_all_devices_example": " lock {node}\n",
|
|
100
|
+
"help.lock_device_example": " lock {node} dev0\n",
|
|
101
|
+
"help.lock_device_duration_example": " lock {node} dev0 2h\n",
|
|
102
|
+
"help.lock_device_range_example": " lock {node} dev0-3\n",
|
|
103
|
+
"help.slock_device_range_example": " slock {node} dev0-3 2h\n",
|
|
104
|
+
"help.unlock_device_example": " unlock {node}\n",
|
|
105
|
+
"help.unlock_device_range_example": " unlock {node} dev0-3\n",
|
|
106
|
+
"help.free_device_range_example": " free {node} dev0-3\n",
|
|
107
|
+
"help.free_node_all_example": " free {node}\n",
|
|
108
|
+
"help.kickout_device_example": " kickout {node}\n",
|
|
109
|
+
"help.kickout_device_range_example": " kickout {node} dev0-3\n",
|
|
110
|
+
"help.kickout_device_range2_example": " kickout {node} dev0\n",
|
|
111
111
|
"help.resource_list_title": "资源列表:\n",
|
|
112
112
|
"help.resource_list_item": " {node_key}: dev_id 0~{max_dev}\n",
|
|
113
113
|
# ── Help text (QUEUE) extras ──
|
|
@@ -167,6 +167,7 @@ MESSAGES = {
|
|
|
167
167
|
"opkick.notify_kicked": "⚠️【运维释放】\n\n节点: {node_key}\n",
|
|
168
168
|
"opkick.notify_kicked_reason": "原因: {reason}\n\n",
|
|
169
169
|
# ── Alias command ──
|
|
170
|
+
"alias.help_section": "{num}. 备注: alias {node} <备注>\n 清除: alias {node}\n",
|
|
170
171
|
"alias.usage": "用法: alias <节点名> [备注]\n示例: alias node0 10.10.10.56\n清除: alias node0",
|
|
171
172
|
"alias.invalid_node": "节点 {node_key} 不存在,可用节点: {valid_keys}\n",
|
|
172
173
|
"alias.invalid_alias": "备注不能包含换行,请输入单行备注",
|
|
@@ -361,7 +361,7 @@ class NodeBot(BaseLockBot):
|
|
|
361
361
|
reply_info += f" {example_node0}\n"
|
|
362
362
|
|
|
363
363
|
if self.config.get_val("ALLOW_USER_ALIAS"):
|
|
364
|
-
reply_info +=
|
|
364
|
+
reply_info += t("alias.help_section", config=self.config, node=example_node0, num=6)
|
|
365
365
|
|
|
366
366
|
reply_info += "\n"
|
|
367
367
|
return reply_info
|
|
@@ -348,7 +348,7 @@ class QueueBot(NodeBot):
|
|
|
348
348
|
parts.append(f" {example_node0}\n")
|
|
349
349
|
|
|
350
350
|
if self.config.get_val("ALLOW_USER_ALIAS"):
|
|
351
|
-
parts.append(
|
|
351
|
+
parts.append(t("alias.help_section", config=self.config, node=example_node0, num=8))
|
|
352
352
|
|
|
353
353
|
parts.append("\n")
|
|
354
354
|
return "".join(parts)
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|