package handler import ( "github.com/gofiber/fiber/v3" "github.com/jmoiron/sqlx" "github.com/peterqiu0516/sub-store/internal/config" "github.com/peterqiu0516/sub-store/internal/database" "github.com/peterqiu0516/sub-store/internal/middleware" ) // Deps holds all shared dependencies for handlers. type Deps struct { Cfg *config.Config DB *sqlx.DB SourceRepo *database.SourceRepo CollectionRepo *database.CollectionRepo TemplateRepo *database.TemplateRepo SettingsRepo *database.SettingsRepo RecycleRepo *database.RecycleRepo CacheRepo *database.CacheRepo } func NewDeps(cfg *config.Config, db *sqlx.DB) *Deps { return &Deps{ Cfg: cfg, DB: db, SourceRepo: database.NewSourceRepo(db), CollectionRepo: database.NewCollectionRepo(db), TemplateRepo: database.NewTemplateRepo(db), SettingsRepo: database.NewSettingsRepo(db), RecycleRepo: database.NewRecycleRepo(db), CacheRepo: database.NewCacheRepo(db), } } // RegisterRoutes wires all routes and returns the Deps used, so callers // (e.g. server startup) can launch background jobs on the same dependencies. func RegisterRoutes(app *fiber.App, cfg *config.Config, db *sqlx.DB) *Deps { deps := NewDeps(cfg, db) // Admin API group — requires admin token api := app.Group("/api", middleware.RequireAdmin(cfg.Auth.AdminToken), middleware.BodyLimit(cfg.Server.BodyLimit), ) // Basic API api.Get("/env", deps.HandleEnv) api.Get("/scripts", deps.HandleScripts) api.Get("/settings", deps.HandleGetSettings) api.Patch("/settings", deps.HandleUpdateSettings) api.Get("/storage", deps.HandleExportStorage) api.Post("/storage", deps.HandleImportStorage) // Source CRUD api.Get("/sources", deps.HandleListSources) api.Post("/sources", deps.HandleCreateSource) api.Put("/sources", deps.HandleSortSources) api.Post("/sort/sources", deps.HandleSortSourcesLegacy) api.Get("/sources/:name", deps.HandleGetSource) api.Patch("/sources/:name", deps.HandleUpdateSource) api.Delete("/sources/:name", deps.HandleDeleteSource) // Collection CRUD api.Get("/collections", deps.HandleListCollections) api.Post("/collections", deps.HandleCreateCollection) api.Put("/collections", deps.HandleSortCollections) api.Post("/sort/collections", deps.HandleSortCollectionsLegacy) api.Get("/collections/:name", deps.HandleGetCollection) api.Patch("/collections/:name", deps.HandleUpdateCollection) api.Delete("/collections/:name", deps.HandleDeleteCollection) // Template CRUD api.Get("/templates", deps.HandleListTemplates) api.Post("/templates", deps.HandleCreateTemplate) api.Get("/templates/:name", deps.HandleGetTemplate) api.Patch("/templates/:name", deps.HandleUpdateTemplate) api.Delete("/templates/:name", deps.HandleDeleteTemplate) // Recycle bin api.Get("/recycle-bin", deps.HandleListRecycleBin) api.Delete("/recycle-bin/:id", deps.HandleDeleteRecycleBinEntry) api.Post("/recycle-bin/:id/restore", deps.HandleRestoreRecycleBinEntry) // Preview api.Post("/preview/source", deps.HandlePreviewSource) api.Post("/preview/collection", deps.HandlePreviewCollection) // Download links api.Get("/link/source/:name", deps.HandleLinkSource) api.Get("/link/collection/:name", deps.HandleLinkCollection) // Flow info api.Get("/source/flow/:name", deps.HandleFlowInfo) // Tool APIs api.Post("/proxy/parse", deps.HandleProxyParse) api.Post("/rule/parse", deps.HandleRuleParse) api.Post("/utils/proxy-uri", deps.HandleProxyURI) api.Post("/utils/node-info", deps.HandleNodeInfo) api.Post("/utils/egress-info", deps.HandleEgressInfo) // Public download routes — no admin token required, uses download token app.Get("/sources/:name/:token", deps.HandleDownloadSource) app.Get("/collections/:name/:token", deps.HandleDownloadCollection) return deps } // success sends a success JSON response. func success(c fiber.Ctx, data any) error { return c.JSON(fiber.Map{"status": "success", "data": data}) } // failed sends a failed JSON response. func failed(c fiber.Ctx, message string, code int) error { return c.Status(code).JSON(fiber.Map{ "status": "failed", "error": fiber.Map{"code": code, "message": message}, }) }