diff --git a/README.md b/README.md index 57440088..6dd1281d 100644 --- a/README.md +++ b/README.md @@ -752,7 +752,7 @@ print("run[CQ:image,file="+j["img"]+"]") ------插 件 扩 展------ -NeteaseCloudMusicApi项目地址:https://binaryify.github.io/NeteaseCloudMusicApi/#/ + - 本插件内置了[NeteaseCloudMusicApi](https://binaryify.github.io/NeteaseCloudMusicApi/#/)框架的一些功能 - [x] 设置猜歌API帮助 - [x] 设置猜歌API [API首页网址] - [x] 猜歌[开启/关闭][歌单/歌词]自动下载 @@ -1351,6 +1351,29 @@ NeteaseCloudMusicApi项目地址:https://binaryify.github.io/NeteaseCloudMusicAp - [x] 团队七阶猜单词 + +
+ 一些游戏王插件 + + `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo"` + + ##### 白鸽API卡查 + + ###### `"github.com/FloatTech/ZeroBot-Plugin/plugin/ygo/ygocdb.go"` + - [x] /ydp [xxx] + - [x] /yds [xxx] + - [x] /ydb [xxx] + - 注:[xxx]为搜索内容;p:返回一张图片;s:返回一张效果描述;b:高级搜索 + + ##### 集换社卡价查询 + + ###### `"github.com/FloatTech/ZeroBot-Plugin/plugin/ygo/ygotrade.go"` + - [x] 查卡价 [卡名] + - [x] 查卡价 [卡名] [稀有度 稀有度 ...] + - [x] 查卡店 [卡名] + - [x] 查卡店 [卡名] [稀有度] + - 注:卡店只支持单个稀有度查询 +
鬼东西 diff --git a/main.go b/main.go index fcf323af..df2699c5 100644 --- a/main.go +++ b/main.go @@ -136,6 +136,7 @@ import ( _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI" // 百度文心AI画图 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词 + _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo" // 游戏王相关插件 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西 diff --git a/plugin/ygo/ygocdb.go b/plugin/ygo/ygocdb.go new file mode 100644 index 00000000..b2c33569 --- /dev/null +++ b/plugin/ygo/ygocdb.go @@ -0,0 +1,187 @@ +// Package ygo 一些关于ygo的插件 +package ygo + +import ( + "net/url" + "strconv" + "strings" + "time" + + "encoding/json" + + "github.com/FloatTech/floatbox/web" + ctrl "github.com/FloatTech/zbpctrl" + control "github.com/FloatTech/zbputils/control" + zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/message" +) + +const ( + serviceErr = "[ygocdb]error:" + api = "https://ygocdb.com/api/v0/?search=" + picherf = "https://cdn.233.momobako.com/ygopro/pics/" +) + +type searchResult struct { + Result []struct { + Cid int `json:"cid"` + ID int `json:"id"` + CnName string `json:"cn_name"` + // CnocgN string `json:"cnocg_n"` // 简中卡名 + JpName string `json:"jp_name"` + EnName string `json:"en_name"` + Text struct { + Types string `json:"types"` + Pdesc string `json:"pdesc"` + Desc string `json:"desc"` + } `json:"text"` + } `json:"result"` +} + +func init() { + en := control.Register("ygocdb", &ctrl.Options[*zero.Ctx]{ + DisableOnDefault: false, + Brief: "游戏王百鸽API",// 本插件基于游戏王百鸽API"https://www.ygo-sem.cn/" + Help: "- /ydp [xxx]\n" + + "- /yds [xxx]\n" + + "- /ydb [xxx]\n" + + "[xxx]为搜索内容\np:返回一张图片\ns:返回一张效果描述\nb:全显示", + }) + + en.OnRegex(`^/yd(p|s|b)\s?(.*)`).SetBlock(true).Handle(func(ctx *zero.Ctx) { + function := ctx.State["regex_matched"].([]string)[1] + ctxtext := ctx.State["regex_matched"].([]string)[2] + if ctxtext == "" { + ctx.SendChain(message.Text("你是想查询「空手假象」吗?")) + return + } + data, err := web.GetData(api + url.QueryEscape(ctxtext)) + if err != nil { + ctx.SendChain(message.Text(serviceErr, err)) + return + } + var result searchResult + err = json.Unmarshal(data, &result) + if err != nil { + ctx.SendChain(message.Text(serviceErr, err)) + return + } + maxpage := len(result.Result) + switch { + case maxpage == 0: + ctx.SendChain(message.Text("没有找到相关的卡片额")) + return + case function == "p": + ctx.SendChain(message.Image(picherf + strconv.Itoa(result.Result[0].ID) + ".jpg")) + return + case function == "s": + cardtextout := cardtext(result, 0) + ctx.SendChain(message.Text(cardtextout)) + return + case function == "d" && maxpage == 1: + cardtextout := cardtext(result, 0) + ctx.SendChain(message.Image(picherf+strconv.Itoa(result.Result[0].ID)+".jpg"), message.Text(cardtextout)) + return + } + var listName []string + var listid []int + for _, v := range result.Result { + listName = append(listName, strconv.Itoa(len(listName))+"."+v.CnName) + listid = append(listid, v.ID) + } + var ( + currentPage = 10 + nextpage = 0 + ) + if maxpage < 10 { + currentPage = maxpage + } + ctx.SendChain(message.Text("找到", strconv.Itoa(maxpage), "张相关卡片,当前显示以下卡名:\n", + strings.Join(listName[:currentPage], "\n"), + "\n————————————\n输入对应数字获取卡片信息,", + "\n或回复“取消”、“下一页”指令")) + recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`(取消)|(下一页)|\d+`), zero.OnlyGroup, zero.CheckUser(ctx.Event.UserID)).Repeat() + after := time.NewTimer(20 * time.Second) + for { + select { + case <-after.C: + cancel() + ctx.Send( + message.ReplyWithMessage(ctx.Event.MessageID, + message.Text("等待超时,搜索结束"), + ), + ) + return + case e := <-recv: + nextcmd := e.Event.Message.String() + switch nextcmd { + case "取消": + cancel() + after.Stop() + ctx.Send( + message.ReplyWithMessage(ctx.Event.MessageID, + message.Text("用户取消,搜索结束"), + ), + ) + return + case "下一页": + after.Reset(20 * time.Second) + if maxpage < 11 { + continue + } + nextpage++ + if nextpage*10 >= maxpage { + nextpage = 0 + currentPage = 10 + ctx.SendChain(message.Text("已是最后一页,返回到第一页")) + } else if nextpage == maxpage/10 { + currentPage = maxpage % 10 + } + ctx.SendChain(message.Text("找到", strconv.Itoa(maxpage), "张相关卡片,当前显示以下卡名:\n", + strings.Join(listName[nextpage*10:nextpage*10+currentPage], "\n"), + "\n————————————————\n输入对应数字获取卡片信息,", + "\n或回复“取消”、“下一页”指令")) + default: + cardint, err := strconv.Atoi(nextcmd) + switch { + case err != nil: + after.Reset(20 * time.Second) + ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号")) + default: + if cardint < nextpage*10+currentPage { + cancel() + after.Stop() + cardtextout := cardtext(result, cardint) + ctx.SendChain(message.Image(picherf+strconv.Itoa(listid[cardint])+".jpg"), message.Text(cardtextout)) + return + } + after.Reset(20 * time.Second) + ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号")) + } + } + } + } + }) +} + +func cardtext(list searchResult, cardid int) string { + var cardtext []string + cardtext = append(cardtext, "中文卡名:\n "+list.Result[cardid].CnName) + if list.Result[cardid].JpName == "" { + cardtext = append(cardtext, "英文卡名:\n "+list.Result[cardid].EnName) + } else { + cardtext = append(cardtext, "日文卡名:\n "+list.Result[cardid].JpName) + } + cardtext = append(cardtext, "卡片密码:"+strconv.Itoa(list.Result[cardid].ID)) + cardtext = append(cardtext, list.Result[cardid].Text.Types) + if list.Result[cardid].Text.Pdesc != "" { + cardtext = append(cardtext, "[灵摆效果]\n"+list.Result[cardid].Text.Pdesc) + if strings.Contains(list.Result[cardid].Text.Types, "效果") { + cardtext = append(cardtext, "[怪兽效果]") + } else { + cardtext = append(cardtext, "[怪兽描述]") + } + } + cardtext = append(cardtext, list.Result[cardid].Text.Desc) + return strings.Join(cardtext, "\n") +} diff --git a/plugin/ygo/ygotrade.go b/plugin/ygo/ygotrade.go new file mode 100644 index 00000000..95d56cb6 --- /dev/null +++ b/plugin/ygo/ygotrade.go @@ -0,0 +1,145 @@ +// Package ygo 一些关于ygo的插件 +package ygo + + +import ( + "encoding/json" + "errors" + "net/url" + "strconv" + "strings" + + "github.com/FloatTech/floatbox/web" + ctrl "github.com/FloatTech/zbpctrl" + "github.com/FloatTech/zbputils/control" + "github.com/FloatTech/zbputils/ctxext" + zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/message" +) + +const ( + rarityTrade = "https://api.jihuanshe.com/api/market/search/match-product?game_key=ygo&game_sub_key=ocg&page=1&keyword=" + storeTrade = "https://api.jihuanshe.com/api/market/card-versions/products?game_key=ygo&game_sub_key=ocg&page=1&condition=1&card_version_id=" +) + +type apiInfo struct { + Data []tradeInfo `json:"data"` +} + +type tradeInfo struct { + // 卡片信息 + ID int `json:"id"` + NameCn string `json:"name_cn"` + CardID int `json:"card_id"` + Number string `json:"number"` + Rarity string `json:"rarity"` + ImageURL string `json:"image_url"` + MinPrice string `json:"min_price"` + // 卡店信息 + SellerUserID int `json:"seller_user_id"` + SellerUsername string `json:"seller_username"` + SellerUserAvatar string `json:"seller_user_avatar"` + SellerProvince string `json:"seller_province"` + SellerCity string `json:"seller_city"` + SellerCreditRank string `json:"seller_credit_rank"` + Quantity string `json:"quantity"` + CardVersionImage string `json:"card_version_image"` +} + +func init() { + engine := control.Register("ygotrade", &ctrl.Options[*zero.Ctx]{ + DisableOnDefault: false, + Brief: "游戏王卡价查询",// 本插件基于集换社API + Help: "- 查卡价 [卡名]\n- 查卡价 [卡名] [稀有度 稀有度 ...]\n- 查卡店 [卡名]\n- 查卡店 [卡名] [稀有度]", + }).ApplySingle(ctxext.DefaultSingle) + engine.OnPrefix("查卡价", func(ctx *zero.Ctx) bool { + ctx.State["args"] = strings.TrimSpace(ctx.State["args"].(string)) + return ctx.State["args"].(string) != "" + }).SetBlock(true).Handle(func(ctx *zero.Ctx) { + cardName, rarity, _ := strings.Cut(ctx.State["args"].(string), " ") + listOfTrace, err := getRarityTrade(cardName, rarity) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return + } + msg := make(message.Message, len(listOfTrace)) + for i := 0; i < len(listOfTrace); i++ { + msg[i] = ctxext.FakeSenderForwardNode(ctx, message.Text( + "卡名:", listOfTrace[i].NameCn, + "\nID:", listOfTrace[i].ID, + "\n卡序:", listOfTrace[i].Number, + "\n罕贵度:", listOfTrace[i].Rarity, + "\n当前最低价:", listOfTrace[i].MinPrice), + message.Image(listOfTrace[i].ImageURL)) + } + if id := ctx.Send(msg); id.ID() == 0 { + ctx.SendChain(message.Text("ERROR: 可能被风控了")) + } + }) + engine.OnPrefix("查卡店", func(ctx *zero.Ctx) bool { + ctx.State["args"] = strings.TrimSpace(ctx.State["args"].(string)) + return ctx.State["args"].(string) != "" + }).SetBlock(true).Handle(func(ctx *zero.Ctx) { + cardName, rarity, _ := strings.Cut(ctx.State["args"].(string), " ") + if strings.Count(rarity, " ") > 0 { + ctx.SendChain(message.Text("ERROR: ", "卡店查询不支持查找多个罕贵度")) + return + } + listOfTrace, err := getRarityTrade(cardName, rarity) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return + } + listStroe, err := getStoreTrade(listOfTrace[0].ID) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return + } + msg := make(message.Message, len(listStroe)) + for i := 0; i < len(listStroe); i++ { + msg[i] = ctxext.FakeSenderForwardNode(ctx, message.Text( + "卖家名:", listStroe[i].SellerUsername, + "\nID:", listStroe[i].SellerUserID, + "\n地区:", listStroe[i].SellerCity, + "\n信誉度:", listStroe[i].SellerCreditRank, + "\n数量:", listStroe[i].Quantity, + "\n当前最低价:", listStroe[i].MinPrice), + message.Image(listStroe[i].CardVersionImage)) + } + if id := ctx.Send(msg); id.ID() == 0 { + ctx.SendChain(message.Text("ERROR: 可能被风控了")) + } + }) +} + +// 获取卡名该罕贵度卡片数据 +func getRarityTrade(key, rarity string) (tradeInfo []tradeInfo, err error) { + listOfTrace, err := web.GetData(rarityTrade + url.QueryEscape(key) + "&rarity=" + url.QueryEscape(rarity)) + if err != nil { + return + } + var apiInfo apiInfo + err = json.Unmarshal(listOfTrace, &apiInfo) + if len(apiInfo.Data) == 0 { + err = errors.New("没有找到相关卡片或输入参数错误") + return + } + tradeInfo = apiInfo.Data + return +} + +// 获取卡店卡片数据 +func getStoreTrade(cardID int) (stroeInfo []tradeInfo, err error) { + listOfTrace, err := web.GetData(storeTrade + url.QueryEscape(strconv.Itoa(cardID))) + if err != nil { + return + } + var apiInfo apiInfo + err = json.Unmarshal(listOfTrace, &apiInfo) + if len(apiInfo.Data) == 0 { + err = errors.New("没有找到相关卡片或输入参数错误") + return + } + stroeInfo = apiInfo.Data + return +}