Files
huya-go/internal/huya/activity.go
T

622 lines
16 KiB
Go

package huya
import (
"math"
"strconv"
"strings"
"huya-go/internal/taf"
)
const (
ActivityWebUA = "web&1.0&huya"
ActivityRecordUA = "webh5&1.0.0&huya"
ActivityBindUA = "pc&1.0.0&huya"
ServantWebActUI = "webActUI"
FuncGetUserScore = "getUserScore"
FuncPrizeList = "getActPrizeList"
FuncPrizeRecords = "getUserPrizeRecords"
FuncExchangePrize = "scoreExchangePrize"
)
type ActivityUserID struct {
UID int64 `json:"uid"`
GUID string `json:"guid,omitempty"`
Token string `json:"token,omitempty"`
HuyaUA string `json:"huya_ua"`
Cookie string `json:"-"`
TokenType int32 `json:"token_type"`
DeviceInfo string `json:"device_info,omitempty"`
}
func NewActivityUserID(uid int64, cookie, ua string) ActivityUserID {
return ActivityUserID{
UID: uid,
HuyaUA: ua,
Cookie: NormalizeCookie(cookie),
TokenType: 0,
}
}
func (u *ActivityUserID) WriteTo(w *taf.Writer) error {
if err := w.WriteInt64(0, u.UID); err != nil {
return err
}
if err := w.WriteString(1, u.GUID); err != nil {
return err
}
if err := w.WriteString(2, u.Token); err != nil {
return err
}
if err := w.WriteString(3, u.HuyaUA); err != nil {
return err
}
if err := w.WriteString(4, u.Cookie); err != nil {
return err
}
if err := w.WriteInt32(5, int64(u.TokenType)); err != nil {
return err
}
return w.WriteString(6, u.DeviceInfo)
}
func (u *ActivityUserID) ReadFrom(r *taf.Reader) error {
var err error
if u.UID, err = r.ReadInt64(0, false, u.UID); err != nil {
return err
}
if u.GUID, err = r.ReadString(1, false, u.GUID); err != nil {
return err
}
if u.Token, err = r.ReadString(2, false, u.Token); err != nil {
return err
}
if u.HuyaUA, err = r.ReadString(3, false, u.HuyaUA); err != nil {
return err
}
if u.Cookie, err = r.ReadString(4, false, u.Cookie); err != nil {
return err
}
if u.TokenType, err = r.ReadInt32(5, false, u.TokenType); err != nil {
return err
}
u.DeviceInfo, err = r.ReadString(6, false, u.DeviceInfo)
return err
}
type GetUserScoreReq struct {
User ActivityUserID
SID int32
}
func (q *GetUserScoreReq) WriteTo(w *taf.Writer) error {
if err := w.WriteStruct(0, &q.User); err != nil {
return err
}
return w.WriteInt32(1, int64(q.SID))
}
func (q *GetUserScoreReq) ReadFrom(r *taf.Reader) error {
_, err := r.ReadStruct(0, false, &q.User)
if err != nil {
return err
}
q.SID, err = r.ReadInt32(1, false, q.SID)
return err
}
type GetUserScoreResp struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
GainScore int32 `json:"gain_score"`
UsedScore int32 `json:"used_score"`
NewGainScore int64 `json:"new_gain_score"`
NewUsedScore int64 `json:"new_used_score"`
Score int64 `json:"score"`
IsOpenExchangeTip int32 `json:"is_open_exchange_tip"`
}
func (r *GetUserScoreResp) WriteTo(w *taf.Writer) error { return nil }
func (r *GetUserScoreResp) ReadFrom(rd *taf.Reader) error {
var err error
if r.Status, err = rd.ReadInt32(0, false, r.Status); err != nil {
return err
}
if r.Msg, err = rd.ReadString(1, false, r.Msg); err != nil {
return err
}
if r.GainScore, err = rd.ReadInt32(2, false, r.GainScore); err != nil {
return err
}
if r.UsedScore, err = rd.ReadInt32(3, false, r.UsedScore); err != nil {
return err
}
if r.NewGainScore, err = rd.ReadInt64(4, false, r.NewGainScore); err != nil {
return err
}
if r.NewUsedScore, err = rd.ReadInt64(5, false, r.NewUsedScore); err != nil {
return err
}
if r.Score, err = rd.ReadInt64(6, false, r.Score); err != nil {
return err
}
r.IsOpenExchangeTip, err = rd.ReadInt32(7, false, r.IsOpenExchangeTip)
return err
}
func (r GetUserScoreResp) AvailableScore() int64 {
if r.NewGainScore != 0 || r.NewUsedScore != 0 {
score := r.NewGainScore - r.NewUsedScore
if score < 0 {
return 0
}
return score
}
return r.Score
}
type GetActPrizeListReq struct {
User ActivityUserID
SID int32
}
func (q *GetActPrizeListReq) WriteTo(w *taf.Writer) error {
if err := w.WriteStruct(0, &q.User); err != nil {
return err
}
return w.WriteInt32(1, int64(q.SID))
}
func (q *GetActPrizeListReq) ReadFrom(r *taf.Reader) error {
_, err := r.ReadStruct(0, false, &q.User)
if err != nil {
return err
}
q.SID, err = r.ReadInt32(1, false, q.SID)
return err
}
type PrizeInfo struct {
ID int64 `json:"id"`
SID int64 `json:"sid"`
Name string `json:"name"`
Score int64 `json:"score"`
Type int32 `json:"type"`
Image string `json:"img,omitempty"`
Sort int32 `json:"sort"`
Frequency int32 `json:"frequency"`
FrequencyLimit int32 `json:"frequency_limit"`
CreateTime int64 `json:"create_time"`
Num int64 `json:"num"`
Status int32 `json:"status"`
Percent string `json:"percent"`
NewScore int64 `json:"new_score"`
Tags string `json:"tags,omitempty"`
LeftNum int64 `json:"left_num"`
IsShowNum int32 `json:"is_show_num"`
}
func (p *PrizeInfo) WriteTo(w *taf.Writer) error { return nil }
func (p *PrizeInfo) ReadFrom(r *taf.Reader) error {
var err error
if p.ID, err = r.ReadInt64(0, false, p.ID); err != nil {
return err
}
if p.SID, err = r.ReadInt64(1, false, p.SID); err != nil {
return err
}
if p.Name, err = r.ReadString(2, false, p.Name); err != nil {
return err
}
if p.Score, err = r.ReadInt64(3, false, p.Score); err != nil {
return err
}
if p.Type, err = r.ReadInt32(4, false, p.Type); err != nil {
return err
}
if p.Image, err = r.ReadString(5, false, p.Image); err != nil {
return err
}
if p.Sort, err = r.ReadInt32(6, false, p.Sort); err != nil {
return err
}
if p.Frequency, err = r.ReadInt32(7, false, p.Frequency); err != nil {
return err
}
if p.FrequencyLimit, err = r.ReadInt32(8, false, p.FrequencyLimit); err != nil {
return err
}
if p.CreateTime, err = r.ReadInt64(9, false, p.CreateTime); err != nil {
return err
}
if p.Num, err = r.ReadInt64(10, false, p.Num); err != nil {
return err
}
if p.Status, err = r.ReadInt32(11, false, p.Status); err != nil {
return err
}
if p.Percent, err = r.ReadString(12, false, p.Percent); err != nil {
return err
}
if p.NewScore, err = r.ReadInt64(13, false, p.NewScore); err != nil {
return err
}
if p.Tags, err = r.ReadString(14, false, p.Tags); err != nil {
return err
}
if p.LeftNum, err = r.ReadInt64(15, false, p.LeftNum); err != nil {
return err
}
p.IsShowNum, err = r.ReadInt32(16, false, p.IsShowNum)
return err
}
func (p PrizeInfo) Price() int64 {
if p.NewScore != 0 {
return p.NewScore
}
return p.Score
}
func (p PrizeInfo) EstimatedLeft() int64 {
left, ok := p.InventoryLeft()
if ok {
return left
}
return 0
}
func (p PrizeInfo) InventoryLeft() (int64, bool) {
if p.LeftNum > 0 {
return p.LeftNum, true
}
text := strings.TrimSuffix(strings.TrimSpace(p.Percent), "%")
if text == "" || p.Num <= 0 {
return 0, false
}
percent, err := strconv.ParseFloat(text, 64)
if err != nil {
return 0, false
}
return int64(math.Floor(float64(p.Num)*percent/100.0 + 1e-9)), true
}
type PrizeTag struct {
ID int64 `json:"id"`
Name string `json:"name"`
Weight int32 `json:"weight"`
}
func (t *PrizeTag) WriteTo(w *taf.Writer) error { return nil }
func (t *PrizeTag) ReadFrom(r *taf.Reader) error {
var err error
if t.ID, err = r.ReadInt64(0, false, t.ID); err != nil {
return err
}
if t.Name, err = r.ReadString(1, false, t.Name); err != nil {
return err
}
t.Weight, err = r.ReadInt32(2, false, t.Weight)
return err
}
type GetActPrizeListResp struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
Prizes []PrizeInfo `json:"prizes"`
ModuleID int32 `json:"module_id"`
Tags []PrizeTag `json:"tags"`
}
func (r *GetActPrizeListResp) WriteTo(w *taf.Writer) error { return nil }
func (r *GetActPrizeListResp) ReadFrom(rd *taf.Reader) error {
var err error
if r.Status, err = rd.ReadInt32(0, false, r.Status); err != nil {
return err
}
if r.Msg, err = rd.ReadString(1, false, r.Msg); err != nil {
return err
}
items, err := rd.ReadListStruct(2, false, func() taf.Unmarshaler { return &PrizeInfo{} })
if err != nil {
return err
}
r.Prizes = make([]PrizeInfo, 0, len(items))
for _, item := range items {
if prize, ok := item.(*PrizeInfo); ok {
r.Prizes = append(r.Prizes, *prize)
}
}
if r.ModuleID, err = rd.ReadInt32(3, false, r.ModuleID); err != nil {
return err
}
tags, err := rd.ReadListStruct(4, false, func() taf.Unmarshaler { return &PrizeTag{} })
if err != nil {
return err
}
r.Tags = make([]PrizeTag, 0, len(tags))
for _, item := range tags {
if tag, ok := item.(*PrizeTag); ok {
r.Tags = append(r.Tags, *tag)
}
}
return nil
}
type GetUserPrizeRecordsReq struct {
User ActivityUserID
SID int32
}
func (q *GetUserPrizeRecordsReq) WriteTo(w *taf.Writer) error {
if err := w.WriteStruct(0, &q.User); err != nil {
return err
}
return w.WriteInt32(1, int64(q.SID))
}
func (q *GetUserPrizeRecordsReq) ReadFrom(r *taf.Reader) error {
_, err := r.ReadStruct(0, false, &q.User)
if err != nil {
return err
}
q.SID, err = r.ReadInt32(1, false, q.SID)
return err
}
type UserPrizeInfo struct {
ID int64 `json:"id"`
Name string `json:"name"`
Score int64 `json:"score"`
CreateTime int64 `json:"create_time"`
Status int32 `json:"status"`
Type int32 `json:"type"`
IsReal int32 `json:"is_real"`
NewScore int64 `json:"new_score"`
Account string `json:"account,omitempty"`
Code string `json:"code,omitempty"`
CommonPrizeType int32 `json:"common_prize_type"`
}
func (p *UserPrizeInfo) WriteTo(w *taf.Writer) error { return nil }
func (p *UserPrizeInfo) ReadFrom(r *taf.Reader) error {
var err error
if p.ID, err = r.ReadInt64(0, false, p.ID); err != nil {
return err
}
if p.Name, err = r.ReadString(1, false, p.Name); err != nil {
return err
}
if p.Score, err = r.ReadInt64(2, false, p.Score); err != nil {
return err
}
if p.CreateTime, err = r.ReadInt64(3, false, p.CreateTime); err != nil {
return err
}
if p.Status, err = r.ReadInt32(4, false, p.Status); err != nil {
return err
}
if p.Type, err = r.ReadInt32(5, false, p.Type); err != nil {
return err
}
if p.IsReal, err = r.ReadInt32(6, false, p.IsReal); err != nil {
return err
}
if p.NewScore, err = r.ReadInt64(7, false, p.NewScore); err != nil {
return err
}
if p.Account, err = r.ReadString(8, false, p.Account); err != nil {
return err
}
if p.Code, err = r.ReadString(9, false, p.Code); err != nil {
return err
}
p.CommonPrizeType, err = r.ReadInt32(10, false, p.CommonPrizeType)
return err
}
type GetUserPrizeRecordsResp struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
Records []UserPrizeInfo `json:"records"`
}
func (r *GetUserPrizeRecordsResp) WriteTo(w *taf.Writer) error { return nil }
func (r *GetUserPrizeRecordsResp) ReadFrom(rd *taf.Reader) error {
var err error
if r.Status, err = rd.ReadInt32(0, false, r.Status); err != nil {
return err
}
if r.Msg, err = rd.ReadString(1, false, r.Msg); err != nil {
return err
}
items, err := rd.ReadListStruct(2, false, func() taf.Unmarshaler { return &UserPrizeInfo{} })
if err != nil {
return err
}
r.Records = make([]UserPrizeInfo, 0, len(items))
for _, item := range items {
if record, ok := item.(*UserPrizeInfo); ok {
r.Records = append(r.Records, *record)
}
}
return nil
}
type ScoreExchangePrizeReq struct {
User ActivityUserID
SID int32
PID int32
IP string
ClientEnv map[string]string
Source string
IsRole int32
}
func (q *ScoreExchangePrizeReq) WriteTo(w *taf.Writer) error {
if err := w.WriteStruct(0, &q.User); err != nil {
return err
}
if err := w.WriteInt32(1, int64(q.SID)); err != nil {
return err
}
if err := w.WriteInt32(2, int64(q.PID)); err != nil {
return err
}
if err := w.WriteString(3, q.IP); err != nil {
return err
}
if err := w.WriteMapStringString(4, q.ClientEnv); err != nil {
return err
}
if err := w.WriteString(5, q.Source); err != nil {
return err
}
if q.IsRole == 0 {
q.IsRole = 1
}
return w.WriteInt32(6, int64(q.IsRole))
}
func (q *ScoreExchangePrizeReq) ReadFrom(r *taf.Reader) error {
_, err := r.ReadStruct(0, false, &q.User)
if err != nil {
return err
}
if q.SID, err = r.ReadInt32(1, false, q.SID); err != nil {
return err
}
if q.PID, err = r.ReadInt32(2, false, q.PID); err != nil {
return err
}
if q.IP, err = r.ReadString(3, false, q.IP); err != nil {
return err
}
if q.ClientEnv, err = r.ReadMapStringString(4, false); err != nil {
return err
}
if q.Source, err = r.ReadString(5, false, q.Source); err != nil {
return err
}
q.IsRole, err = r.ReadInt32(6, false, q.IsRole)
return err
}
type ExchangeInfo struct {
PID int32 `json:"pid"`
ExchangeScore int64 `json:"exchange_score"`
Desc string `json:"desc"`
}
func (e *ExchangeInfo) WriteTo(w *taf.Writer) error { return nil }
func (e *ExchangeInfo) ReadFrom(r *taf.Reader) error {
var err error
if e.PID, err = r.ReadInt32(1, false, e.PID); err != nil {
return err
}
if e.ExchangeScore, err = r.ReadInt64(2, false, e.ExchangeScore); err != nil {
return err
}
e.Desc, err = r.ReadString(3, false, e.Desc)
return err
}
type ActPreCondition struct {
ConditionType int32 `json:"condition_type"`
ConditionParams map[string]string `json:"condition_params,omitempty"`
Tip string `json:"tip,omitempty"`
JumpURL string `json:"jump_url,omitempty"`
ButtonDesc string `json:"button_desc,omitempty"`
}
func (c *ActPreCondition) WriteTo(w *taf.Writer) error { return nil }
func (c *ActPreCondition) ReadFrom(r *taf.Reader) error {
var err error
if c.ConditionType, err = r.ReadInt32(0, false, c.ConditionType); err != nil {
return err
}
if c.ConditionParams, err = r.ReadMapStringString(1, false); err != nil {
return err
}
if c.Tip, err = r.ReadString(2, false, c.Tip); err != nil {
return err
}
if c.JumpURL, err = r.ReadString(3, false, c.JumpURL); err != nil {
return err
}
c.ButtonDesc, err = r.ReadString(4, false, c.ButtonDesc)
return err
}
type ScoreExchangePrizeResp struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
OrderID string `json:"order_id,omitempty"`
ExchangeInfo ExchangeInfo `json:"exchange_info"`
ActPreCondition ActPreCondition `json:"act_pre_condition"`
}
func (r *ScoreExchangePrizeResp) WriteTo(w *taf.Writer) error { return nil }
func (r *ScoreExchangePrizeResp) ReadFrom(rd *taf.Reader) error {
var err error
if r.Status, err = rd.ReadInt32(0, false, r.Status); err != nil {
return err
}
if r.Msg, err = rd.ReadString(1, false, r.Msg); err != nil {
return err
}
if r.OrderID, err = rd.ReadString(3, false, r.OrderID); err != nil {
return err
}
if _, err = rd.ReadStruct(4, false, &r.ExchangeInfo); err != nil {
return err
}
_, err = rd.ReadStruct(5, false, &r.ActPreCondition)
return err
}
func (r ScoreExchangePrizeResp) Success() bool {
return r.Status == 200 && (r.Msg == "" || strings.Contains(r.Msg, "成功"))
}
func prizeListInventorySummary(prizes []PrizeInfo) (left, total int64, leftKnown, totalKnown int) {
for _, prize := range prizes {
if prize.Num > 0 {
total += prize.Num
totalKnown++
}
if itemLeft, ok := prize.InventoryLeft(); ok {
left += itemLeft
leftKnown++
}
}
return left, total, leftKnown, totalKnown
}
func exchangeResponseMessage(resp *ScoreExchangePrizeResp) string {
if resp == nil {
return ""
}
for _, text := range []string{
resp.Msg,
resp.ActPreCondition.Tip,
resp.ActPreCondition.ButtonDesc,
resp.ExchangeInfo.Desc,
resp.OrderID,
} {
if strings.TrimSpace(text) != "" {
return strings.TrimSpace(text)
}
}
return ""
}