261 lines
7.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package scoresaber
import (
"fmt"
"log"
"os"
"strconv"
"strings"
"sync"
"git.lxtend.com/qqbot/constants"
"git.lxtend.com/qqbot/handler"
"git.lxtend.com/qqbot/message"
"git.lxtend.com/qqbot/model"
"git.lxtend.com/qqbot/service/scoresaber"
"git.lxtend.com/qqbot/util"
)
func init() {
handler.RegisterHandler("查ss", getSSProfile, constants.LEVEL_USER)
handler.RegisterHelpInform("查ss", "scoresaber", " 查看您的最新分数")
handler.RegisterHandler("绑定ss", bindSS, constants.LEVEL_USER)
handler.RegisterHelpInform("绑定ss", "scoresaber", "绑定您的scoresaber账号")
handler.RegisterHandler("解绑ss", unbindSS, constants.LEVEL_USER)
handler.RegisterHelpInform("解绑ss", "scoresaber", "解绑您的scoresaber账号")
handler.RegisterHandler("最新ss", getMyRecentScore, constants.LEVEL_USER)
handler.RegisterHelpInform("最新ss", "scoresaber", "查看您的最新游戏记录")
handler.RegisterHandler("截ss", screenshotSS, constants.LEVEL_USER)
handler.RegisterHelpInform("ss+n", "scoresaber", "区排名升高n位还需要打出多少pp")
handler.RegisterFrontMatchHandler("ss+", ssPlusN, constants.LEVEL_USER)
// handler.RegisterHelpInform("截ss", "scoresaber", "scoresaber主页截图")
// handler.RegisterHandler("jss", screenshotSS, constants.LEVEL_USER)
}
func ssPlusN(msg model.Message) (reply model.Reply) {
var (
resultStr strings.Builder
err error
maxRetries = 5 // 最大重试次数
attempts = 0
)
var N int
if len(msg.RawMsg) > len("ss+") {
N, err = strconv.Atoi(msg.RawMsg[len("ss+"):])
if err != nil || N <= 0 {
return model.Reply{
ReplyMsg: "请输入一个正整数",
ReferOriginMsg: true,
FromMsg: msg,
}
}
}
// 获取当前用户在区中的排名
userIdStr := strconv.Itoa(int(msg.UserId))
userSSID, err := scoresaber.GetSSID(userIdStr)
if err != nil {
return model.Reply{
ReplyMsg: err.Error(),
ReferOriginMsg: true,
FromMsg: msg,
}
}
var userInfo scoresaber.PlayerData
for attempts < maxRetries {
err = nil
userInfo, err = scoresaber.FetchPlayerData(userSSID)
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 := scoresaber.FetchCountryLeaderboard(userInfo.Country, userInfo.CountryRank-N, userInfo.ID)
if err != nil {
return model.Reply{
ReplyMsg: "获取您的分数时出现问题,请稍后重试。" + err.Error(),
ReferOriginMsg: true,
FromMsg: msg,
}
}
if userInfo.CountryRank-N < 0 {
resultStr.WriteString(fmt.Sprintf("注意:你最多只需要提升%d名就是%s区Top1了。\n", userInfo.CountryRank-1, userInfo.Country))
}
//寻找leaderboard中排名为userInfo.CountryRank-N的玩家
var targetPlayer scoresaber.PlayerData
targetRank := userInfo.CountryRank - N
if targetRank < 0 {
targetRank = 1
}
for _, player := range leaderboard.Players {
if player.CountryRank == targetRank {
targetPlayer = player
break
}
}
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 getSSProfile(msg model.Message) (reply model.Reply) {
var (
resultStr string
err error
maxRetries = 5 // 最大重试次数
attempts = 0
noUpdate = false
)
var ssId string
if len(msg.RawMsg) > len("查ss ") {
ssId = strings.Split(msg.RawMsg, " ")[1]
noUpdate = true
}
userIdStr := strconv.Itoa(int(msg.UserId))
for attempts < maxRetries {
err = nil
if ssId == "" {
ssId, err = scoresaber.GetSSID(userIdStr)
}
if err != nil {
return model.Reply{
ReplyMsg: "您未绑定ss账号输入\"绑定ss [ssId]\"绑定(ssId为您的scoresaber主页链接中的数字部分)",
ReferOriginMsg: true,
FromMsg: msg,
}
}
if !noUpdate {
resultStr, err = scoresaber.SSQuery.GetScore(ssId)
} else {
resultStr, err = scoresaber.SSQuery.GetScoreWithoutUpdate(ssId)
}
if err == nil {
break
}
attempts++
log.Printf("获取分数时出错,第 %d 次重试: %v", attempts, err)
}
// 如果所有尝试都失败,返回适当的错误消息
if err != nil {
resultStr = "获取您的分数时出现问题,请稍后重试。" + err.Error()
}
return model.Reply{
ReplyMsg: resultStr,
ReferOriginMsg: true,
FromMsg: msg,
}
}
func bindSS(msg model.Message) (reply model.Reply) {
return model.Reply{
ReplyMsg: scoresaber.SSQuery.BindSS(strconv.Itoa(int(msg.UserId)), msg.RawMsg[len("绑定ss "):]),
ReferOriginMsg: true,
FromMsg: msg,
}
}
func unbindSS(msg model.Message) (reply model.Reply) {
return model.Reply{
ReplyMsg: scoresaber.SSQuery.UnbindSS(strconv.Itoa(int(msg.UserId))),
ReferOriginMsg: true,
FromMsg: msg,
}
}
func getMyRecentScore(msg model.Message) (reply model.Reply) {
count := 1
scoreMsg := ""
if len(msg.RawMsg) > len("最新ss ") {
var err error
count, err = strconv.Atoi(msg.RawMsg[len("最新ss "):])
if err != nil || count <= 0 {
return model.Reply{
ReplyMsg: "",
ReferOriginMsg: true,
FromMsg: msg,
}
}
if count > 10 {
count = 10
}
}
var userName string
recordCount := 0
records, err := scoresaber.SSQuery.GetRecentScores(count, strconv.Itoa(int(msg.UserId)))
if err != nil {
return model.Reply{
ReplyMsg: err.Error(),
ReferOriginMsg: true,
FromMsg: msg,
}
}
coverImageMap := make(map[string]string)
wg := sync.WaitGroup{}
for _, record := range records {
coverImageMap[record.SongHash] = record.CoverImage
wg.Add(1)
go func(songHash string) {
defer wg.Done()
//文件存在则跳过
if _, err := os.Stat(util.GetResizedIamgePathByOrgPath(util.GenTempFilePath(songHash + ".jpeg"))); err == nil {
return
}
util.DownloadFile(coverImageMap[songHash], util.GenTempFilePath(songHash+".jpeg"))
newPath, err := util.ResizeImageByMaxHeight(util.GenTempFilePath(songHash+".jpeg"), 20)
os.Remove(util.GenTempFilePath(songHash + ".jpeg"))
if err != nil {
log.Printf("缩放图片失败: %v", err)
}
coverImageMap[songHash] = newPath
}(record.SongHash)
}
wg.Wait()
for _, record := range records {
imageMsg := message.ImageMessage{
Type: "image",
Data: message.ImageMessageData{
File: util.GetResizedIamgePathByOrgPath(util.GenTempFilePath(record.SongHash + ".jpeg")),
},
}
scoreMsg += imageMsg.ToCQString() + record.ToString() + "\n"
userName = record.Name
recordCount++
}
if len(scoreMsg) > 0 {
scoreMsg = scoreMsg[:len(scoreMsg)-len("\n")] //去掉最后一个换行符
} else {
return model.Reply{
ReplyMsg: "无最近游戏记录",
ReferOriginMsg: true,
FromMsg: msg,
}
}
return model.Reply{
ReplyMsg: "玩家 " + userName + " 的" + strconv.Itoa(recordCount) + "条最近记录为:\n" + scoreMsg,
ReferOriginMsg: true,
FromMsg: msg,
}
}
func screenshotSS(msg model.Message) (reply model.Reply) {
return model.Reply{
ReplyMsg: "[CQ:image,file=file:///tmp/qqbot/" + scoresaber.GetSSPicture(strconv.Itoa(int(msg.UserId))) + "]",
ReferOriginMsg: true,
FromMsg: msg,
}
}