Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
@@ -0,0 +1,362 @@
package ai_undress_service
import (
"91porn-server/common"
"91porn-server/models/commod"
"91porn-server/models/v/aiplazamod"
"91porn-server/models/v/walletmod"
"fmt"
"strconv"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"91porn-server/common/db"
"91porn-server/common/httputil"
"91porn-server/common/log"
"91porn-server/common/stderr"
"91porn-server/models/v/aiUnDressmod"
"91porn-server/models/v/txnmod"
"91porn-server/web/webg"
)
func List(req *aiUnDressmod.WebListRequest) (interface{}, stderr.Code) {
var data = map[string]interface{}{
"list": []interface{}{},
"count": 0,
}
count, err := aiUnDressmod.CountDocument(req.Filter())
if err != nil {
return nil, stderr.ErrDbQueryError
}
if count == 0 {
return data, stderr.Success
}
list, err := aiUnDressmod.QueryAllDocument(req.Filter(), req.Options())
if err != nil {
return data, stderr.ErrDbQueryError
}
data["count"] = count
data["list"] = list
return data, stderr.Success
}
func Update(act string, req *aiUnDressmod.EditCond) stderr.Code {
// 获取Ai记录
data, err := aiUnDressmod.FindDataByID(req.ID)
if err != nil {
return stderr.ErrDbQueryError
}
if (*req.Status == aiUnDressmod.FAILURE || *req.Status == aiUnDressmod.REFUND) &&
(data.Status == aiUnDressmod.FAILURE || data.Status == aiUnDressmod.REFUND) {
return stderr.Success
}
// 根据状态判断
switch *req.Status {
case aiUnDressmod.Processing:
if data.Status != aiUnDressmod.SUCCESS && data.Status != aiUnDressmod.SubmitOrder {
return stderr.AiUnDressStatusIsErr
}
err = aiUnDressmod.Edit(nil, req.Filter(), req.Update(act))
if err != nil {
return stderr.ErrDbUpdateError
}
case aiUnDressmod.SUCCESS:
err = aiUnDressmod.Edit(nil, req.Filter(), req.Update(act))
if err != nil {
return stderr.ErrDbUpdateError
}
case aiUnDressmod.FAILURE, aiUnDressmod.REFUND:
// 失败处理 退金币
deAmt := -data.DebitAmountCoin
deIncome := -data.DebitIncomeCoin
uid := data.UID
oldVersion := false
err = webg.VideoDB.Trans(func(tool *db.MongoTool) error {
updateSet, _ := req.Update(act)["$set"].(bson.M)
transitioned, transitionErr := aiUnDressmod.TransitionStatus(tool, data.ID, data.Status, *req.Status, updateSet)
if transitionErr != nil {
return transitionErr
}
if !transitioned {
return nil
}
var tl []txnmod.TransactionLog
// 根据是否是免费次数退回
if data.Count > 0 || data.IsFreeTimes {
deCount := data.Count
if data.Count == 0 {
deCount = 1
}
// 加钱包余额
wallet, wErr := walletmod.DebitAiFreeTimes(tool, -deCount, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiUnDress Edit walletmod.DebitAiFreeTimes error:%+v:", wErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: deCount,
ActualAmount: float64(deCount),
TranType: txnmod.AiUndressDebitFreeTimesReturn.Key(),
TranTypeInt: int64(txnmod.AiUndressDebitFreeTimesReturn),
Desc: fmt.Sprintf("AI脱衣免费次数退返[%d次]", deCount),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if !data.IsFreeTimes && data.DebitAmountCoin == 0 && data.DebitIncomeCoin == 0 {
deAmt = -data.Coin
oldVersion = true
}
if data.DebitAmountCoin > 0 || data.DebitIncomeCoin > 0 || oldVersion {
// 加钱包余额
wallet, wErr := walletmod.ReturnAmountAndIncome(tool, deAmt, deIncome, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiUnDress Edit walletmod.DebitAmount error:%+v:", wErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
if data.DebitIncomeCoin > 0 {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deIncome,
ActualAmount: float64(-deIncome),
TranType: txnmod.AiUndressDebitIncomeGoldReturn.Key(),
TranTypeInt: int64(txnmod.AiUndressDebitIncomeGoldReturn),
Desc: fmt.Sprintf("AI脱衣收益金币退返-%d", -deIncome),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if data.DebitAmountCoin > 0 || oldVersion {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deAmt,
ActualAmount: float64(-deAmt),
TranType: txnmod.AiUndressDebitGoldReturn.Key(),
TranTypeInt: int64(txnmod.AiUndressDebitGoldReturn),
Desc: fmt.Sprintf("AI脱衣金币退返-%d", -deAmt),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
}
txnErr := txnmod.InsertManyTransactionLog(tool, tl)
if txnErr != nil {
log.Error(fmt.Sprintf("Handle AiUnDress Edit txnmod.InsertManyTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
return nil
})
if err != nil {
log.Error(fmt.Sprintf("Handle AiUnDress Edit Trans error:%+v;uid:%v;", err, uid))
return stderr.ErrDbUpdateError
}
}
return stderr.Success
}
// Auto 提交AI自动化服务
func Auto(act string, req *aiUnDressmod.AutoCond) stderr.Code {
// 获取Ai记录
data, err := aiUnDressmod.FindDataByID(req.ID)
if err != nil {
return stderr.ErrDbQueryError
}
if data.Status == aiUnDressmod.SubmitOrder {
return stderr.Success
}
//提交订单到第三方
notifyURL, notifyErr := webg.AICallbackURL("/api/web/admin/ai/undress/callback")
if notifyErr != nil {
log.Error("AI脱衣回调地址配置异常", log.E(notifyErr))
return stderr.Failure
}
httpReq := aiUnDressmod.AiUndressOrderReq{
AppId: int(commod.KFK_APPID),
FileUrl: data.OriginPics,
UserId: strconv.FormatUint(data.UID, 10),
AppOrderNum: data.ID.Hex(),
NotifyUrl: notifyURL,
}
var resp aiUnDressmod.AiUndressOrderResp
url := webg.Conf.URL.AiUndressServer + "/api/undress/prd/create_job"
codeJ, err := httputil.DefaultClientPostJsonWithResp(&resp, url, nil, httpReq)
if err != nil {
log.Error("CreateUnderss httputil.DefaultClientPostWithResp err", log.E(err))
return stderr.Failure
}
if codeJ != 200 {
log.Error("CreateUnderss req http code error", log.Any("code", codeJ))
return stderr.Failure
}
//更新ai脱衣订单状态
if err := aiUnDressmod.SubmitStatus(req.ID, aiUnDressmod.SubmitOrder, "已提交"); err != nil {
return stderr.ErrDbUpdateError
}
return stderr.Success
}
// CallBackOrder AI脱衣回调
func CallBackOrder(req *aiUnDressmod.CallBackReq) stderr.Code {
// 获取Ai记录
data, err := aiUnDressmod.FindDataByID(req.AppOrderNum)
if err != nil {
return stderr.ErrDbQueryError
}
if data.Status != aiUnDressmod.SubmitOrder {
log.Error("AI脱衣-重复回调或者状态不正确", log.Any("id", data.ID.Hex()), log.Any("status", data.Status))
return stderr.Success
}
var (
set = bson.M{"remark": req.Msg}
// 返还次数、返还金币、返还收益金币
refoundCount, deAmt, deIncome int64
// 订单状态
status int
oldVersion = false
successCount = len(req.ImgUrl)
uid = data.UID
_id = data.ID
isFreeTimes = false
)
if req.ImgUrl != nil && len(req.ImgUrl) > 0 {
set["newPic"] = req.ImgUrl
// 同步内存中的 data.NewPic,否则下方 goroutine 读取 data.NewPic[0] 会因未更新而越界 panic
data.NewPic = req.ImgUrl
}
if successCount > 0 { // 成功
status = aiUnDressmod.SUCCESS
refoundCount = 0
deAmt = 0
deIncome = 0
} else { // 失败
status = aiUnDressmod.REFUND
refoundCount = data.Count
// 失败处理 退金币
deAmt = -data.DebitAmountCoin
deIncome = -data.DebitIncomeCoin
isFreeTimes = data.IsFreeTimes
}
set["status"] = status
handled := false
if err := webg.VideoDB.Trans(func(tool *db.MongoTool) error {
transitioned, transitionErr := aiUnDressmod.TransitionStatus(tool, _id, aiUnDressmod.SubmitOrder, status, set)
if transitionErr != nil {
return transitionErr
}
if !transitioned {
return nil
}
handled = true
var tl []txnmod.TransactionLog
if refoundCount > 0 || isFreeTimes {
if refoundCount == 0 {
refoundCount = 1
}
// 加免费次数,负负为正
wallet, wErr := walletmod.DebitAiFreeTimes(tool, -refoundCount, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiUnDress CallBackOrder walletmod.DebitAiFreeTimes error:%+v:", wErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: refoundCount,
ActualAmount: float64(refoundCount),
TranType: txnmod.AiUndressDebitFreeTimesReturn.Key(),
TranTypeInt: int64(txnmod.AiUndressDebitFreeTimesReturn),
Desc: fmt.Sprintf("AI脱衣免费次数退返[%d次]", refoundCount),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if !data.IsFreeTimes && data.DebitAmountCoin == 0 && data.DebitIncomeCoin == 0 {
deAmt = -data.Coin
oldVersion = true
}
if deAmt < 0 || deIncome < 0 || oldVersion {
// 加钱包余额,负负为正
wallet, wErr := walletmod.ReturnAmountAndIncome(tool, deAmt, deIncome, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiUnDress CallBackOrder walletmod.DebitAmount error:%+v:", wErr), log.Any("uid", uid))
return stderr.ErrDbUpdateError
}
if data.DebitIncomeCoin > 0 {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deIncome,
ActualAmount: float64(-deIncome),
TranType: txnmod.AiUndressDebitIncomeGoldReturn.Key(),
TranTypeInt: int64(txnmod.AiUndressDebitIncomeGoldReturn),
Desc: fmt.Sprintf("AI脱衣收益金币退返-%d", -deIncome),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if data.DebitAmountCoin > 0 || oldVersion {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deAmt,
ActualAmount: float64(-deAmt),
TranType: txnmod.AiUndressDebitGoldReturn.Key(),
TranTypeInt: int64(txnmod.AiUndressDebitGoldReturn),
Desc: fmt.Sprintf("AI脱衣金币退返-%d", -deAmt),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
}
if len(tl) > 0 {
txnErr := txnmod.InsertManyTransactionLog(tool, tl)
if txnErr != nil {
log.Error(fmt.Sprintf("Handle AiUnDress CallBackOrder txnmod.InsertManyTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
}
return nil
}); err != nil {
log.Error(fmt.Sprintf("Handle AiUnDress CallBackOrder Trans error:%+v;uid:%v;", err, uid))
return stderr.ErrDbUpdateError
}
if !handled {
return stderr.Success
}
if successCount > 0 {
common.Go(func() {
if data.ShareStatus != 1 {
return
}
// 新增一个分享
alPlaza := aiplazamod.AiPlaza{
Type: 3,
OrderId: data.ID,
Template: "",
Uid: data.UID,
Title: data.ShareTitle,
OriginalImage: data.OriginPic,
OriginalVideo: "",
OriginContent: "",
GenerateImage: data.NewPic[0],
GenerateVideo: "",
Status: aiplazamod.DefaultStatus,
}
_, err = aiplazamod.Insert(nil, alPlaza)
if err != nil {
log.Error("新增ai广场帖子失败", log.Any("alPlaza", alPlaza), log.E(err))
return
}
})
}
return stderr.Success
}