From 4a0dc59585c0b59b3b0742e66f5672e33885b555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 12 May 2022 12:27:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20saucenao?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 6 +- go.sum | 12 ++- plugin/danbooru/main.go | 10 +-- plugin/saucenao/searcher.go | 142 ++++++++++++++++++++++++++++++------ 4 files changed, 132 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index f9dff3ef..484dab9e 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/FloatTech/ZeroBot-Plugin go 1.18 require ( - github.com/FloatTech/AnimeAPI v1.4.1-0.20220510153300-44a0551f6f51 + github.com/FloatTech/AnimeAPI v1.4.1-0.20220512034947-4dd25b414348 github.com/FloatTech/sqlite v0.2.1 - github.com/FloatTech/zbputils v1.4.0 + github.com/FloatTech/zbputils v1.4.1-0.20220510155433-a0cc1629b1df github.com/antchfx/htmlquery v1.2.4 github.com/corona10/goimagehash v1.0.3 github.com/fogleman/gg v1.3.0 @@ -17,6 +17,7 @@ require ( github.com/fumiama/sqlite3 v1.14.6 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/jinzhu/gorm v1.9.16 + github.com/jozsefsallai/gophersauce v1.0.1 github.com/mroth/weightedrand v0.4.1 github.com/pkumza/numcn v1.0.0 github.com/shirou/gopsutil/v3 v3.22.3 @@ -33,6 +34,7 @@ require ( github.com/antchfx/xpath v1.2.0 // indirect github.com/disintegration/imaging v1.6.2 // indirect github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect + github.com/gabriel-vasile/mimetype v1.0.4 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/google/uuid v1.3.0 // indirect diff --git a/go.sum b/go.sum index dcc8b3df..42e10cd1 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ -github.com/FloatTech/AnimeAPI v1.4.1-0.20220510153300-44a0551f6f51 h1:eTfn1HRSS3l7VmfUGmKjnw6Y1i0xU1asAJsYuv3boyw= -github.com/FloatTech/AnimeAPI v1.4.1-0.20220510153300-44a0551f6f51/go.mod h1:isziaRAqDpCpekOZcOqA/S5PwOGiKYVW1qAZms6cK/Y= +github.com/FloatTech/AnimeAPI v1.4.1-0.20220512034947-4dd25b414348 h1:UQRYPg3hXqF/tcqMMcNKPdgOWkjhfNamC1FXi6e1cek= +github.com/FloatTech/AnimeAPI v1.4.1-0.20220512034947-4dd25b414348/go.mod h1:NAGWR4TXLwEVEx0e8yoMj6j5DS0bNWrFcuATozNkT2I= github.com/FloatTech/sqlite v0.2.1 h1:9t6Me48XJJCIoPy4nLRvcdhcVKfT0c2lilp7SEKROG8= github.com/FloatTech/sqlite v0.2.1/go.mod h1:6NfHRzqOo9RWeMJEoAQVuo51Omd5LFNxCNQhMF02/9U= -github.com/FloatTech/zbputils v1.4.0 h1:zjFiTJ5UHFjnDX6iP+f1KMCO9uqFbDjFFVzW8cyMbe8= -github.com/FloatTech/zbputils v1.4.0/go.mod h1:Cf2wAFtq7OUj4RUHcSQtcAYgAspP06wQseKZwtCJRXQ= +github.com/FloatTech/zbputils v1.4.1-0.20220510155433-a0cc1629b1df h1:zt+Um+D9UqF5SZmYPmklLh7ff/u0ByU53KX1pqlFEhM= +github.com/FloatTech/zbputils v1.4.1-0.20220510155433-a0cc1629b1df/go.mod h1:Cf2wAFtq7OUj4RUHcSQtcAYgAspP06wQseKZwtCJRXQ= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c h1:cNPOdTNiVwxLpROLjXCgbIPvdkE+BwvxDvgmdYmWx6Q= github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c/go.mod h1:KqZzu7slNKROh3TSYEH/IUMG6f4M+1qubZ5e52QypsE= @@ -42,6 +42,8 @@ github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6 github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40= github.com/fumiama/sqlite3 v1.14.6 h1:+e+iygyiDXQJVi7xeXIviBvR7hAc5y20WA9hRwfKn10= github.com/fumiama/sqlite3 v1.14.6/go.mod h1:Xx9a2/OtHuy9pBjow0N+bE/RhNeZ7zZz5xh25vqbA5A= +github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8= +github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= @@ -65,6 +67,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM= +github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= diff --git a/plugin/danbooru/main.go b/plugin/danbooru/main.go index bbb12278..b8dec2c0 100644 --- a/plugin/danbooru/main.go +++ b/plugin/danbooru/main.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "github.com/FloatTech/AnimeAPI/danbooru" - "github.com/FloatTech/AnimeAPI/saucenao" "github.com/FloatTech/zbputils/control" "github.com/FloatTech/zbputils/file" "github.com/FloatTech/zbputils/img/writer" @@ -30,14 +29,7 @@ func init() { // 插件主体 Handle(func(ctx *zero.Ctx) { ctx.SendChain(message.Text("少女祈祷中...")) for _, url := range ctx.State["image_url"].([]string) { - name := "" - r, err := saucenao.SauceNAO(url) - if err != nil { - name = "未知图片" - } else { - name = r[0].Title - } - t, err := danbooru.TagURL(name, url) + t, err := danbooru.TagURL("", url) if err != nil { ctx.SendChain(message.Text("ERROR:", err)) return diff --git a/plugin/saucenao/searcher.go b/plugin/saucenao/searcher.go index 9148780a..e26ecee3 100644 --- a/plugin/saucenao/searcher.go +++ b/plugin/saucenao/searcher.go @@ -3,6 +3,7 @@ package saucenao import ( "fmt" + "os" "strconv" "github.com/sirupsen/logrus" @@ -11,21 +12,41 @@ import ( "github.com/FloatTech/AnimeAPI/ascii2d" "github.com/FloatTech/AnimeAPI/pixiv" - "github.com/FloatTech/AnimeAPI/saucenao" + "github.com/jozsefsallai/gophersauce" + "github.com/FloatTech/zbputils/binary" "github.com/FloatTech/zbputils/control" "github.com/FloatTech/zbputils/ctxext" "github.com/FloatTech/zbputils/file" "github.com/FloatTech/zbputils/img/pool" ) +var ( + saucenaocli *gophersauce.Client +) + func init() { // 插件主体 engine := control.Register("saucenao", &control.Options{ DisableOnDefault: false, Help: "搜图\n" + "- 以图搜图 | 搜索图片 | 以图识图[图片]\n" + "- 搜图[P站图片ID]", + PrivateDataFolder: "saucenao", }) + apikeyfile := engine.DataFolder() + "apikey.txt" + if file.IsExist(apikeyfile) { + key, err := os.ReadFile(apikeyfile) + if err != nil { + panic(err) + } + saucenaocli, err = gophersauce.NewClient(&gophersauce.Settings{ + MaxResults: 1, + APIKey: binary.BytesToString(key), + }) + if err != nil { + panic(err) + } + } // 根据 PID 搜图 engine.OnRegex(`^搜图(\d+)$`).SetBlock(true). Handle(func(ctx *zero.Ctx) { @@ -64,11 +85,11 @@ func init() { // 插件主体 imgs = append(imgs, message.Image("file:///"+f)) } txt := message.Text( - "标题:", illust.Title, "\n", - "插画ID:", illust.Pid, "\n", - "画师:", illust.UserName, "\n", - "画师ID:", illust.UserId, "\n", - "直链:", "https://pixivel.moe/detail?id=", illust.Pid, + "标题: ", illust.Title, "\n", + "插画ID: ", illust.Pid, "\n", + "画师: ", illust.UserName, "\n", + "画师ID: ", illust.UserId, "\n", + "直链: ", "https://pixivel.moe/detail?id=", illust.Pid, ) if imgs != nil { // 发送搜索结果 @@ -87,24 +108,81 @@ func init() { // 插件主体 // 开始搜索图片 ctx.SendChain(message.Text("少女祈祷中......")) for _, pic := range ctx.State["image_url"].([]string) { - if result, err := saucenao.SauceNAO(pic); err != nil { + if saucenaocli != nil { + resp, err := saucenaocli.FromURL(pic) + if err == nil && resp.Count() > 0 { + result := resp.First() + // 返回SauceNAO的结果 + picid := 0 + picidstr := "" + source := "" + switch { + case result.IsPixiv(): + picid = result.Data.PixivID + source = "Pixiv" + case result.IsAniDB(): + picid = result.Data.AniDBAID + source = "AniDB" + case result.IsBcy(): + picid = result.Data.BcyID + source = "Bcy" + case result.IsDanbooru(): + picid = result.Data.DanbooruID + source = "Danbooru" + case result.IsDeviantArt(): + picid = result.Data.DeviantArtID + source = "DeviantArt" + case result.IsIMDb(): + picidstr = result.Data.IMDbID + source = "IMDb" + case result.IsPawoo(): + picid = result.Data.PawooID + source = "Pawoo" + case result.IsSankaku(): + picid = result.Data.SankakuID + source = "Sankaku" + case result.IsSeiga(): + picid = result.Data.SeigaID + source = "Seiga" + } + if picid != 0 { + ctx.SendChain( + message.Text("我有把握是这个!"), + message.Image(result.Header.Thumbnail), + message.Text( + "\n", + "图源: ", source, "\n", + "相似度: ", result.Header.Similarity, "\n", + "标题: ", result.Data.Title, "\n", + "插画ID: ", picid, "\n", + "画师: ", result.Data.MemberName, "\n", + "画师ID: ", result.Data.MemberID, "\n", + "直链: ", "https://pixivel.moe/detail?id=", result.Data.PixivID, + ), + ) + continue + } + if picidstr != "" { + ctx.SendChain( + message.Text("我有把握是这个!"), + message.Image(result.Header.Thumbnail), + message.Text( + "\n", + "图源: ", source, "\n", + "相似度: ", result.Header.Similarity, "\n", + "标题: ", result.Data.Title, "\n", + "插画ID: ", picidstr, "\n", + "画师: ", result.Data.MemberName, "\n", + "画师ID: ", result.Data.MemberID, "\n", + "直链: ", "https://pixivel.moe/detail?id=", result.Data.PixivID, + ), + ) + continue + } + } ctx.SendChain(message.Text("ERROR:", err)) } else { - // 返回SauceNAO的结果 - ctx.SendChain( - message.Text("我有把握是这个!"), - message.Image(result[0].Thumbnail), - message.Text( - "\n", - "相似度:", result[0].Similarity, "\n", - "标题:", result[0].Title, "\n", - "插画ID:", result[0].PixivID, "\n", - "画师:", result[0].MemberName, "\n", - "画师ID:", result[0].MemberID, "\n", - "直链:", "https://pixivel.moe/detail?id=", result[0].PixivID, - ), - ) - continue + ctx.SendChain(message.Text("请私聊发送 设置 saucenao api key [apikey] 以启用 saucenao 搜图, key 请前往 https://saucenao.com/user.php?page=search-api 获取")) } // ascii2d 搜索 if result, err := ascii2d.Ascii2d(pic); err != nil { @@ -116,7 +194,7 @@ func init() { // 插件主体 msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Image(result[i].Thumb), message.Text(fmt.Sprintf( - "标题:%s\n图源:%s\n画师:%s\n画师链接:%s\n图片链接:%s", + "标题: %s\n图源: %s\n画师: %s\n画师链接: %s\n图片链接: %s", result[i].Name, result[i].Type, result[i].AuthNm, @@ -134,4 +212,22 @@ func init() { // 插件主体 } } }) + engine.OnRegex(`^设置\s?saucenao\s?api\s?key\s?([0-9a-f]{40})$`, zero.SuperUserPermission, zero.OnlyPrivate).SetBlock(true). + Handle(func(ctx *zero.Ctx) { + var err error + saucenaocli, err = gophersauce.NewClient(&gophersauce.Settings{ + MaxResults: 1, + APIKey: ctx.State["regex_matched"].([]string)[1], + }) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return + } + err = os.WriteFile(apikeyfile, binary.StringToBytes(saucenaocli.APIKey), 0644) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return + } + ctx.SendChain(message.Text("成功!")) + }) }