Files
huangguo_server/app/api/newactivityctrl/newactivity.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

297 lines
11 KiB
Go

package newactivityctrl
import (
"fmt"
"math/rand"
"net/http"
"strconv"
"time"
"91porn-server/app/appg"
"91porn-server/app/middleware/authuser"
"91porn-server/app/service/productser"
"91porn-server/common"
"91porn-server/common/log"
"91porn-server/common/stderr"
"91porn-server/common/synclock"
"91porn-server/common/timeutil"
"91porn-server/models/v/newactivity"
"91porn-server/models/v/walletmod"
"github.com/gin-gonic/gin"
)
// @Tags 特制H5活动
// @Summary 获取用户余额
// @Description 获取用户余额
// @Security ApiKeyAuth
// @Tags app-H5嫩模活动
// @Accept json
// @Produce json
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/newactivity/userBanlance [post]
func UserBalance(ctx *gin.Context) {
token := ctx.Request.Header.Get("X-Authorization") //为兼容H5带APP token
if token == "" {
ctx.AbortWithStatusJSON(http.StatusOK, stderr.ErrNoToken.Struct())
return
}
claims, err := authuser.ParseWebClaims(token)
if err != nil {
log.Error("activity UserBalance ParseWebClaims error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err))
ctx.JSON(http.StatusBadRequest, stderr.InvalidToken.Struct())
return
}
w, err := walletmod.GetWallet(claims.UID)
if err != nil {
ctx.JSON(http.StatusInternalServerError,
gin.H{"data": err.Error(),
"code": stderr.ErrServerUnavailable,
"msg": stderr.ErrServerUnavailable.Msg()})
return
}
ctx.JSON(int(stderr.Success), gin.H{"data": w.Amount + w.Income, "code": stderr.Success, "msg": stderr.Success.Msg()})
}
// @Tags 特制H5活动
// @Summary 获取所有嫩模list
// @Description 获取所有嫩模list
// @Security ApiKeyAuth
// @Tags app-H5嫩模活动
// @Accept json
// @Produce json
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/newactivity/modelList [post]
func ModelList(ctx *gin.Context) {
token := ctx.Request.Header.Get("X-Authorization") //为兼容H5带APP token
if token == "" {
ctx.AbortWithStatusJSON(http.StatusOK, stderr.ErrNoToken.Struct())
return
}
if _, err := authuser.ParseWebClaims(token); err != nil {
log.Error("activity ModelList ParseWebClaims error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err))
ctx.JSON(http.StatusBadRequest, stderr.InvalidToken.Struct())
return
}
rs, err := newactivity.ModelList()
if err != nil {
ctx.JSON(http.StatusInternalServerError,
gin.H{"data": err.Error(),
"code": stderr.ErrServerUnavailable,
"msg": stderr.ErrServerUnavailable.Msg()})
return
}
ctx.JSON(int(stderr.Success), gin.H{"data": rs, "code": stderr.Success, "msg": stderr.Success.Msg()})
}
// @Tags 特制H5活动
// @Summary 查询指定模特数据
// @Description 查询指定模特数据
// @Security ApiKeyAuth
// @Tags app-H5嫩模活动
// @Accept json
// @Produce json
// @Param modelId formData integer false "模特ID"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/newactivity/findOneModel [post]
func FindOneModel(ctx *gin.Context) {
token := ctx.Request.Header.Get("X-Authorization") //为兼容H5带APP token
if token == "" {
ctx.AbortWithStatusJSON(http.StatusOK, stderr.ErrNoToken.Struct())
return
}
if _, err := authuser.ParseWebClaims(token); err != nil {
log.Error("activity FindOneModel ParseWebClaims error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err))
ctx.JSON(http.StatusBadRequest, stderr.InvalidToken.Struct())
return
}
var req struct {
ModelId uint32 `json:"modelId"`
}
if err := ctx.ShouldBind(&req); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"data": err.Error(), "code": stderr.ErrParamError, "msg": stderr.ErrParamError.Msg()})
return
}
rs, err := newactivity.FindOne(req.ModelId)
if err != nil {
ctx.JSON(http.StatusInternalServerError,
gin.H{"data": err.Error(),
"code": stderr.ErrServerUnavailable,
"msg": stderr.ErrServerUnavailable.Msg()})
return
}
ctx.JSON(http.StatusOK, gin.H{"data": rs, "code": stderr.Success, "msg": stderr.Success.Msg()})
}
// @Tags 特制H5活动
// @Summary 购买礼物
// @Description 购买礼物
// @Security ApiKeyAuth
// @Tags app-H5嫩模活动
// @Accept json
// @Produce json
// @Param modelId formData integer false "模特id"
// @Param quantity formData integer false "礼物数目"
// @Param buyOut formData boolean false "是否买断"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/newactivity/buyGifts [post]
func BuyGifts(ctx *gin.Context) {
token := ctx.Request.Header.Get("X-Authorization") //为兼容H5带APP token
if token == "" {
ctx.AbortWithStatusJSON(http.StatusOK, stderr.ErrNoToken.Struct())
return
}
claims, err := authuser.ParseWebClaims(token)
if err != nil {
log.Error("activity BuyGifts ParseWebClaims error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err))
ctx.JSON(http.StatusBadRequest, stderr.InvalidToken.Struct())
return
}
var req newactivity.BuyReq
if err := ctx.ShouldBind(&req); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"data": err.Error(), "code": stderr.ErrParamError, "msg": stderr.ErrParamError.Msg()})
return
}
if req.Quantity <= 0 || req.Quantity > 300 || (req.BuyOut && req.Quantity != 300) {
ctx.JSON(http.StatusBadRequest, gin.H{"msg": "请重新指定礼物数目", "code": http.StatusBadRequest})
return
}
//上锁(用户账户锁)
lock := synclock.Lock{Lock: appg.Redis}
if _, err = lock.UserAccountSpinLock(uint32(claims.UID), synclock.SpinLockExpire); err != nil {
return
}
defer lock.UserAccountUnlock(uint32(claims.UID))
code := productser.BuyModel(claims.UID, req)
if code != stderr.Success {
ctx.JSON(http.StatusBadRequest, code.Struct())
return
}
ctx.JSON(http.StatusOK, code.Struct())
}
// @Tags 特制H5活动
// @Summary 购买礼物
// @Description 购买礼物
// @Security ApiKeyAuth
// @Tags app-H5嫩模活动
// @Accept json
// @Produce json
// @Param modelId formData integer false "模特id"
// @Param quantity formData integer false "礼物数目"
// @Param buyOut formData boolean false "是否买断"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/newactivity/buyGiftsSchedule [post]
func BuyGiftsSchedule(ctx *gin.Context) {
var req struct {
UIDs []uint64 `json:"uids" form:"uids"`
Token string `json:"token" form:"token" binding:"required"`
Active bool `json:"active" form:"active"`
NumPercent int `json:"numPercent" form:"numPercent"` //每次对于一个嫩模购买的份数
Interval int `json:"interval" form:"interval"` //时间间隔 以秒为单位
}
if err := ctx.ShouldBind(&req); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"data": err.Error(), "code": stderr.ErrParamError, "msg": stderr.ErrParamError.Msg()})
return
}
if req.Token != "iNrKZ7vIm98ImFYmOKxXytf1ANJiZGB2" {
ctx.AbortWithStatusJSON(http.StatusOK, stderr.ErrNoToken.Struct())
return
}
if req.NumPercent >= 300 {
ctx.JSON(http.StatusBadRequest, gin.H{"msg": "请重新指定礼物数目", "code": http.StatusBadRequest})
return
}
if req.Interval == 0 {
req.Interval = 4
}
if req.NumPercent == 0 {
req.NumPercent = 3
}
key := "NengModel-Schedule" + timeutil.BeginningOfDay(time.Now()).Format("YYYY-MM-DD")
active := strconv.FormatBool(req.Active)
//每次调用相当于就是一个任务
_, _ = appg.Redis.Del(key)
time.Sleep(2 * time.Second)
if err := appg.Redis.Set(key, active, 0); err != nil {
ctx.JSON(http.StatusOK, gin.H{"data": err.Error(), "code": stderr.ErrParamError, "msg": stderr.ErrParamError.Msg()})
return
}
common.Go(func() {
for {
result, err := appg.Redis.Get(key)
if err != nil || result == nil {
return
}
if *result == "false" {
return
}
buyReq := newactivity.BuyReq{
ModelId: uint32(rand.Intn(178) + 1),
Quantity: int32(rand.Intn(req.NumPercent) + 1),
BuyOut: false,
}
uid := req.UIDs[rand.Intn(len(req.UIDs)-1)]
//上锁(用户账户锁)
lock := synclock.Lock{Lock: appg.Redis}
if _, err = lock.UserAccountSpinLock(uint32(uid), synclock.SpinLockExpire); err != nil {
continue
}
defer lock.UserAccountUnlock(uint32(uid))
code := productser.BuyModelFakeUser(uid, buyReq)
log.Info("[METHOD-BuyGiftsSchedule] run fake buy model run ========>", log.Any("code", code), log.Any("uid", uid), log.Any("param", fmt.Sprintf("%+v", buyReq)))
}
})
if req.Active {
ctx.JSON(http.StatusOK, gin.H{"msg": "任务开始启动执行.....", "code": http.StatusOK})
return
}
ctx.JSON(http.StatusOK, gin.H{"msg": "结束任务.....", "code": http.StatusOK})
}
// @Tags 特制H5活动
// @Summary 获奖记录
// @Description 获奖记录
// @Security ApiKeyAuth
// @Tags app-H5嫩模活动
// @Accept json
// @Produce json
// @Param date formData string false "日期"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/newactivity/winRecords [post]
func WinRecords(ctx *gin.Context) {
token := ctx.Request.Header.Get("X-Authorization") //为兼容H5带APP token
if token == "" {
ctx.AbortWithStatusJSON(http.StatusOK, stderr.ErrNoToken.Struct())
return
}
if _, err := authuser.ParseWebClaims(token); err != nil {
log.Error("activity WinRecords ParseWebClaims error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err))
ctx.JSON(http.StatusBadRequest, stderr.InvalidToken.Struct())
return
}
var req struct {
Date time.Time `json:"date"`
}
if err := ctx.ShouldBind(&req); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"data": err.Error(), "code": stderr.ErrParamError, "msg": stderr.ErrParamError.Msg()})
return
}
rs, err := newactivity.WinRecordsByDate(req.Date)
if err != nil {
ctx.JSON(http.StatusInternalServerError,
gin.H{"data": err.Error(),
"code": stderr.ErrServerUnavailable,
"msg": stderr.ErrServerUnavailable.Msg()})
return
}
ctx.JSON(http.StatusOK, gin.H{"data": rs, "code": stderr.Success, "msg": stderr.Success.Msg()})
}