264 lines
8.1 KiB
Go
264 lines
8.1 KiB
Go
package router
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/common"
|
|
"chatapp3-golang/internal/service/smashegg"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// registerSmashEggRoutes registers app, legacy H5, and admin smash egg APIs.
|
|
func registerSmashEggRoutes(engine *gin.Engine, javaClient authGateway, service *smashegg.Service) {
|
|
if service == nil {
|
|
return
|
|
}
|
|
|
|
appGroup := engine.Group("/app/smash-golden-egg")
|
|
appGroup.Use(authMiddleware(javaClient))
|
|
appGroup.GET("/config", func(c *gin.Context) {
|
|
resp, err := service.GetAppConfig(c.Request.Context(), mustAuthUser(c))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
appGroup.POST("/draw", func(c *gin.Context) {
|
|
var req smashegg.DrawRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
writeError(c, smashegg.NewAppError(http.StatusBadRequest, "bad_request", err.Error()))
|
|
return
|
|
}
|
|
req.IdempotencyKey = requestIdempotencyKey(c, req.IdempotencyKey)
|
|
resp, err := service.Draw(c.Request.Context(), mustAuthUser(c), req)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
appGroup.GET("/records", func(c *gin.Context) {
|
|
cursor, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("cursor", "1")))
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "20")))
|
|
resp, err := service.PageUserRecords(c.Request.Context(), mustAuthUser(c), cursor, limit)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
appGroup.GET("/notices", func(c *gin.Context) {
|
|
resp, err := service.ListRecentNotices(c.Request.Context(), mustAuthUser(c).SysOrigin, 20)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
appGroup.GET("/rank/day", func(c *gin.Context) {
|
|
cursor, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("cursor", "1")))
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "100")))
|
|
resp, err := service.PageDayRank(c.Request.Context(), mustAuthUser(c).SysOrigin, cursor, limit)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
|
|
adminGroup := engine.Group("/resident-activity/smash-golden-egg")
|
|
adminGroup.Use(consoleAuthMiddleware(javaClient))
|
|
adminGroup.GET("/config", func(c *gin.Context) {
|
|
resp, err := service.GetConfig(c.Request.Context(), c.Query("sysOrigin"))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
adminGroup.POST("/config/save", func(c *gin.Context) {
|
|
var req smashegg.SaveConfigRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
writeError(c, smashegg.NewAppError(http.StatusBadRequest, "bad_request", err.Error()))
|
|
return
|
|
}
|
|
resp, err := service.SaveConfig(c.Request.Context(), req)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
adminGroup.GET("/draw-record/page", func(c *gin.Context) {
|
|
cursor, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("cursor", "1")))
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "20")))
|
|
resp, err := service.PageAdminRecords(
|
|
c.Request.Context(),
|
|
c.Query("sysOrigin"),
|
|
smashegg.ParseUserID(c.Query("userId")),
|
|
c.Query("status"),
|
|
cursor,
|
|
limit,
|
|
c.Query("startTime"),
|
|
c.Query("endTime"),
|
|
)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
|
|
h5Group := engine.Group("/h5/smash-golden-egg")
|
|
h5Group.Any("/config", func(c *gin.Context) {
|
|
handleLegacySmashEggAction(c, javaClient, service, "Action/TreasureHunt.getPrizeList")
|
|
})
|
|
h5Group.Any("/draw", func(c *gin.Context) {
|
|
handleLegacySmashEggAction(c, javaClient, service, "Action/TreasureHunt.startHunt")
|
|
})
|
|
h5Group.Any("/records", func(c *gin.Context) {
|
|
handleLegacySmashEggAction(c, javaClient, service, "Action/TreasureHunt.getMyHuntRecord")
|
|
})
|
|
h5Group.Any("/notices", func(c *gin.Context) {
|
|
handleLegacySmashEggAction(c, javaClient, service, "Action/TreasureHunt.getHuntRecord")
|
|
})
|
|
h5Group.Any("/rank/day", func(c *gin.Context) {
|
|
handleLegacySmashEggAction(c, javaClient, service, "Action/TreasureHunt.getDayRank")
|
|
})
|
|
|
|
engine.Any("/index.php", func(c *gin.Context) {
|
|
action := strings.TrimSpace(c.Query("action"))
|
|
if !strings.HasPrefix(action, "Action/TreasureHunt.") {
|
|
writeError(c, smashegg.NewAppError(http.StatusNotFound, "not_found", "legacy action is not supported"))
|
|
return
|
|
}
|
|
handleLegacySmashEggAction(c, javaClient, service, action)
|
|
})
|
|
}
|
|
|
|
func handleLegacySmashEggAction(c *gin.Context, javaClient authGateway, service *smashegg.Service, action string) {
|
|
user, err := legacySmashEggUser(c, javaClient)
|
|
if err != nil {
|
|
writeLegacyError(c, http.StatusUnauthorized, err.Error())
|
|
return
|
|
}
|
|
|
|
var resp map[string]any
|
|
switch action {
|
|
case "Action/TreasureHunt.getPrizeList":
|
|
resp, err = service.LegacyPrizeList(c.Request.Context(), user)
|
|
case "Action/TreasureHunt.startHunt":
|
|
times, _ := strconv.Atoi(strings.TrimSpace(firstNonEmptyQuery(c, "times", "num")))
|
|
if times <= 0 {
|
|
times = 1
|
|
}
|
|
resp, err = service.LegacyStartHunt(c.Request.Context(), user, times, requestIdempotencyKey(c, ""))
|
|
case "Action/TreasureHunt.getMyHuntRecord":
|
|
start, _ := strconv.Atoi(strings.TrimSpace(firstNonEmptyQuery(c, "offset", "start")))
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(firstNonEmptyQuery(c, "limit", "num")))
|
|
if limit <= 0 {
|
|
limit = 20
|
|
}
|
|
resp, err = service.LegacyMyHuntRecords(c.Request.Context(), user, start, limit)
|
|
case "Action/TreasureHunt.getHuntRecord":
|
|
resp, err = service.LegacyHuntNotices(c.Request.Context(), user.SysOrigin)
|
|
case "Action/TreasureHunt.getDayRank":
|
|
resp, err = service.LegacyDayRank(c.Request.Context(), user.SysOrigin)
|
|
default:
|
|
writeLegacyError(c, http.StatusNotFound, "legacy action is not supported")
|
|
return
|
|
}
|
|
if err != nil {
|
|
writeLegacyError(c, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
writeLegacyOK(c, resp)
|
|
}
|
|
|
|
func legacySmashEggUser(c *gin.Context, javaClient authGateway) (common.AuthUser, error) {
|
|
token := strings.TrimSpace(c.Query("token"))
|
|
if token == "" {
|
|
token = trimBearer(strings.TrimSpace(c.GetHeader("Authorization")))
|
|
}
|
|
if token != "" && javaClient != nil {
|
|
ctx, cancel := context.WithTimeout(c.Request.Context(), 10*time.Second)
|
|
defer cancel()
|
|
credential, err := javaClient.AuthenticateToken(ctx, token)
|
|
if err != nil {
|
|
return common.AuthUser{}, err
|
|
}
|
|
return common.AuthUser{
|
|
UserID: int64(credential.UserID),
|
|
SysOrigin: credential.SysOrigin,
|
|
Token: token,
|
|
}, nil
|
|
}
|
|
|
|
userID := smashegg.ParseUserID(firstNonEmptyQuery(c, "_login_uid", "uid", "userId"))
|
|
sysOrigin := strings.ToUpper(strings.TrimSpace(firstNonEmptyQuery(c, "sysOrigin", "originSys")))
|
|
if sysOrigin == "" {
|
|
sysOrigin = strings.ToUpper(strings.TrimSpace(c.GetHeader("req-sys-origin")))
|
|
}
|
|
if userID <= 0 || sysOrigin == "" {
|
|
return common.AuthUser{}, common.NewAppError(http.StatusUnauthorized, "missing_token", "token is required")
|
|
}
|
|
return common.AuthUser{UserID: userID, SysOrigin: sysOrigin, Token: token}, nil
|
|
}
|
|
|
|
func firstNonEmptyQuery(c *gin.Context, keys ...string) string {
|
|
for _, key := range keys {
|
|
if value := strings.TrimSpace(c.Query(key)); value != "" {
|
|
return value
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func requestIdempotencyKey(c *gin.Context, fallback string) string {
|
|
for _, value := range []string{
|
|
fallback,
|
|
c.GetHeader("Idempotency-Key"),
|
|
c.GetHeader("X-Idempotency-Key"),
|
|
firstNonEmptyQuery(c, "idempotencyKey", "idempotency_key", "requestId", "request_id", "nonce"),
|
|
strings.TrimSpace(c.PostForm("idempotencyKey")),
|
|
strings.TrimSpace(c.PostForm("idempotency_key")),
|
|
strings.TrimSpace(c.PostForm("requestId")),
|
|
strings.TrimSpace(c.PostForm("request_id")),
|
|
strings.TrimSpace(c.PostForm("nonce")),
|
|
} {
|
|
if strings.TrimSpace(value) != "" {
|
|
return strings.TrimSpace(value)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func writeLegacyOK(c *gin.Context, data any) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"response_data": data,
|
|
"response_status": gin.H{
|
|
"code": 0,
|
|
"error": "",
|
|
},
|
|
})
|
|
}
|
|
|
|
func writeLegacyError(c *gin.Context, code int, message string) {
|
|
if message == "" {
|
|
message = "error"
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"response_data": gin.H{},
|
|
"response_status": gin.H{
|
|
"code": code,
|
|
"error": message,
|
|
},
|
|
})
|
|
}
|