diff --git a/README.md b/README.md index f47aa0a5..fcead96e 100644 --- a/README.md +++ b/README.md @@ -971,6 +971,8 @@ print("run[CQ:image,file="+j["img"]+"]") - [x] 搜图[P站图片ID] + - [x] 设置 saucenao api key [apikey] +
叔叔的AI二次元图片放大 diff --git a/go.mod b/go.mod index f3d6c247..a43caade 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/Coloured-glaze/gg v1.3.4 - github.com/FloatTech/AnimeAPI v1.5.1-0.20221004094358-91497e10dd03 + github.com/FloatTech/AnimeAPI v1.5.1-0.20221005032016-95a00a04e77a github.com/FloatTech/floatbox v0.0.0-20221004092550-1ebf9b4e6198 github.com/FloatTech/sqlite v0.4.0 github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b @@ -71,7 +71,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/exp/shiny v0.0.0-20220916125017-b168a2c6b86b // indirect + golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741 // indirect golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect diff --git a/go.sum b/go.sum index a0b59522..21f32013 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/Coloured-glaze/gg v1.3.4 h1:l31zIF/HaVwkzjrj+A56RGQoSKyKuR1IWtIrqXGFStI= github.com/Coloured-glaze/gg v1.3.4/go.mod h1:Ih5NLNNDHOy3RJbB0EPqGTreIzq/H02TGThIagh8HJg= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/FloatTech/AnimeAPI v1.5.1-0.20221004094358-91497e10dd03 h1:BDFRtCpTlJxrEpV26VMauAIURqa5L4BD728L6n0xpvM= -github.com/FloatTech/AnimeAPI v1.5.1-0.20221004094358-91497e10dd03/go.mod h1:wY11pOy/T2MBXIGSbYHaynyGzU4Pxz0X2hGPmnlUCCk= +github.com/FloatTech/AnimeAPI v1.5.1-0.20221005032016-95a00a04e77a h1:h/w9FS4DpGyL79n1BLSjhUwypA/6UcmbRUPipevJqjU= +github.com/FloatTech/AnimeAPI v1.5.1-0.20221005032016-95a00a04e77a/go.mod h1:dKSyHtapX1oXFysIwCq9unuKK4wcxDYAZnZvjfE6Ne8= github.com/FloatTech/floatbox v0.0.0-20221004092550-1ebf9b4e6198 h1:AkwB7LKMK74yS5rIERhOQbJosDgOefJBSkhEiMbyr+A= github.com/FloatTech/floatbox v0.0.0-20221004092550-1ebf9b4e6198/go.mod h1:4UDl6E/I2HqAqRnKdsxxfO28fkqGo3CzFOP2BhyI6ag= github.com/FloatTech/sqlite v0.4.0 h1:fvQ1vc7fw99jYXccs5KItMluy7QL1t6NxbkH7aN1F4g= @@ -209,8 +209,8 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/exp/shiny v0.0.0-20220916125017-b168a2c6b86b h1:MJd2zuDfsuomOxzoB2i4Gs8s3V9gqJEHl+hcKRV2+oI= -golang.org/x/exp/shiny v0.0.0-20220916125017-b168a2c6b86b/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8= +golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741 h1:b7y8iQCnzOE0NhgpMj2yHw17Us+lhXxFbdzKlTpqm5I= +golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8= golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= diff --git a/plugin/danbooru/main.go b/plugin/danbooru/main.go index 8596c771..c82ce094 100644 --- a/plugin/danbooru/main.go +++ b/plugin/danbooru/main.go @@ -5,7 +5,6 @@ import ( "crypto/md5" "encoding/hex" - "github.com/FloatTech/AnimeAPI/danbooru" "github.com/FloatTech/floatbox/file" "github.com/FloatTech/floatbox/img/writer" ctrl "github.com/FloatTech/zbpctrl" @@ -30,7 +29,7 @@ func init() { // 插件主体 Handle(func(ctx *zero.Ctx) { ctx.SendChain(message.Text("少女祈祷中...")) for _, url := range ctx.State["image_url"].([]string) { - t, err := danbooru.TagURL("", url) + t, err := tagurl("", url) if err != nil { ctx.SendChain(message.Text("ERROR: ", err)) return diff --git a/plugin/danbooru/tag.go b/plugin/danbooru/tag.go new file mode 100644 index 00000000..45529c2b --- /dev/null +++ b/plugin/danbooru/tag.go @@ -0,0 +1,118 @@ +package deepdanbooru + +import ( + "bytes" + "encoding/json" + "fmt" + "image" + "net/url" + "sort" + + "github.com/Coloured-glaze/gg" + "github.com/FloatTech/floatbox/file" + "github.com/FloatTech/floatbox/web" + imgutils "github.com/FloatTech/zbputils/img" + "github.com/FloatTech/zbputils/img/text" // jpg png gif + _ "golang.org/x/image/webp" +) + +const api = "https://nsfwtag.azurewebsites.net/api/tag?limit=0.5&url=" + +type sorttags struct { + tags map[string]float64 + tseq []string +} + +func newsorttags(tags map[string]float64) (s *sorttags) { + t := make([]string, 0, len(tags)) + for k := range tags { + t = append(t, k) + } + return &sorttags{tags: tags, tseq: t} +} + +func (s *sorttags) Len() int { + return len(s.tags) +} + +func (s *sorttags) Less(i, j int) bool { + v1 := s.tseq[i] + v2 := s.tseq[j] + return s.tags[v1] >= s.tags[v2] +} + +// Swap swaps the elements with indexes i and j. +func (s *sorttags) Swap(i, j int) { + s.tseq[j], s.tseq[i] = s.tseq[i], s.tseq[j] +} + +func tagurl(name, u string) (im image.Image, err error) { + ch := make(chan []byte, 1) + go func() { + var data []byte + data, err = web.GetData(u) + ch <- data + }() + + data, err := web.GetData(api + url.QueryEscape(u)) + if err != nil { + return + } + tags := make(map[string]float64) + err = json.Unmarshal(bytes.ReplaceAll(data, []byte("'"), []byte("\"")), &tags) + if err != nil { + return + } + + longestlen := 0 + for k := range tags { + if len(k) > longestlen { + longestlen = len(k) + } + } + longestlen++ + + st := newsorttags(tags) + sort.Sort(st) + + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return + } + _, err = file.GetLazyData(text.ConsolasFontFile, true) + if err != nil { + return + } + + data = <-ch + if err != nil { + return + } + img, _, err := image.Decode(bytes.NewReader(data)) + if err != nil { + return + } + + img = imgutils.Limit(img, 1280, 720) + + canvas := gg.NewContext(img.Bounds().Size().X, img.Bounds().Size().Y+int(float64(img.Bounds().Size().X)*0.2)+len(tags)*img.Bounds().Size().X/25) + canvas.SetRGB(1, 1, 1) + canvas.Clear() + canvas.DrawImage(img, 0, 0) + if err = canvas.LoadFontFace(text.BoldFontFile, float64(img.Bounds().Size().X)*0.1); err != nil { + return + } + canvas.SetRGB(0, 0, 0) + canvas.DrawString(name, float64(img.Bounds().Size().X)*0.02, float64(img.Bounds().Size().Y)+float64(img.Bounds().Size().X)*0.1) + i := float64(img.Bounds().Size().Y) + float64(img.Bounds().Size().X)*0.2 + if err = canvas.LoadFontFace(text.ConsolasFontFile, float64(img.Bounds().Size().X)*0.04); err != nil { + return + } + rate := float64(img.Bounds().Size().X) * 0.04 + for _, k := range st.tseq { + canvas.DrawString(fmt.Sprintf("* %-*s -%.3f-", longestlen, k, tags[k]), float64(img.Bounds().Size().X)*0.04, i) + i += rate + } + im = canvas.Image() + return +} diff --git a/plugin/saucenao/searcher.go b/plugin/saucenao/searcher.go index 2b33325d..ea43ad94 100644 --- a/plugin/saucenao/searcher.go +++ b/plugin/saucenao/searcher.go @@ -154,7 +154,7 @@ func init() { // 插件主体 } } } else { - ctx.SendChain(message.Text("请私聊发送 设置 saucenao api key [apikey] 以启用 saucenao 搜图, key 请前往 https://saucenao.com/user.php?page=search-api 获取")) + 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 {