diff --git a/blocking_bridge.go b/blocking_bridge.go deleted file mode 100644 index eee61e9..0000000 --- a/blocking_bridge.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -// 桥接到 internal/blocking — 让根目录其余文件可以继续使用旧名字 -// blockingCache / newBlockingCache / registerAdminBlockingRoutes, -// 而无须改动 main.go / web.go 等十几处调用点。 - -import ( - "github.com/gin-gonic/gin" - - blockingpkg "meshtastic_mqtt_server/internal/blocking" -) - -type blockingCache = blockingpkg.Cache - -func newBlockingCache(s *store) (*blockingCache, error) { - return blockingpkg.New(s) -} - -func registerAdminBlockingRoutes(r gin.IRouter, s *store, b *blockingCache) { - blockingpkg.RegisterRoutes(r, s, b) -} diff --git a/bot_bridge.go b/bot_bridge.go deleted file mode 100644 index 61924d8..0000000 --- a/bot_bridge.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -// 桥接到 internal/bot — 让 main.go / web.go 中使用 botService / -// botTextSender / newBotService / newPKIKeyResolver / registerAdminBotRoutes -// 这些旧名字的代码继续可用。 - -import ( - mqtt "github.com/mochi-mqtt/server/v2" - - "github.com/gin-gonic/gin" - - botpkg "meshtastic_mqtt_server/internal/bot" -) - -type ( - botService = botpkg.Service - botTextSender = botpkg.TextSender - botSendTextRequest = botpkg.SendTextRequest -) - -func newBotService(s *store, server *mqtt.Server, key []byte) *botService { - return botpkg.NewService(s, server, key) -} - -func newPKIKeyResolver(s *store) func(toNodeNum, fromNodeNum uint32) ([]byte, []byte, bool) { - return botpkg.NewPKIKeyResolver(s) -} - -func registerAdminBotRoutes(r gin.IRouter, s *store, sender botTextSender) { - botpkg.RegisterRoutes(r, s, sender) -} diff --git a/config.go b/config.go deleted file mode 100644 index d8af479..0000000 --- a/config.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - cryptotls "crypto/tls" - - cfgpkg "meshtastic_mqtt_server/internal/config" -) - -// 桥接到 internal/config — 让根目录其余文件无须修改即可继续使用旧的非导出名字。 - -const ( - configFileName = cfgpkg.FileName - databaseDriverSQLite = cfgpkg.DriverSQLite - databaseDriverMySQL = cfgpkg.DriverMySQL -) - -// 旧的小写类型名通过别名继续可用。 -type ( - config = cfgpkg.Config - mqttConfig = cfgpkg.MQTTConfig - tlsConfig = cfgpkg.TLSConfig - meshtasticConfig = cfgpkg.MeshtasticConfig - databaseConfig = cfgpkg.DatabaseConfig - sqliteConfig = cfgpkg.SQLiteConfig - mysqlConfig = cfgpkg.MySQLConfig - webConfig = cfgpkg.WebConfig - webAdminConfig = cfgpkg.WebAdminConfig - aiConfig = cfgpkg.AIConfig -) - -func defaultConfig() *config { return cfgpkg.Default() } -func defaultConfigDir() string { return cfgpkg.DefaultDir() } -func defaultConfigPath() string { return cfgpkg.DefaultPath() } -func loadConfig(path string) (*config, error) { return cfgpkg.Load(path) } -func writeConfig(path string, cfg *config) error { return cfgpkg.Write(path, cfg) } -func validateConfig(cfg *config) error { return cfgpkg.Validate(cfg) } -func clearWebSocketPathOnUnsupportedGOOS(cfg *config, goos string) bool { - return cfgpkg.ClearWebSocketPathOnUnsupportedGOOS(cfg, goos) -} - -func buildTLSConfig(cfg tlsConfig) (*cryptotls.Config, error) { - return cfgpkg.BuildTLS(cfg) -} diff --git a/help_bridge.go b/help_bridge.go deleted file mode 100644 index 82ae746..0000000 --- a/help_bridge.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -// 桥接到 internal/help — 让 web.go 中的 registerHelpRoutes / -// registerAdminHelpRoutes / renderHelpMarkdown 旧名字仍可用。 - -import ( - "github.com/gin-gonic/gin" - - helppkg "meshtastic_mqtt_server/internal/help" -) - -func registerHelpRoutes(r gin.IRouter, s *store) { helppkg.RegisterPublicRoutes(r, s) } -func registerAdminHelpRoutes(r gin.IRouter, s *store) { helppkg.RegisterAdminRoutes(r, s) } -func renderHelpMarkdown(markdown string) (string, error) { - return helppkg.RenderMarkdown(markdown) -} diff --git a/llmadmin_bridge.go b/llmadmin_bridge.go deleted file mode 100644 index 287d0c4..0000000 --- a/llmadmin_bridge.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// 桥接到 internal/llmadmin — 让 web.go 中的 registerAdminLLMRoutes 旧名仍可用。 - -import ( - "github.com/gin-gonic/gin" - - llmadminpkg "meshtastic_mqtt_server/internal/llmadmin" -) - -func registerAdminLLMRoutes(r *gin.RouterGroup, s *store) { - llmadminpkg.RegisterRoutes(r, s) -} diff --git a/main.go b/main.go index f2f5b52..adf63c0 100644 --- a/main.go +++ b/main.go @@ -14,15 +14,23 @@ import ( "syscall" "time" - "meshtastic_mqtt_server/ai" - "meshtastic_mqtt_server/autoreply" - "meshtastic_mqtt_server/llm" - "meshtastic_mqtt_server/mqtpp" - mqtt "github.com/mochi-mqtt/server/v2" - "github.com/mochi-mqtt/server/v2/hooks/auth" + mqttauth "github.com/mochi-mqtt/server/v2/hooks/auth" "github.com/mochi-mqtt/server/v2/listeners" "github.com/mochi-mqtt/server/v2/packets" + + "meshtastic_mqtt_server/ai" + "meshtastic_mqtt_server/autoreply" + "meshtastic_mqtt_server/internal/auth" + blockingpkg "meshtastic_mqtt_server/internal/blocking" + botpkg "meshtastic_mqtt_server/internal/bot" + configpkg "meshtastic_mqtt_server/internal/config" + mqttforwardpkg "meshtastic_mqtt_server/internal/mqttforward" + rspkg "meshtastic_mqtt_server/internal/runtimesettings" + storepkg "meshtastic_mqtt_server/internal/store" + webpkg "meshtastic_mqtt_server/internal/web" + "meshtastic_mqtt_server/llm" + "meshtastic_mqtt_server/mqtpp" ) const ( @@ -39,10 +47,10 @@ const ( type meshtasticFilterHook struct { mqtt.HookBase key []byte - dbQueue *dbWriteQueue - stats *meshtasticMessageStats - blocking *blockingCache - settings *runtimeSettingsCache + dbQueue *storepkg.WriteQueue + stats *mqttforwardpkg.Stats + blocking *blockingpkg.Cache + settings *rspkg.Cache pkiResolver func(toNodeNum, fromNodeNum uint32) ([]byte, []byte, bool) autoAcker func(record map[string]any) } @@ -107,7 +115,7 @@ func (h *meshtasticFilterHook) rejectPublish(cl *mqtt.Client, pk packets.Packet, h.dbQueue.EnqueueDiscard(record, pk.Payload, mqttClientInfoFromClient(cl)) } -func blockingViolationForRecord(blocking *blockingCache, record map[string]any) map[string]any { +func blockingViolationForRecord(blocking *blockingpkg.Cache, record map[string]any) map[string]any { if blocking == nil || record == nil { return nil } @@ -129,12 +137,12 @@ func blockingViolationForRecord(blocking *blockingCache, record map[string]any) return nil } -func mqttClientInfoFromClient(cl *mqtt.Client) mqttClientInfo { +func mqttClientInfoFromClient(cl *mqtt.Client) storepkg.MQTTClientInfo { if cl == nil { - return mqttClientInfo{} + return storepkg.MQTTClientInfo{} } - info := mqttClientInfo{ + info := storepkg.MQTTClientInfo{ ClientID: cl.ID, Username: string(cl.Properties.Username), Listener: cl.Net.Listener, @@ -166,8 +174,8 @@ func main() { } // parseArgs 加载配置文件、解析命令行覆盖项,并展开 Meshtastic channel PSK。 -func parseArgs() (*config, error) { - cfg, err := loadConfig(defaultConfigPath()) +func parseArgs() (*configpkg.Config, error) { + cfg, err := configpkg.Load(configpkg.DefaultPath()) if err != nil { return nil, err } @@ -198,9 +206,9 @@ func parseArgs() (*config, error) { if value := os.Getenv("MESH_ADMIN_SESSION_SECRET"); value != "" { cfg.Web.Admin.SessionSecret = value } - clearWebSocketPathOnUnsupportedGOOS(cfg, runtime.GOOS) + configpkg.ClearWebSocketPathOnUnsupportedGOOS(cfg, runtime.GOOS) - if err := validateConfig(cfg); err != nil { + if err := configpkg.Validate(cfg); err != nil { return nil, err } key, err := mqtpp.ExpandPSK(cfg.Meshtastic.PSK) @@ -212,38 +220,38 @@ func parseArgs() (*config, error) { } // run 创建 MQTT broker 和 Web 服务,并阻塞等待退出信号。 -func run(cfg *config) error { - store, err := openStore(cfg.Database) +func run(cfg *configpkg.Config) error { + store, err := storepkg.OpenStore(cfg.Database) if err != nil { return err } defer store.Close() - dbQueue := newDBWriteQueue(store) + dbQueue := storepkg.NewWriteQueue(store) defer dbQueue.Close() if err := store.EnsureDefaultAdmin(cfg.Web.Admin.Username, cfg.Web.Admin.Password); err != nil { return err } - blocking, err := newBlockingCache(store) + blocking, err := blockingpkg.New(store) if err != nil { return err } - settings, err := newRuntimeSettingsCache(store) + settings, err := rspkg.New(store) if err != nil { return err } - messageStats := &meshtasticMessageStats{} + messageStats := &mqttforwardpkg.Stats{} server, mqttHook, mqttAddr, err := startMQTTServer(cfg, store, dbQueue, messageStats, blocking, settings) if err != nil { return err } - botSender := newBotService(store, server, cfg.Key) + botSender := botpkg.NewService(store, server, cfg.Key) mqttHook.autoAcker = botSender.MaybeAutoAck botCtx, stopBotBroadcaster := context.WithCancel(context.Background()) defer stopBotBroadcaster() botSender.StartNodeInfoBroadcaster(botCtx) - forwardManager := newMQTTForwardManager(store) + forwardManager := mqttforwardpkg.NewManager(store) if err := forwardManager.StartFromStore(); err != nil { server.Close() return err @@ -262,12 +270,12 @@ func run(cfg *config) error { providerConfigs := make([]llm.ProviderConfig, 0, len(llmProviders)) for _, p := range llmProviders { providerConfigs = append(providerConfigs, llm.ProviderConfig{ - Name: p.Name, - Active: p.Active, - APIKey: p.APIKey, - BaseURL: p.BaseURL, - Model: p.Model, - Timeout: p.Timeout, + Name: p.Name, + Active: p.Active, + APIKey: p.APIKey, + BaseURL: p.BaseURL, + Model: p.Model, + Timeout: p.Timeout, ContextWindowTokens: p.ContextWindowTokens, }) } @@ -276,7 +284,7 @@ func run(cfg *config) error { botSenderAdapter := autoreply.NewBotServiceAdapter( // SendDirectText: 发送私聊消息 func(ctx context.Context, botID uint64, toNodeNum int64, text string) error { - _, err := botSender.SendText(ctx, botSendTextRequest{ + _, err := botSender.SendText(ctx, botpkg.SendTextRequest{ BotID: botID, MessageType: "direct", ToNodeNum: &toNodeNum, @@ -286,7 +294,7 @@ func run(cfg *config) error { }, // SendChannelText: 发送频道消息 func(ctx context.Context, botID uint64, channelID string, text string) error { - _, err := botSender.SendText(ctx, botSendTextRequest{ + _, err := botSender.SendText(ctx, botpkg.SendTextRequest{ BotID: botID, MessageType: "channel", ChannelID: channelID, @@ -297,10 +305,10 @@ func run(cfg *config) error { ) aiService, err = ai.NewService(ai.Config{ - LLMProviders: providerConfigs, - DataDir: cfg.DataDir, - Enabled: cfg.AI.Enabled, - ToolConfigStore: store, + LLMProviders: providerConfigs, + DataDir: cfg.DataDir, + Enabled: cfg.AI.Enabled, + ToolConfigStore: store, }, store.DB(), botSenderAdapter) if err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to initialize AI service: %v\n", err) @@ -319,12 +327,12 @@ func run(cfg *config) error { var httpServers []*http.Server errCh := make(chan error, 2) if cfg.Web.Enabled { - sessions, err := newSessionManager(cfg.Web.Admin) + sessions, err := auth.NewManager(cfg.Web.Admin) if err != nil { return err } - mqttStatus := mqttRuntimeStatus{server: server, address: mqttAddr, tls: cfg.MQTT.TLS.Enabled, stats: messageStats, dbQueue: dbQueue} - handler := newRouter(cfg.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender) + mqttStatus := webpkg.MQTTRuntimeStatus{Server: server, Address: mqttAddr, TLS: cfg.MQTT.TLS.Enabled, Stats: messageStats, DBQueue: dbQueue} + handler := webpkg.NewRouter(cfg.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender) webAddresses := []string{} if cfg.Web.PortEnabled { httpServer := &http.Server{ @@ -344,7 +352,7 @@ func run(cfg *config) error { httpServers = append(httpServers, httpServer) webAddresses = append(webAddresses, cfg.Web.SocketPath) go func() { - if err := serveHTTPUnixSocket(httpServer, cfg.Web.SocketPath); err != nil && !errors.Is(err, http.ErrServerClosed) { + if err := webpkg.ServeUnixSocket(httpServer, cfg.Web.SocketPath); err != nil && !errors.Is(err, http.ErrServerClosed) { errCh <- err } }() @@ -378,9 +386,9 @@ func run(cfg *config) error { return runErr } -func startMQTTServer(cfg *config, store *store, dbQueue *dbWriteQueue, stats *meshtasticMessageStats, blocking *blockingCache, settings *runtimeSettingsCache) (*mqtt.Server, *meshtasticFilterHook, string, error) { +func startMQTTServer(cfg *configpkg.Config, store *storepkg.Store, dbQueue *storepkg.WriteQueue, stats *mqttforwardpkg.Stats, blocking *blockingpkg.Cache, settings *rspkg.Cache) (*mqtt.Server, *meshtasticFilterHook, string, error) { server := mqtt.New(&mqtt.Options{InlineClient: true}) - if err := server.AddHook(new(auth.AllowHook), nil); err != nil { + if err := server.AddHook(new(mqttauth.AllowHook), nil); err != nil { return nil, nil, "", err } hook := &meshtasticFilterHook{ @@ -389,14 +397,14 @@ func startMQTTServer(cfg *config, store *store, dbQueue *dbWriteQueue, stats *me stats: stats, blocking: blocking, settings: settings, - pkiResolver: newPKIKeyResolver(store), + pkiResolver: botpkg.NewPKIKeyResolver(store), } if err := server.AddHook(hook, nil); err != nil { return nil, nil, "", err } addr := net.JoinHostPort(cfg.MQTT.Host, strconv.Itoa(cfg.MQTT.Port)) - tlsConfig, err := buildTLSConfig(cfg.MQTT.TLS) + tlsConfig, err := configpkg.BuildTLS(cfg.MQTT.TLS) if err != nil { return nil, nil, "", err } diff --git a/main_test.go b/main_test.go index 6494360..544f329 100644 --- a/main_test.go +++ b/main_test.go @@ -4,11 +4,15 @@ import ( "testing" mqtt "github.com/mochi-mqtt/server/v2" + + blockingpkg "meshtastic_mqtt_server/internal/blocking" + storepkg "meshtastic_mqtt_server/internal/store" + "meshtastic_mqtt_server/internal/store/testutil" ) func TestMQTTClientInfoFromClientNil(t *testing.T) { info := mqttClientInfoFromClient(nil) - if info != (mqttClientInfo{}) { + if info != (storepkg.MQTTClientInfo{}) { t.Fatalf("info = %#v, want zero value", info) } } @@ -42,20 +46,19 @@ func TestMQTTClientInfoFromClientUnsplitRemote(t *testing.T) { } } -// 注:blockingViolationForRecord 的测试现在跟着 blockingCache 一起搬到了 -// internal/blocking/violations_test.go,使用真实 *Store 构造缓存而不是 -// 直接捏造未导出字段。这里保留 mqtt client info 这部分测试不动。 +// blockingViolationForRecord 的测试用真实 *Store + blocking.Cache 走完整路径, +// 不依赖 cache 的未导出字段。 func TestBlockingViolationForRecordNode(t *testing.T) { - st := openTestStore(t) + st := testutil.OpenStore(t) defer st.Close() nodeNum := int64(305419896) if _, err := st.CreateNodeBlocking("!12345678", &nodeNum, "blocked", true); err != nil { t.Fatalf("CreateNodeBlocking() error = %v", err) } - cache, err := newBlockingCache(st) + cache, err := blockingpkg.New(st) if err != nil { - t.Fatalf("newBlockingCache() error = %v", err) + t.Fatalf("blocking.New() error = %v", err) } record := map[string]any{"type": "position", "from": "!12345678", "from_num": uint32(305419896)} violation := blockingViolationForRecord(cache, record) @@ -65,14 +68,14 @@ func TestBlockingViolationForRecordNode(t *testing.T) { } func TestBlockingViolationForRecordForbiddenWordFields(t *testing.T) { - st := openTestStore(t) + st := testutil.OpenStore(t) defer st.Close() if _, err := st.CreateForbiddenWordBlocking("spam", "contains", false, "blocked", true); err != nil { t.Fatalf("CreateForbiddenWordBlocking() error = %v", err) } - cache, err := newBlockingCache(st) + cache, err := blockingpkg.New(st) if err != nil { - t.Fatalf("newBlockingCache() error = %v", err) + t.Fatalf("blocking.New() error = %v", err) } for _, tc := range []struct { @@ -94,14 +97,14 @@ func TestBlockingViolationForRecordForbiddenWordFields(t *testing.T) { } func TestBlockingViolationForRecordAllowed(t *testing.T) { - st := openTestStore(t) + st := testutil.OpenStore(t) defer st.Close() if _, err := st.CreateForbiddenWordBlocking("spam", "contains", false, "blocked", true); err != nil { t.Fatalf("CreateForbiddenWordBlocking() error = %v", err) } - cache, err := newBlockingCache(st) + cache, err := blockingpkg.New(st) if err != nil { - t.Fatalf("newBlockingCache() error = %v", err) + t.Fatalf("blocking.New() error = %v", err) } record := map[string]any{"type": "text_message", "from": "!1", "text": "hello"} if violation := blockingViolationForRecord(cache, record); violation != nil { diff --git a/mapsource_bridge.go b/mapsource_bridge.go deleted file mode 100644 index 772e6ad..0000000 --- a/mapsource_bridge.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// 桥接到 internal/mapsource — 让 web.go 中的 registerMapSourceRoutes / -// registerAdminMapSourceRoutes 旧名字仍可用。 - -import ( - "github.com/gin-gonic/gin" - - mspkg "meshtastic_mqtt_server/internal/mapsource" -) - -func registerMapSourceRoutes(r gin.IRouter, s *store) { mspkg.RegisterPublicRoutes(r, s) } -func registerAdminMapSourceRoutes(r gin.IRouter, s *store) { mspkg.RegisterAdminRoutes(r, s) } diff --git a/mqttforward_bridge.go b/mqttforward_bridge.go deleted file mode 100644 index ea103b7..0000000 --- a/mqttforward_bridge.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -// 桥接到 internal/mqttforward — 让 main.go / web.go / mqtt_status.go 中 -// 使用 mqttForwardManager / meshtasticMessageStats / mqttForwardReloader 等 -// 旧名字的代码仍可工作。 - -import ( - "github.com/gin-gonic/gin" - - mfpkg "meshtastic_mqtt_server/internal/mqttforward" -) - -type ( - mqttForwardManager = mfpkg.Manager - mqttForwardReloader = mfpkg.Reloader - mqttForwardRuntimeStatus = mfpkg.RuntimeStatus - meshtasticMessageStats = mfpkg.Stats -) - -func newMQTTForwardManager(s *store) *mqttForwardManager { - return mfpkg.NewManager(s) -} - -func registerAdminMQTTForwardRoutes(r gin.IRouter, s *store, forwarder mqttForwardReloader) { - mfpkg.RegisterRoutes(r, s, forwarder) -} diff --git a/runtime_settings_bridge.go b/runtime_settings_bridge.go deleted file mode 100644 index 87ed6b8..0000000 --- a/runtime_settings_bridge.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -// 桥接到 internal/runtimesettings — 让根目录代码继续使用旧的小写名字。 - -import ( - "github.com/gin-gonic/gin" - - rspkg "meshtastic_mqtt_server/internal/runtimesettings" -) - -type runtimeSettingsCache = rspkg.Cache - -func newRuntimeSettingsCache(s *store) (*runtimeSettingsCache, error) { - return rspkg.New(s) -} - -func registerAdminRuntimeSettingsRoutes(r gin.IRouter, s *store, c *runtimeSettingsCache) { - rspkg.RegisterRoutes(r, s, c) -} diff --git a/sign_bridge.go b/sign_bridge.go deleted file mode 100644 index 1a13ecb..0000000 --- a/sign_bridge.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -// 桥接到 internal/sign — 让 web.go 中 registerAdminSignRoutes / signDTO / -// signDayCountDTO 旧名字仍可用。 - -import ( - "github.com/gin-gonic/gin" - - signpkg "meshtastic_mqtt_server/internal/sign" -) - -func registerAdminSignRoutes(r gin.IRouter, s *store) { - signpkg.RegisterAdminRoutes(r, s) -} - -func signDTO(row signRecord) gin.H { return signpkg.SignDTO(row) } -func signDayCountDTO(row signDayCount) gin.H { return signpkg.SignDayCountDTO(row) } diff --git a/store_bridge.go b/store_bridge.go deleted file mode 100644 index 967893b..0000000 --- a/store_bridge.go +++ /dev/null @@ -1,145 +0,0 @@ -package main - -// 桥接到 internal/store —— 让根目录其余文件无须修改即可继续使用旧的小写类型/函数名。 -// 当各领域包逐步迁出根目录后,可以删除这些别名。 - -import ( - storepkg "meshtastic_mqtt_server/internal/store" -) - -// ---- 类型别名 ---- - -type ( - store = storepkg.Store - mqttClientInfo = storepkg.MQTTClientInfo - dbWriteQueue = storepkg.WriteQueue - listOptions = storepkg.ListOptions - mapReportViewportOptions = storepkg.MapReportViewportOptions - mapReportViewportResult = storepkg.MapReportViewportResult - mapReportClusterRecord = storepkg.MapReportClusterRecord - userRecord = storepkg.UserRecord - loginLogRecord = storepkg.LoginLogRecord - helpContentRecord = storepkg.HelpContentRecord - runtimeSettingRecord = storepkg.RuntimeSettingRecord - mapTileSourceRecord = storepkg.MapTileSourceRecord - mapTileSourceInput = storepkg.MapTileSourceInput - discardDetailsRecord = storepkg.DiscardDetailsRecord - signRecord = storepkg.SignRecord - nodeBlockingRecord = storepkg.NodeBlockingRecord - ipBlockingRecord = storepkg.IPBlockingRecord - forbiddenWordBlockingRecord = storepkg.ForbiddenWordBlockingRecord - mqttForwarderRecord = storepkg.MQTTForwarderRecord - mqttForwarderInput = storepkg.MQTTForwarderInput - mqttForwardTopicRecord = storepkg.MQTTForwardTopicRecord - mqttForwardTopicInput = storepkg.MQTTForwardTopicInput - botNodeRecord = storepkg.BotNodeRecord - botNodeInput = storepkg.BotNodeInput - botMessageRecord = storepkg.BotMessageRecord - botDirectMessageRecord = storepkg.BotDirectMessageRecord - llmMessageQueueRecord = storepkg.LLMMessageQueueRecord - nodeInfoRecord = storepkg.NodeInfoRecord - mapReportRecord = storepkg.MapReportRecord - textMessageRecord = storepkg.TextMessageRecord - llmProviderRecord = storepkg.LLMProviderRecord - llmToolRouterRecord = storepkg.LLMToolRouterRecord - llmPrimaryConfigRecord = storepkg.LLMPrimaryConfigRecord - positionRecord = storepkg.PositionRecord - telemetryRecord = storepkg.TelemetryRecord - routingRecord = storepkg.RoutingRecord - tracerouteRecord = storepkg.TracerouteRecord -) - -// AppendPacketFields / MQTTClientRecordFields 已经是导出名,不需要别名。 -// 直接用包限定名供 root 文件调用: -type ( - AppendPacketFields = storepkg.AppendPacketFields - MQTTClientRecordFields = storepkg.MQTTClientRecordFields -) - -// 其它额外导出类型的别名(旧的小写形式仍被根目录文件直接使用)。 -type ( - runtimeSettingsSnapshot = storepkg.RuntimeSettingsSnapshot - mqttForwarderConfig = storepkg.MQTTForwarderConfig - botDirectMessageListOptions = storepkg.BotDirectMessageListOptions - botMessageListOptions = storepkg.BotMessageListOptions - botDirectConversation = storepkg.BotDirectConversation - signDayCount = storepkg.SignDayCount -) - -var errBlockingAlreadyExists = storepkg.ErrBlockingAlreadyExists -var errBotNodeAlreadyExists = storepkg.ErrBotNodeAlreadyExists -var ( - errMapTileSourceAlreadyExists = storepkg.ErrMapTileSourceAlreadyExists - errMapTileSourceCannotDeleteDefault = storepkg.ErrMapTileSourceCannotDeleteDefault - errMapTileSourceCannotDisableDefault = storepkg.ErrMapTileSourceCannotDisableDefault - errMapTileSourceDefaultMustBeEnabled = storepkg.ErrMapTileSourceDefaultMustBeEnabled -) - -func mapTileSourceHash(urlTemplate string) string { - return storepkg.MapTileSourceHash(urlTemplate) -} - -const ( - forbiddenWordMatchContains = storepkg.ForbiddenWordMatchContains - runtimeSettingAllowEncryptedForwarding = storepkg.RuntimeSettingAllowEncryptedForwarding - runtimeSettingLLMQueueEnabled = storepkg.RuntimeSettingLLMQueueEnabled - runtimeSettingLLMQueueIncludeChannel = storepkg.RuntimeSettingLLMQueueIncludeChannel - - botDefaultPSK = storepkg.BotDefaultPSK - botMessageTypeChannel = storepkg.BotMessageTypeChannel - botMessageTypeDirect = storepkg.BotMessageTypeDirect - botMessageStatusPending = storepkg.BotMessageStatusPending - botMessageStatusPublished = storepkg.BotMessageStatusPublished - botMessageStatusFailed = storepkg.BotMessageStatusFailed - botDirectMessageDirectionInbound = storepkg.BotDirectMessageDirectionInbound - botDirectMessageDirectionOutbound = storepkg.BotDirectMessageDirectionOutbound - botDefaultTopicPrefix = storepkg.BotDefaultTopicPrefix - - mqttForwardDirectionSourceToTarget = storepkg.MQTTForwardDirectionSourceToTarget - mqttForwardDirectionBidirectional = storepkg.MQTTForwardDirectionBidirectional -) - -const botDefaultNodeInfoBroadcastSeconds = storepkg.BotDefaultNodeInfoBroadcastSeconds - -func validateBotNodeNum(n int64) error { return storepkg.ValidateBotNodeNum(n) } - -var errUserAlreadyExists = storepkg.ErrUserAlreadyExists - -var ( - errMQTTForwarderAlreadyExists = storepkg.ErrMQTTForwarderAlreadyExists - errMQTTForwardTopicAlreadyExists = storepkg.ErrMQTTForwardTopicAlreadyExists -) - -func nullableString(v any) *string { return storepkg.NullableString(v) } -func nullableStringValue(v any) *string { return storepkg.NullableStringValue(v) } -func decodeBotPublicKey(row botNodeRecord) ([]byte, error) { - return storepkg.DecodeBotPublicKey(row) -} - -// LLM 消息队列状态字符串常量。 -const ( - llmMessageStatusPending = storepkg.LLMMessageStatusPending - llmMessageStatusProcessing = storepkg.LLMMessageStatusProcessing - llmMessageStatusProcessed = storepkg.LLMMessageStatusProcessed - llmMessageStatusError = storepkg.LLMMessageStatusError -) - -const defaultHelpMarkdown = storepkg.DefaultHelpMarkdown - -// 旧名 llmMessageDTO 现在通过 store 提供。 -func llmMessageDTO(row llmMessageQueueRecord) map[string]any { - return storepkg.LLMMessageDTO(row) -} - -// ---- 工厂函数包装 ---- - -func openStore(cfg databaseConfig) (*store, error) { return storepkg.OpenStore(cfg) } -func normalizeListOptions(o listOptions) listOptions { - return storepkg.NormalizeListOptions(o) -} -func normalizeMapReportViewportOptions(o mapReportViewportOptions) mapReportViewportOptions { - return storepkg.NormalizeMapReportViewportOptions(o) -} - -// newDBWriteQueue 在新包里更名,提供旧名字避免改 main.go。 -func newDBWriteQueue(s *store) *dbWriteQueue { return storepkg.NewWriteQueue(s) } diff --git a/test_helpers_test.go b/test_helpers_test.go deleted file mode 100644 index 24a28bc..0000000 --- a/test_helpers_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "path/filepath" - "testing" - - storepkg "meshtastic_mqtt_server/internal/store" -) - -// openTestStore 在根目录的测试中沿用旧函数名,但底层调用 internal/store 的实现。 -func openTestStore(t *testing.T) *store { - t.Helper() - st, err := storepkg.OpenStore(databaseConfig{ - Driver: databaseDriverSQLite, - SQLite: sqliteConfig{Path: filepath.Join(t.TempDir(), "mesh_mqtt_go.db")}, - }) - if err != nil { - t.Fatalf("OpenStore() error = %v", err) - } - return st -} diff --git a/web_bridge.go b/web_bridge.go deleted file mode 100644 index ddd57f0..0000000 --- a/web_bridge.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -// 桥接到 internal/web — 让 main.go 中使用 newSessionManager / newRouter / -// mqttRuntimeStatus / serveHTTPUnixSocket 这些旧名字的代码继续编译。 - -import ( - "net/http" - - "github.com/gin-gonic/gin" - mqtt "github.com/mochi-mqtt/server/v2" - - "meshtastic_mqtt_server/internal/auth" - mqttforwardpkg "meshtastic_mqtt_server/internal/mqttforward" - storepkg "meshtastic_mqtt_server/internal/store" - webpkg "meshtastic_mqtt_server/internal/web" -) - -// 旧类型/旧函数名 → 新位置的别名。 - -type mqttRuntimeStatusInternal = webpkg.MQTTRuntimeStatus - -// mqttRuntimeStatus 旧名字保持小写、字段也是小写——这里用一个适配类型把 -// main 包的旧字段写法包到 web 包导出的大写字段上。 -type mqttRuntimeStatus struct { - server *mqtt.Server - address string - tls bool - stats *meshtasticMessageStats - dbQueue *dbWriteQueue -} - -// 让 mqttRuntimeStatus 自动实现 webpkg.MQTTStatusProvider,把请求转给真正的实现。 -func (m mqttRuntimeStatus) Status() webpkg.AdminMQTTStatus { - return webpkg.MQTTRuntimeStatus{ - Server: m.server, - Address: m.address, - TLS: m.tls, - Stats: m.stats, - DBQueue: m.dbQueue, - }.Status() -} - -// 让旧代码里 `mqttforwardpkg.Stats` 别名留作 main 包内可见。 -var _ *mqttforwardpkg.Stats = (*meshtasticMessageStats)(nil) - -func newSessionManager(cfg webAdminConfig) (*auth.Manager, error) { - return auth.NewManager(cfg) -} - -func newRouter(cfg webConfig, store *storepkg.Store, sessions *auth.Manager, mqttStatus webpkg.MQTTStatusProvider, blocking *blockingCache, forwarder mqttForwardReloader, settings *runtimeSettingsCache, botSender botTextSender) *gin.Engine { - return webpkg.NewRouter(cfg, store, sessions, mqttStatus, blocking, forwarder, settings, botSender) -} - -func serveHTTPUnixSocket(server *http.Server, socketPath string) error { - return webpkg.ServeUnixSocket(server, socketPath) -}