package config import ( "os" "strings" "time" "git.misaka.ren/M1saka/zhanlu_proxy/internal/auth" "git.misaka.ren/M1saka/zhanlu_proxy/internal/util" ) type Config struct { ListenAddr string MobileLoginBaseURL string MobileModelBaseURL string UpstreamPath string DBPath string StatsDisabled bool SSOExchangeURL string SSOBaseURL string TokenDecryptKey string PublicKeyPEM string PhonePublicKeyPEM string SM2PrivateKey string OpenAIAPIKey string LoginPassword string PluginVersion string UpstreamTimeout time.Duration StreamIdleTimeout time.Duration Debug bool Credentials auth.Credentials } func Load() (Config, error) { cfg := Config{ ListenAddr: getenv("ZHANLU_LISTEN_ADDR", ":8080"), MobileLoginBaseURL: util.FirstNonEmpty(os.Getenv("ZHANLU_MOBILE_LOGIN_BASE_URL"), getenv("ZHANLU_SERVER_BASE_URL", "https://ecloud.10086.cn")), MobileModelBaseURL: getenv("ZHANLU_MOBILE_MODEL_BASE_URL", "https://ecloud.10086.cn/api/query/aigateway"), UpstreamPath: getenv("ZHANLU_UPSTREAM_PATH", "/chat/completions"), DBPath: getenv("ZHANLU_DB_FILE", "zhanlu.db"), StatsDisabled: strings.EqualFold(os.Getenv("ZHANLU_STATS_DISABLED"), "true"), SSOBaseURL: getenv("ZHANLU_SSO_BASE_URL", "http://4c.hq.cmcc"), SSOExchangeURL: getenv("ZHANLU_SSO_EXCHANGE_URL", "http://rdcloud.4c.hq.cmcc/cmdevops-aiplus-agent-gateway/api/acepilot/zhanlu/authToken"), TokenDecryptKey: getenv("ZHANLU_TOKEN_DECRYPT_KEY", "3jw7woww2rvhla6k"), PublicKeyPEM: getenv("ZHANLU_PUBLIC_KEY_PEM", defaultPublicKeyPEM), PhonePublicKeyPEM: getenv("ZHANLU_PHONE_PUBLIC_KEY_PEM", defaultPhonePublicKeyPEM), SM2PrivateKey: getenv("ZHANLU_APIKEY_AUTH_SM2_PRIVATE_KEY", defaultSM2PrivateKey), OpenAIAPIKey: os.Getenv("OPENAI_COMPAT_API_KEY"), LoginPassword: os.Getenv("ZHANLU_LOGIN_PASSWORD"), PluginVersion: getenv("ZHANLU_PLUGIN_VERSION", "1.4.2"), UpstreamTimeout: durationEnv("ZHANLU_UPSTREAM_TIMEOUT", 300*time.Second), StreamIdleTimeout: durationEnv("ZHANLU_STREAM_IDLE_TIMEOUT", 300*time.Second), Debug: strings.EqualFold(os.Getenv("ZHANLU_DEBUG"), "true"), } cfg.Credentials = auth.Credentials{ AccessKey: os.Getenv("ZHANLU_ACCESS_KEY"), SecretKey: os.Getenv("ZHANLU_SECRET_KEY"), Token: os.Getenv("ZHANLU_TOKEN"), APIKey: os.Getenv("ZHANLU_API_KEY"), } // Credentials from the environment were incomplete; the store serves the // persisted row at runtime. return cfg, nil } func getenv(key, fallback string) string { if v := strings.TrimSpace(os.Getenv(key)); v != "" { return v } return fallback } func durationEnv(key string, fallback time.Duration) time.Duration { v := strings.TrimSpace(os.Getenv(key)) if v == "" { return fallback } d, err := time.ParseDuration(v) if err != nil { return fallback } return d } const defaultPublicKeyPEM = `-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhxudxTewPgljUHEZHkusP7m3I+zA4/RGvuUMt6TtII/m4zwUOm/Y31zHBTmkCCt8k5vj9y+AmO0TsGmHooNQuMebakdmEWdcA5h7YAHHFbF2w5LcxIXjib08vgVpA+m3R5xPbLK+vfHe2aAX36b5nHReDNncY5vAl3U4CgIEBGPqyG67vJytRWqP+sfEdw5+m192Rf4SCGyiBzRmjiVlH3zeEBjdbOrkAnzKOVz6AHBl2q7LPLJKIzxjoAyhEp5qnDjHUFo5VZUgFwUOt83A/jbGMyzmjRoxBuvKcs9tBuorZyUwIsZN6E+rtQk2YqMPj4RkDsZ7LRmj6on8sN2rHQIDAQAB -----END PUBLIC KEY-----` const defaultPhonePublicKeyPEM = `-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnqiA2qP9BNvKw5DnVnrBVBhd+5gJDVn3mDemCfq/AN1cdaHV57hQo6R1ufp45mOkSwLaJcTE82zFKmgKoEAKwD1SR10rp0xJC7x3yvx2FbpEsiW9TeZlvJdri1BYKUMS8OP8ykjHSJoy0oMaV6e95R2rsu4DEH7JuA9+Bt0sOoLewvHx/fs1e28tH+928uUEKdLug+cv/XTKjLudpLjiSMPZU6EHFqrUhA9zmEasOMmg9Dj0j4sChBooCeCGnh/pYHJaosH5amhlSQ8FnEG0BQBrQbZ+qhRH4LYyqGYN8grDNeSnPj7vPDcwiEm++85i5AngZfEMnGWZg5jYDhO9+QIDAQAB -----END PUBLIC KEY-----` const defaultSM2PrivateKey = "8d6ee90b3c4d299ae5abd655dbc3547c110ae8aeff1de18b0df241f215f90748"