You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
418 lines
10 KiB
418 lines
10 KiB
package anchorReward |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"go-common/app/service/live/xrewardcenter/conf" |
|
AnchorTaskModel "go-common/app/service/live/xrewardcenter/model/anchorTask" |
|
model "go-common/app/service/live/xrewardcenter/model/anchorTask" |
|
"go-common/library/cache/memcache" |
|
"go-common/library/cache/redis" |
|
"go-common/library/database/orm" |
|
xsql "go-common/library/database/sql" |
|
"go-common/library/log" |
|
xtime "go-common/library/time" |
|
"math" |
|
"time" |
|
|
|
"bytes" |
|
"encoding/json" |
|
bm "go-common/library/net/http/blademaster" |
|
"io/ioutil" |
|
"net/http" |
|
"strconv" |
|
|
|
"github.com/jinzhu/gorm" |
|
) |
|
|
|
// OrderExist . |
|
const ( |
|
// 缓存过期时间 |
|
rewardConfExpire = 3600 |
|
rewardConfPrefix = "rconf_v1_%d" |
|
) |
|
|
|
// Dao dao |
|
type Dao struct { |
|
c *conf.Config |
|
mc *memcache.Pool |
|
redis *redis.Pool |
|
orm *gorm.DB |
|
db *xsql.DB |
|
keyRewardConfExpire int32 |
|
client *bm.Client |
|
} |
|
|
|
// New init mysql db |
|
func New(c *conf.Config) (dao *Dao) { |
|
dao = &Dao{ |
|
c: c, |
|
mc: memcache.NewPool(c.Memcache), |
|
redis: redis.NewPool(c.Redis), |
|
db: xsql.NewMySQL(c.MySQL), |
|
orm: orm.NewMySQL(c.ORM), |
|
keyRewardConfExpire: rewardConfExpire, |
|
client: bm.NewClient(c.HTTPClient), |
|
} |
|
dao.initORM() |
|
return |
|
} |
|
|
|
func keyRewardConf(id int64) string { |
|
return fmt.Sprintf(rewardConfPrefix, id) |
|
} |
|
|
|
func (d *Dao) initORM() { |
|
d.orm.LogMode(true) |
|
d.orm.SingularTable(true) |
|
} |
|
|
|
//go:generate $GOPATH/src/go-common/app/tool/cache/gen |
|
type _cache interface { |
|
// cache: -sync=true -nullcache=&model.AnchorRewardConf{ID:-1} -check_null_code=$.ID==-1 |
|
RewardConf(c context.Context, id int64) (*model.AnchorRewardConf, error) |
|
} |
|
|
|
//go:generate $GOPATH/src/go-common/app/tool/cache/mc |
|
type _mc interface { |
|
// 获取奖励配置 |
|
// mc: -key=keyRewardConf |
|
CacheRewardConf(c context.Context, id int64) (*model.AnchorRewardConf, error) |
|
|
|
// 保存奖励配置 |
|
// mc: -key=keyRewardConf -expire=d.keyRewardConfExpire -encode=json|gzip |
|
AddCacheRewardConf(c context.Context, id int64, value *model.AnchorRewardConf) error |
|
} |
|
|
|
// AddReward add Reward to a user. |
|
func (d *Dao) AddReward(c context.Context, iRewardID int64, uid int64, iSource int64, iRoomid int64, iLifespan int64) (err error) { |
|
//aReward, _ := getRewardConfByLid(iRewardID) |
|
|
|
m, _ := time.ParseDuration(fmt.Sprintf("+%dh", iLifespan)) |
|
|
|
arg := &AnchorTaskModel.AnchorReward{ |
|
Uid: uid, |
|
RewardId: iRewardID, |
|
Roomid: iRoomid, |
|
Source: iSource, |
|
AchieveTime: xtime.Time(time.Now().Unix()), |
|
ExpireTime: xtime.Time(time.Now().Add(m).Unix()), |
|
Status: model.RewardUnUsed, |
|
} |
|
|
|
//spew.Dump |
|
// (arg) |
|
if err := d.orm.Create(arg).Error; err != nil { |
|
log.Error("addReward(%v) error(%v)", arg, err) |
|
return err |
|
} |
|
|
|
if err := d.SetNewReward(c, uid, int64(1)); err != nil { |
|
log.Error("addRewardMc(%v) error(%v)", uid, err) |
|
} |
|
|
|
if err := d.SetHasReward(c, uid, int64(1)); err != nil { |
|
log.Error("SetHasReward(%v) error(%v)", uid, err) |
|
} |
|
|
|
log.Info("addReward (%v) succ", arg) |
|
|
|
return |
|
} |
|
|
|
//GetByUidPage get reward by uid and page. |
|
func (d *Dao) GetByUidPage(c context.Context, uid int64, page int64, pageSize int64, status []int64) (pager *model.AnchorRewardPager, list []*model.AnchorRewardObject, err error) { |
|
err = nil |
|
pager = &model.AnchorRewardPager{} |
|
list = []*model.AnchorRewardObject{} |
|
|
|
var ( |
|
Items []*AnchorTaskModel.AnchorReward |
|
count int64 |
|
) |
|
iOffSet := (page - 1) * pageSize |
|
|
|
db := d.orm.Where("status in (?)", status).Where("uid=?", uid) |
|
db.Model(&AnchorTaskModel.AnchorReward{}).Count(&count) |
|
|
|
if err = db.Model(&AnchorTaskModel.AnchorReward{}).Limit(pageSize).Offset(iOffSet).Order("mtime DESC, id").Find(&Items).Error; err != nil { |
|
log.Error("get ap_anchor_task_reward_list uid(%v) error(%v)", uid, err) |
|
return |
|
} |
|
|
|
for _, v := range Items { |
|
aReward, err := d.RewardConf(c, v.RewardId) |
|
if err != nil { |
|
log.Error("RewardConf(%v) error(%v)", v.RewardId, err) |
|
return pager, list, err |
|
} |
|
|
|
if aReward == nil { |
|
continue |
|
} |
|
|
|
aListItem := &model.AnchorRewardObject{ |
|
Id: v.Id, |
|
RewardType: aReward.RewardType, |
|
Status: v.Status, |
|
RewardId: v.RewardId, |
|
Name: aReward.Name, |
|
Icon: aReward.Icon, |
|
AchieveTime: v.AchieveTime.Time().Format("2006-01-02 15:04:05"), |
|
ExpireTime: v.ExpireTime.Time().Format("2006-01-02 15:04:05"), |
|
UseTime: v.UseTime.Time().Format("2006-01-02 15:04:05"), |
|
Source: v.Source, |
|
RewardIntro: aReward.RewardIntro, |
|
} |
|
|
|
list = append(list, aListItem) |
|
} |
|
pager = &model.AnchorRewardPager{ |
|
Page: page, |
|
PageSize: pageSize, |
|
TotalPage: int64(math.Ceil(float64(count) / float64(pageSize))), |
|
TotalCount: count, |
|
} |
|
|
|
return |
|
} |
|
|
|
// Ping dao ping |
|
func (d *Dao) Ping(c context.Context) (err error) { |
|
if d.orm != nil { |
|
d.orm.DB().PingContext(c) |
|
} |
|
|
|
err = d.pingMC(c) |
|
return |
|
} |
|
|
|
// GetById get reward by id. |
|
func (d *Dao) GetById(id int64) (reward *model.AnchorReward, err error) { |
|
rewards := []*model.AnchorReward{} |
|
if err := d.orm.Model(&model.AnchorReward{}).Find(&rewards, "id=?", id).Error; err != nil { |
|
log.Error("getRewardById (%v) error(%v)", id, err) |
|
return reward, err |
|
} |
|
if len(rewards) != 0 { |
|
reward = rewards[0] |
|
} |
|
|
|
return |
|
} |
|
|
|
// UseReward use reward by id. |
|
func (d *Dao) UseReward(id int64, usePlat string) (rst bool, err error) { |
|
if err := d.orm. |
|
Model(&model.AnchorReward{}). |
|
Where("id=?", id). |
|
Update(map[string]interface{}{"status": model.RewardUsed, "use_plat": usePlat, "use_time": xtime.Time(time.Now().Unix())}).Error; err != nil { |
|
log.Error("useReward (%v) error(%v)", id, err) |
|
return rst, err |
|
} |
|
rst = true |
|
return |
|
} |
|
|
|
// HasNewReward . |
|
func (d *Dao) HasNewReward(c context.Context, uid int64) (rst int64, err error) { |
|
rst, _ = d.GetNewReward(c, uid) |
|
return |
|
} |
|
|
|
func (d *Dao) findByUid(uid int64, limitOne bool) (reward *model.AnchorReward, err error) { |
|
rewards := []*model.AnchorReward{} |
|
db := d.orm.Where("uid=?", uid) |
|
|
|
if limitOne { |
|
db = db.Limit(1) |
|
} |
|
|
|
if err := db.Model(&model.AnchorReward{}).Find(&rewards).Error; err != nil { |
|
log.Error("getRewardById (%v) error(%v)", uid, err) |
|
return reward, err |
|
} |
|
if len(rewards) != 0 { |
|
reward = rewards[0] |
|
} |
|
|
|
return |
|
} |
|
|
|
// HasReward returns if a user have reward. |
|
func (d *Dao) HasReward(c context.Context, uid int64) (r int64, err error) { |
|
rst, err := d.GetHasReward(c, uid) |
|
if err != nil { |
|
if err == memcache.ErrNotFound { |
|
reward, err2 := d.findByUid(uid, true) |
|
if err2 != nil { |
|
return rst, err2 |
|
} |
|
if reward != nil { |
|
rst = int64(1) |
|
d.SetHasReward(c, uid, rst) |
|
} else { |
|
rst = int64(0) |
|
d.SetHasReward(c, uid, rst) |
|
} |
|
return rst, err |
|
} |
|
log.Error("HasReward(%v) error(%v)", uid, err) |
|
return rst, err |
|
} |
|
return rst, err |
|
} |
|
|
|
// CheckOrderID check orderid is valid. |
|
func (d *Dao) CheckOrderID(c context.Context, id string) (exist int64, err error) { |
|
exist = 0 |
|
if exist, err = d.GetOrder(c, id); err != nil { |
|
//spew.Dump(exist, err) |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
return exist, err |
|
} |
|
return exist, err |
|
} |
|
|
|
// SaveOrderID save order id. |
|
func (d *Dao) SaveOrderID(c context.Context, id string) error { |
|
err := d.SaveOrder(c, id) |
|
return err |
|
} |
|
|
|
// SetExpire . |
|
func (d *Dao) SetExpire(now time.Time) (err error) { |
|
var ( |
|
db = d.orm |
|
) |
|
|
|
setMap := map[string]interface{}{ |
|
"status": model.RewardExpired, |
|
} |
|
|
|
if err = db.Model(model.AnchorReward{}). |
|
Where("status=? AND reward_id = ? AND expire_time <= ?", model.RewardUnUsed, 1, now.Format("2006-01-02 15:04:05")). |
|
Update(setMap). |
|
Error; err != nil { |
|
log.Error("SetExpire (%v) error(%v)", setMap, err) |
|
return err |
|
} |
|
return |
|
} |
|
|
|
// CountExpire . |
|
func (d *Dao) CountExpire(interval int64, now time.Time) (err error) { |
|
var ( |
|
c = context.TODO() |
|
db = d.orm |
|
result = &[]model.AnchorReward{} |
|
) |
|
|
|
dur, _ := time.ParseDuration("-" + strconv.FormatInt(interval, 10) + "s") |
|
begin := now.Add(dur) |
|
|
|
//spew.Dump(begin.Format("2006-01-02 15:04:05")) |
|
//spew.Dump(now.Format("2006-01-02 15:04:05")) |
|
sqlTemp := |
|
"SELECT * FROM ap_anchor_task_reward_list WHERE status = ? AND expire_time > ? AND expire_time <= ? AND reward_id= ?" |
|
|
|
db.Raw(sqlTemp, |
|
model.RewardExpired, |
|
begin.Format("2006-01-02 15:04:05"), |
|
now.Format("2006-01-02 15:04:05"), |
|
1).Scan(&result) |
|
|
|
for _, v := range *result { |
|
d.AddExpireCountCache(c, fmt.Sprintf(model.CountExpireUserKey, v.Uid), model.ExpireCountTime) |
|
} |
|
return |
|
} |
|
|
|
// SendBroadcastV2 . |
|
func (d *Dao) SendBroadcastV2(c context.Context, uid int64, roomid int64, rewardId int64) (err error) { |
|
log.Info("send reward broadcast begin:%d", roomid) |
|
|
|
var endPoint string = fmt.Sprintf("http://live-dm.bilibili.co/dm/1/push?cid=%d&ensure=1", roomid) |
|
|
|
postJson := make(map[string]interface{}) |
|
postJson["cmd"] = "new_anchor_reward" |
|
postJson["uid"] = uid |
|
postJson["roomid"] = roomid |
|
postJson["reward_id"] = rewardId |
|
|
|
bytesData, err := json.Marshal(postJson) |
|
if err != nil { |
|
log.Error("json.Marshal(%v) error(%v)", postJson, err) |
|
return |
|
} |
|
|
|
req, err := http.NewRequest("POST", endPoint, bytes.NewReader(bytesData)) |
|
|
|
req.Header.Add("Content-Type", "application/json") |
|
|
|
if err != nil { |
|
log.Error("http.NewRequest(%v) url(%v) error(%v)", postJson, endPoint, err) |
|
return |
|
} |
|
|
|
var v interface{} |
|
|
|
if err = d.client.Do(c, req, v); err != nil { |
|
log.Error("s.client.Do error(%v) res (%v)", err, v) |
|
return |
|
} |
|
log.Info("s.client.Do endpoint (%v) req (%v) res (%v)", endPoint, postJson, v) |
|
|
|
return |
|
} |
|
|
|
// SendBroadcast . |
|
func (d *Dao) SendBroadcast(uid int64, roomid int64, rewardId int64) (err error) { |
|
log.Info("send reward broadcast begin:%d", roomid) |
|
|
|
var endPoint = fmt.Sprintf("http://live-dm.bilibili.co/dm/1/push?cid=%d&ensure=1", roomid) |
|
|
|
postJson := make(map[string]interface{}) |
|
postJson["cmd"] = "new_anchor_reward" |
|
postJson["uid"] = uid |
|
postJson["roomid"] = roomid |
|
postJson["reward_id"] = rewardId |
|
|
|
bytesData, err := json.Marshal(postJson) |
|
if err != nil { |
|
log.Error("json.Marshal(%v) error(%v)", postJson, err) |
|
return |
|
} |
|
|
|
req, err := http.NewRequest("POST", endPoint, bytes.NewReader(bytesData)) |
|
|
|
req.Header.Add("Content-Type", "application/json") |
|
|
|
if err != nil { |
|
log.Error("http.NewRequest(%v) url(%v) error(%v)", postJson, endPoint, err) |
|
return |
|
} |
|
|
|
client := http.Client{ |
|
Timeout: time.Second, |
|
} |
|
|
|
// use httpClient to send request |
|
response, err := client.Do(req) |
|
|
|
if err != nil { |
|
log.Error("sending request to API endpoint(%v) error(%v)", req, err) |
|
return |
|
} |
|
|
|
body, err := ioutil.ReadAll(response.Body) |
|
if err != nil { |
|
log.Error("parse resp body(%v) error(%v)", body, err) |
|
} |
|
|
|
log.Info("send reward broadcast end:%d", roomid) |
|
|
|
return |
|
}
|
|
|