├── .gitignore ├── README.md ├── go.mod ├── go.sum ├── main.go └── plugin_gif ├── gif.go ├── other.go ├── png.go └── run.go /.gitignore: -------------------------------------------------------------------------------- 1 | data/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZeroBot-Plugin-Gif 2 | [ZeroBot QQ机器人](https://github.com/wdvxdr1123/ZeroBot)插件,可以制作各种沙雕gif图 3 | >素材包地址:https://github.com/tdf1939/sucai 4 | 5 | 6 | 触发方式分3种: 7 | 1. [指令词]+[qq号] 如:爬123456 8 | 2. [指令词]+[图片] 如:爬[图片] 9 | 3. [指令词]+[艾特] 如:爬@小H 10 | 11 | ![-957d0bbdfaaae62](https://user-images.githubusercontent.com/24691568/129891611-579da8ec-6dc3-40ac-8303-29bbc266dea1.png) 12 | 13 | 14 | - [x] 爬 15 | - [x] 冲 16 | - [x] 摸 17 | - [x] 搓 18 | - [x] 拍 19 | - [x] 丢 20 | - [x] 敲 21 | - [x] 吃 22 | - [x] 啃 23 | - [x] 撕 24 | - [x] 蹭 25 | - [ ] 亲 26 | - [x] 一直 27 | - [x] 灰度 28 | - [x] 上翻 29 | - [x] 下翻 30 | - [x] 左翻 31 | - [x] 右翻 32 | - [x] 反色 33 | - [x] 倒放 34 | - [x] 浮雕 35 | - [x] 打码 36 | - [x] 负片 37 | 38 | ## 其他插件推荐: 39 | 1. 炉石插件:https://github.com/tdf1939/ZeroBot-Plugin-HS 40 | 2. ZeroBot实用插件合集:https://github.com/FloatTech/ZeroBot-Plugin 41 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tdf1939/ZeroBot-Plugin-Gif 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/disintegration/imaging v1.6.2 // indirect 7 | github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect 8 | github.com/fogleman/gg v1.3.0 // indirect 9 | github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect 10 | github.com/sirupsen/logrus v1.8.1 11 | github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 12 | github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3 // indirect 13 | github.com/wdvxdr1123/ZeroBot v1.2.2 14 | golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= 5 | github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= 6 | github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU= 7 | github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM= 8 | github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= 9 | github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= 10 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 11 | github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= 12 | github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= 13 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 14 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 15 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 16 | github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= 17 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 18 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 19 | github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= 20 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 21 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 22 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 23 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 24 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 25 | github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b h1:6Xjqolv/0DDdUqlpnsTomXQvjvvkz7Ux7TcMALvozEw= 26 | github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 27 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 28 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 29 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 30 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 31 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 32 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 33 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 34 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 35 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 36 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 37 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 38 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 39 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 40 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 41 | github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= 42 | github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk= 43 | github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA= 44 | github.com/tdf1939/img v0.0.0-20210819110805-f023acf32347 h1:PWqtKJx/Xbl6d5nZIdZRKvghv1UhqLabHMNOZH/uJkM= 45 | github.com/tdf1939/img v0.0.0-20210819110805-f023acf32347/go.mod h1:FgTEOcosTWrkOr7++gbtPSj1rX5loRWrf/AL+hm3Cnw= 46 | github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3 h1:DUQxv4Ua1sb0/zOkExNJ/MSJcSnbZ7WT9thXCPWTh5U= 47 | github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3/go.mod h1:FgTEOcosTWrkOr7++gbtPSj1rX5loRWrf/AL+hm3Cnw= 48 | github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ= 49 | github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= 50 | github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= 51 | github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 52 | github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= 53 | github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= 54 | github.com/wdvxdr1123/ZeroBot v1.2.2 h1:BKEy3l80BMrQWpFWaII0AfFMyf9bqrB0TxfWhTdoV58= 55 | github.com/wdvxdr1123/ZeroBot v1.2.2/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc= 56 | golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= 57 | golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 58 | golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= 59 | golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= 60 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 61 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 62 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 63 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 64 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= 65 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 66 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 67 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 68 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 69 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 70 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 71 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 72 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 73 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 74 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 75 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | 8 | _ "github.com/tdf1939/ZeroBot-Plugin-Gif/plugin_gif" 9 | 10 | // 以下为内置依赖,勿动 11 | log "github.com/sirupsen/logrus" 12 | easy "github.com/t-tomalak/logrus-easy-formatter" 13 | zero "github.com/wdvxdr1123/ZeroBot" 14 | "github.com/wdvxdr1123/ZeroBot/driver" 15 | ) 16 | 17 | var ( 18 | contents = []string{ 19 | "* OneBot + ZeroBot + Golang ", 20 | "* Version 1.1.0 - 2021-08-06 23:36:29 +0800 CST", 21 | "* Copyright © 2020 - 2021 Kanri, DawnNights, Fumiama, Suika", 22 | "* Project: https://github.com/FloatTech/ZeroBot-Plugin", 23 | } 24 | banner = strings.Join(contents, "\n") 25 | ) 26 | 27 | func init() { 28 | log.SetFormatter(&easy.Formatter{ 29 | TimestampFormat: "2006-01-02 15:04:05", 30 | LogFormat: "[zero][%time%][%lvl%]: %msg% \n", 31 | }) 32 | log.SetLevel(log.DebugLevel) 33 | } 34 | 35 | func main() { 36 | fmt.Print( 37 | "======================[ZeroBot-Plugin]======================", 38 | "\n", banner, "\n", 39 | "============================================================\n", 40 | ) // 启动打印 41 | zero.Run(zero.Config{ 42 | NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"}, 43 | CommandPrefix: "/", 44 | 45 | // SuperUsers 某些功能需要主人权限,可通过以下两种方式修改 46 | // []string{}:通过代码写死的方式添加主人账号 47 | // os.Args[1:]:通过命令行参数的方式添加主人账号 48 | SuperUsers: append([]string{"12345678", "87654321"}, os.Args[1:]...), 49 | 50 | Driver: []zero.Driver{ 51 | &driver.WSClient{ 52 | // OneBot 正向WS 默认使用 6700 端口 53 | Url: "ws://127.0.0.1:6700", 54 | AccessToken: "", 55 | }, 56 | }, 57 | }) 58 | 59 | // 帮助 60 | zero.OnFullMatchGroup([]string{"help", "/help", ".help", "菜单", "帮助"}, zero.OnlyToMe).SetBlock(false).SetPriority(999). 61 | Handle(func(ctx *zero.Ctx) { 62 | ctx.Send(banner) 63 | }) 64 | select {} 65 | } 66 | -------------------------------------------------------------------------------- /plugin_gif/gif.go: -------------------------------------------------------------------------------- 1 | package plugin_gif 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "image" 7 | "image/gif" 8 | 9 | "github.com/tdf1939/img" 10 | ) 11 | 12 | // GIF 转 base64 13 | func encodeGIF(g *gif.GIF) ([]byte, error) { 14 | buffer := new(bytes.Buffer) 15 | encoder := base64.NewEncoder(base64.StdEncoding, buffer) 16 | err := gif.EncodeAll(encoder, g) 17 | if err != nil { 18 | return nil, err 19 | } 20 | encoder.Close() 21 | return buffer.Bytes(), nil 22 | } 23 | 24 | // 摸 25 | func mo(pngs ...string) ([]byte, error) { 26 | tou := img.ImDc(pngs[0], 0, 0).Circle(0).Im 27 | mo := []*image.NRGBA{ 28 | img.ImDc(DLSc("mo/0.png"), 0, 0).DstOver(tou, 80, 80, 32, 32).Im, 29 | img.ImDc(DLSc("mo/1.png"), 0, 0).DstOver(tou, 70, 90, 42, 22).Im, 30 | img.ImDc(DLSc("mo/2.png"), 0, 0).DstOver(tou, 75, 85, 37, 27).Im, 31 | img.ImDc(DLSc("mo/3.png"), 0, 0).DstOver(tou, 85, 75, 27, 37).Im, 32 | img.ImDc(DLSc("mo/4.png"), 0, 0).DstOver(tou, 90, 70, 22, 42).Im, 33 | } 34 | return encodeGIF(img.AndGif(1, mo)) 35 | } 36 | 37 | // 搓 38 | func cuo(pngs ...string) ([]byte, error) { 39 | tou := img.ImDc(pngs[0], 110, 110).Circle(0).Im 40 | m1 := img.Rotate(tou, 72, 0, 0) 41 | m2 := img.Rotate(tou, 144, 0, 0) 42 | m3 := img.Rotate(tou, 216, 0, 0) 43 | m4 := img.Rotate(tou, 288, 0, 0) 44 | cuo := []*image.NRGBA{ 45 | img.ImDc(DLSc("cuo/0.png"), 0, 0).DstOverC(tou, 0, 0, 75, 130).Im, 46 | img.ImDc(DLSc("cuo/1.png"), 0, 0).DstOverC(m1.Im, 0, 0, 75, 130).Im, 47 | img.ImDc(DLSc("cuo/2.png"), 0, 0).DstOverC(m2.Im, 0, 0, 75, 130).Im, 48 | img.ImDc(DLSc("cuo/3.png"), 0, 0).DstOverC(m3.Im, 0, 0, 75, 130).Im, 49 | img.ImDc(DLSc("cuo/4.png"), 0, 0).DstOverC(m4.Im, 0, 0, 75, 130).Im, 50 | } 51 | return encodeGIF(img.AndGif(5, cuo)) 52 | } 53 | 54 | // 敲 55 | func qiao(pngs ...string) ([]byte, error) { 56 | tou := img.ImDc(pngs[0], 40, 40).Circle(0).Im 57 | qiao := []*image.NRGBA{ 58 | img.ImDc(DLSc("qiao/0.png"), 0, 0).Over(tou, 40, 33, 57, 52).Im, 59 | img.ImDc(DLSc("qiao/1.png"), 0, 0).Over(tou, 38, 36, 58, 50).Im, 60 | } 61 | return encodeGIF(img.AndGif(1, qiao)) 62 | } 63 | 64 | // 吃 65 | func chi(pngs ...string) ([]byte, error) { 66 | tou := img.ImDc(pngs[0], 32, 32).Im 67 | chi := []*image.NRGBA{ 68 | img.ImDc(DLSc("chi/0.png"), 0, 0).DstOver(tou, 0, 0, 1, 38).Im, 69 | img.ImDc(DLSc("chi/1.png"), 0, 0).DstOver(tou, 0, 0, 1, 38).Im, 70 | img.ImDc(DLSc("chi/2.png"), 0, 0).DstOver(tou, 0, 0, 1, 38).Im, 71 | } 72 | return encodeGIF(img.AndGif(1, chi)) 73 | } 74 | 75 | // 蹭 76 | func ceng(pngs ...string) ([]byte, error) { 77 | tou := img.ImDc(pngs[0], 100, 100).Circle(0).Im 78 | tou2 := img.ImDc(pngs[1], 100, 100).Circle(0).Im 79 | ceng := []*image.NRGBA{ 80 | img.ImDc(DLSc("ceng/0.png"), 0, 0).Over(tou, 75, 77, 40, 88).Over(tou2, 77, 103, 102, 81).Im, 81 | img.ImDc(DLSc("ceng/1.png"), 0, 0).Over(tou, 75, 77, 46, 100).Over(img.Rotate(tou2, 10, 62, 127).Im, 0, 0, 92, 40).Im, 82 | img.ImDc(DLSc("ceng/2.png"), 0, 0).Over(tou, 75, 77, 67, 99).Over(tou2, 76, 117, 90, 8).Im, 83 | img.ImDc(DLSc("ceng/3.png"), 0, 0).Over(tou, 75, 77, 52, 83).Over(img.Rotate(tou2, -40, 94, 94).Im, 0, 0, 53, -20).Im, 84 | img.ImDc(DLSc("ceng/4.png"), 0, 0).Over(tou, 75, 77, 56, 110).Over(img.Rotate(tou2, -66, 132, 80).Im, 0, 0, 78, 40).Im, 85 | img.ImDc(DLSc("ceng/5.png"), 0, 0).Over(tou, 75, 77, 62, 102).Over(tou2, 71, 100, 110, 94).Im, 86 | } 87 | return encodeGIF(img.AndGif(8, ceng)) 88 | } 89 | 90 | // 啃 91 | func ken(pngs ...string) ([]byte, error) { 92 | tou := img.ImDc(pngs[0], 100, 100).Im 93 | ken := []*image.NRGBA{ 94 | img.ImDc(DLSc("ken/0.png"), 0, 0).DstOver(tou, 90, 90, 105, 150).Im, 95 | img.ImDc(DLSc("ken/1.png"), 0, 0).DstOver(tou, 90, 83, 96, 172).Im, 96 | img.ImDc(DLSc("ken/2.png"), 0, 0).DstOver(tou, 90, 90, 106, 148).Im, 97 | img.ImDc(DLSc("ken/3.png"), 0, 0).DstOver(tou, 88, 88, 97, 167).Im, 98 | img.ImDc(DLSc("ken/4.png"), 0, 0).DstOver(tou, 90, 85, 89, 179).Im, 99 | img.ImDc(DLSc("ken/5.png"), 0, 0).DstOver(tou, 90, 90, 106, 151).Im, 100 | img.ImDc(DLSc("ken/6.png"), 0, 0).Im, 101 | img.ImDc(DLSc("ken/7.png"), 0, 0).Im, 102 | img.ImDc(DLSc("ken/8.png"), 0, 0).Im, 103 | img.ImDc(DLSc("ken/9.png"), 0, 0).Im, 104 | img.ImDc(DLSc("ken/10.png"), 0, 0).Im, 105 | img.ImDc(DLSc("ken/11.png"), 0, 0).Im, 106 | img.ImDc(DLSc("ken/12.png"), 0, 0).Im, 107 | img.ImDc(DLSc("ken/13.png"), 0, 0).Im, 108 | img.ImDc(DLSc("ken/14.png"), 0, 0).Im, 109 | img.ImDc(DLSc("ken/15.png"), 0, 0).Im, 110 | } 111 | return encodeGIF(img.AndGif(7, ken)) 112 | } 113 | 114 | // 拍 115 | func pai(pngs ...string) ([]byte, error) { 116 | tou := img.ImDc(pngs[0], 30, 30).Circle(0).Im 117 | pai := []*image.NRGBA{ 118 | img.ImDc(DLSc("pai/0.png"), 0, 0).Over(tou, 0, 0, 1, 47).Im, 119 | img.ImDc(DLSc("pai/1.png"), 0, 0).Over(tou, 0, 0, 1, 67).Im, 120 | } 121 | return encodeGIF(img.AndGif(1, pai)) 122 | } 123 | 124 | // 冲 125 | func chong(pngs ...string) ([]byte, error) { 126 | tou := img.ImDc(pngs[0], 0, 0).Circle(0).Im 127 | chong := []*image.NRGBA{ 128 | img.ImDc(DLSc("xqe/0.png"), 0, 0).Over(tou, 30, 30, 15, 53).Im, 129 | img.ImDc(DLSc("xqe/1.png"), 0, 0).Over(tou, 30, 30, 40, 53).Im, 130 | } 131 | return encodeGIF(img.AndGif(1, chong)) 132 | } 133 | 134 | // 丢 135 | func diu(pngs ...string) ([]byte, error) { 136 | tou := img.ImDc(pngs[0], 0, 0).Circle(0).Im 137 | diu := []*image.NRGBA{ 138 | img.ImDc(DLSc("diu/0.png"), 0, 0).Over(tou, 32, 32, 108, 36).Im, 139 | img.ImDc(DLSc("diu/1.png"), 0, 0).Over(tou, 32, 32, 122, 36).Im, 140 | img.ImDc(DLSc("diu/2.png"), 0, 0).Im, 141 | img.ImDc(DLSc("diu/3.png"), 0, 0).Over(tou, 123, 123, 19, 129).Im, 142 | img.ImDc(DLSc("diu/4.png"), 0, 0).Over(tou, 185, 185, -50, 200).Over(tou, 33, 33, 289, 70).Im, 143 | img.ImDc(DLSc("diu/5.png"), 0, 0).Over(tou, 32, 32, 280, 73).Im, 144 | img.ImDc(DLSc("diu/6.png"), 0, 0).Over(tou, 35, 35, 259, 31).Im, 145 | img.ImDc(DLSc("diu/7.png"), 0, 0).Over(tou, 175, 175, -50, 220).Im, 146 | } 147 | return encodeGIF(img.AndGif(7, diu)) 148 | } 149 | -------------------------------------------------------------------------------- /plugin_gif/other.go: -------------------------------------------------------------------------------- 1 | package plugin_gif 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | "strings" 10 | ) 11 | 12 | //获取素材 13 | func DLSc(nm string) string { 14 | _, err := os.Stat(`data/image/sucai/` + nm) 15 | if err != nil { 16 | Download(`https://ghproxy.com/https://raw.githubusercontent.com/tdf1939/sucai/main/`+nm, `data/image/sucai/`+nm) 17 | } 18 | return `data/image/sucai/` + nm 19 | } 20 | 21 | //下载图片 22 | func Download(url, dlpath string) { 23 | //创建目录 24 | var List = strings.Split(dlpath, `/`) 25 | err := os.MkdirAll(strings.TrimSuffix(dlpath, List[len(List)-1]), 0755) 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | res, err := http.Get(url) 31 | if err != nil { 32 | fmt.Println("A error occurred!") 33 | return 34 | } 35 | defer res.Body.Close() 36 | // 获得get请求响应的reader对象 37 | reader := bufio.NewReaderSize(res.Body, 32*1024) 38 | //创建文件 39 | file, err := os.Create(dlpath) 40 | if err != nil { 41 | panic(err) 42 | } 43 | // 获得文件的writer对象 44 | writer := bufio.NewWriter(file) 45 | io.Copy(writer, reader) 46 | } 47 | -------------------------------------------------------------------------------- /plugin_gif/png.go: -------------------------------------------------------------------------------- 1 | package plugin_gif 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "image" 7 | "image/png" 8 | "math/rand" 9 | "strconv" 10 | "time" 11 | 12 | "github.com/tdf1939/img" 13 | ) 14 | 15 | // PNG 转 base64 16 | func encodePNG(im image.Image) ([]byte, error) { 17 | buffer := new(bytes.Buffer) 18 | encoder := base64.NewEncoder(base64.StdEncoding, buffer) 19 | err := png.Encode(encoder, im) 20 | if err != nil { 21 | return nil, err 22 | } 23 | encoder.Close() 24 | return buffer.Bytes(), nil 25 | } 26 | 27 | // 爬 28 | func pa(pngs ...string) ([]byte, error) { 29 | tou := img.ImDc(pngs[0], 0, 0).Circle(0).Im 30 | // 随机爬图序号 31 | rand.Seed(time.Now().UnixNano()) 32 | rand := rand.Intn(60) + 1 33 | dc := img.ImDc(DLSc("pa/"+strconv.Itoa(rand)+".png"), 0, 0). 34 | DstOver(tou, 100, 100, 0, 400).Im 35 | return encodePNG(dc) 36 | } 37 | 38 | // 撕 39 | func si(pngs ...string) ([]byte, error) { 40 | tou := img.ImDc(pngs[0], 0, 0).Im 41 | im1 := img.Rotate(tou, 20, 380, 380) 42 | im2 := img.Rotate(tou, -12, 380, 380) 43 | dc := img.ImDc(DLSc("si/0.png"), 0, 0). 44 | DstOver(im1.Im, im1.W, im1.H, -3, 370). 45 | DstOver(im2.Im, im2.W, im2.H, 653, 310).Im 46 | return encodePNG(dc) 47 | } 48 | 49 | // 一直 50 | func yizhi(pngs ...string) ([]byte, error) { 51 | tou := img.ImsDc(pngs[0], 0, 0) 52 | var dc []*image.NRGBA 53 | for _, v := range tou { 54 | dc = append(dc, img.ImDc(DLSc("xiao/0.png"), 0, 0). 55 | Over(v, 249, 249, 0, 0). 56 | Over(v, 47, 47, 140, 250).Clone().Im, 57 | ) 58 | } 59 | return encodeGIF(img.AndGif(1, dc)) 60 | } 61 | 62 | // TODO 关注 必须下载素材到指定位置才可用 63 | func guanZhu(txt1, txt2 string, pngs ...string) ([]byte, error) { 64 | // 加载图片 65 | im := img.ImDc(pngs[0], 0, 0) 66 | //叠加图片 67 | dst := img.ImDc(DLSc("guanzhu/gg.png"), 0, 0). 68 | DstOver(im.Im, 155, 155, 45, 45) 69 | dc := dst.Text(DLSc("font/3.ttf"), 38, img.Black, 210, 110, txt1). 70 | Text(DLSc("font/3.ttf"), 36, img.Grey, 210, 170, txt2).Im 71 | return encodePNG(dc) 72 | } 73 | 74 | // 简单操作 75 | func other(handle func(*img.Dc) *img.Dc) func(pngs ...string) ([]byte, error) { 76 | return func(pngs ...string) ([]byte, error) { 77 | im := img.ImDc(pngs[0], 0, 0) 78 | return encodePNG(handle(im).Im) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /plugin_gif/run.go: -------------------------------------------------------------------------------- 1 | package plugin_gif 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | 8 | "github.com/tdf1939/img" 9 | zero "github.com/wdvxdr1123/ZeroBot" 10 | "github.com/wdvxdr1123/ZeroBot/message" 11 | ) 12 | 13 | // FirstValueInList 判断正则匹配的第一个参数是否在列表中 14 | func FirstValueInList(list []string) zero.Rule { 15 | return func(ctx *zero.Ctx) bool { 16 | first := ctx.State["regex_matched"].([]string)[1] 17 | for i := range list { 18 | if first == list[i] { 19 | return true 20 | } 21 | } 22 | return false 23 | } 24 | } 25 | 26 | var ( 27 | table = map[string]func(...string) ([]byte, error){ 28 | // 动图 29 | "摸": mo, 30 | "搓": cuo, 31 | "敲": qiao, 32 | "吃": chi, 33 | "蹭": ceng, 34 | "啃": ken, 35 | "拍": pai, 36 | "冲": chong, 37 | "丢": diu, 38 | // 静图 39 | "爬": pa, 40 | "撕": si, 41 | "一直": yizhi, 42 | // 简单操作 43 | "上翻": other(func(im *img.Dc) *img.Dc { return im.FlipV() }), 44 | "下翻": other(func(im *img.Dc) *img.Dc { return im.FlipV() }), 45 | "左翻": other(func(im *img.Dc) *img.Dc { return im.FlipH() }), 46 | "右翻": other(func(im *img.Dc) *img.Dc { return im.FlipH() }), 47 | "反色": other(func(im *img.Dc) *img.Dc { return im.Invert() }), 48 | "灰度": other(func(im *img.Dc) *img.Dc { return im.Grayscale() }), 49 | "浮雕": other(func(im *img.Dc) *img.Dc { return im.Convolve3x3() }), 50 | "打码": other(func(im *img.Dc) *img.Dc { return im.Blur(10) }), 51 | "负片": other(func(im *img.Dc) *img.Dc { return im.Invert().Grayscale() }), 52 | } 53 | ) 54 | 55 | // HasImageFunc 判断开头是否存在对应函数 56 | func HasImageFunc() zero.Rule { 57 | return func(ctx *zero.Ctx) bool { 58 | for k := range table { 59 | if strings.HasPrefix(ctx.Event.RawMessage, k) { 60 | ctx.State["image_type"] = k 61 | return true 62 | } 63 | } 64 | return false 65 | } 66 | } 67 | 68 | // 判断字符串为纯数字 69 | func isNum(s string) bool { 70 | _, err := strconv.Atoi(s) 71 | return err == nil 72 | } 73 | 74 | // CatchAssets 获取素材 75 | func CatchAssets() zero.Rule { 76 | return func(ctx *zero.Ctx) bool { 77 | var assets []string 78 | for _, v := range ctx.Event.Message { 79 | switch { 80 | case v.Type == "at": 81 | assets = append(assets, "http://q4.qlogo.cn/g?b=qq&nk="+v.Data["qq"]+"&s=640") 82 | case v.Type == "image": 83 | assets = append(assets, "https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v.Data["file"])+"/0") 84 | case v.Type == "text": 85 | temp := strings.TrimLeft(v.Data["text"], ctx.State["image_type"].(string)) 86 | if isNum(temp) { 87 | assets = append(assets, "http://q4.qlogo.cn/g?b=qq&nk="+temp+"&s=640") 88 | } 89 | } 90 | } 91 | ctx.State["image_assets"] = assets 92 | return len(assets) > 0 93 | } 94 | } 95 | 96 | func init() { // 插件主体 97 | zero.On("message", HasImageFunc(), CatchAssets()). 98 | SetBlock(true).SetPriority(20).Handle(func(ctx *zero.Ctx) { 99 | handle := table[ctx.State["image_type"].(string)] 100 | assets := ctx.State["image_assets"].([]string) 101 | assets = append(assets, fmt.Sprintf("http://q4.qlogo.cn/g?b=qq&nk=%d&s=640", ctx.Event.UserID)) 102 | data, err := handle(assets...) 103 | if err != nil { 104 | ctx.SendChain(message.Text("ERROR: ", err)) 105 | } 106 | ctx.SendChain(message.Image("base64://" + string(data))) 107 | }) 108 | } 109 | --------------------------------------------------------------------------------