auto-save 2026-05-09 17:52 (~3)
This commit is contained in:
@@ -1,19 +1,5 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "d8b5e3a",
|
||||
"message": "auto-save 2026-05-07 15:26 (~1)",
|
||||
"ts": "2026-05-07T15:26:53+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "a6a644e",
|
||||
"message": "auto-save 2026-05-07 15:32 (~1)",
|
||||
"ts": "2026-05-07T15:34:35+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "d8dcef7",
|
||||
@@ -3474,6 +3460,19 @@
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 1 项未提交变更 · 最近提交:auto-save 2026-05-09 17:41 (~1)",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-09T17:46:54+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-09 17:46 (~1)",
|
||||
"hash": "4dc1b24",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-09T09:48:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 master · 1 项未提交变更 · 最近提交:auto-save 2026-05-09 17:46 (~1)",
|
||||
"files_changed": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
2. 事件订阅里添加请求地址:默认应用用 `https://hermes.kang-kang.com/feishu/events`;其它应用用 `https://hermes.kang-kang.com/feishu/events/{app_id}`。
|
||||
3. 如果启用事件加密,需要先给本服务补充解密支持;当前版本按明文事件回调处理。
|
||||
4. 建议配置 `FEISHU_VERIFICATION_TOKEN`,并保持和飞书后台一致。
|
||||
5. 如果飞书后台刚切换过 token,`FEISHU_VERIFICATION_TOKEN` 可临时用英文逗号配置多个值,兼容旧事件投递和新 URL 校验。
|
||||
|
||||
## 主动通知示例
|
||||
|
||||
|
||||
@@ -37,6 +37,10 @@ def _csv_set(value: str) -> set[str]:
|
||||
return {item.strip() for item in value.split(",") if item.strip()}
|
||||
|
||||
|
||||
def _csv_list(value: str) -> list[str]:
|
||||
return [item.strip() for item in value.split(",") if item.strip()]
|
||||
|
||||
|
||||
def _load_feishu_apps() -> dict[str, dict[str, Any]]:
|
||||
apps: dict[str, dict[str, Any]] = {}
|
||||
for suffix in ["", *[f"_{idx}" for idx in range(2, 10)]]:
|
||||
@@ -47,7 +51,7 @@ def _load_feishu_apps() -> dict[str, dict[str, Any]]:
|
||||
apps[app_id] = {
|
||||
"app_id": app_id,
|
||||
"app_secret": app_secret,
|
||||
"verification_token": _env(f"FEISHU_VERIFICATION_TOKEN{suffix}"),
|
||||
"verification_tokens": _csv_list(_env(f"FEISHU_VERIFICATION_TOKEN{suffix}")),
|
||||
"default_receive_id": _env(f"FEISHU_DEFAULT_RECEIVE_ID{suffix}"),
|
||||
"default_receive_id_type": _env(
|
||||
f"FEISHU_DEFAULT_RECEIVE_ID_TYPE{suffix}",
|
||||
@@ -188,17 +192,17 @@ def token_digest(value: str) -> str:
|
||||
|
||||
def verify_callback_token(body: dict[str, Any], app_id: str) -> bool:
|
||||
app = Config.feishu_apps.get(app_id, {})
|
||||
expected = app.get("verification_token", "")
|
||||
if not expected:
|
||||
expected_tokens = app.get("verification_tokens", [])
|
||||
if not expected_tokens:
|
||||
return True
|
||||
token = callback_token(body)
|
||||
ok = token == expected
|
||||
ok = token in expected_tokens
|
||||
if not ok:
|
||||
logging.warning(
|
||||
"invalid Feishu verification token app_id=%s got=%s expected=%s body_keys=%s header_keys=%s event_keys=%s",
|
||||
"invalid Feishu verification token app_id=%s got=%s expected_any=%s body_keys=%s header_keys=%s event_keys=%s",
|
||||
app_id,
|
||||
token_digest(token),
|
||||
token_digest(expected),
|
||||
[token_digest(item) for item in expected_tokens],
|
||||
sorted(body.keys()),
|
||||
sorted(body.get("header", {}).keys()) if isinstance(body.get("header"), dict) else [],
|
||||
sorted(body.get("event", {}).keys()) if isinstance(body.get("event"), dict) else [],
|
||||
|
||||
Reference in New Issue
Block a user