ForcePilot/backend/package/yuxi/channel/extensions/github/gateway.py
Kris 702fcd4c33 feat(github): 新增GitHub渠道插件完整实现
新增了完整的GitHub集成插件,包含认证、会话管理、Webhook处理、消息收发、反应支持等核心功能,支持Issues、Discussions、Pull Request的交互与通知。
2026-05-21 10:48:42 +08:00

78 lines
2.5 KiB
Python

from __future__ import annotations
import asyncio
import logging
from dataclasses import dataclass
from yuxi.channel.extensions.github.config import GitHubConfigAdapter
from yuxi.channel.extensions.github.types import GitHubAppAccount
from yuxi.channel.extensions.github.webhook import GitHubWebhookHandler
from yuxi.channel.gateway.routes import webhook_registry
logger = logging.getLogger(__name__)
@dataclass
class GitHubGatewaySnapshot:
queue: asyncio.Queue
webhook_path: str
running: bool = False
class GitHubGatewayAdapter:
def __init__(self):
self._config_adapter = GitHubConfigAdapter()
self._webhook_handler = GitHubWebhookHandler()
self._running: dict[str, bool] = {}
self._account: GitHubAppAccount | None = None
async def start(self, ctx) -> object:
account_dict = getattr(ctx, "account", {}) or {}
account_id = account_dict.get("account_id", "default")
resolved = await self._config_adapter.resolve_account(account_id)
account = GitHubAppAccount(
account_id=resolved.get("account_id", "default"),
app_id=resolved.get("app_id", 0),
private_key=resolved.get("private_key", ""),
installation_id=resolved.get("installation_id", 0),
webhook_secret=resolved.get("webhook_secret", ""),
webhook_path=resolved.get("webhook_path", "/api/webhook/github"),
bot_login=resolved.get("bot_login", ""),
repositories=resolved.get("repositories", []),
dm_policy=resolved.get("dm_policy", "open"),
allow_from=resolved.get("allow_from", []),
)
if not account.is_configured:
logger.warning("GitHub account not configured: %s", account_id)
return asyncio.Queue()
self._account = account
self._webhook_handler.register_account(account)
webhook_registry.register(
"github",
self._webhook_handler.handle_webhook,
guard_config=None,
)
self._running[account_id] = True
logger.info(
"GitHub gateway started for account: %s, webhook: %s",
account_id, account.webhook_path,
)
queue = getattr(ctx, "queue", asyncio.Queue())
return GitHubGatewaySnapshot(
queue=queue,
webhook_path=account.webhook_path,
running=True,
)
async def stop(self, ctx) -> None:
self._running.clear()
self._account = None
logger.info("GitHub gateway stopped")