package main // This file builds the four built-in IM channel adapters from environment // configuration. The config package carries no channel block, so credentials are // read from CHANNEL__* env vars here and injected into each adapter's // concrete Config. Adapters whose construction fails are skipped rather than // aborting boot, matching the "no credentials → warn and continue" contract of // the channel bridge. import ( "log/slog" "os" "git.yeij.top/AskaEth/Cyrene_v2/internal/channel/adapter" "git.yeij.top/AskaEth/Cyrene_v2/internal/logger" "git.yeij.top/AskaEth/Cyrene_v2/plugins/channels/qq_obv11" "git.yeij.top/AskaEth/Cyrene_v2/plugins/channels/telegram" "git.yeij.top/AskaEth/Cyrene_v2/plugins/channels/webhook" "git.yeij.top/AskaEth/Cyrene_v2/plugins/channels/weixin_ilink" ) // buildChannelAdapters constructs the four channel adapters from environment // configuration and returns the successfully built subset. Adapter construction // never dials the network; actual connection happens in the channel bridge. func buildChannelAdapters(log *slog.Logger) []adapter.PlatformAdapter { qq := qq_obv11.NewAdapter(qq_obv11.Config{ Mode: envString("CHANNEL_QQ_OBV11_MODE", "server"), ListenAddr: os.Getenv("CHANNEL_QQ_OBV11_LISTEN_ADDR"), RemoteURL: os.Getenv("CHANNEL_QQ_OBV11_REMOTE_URL"), AccessToken: os.Getenv("CHANNEL_QQ_OBV11_ACCESS_TOKEN"), SelfID: os.Getenv("CHANNEL_QQ_OBV11_SELF_ID"), Logger: log, }) weixin, werr := weixin_ilink.New(weixin_ilink.Config{ BaseURL: os.Getenv("CHANNEL_WEIXIN_ILINK_BASE_URL"), CDNBaseURL: os.Getenv("CHANNEL_WEIXIN_ILINK_CDN_BASE_URL"), BotToken: os.Getenv("CHANNEL_WEIXIN_ILINK_BOT_TOKEN"), BotID: os.Getenv("CHANNEL_WEIXIN_ILINK_BOT_ID"), OwnerID: os.Getenv("CHANNEL_WEIXIN_ILINK_OWNER_ID"), }, nil, log) if werr != nil { // A blank config defaults to a valid base URL, so this only fires on an // explicitly invalid one; skip the channel rather than fail startup. log.Warn("weixin-ilink adapter build skipped", "error", werr) weixin = nil } tg := telegram.New(telegram.Config{ BotToken: os.Getenv("CHANNEL_TELEGRAM_BOT_TOKEN"), WebhookURL: os.Getenv("CHANNEL_TELEGRAM_WEBHOOK_URL"), }, telegram.WithLogger(log)) // webhook.WithLogger does not tag provenance, so wrap base with the module // source here to satisfy the logging rule. wh := webhook.New( webhook.WithConfig(webhook.Config{ EndpointPath: os.Getenv("CHANNEL_WEBHOOK_ENDPOINT_PATH"), ChannelID: os.Getenv("CHANNEL_WEBHOOK_CHANNEL_ID"), ChannelName: os.Getenv("CHANNEL_WEBHOOK_CHANNEL_NAME"), Secret: os.Getenv("CHANNEL_WEBHOOK_SECRET"), SignatureHeader: os.Getenv("CHANNEL_WEBHOOK_SIGNATURE_HEADER"), }), webhook.WithLogger(logger.WithSource(log, "plugins/channels/webhook")), ) out := []adapter.PlatformAdapter{qq, tg, wh} if weixin != nil { out = append(out, weixin) } return out } // envString returns the value of key, or fallback when the variable is unset or // blank. func envString(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback }