diff --git a/service/beatleader/bind_bl.go b/service/beatleader/bind_bl.go index 1ad56f1..47926c9 100644 --- a/service/beatleader/bind_bl.go +++ b/service/beatleader/bind_bl.go @@ -9,6 +9,7 @@ import ( "log" "net/http" "strconv" + "strings" "time" "git.lxtend.com/qqbot/sqlite3" @@ -286,38 +287,11 @@ func (bl *blQuery) SaveRecord(scoreData ScoreData) { } func (bl *blQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, error) { - db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB - tx, err := db.Beginx() - if err != nil { - log.Print(err) - return nil, errors.New("数据库连接失败,请稍后重试") - } - defer tx.Rollback() - // 查询绑定的 blId blId, err := getBLID(qqId) if err != nil { return nil, err } - - // // 查询记录 - // var records []RecordDataLite - // err = tx.Select(&records, "SELECT * FROM blRecordData WHERE bl_id = ? ORDER BY generated_time DESC LIMIT ?", blId, count) - // if err != nil { - // if err == sql.ErrNoRows { - // return nil, errors.New("未查询到数据") - // } - // log.Println("查询数据出错:", err) - // return nil, errors.New("查询记录失败") - // } - - // // 提交事务 - // err = tx.Commit() - // if err != nil { - // log.Print(err) - // return nil, errors.New("提交事务失败") - // } - // return records, nil playerData, err := FetchPlayerData(blId) if err != nil { @@ -372,15 +346,56 @@ func (bl *blQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, er DeviceControllerRight: GetControllerStr(score.Controller), GeneratedTime: time.Unix(score.Timepost, 0).Format("2006-01-02 15:04:05.999999999-07:00"), } - if score.Leaderboard.Song.ID != "" && len(score.Leaderboard.Song.ID) > 5 { - dataLite.SongId = score.Leaderboard.Song.ID[0:5] - } else if score.Leaderboard.Song.ID != "" { - dataLite.SongId = score.Leaderboard.Song.ID - } if score.Leaderboard.Difficulty.Stars != nil { dataLite.Stars = *score.Leaderboard.Difficulty.Stars } records = append(records, dataLite) } + // 获取歌曲ID + hashs := make([]string, 0) + for _, record := range records { + hashs = append(hashs, record.SongHash) + } + hashToSongId, err := GetSongIdsByHash(hashs) + if err != nil { + return nil, err + } + for i := 0; i < len(records); i++ { + records[i].SongId = hashToSongId[records[i].SongHash] + } + return records, nil } + +func GetSongIdsByHash(hashs []string) (hashToSongId map[string]string, err error) { + //每批最多49个 + batchSize := 49 + for i := 0; i < len(hashs); i += batchSize { + end := i + batchSize + if end > len(hashs) { + end = len(hashs) + } + batchHashs := hashs[i:end] + queryUrl := "https://api.beatsaver.com/maps/hash/" + strings.Join(batchHashs, ",") + resp, err := http.Get(queryUrl) + if err != nil { + return nil, err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var response map[string]struct { + ID string `json:"id"` + } + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + for hash, data := range response { + hashToSongId[hash] = data.ID + } + } + return hashToSongId, nil +} diff --git a/service/scoresaber/bind_ss.go b/service/scoresaber/bind_ss.go index 546d9e7..227b6e0 100644 --- a/service/scoresaber/bind_ss.go +++ b/service/scoresaber/bind_ss.go @@ -2,9 +2,14 @@ package scoresaber import ( "database/sql" + "encoding/json" "errors" + "fmt" + "io" "log" + "net/http" "strconv" + "strings" "time" "git.lxtend.com/qqbot/sqlite3" @@ -242,6 +247,7 @@ func (ss *ssQuery) SaveRecord(cmdData CommandData) { SongSubName: cmdData.Leaderboard.SongSubName, SongAuthorName: cmdData.Leaderboard.SongAuthorName, SongHash: cmdData.Leaderboard.SongHash, + SongId: "", CoverImage: cmdData.Leaderboard.CoverImage, DifficultyRaw: cmdData.Leaderboard.Difficulty.DifficultyRaw, Stars: cmdData.Leaderboard.Stars, @@ -298,36 +304,126 @@ func (ss *ssQuery) SaveRecord(cmdData CommandData) { } func (ss *ssQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, error) { - db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB - tx, err := db.Beginx() - if err != nil { - log.Print(err) - return nil, errors.New("数据库连接失败,请稍后重试") - } - defer tx.Rollback() - ssId, err := GetSSID(qqId) if err != nil { return nil, err } - // 查询记录 - var records []RecordDataLite - err = tx.Select(&records, "SELECT * FROM ssRecordData WHERE ss_id = ? ORDER BY generated_time DESC LIMIT ?", ssId, count) + playerData, err := FetchPlayerData(ssId) if err != nil { - if err == sql.ErrNoRows { - return nil, errors.New("未查询到数据") + return nil, err + } + + historyUrl := "https://scoresaber.com/api/player/%s/scores?page=1&sort=recent" + fullUrl := fmt.Sprintf(historyUrl, ssId) + resp, err := http.Get(fullUrl) + if err != nil { + return nil, err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var response struct { + Data []struct { + Score Score `json:"score"` + Leaderboard Leaderboard `json:"leaderboard"` + } `json:"playerScores"` + } + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + scores := response.Data + records := make([]RecordDataLite, 0) + for k, score := range scores { + if k > count { + break } - log.Println("查询数据出错:", err) - return nil, errors.New("查询记录失败") + record := RecordDataLite{ + ScoreID: score.Score.ID, + SsID: ssId, + Name: playerData.Name, + Country: playerData.Country, + SongName: score.Leaderboard.SongName, + SongSubName: score.Leaderboard.SongSubName, + SongAuthorName: score.Leaderboard.SongAuthorName, + SongHash: score.Leaderboard.SongHash, + SongId: "", + CoverImage: score.Leaderboard.CoverImage, + DifficultyRaw: score.Leaderboard.Difficulty.DifficultyRaw, + Stars: score.Leaderboard.Stars, + PP: score.Score.Pp, + Weight: score.Score.Weight, + Modifiers: score.Score.Modifiers, + Multiplier: score.Score.Multiplier, + Rank: score.Score.Rank, + BadCuts: score.Score.BadCuts, + Score: score.Score.ModifiedScore, + MaxScore: score.Leaderboard.MaxScore, + FullCombo: score.Score.FullCombo, + DeviceHmd: "", + DeviceControllerLeft: "", + DeviceControllerRight: "", + GeneratedTime: score.Score.TimeSet.Format("2006-01-02 15:04:05.999999999-07:00"), + } + // 检查设备信息并设置 + if score.Score.DeviceHmd != nil { + record.DeviceHmd = *score.Score.DeviceHmd + } + if score.Score.DeviceControllerLeft != nil { + record.DeviceControllerLeft = *score.Score.DeviceControllerLeft + } + if score.Score.DeviceControllerRight != nil { + record.DeviceControllerRight = *score.Score.DeviceControllerRight + } + records = append(records, record) } - - // 提交事务 - err = tx.Commit() + // 获取歌曲ID + hashs := make([]string, 0) + for _, record := range records { + hashs = append(hashs, record.SongHash) + } + hashToSongId, err := GetSongIdsByHash(hashs) if err != nil { - log.Print(err) - return nil, errors.New("提交事务失败") + return nil, err + } + for i := 0; i < len(records); i++ { + records[i].SongId = hashToSongId[records[i].SongHash] } - return records, nil } + +func GetSongIdsByHash(hashs []string) (hashToSongId map[string]string, err error) { + //每批最多49个 + batchSize := 49 + for i := 0; i < len(hashs); i += batchSize { + end := i + batchSize + if end > len(hashs) { + end = len(hashs) + } + batchHashs := hashs[i:end] + queryUrl := "https://api.beatsaver.com/maps/hash/" + strings.Join(batchHashs, ",") + resp, err := http.Get(queryUrl) + if err != nil { + return nil, err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var response map[string]struct { + ID string `json:"id"` + } + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + for hash, data := range response { + hashToSongId[hash] = data.ID + } + } + return hashToSongId, nil +} diff --git a/service/scoresaber/model.go b/service/scoresaber/model.go index e83b044..37ee014 100644 --- a/service/scoresaber/model.go +++ b/service/scoresaber/model.go @@ -101,6 +101,7 @@ type RecordDataLite struct { SongSubName string `json:"songSubName" db:"song_sub_name"` SongAuthorName string `json:"songAuthorName" db:"song_author_name"` SongHash string `json:"songHash" db:"song_hash"` + SongId string `json:"songId" db:"song_id"` CoverImage string `json:"coverImage" db:"cover_image"` DifficultyRaw string `json:"difficultyRaw" db:"difficulty_raw"` Stars float64 `json:"stars" db:"stars"`