diff --git a/plugin/gif/README.md b/plugin/gif/README.md index 628a9d50..e9728814 100644 --- a/plugin/gif/README.md +++ b/plugin/gif/README.md @@ -1,6 +1,6 @@ # ZeroBot-Plugin-Gif [ZeroBot QQ机器人](https://github.com/wdvxdr1123/ZeroBot)插件,可以制作各种沙雕gif图 -> 素材包地址: https://gitcode.net/u011570312/imagematerials +> 素材包地址: https://gitcode.net/anto_july/imagematerials ## 触发方式 1. [指令词]+[qq号] 如:爬123456 @@ -29,3 +29,62 @@ - [x] 浮雕 - [x] 打码 - [x] 负片 +- [x] 旋转45 +- [x] 变形100 100 +- [x] 亲 +- [x] 娶|结婚申请|结婚登记 +- [x] 像只 +- [x] 阿尼亚喜欢 +- [x] 我永远喜欢|永远喜欢 +- [x] 像样的亲亲 +- [x] 国旗 +- [x] 不要靠近 +- [x] 万能表情|空白表情 +- [x] 采访 +- [x] 需要|你可能需要 +- [x] 这像画吗 +- [x] 小画家 +- [x] 完美 +- [x] 玩游戏 (应该使用透视变换) +- [x] 出警 +- [x] 警察 +- [x] 舔|舔屏|prpr (应该使用透视变换) +- [x] 安全感 +- [x] 精神支柱 +- [x] 想什么 +- [x] 墙纸 +- [x] 为什么at我 +- [x] 交个朋友 +- [x] 打工人|继续干活 +- [x] 兑换券 +- [ ] 捂脸 (使用了透视变换, 需要研究矩阵变换) +- [x] 注意力涣散 +- [x] 垃圾桶|垃圾 +- [x] 锤 +- [x] 啾啾 +- [x] 2敲 +- [x] 听音乐 +- [ ] 群青 (需要mask) +- [ ] 加载中 (需要mask) +- [x] 永远爱你 (未加闪光) +- [ ] 关注 (处理文字麻烦) +- [x] 2拍 +- [x] 顶 +- [x] 捣 +- [x] 打拳 (未加闪光) +- [ ] 复读 (处理文字麻烦) +- [x] 滚 +- [x] 吸 +- [x] 扔 +- [x] 捶 +- [x] 紧贴 +- [ ] 膜拜 (使用了透视变换, 需要研究矩阵变换) +- [ ] 小天使 (摆) +- [ ] 一直 (摆) +- [x] 转 +- [ ] 问问 (摆) +- [ ] 典中典 (摆) +- [ ] 震惊 (摆) +- [ ] 哈哈镜 (摆) +- [ ] 对称 (猎奇, 不整) +- [ ] 远离 (摆) diff --git a/plugin/gif/context.go b/plugin/gif/context.go index b600dcb0..f35a3e03 100644 --- a/plugin/gif/context.go +++ b/plugin/gif/context.go @@ -20,7 +20,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) { target := datapath + `materials/` + name var err error if file.IsNotExist(target) { - err = file.DownloadTo(`https://gitcode.net/u011570312/imagematerials/-/raw/main/`+name, target, true) + err = file.DownloadTo(`https://gitcode.net/anto_july/imagematerials/-/raw/main/`+name, target, true) if err != nil { exit(err) return diff --git a/plugin/gif/gif.go b/plugin/gif/gif.go index 1969ad41..406b1443 100644 --- a/plugin/gif/gif.go +++ b/plugin/gif/gif.go @@ -2,14 +2,16 @@ package gif import ( "image" + "image/color" "sync" "github.com/FloatTech/zbputils/img" "github.com/FloatTech/zbputils/img/writer" + "github.com/fogleman/gg" ) -// A摸 -func (cc *context) A摸() (string, error) { +// mo 摸 +func mo(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -44,8 +46,8 @@ func (cc *context) A摸() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, mo)) } -// A搓 -func (cc *context) A搓() (string, error) { +// cuo 搓 +func cuo(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -84,8 +86,8 @@ func (cc *context) A搓() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(5, cuo)) } -// A敲 -func (cc *context) A敲() (string, error) { +// qiao 敲 +func qiao(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -117,8 +119,8 @@ func (cc *context) A敲() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, qiao)) } -// A吃 -func (cc *context) A吃() (string, error) { +// chi 吃 +func chi(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -151,8 +153,8 @@ func (cc *context) A吃() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chi)) } -// A蹭 -func (cc *context) A蹭() (string, error) { +// ceng 蹭 +func ceng(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -192,8 +194,8 @@ func (cc *context) A蹭() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(8, ceng)) } -// A啃 -func (cc *context) A啃() (string, error) { +// ken 啃 +func ken(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -239,8 +241,8 @@ func (cc *context) A啃() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, ken)) } -// A拍 -func (cc *context) A拍() (string, error) { +// pai 拍 +func pai(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -272,8 +274,8 @@ func (cc *context) A拍() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, pai)) } -// A冲 -func (cc *context) A冲() (string, error) { +// xqe 冲 +func xqe(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -305,8 +307,8 @@ func (cc *context) A冲() (string, error) { return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chong)) } -// A丢 -func (cc *context) A丢() (string, error) { +// diu 丢 +func diu(cc *context, value ...string) (string, error) { var wg sync.WaitGroup var err error var m sync.Mutex @@ -343,3 +345,524 @@ func (cc *context) A丢() (string, error) { } return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, diu)) } + +// kiss 亲 +func kiss(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 13 + name := cc.usrdir + "Kiss.gif" + c := dlrange("kiss", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + tou, err := cc.getLogo(0, 0) + if err != nil { + return "", err + } + tou2, err := cc.getLogo2(0, 0) + if err != nil { + return "", err + } + userLocs := [][]int{{58, 90}, {62, 95}, {42, 100}, {50, 100}, {56, 100}, {18, 120}, {28, 110}, {54, 100}, {46, 100}, {60, 100}, {35, 115}, {20, 120}, {40, 96}} + selfLocs := [][]int{{92, 64}, {135, 40}, {84, 105}, {80, 110}, {155, 82}, {60, 96}, {50, 80}, {98, 55}, {35, 65}, {38, 100}, {70, 80}, {84, 65}, {75, 65}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + kiss := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + kiss[i] = imgs[i].InsertUp(tou, 50, 50, userLocs[i][0], userLocs[i][1]). + InsertUp(tou2, 40, 40, selfLocs[i][0], selfLocs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, kiss)) +} + +// garbage 垃圾 垃圾桶 +func garbage(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 25 + name := cc.usrdir + "Garbage.gif" + c := dlrange("garbage", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 79, 79) + if err != nil { + return "", err + } + locs := [][]int{{39, 40}, {39, 40}, {39, 40}, {39, 30}, {39, 30}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 30}, {39, 27}, {39, 32}, {37, 49}, {37, 64}, {37, 67}, {37, 67}, {39, 69}, {37, 70}, {37, 70}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + garbage := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + garbage[i] = imgs[i].InsertBottom(im.Im, 0, 0, locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, garbage)) +} + +// thump 捶 +func thump(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 4 + name := cc.usrdir + "Thump.gif" + c := dlrange("thump", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{65, 128, 77, 72}, {67, 128, 73, 72}, {54, 139, 94, 61}, {57, 135, 86, 65}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + thump := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + thump[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, thump)) +} + +// jiujiu 啾啾 +func jiujiu(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 8 + name := cc.usrdir + "Jiujiu.gif" + c := dlrange("jiujiu", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 75, 51) + if err != nil { + return "", err + } + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + jiujiu := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + jiujiu[i] = imgs[i].InsertBottom(im.Im, 0, 0, 0, 0).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, jiujiu)) +} + +// knock 2敲 +func knock(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 8 + name := cc.usrdir + "Knock.gif" + c := dlrange("knock", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{60, 308, 210, 195}, {60, 308, 210, 198}, {45, 330, 250, 172}, {58, 320, 218, 180}, {60, 310, 215, 193}, {40, 320, 250, 285}, {48, 308, 226, 192}, {51, 301, 223, 200}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + knock := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + knock[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, knock)) +} + +// 听音乐 listenMusic +func listenMusic(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 1 + name := cc.usrdir + "ListenMusic.gif" + c := dlrange("listen_music", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + face, err := cc.getLogo(0, 0) + if err != nil { + return "", err + } + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + listenmusic := make([]*image.NRGBA, 36) + for i := 0; i < 36; i++ { + listenmusic[i] = imgs[0].InsertBottomC(img.Rotate(face, float64(-i*10), 215, 215).Im, 0, 0, 207, 207).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, listenmusic)) +} + +// loveYou 永远爱你 +func loveYou(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 2 + name := cc.usrdir + "LoveYou.gif" + c := dlrange("love_you", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{68, 65, 70, 70}, {63, 59, 80, 80}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + loveyou := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + loveyou[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, loveyou)) +} + +// pat 2拍 +func pat(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 10 + name := cc.usrdir + "Pat.gif" + c := dlrange("pat", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{11, 73, 106, 100}, {8, 79, 112, 96}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + p := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + if i == 2 { + p[i] = imgs[i].InsertBottom(im.Im, locs[1][2], locs[1][3], locs[1][0], locs[1][1]).Im + } else { + p[i] = imgs[i].InsertBottom(im.Im, locs[0][2], locs[0][3], locs[0][0], locs[0][1]).Im + } + } + seq := []int{0, 1, 2, 3, 1, 2, 3, 0, 1, 2, 3, 0, 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 5, 5, 6, 7, 8, 9} + pat := make([]*image.NRGBA, len(seq)) + for i := 0; i < len(pat); i++ { + pat[i] = p[seq[i]] + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, pat)) +} + +// jackUp 顶 +func jackUp(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 23 + name := cc.usrdir + "JackUp.gif" + c := dlrange("play", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{180, 60, 100, 100}, {184, 75, 100, 100}, {183, 98, 100, 100}, {179, 118, 110, 100}, {156, 194, 150, 48}, {178, 136, 122, 69}, {175, 66, 122, 85}, {170, 42, 130, 96}, {175, 34, 118, 95}, {179, 35, 110, 93}, {180, 54, 102, 93}, {183, 58, 97, 92}, {174, 35, 120, 94}, {179, 35, 109, 93}, {181, 54, 101, 92}, {182, 59, 98, 92}, {183, 71, 90, 96}, {180, 131, 92, 101}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + p := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + if i < len(locs) { + p[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } else { + p[i] = imgs[i].Im + } + } + play := make([]*image.NRGBA, 0, 16) + play = append(play, p[0:12]...) + play = append(play, p[0:12]...) + play = append(play, p[0:8]...) + play = append(play, p[12:18]...) + play = append(play, p[18:23]...) + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, play)) +} + +// pound 捣 +func pound(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 8 + name := cc.usrdir + "Pound.gif" + c := dlrange("pound", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{135, 240, 138, 47}, {135, 240, 138, 47}, {150, 190, 105, 95}, {150, 190, 105, 95}, {148, 188, 106, 98}, {146, 196, 110, 88}, {145, 223, 112, 61}, {145, 223, 112, 61}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + pound := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + pound[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, pound)) +} + +// punch 打拳 +func punch(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 13 + name := cc.usrdir + "Punch.gif" + c := dlrange("punch", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 260, 260) + if err != nil { + return "", err + } + locs := [][]int{{-50, 20}, {-40, 10}, {-30, 0}, {-20, -10}, {-10, -10}, {0, 0}, {10, 10}, {20, 20}, {10, 10}, {0, 0}, {-10, -10}, {10, 0}, {-30, 10}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + punch := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + punch[i] = imgs[i].InsertBottom(im.Im, 0, 0, locs[i][0], locs[i][1]-15).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, punch)) +} + +// roll 滚 +func roll(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 8 + name := cc.usrdir + "roll.gif" + c := dlrange("roll", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 210, 210) + if err != nil { + return "", err + } + locs := [][]int{{87, 77, 0}, {96, 85, -45}, {92, 79, -90}, {92, 78, -135}, {92, 75, -180}, {92, 75, -225}, {93, 76, -270}, {90, 80, -315}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + roll := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + roll[i] = imgs[i].InsertBottomC(img.Rotate(im.Im, float64(locs[i][2]), 0, 0).Im, 0, 0, locs[i][0]+105, locs[i][1]+105).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, roll)) +} + +// suck 吸 嗦 +func suck(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 12 + name := cc.usrdir + "Suck.gif" + c := dlrange("suck", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{82, 100, 130, 119}, {82, 94, 126, 125}, {82, 120, 128, 99}, {81, 164, 132, 55}, {79, 163, 132, 55}, {82, 140, 127, 79}, {83, 152, 125, 67}, {75, 157, 140, 62}, {72, 165, 144, 54}, {80, 132, 128, 87}, {81, 127, 127, 92}, {79, 111, 132, 108}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + suck := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + suck[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, suck)) +} + +// hammer 锤 +func hammer(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 7 + name := cc.usrdir + "Hammer.gif" + c := dlrange("hammer", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{62, 143, 158, 113}, {52, 177, 173, 105}, {42, 192, 192, 92}, {46, 182, 184, 100}, {54, 169, 174, 110}, {69, 128, 144, 135}, {65, 130, 152, 124}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + hammer := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + hammer[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, hammer)) +} + +// tightly 紧贴 紧紧贴着 +func tightly(cc *context, value ...string) (string, error) { + var wg sync.WaitGroup + var err error + var m sync.Mutex + piclen := 20 + name := cc.usrdir + "Tightly.gif" + c := dlrange("tightly", piclen, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + locs := [][]int{{39, 169, 267, 141}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {28, 176, 293, 134}, {5, 215, 333, 96}, {10, 210, 321, 102}, {3, 210, 330, 104}, {4, 210, 328, 102}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {29, 195, 285, 120}} + imgs, err := loadFirstFrames(c, piclen) + if err != nil { + return "", err + } + tightly := make([]*image.NRGBA, piclen) + for i := 0; i < piclen; i++ { + tightly[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, tightly)) +} + +// turn 转 +func turn(cc *context, value ...string) (string, error) { + name := cc.usrdir + "Turn.gif" + face, err := cc.getLogo(0, 0) + if err != nil { + return "", err + } + canvas := gg.NewContext(250, 250) + canvas.SetColor(color.White) + canvas.DrawRectangle(0, 0, 250, 250) + canvas.Fill() + turn := make([]*image.NRGBA, 36) + for i := 0; i < 36; i++ { + turn[i] = img.Size(canvas.Image(), 0, 0).InsertUpC(img.Rotate(face, float64(10*i), 250, 250).Im, 0, 0, 125, 125).Im + } + return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, turn)) +} diff --git a/plugin/gif/png.go b/plugin/gif/png.go index c8845d8f..1f7b74bc 100644 --- a/plugin/gif/png.go +++ b/plugin/gif/png.go @@ -2,19 +2,22 @@ package gif import ( "errors" - "image" + "image/color" "math/rand" "os" "strconv" + "sync" "github.com/FloatTech/zbputils/file" "github.com/FloatTech/zbputils/img" + "github.com/FloatTech/zbputils/img/text" "github.com/FloatTech/zbputils/img/writer" + "github.com/fogleman/gg" ) -// A爬 -func (cc *context) A爬() (string, error) { - name := cc.usrdir + `爬.png` +// pa 爬 +func pa(cc *context, args ...string) (string, error) { + name := cc.usrdir + "爬.png" tou, err := cc.getLogo(0, 0) if err != nil { return "", err @@ -27,7 +30,7 @@ func (cc *context) A爬() (string, error) { return "", err } } - f, err := dlblock(`pa/` + strconv.Itoa(rand) + `.png`) + f, err := dlblock("pa/" + strconv.Itoa(rand) + ".png") if err != nil { return "", err } @@ -38,9 +41,9 @@ func (cc *context) A爬() (string, error) { return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertBottom(tou, 100, 100, 0, 400).Im) } -// A撕 -func (cc *context) A撕() (string, error) { - name := cc.usrdir + `撕.png` +// si 撕 +func si(cc *context, args ...string) (string, error) { + name := cc.usrdir + "撕.png" tou, err := cc.getLogo(0, 0) if err != nil { return "", err @@ -53,7 +56,7 @@ func (cc *context) A撕() (string, error) { return "", err } } - f, err := dlblock(`si/0.png`) + f, err := dlblock("si/0.png") if err != nil { return "", err } @@ -64,45 +67,991 @@ func (cc *context) A撕() (string, error) { return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertBottom(im1.Im, im1.W, im1.H, -3, 370).InsertBottom(im2.Im, im2.W, im2.H, 653, 310).Im) } -// 简单 -func (cc *context) other(value ...string) (string, error) { - name := cc.usrdir + value[0] + `.png` +// flipV 上翻,下翻 +func flipV(cc *context, args ...string) (string, error) { + name := cc.usrdir + "FlipV.png" // 加载图片 im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) if err != nil { return "", err } - var imgnrgba *image.NRGBA - switch value[0] { - case "上翻", "下翻": - imgnrgba = im.FlipV().Im - case "左翻", "右翻": - imgnrgba = im.FlipH().Im - case "反色": - imgnrgba = im.Invert().Im - case "灰度": - imgnrgba = im.Grayscale().Im - case "负片": - imgnrgba = im.Invert().Grayscale().Im - case "浮雕": - imgnrgba = im.Convolve3x3().Im - case "打码": - imgnrgba = im.Blur(10).Im - case "旋转": - r, _ := strconv.ParseFloat(value[1], 64) - imgnrgba = img.Rotate(im.Im, r, 0, 0).Im - case "变形": - w, err := strconv.Atoi(value[1]) - if err != nil { - return "", err - } - h, err := strconv.Atoi(value[2]) - if err != nil { - return "", err - } - imgnrgba = img.Size(im.Im, w, h).Im - default: - return "", errors.New("no such method") - } + imgnrgba := im.FlipV().Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// flipH 左翻,右翻 +func flipH(cc *context, args ...string) (string, error) { + name := cc.usrdir + "FlipH.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + imgnrgba := im.FlipH().Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// invert 反色 +func invert(cc *context, args ...string) (string, error) { + name := cc.usrdir + "Invert.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + imgnrgba := im.Invert().Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// blur 反色 +func blur(cc *context, args ...string) (string, error) { + name := cc.usrdir + "Blur.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + imgnrgba := im.Blur(10).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// grayscale 灰度 +func grayscale(cc *context, args ...string) (string, error) { + name := cc.usrdir + "Grayscale.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + imgnrgba := im.Grayscale().Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// invertAndGrayscale 负片 +func invertAndGrayscale(cc *context, args ...string) (string, error) { + name := cc.usrdir + "InvertAndGrayscale.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + imgnrgba := im.Invert().Grayscale().Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// convolve3x3 浮雕 +func convolve3x3(cc *context, args ...string) (string, error) { + name := cc.usrdir + "Convolve3x3.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + imgnrgba := im.Convolve3x3().Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// rotate 旋转,带参数暂时不用 +func rotate(cc *context, args ...string) (string, error) { + name := cc.usrdir + "Rotate.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + r, _ := strconv.ParseFloat(args[0], 64) + imgnrgba := img.Rotate(im.Im, r, 0, 0).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// deformation 变形,带参数暂时不用 +func deformation(cc *context, args ...string) (string, error) { + name := cc.usrdir + "Deformation.png" + // 加载图片 + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0) + if err != nil { + return "", err + } + w, err := strconv.Atoi(args[0]) + if err != nil { + return "", err + } + h, err := strconv.Atoi(args[1]) + if err != nil { + return "", err + } + imgnrgba := img.Size(im.Im, w, h).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// alike 你像个xxx一样 +func alike(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("alike", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Anyasuki.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 82, 69) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertUp(im.Im, 0, 0, 136, 21).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// marriage +func marriage(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("marriage", 2, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 2) + if err != nil { + return "", err + } + name := cc.usrdir + "Marriage.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 1080, 1080) + if err != nil { + return "", err + } + imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).InsertUp(imgs[1].Im, 0, 0, 800, 0).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// anyasuki 阿尼亚喜欢 +func anyasuki(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("anyasuki", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + name := cc.usrdir + "Anyasuki.png" + back, err := gg.LoadImage(c[0]) + if err != nil { + return "", err + } + face, err := gg.LoadImage(cc.headimgsdir[0]) + if err != nil { + return "", err + } + canvas := gg.NewContext(475, 540) + canvas.DrawImage(img.Size(face, 347, 267).Im, 82, 53) + canvas.DrawImage(back, 0, 0) + canvas.SetColor(color.Black) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "阿尼亚喜欢这个" + } + l, _ := canvas.MeasureString(args[0]) + if l > 500 { + return "", errors.New("文字消息太长了") + } + canvas.DrawString(args[0], (500-l)/2.0, 535) + return "file:///" + name, canvas.SavePNG(name) +} + +// alwaysLike 我永远喜欢 +func alwaysLike(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("always_like", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + name := cc.usrdir + "AlwaysLike.png" + back, err := gg.LoadImage(c[0]) + if err != nil { + return "", err + } + face, err := gg.LoadImage(cc.headimgsdir[0]) + if err != nil { + return "", err + } + canvas := gg.NewContext(830, 599) + canvas.DrawImage(back, 0, 0) + canvas.DrawImage(img.Size(face, 341, 341).Im, 44, 74) + canvas.SetColor(color.Black) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 56); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "你们" + } + args[0] = "我永远喜欢" + args[0] + l, _ := canvas.MeasureString(args[0]) + if l > 830 { + return "", errors.New("文字消息太长了") + } + canvas.DrawString(args[0], (830-l)/2.0, 559) + return "file:///" + name, canvas.SavePNG(name) +} + +// decentKiss 像样的亲亲 +func decentKiss(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("decent_kiss", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "DecentKiss.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 589, 577) + if err != nil { + return "", err + } + imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// chinaFlag 国旗 +func chinaFlag(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("china_flag", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "ChinaFlag.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 410, 410) + if err != nil { + return "", err + } + imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// dontTouch 不要靠近 +func dontTouch(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("dont_touch", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "DontTouch.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 410, 410) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertUp(im.Im, 148, 148, 46, 238).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// universal 万能表情 空白表情 +func universal(cc *context, args ...string) (string, error) { + name := cc.usrdir + "Universal.png" + face, err := gg.LoadImage(cc.headimgsdir[0]) + if err != nil { + return "", err + } + canvas := gg.NewContext(500, 550) + canvas.DrawImage(img.Size(face, 500, 500).Im, 0, 0) + canvas.SetColor(color.Black) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "在此处添加文字" + } + l, _ := canvas.MeasureString(args[0]) + if l > 500 { + return "", errors.New("文字消息太长了") + } + canvas.DrawString(args[0], (500-l)/2.0, 545) + return "file:///" + name, canvas.SavePNG(name) +} + +// interview 采访 +func interview(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("interview", 2, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + name := cc.usrdir + "Interview.png" + huaji, err := gg.LoadImage(c[0]) + if err != nil { + return "", err + } + microphone, err := gg.LoadImage(c[1]) + if err != nil { + return "", err + } + face, err := gg.LoadImage(cc.headimgsdir[0]) + if err != nil { + return "", err + } + canvas := gg.NewContext(600, 300) + canvas.DrawImage(img.Size(face, 124, 124).Im, 100, 50) + canvas.DrawImage(huaji, 376, 50) + canvas.DrawImage(microphone, 300, 50) + canvas.SetColor(color.Black) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "采访大佬经验" + } + l, _ := canvas.MeasureString(args[0]) + if l > 600 { + return "", errors.New("文字消息太长了") + } + canvas.DrawString(args[0], (600-l)/2.0, 270) + return "file:///" + name, canvas.SavePNG(name) +} + +// need 需要 你可能需要 +func need(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("need", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Need.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 114, 114) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 327, 232).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// paint 这像画吗 +func paint(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("paint", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Paint.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 117, 135) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 4, 0, 0).Im, 0, 0, 95, 107).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// painter 小画家 +func painter(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("painter", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Painter.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 240, 345) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 125, 91).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// perfect 完美 +func perfect(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("perfect", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Perfect.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 310, 460) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertUp(im.Im, 0, 0, 313, 64).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// playGame 玩游戏 +func playGame(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("play_game", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + name := cc.usrdir + "PlayGame.png" + back, err := gg.LoadImage(c[0]) + if err != nil { + return "", err + } + face, err := gg.LoadImage(cc.headimgsdir[0]) + if err != nil { + return "", err + } + canvas := gg.NewContext(526, 503) + canvas.DrawImage(img.Rotate(face, 10, 225, 160).Im, 161, 117) + canvas.DrawImage(back, 0, 0) + canvas.SetColor(color.Black) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "来玩休闲游戏啊" + } + l, _ := canvas.MeasureString(args[0]) + if l > 526 { + return "", errors.New("文字消息太长了") + } + canvas.DrawString(args[0], (526-l)/2.0, 483) + return "file:///" + name, canvas.SavePNG(name) +} + +// police 出警 +func police(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("police", 2, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 2) + if err != nil { + return "", err + } + name := cc.usrdir + "Police.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 245, 245) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 224, 46).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// police1 警察 +func police1(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("police", 2, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 2) + if err != nil { + return "", err + } + name := cc.usrdir + "Police1.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 60, 75) + if err != nil { + return "", err + } + imgnrgba := imgs[1].InsertBottom(img.Rotate(im.Im, 16, 0, 0).Im, 0, 0, 37, 291).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// prpr 舔 舔屏 prpr +func prpr(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("prpr", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Prpr.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 330, 330) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 8, 0, 0).Im, 0, 0, 46, 264).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// safeSense 安全感 +func safeSense(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("safe_sense", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + name := cc.usrdir + "SafeSense.png" + back, err := gg.LoadImage(c[0]) + if err != nil { + return "", err + } + face, err := gg.LoadImage(cc.headimgsdir[0]) + if err != nil { + return "", err + } + canvas := gg.NewContext(430, 478) + canvas.DrawImage(back, 0, 0) + canvas.DrawImage(img.Size(face, 215, 343).Im, 215, 135) + canvas.SetColor(color.Black) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "你给我的安全感远不如他的万分之一" + } + + l, _ := canvas.MeasureString(args[0]) + if l > 860 { + return "", errors.New("文字消息太长了") + } + canvas.DrawString(args[0][:len(args[0])/2], (430-l/2)/2.0, 40) + canvas.DrawString(args[0][len(args[0])/2:], (430-l/2)/2.0, 80) + return "file:///" + name, canvas.SavePNG(name) +} + +// support 精神支柱 +func support(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("support", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Support.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 815, 815) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 23, 0, 0).Im, 0, 0, -172, -17).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// thinkwhat 想什么 +func thinkwhat(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("thinkwhat", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Thinkwhat.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 534, 493) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 530, 0).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// wallpaper 墙纸 +func wallpaper(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("wallpaper", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Wallpaper.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 775, 496) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 260, 580).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// whyatme 为什么at我 +func whyatme(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("whyatme", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Whyatme.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 265, 265) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 42, 13).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// makeFriend 交个朋友 +func makeFriend(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("make_friend", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + name := cc.usrdir + "MakeFriend.png" + back, err := gg.LoadImage(c[0]) + if err != nil { + return "", err + } + face, err := gg.LoadImage(cc.headimgsdir[0]) + if err != nil { + return "", err + } + canvas := gg.NewContext(1000, 1000) + canvas.DrawImage(img.Size(face, 1000, 1000).Im, 0, 0) + canvas.DrawImage(img.Rotate(face, 9, 250, 250).Im, 743, 845) + canvas.DrawImage(img.Rotate(face, 9, 55, 55).Im, 836, 722) + canvas.DrawImage(back, 0, 0) + canvas.SetColor(color.White) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 20); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "我" + } + l, _ := canvas.MeasureString(args[0]) + if l > 230 { + return "", errors.New("文字消息太长了") + } + canvas.Rotate(gg.Radians(-9)) + canvas.DrawString(args[0], 595, 819) + return "file:///" + name, canvas.SavePNG(name) +} + +// backToWork 打工人, 继续干活 +func backToWork(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("back_to_work", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "BackToWork.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 220, 310) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 25, 0, 0).Im, 0, 0, 56, 32).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// coupon 兑换券 +func coupon(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("coupon", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + name := cc.usrdir + "Coupon.png" + if args[0] == "" { + args[0] = "群主陪睡券" + } + back, err := gg.LoadImage(c[0]) + if err != nil { + return "", err + } + face, err := cc.getLogo(0, 0) + if err != nil { + return "", err + } + canvas := gg.NewContext(500, 355) + canvas.DrawImage(back, 0, 0) + canvas.Rotate(gg.Radians(-22)) + canvas.DrawImage(img.Size(face, 60, 60).Im, 100, 163) + canvas.SetColor(color.Black) + _, err = file.GetLazyData(text.BoldFontFile, true) + if err != nil { + return "", err + } + if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil { + return "", err + } + if args[0] == "" { + args[0] = "陪睡券" + } + l, _ := canvas.MeasureString(args[0]) + if l > 270 { + return "", errors.New("文字消息太长了") + } + canvas.DrawStringAnchored(args[0], 135, 255, 0.5, 0.5) + canvas.DrawStringAnchored("(永久有效)", 135, 295, 0.5, 0.5) + return "file:///" + name, canvas.SavePNG(name) +} + +// distracted 注意力涣散 +func distracted(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("distracted", 2, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 2) + if err != nil { + return "", err + } + name := cc.usrdir + "Distracted.png" + im, err := img.LoadFirstFrame(cc.headimgsdir[0], 500, 500) + if err != nil { + return "", err + } + imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 140, 320).InsertUp(imgs[1].Im, 0, 0, 0, 0).Im + return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) +} + +// throw 扔 +func throw(cc *context, args ...string) (string, error) { + var wg sync.WaitGroup + var m sync.Mutex + var err error + c := dlrange("throw", 1, &wg, func(e error) { + m.Lock() + err = e + m.Unlock() + }) + if err != nil { + return "", err + } + wg.Wait() + imgs, err := loadFirstFrames(c, 1) + if err != nil { + return "", err + } + name := cc.usrdir + "Throw.png" + face, err := cc.getLogo(0, 0) + if err != nil { + return "", err + } + imgnrgba := imgs[0].InsertUpC(img.Rotate(face, float64(rand.Intn(360)), 143, 143).Im, 0, 0, 86, 249).Im return "file:///" + name, writer.SavePNG2Path(name, imgnrgba) } diff --git a/plugin/gif/run.go b/plugin/gif/run.go index 4490ffee..6e5ea0d0 100644 --- a/plugin/gif/run.go +++ b/plugin/gif/run.go @@ -2,7 +2,6 @@ package gif import ( - "reflect" "strconv" "strings" @@ -15,19 +14,103 @@ import ( ) var ( - cmds = []string{"搓", "冲", "摸", "拍", "丢", "吃", "敲", "啃", "蹭", "爬", "撕", - "灰度", "上翻", "下翻", "左翻", "右翻", "反色", "浮雕", "打码", "负片"} + cmd = make([]string, 0) datapath string + cmdMap = map[string]func(cc *context, args ...string) (string, error){ + "搓": cuo, + "冲": xqe, + "摸": mo, + "拍": pai, + "丢": diu, + "吃": chi, + "敲": qiao, + "啃": ken, + "蹭": ceng, + "爬": pa, + "撕": si, + "灰度": grayscale, + "上翻": flipV, + "下翻": flipV, + "左翻": flipH, + "右翻": flipH, + "反色": invert, + "浮雕": convolve3x3, + "打码": blur, + "负片": invertAndGrayscale, + "旋转": rotate, + "变形": deformation, + "亲": kiss, + "结婚申请": marriage, + "结婚登记": marriage, + "阿尼亚喜欢": anyasuki, + "像只": alike, + "我永远喜欢": alwaysLike, + "永远喜欢": alwaysLike, + "像样的亲亲": decentKiss, + "国旗": chinaFlag, + "不要靠近": dontTouch, + "万能表情": universal, + "空白表情": universal, + "采访": interview, + "需要": need, + "你可能需要": need, + "这像画吗": paint, + "小画家": painter, + "完美": perfect, + "玩游戏": playGame, + "出警": police, + "警察": police1, + "舔": prpr, + "舔屏": prpr, + "prpr": prpr, + "安全感": safeSense, + "精神支柱": support, + "想什么": thinkwhat, + "墙纸": wallpaper, + "为什么at我": whyatme, + "交个朋友": makeFriend, + "打工人": backToWork, + "继续干活": backToWork, + "兑换券": coupon, + "注意力涣散": distracted, + "垃圾桶": garbage, + "垃圾": garbage, + "捶": thump, + "啾啾": jiujiu, + "2敲": knock, + "听音乐": listenMusic, + "永远爱你": loveYou, + "2拍": pat, + "顶": jackUp, + "捣": pound, + "打拳": punch, + "滚": roll, + "吸": suck, + "嗦": suck, + "扔": throw, + "锤": hammer, + "紧贴": tightly, + "紧紧贴着": tightly, + "转": turn, + } ) func init() { // 插件主体 + for k := range cmdMap { + cmd = append(cmd, k) + } en := control.Register("gif", &ctrl.Options[*zero.Ctx]{ - DisableOnDefault: false, - Help: "制图\n- " + strings.Join(cmds, "\n- "), + DisableOnDefault: false, + Help: "制图\n- 搓\n- 冲\n- 摸\n- 拍\n- 丢\n- 吃\n- 敲\n- 啃\n- 蹭\n- 爬\n- 撕\n- 灰度\n- 上翻|下翻\n" + + "- 左翻|右翻\n- 反色\n- 浮雕\n- 打码\n- 负片\n- 旋转 45\n- 变形 100 100\n- 亲\n- 结婚申请|结婚登记\n- 阿尼亚喜欢\n- 像只\n" + + "- 我永远喜欢|永远喜欢\n- 像样的亲亲\n- 国旗\n- 不要靠近\n- 万能表情|空白表情\n- 采访\n- 需要|你可能需要\n- 这像画吗\n- 小画家\n" + + "- 完美\n- 玩游戏\n- 出警\n- 警察\n- 舔|舔屏|prpr\n- 安全感\n- 精神支柱\n- 想什么\n- 墙纸\n- 为什么at我\n- 交个朋友\n- 打工人|继续干活\n" + + "- 兑换券\n- 注意力涣散\n- 垃圾桶|垃圾\n- 捶\n- 啾啾\n- 2敲\n- 听音乐\n- 永远爱你\n- 2拍\n- 顶\n- 捣\n- 打拳\n- 滚\n- 吸|嗦\n- 扔\n" + + "- 锤\n- 紧贴|紧紧贴着\n- 转\n", PrivateDataFolder: "gif", }).ApplySingle(ctxext.DefaultSingle) datapath = file.BOTPATH + "/" + en.DataFolder() - en.OnRegex(`^(` + strings.Join(cmds, "|") + `)\D*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`). + en.OnRegex(`^(` + strings.Join(cmd, "|") + `)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`). SetBlock(true).Handle(func(ctx *zero.Ctx) { c := newContext(ctx.Event.UserID) list := ctx.State["regex_matched"].([]string) @@ -36,16 +119,8 @@ func init() { // 插件主体 ctx.SendChain(message.Text("ERROR:", err)) return } - var picurl string - if len([]rune(list[1])) == 1 { - r := reflect.ValueOf(c).MethodByName("A" + list[1]).Call(nil) - picurl = r[0].String() - if !r[1].IsNil() { - err = r[1].Interface().(error) - } - } else { - picurl, err = c.other(list[1]) // "灰度", "上翻", "下翻", "左翻", "右翻", "反色", "倒放", "浮雕", "打码", "负片" - } + argslist := strings.Split(strings.TrimSuffix(strings.TrimPrefix(list[0], list[1]), list[2]), " ") + picurl, err := cmdMap[list[1]](c, argslist...) if err != nil { ctx.SendChain(message.Text("ERROR:", err)) return