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
+}