oclaw/svc/integrations/wecom_client.py
oliver 420abac9f1 refactor: root-package imports (svc/runtime/interfaces) and fix PYTHONPATH
- Rename platform/ to svc/ to avoid shadowing stdlib platform.
- Replace from oclaw.* with from svc/runtime/interfaces; update -m CLI paths.
- tests/conftest: prepend repo root to sys.path (no parent-folder package name).
- CI: paths and offline_eval script under repo root.
- Ops scripts: PYTHONPATH must be repo root for python -m runtime.* (fixes gateway/WhatsApp sidecar startup).
- Fix default oclaw.json path in tabular/file attachment limits; stabilize attachment test config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 14:51:17 +08:00

64 lines
2.5 KiB
Python

from __future__ import annotations
from svc.persistence.sqlite_store import SqliteStore
class WeComClient:
"""WeCom AI bot (websocket / bot_api only)."""
def __init__(self, store: SqliteStore):
self.store = store
def _bot_cfg(self) -> tuple[str, str]:
bot_id = str(self.store.get_setting("wecom_bot_id") or "").strip()
bot_secret = str(self.store.get_secret("wecom_bot_secret") or self.store.get_setting("wecom_bot_secret") or "").strip()
if bot_id and bot_secret:
return bot_id, bot_secret
if bot_id:
row = self.store.find_user_by_channel_account(channel="wecom", account_id=bot_id)
if row:
tid = str(row["tenant_id"])
uid = str(row["user_id"])
sk = f"wecom:bot_secret:{tid}:{uid}:{bot_id}"
sec = str(self.store.get_secret(sk) or "").strip()
if sec:
return bot_id, sec
try:
tenants = self.store.list_tenants(limit=1)
tenant_id = str((tenants[0] or {}).get("id") or "") if tenants else ""
if not tenant_id:
return bot_id, bot_secret
admin = self.store.get_user_by_username(tenant_id=tenant_id, username="administrator")
user_id = str((admin or {}).get("id") or "")
if not user_id:
return bot_id, bot_secret
accounts = self.store.list_user_channel_accounts(
tenant_id=tenant_id, user_id=user_id, channel="wecom", include_inactive=False
)
if not accounts:
return bot_id, bot_secret
aid = str(accounts[0].get("account_id") or "").strip()
if not aid:
return bot_id, bot_secret
scoped_key = f"wecom:bot_secret:{tenant_id}:{user_id}:{aid}"
sec = str(self.store.get_secret(scoped_key) or "").strip()
if aid and sec:
return aid, sec
except Exception:
return bot_id, bot_secret
return bot_id, bot_secret
def mode_for_account(self, account_id: str) -> str: # noqa: ARG002
return "bot_api"
def mode(self) -> str:
return "bot_api"
def get_bot_credentials(self) -> tuple[str, str]:
bot_id, bot_secret = self._bot_cfg()
if not bot_id or not bot_secret:
raise RuntimeError("missing wecom bot config: wecom_bot_id / wecom_bot_secret")
return bot_id, bot_secret
__all__ = ["WeComClient"]