package wire import ( "time" "with_you/internal/cache" "with_you/internal/config" "with_you/internal/model" "with_you/internal/pkg/crypto" "with_you/internal/pkg/email" "with_you/internal/pkg/hook" "with_you/internal/pkg/openai" "with_you/internal/pkg/redis" "with_you/internal/pkg/s3" "with_you/internal/pkg/tencent" "with_you/internal/pkg/ws" "with_you/internal/repository" "with_you/internal/service" "github.com/google/wire" "go.uber.org/zap" "gorm.io/gorm" ) // InfrastructureSet 基础设施 Provider Set var InfrastructureSet = wire.NewSet( // 配置 ProvideConfig, // 日志 ProvideLogger, // 数据库 ProvideDB, // 事务管理器 ProvideTransactionManager, // Redis 和缓存 ProvideRedisClient, ProvideCache, // 钩子系统 ProvideHookManager, ProvideBuiltinHooks, ProvideModerationHooks, // WebSocket Hub ProvideWSHub, // 外部服务客户端 ProvideOpenAIClient, ProvideTencentClient, ProvideEmailClient, ProvideS3Client, // 消息加密器 ProvideMessageEncryptor, ) // ProvideConfig 加载配置 func ProvideConfig() (*config.Config, error) { return config.Load("configs/config.yaml") } // ProvideDB 提供数据库连接 func ProvideDB(cfg *config.Config) (*gorm.DB, error) { return model.NewDB(&cfg.Database) } // ProvideRedisClient 提供 Redis 客户端 func ProvideRedisClient(cfg *config.Config) *redis.Client { client, err := redis.New(&cfg.Redis) if err != nil { zap.L().Warn("Failed to connect to Redis, falling back to memory cache", zap.Error(err), ) return nil } return client } // ProvideCache 提供缓存实例 func ProvideCache(cfg *config.Config, redisClient *redis.Client) cache.Cache { cache.Configure(cache.Settings{ Enabled: cfg.Cache.Enabled, KeyPrefix: cfg.Cache.KeyPrefix, DefaultTTL: time.Duration(cfg.Cache.DefaultTTL) * time.Second, NullTTL: time.Duration(cfg.Cache.NullTTL) * time.Second, JitterRatio: cfg.Cache.JitterRatio, PostListTTL: time.Duration(cfg.Cache.Modules.PostList) * time.Second, ConversationTTL: time.Duration(cfg.Cache.Modules.Conversation) * time.Second, UnreadCountTTL: time.Duration(cfg.Cache.Modules.UnreadCount) * time.Second, GroupMembersTTL: time.Duration(cfg.Cache.Modules.GroupMembers) * time.Second, DisableFlushDB: cfg.Cache.DisableFlushDB, }) if cfg.Cache.Local.Enabled { layeredCache := cache.NewLayeredCache(redisClient, &cache.LayeredCacheOptions{ LocalSize: cfg.Cache.Local.Size, LocalBuckets: cfg.Cache.Local.Buckets, LocalDefaultTTL: time.Duration(cfg.Cache.Local.DefaultTTL) * time.Second, KeyPrefix: cfg.Cache.KeyPrefix, Enabled: cfg.Cache.Enabled, }) zap.L().Info("Initialized layered cache (local LRU + Redis)") return layeredCache } if redisClient == nil { zap.L().Warn("Redis client is nil, cache will not be available") return nil } cacheInstance := cache.NewRedisCache(redisClient) zap.L().Info("Initialized Redis cache via dependency injection") return cacheInstance } // ProvideHookManager 提供钩子管理器 func ProvideHookManager() *hook.Manager { return hook.NewManager(&hook.ManagerOptions{ MaxConcurrentAsync: 100, Enabled: true, }) } // ProvideBuiltinHooks 注册内置钩子 func ProvideBuiltinHooks(manager *hook.Manager) *hook.BuiltinHooks { builtin := hook.NewBuiltinHooks(manager) builtin.RegisterAll() zap.L().Info("Registered builtin hooks") return builtin } // ProvideModerationHooks 注册审核钩子 func ProvideModerationHooks( manager *hook.Manager, postAIService *service.PostAIService, postRepo repository.PostRepository, commentRepo repository.CommentRepository, userRepo repository.UserRepository, sensitiveService service.SensitiveService, cfg *config.Config, ) *hook.ModerationHooks { strictMode := cfg.OpenAI.StrictModeration moderationHooks := hook.NewModerationHooks( postAIService, sensitiveService, postRepo, commentRepo, userRepo, strictMode, "***", ) moderationHooks.RegisterAll(manager) zap.L().Info("Registered moderation hooks", zap.Bool("strict_mode", strictMode), ) return moderationHooks } // ProvideWSHub 提供 WebSocket Hub func ProvideWSHub() *ws.Hub { return ws.NewHub() } // ProvideOpenAIClient 提供 OpenAI 客户端 func ProvideOpenAIClient(cfg *config.Config) openai.Client { return openai.NewClient(openai.ConfigFromAppConfig(&cfg.OpenAI)) } // ProvideTencentClient 提供腾讯云TMS客户端 func ProvideTencentClient(cfg *config.Config) tencent.Client { return tencent.NewClient(tencent.Config{ Enabled: cfg.TencentTMS.Enabled, SecretID: cfg.TencentTMS.SecretID, SecretKey: cfg.TencentTMS.SecretKey, Region: cfg.TencentTMS.Region, BizType: cfg.TencentTMS.BizType, Timeout: cfg.TencentTMS.Timeout, }) } // ProvideEmailClient 提供邮件客户端 func ProvideEmailClient(cfg *config.Config) email.Client { return email.NewClient(email.ConfigFromAppConfig(&cfg.Email)) } // ProvideS3Client 提供 S3 客户端 func ProvideS3Client(cfg *config.Config) (*s3.Client, error) { return s3.New(&cfg.S3) } // ProvideTransactionManager 提供事务管理器 func ProvideTransactionManager(db *gorm.DB) repository.TransactionManager { return repository.NewTransactionManager(db) } // ProvideMessageEncryptor 提供消息加密器 func ProvideMessageEncryptor(cfg *config.Config) error { if !cfg.Encryption.Enabled { zap.L().Info("Message encryption is disabled") return nil } if len(cfg.Encryption.Key) != 32 { zap.L().Error("Encryption key must be 32 bytes for AES-256", zap.Int("actual_length", len(cfg.Encryption.Key)), ) return nil } if err := crypto.InitMessageEncryptor(cfg.Encryption.Key, cfg.Encryption.KeyVersion); err != nil { zap.L().Error("Failed to initialize message encryptor", zap.Error(err)) return err } zap.L().Info("Message encryption initialized successfully", zap.Int("key_version", cfg.Encryption.KeyVersion), ) return nil } // ProvideLogger 提供 Zap Logger func ProvideLogger() *zap.Logger { logger, err := zap.NewProduction() if err != nil { panic("Failed to create logger: " + err.Error()) } // 设置为全局 logger,以便在其他地方使用 zap.L() zap.ReplaceGlobals(logger) return logger }