package httpx import ( "net/http" "github.com/gin-gonic/gin" "spark-server/internal/pkg/errs" "spark-server/internal/pkg/i18n" "spark-server/internal/pkg/reply" "spark-server/internal/pkg/reqctx" authhandler "spark-server/internal/transport/http/handler/auth" convhandler "spark-server/internal/transport/http/handler/conversation" favhandler "spark-server/internal/transport/http/handler/favorite" filehandler "spark-server/internal/transport/http/handler/file" friendhandler "spark-server/internal/transport/http/handler/friend" grouphandler "spark-server/internal/transport/http/handler/group" msghandler "spark-server/internal/transport/http/handler/message" metahandler "spark-server/internal/transport/http/handler/meta" momenthandler "spark-server/internal/transport/http/handler/moment" musichandler "spark-server/internal/transport/http/handler/music" smshandler "spark-server/internal/transport/http/handler/sms" squarehandler "spark-server/internal/transport/http/handler/square" userhandler "spark-server/internal/transport/http/handler/user" "spark-server/internal/transport/http/respond" ) func registerRoutes(r *gin.Engine, deps *EngineDeps) { registerDocs(r) registerHealth(r, deps.Health) registerAdminRoutes(r, deps) v1 := r.Group("/v1") registerMetaRoutes(v1) registerAuthRoutes(v1, deps) registerSMSRoutes(v1, deps) registerUserRoutes(v1, deps) registerFriendRoutes(v1, deps) registerGroupRoutes(v1, deps) registerFileRoutes(v1, deps) registerFavoriteRoutes(v1, deps) registerMomentRoutes(v1, deps) registerSquareRoutes(v1, deps) registerMusicRoutes(v1, deps) registerConversationRoutes(v1, deps) registerMessageRoutes(v1, deps) } func registerHealth(r *gin.Engine, h Health) { r.GET("/healthz", func(c *gin.Context) { JSON(c, gin.H{"status": "ok"}) }) r.GET("/readyz", func(c *gin.Context) { if h == nil { JSON(c, gin.H{"status": "ok", "ready": true}) return } ok, data := h.Ready(c.Request.Context()) if ok { JSON(c, data) return } lang := reqctx.Lang(c.Request.Context()) c.JSON(http.StatusServiceUnavailable, reply.Stamp(c.Request.Context(), reply.FailData( errs.ErrAvailable.Code, i18n.ErrorMsg(lang, errs.ErrAvailable.Code), data, ))) }) } func registerMetaRoutes(v1 *gin.RouterGroup) { h := metahandler.New() v1.GET("/meta/enums", h.Enums) } func registerAuthRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { g := v1.Group("/auth") if deps.Login == nil { return } h := authhandler.New(deps.Login) g.POST("/login", h.Login) g.POST("/token/refresh", h.Refresh) g.POST("/logout", h.Logout) } func registerSMSRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.SMS == nil { return } h := smshandler.New(deps.SMS) g := v1.Group("/sms") g.POST("/codes", h.SendCode) } func registerUserRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Users == nil { return } h := userhandler.New(deps.Users) g := v1.Group("/users") g.GET("/me", h.Me) g.PATCH("/me", h.PatchMe) g.DELETE("/me", h.DeleteMe) } func registerFriendRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Friends == nil { return } h := friendhandler.New(deps.Friends) g := v1.Group("/friends") g.GET("/lookup", h.Lookup) g.GET("/requests", h.ListRequests) g.POST("/requests", h.Apply) g.GET("", h.List) g.POST("", h.Accept) g.GET("/:uid", h.Get) g.DELETE("/:uid", h.Delete) g.PUT("/:uid/remark", h.Remark) g.PUT("/:uid/pin", h.Pin) g.DELETE("/:uid/pin", h.Unpin) g.PUT("/:uid/block", h.Block) g.DELETE("/:uid/block", h.Unblock) g.POST("/:uid/reports", h.Report) } func registerGroupRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Groups == nil { return } h := grouphandler.New(deps.Groups) g := v1.Group("/groups") g.POST("", h.Create) g.GET("", h.List) g.GET("/:id/members", h.ListMembers) g.POST("/:id/members", h.Invite) g.PATCH("/:id/members/:uid", h.UpdateMember) g.DELETE("/:id/members/:uid", h.RemoveMember) g.POST("/:id/transfer", h.Transfer) g.GET("/:id", h.Get) g.PATCH("/:id", h.Update) g.DELETE("/:id", h.Dissolve) } func registerFileRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Files == nil { return } h := filehandler.New(deps.Files) g := v1.Group("/files") g.POST("", h.Create) g.POST("/batch", h.CreateBatch) g.POST("/downloads", h.Download) g.POST("/downloads/batch", h.DownloadBatch) } func registerFavoriteRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Favorites == nil { return } h := favhandler.New(deps.Favorites) g := v1.Group("/favorites") g.GET("", h.List) g.POST("", h.Create) g.DELETE("/:id", h.Delete) } func registerMomentRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Moments == nil { return } h := momenthandler.New(deps.Moments) g := v1.Group("/moments") g.GET("", h.Feed) g.POST("", h.Publish) g.GET("/unread", h.Unread) g.PUT("/read", h.Read) g.GET("/notices", h.ListNotices) g.POST("/notices/read", h.ReadNotices) g.GET("/settings", h.GetSettings) g.PATCH("/settings", h.PatchSettings) g.PUT("/settings/hides/:uid", h.PutHide) g.DELETE("/settings/hides/:uid", h.DeleteHide) g.GET("/users/:uid", h.Album) g.GET("/:id", h.Get) g.DELETE("/:id", h.Delete) g.PUT("/:id/like", h.Like) g.DELETE("/:id/like", h.Unlike) g.POST("/:id/comments", h.CreateComment) g.DELETE("/:id/comments/:cid", h.DeleteComment) } func registerSquareRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Square == nil { return } h := squarehandler.New(deps.Square) g := v1.Group("/square") g.GET("/posts", h.Feed) g.POST("/posts", h.Publish) g.GET("/posts/:id", h.Get) g.DELETE("/posts/:id", h.Delete) g.PUT("/posts/:id/like", h.Like) g.DELETE("/posts/:id/like", h.Unlike) g.POST("/posts/:id/comments", h.CreateComment) g.DELETE("/posts/:id/comments/:cid", h.DeleteComment) g.GET("/users/:uid/posts", h.UserPosts) g.GET("/notices", h.ListNotices) g.GET("/notices/unread", h.NoticeUnread) g.POST("/notices/read", h.ReadNotices) } func registerMusicRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Music == nil { return } h := musichandler.New(deps.Music) g := v1.Group("/music") // 客户端可读:无需登录(列表为运营配置的公开曲目元数据) g.GET("/playlist", h.Playlist) g.GET("/categories", h.Categories) g.GET("/settings", h.Settings) } func registerConversationRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Sync == nil { return } h := convhandler.New(deps.Sync) g := v1.Group("/conversations") g.GET("", h.Inbox) } func registerMessageRoutes(v1 *gin.RouterGroup, deps *EngineDeps) { if deps.Messages == nil { return } h := msghandler.New(deps.Messages) g := v1.Group("/messages") g.GET("", h.History) g.POST("", h.Send) g.POST("/:id/recall", h.Recall) g.DELETE("/:id", h.Delete) } func JSON(c *gin.Context, data any) { respond.JSON(c, data) } func JSONError(c *gin.Context, err error) { respond.JSONError(c, err) } func BindJSON(c *gin.Context, dst any) error { return respond.BindJSON(c, dst) }