diff --git a/compounds/toolchain/main.go b/compounds/toolchain/main.go new file mode 100644 index 0000000..6eb149d --- /dev/null +++ b/compounds/toolchain/main.go @@ -0,0 +1,9 @@ +package toolchain + +import "strings" + +// SplitCommandTo Split Command and Adjust To. +func SplitCommandTo(raw string, setCommandStopper int) (splitCommandLen int, splitInfo []string) { + rawSplit := strings.SplitN(raw, " ", setCommandStopper) + return len(rawSplit), rawSplit +} diff --git a/plugin/mai/alias.go b/plugin/mai/alias.go new file mode 100644 index 0000000..58f59ce --- /dev/null +++ b/plugin/mai/alias.go @@ -0,0 +1,99 @@ +package mai + +import ( + "encoding/json" + "github.com/FloatTech/floatbox/web" + "os" +) + +type AliasesReturnValue struct { + Aliases []struct { + DvId int `json:"dv_id"` + SongName string `json:"song_name"` + SongId []int `json:"song_id"` + Aliases []string `json:"aliases"` + } `json:"aliases"` +} + +// only support LXNS because => if DivingFish then need Token. + +// QueryReferSong use LocalStorageData. +func QueryReferSong(Alias string, isLxnet bool) (status bool, id []int, needAcc bool) { + // unpackedData + getData, err := os.ReadFile(engine.DataFolder() + "alias.json") + if err != nil { + panic(err) + } + var DataHandler AliasesReturnValue + json.Unmarshal(getData, &DataHandler) + var onloadList [][]int + for _, dataSearcher := range DataHandler.Aliases { + for _, aliasSearcher := range dataSearcher.Aliases { + if aliasSearcher == Alias { + onloadList = append(onloadList, dataSearcher.SongId) // write in memory + } + } + } + // if list is 2,query them is from the same song? | if above 2(3 or more ,means this song need acc.) + switch { + case len(onloadList) == 1: // only one query. + if isLxnet { + for _, listhere := range onloadList[0] { + if listhere < 10000 { + return true, []int{listhere}, false + } + } + } else { + return true, onloadList[0], false + } + // query length is 2,it means this maybe same name but diff id ==> (E.G: Oshama Scramble!) + case len(onloadList) == 2: + for _, listHere := range onloadList[0] { + for _, listAliasTwo := range onloadList[1] { + if listHere == listAliasTwo { + // same list here. + var returnIntList []int + returnIntList = append(returnIntList, onloadList[0]...) + returnIntList = append(returnIntList, onloadList[1]...) + returnIntList = removeIntDuplicates(returnIntList) + if isLxnet { + for _, listhere := range returnIntList { + if listhere < 10000 { + return true, []int{listhere}, false + } + } + } else { + return true, returnIntList, false + } + } + } + } + // if query is none, means it need moreacc + return true, nil, true + case len(onloadList) >= 3: + return true, nil, true + } + // no found. + return false, nil, false +} + +// UpdateAliasPackage Use simple action to update alias. +func UpdateAliasPackage() { + getData, err := web.GetData("https://maihook.lemonkoi.one/api/alias") + if err != nil { + panic(err) + } + os.WriteFile(engine.DataFolder()+"alias.json", getData, 0777) +} + +func removeIntDuplicates(list []int) []int { + seen := make(map[int]bool) + var result []int + for _, item := range list { + if !seen[item] { + seen[item] = true + result = append(result, item) + } + } + return result +} diff --git a/plugin/mai/lxns_handler.go b/plugin/mai/lxns_handler.go index a349424..8d3af04 100644 --- a/plugin/mai/lxns_handler.go +++ b/plugin/mai/lxns_handler.go @@ -103,6 +103,44 @@ type LxnsMaimaiRequestDataPiece struct { UploadTime time.Time `json:"upload_time"` } +type LxnsMaimaiRequestUserReferBestSong struct { + Success bool `json:"success"` + Code int `json:"code"` + Data []struct { + Id int `json:"id"` + SongName string `json:"song_name"` + Level string `json:"level"` + LevelIndex int `json:"level_index"` + Achievements float64 `json:"achievements"` + Fc *string `json:"fc"` + Fs *string `json:"fs"` + DxScore int `json:"dx_score"` + DxRating float64 `json:"dx_rating"` + Rate string `json:"rate"` + Type string `json:"type"` + UploadTime time.Time `json:"upload_time"` + } `json:"data"` +} + +type LxnsMaimaiRequestUserReferBestSongIndex struct { + Success bool `json:"success"` + Code int `json:"code"` + Data struct { + Id int `json:"id"` + SongName string `json:"song_name"` + Level string `json:"level"` + LevelIndex int `json:"level_index"` + Achievements float64 `json:"achievements"` + Fc *string `json:"fc"` + Fs *string `json:"fs"` + DxScore int `json:"dx_score"` + DxRating float64 `json:"dx_rating"` + Rate string `json:"rate"` + Type string `json:"type"` + UploadTime time.Time `json:"upload_time"` + } `json:"data"` +} + // NOTE: lxns network maimai uses qq => friendCode // RequestBasicDataFromLxns @@ -164,7 +202,7 @@ func RequestB50DataByFriendCode(friendCode int64) LxnsMaimaiRequestB50 { return handlerData } -func ReCardRenderBase(data LxnsMaimaiRequestDataPiece, getNum int) image.Image { +func ReCardRenderBase(data LxnsMaimaiRequestDataPiece, getNum int, isSimpleRender bool) image.Image { getType := data.Type var CardBackGround string var multiTypeRender sync.WaitGroup @@ -231,7 +269,9 @@ func ReCardRenderBase(data LxnsMaimaiRequestDataPiece, getNum int) image.Image { drawBackGround.Fill() drawBackGround.SetFontFace(rankFont) drawBackGround.SetColor(diffColor[data.LevelIndex]) - drawBackGround.DrawString("#"+strconv.Itoa(getNum), 130, 111) + if !isSimpleRender { + drawBackGround.DrawString("#"+strconv.Itoa(getNum), 130, 111) + } drawBackGround.FillPreserve() // draw rest of card. drawBackGround.SetFontFace(levelFont) @@ -244,7 +284,7 @@ func ReCardRenderBase(data LxnsMaimaiRequestDataPiece, getNum int) image.Image { drawBackGround.DrawString("▶", 235, 111) drawBackGround.FillPreserve() drawBackGround.SetFontFace(ratingFont) - drawBackGround.DrawString(strconv.Itoa(data.DxScore), 250, 111) + drawBackGround.DrawString(strconv.Itoa(int(data.DxRating)), 250, 111) drawBackGround.FillPreserve() if data.Fc != nil { FcPointer := *data.Fc @@ -400,7 +440,7 @@ func ReFullPageRender(data LxnsMaimaiRequestB50, userData LxnsMaimaiRequestFromQ getInitY := 285 var i int for i = 0; i < getSDLength; i++ { - b50Render.DrawImage(ReCardRenderBase(DataPiecesRepacked(data, true, i), i+1), getInitX, getInitY) + b50Render.DrawImage(ReCardRenderBase(DataPiecesRepacked(data, true, i), i+1, false), getInitX, getInitY) getInitX += 400 if getInitX == 2045 { getInitX = 45 @@ -409,7 +449,7 @@ func ReFullPageRender(data LxnsMaimaiRequestB50, userData LxnsMaimaiRequestFromQ } for dx := 0; dx < getDXLength; dx++ { - b50Render.DrawImage(ReCardRenderBase(DataPiecesRepacked(data, false, dx), dx+1), getDXinitX, getDXinitY) + b50Render.DrawImage(ReCardRenderBase(DataPiecesRepacked(data, false, dx), dx+1, false), getDXinitX, getDXinitY) getDXinitX += 400 if getDXinitX == 2045 { getDXinitX = 45 diff --git a/plugin/mai/main.go b/plugin/mai/main.go index 0dbe182..327d3c9 100644 --- a/plugin/mai/main.go +++ b/plugin/mai/main.go @@ -3,6 +3,7 @@ package mai import ( "bytes" "encoding/json" + "github.com/FloatTech/ZeroBot-Plugin/compounds/toolchain" "image" rand2 "math/rand" "net/http" @@ -298,7 +299,7 @@ func init() { } // token is valid, get data. getIntID, _ := strconv.ParseInt(getMaiID.Userid, 10, 64) - getFullData := GetMusicList(getIntID, 0, 1000) + getFullData := GetMusicList(getIntID, 0, 5000) if strings.Contains(getFullData, "{") == false { ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("返回了错误.png, ERROR:"+getFullData)) return @@ -385,5 +386,237 @@ func init() { // getWebStatusCount := "Web Uptime Ping:\n * MaimaiDXCN: " + ConvertFloat(getWebStatus.Details.MaimaiDXCN.Uptime*100) + "%\n * MaimaiDXCN Main Server: " + ConvertFloat(getWebStatus.Details.MaimaiDXCNMain.Uptime*100) + "%\n * MaimaiDXCN Title Server: " + ConvertFloat(float64(getWebStatus.Details.MaimaiDXCNTitle.Uptime*100)) + "%\n * MaimaiDXCN Update Server: " + ConvertFloat(float64(getWebStatus.Details.MaimaiDXCNUpdate.Uptime*100)) + "%\n * MaimaiDXCN NetLogin Server: " + ConvertFloat(getWebStatus.Details.MaimaiDXCNNetLogin.Uptime*100) + "%\n * MaimaiDXCN Net Server: " + ConvertFloat(getWebStatus.Details.MaimaiDXCNDXNet.Uptime*100) + "%\n" ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("* Zlib 压缩跳过率可以很好的反馈当前 MaiNet (Wahlap Service) 当前负载的情况,根据样本 + Lucy处理情况 来判断 \n* 错误率收集则来源于 机台游玩数据,反应各地区真实mai游玩错误情况 \n* 在 1小时 内,Lucy 共处理了 "+getLucyRespHandlerStr+"次 请求💫,其中详细数据如下:\n\n"+getZlibWord+getRealStatus+"\n"+ConvertRealPlayWords(playerStatus)+"\n* Zlib 3% Loss 以下则 基本上可以正常游玩\n* 10% Loss 则会有明显断网现象(请准备小黑屋工具)\n* 30% Loss 则无法正常游玩(即使使用小黑屋工具) ")) }) + engine.OnRegex(`^[! !/](mai|b50)\squery\s(.*)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) { + getDefaultInfo := ctx.State["regex_matched"].([]string)[2] + // CASE: if User Trigger This command, check other settings. + // getQuery: + // level_index | song_type + getLength, getSplitInfo := toolchain.SplitCommandTo(getDefaultInfo, 2) + userSettingInterface := map[string]string{} + var settedSongAlias string + if getLength > 1 { // prefix judge. + settedSongAlias = getSplitInfo[1] + for i, returnLevelValue := range []string{"绿", "黄", "红", "紫", "白"} { + if strings.Contains(getSplitInfo[0], returnLevelValue) { + userSettingInterface["level_index"] = strconv.Itoa(i) + break + } + } + switch { + case strings.Contains(getSplitInfo[0], "dx"): + userSettingInterface["song_type"] = "dx" + case strings.Contains(getSplitInfo[0], "标"): + userSettingInterface["song_type"] = "standard" + } + } else { + // no other infos. || default setting ==> dx Master | std Master | dx expert | std expert (as the highest score) + settedSongAlias = getSplitInfo[0] + } + // get SongID, render. + getUserID := ctx.Event.UserID + getBool := GetUserSwitcherInfoFromDatabase(getUserID) + queryStatus, songIDList, accStat := QueryReferSong(settedSongAlias, getBool) + if queryStatus == false { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("未找到对应歌曲,可能是数据库未收录(")) + return + } + if accStat { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("Lucy 似乎发现了多个结果w 尝试不要使用谐意呢(")) + return + } + // first read the config. + getLevelIndex := userSettingInterface["level_index"] + getSongType := userSettingInterface["song_type"] + var getReferIndexIsOn bool + if getLevelIndex != "" { // use custom diff + getReferIndexIsOn = true + } + + if getBool { // lxns service. + getFriendID := RequestBasicDataFromLxns(getUserID) + if getFriendID.Data.FriendCode == 0 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有绑定哦~ 请查看你是否在 maimai.lxns.net 上绑定了qq并且允许通过qq查看w ")) + return + } + if !getReferIndexIsOn { // no refer then return the last one. + var getReport LxnsMaimaiRequestUserReferBestSong + switch { + case getSongType == "standard": + getReport = RequestReferSong(getFriendID.Data.FriendCode, int64(songIDList[0]), true) + if getReport.Code == 404 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有发现 SD 谱面~ 如不确定可以忽略请求参数, Lucy会自动识别")) + return + } + case getSongType == "dx": + getReport = RequestReferSong(getFriendID.Data.FriendCode, int64(songIDList[0]), false) + if getReport.Code != 404 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有发现 DX 谱面~ 如不确定可以忽略请求参数, Lucy会自动识别")) + return + } + default: + getReport = RequestReferSong(getFriendID.Data.FriendCode, int64(songIDList[0]), false) + if getReport.Code != 200 { + getReport = RequestReferSong(getFriendID.Data.FriendCode, int64(songIDList[0]), true) + } + } + + getReturnTypeLength := len(getReport.Data) + if getReturnTypeLength == 0 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("Lucy 似乎没有查询到你的游玩数据呢(")) + return + } + // DataGet, convert To MaiPlayData Render. + maiRenderPieces := LxnsMaimaiRequestDataPiece{ + Id: getReport.Data[len(getReport.Data)-1].Id, + SongName: getReport.Data[len(getReport.Data)-1].SongName, + Level: getReport.Data[len(getReport.Data)-1].Level, + LevelIndex: getReport.Data[len(getReport.Data)-1].LevelIndex, + Achievements: getReport.Data[len(getReport.Data)-1].Achievements, + Fc: getReport.Data[len(getReport.Data)-1].Fc, + Fs: getReport.Data[len(getReport.Data)-1].Fs, + DxScore: getReport.Data[len(getReport.Data)-1].DxScore, + DxRating: getReport.Data[len(getReport.Data)-1].DxRating, + Rate: getReport.Data[len(getReport.Data)-1].Rate, + Type: getReport.Data[len(getReport.Data)-1].Type, + UploadTime: getReport.Data[len(getReport.Data)-1].UploadTime, + } + getFinalPic := ReCardRenderBase(maiRenderPieces, 0, true) + _ = gg.NewContextForImage(getFinalPic).SavePNG(engine.DataFolder() + "save/" + "LXNS_PIC_" + strconv.Itoa(songIDList[0]) + "_" + strconv.Itoa(int(getUserID)) + ".png") + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image(engine.DataFolder()+"save/"+"LXNS_PIC_"+strconv.Itoa(songIDList[0])+"_"+strconv.Itoa(int(getUserID))+".png")) + } else { + var getReport LxnsMaimaiRequestUserReferBestSongIndex + getLevelIndexToint, _ := strconv.ParseInt(getLevelIndex, 10, 64) + switch { + case getSongType == "standard": + getReport = RequestReferSongIndex(getFriendID.Data.FriendCode, int64(songIDList[0]), getLevelIndexToint, true) + if getReport.Code == 404 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有发现 SD 谱面~ 如不确定可以忽略请求参数, Lucy会自动识别")) + return + } + case getSongType == "dx": + getReport = RequestReferSongIndex(getFriendID.Data.FriendCode, int64(songIDList[0]), getLevelIndexToint, false) + if getReport.Code != 404 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有发现 DX 谱面~ 如不确定可以忽略请求参数, Lucy会自动识别")) + return + } + default: + getReport = RequestReferSongIndex(getFriendID.Data.FriendCode, int64(songIDList[0]), getLevelIndexToint, false) + if getReport.Code != 200 { + getReport = RequestReferSongIndex(getFriendID.Data.FriendCode, int64(songIDList[0]), getLevelIndexToint, true) + } + } + if getReport.Data.SongName == "" { // nil pointer. + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("Lucy 似乎没有查询到你指定难度的游玩数据呢(")) + return + } + maiRenderPieces := LxnsMaimaiRequestDataPiece{ + Id: getReport.Data.Id, + SongName: getReport.Data.SongName, + Level: getReport.Data.Level, + LevelIndex: getReport.Data.LevelIndex, + Achievements: getReport.Data.Achievements, + Fc: getReport.Data.Fc, + Fs: getReport.Data.Fs, + DxScore: getReport.Data.DxScore, + DxRating: getReport.Data.DxRating, + Rate: getReport.Data.Rate, + Type: getReport.Data.Type, + UploadTime: getReport.Data.UploadTime, + } + getFinalPic := ReCardRenderBase(maiRenderPieces, 0, true) + _ = gg.NewContextForImage(getFinalPic).SavePNG(engine.DataFolder() + "save/" + "LXNS_PIC_" + strconv.Itoa(songIDList[0]) + "_" + strconv.Itoa(int(getUserID)) + ".png") + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image(engine.DataFolder()+"save/"+"LXNS_PIC_"+strconv.Itoa(songIDList[0])+"_"+strconv.Itoa(int(getUserID))+".png")) + } + } else { + toint := strconv.Itoa(int(ctx.Event.UserID)) + fullDevData := QueryDevDataFromDivingFish(toint) + // default setting ==> dx Master | std Master | dx expert | std expert (as the highest score) + var ReferSongTypeList []int + switch { + case getSongType == "standard": + for numPosition, index := range fullDevData.Records { + for _, songID := range songIDList { + if index.Type == "SD" && index.SongId == int(songID) { + ReferSongTypeList = append(ReferSongTypeList, numPosition) + } + } + + } + if len(ReferSongTypeList) == 0 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有发现游玩过的 SD 谱面~ 如不确定可以忽略请求参数, Lucy会自动识别")) + return + } + case getSongType == "dx": + for numPosition, index := range fullDevData.Records { + for _, songID := range songIDList { + if index.Type == "DX" && index.SongId == songID { + ReferSongTypeList = append(ReferSongTypeList, numPosition) + } + } + } + if len(ReferSongTypeList) == 0 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有发现游玩过的 DX 谱面~ 如不确定可以忽略请求参数, Lucy会自动识别")) + return + } + + default: // no settings. + for numPosition, index := range fullDevData.Records { + for _, songID := range songIDList { + if index.Type == "SD" && index.SongId == songID { + ReferSongTypeList = append(ReferSongTypeList, numPosition) + } + } + if len(ReferSongTypeList) == 0 { + for numPositionOn, indexOn := range fullDevData.Records { + for _, songID := range songIDList { + if indexOn.Type == "DX" && indexOn.SongId == int(songID) { + ReferSongTypeList = append(ReferSongTypeList, numPositionOn) + } + } + } + } + if len(ReferSongTypeList) == 0 { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("貌似没有发现你玩过这首歌曲呢(")) + return + } + } + + if !getReferIndexIsOn { + // index a map => level_index = "record_diff" + levelIndexMap := map[int]string{} + for _, dataPack := range ReferSongTypeList { + levelIndexMap[fullDevData.Records[dataPack].LevelIndex] = strconv.Itoa(dataPack) + } + var trulyReturnedData string + for i := 4; i >= 0; i-- { + if levelIndexMap[i] != "" { + trulyReturnedData = levelIndexMap[i] + break + } + } + getNum, _ := strconv.Atoi(trulyReturnedData) + // getNum ==> 0 + returnPackage := fullDevData.Records[getNum] + _ = gg.NewContextForImage(RenderCard(returnPackage, 0, true)).SavePNG(engine.DataFolder() + "save/" + strconv.Itoa(songIDList[0]) + "_" + strconv.Itoa(int(getUserID)) + ".png") + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image(engine.DataFolder()+"save/"+strconv.Itoa(int(songIDList[0]))+"_"+strconv.Itoa(int(getUserID))+".png")) + } else { + levelIndexMap := map[int]string{} + for _, dataPack := range ReferSongTypeList { + levelIndexMap[fullDevData.Records[dataPack].LevelIndex] = strconv.Itoa(dataPack) + } + getDiff, _ := strconv.Atoi(userSettingInterface["level_index"]) + + if levelIndexMap[getDiff] != "" { + getNum, _ := strconv.Atoi(levelIndexMap[getDiff]) + returnPackage := fullDevData.Records[getNum] + _ = gg.NewContextForImage(RenderCard(returnPackage, 0, true)).SavePNG(engine.DataFolder() + "save/" + strconv.Itoa(songIDList[0]) + "_" + strconv.Itoa(int(getUserID)) + ".png") + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image(engine.DataFolder()+"save/"+strconv.Itoa(songIDList[0])+"_"+strconv.Itoa(int(getUserID))+".png")) + } else { + ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("貌似你没有玩过这个难度的曲子哦~")) + } + } + } + } + }) } diff --git a/plugin/mai/request.go b/plugin/mai/request.go index 67bb26c..2b961bd 100644 --- a/plugin/mai/request.go +++ b/plugin/mai/request.go @@ -4,8 +4,10 @@ import ( "bytes" "encoding/json" "errors" + "github.com/FloatTech/floatbox/web" "io" "net/http" + "os" ) type DivingFishB50 struct { @@ -24,6 +26,29 @@ type DivingFishB40 struct { Username string `json:"username"` } +type DivingFishDevFullDataRecords struct { + AdditionalRating int `json:"additional_rating"` + Nickname string `json:"nickname"` + Plate string `json:"plate"` + Rating int `json:"rating"` + Records []struct { + Achievements float64 `json:"achievements"` + Ds float64 `json:"ds"` + DxScore int `json:"dxScore"` + Fc string `json:"fc"` + Fs string `json:"fs"` + Level string `json:"level"` + LevelIndex int `json:"level_index"` + LevelLabel string `json:"level_label"` + Ra int `json:"ra"` + Rate string `json:"rate"` + SongId int `json:"song_id"` + Title string `json:"title"` + Type string `json:"type"` + } `json:"records"` + Username string `json:"username"` +} + func QueryMaiBotDataFromQQ(qq int, isB50 bool) (playerdata []byte, err error) { // packed json and sent. var jsonStruct interface{} @@ -110,3 +135,16 @@ func QueryChunDataFromQQ(qq int) (playerdata []byte, err error) { playerData, err := io.ReadAll(resp.Body) return playerData, err } + +func QueryDevDataFromDivingFish(qq string) DivingFishDevFullDataRecords { + getData, err := web.RequestDataWithHeaders(web.NewDefaultClient(), "https://www.diving-fish.com/api/maimaidxprober/dev/player/records?qq="+qq, "GET", func(request *http.Request) error { + request.Header.Add("Developer-Token", os.Getenv("dvkey")) + return nil + }, nil) + if err != nil { + return DivingFishDevFullDataRecords{} + } + var handlerData DivingFishDevFullDataRecords + json.Unmarshal(getData, &handlerData) + return handlerData +} diff --git a/plugin/mai/struct.go b/plugin/mai/struct.go index baf6c3d..1d0974d 100644 --- a/plugin/mai/struct.go +++ b/plugin/mai/struct.go @@ -361,7 +361,7 @@ func FullPageRender(data player, ctx *zero.Ctx) (raw image.Image, stat bool) { getInitY := 285 var i int for i = 0; i < getSDLength; i++ { - b50Render.DrawImage(RenderCard(data.Charts.Sd[i], i+1), getInitX, getInitY) + b50Render.DrawImage(RenderCard(data.Charts.Sd[i], i+1, false), getInitX, getInitY) getInitX += 400 if getInitX == 2045 { getInitX = 45 @@ -369,7 +369,7 @@ func FullPageRender(data player, ctx *zero.Ctx) (raw image.Image, stat bool) { } } for dx := 0; dx < getDXLength; dx++ { - b50Render.DrawImage(RenderCard(data.Charts.Dx[dx], dx+1), getDXinitX, getDXinitY) + b50Render.DrawImage(RenderCard(data.Charts.Dx[dx], dx+1, false), getDXinitX, getDXinitY) getDXinitX += 400 if getDXinitX == 2045 { getDXinitX = 45 @@ -380,7 +380,7 @@ func FullPageRender(data player, ctx *zero.Ctx) (raw image.Image, stat bool) { } // RenderCard Main Lucy Render Page -func RenderCard(data playerData, num int) image.Image { +func RenderCard(data playerData, num int, isSimpleRender bool) image.Image { getType := data.Type var CardBackGround string var multiTypeRender sync.WaitGroup @@ -455,7 +455,9 @@ func RenderCard(data playerData, num int) image.Image { drawBackGround.Fill() drawBackGround.SetFontFace(rankFont) drawBackGround.SetColor(diffColor[data.LevelIndex]) - drawBackGround.DrawString("#"+strconv.Itoa(num), 130, 111) + if !isSimpleRender { + drawBackGround.DrawString("#"+strconv.Itoa(num), 130, 111) + } drawBackGround.FillPreserve() // draw rest of card. drawBackGround.SetFontFace(levelFont) @@ -864,3 +866,41 @@ func ConvertRealPlayWords(retry RealConvertPlay) string { } return header + pickedWords + "\n" } + +func RequestReferSong(friendID int64, songID int64, isSD bool) LxnsMaimaiRequestUserReferBestSong { + var getReferType string + if isSD { + getReferType = "standard" + } else { + getReferType = "dx" + } + getData, err := web.RequestDataWithHeaders(web.NewDefaultClient(), "https://maimai.lxns.net/api/v0/maimai/player/"+strconv.FormatInt(friendID, 10)+"/bests?song_id="+strconv.FormatInt(songID, 10)+"&song_type="+getReferType, "GET", func(request *http.Request) error { + request.Header.Add("Authorization", os.Getenv("lxnskey")) + return nil + }, nil) + if err != nil { + return LxnsMaimaiRequestUserReferBestSong{Success: false} + } + var handlerData LxnsMaimaiRequestUserReferBestSong + json.Unmarshal(getData, &handlerData) + return handlerData +} + +func RequestReferSongIndex(friendID int64, songID int64, diff int64, isSD bool) LxnsMaimaiRequestUserReferBestSongIndex { + var getReferType string + if isSD { + getReferType = "standard" + } else { + getReferType = "dx" + } + getData, err := web.RequestDataWithHeaders(web.NewDefaultClient(), "https://maimai.lxns.net/api/v0/maimai/player/"+strconv.FormatInt(friendID, 10)+"/bests?song_id="+strconv.FormatInt(songID, 10)+"&song_type="+getReferType+"&level_index="+strconv.FormatInt(diff, 10), "GET", func(request *http.Request) error { + request.Header.Add("Authorization", os.Getenv("lxnskey")) + return nil + }, nil) + if err != nil { + return LxnsMaimaiRequestUserReferBestSongIndex{Success: false} + } + var handlerData LxnsMaimaiRequestUserReferBestSongIndex + json.Unmarshal(getData, &handlerData) + return handlerData +}