331 lines
11 KiB
Go
331 lines
11 KiB
Go
package ai_undress_server
|
|
|
|
import (
|
|
"91porn-server/app/appg"
|
|
"91porn-server/app/service/aiautoser"
|
|
"91porn-server/common"
|
|
"91porn-server/common/constant/redisconst"
|
|
"91porn-server/common/db"
|
|
"91porn-server/common/log"
|
|
"91porn-server/common/stderr"
|
|
"91porn-server/middleware/ua"
|
|
"91porn-server/models/cache/sysconfdata"
|
|
"91porn-server/models/v/advanceordermod"
|
|
"91porn-server/models/v/aiUnDressmod"
|
|
"91porn-server/models/v/sysconfmod"
|
|
"91porn-server/models/v/txnmod"
|
|
"91porn-server/models/v/usermod"
|
|
"91porn-server/models/v/walletmod"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/go-redis/redis"
|
|
carbon "github.com/golang-module/carbon/v2"
|
|
"github.com/shopspring/decimal"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
func List(uid uint64, req *aiUnDressmod.ListRequest) (interface{}, stderr.Code) {
|
|
var data = map[string]interface{}{
|
|
"list": []interface{}{},
|
|
"count": 0,
|
|
}
|
|
count, err := aiUnDressmod.CountDocument(req.Filter(uid))
|
|
if err != nil {
|
|
return nil, stderr.ErrDbQueryError
|
|
}
|
|
if count == 0 {
|
|
return data, stderr.Success
|
|
}
|
|
opts := options.Find().SetSkip(int64(req.Skip())).SetLimit(int64(req.Limit() + 1)).SetSort(bson.M{"updatedAt": -1})
|
|
list, err := aiUnDressmod.QueryAllDocument(req.Filter(uid), opts)
|
|
if err != nil {
|
|
return data, stderr.ErrDbQueryError
|
|
}
|
|
hasNext := false
|
|
if len(list) > int(req.Limit()) {
|
|
list = list[:req.Limit()]
|
|
hasNext = true
|
|
}
|
|
data["count"] = count // 兼容旧版本
|
|
data["hasNext"] = hasNext
|
|
data["list"] = list
|
|
return data, stderr.Success
|
|
}
|
|
|
|
func Generate(uid uint64, req *aiUnDressmod.GenerateRequest, ua ua.UA, ip string) stderr.Code {
|
|
if req.OriginPic == nil || len(req.OriginPic) == 0 {
|
|
return stderr.ErrParamError
|
|
}
|
|
// 获取用户信息
|
|
user, err := usermod.FindUserByUID(uid)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
if user.ID.IsZero() {
|
|
return stderr.UserIsNotExists
|
|
}
|
|
configure, _ := sysconfdata.GetAllFromCache()
|
|
req.Coin = configure.GetInt(sysconfmod.VCodeAiUndressPrice)
|
|
picCount := int64(len(req.OriginPic))
|
|
privilegeFreeCount := int64(0)
|
|
// 获取用户是否是复购
|
|
isRepurchase, err := txnmod.CheckRepurchaseByTransTypes(uid, []txnmod.TransType{
|
|
txnmod.AiUndressDebitFreeTimes,
|
|
txnmod.AiUndressDebitGold,
|
|
txnmod.AiUndressDebitIncomeGold,
|
|
})
|
|
if err != nil {
|
|
log.Error("txnmod.CheckRepurchaseByTransTypes fail", log.E(err))
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
hasPrivilege, advance := advanceordermod.GetUserValidOrder(uid)
|
|
if hasPrivilege {
|
|
// 获取可用免费次数
|
|
validCount := advance.PrepaidPrivilege.AiUndressLimitPerDay - advance.TodayUse.AiUndressCount
|
|
if validCount >= picCount {
|
|
// 扣除免费次数
|
|
debitPlan := advanceordermod.DebitPlan{}
|
|
debitPlan.AiUndressCount = &picCount
|
|
if err := advanceordermod.Debit(nil, uid, debitPlan); err != nil {
|
|
return stderr.ErrDbUpdateError
|
|
}
|
|
privilegeFreeCount = picCount
|
|
picCount = 0
|
|
} else if validCount > 0 {
|
|
// 扣除免费次数
|
|
debitPlan := advanceordermod.DebitPlan{}
|
|
debitPlan.AiUndressCount = &validCount
|
|
if err := advanceordermod.Debit(nil, uid, debitPlan); err != nil {
|
|
return stderr.ErrDbUpdateError
|
|
}
|
|
privilegeFreeCount = validCount
|
|
picCount -= validCount
|
|
}
|
|
if validCount > 0 {
|
|
l := &txnmod.TransactionLog{
|
|
TransNo: primitive.NewObjectID(),
|
|
UID: uid,
|
|
Amount: 1,
|
|
ActualAmount: float64(-1),
|
|
TranType: txnmod.AiUndressDebitFreeTimes.Key(),
|
|
TranTypeInt: int64(txnmod.AiUndressDebitFreeTimes),
|
|
Desc: fmt.Sprintf("生成AI脱衣扣除免费次数[%d次]", privilegeFreeCount),
|
|
RealAmount: decimal.Decimal{},
|
|
SysType: user.SysType,
|
|
IsRepurchase: isRepurchase,
|
|
}
|
|
txnErr := txnmod.InsertTransactionLog(nil, l)
|
|
if txnErr != nil {
|
|
log.Error(fmt.Sprintf("Handle AiUnDress Generate txnmod.InsertTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
}
|
|
}
|
|
var debitFreeCount, debitAmountCoins, debitIncomeCoins int64
|
|
|
|
if picCount > 0 {
|
|
// 获取用户钱包
|
|
w, err := walletmod.GetWallet(uid)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
// 校验用户余额
|
|
if w == nil || !CheckBalance(req.Coin, picCount, *w) {
|
|
return stderr.InsufficientBalance
|
|
}
|
|
|
|
debitFreeCount, debitAmountCoins, debitIncomeCoins = TotalDebit(req.Coin, picCount, *w)
|
|
if w.AiUndressFreeTimes > 0 {
|
|
req.IsFreeTimes = true
|
|
}
|
|
}
|
|
var orderId primitive.ObjectID
|
|
var orderCreatedAt time.Time
|
|
if err = appg.VideoDB.Trans(func(tool *db.MongoTool) error {
|
|
var tl []txnmod.TransactionLog
|
|
if debitFreeCount > 0 {
|
|
expire := carbon.Tomorrow().StartOfDay().StdTime().Sub(time.Now())
|
|
// 累加次数
|
|
appg.Redis.IncrBy(redisconst.AiFreeUndressTodayUseTimesKey(uid), debitFreeCount, expire)
|
|
// 扣除钱剩余次数
|
|
wallet, wErr := walletmod.DebitAiFreeTimes(tool, debitFreeCount, uid)
|
|
if wErr != nil {
|
|
log.Error(fmt.Sprintf("Handle AiUnDress Generate walletmod.DebitAiFreeTimes error:%+v:", wErr), log.Any("uid", uid))
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
|
|
tl = append(tl, txnmod.TransactionLog{
|
|
TransNo: primitive.NewObjectID(),
|
|
UID: uid,
|
|
Amount: 1,
|
|
ActualAmount: float64(-1),
|
|
TranType: txnmod.AiUndressDebitFreeTimes.Key(),
|
|
TranTypeInt: int64(txnmod.AiUndressDebitFreeTimes),
|
|
Desc: fmt.Sprintf("生成AI脱衣扣除免费次数[%d次]", debitFreeCount),
|
|
RealAmount: walletmod.GetRealAmount(wallet),
|
|
SysType: user.SysType,
|
|
IsRepurchase: isRepurchase,
|
|
})
|
|
}
|
|
|
|
if debitIncomeCoins > 0 || debitAmountCoins > 0 {
|
|
// 扣除钱包余额
|
|
wallet, wErr := walletmod.DebitAmountAndIncome(tool, debitAmountCoins, debitIncomeCoins, uid)
|
|
if wErr != nil {
|
|
log.Error(fmt.Sprintf("Handle AiUnDress Generate walletmod.DebitAmount error:%+v:", wErr), log.Any("uid", uid))
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
|
|
if debitAmountCoins > 0 {
|
|
tl = append(tl, txnmod.TransactionLog{
|
|
TransNo: primitive.NewObjectID(),
|
|
UID: uid,
|
|
Amount: -debitAmountCoins,
|
|
ActualAmount: float64(-debitAmountCoins),
|
|
TranType: txnmod.AiUndressDebitGold.Key(),
|
|
TranTypeInt: int64(txnmod.AiUndressDebitGold),
|
|
Desc: fmt.Sprintf("生成AI脱衣金币-%d", debitAmountCoins),
|
|
RealAmount: walletmod.GetRealAmount(wallet),
|
|
SysType: user.SysType,
|
|
IsRepurchase: isRepurchase,
|
|
})
|
|
}
|
|
if debitIncomeCoins > 0 {
|
|
tl = append(tl, txnmod.TransactionLog{
|
|
TransNo: primitive.NewObjectID(),
|
|
UID: uid,
|
|
Amount: -debitIncomeCoins,
|
|
ActualAmount: float64(-debitIncomeCoins),
|
|
TranType: txnmod.AiUndressDebitIncomeGold.Key(),
|
|
TranTypeInt: int64(txnmod.AiUndressDebitIncomeGold),
|
|
Desc: fmt.Sprintf("生成AI脱衣收益金币-%d", debitIncomeCoins),
|
|
RealAmount: walletmod.GetRealAmount(wallet),
|
|
SysType: user.SysType,
|
|
IsRepurchase: isRepurchase,
|
|
})
|
|
}
|
|
}
|
|
|
|
if len(tl) > 0 {
|
|
txnErr := txnmod.InsertManyTransactionLog(tool, tl)
|
|
if txnErr != nil {
|
|
log.Error(fmt.Sprintf("Handle AiUnDress Generate txnmod.InsertTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
}
|
|
|
|
// 新增AI脱衣记录
|
|
orderId = primitive.NewObjectID()
|
|
orderCreatedAt = time.Now()
|
|
if err := aiUnDressmod.InsertMany(tool, req.GenerateMany(orderId, orderCreatedAt, uid, privilegeFreeCount, debitFreeCount, debitAmountCoins, debitIncomeCoins, req.Coin, req.ShareTitle, req.ShareStatus)); err != nil {
|
|
log.Error(fmt.Sprintf("Handle AiUnDress Generate InsertOnes error:%+v:", err), log.Any("uid", uid))
|
|
return stderr.ErrDbInsertError
|
|
}
|
|
|
|
return nil
|
|
}); err != nil {
|
|
log.Error(fmt.Sprintf("Handle AiUnDress Generate Trans error:%+v;uid:%v;", err, uid))
|
|
return stderr.ErrDbUpdateError
|
|
}
|
|
common.Go(func() {
|
|
if err := aiautoser.SubmitUndress(orderId); err != nil {
|
|
log.Error("AI脱衣自动处理失败", log.Any("id", orderId.Hex()), log.E(err))
|
|
}
|
|
})
|
|
|
|
return stderr.Success
|
|
}
|
|
|
|
func AiUndressHide(uid uint64, req *aiUnDressmod.DelRequest) stderr.Code {
|
|
acf, err := aiUnDressmod.FindByID(nil, req.ID)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
if acf.ID.IsZero() {
|
|
return stderr.CodeEmptyData
|
|
}
|
|
if acf.UID != uid {
|
|
return stderr.Failure
|
|
}
|
|
if acf.Status == aiUnDressmod.Processing || acf.Status == aiUnDressmod.SubmitOrder {
|
|
return stderr.AiGenningDelForbidden
|
|
}
|
|
if err = aiUnDressmod.Edit(nil, req.Filter(), req.Update()); err != nil {
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
return stderr.Success
|
|
}
|
|
|
|
func TotalDebit(price int64, count int64, w walletmod.Wallet) (fCount, amountCoins, incomeCoins int64) {
|
|
var (
|
|
debitFreeTimes int64
|
|
debitAmountCoins int64
|
|
debitIncomeCoins int64
|
|
)
|
|
|
|
// 当日剩余ai免费脱衣次数
|
|
todayAiUndressFreeTimes := GetTodayRemainingAiFreeUndressTimes(w)
|
|
// 实际使用的免费脱衣次数
|
|
if todayAiUndressFreeTimes >= count {
|
|
return count, 0, 0
|
|
}
|
|
debitFreeTimes = todayAiUndressFreeTimes
|
|
// 计算当日实际扣减的金额
|
|
debitCoins := (count - debitFreeTimes) * price
|
|
if w.Amount >= debitCoins {
|
|
debitAmountCoins = debitCoins
|
|
} else {
|
|
debitAmountCoins = w.Amount
|
|
debitIncomeCoins = debitCoins - w.Amount
|
|
}
|
|
|
|
return debitFreeTimes, debitAmountCoins, debitIncomeCoins
|
|
}
|
|
|
|
// GetTodayRemainingAiFreeUndressTimes 获取当日剩余的免费ai脱衣的次数
|
|
func GetTodayRemainingAiFreeUndressTimes(w walletmod.Wallet) (num int64) {
|
|
var todayUseAiUndressFreeTimes int // 当日已使用的免费ai脱衣次数
|
|
//获取当日已经使用的ai免费脱衣次数
|
|
str, err := appg.Redis.Get(redisconst.AiFreeUndressTodayUseTimesKey(w.UID))
|
|
if err != nil && err != redis.Nil {
|
|
log.Error(fmt.Sprintf("get AiUndressTodayUseTimes err%v", err))
|
|
// redis报错返回已经当日最大限制次数,避免被刷
|
|
todayUseAiUndressFreeTimes = 0
|
|
} else if str != nil {
|
|
todayUseAiUndressFreeTimes, _ = strconv.Atoi(*str)
|
|
}
|
|
num = int64(appg.Conf.AiFreeUnDressDailyLimit - todayUseAiUndressFreeTimes)
|
|
// 如果用户剩余的免费次数不足,以剩余次数为准
|
|
if num >= w.AiUndressFreeTimes {
|
|
num = w.AiUndressFreeTimes
|
|
}
|
|
if num < 0 {
|
|
num = 0
|
|
}
|
|
return
|
|
}
|
|
|
|
func CheckBalance(price int64, count int64, w walletmod.Wallet) bool {
|
|
var checkStats bool
|
|
var totalCoins = w.Amount
|
|
if w.Income != 0 {
|
|
totalCoins += w.Income
|
|
}
|
|
if w.AiUndressFreeTimes > 0 && w.AiUndressFreeTimes >= count {
|
|
checkStats = true
|
|
}
|
|
|
|
if w.AiUndressFreeTimes > 0 && w.AiUndressFreeTimes < count && totalCoins >= price*(count-w.AiUndressFreeTimes) {
|
|
checkStats = true
|
|
}
|
|
|
|
if w.AiUndressFreeTimes <= 0 && totalCoins >= price*count {
|
|
checkStats = true
|
|
}
|
|
return checkStats
|
|
}
|