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,468 @@
package ai_changeface_img_ser
import (
"91porn-server/common"
"91porn-server/common/db"
"91porn-server/common/httputil"
"91porn-server/common/log"
"91porn-server/common/stderr"
"91porn-server/models/commod"
"91porn-server/models/v/aichangefaceimgmod"
"91porn-server/models/v/aichangefacevidmod"
"91porn-server/models/v/aiplazamod"
"91porn-server/models/v/txnmod"
"91porn-server/models/v/walletmod"
"91porn-server/web/proto"
"91porn-server/web/webg"
"fmt"
"strings"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func List(req *aichangefaceimgmod.WebListRequest) (interface{}, stderr.Code) {
var data = map[string]interface{}{
"list": []interface{}{},
"count": 0,
}
count, err := aichangefaceimgmod.CountDocument(req.Filter())
if err != nil {
return nil, stderr.ErrDbQueryError
}
if count == 0 {
return data, stderr.Success
}
list, err := aichangefaceimgmod.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 *aichangefaceimgmod.EditCond) stderr.Code {
// 获取Ai记录
data, err := aichangefaceimgmod.FindDataByID(req.ID)
if err != nil {
return stderr.ErrDbQueryError
}
if data.ID.IsZero() {
return stderr.CodeEmptyData
}
if (*req.Status == aichangefaceimgmod.FAILURE || *req.Status == aichangefaceimgmod.REFUND) &&
(data.Status == aichangefaceimgmod.FAILURE || data.Status == aichangefaceimgmod.REFUND) {
return stderr.Success
}
// 根据状态判断
switch *req.Status {
case aichangefaceimgmod.Processing:
if data.Status != aichangefaceimgmod.SUCCESS {
return stderr.AiChangeFaceImgStatusIsErr
}
err = aichangefaceimgmod.Edit(nil, req.Filter(), req.Update(act))
if err != nil {
return stderr.ErrDbUpdateError
}
case aichangefaceimgmod.SUCCESS:
if err = aichangefaceimgmod.Edit(nil, req.Filter(), req.Update(act)); err != nil {
return stderr.ErrDbUpdateError
}
case aichangefaceimgmod.FAILURE, aichangefaceimgmod.REFUND:
// 失败处理 退金币
deAmt := -data.DebitAmountCoin
deIncome := -data.DebitIncomeCoin
uid := data.UID
if err = webg.VideoDB.Trans(func(tool *db.MongoTool) error {
updateSet, _ := req.Update(act)["$set"].(bson.M)
transitioned, transitionErr := aichangefaceimgmod.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 AiChangeFaceImg 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.AiChangeFaceImgDebitFreeTimesReturn.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgDebitFreeTimesReturn),
Desc: fmt.Sprintf("AI图片换脸免费次数退返[%d次]", deCount),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if data.DebitAmountCoin > 0 || data.DebitIncomeCoin > 0 {
// 加钱包余额
wallet, wErr := walletmod.ReturnAmountAndIncome(tool, deAmt, deIncome, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiChangeFaceImg 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.AiChangeFaceImgReturnIncomeGold.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgReturnIncomeGold),
Desc: fmt.Sprintf("AI图片换脸收益金币退返-%d", -deIncome),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if data.DebitAmountCoin > 0 {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deAmt,
ActualAmount: float64(-deAmt),
TranType: txnmod.AiChangeFaceImgReturnGold.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgReturnGold),
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 AiChangeFaceImg Edit txnmod.InsertManyTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
}
return nil
}); err != nil {
log.Error(fmt.Sprintf("Handle AiChangeFaceImg Edit Trans error:%+v;uid:%v;", err, uid))
return stderr.ErrDbUpdateError
}
}
return stderr.Success
}
func UpdateNew(act string, req *aichangefaceimgmod.EditCond) stderr.Code {
// 获取Ai记录
data, err := aichangefaceimgmod.FindDataByID(req.ID)
if err != nil {
return stderr.ErrDbQueryError
}
if data.ID.IsZero() {
return stderr.CodeEmptyData
}
if *req.Status == aichangefaceimgmod.StatusSubmit && data.Status == aichangefaceimgmod.StatusSubmit {
return stderr.Success
}
if (*req.Status == aichangefaceimgmod.FAILURE || *req.Status == aichangefaceimgmod.REFUND) &&
(data.Status == aichangefaceimgmod.FAILURE || data.Status == aichangefaceimgmod.REFUND) {
return stderr.Success
}
// 根据状态判断
switch *req.Status {
case aichangefaceimgmod.Processing:
err = aichangefaceimgmod.Edit(nil, req.Filter(), req.Update(act))
if err != nil {
return stderr.ErrDbUpdateError
}
case aichangefaceimgmod.StatusSubmit:
//提交订单到第三方
notifyURL, notifyErr := webg.AICallbackURL("/api/web/admin/ai/change_face_img/callback")
if notifyErr != nil {
log.Error("AI图片换脸回调地址配置异常", log.E(notifyErr))
return stderr.Failure
}
httpReq := proto.AiChangeFaceReq{
AppId: int(commod.KFK_APPID),
OrderNumAPP: data.ID.Hex(),
Title: data.ModTitle,
SourceImageUrl: data.OriginPic,
NotifyUrl: notifyURL,
}
url := webg.Conf.URL.AiServer + "/api/changeface/prd/changeFaceByVideo"
//第三方请求地址
var resp proto.AiChangeFaceResp
codeJ, err := httputil.DefaultClientPostJsonWithResp(&resp, url, nil, httpReq)
if err != nil {
log.Error("CreateChangeFace httputil.DefaultClientPostJsonWithResp err", log.E(err))
return stderr.Failure
}
if codeJ != 200 {
log.Error("CreateChangeFace req http code error", log.Any("code", codeJ))
return stderr.Failure
}
if resp.Code == 40000 {
return stderr.ChangeFaceNoModule
}
if err = aichangefaceimgmod.Edit(nil, req.Filter(), req.Update(act)); err != nil {
return stderr.ErrDbUpdateError
}
case aichangefaceimgmod.FAILURE, aichangefaceimgmod.REFUND:
// 失败处理 退金币
deAmt := -data.DebitAmountCoin
deIncome := -data.DebitIncomeCoin
uid := data.UID
if err = webg.VideoDB.Trans(func(tool *db.MongoTool) error {
updateSet, _ := req.Update(act)["$set"].(bson.M)
transitioned, transitionErr := aichangefaceimgmod.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 AiChangeFaceImg 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.AiChangeFaceImgDebitFreeTimesReturn.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgDebitFreeTimesReturn),
Desc: fmt.Sprintf("AI图片换脸免费次数退返[%d次]", deCount),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if data.DebitAmountCoin > 0 || data.DebitIncomeCoin > 0 {
// 加钱包余额
wallet, wErr := walletmod.ReturnAmountAndIncome(tool, deAmt, deIncome, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiChangeFaceImg 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.AiChangeFaceImgReturnIncomeGold.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgReturnIncomeGold),
Desc: fmt.Sprintf("AI图片换脸收益金币退返-%d", -deIncome),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if data.DebitAmountCoin > 0 {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deAmt,
ActualAmount: float64(-deAmt),
TranType: txnmod.AiChangeFaceImgReturnGold.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgReturnGold),
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 AiChangeFaceImg Edit txnmod.InsertManyTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
}
return nil
}); err != nil {
log.Error(fmt.Sprintf("Handle AiChangeFaceImg Edit Trans error:%+v;uid:%v;", err, uid))
return stderr.ErrDbUpdateError
}
}
return stderr.Success
}
func CallBackOrder(req *aichangefacevidmod.CallbackReq) stderr.Code {
//根据订单号更新ai换脸订单
id, _ := primitive.ObjectIDFromHex(req.AppOrderNum)
//查询该笔订单是否存在
aichangeFaceInfo, err := aichangefaceimgmod.FindByID(nil, id)
if aichangeFaceInfo == nil || err != nil {
return stderr.ErrDbQueryError
}
oldOrderTime := time.Date(2025, 9, 15, 0, 0, 0, 0, time.Local)
if aichangeFaceInfo.CreatedAt.Before(oldOrderTime) &&
(aichangeFaceInfo.Status == aichangefaceimgmod.SUCCESS || aichangeFaceInfo.Status == aichangefaceimgmod.FAILURE || aichangeFaceInfo.Status == aichangefaceimgmod.REFUND) {
// 以前的单子如果处理过了就新下资源和状态
set := bson.M{"newPic": []string{strings.TrimSpace(req.ImgUrl)}}
if req.Msg == "操作成功" {
set["status"] = aichangefaceimgmod.SUCCESS
} else {
set["remark"] = req.Msg
set["status"] = aichangefaceimgmod.REFUND
}
_ = aichangefaceimgmod.Update(nil, id, set)
return stderr.Success
}
if aichangeFaceInfo.Status != aichangefaceimgmod.StatusSubmit {
log.Error("AI图片换脸-重复回调或者状态不正确", log.Any("id", aichangeFaceInfo.ID.Hex()), log.Any("status", aichangeFaceInfo.Status))
return stderr.Success
}
var status = aichangefaceimgmod.SUCCESS
//处理金币退款以及后续操作
set := bson.M{}
if req.ImgUrl != "" {
set["newPic"] = append([]string{}, strings.TrimSpace(req.ImgUrl))
}
if req.Msg != "操作成功" {
set["remark"] = req.Msg
status = aichangefaceimgmod.REFUND
}
set["status"] = status
switch status {
case aichangefaceimgmod.SUCCESS:
transitioned, updateErr := aichangefaceimgmod.TransitionStatus(nil, id, aichangefaceimgmod.StatusSubmit, aichangefaceimgmod.SUCCESS, set)
if updateErr != nil {
return stderr.ErrDbUpdateError
}
if !transitioned {
return stderr.Success
}
common.Go(func() {
if aichangeFaceInfo.ShareStatus != 1 {
return
}
// 新增一个分享
alPlaza := aiplazamod.AiPlaza{
Type: 1,
OrderId: aichangeFaceInfo.ID,
Template: aichangeFaceInfo.MId,
Uid: aichangeFaceInfo.UID,
Title: aichangeFaceInfo.ShareTitle,
OriginalImage: aichangeFaceInfo.ModPic,
OriginalVideo: "",
OriginContent: "",
GenerateImage: req.ImgUrl,
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
case aichangefaceimgmod.REFUND:
//换脸失败,进行退款操作
// 失败处理 退金币
deAmt := -aichangeFaceInfo.DebitAmountCoin
deIncome := -aichangeFaceInfo.DebitIncomeCoin
uid := aichangeFaceInfo.UID
if err = webg.VideoDB.Trans(func(tool *db.MongoTool) error {
transitioned, transitionErr := aichangefaceimgmod.TransitionStatus(tool, id, aichangefaceimgmod.StatusSubmit, aichangefaceimgmod.REFUND, set)
if transitionErr != nil {
return transitionErr
}
if !transitioned {
return nil
}
var tl []txnmod.TransactionLog
// 根据是否是免费次数退回
if aichangeFaceInfo.Count > 0 || aichangeFaceInfo.IsFreeTimes {
deCount := aichangeFaceInfo.Count
if aichangeFaceInfo.Count == 0 {
deCount = 1
}
// 加钱包余额
wallet, wErr := walletmod.DebitAiFreeTimes(tool, -deCount, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiChangeFaceImg 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.AiChangeFaceImgDebitFreeTimesReturn.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgDebitFreeTimesReturn),
Desc: fmt.Sprintf("AI图片换脸免费次数退返[%d次]", deCount),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if aichangeFaceInfo.DebitAmountCoin > 0 || aichangeFaceInfo.DebitIncomeCoin > 0 {
// 加钱包余额
wallet, wErr := walletmod.ReturnAmountAndIncome(tool, deAmt, deIncome, uid)
if wErr != nil {
log.Error(fmt.Sprintf("Handle AiChangeFaceImg Edit walletmod.DebitAmount error:%+v:", wErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
if aichangeFaceInfo.DebitIncomeCoin > 0 {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deIncome,
ActualAmount: float64(-deIncome),
TranType: txnmod.AiChangeFaceImgReturnIncomeGold.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgReturnIncomeGold),
Desc: fmt.Sprintf("AI图片换脸收益金币退返-%d", -deIncome),
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if aichangeFaceInfo.DebitAmountCoin > 0 {
tl = append(tl, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: uid,
Amount: -deAmt,
ActualAmount: float64(-deAmt),
TranType: txnmod.AiChangeFaceImgReturnGold.Key(),
TranTypeInt: int64(txnmod.AiChangeFaceImgReturnGold),
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 AiChangeFaceImg Edit txnmod.InsertManyTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
}
return nil
}); err != nil {
log.Error(fmt.Sprintf("Handle AiChangeFaceImg Edit Trans error:%+v;uid:%v;", err, uid))
return stderr.ErrDbUpdateError
}
}
return stderr.Success
}