跳转至

app

feishu.gateway.app

GatewayContext dataclass

供部署方在网关上挂载事件处理器的配置上下文。

源代码位于: feishu/gateway/app.py
Python
@dataclass(frozen=True)
class GatewayContext:
    r"""供部署方在网关上挂载事件处理器的配置上下文。"""

    client: Any
    seen_store: SeenStore

create_gateway

Python
create_gateway(config: GatewayConfig, *, configure: GatewayConfigure | None = None, client: Any | None = None) -> Starlette

创建一个轻量的 Starlette 飞书网关应用。

源代码位于: feishu/gateway/app.py
Python
def create_gateway(
    config: GatewayConfig,
    *,
    configure: GatewayConfigure | None = None,
    client: Any | None = None,
) -> Starlette:
    r"""创建一个轻量的 Starlette 飞书网关应用。"""
    if not config.service_keys:
        raise ValueError("GatewayConfig.service_keys must contain at least one service API key")
    if configure is not None and config.encrypt_key is None:
        raise ValueError("GatewayConfig.encrypt_key is required when configure is provided")

    owns_client = client is None
    feishu_client = client or FeishuClient(
        config.app_id,
        config.app_secret,
        region=config.region,
        base_url=config.base_url,
        accounts_url=config.accounts_url,
    )
    seen_store = InMemorySeenStore()
    routes = create_gateway_routes(config, feishu_client)

    dispatcher: EventDispatcher | None = None
    if config.encrypt_key is not None:
        configured = configure(GatewayContext(feishu_client, seen_store)) if configure is not None else None
        dispatcher = configured or EventDispatcher()
        routes.extend(
            [
                create_event_route(
                    dispatcher,
                    encrypt_key=config.encrypt_key,
                    verification_token=config.verification_token,
                    seen_store=seen_store,
                    max_age_seconds=config.event_max_age_seconds,
                ),
                create_card_route(
                    dispatcher,
                    encrypt_key=config.encrypt_key,
                    verification_token=config.verification_token,
                    seen_store=seen_store,
                    max_age_seconds=config.event_max_age_seconds,
                ),
            ]
        )

    @asynccontextmanager
    async def lifespan(app: Starlette) -> AsyncIterator[None]:
        app.state.feishu_client = feishu_client
        app.state.seen_store = seen_store
        app.state.event_dispatcher = dispatcher
        try:
            yield
        finally:
            if owns_client:
                close = getattr(feishu_client, "aclose", None)
                if close is not None:
                    await close()

    return Starlette(routes=routes, lifespan=lifespan)