@@ -0,0 +1,330 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user