@@ -0,0 +1,384 @@
|
||||
package ai_changeface_ser
|
||||
|
||||
import (
|
||||
"91porn-server/app/appg"
|
||||
"91porn-server/app/service/aiautoser"
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/aiService"
|
||||
"91porn-server/common/constant/redisconst"
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/stderr"
|
||||
"91porn-server/middleware/ua"
|
||||
"91porn-server/models/commod"
|
||||
"91porn-server/models/v/aichangefacemod"
|
||||
"91porn-server/models/v/aichangefacevidmod"
|
||||
"91porn-server/models/v/backpackmod"
|
||||
"91porn-server/models/v/txnmod"
|
||||
"91porn-server/models/v/usermod"
|
||||
"91porn-server/models/v/walletmod"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
func List(uid uint64, status *aichangefacemod.AiChangeFaceStatus, skip, limit int) ([]aichangefacemod.AiChangeFace, bool, error) {
|
||||
acfs, err := aichangefacemod.ListByUid(uid, status, skip, limit+1)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
hasNext := false
|
||||
if len(acfs) > limit {
|
||||
acfs = acfs[:limit]
|
||||
hasNext = true
|
||||
}
|
||||
return acfs, hasNext, nil
|
||||
}
|
||||
|
||||
func Generate(uid uint64, pics []string, vidModId primitive.ObjectID, discount []primitive.ObjectID, shareTitle string, shareStatus int, ua ua.UA, ip string) stderr.Code {
|
||||
vidMod, err := aiService.NewAiService(
|
||||
aiService.AppId(int(commod.KFK_APPID)),
|
||||
aiService.Url(appg.Conf.URL.AiServer),
|
||||
aiService.Redis(appg.Redis),
|
||||
).GetTemplate(vidModId)
|
||||
if vidMod.ID.IsZero() {
|
||||
return stderr.Failure
|
||||
}
|
||||
var discountValue int64
|
||||
now := time.Now()
|
||||
var dsId []primitive.ObjectID
|
||||
for _, d := range discount {
|
||||
dsId = append(dsId, d)
|
||||
bp, err := backpackmod.GetByID(nil, d)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
if bp == nil { // 抵扣券不存在
|
||||
return stderr.Failure
|
||||
}
|
||||
if bp.GoodsType != backpackmod.AiChangeFaceDiscount { // 抵扣券类型不对
|
||||
return stderr.Failure
|
||||
}
|
||||
if bp.Status == backpackmod.Used { // 抵扣券已被使用
|
||||
return stderr.Failure
|
||||
}
|
||||
if bp.ExpiredTime.Before(now) { // 抵扣券已过期
|
||||
return stderr.Failure
|
||||
}
|
||||
discountValue += bp.GoodsValue
|
||||
}
|
||||
originPrice := vidMod.Coin
|
||||
|
||||
user, err := usermod.FindUserByUID(uid)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
|
||||
if user.IsVIP(time.Now()) {
|
||||
originPrice = vidMod.VipCoin
|
||||
}
|
||||
|
||||
price := int64(originPrice) - discountValue
|
||||
if price < 0 {
|
||||
price = 0
|
||||
}
|
||||
|
||||
// 获取钱包信息
|
||||
wlt, err := walletmod.GetWallet(uid)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
|
||||
if wlt == nil || wlt.Amount+wlt.Income < price {
|
||||
return stderr.InsufficientBalance
|
||||
}
|
||||
|
||||
// 扣除的普通金币和收益金币
|
||||
debitAmt, debitIncome := TotalDebit(price, wlt)
|
||||
// 获取用户是否是复购
|
||||
isRepurchase, err := txnmod.CheckRepurchaseByTransTypes(uid, []txnmod.TransType{
|
||||
txnmod.AiChangefaceDebitGold,
|
||||
txnmod.AiChangefaceDebitInComeGold,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("txnmod.CheckRepurchaseByTransTypes fail", log.E(err))
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
var orderId primitive.ObjectID
|
||||
var orderCreatedAt time.Time
|
||||
if err = appg.VideoDB.Trans(func(tool *db.MongoTool) error {
|
||||
var tl []txnmod.TransactionLog
|
||||
if debitAmt > 0 || debitIncome > 0 {
|
||||
// 扣除钱包余额
|
||||
wallet, err := walletmod.DebitAmountAndIncome(tool, debitAmt, debitIncome, uid)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Handle AiChangeface Generate walletmod.DebitAmount error:%+v:", err), log.Any("uid", uid))
|
||||
if err.Error() == "no enough balance" {
|
||||
return stderr.InsufficientBalance
|
||||
}
|
||||
return stderr.ErrDbUpdateError
|
||||
}
|
||||
|
||||
if debitAmt > 0 {
|
||||
tl = append(tl, txnmod.TransactionLog{
|
||||
TransNo: primitive.NewObjectID(),
|
||||
UID: uid,
|
||||
Amount: -debitAmt,
|
||||
ActualAmount: -float64(debitAmt),
|
||||
TranType: txnmod.AiChangefaceDebitGold.Key(),
|
||||
TranTypeInt: int64(txnmod.AiChangefaceDebitGold),
|
||||
Desc: fmt.Sprintf("生成AI换脸金币-%d", debitAmt),
|
||||
RealAmount: walletmod.GetRealAmount(wallet),
|
||||
SysType: user.SysType,
|
||||
IsRepurchase: isRepurchase,
|
||||
})
|
||||
}
|
||||
|
||||
if debitIncome > 0 {
|
||||
tl = append(tl, txnmod.TransactionLog{
|
||||
TransNo: primitive.NewObjectID(),
|
||||
UID: uid,
|
||||
Amount: -debitIncome,
|
||||
ActualAmount: -float64(debitIncome),
|
||||
TranType: txnmod.AiChangefaceDebitGold.Key(),
|
||||
TranTypeInt: int64(txnmod.AiChangefaceDebitGold),
|
||||
Desc: fmt.Sprintf("生成AI换脸收益金币-%d", debitIncome),
|
||||
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 AiChangeface Generate txnmod.InsertManyTransactionLog error:%+v:", txnErr), log.Any("uid", uid))
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
}
|
||||
|
||||
// 抵扣券使用
|
||||
if len(dsId) > 0 {
|
||||
modified, err := backpackmod.UseManyGoods(tool, dsId)
|
||||
if err != nil {
|
||||
return stderr.ErrDbUpdateError
|
||||
}
|
||||
if modified != int64(len(dsId)) {
|
||||
return stderr.Failure
|
||||
}
|
||||
}
|
||||
|
||||
// 新增AI脱衣记录
|
||||
orderId = primitive.NewObjectID()
|
||||
orderCreatedAt = time.Now()
|
||||
if err = aichangefacemod.AddAiChangeFace(tool, orderId, orderCreatedAt, uid, pics, vidMod, debitAmt, debitIncome, discount, shareTitle, shareStatus); err != nil {
|
||||
log.Error(fmt.Sprintf("Handle AiChangeface Generate InsertOnes error:%+v:", err), log.Any("uid", uid))
|
||||
return stderr.ErrDbInsertError
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
if e, ok := err.(stderr.Code); ok {
|
||||
return e
|
||||
}
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
common.Go(func() {
|
||||
if err := aiautoser.SubmitVideo(orderId); err != nil {
|
||||
log.Error("AI视频换脸自动处理失败", log.Any("id", orderId.Hex()), log.E(err))
|
||||
}
|
||||
})
|
||||
|
||||
return stderr.Success
|
||||
}
|
||||
|
||||
func TotalDebit(coins int64, w *walletmod.Wallet) (amtDebit, income int64) {
|
||||
var (
|
||||
deAmt int64
|
||||
deIncome int64
|
||||
)
|
||||
if w.Amount >= coins {
|
||||
deAmt = coins
|
||||
}
|
||||
if w.Amount < coins && w.Amount+w.Income >= coins {
|
||||
deAmt = w.Amount
|
||||
deIncome = coins - w.Amount
|
||||
}
|
||||
return deAmt, deIncome
|
||||
}
|
||||
|
||||
// ModList 获取模版列表
|
||||
func ModList(uid uint64) (data *aichangefacevidmod.AppResponse, err error) {
|
||||
var ret aichangefacevidmod.AppResponse
|
||||
key := redisconst.AIModCache
|
||||
str, err := appg.Redis.Get(key)
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("用户ID:%d;缓存获取AI模版列表信息异常:%v", uid, err))
|
||||
}
|
||||
|
||||
if str != nil {
|
||||
if err = json.Unmarshal([]byte(*str), &ret); err == nil {
|
||||
return &ret, nil
|
||||
}
|
||||
log.Warn(fmt.Sprintf("用户ID:%d;解析缓存数据异常:%v", uid, err))
|
||||
}
|
||||
|
||||
mods, err := aichangefacevidmod.GetAllMods()
|
||||
if err != nil {
|
||||
return &ret, err
|
||||
}
|
||||
|
||||
if len(mods) > 0 {
|
||||
for _, m := range mods {
|
||||
if m.ModuleType == aichangefacevidmod.AIUndress {
|
||||
ret.AiUndressMod = append(ret.AiUndressMod, aichangefacevidmod.AiUndressMod{
|
||||
ID: m.ID,
|
||||
Cover: m.Cover,
|
||||
})
|
||||
}
|
||||
if m.ModuleType == aichangefacevidmod.AIImgToVideo {
|
||||
ret.AiImgToVideoMod = append(ret.AiImgToVideoMod, aichangefacevidmod.AiImgToVideoMod{
|
||||
ID: m.ID,
|
||||
Title: m.Title,
|
||||
SceneType: m.SceneType,
|
||||
Cover: m.Cover,
|
||||
NewUrl: m.NewUrl,
|
||||
})
|
||||
}
|
||||
if m.ModuleType == aichangefacevidmod.AITextToImage {
|
||||
ret.AiTextToImgMod = append(ret.AiTextToImgMod, aichangefacevidmod.AiTextToImgMod{
|
||||
ID: m.ID,
|
||||
Cover: m.Cover,
|
||||
Title: m.Title,
|
||||
StyleType: m.HotValue,
|
||||
})
|
||||
}
|
||||
//if m.ModuleType == aichangefacevidmod.AIVideoChangeFace {
|
||||
// ret.AiChangeFaceVideoMod = append(ret.AiChangeFaceVideoMod, aichangefacevidmod.AiChangeMod{
|
||||
// ID: m.ID,
|
||||
// Title: m.Title,
|
||||
// SourceURL: m.SourceURL,
|
||||
// Cover: m.Cover,
|
||||
// PlayTime: m.PlayTime,
|
||||
// Type: m.Type,
|
||||
// HotMark: m.HotMark,
|
||||
// HotValue: m.HotValue,
|
||||
// Coin: m.Coin,
|
||||
// VipCoin: m.VipCoin,
|
||||
// })
|
||||
//}
|
||||
//if m.ModuleType == aichangefacevidmod.AIImgChangeFace {
|
||||
// ret.AiChangeFaceMod = append(ret.AiChangeFaceMod, aichangefacevidmod.AiChangeFaceMod{
|
||||
// Title: m.Title,
|
||||
// ID: m.ID,
|
||||
// Cover: m.Cover,
|
||||
// HotMark: m.HotMark,
|
||||
// HotValue: m.HotValue,
|
||||
// Coin: m.Coin,
|
||||
// VipCoin: m.VipCoin,
|
||||
// })
|
||||
//}
|
||||
}
|
||||
}
|
||||
common.Go(func() {
|
||||
d, err := json.Marshal(ret)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = appg.Redis.Set(key, d, 5*time.Minute); err != nil {
|
||||
log.Warn(fmt.Sprintf("用户ID:%d;保存缓存数据异常:%v", uid, err))
|
||||
}
|
||||
})
|
||||
return &ret, nil
|
||||
}
|
||||
|
||||
type ModListV2Req struct {
|
||||
Type int `json:"type" form:"type"` // 0-图片换脸 1-视频换脸
|
||||
CategoryId string `json:"categoryId" form:"categoryId"` // 模版分类id,如果为空,则默认第一个模版分类
|
||||
}
|
||||
|
||||
type ModListV2Resp struct {
|
||||
CategoryList []*aiService.Category `json:"categoryList"`
|
||||
TemplateList []*aiService.Template `json:"templateList"`
|
||||
CategoryId string `json:"categoryId"` // 当前返回的分类id下的模版
|
||||
}
|
||||
|
||||
// ModListV2 获取模版列表
|
||||
func ModListV2(req ModListV2Req) (resp ModListV2Resp, err error) {
|
||||
ai := aiService.NewAiService(
|
||||
aiService.AppId(int(commod.KFK_APPID)),
|
||||
aiService.Url(appg.Conf.URL.AiServer),
|
||||
aiService.Redis(appg.Redis),
|
||||
)
|
||||
resp.CategoryList, resp.CategoryId, resp.TemplateList, err = ai.GetTemplateList(req.Type, req.CategoryId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
type ModInfoReq struct {
|
||||
Id string `json:"id" form:"id"`
|
||||
Type int `json:"type" form:"type"` // 1-ai图片换脸 2-ai视频换脸 3-ai脱衣 4-ai图生视频 5-ai绘画
|
||||
}
|
||||
|
||||
type ModInfoResp struct {
|
||||
AiUndressMod aichangefacevidmod.AiUndressMod `json:"aiUndressMod" bson:"aiUndressMod"` // AI脱衣模版
|
||||
AiTextToImgMod aichangefacevidmod.AiTextToImgMod `json:"aiTextToImgMod" bson:"aiTextToImgMod"` // AI绘图模型
|
||||
AiImgToVideoMod aichangefacevidmod.AiImgToVideoMod `json:"aiImgToVideoMod" bson:"aiImgToVideoMod"` // AI图生视频模型
|
||||
AiChangeFaceMod aiService.Template `json:"aiChangeFaceMod" bson:"aiChangeFaceMod"` // Ai视频/图片换脸模型
|
||||
}
|
||||
|
||||
func (p *ModInfoReq) GetInfo() (resp ModInfoResp, err error) {
|
||||
id, _ := primitive.ObjectIDFromHex(p.Id)
|
||||
if id.IsZero() {
|
||||
return resp, errors.New("id无效")
|
||||
}
|
||||
if p.Type > 2 {
|
||||
// 从本地的表里获取
|
||||
m, err := aichangefacevidmod.GetModById(id)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if m.ModuleType == aichangefacevidmod.AIUndress {
|
||||
resp.AiUndressMod = aichangefacevidmod.AiUndressMod{
|
||||
ID: m.ID,
|
||||
Cover: m.Cover,
|
||||
}
|
||||
}
|
||||
if m.ModuleType == aichangefacevidmod.AIImgToVideo {
|
||||
resp.AiImgToVideoMod = aichangefacevidmod.AiImgToVideoMod{
|
||||
ID: m.ID,
|
||||
Cover: m.Cover,
|
||||
NewUrl: m.NewUrl,
|
||||
}
|
||||
}
|
||||
if m.ModuleType == aichangefacevidmod.AITextToImage {
|
||||
resp.AiTextToImgMod = aichangefacevidmod.AiTextToImgMod{
|
||||
ID: m.ID,
|
||||
Cover: m.Cover,
|
||||
Title: m.Title,
|
||||
StyleType: m.HotValue,
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// 获取视频/图片换脸模版
|
||||
ai := aiService.NewAiService(
|
||||
aiService.AppId(int(commod.KFK_APPID)),
|
||||
aiService.Url(appg.Conf.URL.AiServer),
|
||||
aiService.Redis(appg.Redis),
|
||||
)
|
||||
template, err := ai.GetTemplate(id)
|
||||
if err != nil {
|
||||
log.Error("ai.GetTemplate fail", log.Any("id", id), log.E(err))
|
||||
return
|
||||
}
|
||||
resp.AiChangeFaceMod = template
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user