@@ -0,0 +1,943 @@
|
||||
/*
|
||||
* @Description: In User Settings Edit
|
||||
* @Author: your name
|
||||
* @Date: 2019-08-29 19:55:45
|
||||
* @LastEditTime: 2019-08-30 19:39:56
|
||||
* @LastEditors: Please set LastEditors
|
||||
*/
|
||||
package walletmod
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDownloadRequestConflict = errors.New("download request id belongs to another resource")
|
||||
ErrDownloadCountNotEnough = errors.New("download count is not enough")
|
||||
ErrDownloadAuthorizationRace = errors.New("download authorization changed concurrently")
|
||||
)
|
||||
|
||||
const maxDownloadRequestHistory = 1000
|
||||
|
||||
var mutex sync.Mutex
|
||||
|
||||
const table = models.Wallet
|
||||
|
||||
func coll(t *db.MongoTool) *db.MongoTool {
|
||||
if t == nil {
|
||||
return mdb.Coll(table)
|
||||
}
|
||||
return t.Coll(table)
|
||||
}
|
||||
|
||||
func initIndex() {
|
||||
many := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{Key: "uid", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
}
|
||||
if _, err := coll(nil).CreateIndex(many); err != nil {
|
||||
panic(fmt.Sprintf("wallet model set index err ==>[%+v]", err))
|
||||
}
|
||||
}
|
||||
|
||||
func InsertWallet(t *db.MongoTool, w *Wallet) error {
|
||||
if _, err := coll(t).InsertOne(w); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertWallet", table, "InsertOne", err),
|
||||
log.Any("w", w),
|
||||
)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetWallet 通过uid,查找用户余额
|
||||
func GetWallet(uid uint64) (w *Wallet, err error) {
|
||||
w = &Wallet{}
|
||||
if err = coll(nil).FindOne(w, bson.M{"uid": uid}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetWallet", table, "FindOne", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetWalletMap(uidList []uint64) (map[uint64]Wallet, error) {
|
||||
if len(uidList) == 0 {
|
||||
return make(map[uint64]Wallet), nil
|
||||
}
|
||||
filter := bson.M{
|
||||
"uid": bson.M{
|
||||
"$in": uidList,
|
||||
},
|
||||
}
|
||||
walletList := make([]Wallet, 0, len(uidList))
|
||||
if err := coll(nil).Find(&walletList, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
walletMap := make(map[uint64]Wallet, len(walletList))
|
||||
for _, wallet := range walletList {
|
||||
walletMap[wallet.UID] = wallet
|
||||
}
|
||||
return walletMap, nil
|
||||
}
|
||||
|
||||
// CreditAmount 货币增加(虚拟货币)
|
||||
func CreditAmount(t *db.MongoTool, amt int64, uid uint64) (*Wallet, error) {
|
||||
w := Wallet{}
|
||||
if err := coll(t).FindOneAndUpsert(&w, bson.M{"uid": uid}, bson.M{
|
||||
"$inc": bson.M{"amount": amt},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditAmount", table, "FindOneAndUpsert", err),
|
||||
log.Any("amt", amt),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// DebitAmount 货币扣除(虚拟货币)
|
||||
func DebitAmount(t *db.MongoTool, amt int64, uid uint64) (*Wallet, error) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
w := Wallet{}
|
||||
if err := coll(t).FindOneAndUpdate(&w, bson.M{"uid": uid, "amount": bson.M{"$gte": amt}}, bson.M{
|
||||
"$inc": bson.M{"amount": -amt}}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitAmount", table, "FindOneAndUpdate", err),
|
||||
log.Any("amt", amt),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("not enough balance")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// CreditIntegral 新增积分
|
||||
func CreditIntegral(t *db.MongoTool, integral int64, uid uint64) (*Wallet, error) {
|
||||
w := Wallet{}
|
||||
if err := coll(t).FindOneAndUpsert(&w, bson.M{"uid": uid}, bson.M{
|
||||
"$inc": bson.M{"integral": integral},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditIntegral", table, "FindOneAndUpsert", err),
|
||||
log.Any("integral", integral),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// DebitIntegral 扣除积分
|
||||
func DebitIntegral(t *db.MongoTool, integral int64, uid uint64) (*Wallet, error) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
w := Wallet{}
|
||||
if err := coll(t).FindOneAndUpdate(&w, bson.M{"uid": uid, "integral": bson.M{"$gte": integral}}, bson.M{
|
||||
"$inc": bson.M{"integral": -integral}}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitIntegral", table, "FindOneAndUpdate", err),
|
||||
log.Any("integral", integral),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("not enough balance")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// 扣除金币
|
||||
// 金币不足则报错
|
||||
func DebitAmountAndCheck(t *db.MongoTool, uid int64, amt int64) error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
result, err := coll(t).UpdateOne(bson.M{"uid": uid, "amount": bson.M{"$gte": amt}}, bson.M{
|
||||
"$inc": bson.M{"amount": -amt}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.ModifiedCount != 1 {
|
||||
return errors.New("金币余额不足")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 扣除金币
|
||||
// 金币不足则报错
|
||||
// 包括普通金币和可提现金币
|
||||
// 先扣除普通金币, 再扣除可提现金币
|
||||
// t 必须已经开启事务!!!
|
||||
func DebitAmountDefault(t *db.MongoTool, uid int64, amt int64) error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
var wallet Wallet
|
||||
if err := coll(t).FindOne(&wallet, bson.M{"uid": uid}); err != nil {
|
||||
return err
|
||||
}
|
||||
if wallet.Amount+wallet.Income < amt {
|
||||
return errors.New("金币余额不足")
|
||||
}
|
||||
if wallet.Amount >= amt {
|
||||
result, err := coll(t).UpdateOne(bson.M{"uid": uid, "amount": bson.M{"$gte": amt}}, bson.M{
|
||||
"$inc": bson.M{"amount": -amt}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.ModifiedCount != 1 {
|
||||
return errors.New("金币余额不足")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
useIncome := amt - wallet.Amount
|
||||
result, err := coll(t).UpdateOne(bson.M{"uid": uid, "amount": wallet.Amount, "income": bson.M{"$gte": useIncome}}, bson.M{
|
||||
"$inc": bson.M{"amount": -wallet.Amount, "income": -useIncome}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.ModifiedCount != 1 {
|
||||
return errors.New("金币余额不足")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAmount 获取金币
|
||||
func GetAmount(t *db.MongoTool, uid uint64) (int64, error) {
|
||||
w := &Wallet{}
|
||||
if err := coll(t).FindOne(w, bson.M{"uid": uid}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetAmount", table, "FindOne", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return 0, err
|
||||
}
|
||||
return w.Amount, nil
|
||||
}
|
||||
|
||||
// GetAmount 获取果币
|
||||
func GetFruitAmount(t *db.MongoTool, uid uint64) (int64, error) {
|
||||
w := &Wallet{}
|
||||
if err := coll(t).FindOne(w, bson.M{"uid": uid}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetAmount", table, "FindOne", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return 0, err
|
||||
}
|
||||
return w.FruitCoin, nil
|
||||
}
|
||||
|
||||
// GetAiMateBalance 获取ai伴侣币余额
|
||||
func GetAiMateBalance(t *db.MongoTool, uid uint64) (float64, error) {
|
||||
w := &Wallet{}
|
||||
if err := coll(t).FindOne(w, bson.M{"uid": uid}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetAmount", table, "FindOne", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return 0, err
|
||||
}
|
||||
return w.AiMateBalance, nil
|
||||
}
|
||||
|
||||
// SetAmount 设置货币(虚拟货币)
|
||||
func SetAmount(t *db.MongoTool, amt int64, uid uint64) error {
|
||||
//写入数据库,待完成
|
||||
if _, err := coll(t).UpdateOne(bson.M{"uid": uid}, bson.M{
|
||||
"$set": bson.M{"amount": amt},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "SetAmount", table, "UpdateOne", err),
|
||||
log.Any("amt", amt),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 返回更新前的值 被删除的商人无法更新
|
||||
func FindUpdate(tool *db.MongoTool, uid uint64, amt int64) (*Wallet, error) {
|
||||
w := Wallet{}
|
||||
opt := &options.FindOneAndUpdateOptions{}
|
||||
opt.SetReturnDocument(options.Before)
|
||||
if err := coll(tool).FindOneAndUpdate(&w, bson.M{"uid": uid}, bson.M{"$set": bson.M{"amount": amt}}, opt); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindUpdate", table, "FindOneAndUpdate", err))
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("wallet not found")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
func Debit(t *db.MongoTool, p *DebitPlan, uid uint64) (*Wallet, error) {
|
||||
if p == nil {
|
||||
return nil, errors.New("wallet nil DebitPlan")
|
||||
}
|
||||
w := &Wallet{}
|
||||
var err error
|
||||
if p.Amount != 0 {
|
||||
w, err = DebitAmount(t, p.Amount, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if p.Income != 0 {
|
||||
w, err = DebitIncome(t, p.Income, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if p.Consumption != 0 {
|
||||
err = CreditConsumption(t, p.Consumption, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if p.DownloadCount != 0 {
|
||||
err = CreditDownloadCount(t, p.DownloadCount, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if p.AiUndressFreeTimes != 0 {
|
||||
w, err = DebitAiFreeTimes(t, p.AiUndressFreeTimes, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if p.LotteryTimes != 0 {
|
||||
w, err = DebitLotteryTimes(t, p.LotteryTimes, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if !w.ID.IsZero() {
|
||||
return w, nil
|
||||
}
|
||||
if err = coll(t).FindOne(w, bson.M{"uid": uid}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("wallet not found")
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// CreditIncomeBasePot
|
||||
func CreditIncomeBasePot(t *db.MongoTool, incomeInt int64, income float64, pot float64, uid uint64) (*Wallet, error) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
var wallet Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&wallet, bson.M{"uid": uid}, bson.M{
|
||||
"$set": bson.M{"incomePot": pot, "vidIncome": income},
|
||||
"$inc": bson.M{"income": incomeInt},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditIncome", table, "FindOneAndUpdate", err),
|
||||
log.Any("income", income),
|
||||
log.Any("incomePot", pot),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return &wallet, nil
|
||||
}
|
||||
|
||||
// CreditIncomeBasePotWithReward
|
||||
func CreditIncomeBasePotWithReward(t *db.MongoTool, incomeInt int64, rewardIncome decimal.Decimal, pot float64, uid uint64) (*Wallet, error) {
|
||||
var w Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&w, bson.M{"uid": uid}, bson.M{
|
||||
"$set": bson.M{"incomePot": pot},
|
||||
"$inc": bson.M{"income": incomeInt, "rewardIncome": rewardIncome},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditIncome", table, "FindOneAndUpsert", err),
|
||||
log.Any("income", incomeInt),
|
||||
log.Any("incomePot", pot),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// CreditDebIncome 累计扣量金币 增加
|
||||
func CreditDebIncome(t *db.MongoTool, income string, uid uint64) error {
|
||||
debIncr, _ := primitive.ParseDecimal128(income)
|
||||
//写入数据库,待完成
|
||||
res, err := coll(t).UpsertOne(bson.M{"uid": uid}, bson.M{
|
||||
"$inc": bson.M{"dedIncome": debIncr},
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditDebIncome", table, "UpsertOne", err),
|
||||
log.Any("income", income),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return err
|
||||
}
|
||||
if res.UpsertedCount != 1 && res.ModifiedCount != 1 {
|
||||
return errors.New("Invalid account")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreditIncome 货币增加
|
||||
func CreditIncome(t *db.MongoTool, income int64, uid uint64) (*Wallet, error) {
|
||||
var w Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&w, bson.M{"uid": uid}, bson.M{
|
||||
"$inc": bson.M{"income": income},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditIncome", table, "FindOneAndUpsert", err),
|
||||
log.Any("income", income),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// DebitIncome 货币扣除
|
||||
func DebitIncome(t *db.MongoTool, income int64, uid uint64) (*Wallet, error) {
|
||||
var w Wallet
|
||||
if err := coll(t).FindOneAndUpdate(&w, bson.M{"uid": uid, "income": bson.M{"$gte": income}}, bson.M{
|
||||
"$inc": bson.M{"income": -income},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitIncome", table, "FindOneAndUpdate", err),
|
||||
log.Any("income", income),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("wallet not found")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// CreditFruitCoin 果币增加
|
||||
func CreditFruitCoin(t *db.MongoTool, uid uint64, fruitCoin int64) (*Wallet, error) {
|
||||
var item *Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&item, bson.M{"uid": uid}, bson.M{"$inc": bson.M{"fruitCoin": fruitCoin}}); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditFruitCoin", table, "FindOneAndUpsert", err),
|
||||
log.Any("fruitCoin", fruitCoin),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// UpdateAiMateBalance ai伴侣币修改
|
||||
func UpdateAiMateBalance(t *db.MongoTool, uid uint64, aiMateBalance float64) (*Wallet, error) {
|
||||
var item *Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&item, bson.M{"uid": uid}, bson.M{"$set": bson.M{"aiMateBalance": aiMateBalance}}); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateAiMateBalance", table, "FindOneAndUpsert", err),
|
||||
log.Any("aiMateBalance", aiMateBalance),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// DebitFruitCoin 果币减少
|
||||
func DebitFruitCoin(t *db.MongoTool, uid uint64, fruitCoin int64) (*Wallet, error) {
|
||||
var item *Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&item, bson.M{"uid": uid}, bson.M{"$inc": bson.M{"fruitCoin": -fruitCoin}}); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitFruitCoin", table, "FindOneAndUpsert", err),
|
||||
log.Any("fruitCoin", -fruitCoin),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// CreditNudeChatIncome 裸聊收益增加
|
||||
func CreditNudeChatIncome(t *db.MongoTool, uid uint64, nudeChatIncome int64) (*Wallet, error) {
|
||||
var item *Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&item, bson.M{"uid": uid}, bson.M{"$inc": bson.M{
|
||||
"nudeChatIncome": decimal.NewFromInt(nudeChatIncome),
|
||||
"income": nudeChatIncome,
|
||||
}}); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditNudeChatIncome", table, "FindOneAndUpsert", err),
|
||||
log.Any("nudeChatIncome", nudeChatIncome),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// DebitNudeChatIncome 裸聊收益减少
|
||||
func DebitNudeChatIncome(t *db.MongoTool, uid uint64, nudeChatIncome int64) (*Wallet, error) {
|
||||
var item *Wallet
|
||||
if err := coll(t).FindOneAndUpsert(&item, bson.M{"uid": uid}, bson.M{"$inc": bson.M{
|
||||
"nudeChatIncome": decimal.NewFromInt(-nudeChatIncome),
|
||||
"income": -nudeChatIncome,
|
||||
}}); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitNudeChatIncome", table, "FindOneAndUpsert", err),
|
||||
log.Any("nudeChatIncome", nudeChatIncome),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// CreditMoney 货币增加
|
||||
func CreditMoney(t *db.MongoTool, money int64, uid uint64) error {
|
||||
//写入数据库,待完成
|
||||
res, err := coll(t).UpsertOne(bson.M{"uid": uid}, bson.M{
|
||||
"$inc": bson.M{"money": money},
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditMoney", table, "UpsertOne", err),
|
||||
log.Any("money", money),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return err
|
||||
}
|
||||
if res.UpsertedCount != 1 && res.ModifiedCount != 1 {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditMoney", table, "errors.New", "Invalid account"),
|
||||
log.Any("money", money),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return errors.New("Invalid account")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DebitMoney 货币扣除
|
||||
func DebitMoney(t *db.MongoTool, money int64, uid uint64) (*Wallet, error) {
|
||||
w := Wallet{}
|
||||
if err := coll(t).FindOneAndUpdate(&w, bson.M{"uid": uid, "money": bson.M{"$gte": money}}, bson.M{
|
||||
"$inc": bson.M{"money": -money},
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitMoney", table, "FindOneAndUpdate", err),
|
||||
log.Any("money", money),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("not enough balance")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// CreditConsumption 总充值增加
|
||||
func CreditConsumption(t *db.MongoTool, money int64, uid uint64) error {
|
||||
res, err := coll(t).UpsertOne(bson.M{
|
||||
"uid": uid,
|
||||
}, bson.M{
|
||||
"$inc": bson.M{
|
||||
"consumption": money,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditConsumption", table, "UpsertOne", err),
|
||||
log.Any("money", money),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return err
|
||||
}
|
||||
if res.UpsertedCount != 1 && res.ModifiedCount != 1 {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditConsumption", table, "errors.New", "Invalid account"),
|
||||
log.Any("money", money),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return errors.New("Invalid account")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreditDownloadCount 总下载次数加
|
||||
func CreditDownloadCount(t *db.MongoTool, downloadCount int64, uid uint64) error {
|
||||
res, err := coll(t).UpsertOne(bson.M{"uid": uid}, bson.M{"$inc": bson.M{"downloadCount": -downloadCount}})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditDownloadCount", table, "UpsertOne", err),
|
||||
log.Any("downloadCount", downloadCount),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return err
|
||||
}
|
||||
if res.UpsertedCount != 1 && res.ModifiedCount != 1 {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditDownloadCount", table, "errors.New", "Invalid account"),
|
||||
log.Any("downloadCount", downloadCount),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return errors.New("update DownloadCount err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Find(filter bson.M) ([]*Wallet, error) {
|
||||
ws := make([]*Wallet, 0)
|
||||
if err := coll(nil).Find(&ws, filter); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Find", table, "Find", err),
|
||||
log.Any("filter", filter),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return ws, nil
|
||||
}
|
||||
|
||||
// Credit 货币增加(虚拟货币)
|
||||
func Credit(t *db.MongoTool, creditPlan CreditPlan, uid uint64) (*Wallet, error) {
|
||||
w := Wallet{}
|
||||
if err := coll(t).FindOneAndUpsert(&w, bson.M{"uid": uid}, bson.M{
|
||||
"$inc": creditPlan,
|
||||
}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CreditAmount", table, "FindOneAndUpsert", err),
|
||||
log.Any("creditPlan", creditPlan),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// DescCredit 货币扣除(虚拟货币)
|
||||
func DescCredit(t *db.MongoTool, creditPlan CreditPlan, uid uint64) (wallet *Wallet, err error) {
|
||||
filter := bson.M{"uid": uid}
|
||||
if creditPlan.Income != nil {
|
||||
filter["income"] = bson.M{"$gte": creditPlan.Income}
|
||||
}
|
||||
if creditPlan.Amount != nil {
|
||||
filter["amount"] = bson.M{"$gte": creditPlan.Amount}
|
||||
}
|
||||
if creditPlan.LotteryTimes != nil {
|
||||
filter["lotteryTimes"] = bson.M{"$gte": creditPlan.LotteryTimes}
|
||||
}
|
||||
err = coll(t).FindOneAndUpsert(&wallet, filter, bson.M{
|
||||
"$inc": creditPlan,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DescCredit", table, "FindOneAndUpsert", err),
|
||||
log.Any("creditPlan", creditPlan),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 抽奖预扣
|
||||
func AddFreeze(userId uint64, amt int64) (*Wallet, error) {
|
||||
filter := bson.M{
|
||||
"uid": userId,
|
||||
"amount": bson.M{"$gte": amt},
|
||||
}
|
||||
inc := bson.M{
|
||||
"amount": -amt,
|
||||
"freezeAmount": amt,
|
||||
}
|
||||
w := Wallet{}
|
||||
if err := coll(nil).FindOneAndUpdate(&w, filter, bson.M{"$inc": inc}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DrawFreeze", table, "FindOneAndUpdate", err),
|
||||
log.Any("uid", userId),
|
||||
log.Any("amt", amt),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("not enough balance")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// 扣除预扣
|
||||
func CutFreeze(t *db.MongoTool, userId uint64, amt, amount int64) (*Wallet, error) {
|
||||
filter := bson.M{
|
||||
"uid": userId,
|
||||
"freezeAmount": bson.M{"$gte": amt},
|
||||
}
|
||||
inc := bson.M{
|
||||
"freezeAmount": -amt,
|
||||
"amount": amount,
|
||||
}
|
||||
w := Wallet{}
|
||||
if err := coll(nil).FindOneAndUpdate(&w, filter, bson.M{"$inc": inc}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CutFreeze", table, "FindOneAndUpdate", err),
|
||||
log.Any("uid", userId),
|
||||
log.Any("amt", amt),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("not enough balance")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) RealAmount() decimal.Decimal {
|
||||
return decimal.NewFromInt(w.Amount).Add(decimal.NewFromInt(w.Income)).
|
||||
Add(decimal.NewFromFloat(w.IncomePot)).Add(decimal.NewFromInt(w.Money))
|
||||
}
|
||||
|
||||
func GetRealAmount(w *Wallet) decimal.Decimal {
|
||||
if w == nil {
|
||||
return decimal.Decimal{}
|
||||
}
|
||||
return decimal.NewFromInt(w.Amount).Add(decimal.NewFromInt(w.Income)).
|
||||
Add(decimal.NewFromFloat(w.IncomePot)).Add(decimal.NewFromInt(w.Money))
|
||||
}
|
||||
|
||||
func (w *Wallet) RealIntegral() decimal.Decimal {
|
||||
if w != nil && w.Integral != 0 {
|
||||
return decimal.NewFromInt(w.Integral)
|
||||
} else {
|
||||
return decimal.NewFromInt(0)
|
||||
}
|
||||
}
|
||||
|
||||
func UpsertOne(t *db.MongoTool, filter bson.M, update bson.M) error {
|
||||
if _, err := coll(t).UpsertOne(filter, update); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "update", table, "updateOne", err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func BulkWrite(t *db.MongoTool, models []mongo.WriteModel, opts ...*options.BulkWriteOptions) error {
|
||||
if _, err := coll(t).Bulk(models, opts...); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "update", table, "updateOne", err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IncUsdtAmount usdt可提现额度加减
|
||||
func IncUsdtAmount(userId uint64, usdtAmount int64) (*Wallet, error) {
|
||||
filter := bson.M{"uid": userId}
|
||||
if usdtAmount < 0 {
|
||||
filter["usdtAmount"] = bson.M{"$gte": 0}
|
||||
}
|
||||
inc := bson.M{"usdtAmount": usdtAmount}
|
||||
var w Wallet
|
||||
if err := coll(nil).FindOneAndUpdate(&w, filter, bson.M{"$inc": inc}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncUsdtAmount", table, "FindOneAndUpdate", err),
|
||||
log.Any("uid", userId),
|
||||
log.Any("amt", usdtAmount),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
if w.ID.IsZero() {
|
||||
return nil, errors.New("wallet not found")
|
||||
}
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// AddUsdtAmount 增加usdt可提现额度
|
||||
func AddUsdtAmount(t *db.MongoTool, userId uint64, usdtAmount int64) error {
|
||||
result, err := coll(t).UpdateOne(bson.M{"uid": userId}, bson.M{"$inc": bson.M{"usdtAmount": usdtAmount}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.ModifiedCount == 0 {
|
||||
return errors.New("result.ModifiedCount is 0")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsRechargeUser 是否充值用户
|
||||
func IsRechargeUser(t *db.MongoTool, uid uint64) bool {
|
||||
w := &Wallet{}
|
||||
if err := coll(t).FindOne(w, bson.M{"uid": uid}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsRechargeUser", table, "FindOne", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return false
|
||||
}
|
||||
if w.ID.IsZero() || w.Consumption <= 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// DebitAmountAndIncome 货币扣除(虚拟货币)
|
||||
func DebitAmountAndIncome(t *db.MongoTool, amt, income int64, uid uint64) (wallet *Wallet, err error) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
filter := bson.M{"uid": uid}
|
||||
update := bson.M{}
|
||||
if amt > 0 {
|
||||
filter["amount"] = bson.M{"$gte": amt}
|
||||
update["amount"] = -amt
|
||||
}
|
||||
if income > 0 {
|
||||
filter["income"] = bson.M{"$gte": income}
|
||||
update["income"] = -income
|
||||
}
|
||||
|
||||
err = coll(t).FindOneAndUpdate(&wallet, filter, bson.M{"$inc": update})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitAmountAndIncome", table, "FindOneAndUpdate", err),
|
||||
log.Any("filter", filter),
|
||||
log.Any("update", update),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ReturnAmountAndIncome 货币返回(虚拟货币)
|
||||
func ReturnAmountAndIncome(t *db.MongoTool, amt, income int64, uid uint64) (wallet *Wallet, err error) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
filter := bson.M{"uid": uid}
|
||||
update := bson.M{}
|
||||
if -amt > 0 {
|
||||
update["amount"] = -amt
|
||||
}
|
||||
if -income > 0 {
|
||||
update["income"] = -income
|
||||
}
|
||||
|
||||
err = coll(t).FindOneAndUpdate(&wallet, filter, bson.M{"$inc": update})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "ReturnAmountAndIncome", table, "FindOneAndUpdate", err),
|
||||
log.Any("filter", filter),
|
||||
log.Any("update", update),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DebitAiFreeTimes 扣出AI脱衣次数
|
||||
func DebitAiFreeTimes(t *db.MongoTool, freeTimes int64, uid uint64) (wallet *Wallet, err error) {
|
||||
filter := bson.M{"uid": uid}
|
||||
if freeTimes > 0 {
|
||||
filter["aiUndressFreeTimes"] = bson.M{"$gte": freeTimes}
|
||||
}
|
||||
err = coll(t).FindOneAndUpsert(&wallet, filter, bson.M{"$inc": bson.M{"aiUndressFreeTimes": -freeTimes}})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitAiFreeTimes", table, "FindOneAndUpdate", err),
|
||||
log.Any("freeTimes", freeTimes),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DebitDownloadCounts 扣出下载次数
|
||||
func DebitDownloadCounts(t *db.MongoTool, downloadCount int64, uid uint64) (wallet *Wallet, err error) {
|
||||
filter := bson.M{"uid": uid}
|
||||
if downloadCount > 0 {
|
||||
filter["downloadCount"] = bson.M{"$gte": downloadCount}
|
||||
}
|
||||
err = coll(t).FindOneAndUpsert(&wallet, filter, bson.M{"$inc": bson.M{"downloadCount": -downloadCount}})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitAiDownloadCount", table, "FindOneAndUpdate", err),
|
||||
log.Any("downloadCount", downloadCount),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AuthorizeDramaDownload atomically records one idempotency key and debits one
|
||||
// shared download count. The bounded wallet history covers retries even if an
|
||||
// App instance or Redis cache restarts.
|
||||
func AuthorizeDramaDownload(t *db.MongoTool, uid uint64, requestKey, fingerprint string, now time.Time) (*Wallet, bool, error) {
|
||||
wallet := &Wallet{}
|
||||
if err := coll(t).FindOne(wallet, bson.M{"uid": uid}); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
for _, request := range wallet.DownloadRequests {
|
||||
if request.RequestKey != requestKey {
|
||||
continue
|
||||
}
|
||||
if request.Fingerprint != fingerprint {
|
||||
return nil, false, ErrDownloadRequestConflict
|
||||
}
|
||||
return wallet, false, nil
|
||||
}
|
||||
if wallet.DownloadCount <= 0 {
|
||||
return nil, false, ErrDownloadCountNotEnough
|
||||
}
|
||||
record := DownloadRequest{RequestKey: requestKey, Fingerprint: fingerprint, CreatedAt: now}
|
||||
filter := bson.M{
|
||||
"uid": uid, "downloadCount": bson.M{"$gte": 1},
|
||||
"downloadRequests.requestKey": bson.M{"$ne": requestKey},
|
||||
}
|
||||
update := bson.M{
|
||||
"$inc": bson.M{"downloadCount": -1},
|
||||
"$push": bson.M{"downloadRequests": bson.M{
|
||||
"$each": []DownloadRequest{record}, "$slice": -maxDownloadRequestHistory,
|
||||
}},
|
||||
}
|
||||
updated := &Wallet{}
|
||||
if err := coll(t).FindOneAndUpdate(updated, filter, update); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if updated.UID == 0 {
|
||||
return nil, false, ErrDownloadAuthorizationRace
|
||||
}
|
||||
return updated, true, nil
|
||||
}
|
||||
|
||||
// DebitLotteryTimes 扣出抽奖次数
|
||||
func DebitLotteryTimes(t *db.MongoTool, lotteryTimes int64, uid uint64) (wallet *Wallet, err error) {
|
||||
filter := bson.M{"uid": uid}
|
||||
if lotteryTimes > 0 {
|
||||
filter["lotteryTimes"] = bson.M{"$gte": lotteryTimes}
|
||||
}
|
||||
err = coll(t).FindOneAndUpsert(&wallet, filter, bson.M{"$inc": bson.M{"lotteryTimes": -lotteryTimes}})
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DebitAiDownloadCount", table, "FindOneAndUpdate", err),
|
||||
log.Any("downloadCount", lotteryTimes),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Credit ai伴侣货币增加(虚拟货币)
|
||||
func CreditAiMate(t *db.MongoTool, amt float64, uid uint64, aiMateOrderId string) (wallet *Wallet, err error) {
|
||||
update := bson.M{"$inc": bson.M{"aiMateBalance": amt}}
|
||||
if amt < 0 && aiMateOrderId != "" {
|
||||
update["$set"] = bson.M{"lastAiMateRecordId": aiMateOrderId}
|
||||
}
|
||||
if err = coll(t).FindOneAndUpsert(&wallet, bson.M{"uid": uid}, update); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-CreditAmount]==> Model %s FindOneAndUpsert fail error:%+v:", table, err),
|
||||
log.Any("aiMateBalance", amt),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 重新设置用户ai积分
|
||||
func SetAiMateBalance(t *db.MongoTool, uid uint64, aiMateBalance float64) error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
_, err := coll(t).UpsertOne(bson.M{"uid": uid}, bson.M{"$set": bson.M{"aiMateBalance": aiMateBalance}})
|
||||
return err
|
||||
}
|
||||
|
||||
// GetIntegral 获取积分
|
||||
func GetIntegral(t *db.MongoTool, uid uint64) (int64, error) {
|
||||
w := &Wallet{}
|
||||
if err := coll(t).FindOne(w, bson.M{"uid": uid}); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetAmount", table, "FindOne", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return 0, err
|
||||
}
|
||||
return w.Integral, nil
|
||||
}
|
||||
Reference in New Issue
Block a user