343 lines
10 KiB
Go
Executable File
343 lines
10 KiB
Go
Executable File
package ai_text_to_novel_ser
|
||
|
||
import (
|
||
"91porn-server/common/db"
|
||
"91porn-server/common/log"
|
||
"91porn-server/common/stderr"
|
||
"91porn-server/models/cache/aitexttonoveldata"
|
||
"91porn-server/models/commod"
|
||
"91porn-server/models/v/aitexttonovelmod"
|
||
"91porn-server/models/v/txnmod"
|
||
"91porn-server/models/v/walletmod"
|
||
"91porn-server/web/webg"
|
||
"errors"
|
||
"fmt"
|
||
"strings"
|
||
"time"
|
||
|
||
"go.mongodb.org/mongo-driver/bson"
|
||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||
)
|
||
|
||
type WebListReq struct {
|
||
ID *string `json:"id" form:"id"` // ID
|
||
UID *uint64 `json:"uid" form:"uid"` // 用户ID
|
||
Status *int `json:"status" form:"status"` // 状态
|
||
commod.Page
|
||
}
|
||
|
||
func (q *WebListReq) Filter() primitive.M {
|
||
filter := bson.M{}
|
||
if q.ID != nil {
|
||
id, _ := primitive.ObjectIDFromHex(*q.ID)
|
||
filter["_id"] = id
|
||
}
|
||
if q.Status != nil {
|
||
filter["status"] = q.Status
|
||
}
|
||
if q.UID != nil {
|
||
filter["uid"] = q.UID
|
||
}
|
||
return filter
|
||
}
|
||
|
||
func (q *WebListReq) Sort() primitive.D {
|
||
return bson.D{{Key: "createdAt", Value: -1}}
|
||
}
|
||
|
||
type WebListRes struct {
|
||
Total int64 `json:"total"`
|
||
HasNext bool `json:"hasNext"`
|
||
List []aitexttonovelmod.AiTextToNovel `json:"list"`
|
||
}
|
||
|
||
// GetList 获取列表
|
||
func (q *WebListReq) GetList() (res WebListRes, err error) {
|
||
res.List, res.Total, res.HasNext, err = aitexttonovelmod.GetList(q.Filter(), int64(q.Skip()), int64(q.Limit()), q.Sort())
|
||
return
|
||
}
|
||
|
||
type WebUpdateReq struct {
|
||
ID primitive.ObjectID `json:"id" binding:"required"`
|
||
UID *uint64 `json:"uid"` // 用户ID
|
||
Background *string `json:"background"` // 小说人物设定/故事背景等
|
||
Scene *string `json:"scene"` // 地点场景
|
||
Text *string `json:"text"` // 故事情节描述
|
||
Other *string `json:"other"` // 小说其他要求
|
||
ModelType *string `json:"modelType"` // AI小说模型 1,2
|
||
Content *string `json:"content"` // AI生成小说正文
|
||
Status *int `json:"status"` // 状态
|
||
Coin *int64 `json:"coin"` // AI小说金币个数
|
||
DebitAmountCoin *int64 `json:"debitAmountCoin"` // 此次AI小说扣除金币个数
|
||
DebitIncomeCoin *int64 `json:"debitIncomeCoin"` // 此次AI小说扣除收益金币个数
|
||
IsFreeTimes *bool `json:"isFreeTimes"` // 是否使用免费次数
|
||
IsHide *bool `json:"isHide"` // 是否被用户隐藏
|
||
Remark *string `json:"remark"` // 备注
|
||
IsDelete *bool `json:"isDelete"` // 是否删除
|
||
}
|
||
|
||
// Update 更新数据
|
||
func (p *WebUpdateReq) Update() error {
|
||
info, err := aitexttonovelmod.GetInfo(p.ID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if info.ID.IsZero() {
|
||
return errors.New("data is null")
|
||
}
|
||
|
||
data := make(map[string]interface{})
|
||
if p.UID != nil {
|
||
data["uid"] = *p.UID
|
||
}
|
||
if p.Background != nil {
|
||
data["background"] = *p.Background
|
||
}
|
||
if p.Scene != nil {
|
||
data["scene"] = *p.Scene
|
||
}
|
||
if p.Text != nil {
|
||
data["text"] = *p.Text
|
||
}
|
||
if p.Other != nil {
|
||
data["other"] = *p.Other
|
||
}
|
||
if p.ModelType != nil {
|
||
data["modelType"] = *p.ModelType
|
||
}
|
||
if p.Content != nil {
|
||
data["content"] = *p.Content
|
||
}
|
||
if p.Status != nil {
|
||
data["status"] = *p.Status
|
||
}
|
||
if p.Coin != nil {
|
||
data["coin"] = *p.Coin
|
||
}
|
||
if p.DebitAmountCoin != nil {
|
||
data["debitAmountCoin"] = *p.DebitAmountCoin
|
||
}
|
||
if p.DebitIncomeCoin != nil {
|
||
data["debitIncomeCoin"] = *p.DebitIncomeCoin
|
||
}
|
||
if p.IsFreeTimes != nil {
|
||
data["isFreeTimes"] = *p.IsFreeTimes
|
||
}
|
||
if p.IsHide != nil {
|
||
data["isHide"] = *p.IsHide
|
||
}
|
||
if p.Remark != nil {
|
||
data["remark"] = *p.Remark
|
||
}
|
||
if p.IsDelete != nil {
|
||
data["isDelete"] = *p.IsDelete
|
||
}
|
||
data["updatedAt"] = time.Now()
|
||
if p.Status != nil && *p.Status == 5 {
|
||
if info.Status == int(aitexttonovelmod.StatusRefunded) || info.Status == int(aitexttonovelmod.StatusGenerationFailed) {
|
||
return errors.New("Please do not refund repeatedly.")
|
||
}
|
||
|
||
if err = webg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||
if _, err = aitexttonovelmod.UpdateByID(t, info.ID, data); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 退款
|
||
if info.DebitAmountCoin == 0 && info.DebitIncomeCoin == 0 { // 总金额为0则不需要退款
|
||
return nil
|
||
}
|
||
|
||
// 退款进入钱包余额
|
||
wallet, err := walletmod.ReturnAmountAndIncome(t, -info.DebitAmountCoin, -info.DebitIncomeCoin, info.UID)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("Handle text to novel Edit walletmod.DebitAmount error:%+v:", err), log.Any("uid", info.UID))
|
||
return err
|
||
}
|
||
var tl []txnmod.TransactionLog
|
||
if info.DebitAmountCoin > 0 {
|
||
tl = append(tl, txnmod.TransactionLog{
|
||
TransNo: primitive.NewObjectID(),
|
||
UID: info.UID,
|
||
Amount: info.DebitAmountCoin,
|
||
ActualAmount: float64(info.DebitAmountCoin),
|
||
TranType: txnmod.AiTextToNovelDebitGoldReturn.Key(),
|
||
TranTypeInt: int64(txnmod.AiTextToNovelDebitGoldReturn),
|
||
Desc: fmt.Sprintf("退还AI小说金币-%d", info.DebitAmountCoin),
|
||
RealAmount: walletmod.GetRealAmount(wallet),
|
||
})
|
||
}
|
||
if info.DebitIncomeCoin > 0 {
|
||
tl = append(tl, txnmod.TransactionLog{
|
||
TransNo: primitive.NewObjectID(),
|
||
UID: info.UID,
|
||
Amount: info.DebitIncomeCoin,
|
||
ActualAmount: float64(info.DebitIncomeCoin),
|
||
TranType: txnmod.AiTextToNovelDebitIncomeGoldReturn.Key(),
|
||
TranTypeInt: int64(txnmod.AiTextToNovelDebitIncomeGoldReturn),
|
||
Desc: fmt.Sprintf("退还AI小说收益金币-%d", info.DebitIncomeCoin),
|
||
RealAmount: walletmod.GetRealAmount(wallet),
|
||
})
|
||
}
|
||
|
||
if len(tl) > 0 {
|
||
txnErr := txnmod.InsertManyTransactionLog(t, tl)
|
||
if txnErr != nil {
|
||
log.Error(fmt.Sprintf("Handle ai text to novel txnmod.InsertTransactionLog error:%+v:", txnErr), log.Any("uid", info.UID))
|
||
return stderr.ErrDbQueryError
|
||
}
|
||
}
|
||
return nil
|
||
}); err != nil {
|
||
if e, ok := err.(stderr.Code); ok {
|
||
return e
|
||
}
|
||
return stderr.ErrDbQueryError
|
||
}
|
||
return nil
|
||
} else {
|
||
if _, err = aitexttonoveldata.UpdateData(nil, p.ID.Hex(), data); err != nil {
|
||
}
|
||
return err
|
||
}
|
||
}
|
||
|
||
type WebDeleteReq struct {
|
||
ID primitive.ObjectID `json:"id" binding:"required"`
|
||
}
|
||
|
||
// Delete 删除数据
|
||
func (p *WebDeleteReq) Delete() error {
|
||
data, err := aitexttonovelmod.GetInfo(p.ID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if err = validateDeleteStatus(data.Status); err != nil {
|
||
return err
|
||
}
|
||
|
||
if err := aitexttonoveldata.DeleteData(nil, p.ID); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func validateDeleteStatus(status int) error {
|
||
if status == int(aitexttonovelmod.StatusOrderSuccess) ||
|
||
status == int(aitexttonovelmod.StatusSubmitted) {
|
||
return stderr.AiGenningDelForbidden
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// CallbackReq 换脸订单回调请求
|
||
type CallbackReq struct {
|
||
Content string `json:"content"` // AI小说内容
|
||
AppOrderNum string `json:"appOrderNum"` // app订单号
|
||
Status int `json:"status"` // 订单状态 1:成功,2:失败
|
||
Msg string `json:"msg"` // 消息
|
||
}
|
||
|
||
func (p *CallbackReq) Callback() error {
|
||
id, _ := primitive.ObjectIDFromHex(p.AppOrderNum)
|
||
// 查询该笔订单是否存在
|
||
data, err := aitexttonovelmod.GetInfo(id)
|
||
if err != nil {
|
||
return stderr.ErrDbQueryError
|
||
}
|
||
|
||
if data.ID.IsZero() {
|
||
return errors.New("ai text to novel data is null")
|
||
}
|
||
|
||
if data.Status != int(aitexttonovelmod.StatusSubmitted) {
|
||
log.Error("AI小说-重复回调或者状态不正确", log.Any("id", data.ID.Hex()), log.Any("status", data.Status))
|
||
return nil
|
||
}
|
||
|
||
var status = aitexttonovelmod.StatusGenerationSuccess
|
||
|
||
// 处理金币退款以及后续操作
|
||
set := bson.M{}
|
||
if p.Content != "" {
|
||
set["content"] = strings.TrimSpace(p.Content)
|
||
}
|
||
if p.Status != 1 {
|
||
set["remark"] = p.Msg
|
||
set["content"] = ""
|
||
status = aitexttonovelmod.StatusGenerationFailed
|
||
}
|
||
set["status"] = status
|
||
set["updatedAt"] = time.Now()
|
||
|
||
switch status {
|
||
case aitexttonovelmod.StatusGenerationSuccess:
|
||
if _, err = aitexttonovelmod.UpdateByID(nil, id, set); err != nil {
|
||
return stderr.ErrDbUpdateError
|
||
}
|
||
return nil
|
||
case aitexttonovelmod.StatusGenerationFailed: // 退款
|
||
if err = webg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||
if _, err = aitexttonovelmod.UpdateByID(t, id, set); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 退款
|
||
if data.DebitAmountCoin == 0 && data.DebitIncomeCoin == 0 { // 总金额为0则不需要退款
|
||
return nil
|
||
}
|
||
|
||
// 退款进入钱包余额
|
||
wallet, err := walletmod.ReturnAmountAndIncome(t, -data.DebitAmountCoin, -data.DebitIncomeCoin, data.UID)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("Handle Callback Edit walletmod.DebitAmount error:%+v:", err), log.Any("uid", data.UID))
|
||
return err
|
||
}
|
||
var tl []txnmod.TransactionLog
|
||
if data.DebitAmountCoin > 0 {
|
||
tl = append(tl, txnmod.TransactionLog{
|
||
TransNo: primitive.NewObjectID(),
|
||
UID: data.UID,
|
||
Amount: data.DebitAmountCoin,
|
||
ActualAmount: float64(data.DebitAmountCoin),
|
||
TranType: txnmod.AiTextToNovelDebitGoldReturn.Key(),
|
||
TranTypeInt: int64(txnmod.AiTextToNovelDebitGoldReturn),
|
||
Desc: fmt.Sprintf("退还AI小说金币-%d", data.DebitAmountCoin),
|
||
RealAmount: walletmod.GetRealAmount(wallet),
|
||
})
|
||
}
|
||
if data.DebitIncomeCoin > 0 {
|
||
tl = append(tl, txnmod.TransactionLog{
|
||
TransNo: primitive.NewObjectID(),
|
||
UID: data.UID,
|
||
Amount: data.DebitIncomeCoin,
|
||
ActualAmount: float64(data.DebitIncomeCoin),
|
||
TranType: txnmod.AiTextToNovelDebitIncomeGoldReturn.Key(),
|
||
TranTypeInt: int64(txnmod.AiTextToNovelDebitIncomeGoldReturn),
|
||
Desc: fmt.Sprintf("退还AI小说收益金币-%d", data.DebitIncomeCoin),
|
||
RealAmount: walletmod.GetRealAmount(wallet),
|
||
})
|
||
}
|
||
|
||
if len(tl) > 0 {
|
||
txnErr := txnmod.InsertManyTransactionLog(t, tl)
|
||
if txnErr != nil {
|
||
log.Error(fmt.Sprintf("Handle ai text to image Callback txnmod.InsertTransactionLog error:%+v:", txnErr), log.Any("uid", data.UID))
|
||
return stderr.ErrDbQueryError
|
||
}
|
||
}
|
||
return nil
|
||
}); err != nil {
|
||
if e, ok := err.(stderr.Code); ok {
|
||
return e
|
||
}
|
||
return stderr.ErrDbQueryError
|
||
}
|
||
return nil
|
||
default:
|
||
}
|
||
return nil
|
||
}
|