From ec6d65c9b81c626c727ba6cf156323070211d1dd Mon Sep 17 00:00:00 2001 From: lixiangwuxian Date: Wed, 30 Apr 2025 14:33:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20blPlus=20=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handler/beatleader/beatleader.go | 123 ++++++++++++++++--------------- service/beatleader/user_info.go | 55 ++++++++++++++ 2 files changed, 118 insertions(+), 60 deletions(-) diff --git a/handler/beatleader/beatleader.go b/handler/beatleader/beatleader.go index ba4c63d..61436c2 100644 --- a/handler/beatleader/beatleader.go +++ b/handler/beatleader/beatleader.go @@ -1,8 +1,10 @@ package beatleader import ( + "fmt" "log" "strconv" + "strings" "sync" "git.lxtend.com/qqbot/constants" @@ -10,6 +12,7 @@ import ( "git.lxtend.com/qqbot/message" "git.lxtend.com/qqbot/model" "git.lxtend.com/qqbot/service/beatleader" + "git.lxtend.com/qqbot/service/scoresaber" "git.lxtend.com/qqbot/util" ) @@ -29,66 +32,66 @@ func init() { handler.RegisterHandler("jbl", screenShotBL, constants.LEVEL_USER) } -// func blPlus(msg model.Message) (reply model.Reply) { -// var ( -// resultStr strings.Builder -// err error -// maxRetries = 5 // 最大重试次数 -// attempts = 0 -// ) -// var N int -// if len(msg.RawMsg) > len("bl+") { -// N, err = strconv.Atoi(msg.RawMsg[len("bl+"):]) -// if err != nil || N <= 0 { -// return model.Reply{ -// ReplyMsg: "请输入一个正整数", -// ReferOriginMsg: true, -// FromMsg: msg, -// } -// } -// } -// userIdStr := strconv.Itoa(int(msg.UserId)) -// userBLID, err := scoresaber.GetSSID(userIdStr) -// if err != nil { -// return model.Reply{ -// ReplyMsg: err.Error(), -// ReferOriginMsg: true, -// FromMsg: msg, -// } -// } -// var userInfo beatleader.PlayerData -// for attempts < maxRetries { -// err = nil -// userInfo, err = beatleader.FetchPlayerData(userBLID) -// if err != nil { -// break -// } -// attempts++ -// } -// if err != nil { -// return model.Reply{ -// ReplyMsg: "获取您的分数时出现问题,请稍后重试。" + err.Error(), -// ReferOriginMsg: true, -// FromMsg: msg, -// } -// } -// resultStr.WriteString(fmt.Sprintf("您当前的全区排名为:%d\n", userInfo.CountryRank)) -// // 获取当前用户所在区对应+N位的玩家列表 -// leaderboard, err := beatleader.FetchCountryLeaderboard(userInfo.Country, userInfo.CountryRank-N, userInfo.ID) -// if err != nil { -// return model.Reply{ -// ReplyMsg: "获取当前用户所在区对应+N位的玩家列表时出现问题,请稍后重试。" + err.Error(), -// ReferOriginMsg: true, -// FromMsg: msg, -// } -// } -// resultStr.WriteString(fmt.Sprintf("您只需要再打出%.2fpp就能达到%s区第%d名。", targetPlayer.PP-userInfo.PP, userInfo.Country, targetPlayer.CountryRank)) -// return model.Reply{ -// ReplyMsg: resultStr.String(), -// ReferOriginMsg: true, -// FromMsg: msg, -// } -// } +func blPlus(msg model.Message) (reply model.Reply) { + var ( + resultStr strings.Builder + err error + maxRetries = 5 // 最大重试次数 + attempts = 0 + ) + var N int + if len(msg.RawMsg) > len("bl+") { + N, err = strconv.Atoi(msg.RawMsg[len("bl+"):]) + if err != nil || N <= 0 { + return model.Reply{ + ReplyMsg: "请输入一个正整数", + ReferOriginMsg: true, + FromMsg: msg, + } + } + } + userIdStr := strconv.Itoa(int(msg.UserId)) + userBLID, err := scoresaber.GetSSID(userIdStr) + if err != nil { + return model.Reply{ + ReplyMsg: err.Error(), + ReferOriginMsg: true, + FromMsg: msg, + } + } + var userInfo *beatleader.PlayerData + for attempts < maxRetries { + err = nil + userInfo, err = beatleader.FetchPlayerData(userBLID) + if err != nil { + break + } + attempts++ + } + if err != nil { + return model.Reply{ + ReplyMsg: "获取您的分数时出现问题,请稍后重试。" + err.Error(), + ReferOriginMsg: true, + FromMsg: msg, + } + } + resultStr.WriteString(fmt.Sprintf("您当前的全区排名为:%d\n", userInfo.CountryRank)) + // 获取当前用户所在区对应+N位的玩家列表 + // leaderboard, err := beatleader.FetchCountryLeaderboard(userInfo.Country, userInfo.CountryRank-N, userInfo.ID) + // if err != nil { + // return model.Reply{ + // ReplyMsg: "获取当前用户所在区对应+N位的玩家列表时出现问题,请稍后重试。" + err.Error(), + // ReferOriginMsg: true, + // FromMsg: msg, + // } + // } + // resultStr.WriteString(fmt.Sprintf("您只需要再打出%.2fpp就能达到%s区第%d名。", targetPlayer.PP-userInfo.PP, userInfo.Country, targetPlayer.CountryRank)) + return model.Reply{ + ReplyMsg: resultStr.String(), + ReferOriginMsg: true, + FromMsg: msg, + } +} func getMyBL(msg model.Message) (reply *model.Reply) { var ( diff --git a/service/beatleader/user_info.go b/service/beatleader/user_info.go index fb41129..7009b6a 100644 --- a/service/beatleader/user_info.go +++ b/service/beatleader/user_info.go @@ -67,3 +67,58 @@ func FetchPlayerData(blID string) (*PlayerData, error) { return &playerData, nil } + +func FetchCountryLeaderboard(country string, aimRank int, userId string) (*PlayerDataLite, error) { + url := fmt.Sprintf("https://api.beatleader.com/players?leaderboardContext=general&page=1&count=50&sortBy=pp&mapsType=ranked&ppType=general&order=desc") + + // 创建请求 + req, err := http.NewRequest("GET", url, nil) + + // 设置请求头 + req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0") + req.Header.Set("Accept", "application/json, text/plain, */*") + req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2") + req.Header.Set("Accept-Encoding", "gzip") + req.Header.Set("DNT", "1") + req.Header.Set("Connection", "keep-alive") + req.Header.Set("Referer", fmt.Sprintf("https://beatleader.xyz/u/%s/scores/date/desc/1", userId)) + req.Header.Set("Sec-Fetch-Dest", "empty") + req.Header.Set("Sec-Fetch-Mode", "cors") + req.Header.Set("Sec-Fetch-Site", "same-origin") + req.Header.Set("Sec-GPC", "1") + req.Header.Set("Pragma", "no-cache") + req.Header.Set("Cache-Control", "no-cache") + req.Header.Set("TE", "trailers") + + // 发送请求,失败则重试至多3次 + client := &http.Client{} + resp, err := client.Do(req) + for i := 0; i < 3 && err != nil; i++ { + resp, err = client.Do(req) + } + if err != nil { + return nil, err + } + defer resp.Body.Close() + + // 处理压缩响应 + var reader io.Reader + if resp.Header.Get("Content-Encoding") == "gzip" { + reader, err = gzip.NewReader(resp.Body) + if err != nil { + return nil, err + } + defer reader.(*gzip.Reader).Close() + } else { + reader = resp.Body + } + + // 解析响应体 + var playerDataLite PlayerDataLite + err = json.NewDecoder(reader).Decode(&playerDataLite) + if err != nil { + return nil, err + } + + return &playerDataLite, nil +}