From b05ea363b3864eba29a4de84b0358d6006764d2e Mon Sep 17 00:00:00 2001 From: NorthLan <6995syu@163.com> Date: Thu, 13 Oct 2022 21:44:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=A4=BC=E7=89=A9?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/user_center/rpc/etc/user_center-dev.yaml | 26 +-- .../rpc/internal/config/config_game.go | 28 ++-- .../rpc/internal/logic/gift/util.go | 2 +- .../internal/logic/gift_collect/collector.go | 19 ++- .../logic/gift_collect/collector_bilibili.go | 15 +- .../logic/gift_collect/collector_douyu.go | 154 ++++++++++++++++++ 6 files changed, 209 insertions(+), 35 deletions(-) create mode 100644 app/user_center/rpc/internal/logic/gift_collect/collector_douyu.go diff --git a/app/user_center/rpc/etc/user_center-dev.yaml b/app/user_center/rpc/etc/user_center-dev.yaml index dfccae6..107b27f 100644 --- a/app/user_center/rpc/etc/user_center-dev.yaml +++ b/app/user_center/rpc/etc/user_center-dev.yaml @@ -27,7 +27,7 @@ Kafka: UserRetriever: Enabled: false UpdateDuration: 720 # 720 hours = 30 Day = 1 Month - NobilityPlatforms: [ "bilibili" ] # 需要获取贵族的平台列表 + NobilityPlatforms: [ "Bilibili" ] # 需要获取贵族的平台列表 Cron: PlatformUser: "0 0/1 * * * ?" # 每隔1分钟执行一次 Nobility: "0 0/59 * * * ?" # 每隔59分钟执行一次 @@ -36,6 +36,19 @@ UserRetriever: # Mid: 6704420 RoomShortInfoApi: https://api.live.bilibili.com/room/v1/Room/room_init TopListApi: https://api.live.bilibili.com/guard/topList +# 平台礼物到RMB的转换 +GiftToRMB: + Bilibili: 0.001 + Douyu: 0.1 +GiftCollector: + Enabled: true + Cron: + CollectGift: "0 0 0/6 * * ?" # 每隔6小时执行一次 + Bilibili: + Enabled: true + Douyu: + Enabled: false + RoomId: 10984327 Rank: Enabled: false Cron: @@ -76,11 +89,6 @@ Rank: TitleId: 1005 Best: [66.6,45.6,28,18,10,6] Consolation: 2 -GiftCollector: - Enabled: false - Platforms: [ "bilibili" ] - Cron: - CollectGift: "0 0 0/6 * * ?" # 每隔6小时执行一次 Coin: # 签到配置 CheckIn: @@ -90,12 +98,10 @@ Coin: CriticalRadio: [ 1.2, 1.3, 1.5, 1.8 ] # 暴击倍率 # RMB到弹币的转换 RMBToCoin: 10 - # 平台礼物到RMB的转换 - GiftToRMB: - bilibili: 0.001 # 平台免费礼物到弹币的转换 FreeToCoin: - bilibili: 0.01 # 价值1毛 + Bilibili: 0.01 # 价值1毛 + Douyu: 0.01 # 价值1毛 Grade: BravePointCost: [0,300,320,350,400,450,500,600,800,1000] MaxBravePoint: 3000 diff --git a/app/user_center/rpc/internal/config/config_game.go b/app/user_center/rpc/internal/config/config_game.go index 354fed2..59ab875 100644 --- a/app/user_center/rpc/internal/config/config_game.go +++ b/app/user_center/rpc/internal/config/config_game.go @@ -72,20 +72,19 @@ type ( TopListApi string } } - Rank struct { + GiftToRMB map[string]float64 // 平台礼物到RMB的转换 + GiftCollector struct { Enabled bool // 是否开启 Cron struct { - Update string // 更新榜单 - Persistence string // 持久化 - } - Submit map[int32]RankSubmit // 排行榜结算 - } - GiftCollector struct { - Enabled bool // 是否开启 - Platforms []string // 需搜集的平台 - Cron struct { CollectGift string } + Douyu struct { + Enabled bool // 独立开关 + RoomId int64 // 直播间ID + } + Bilibili struct { + Enabled bool // 独立开关 + } } // 弹币 Coin struct { @@ -96,9 +95,16 @@ type ( CriticalRadio []float32 // 暴击倍数 } RMBToCoin float64 // RMB到弹币的转换 - GiftToRMB map[string]float64 // 平台礼物到RMB的转换 FreeToCoin map[string]float64 // 平台免费礼物到弹币的转换 } + Rank struct { + Enabled bool // 是否开启 + Cron struct { + Update string // 更新榜单 + Persistence string // 持久化 + } + Submit map[int32]RankSubmit // 排行榜结算 + } // 段位 Grade struct { BravePointCost []int64 // 骁勇分抵扣规则,对于grade等级 diff --git a/app/user_center/rpc/internal/logic/gift/util.go b/app/user_center/rpc/internal/logic/gift/util.go index 44395d8..58eefd2 100644 --- a/app/user_center/rpc/internal/logic/gift/util.go +++ b/app/user_center/rpc/internal/logic/gift/util.go @@ -6,7 +6,7 @@ import ( ) func calcCoin(cfg *config.GameConfig, platform string, isPaid bool, price float64, num int64) int64 { - giftToRMBRadio, _ := cfg.Coin.GiftToRMB[platform] + giftToRMBRadio, _ := cfg.GiftToRMB[platform] freeToRadio, _ := cfg.Coin.FreeToCoin[platform] rmbTo := cfg.Coin.RMBToCoin diff --git a/app/user_center/rpc/internal/logic/gift_collect/collector.go b/app/user_center/rpc/internal/logic/gift_collect/collector.go index 1dc7878..3b8cfa6 100644 --- a/app/user_center/rpc/internal/logic/gift_collect/collector.go +++ b/app/user_center/rpc/internal/logic/gift_collect/collector.go @@ -12,9 +12,10 @@ var Service *GiftCollector type ( GiftData struct { - Id int64 // 礼物ID + ID int64 // 礼物ID Name string // 礼物名称 Price float64 // 礼物单价(rmb) + Pic string // 礼物图 IsPaid bool // 是否收费礼物 } GiftCollector struct { @@ -36,11 +37,13 @@ type ( func InitCollector(svcCtx *svc.ServiceContext) { ctx := context.Background() Service = &GiftCollector{ - ctx: context.Background(), - svcCtx: svcCtx, - cron: cron.New(cron.WithSeconds()), + ctx: context.Background(), + svcCtx: svcCtx, + cron: cron.New(cron.WithSeconds()), + cacheGift: map[string]map[int64]GiftData{}, collectorMapper: map[string]CollectorFunc{ pbVars.Platform_name[int32(pbVars.Platform_Bilibili)]: GiftCollectorBilibili, + pbVars.Platform_name[int32(pbVars.Platform_Douyu)]: GiftCollectorDouyu, }, Logger: logx.WithContext(ctx), } @@ -54,16 +57,16 @@ func InitCollector(svcCtx *svc.ServiceContext) { func (c *GiftCollector) startJob() { cfg := c.svcCtx.GameConfig.GiftCollector // 先执行一次 - c.collectGift(cfg.Platforms...) + c.collectGift() _, _ = c.cron.AddFunc(cfg.Cron.CollectGift, func() { - c.collectGift(cfg.Platforms...) + c.collectGift() }) c.cron.Start() } -func (c *GiftCollector) collectGift(platforms ...string) { - for _, platform := range platforms { +func (c *GiftCollector) collectGift() { + for _, platform := range pbVars.Platform_name { if handle, ok := c.collectorMapper[platform]; ok { ret, err := handle(c.ctx, c.svcCtx) if err != nil { diff --git a/app/user_center/rpc/internal/logic/gift_collect/collector_bilibili.go b/app/user_center/rpc/internal/logic/gift_collect/collector_bilibili.go index a27c593..896bac6 100644 --- a/app/user_center/rpc/internal/logic/gift_collect/collector_bilibili.go +++ b/app/user_center/rpc/internal/logic/gift_collect/collector_bilibili.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "gorm.io/gorm" "io/ioutil" + pbVars "live-service/app/pb/vars" "live-service/app/user_center/model" "live-service/app/user_center/rpc/internal/svc" "net/http" @@ -40,8 +41,12 @@ func isPaidGift(coinType string) bool { } func GiftCollectorBilibili(ctx context.Context, svcCtx *svc.ServiceContext) (ret map[int64]GiftData, err error) { - const platform = "bilibili" - radio, _ := svcCtx.GameConfig.Coin.GiftToRMB[platform] + platform := pbVars.Platform_name[int32(pbVars.Platform_Bilibili)] + cfg := svcCtx.GameConfig.GiftCollector.Bilibili + if !cfg.Enabled { + return nil, errors.New("未开启") + } + radio, _ := svcCtx.GameConfig.GiftToRMB[platform] // 1. 读取API httpResp, err := http.Get("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/giftConfig?platform=app") @@ -70,7 +75,7 @@ func GiftCollectorBilibili(ctx context.Context, svcCtx *svc.ServiceContext) (ret if dataLen%batchSize != 0 { batches += 1 } - ret = make(map[int64]GiftData) + ret = map[int64]GiftData{} for i := 0; i < batches; i++ { _ = svcCtx.GiftModel.TransactCtx(ctx, nil, func(tx *gorm.DB) error { lenJ := (i + 1) * batchSize @@ -88,7 +93,7 @@ func GiftCollectorBilibili(ctx context.Context, svcCtx *svc.ServiceContext) (ret Platform: platform, } giftData := GiftData{ - Id: gift.Id, + ID: gift.Id, Name: gift.Name, } if isPaidGift(gift.CoinType) { @@ -103,7 +108,7 @@ func GiftCollectorBilibili(ctx context.Context, svcCtx *svc.ServiceContext) (ret giftData.IsPaid = false giftData.Price = float64(dbGift.PPriceFree) } - ret[giftData.Id] = giftData + ret[giftData.ID] = giftData if err = svcCtx.GiftModel.Update(ctx, tx, dbGift); err != nil { if errors.Is(err, gormx.ErrRowsAffectedZero) { diff --git a/app/user_center/rpc/internal/logic/gift_collect/collector_douyu.go b/app/user_center/rpc/internal/logic/gift_collect/collector_douyu.go new file mode 100644 index 0000000..8384e35 --- /dev/null +++ b/app/user_center/rpc/internal/logic/gift_collect/collector_douyu.go @@ -0,0 +1,154 @@ +package gift_collect + +import ( + "context" + "fmt" + "git.noahlan.cn/northlan/ntools-go/gorm-zero/gormx" + "git.noahlan.cn/northlan/ntools-go/uuid" + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" + "gorm.io/gorm" + "io" + pbVars "live-service/app/pb/vars" + "live-service/app/user_center/model" + "live-service/app/user_center/rpc/internal/svc" + "net/http" + "strconv" +) + +const ( + giftTypeYuChi = "YUCHI" + giftTypeYuWan = "YUWAN" +) + +func isDouyuPaidGift(giftType string) bool { + if giftType == giftTypeYuChi { + return true + } + if giftType == giftTypeYuWan { + return false + } + return false +} + +func GiftCollectorDouyu(ctx context.Context, svcCtx *svc.ServiceContext) (map[int64]GiftData, error) { + platform := pbVars.Platform_name[int32(pbVars.Platform_Douyu)] + cfg := svcCtx.GameConfig.GiftCollector.Douyu + if !cfg.Enabled { + return nil, errors.New("未开启") + } + radio, _ := svcCtx.GameConfig.GiftToRMB[platform] + ret := make(map[int64]GiftData) + + // bagGiftData + { + httpResp, err := http.Get("https://webconf.douyucdn.cn/resource/common/prop_gift_list/prop_gift_config.json") + if err != nil { + return nil, err + } + httpBodyResp, err := io.ReadAll(httpResp.Body) + if err != nil { + return nil, err + } + httpBodyResp = httpBodyResp[len("DYConfigCallback("):] + httpBodyResp = httpBodyResp[:len(httpBodyResp)-2] + + var gf struct { + Data map[string]struct { + Name string `json:"name"` + Price int64 `json:"pc"` + Pic string `json:"bimg"` + } `json:"data"` + } + err = jsoniter.Unmarshal(httpBodyResp, &gf) + if err != nil { + return nil, err + } + for id, g := range gf.Data { + idInt, err := strconv.ParseInt(id, 10, 64) + if err != nil { + continue + } + gfCfg := GiftData{ + ID: idInt, + Name: g.Name, + IsPaid: true, + Price: float64(g.Price) * radio, + Pic: g.Pic, + } + ret[gfCfg.ID] = gfCfg + } + } + // roomGiftData + { + httpResp, err := http.Get(fmt.Sprintf("https://gift.douyucdn.cn/api/gift/v3/web/list?rid=%d", cfg.RoomId)) + if err != nil { + return nil, err + } + httpBodyResp, err := io.ReadAll(httpResp.Body) + if err != nil { + return nil, err + } + type GiftPriceInfo struct { + Price int64 `json:"price"` + PriceType string `json:"priceType"` + } + type BasicInfo struct { + GiftPic string `json:"giftPic"` + } + var gf struct { + Data struct { + GiftList []struct { + ID int64 `json:"id"` // 礼物ID + Name string `json:"name"` // 礼物名 + PicUrlPrefix string `json:"picUrlPrefix"` // 礼物图前缀 + BasicInfo `json:"basicInfo"` // 基础信息 + GiftPriceInfo `json:"priceInfo"` // 价格参数 + } `json:"giftList"` + } `json:"data"` + } + err = jsoniter.Unmarshal(httpBodyResp, &gf) + if err != nil { + return nil, err + } + for _, g := range gf.Data.GiftList { + gfCfg := GiftData{ + ID: g.ID, + Name: g.Name, + IsPaid: isDouyuPaidGift(g.PriceType), + Price: float64(g.Price), + Pic: g.PicUrlPrefix + g.BasicInfo.GiftPic, + } + ret[gfCfg.ID] = gfCfg + } + } + _ = svcCtx.GiftModel.TransactCtx(ctx, nil, func(tx *gorm.DB) error { + for _, data := range ret { + dbGift := &model.Gift{ + Id: uuid.NextId(), + GiftId: strconv.FormatInt(data.ID, 10), + GiftName: data.Name, + Platform: platform, + PPriceFree: 0, + Price: 0, + Pic: data.Pic, + PPricePaid: 0, + } + if data.IsPaid { + dbGift.PPricePaid = int64(data.Price) + dbGift.Price = data.Price * radio + data.Price = dbGift.Price + } else { + dbGift.PPriceFree = int64(data.Price) + } + if err := svcCtx.GiftModel.Update(ctx, tx, dbGift); err != nil { + if errors.Is(err, gormx.ErrRowsAffectedZero) { + err = nil + _ = svcCtx.GiftModel.Insert(ctx, tx, dbGift) + } + } + } + return nil + }) + return ret, nil +}