64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
"""wechat_bot_bindings 表(ClawBot 个人微信绑定,DESIGN §8.7 渠道 A).
|
|
|
|
Revision ID: 0012
|
|
Revises: 0011
|
|
Create Date: 2026-06-24
|
|
|
|
新增独立表 wechat_bot_bindings —— 不碰现有 schema(公测兼容)。一行 = 一个用户绑定其
|
|
个人微信 ClawBot。bot_token / latest_context_token 存密文(core/wechat/crypto.py)。
|
|
入站长轮询管理器按 status='active' 拉绑定起 getupdates 循环;主动推送用 latest_context_token
|
|
(24h 内有效)。详 DESIGN §8.7 / core/storage/models.py。
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
from sqlalchemy.dialects.postgresql import UUID as PG_UUID
|
|
|
|
|
|
revision: str = "0012"
|
|
down_revision: Union[str, None] = "0011"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"wechat_bot_bindings",
|
|
sa.Column(
|
|
"user_id", PG_UUID(as_uuid=True),
|
|
sa.ForeignKey("users.user_id", ondelete="CASCADE"), primary_key=True,
|
|
),
|
|
sa.Column("bot_token", sa.Text(), nullable=False),
|
|
sa.Column("bot_im_id", sa.Text(), nullable=True),
|
|
sa.Column("user_im_id", sa.Text(), nullable=True),
|
|
sa.Column(
|
|
"base_url", sa.Text(), nullable=False,
|
|
server_default="https://ilinkai.weixin.qq.com",
|
|
),
|
|
sa.Column("latest_context_token", sa.Text(), nullable=True),
|
|
sa.Column("context_token_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column(
|
|
"chat_task_id", PG_UUID(as_uuid=True),
|
|
sa.ForeignKey("tasks.task_id", ondelete="SET NULL"), nullable=True,
|
|
),
|
|
sa.Column("status", sa.Text(), nullable=False, server_default="active"),
|
|
sa.Column(
|
|
"created_at", sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(), nullable=False,
|
|
),
|
|
sa.Column(
|
|
"updated_at", sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(), nullable=False,
|
|
),
|
|
)
|
|
# 入站管理器扫 active 绑定起长轮询
|
|
op.create_index(
|
|
"ix_wechat_bot_bindings_active", "wechat_bot_bindings", ["status"],
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_wechat_bot_bindings_active", table_name="wechat_bot_bindings")
|
|
op.drop_table("wechat_bot_bindings")
|