mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 22:00:11 +08:00
🍱 🎨 ⚡️ 运势 不解压 不传 base64
This commit is contained in:
parent
bc989f2fb0
commit
f05f09d741
2
data
2
data
@ -1 +1 @@
|
|||||||
Subproject commit 1349bd0d4a64daa5d5d76659a787a8594358b55b
|
Subproject commit 64113f69a74952a35f5c7432a2c0569188bb038c
|
||||||
@ -3,12 +3,11 @@ package fortune
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"crypto/md5"
|
||||||
"encoding/base64"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"image/jpeg"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -24,13 +23,19 @@ import (
|
|||||||
control "github.com/FloatTech/zbputils/control"
|
control "github.com/FloatTech/zbputils/control"
|
||||||
"github.com/FloatTech/zbputils/file"
|
"github.com/FloatTech/zbputils/file"
|
||||||
"github.com/FloatTech/zbputils/math"
|
"github.com/FloatTech/zbputils/math"
|
||||||
|
"github.com/FloatTech/zbputils/process"
|
||||||
|
"github.com/FloatTech/zbputils/txt2img"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// 底图缓存位置
|
// 底图缓存位置
|
||||||
base = "data/fortune/"
|
images = "data/Fortune/"
|
||||||
// 素材下载网站
|
// 基础文件位置
|
||||||
site = "https://pan.dihe.moe/fortune/"
|
omikujson = "data/Fortune/text.json"
|
||||||
|
// 字体文件位置
|
||||||
|
font = "data/Font/sakura.ttf"
|
||||||
|
// 生成图缓存位置
|
||||||
|
cache = images + "cache/"
|
||||||
// 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌
|
// 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌
|
||||||
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师
|
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师
|
||||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师"}
|
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师"}
|
||||||
@ -38,13 +43,32 @@ var (
|
|||||||
index = make(map[string]uint8)
|
index = make(map[string]uint8)
|
||||||
// 下载锁
|
// 下载锁
|
||||||
dlmu sync.Mutex
|
dlmu sync.Mutex
|
||||||
|
// 签文
|
||||||
|
omikujis []map[string]string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
for i, s := range table {
|
for i, s := range table {
|
||||||
index[s] = uint8(i)
|
index[s] = uint8(i)
|
||||||
}
|
}
|
||||||
err := os.MkdirAll(base, 0755)
|
err := os.MkdirAll(images, 0755)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = os.MkdirAll(cache, 0755)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
process.SleepAbout1sTo2s()
|
||||||
|
data, err := file.GetLazyData(omikujson, true, false)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, &omikujis)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
_, err = file.GetLazyData(font, false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -81,38 +105,6 @@ func init() {
|
|||||||
})
|
})
|
||||||
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).SecondPriority().
|
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).SecondPriority().
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
// 检查签文文件是否存在
|
|
||||||
mikuji := base + "运势签文.json"
|
|
||||||
if file.IsNotExist(mikuji) {
|
|
||||||
dlmu.Lock()
|
|
||||||
if file.IsNotExist(mikuji) {
|
|
||||||
ctx.SendChain(message.Text("正在下载签文文件,请稍后..."))
|
|
||||||
err := file.DownloadTo(site+"运势签文.json", mikuji, false)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
dlmu.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("下载签文文件完毕"))
|
|
||||||
}
|
|
||||||
dlmu.Unlock()
|
|
||||||
}
|
|
||||||
// 检查字体文件是否存在
|
|
||||||
ttf := base + "sakura.ttf"
|
|
||||||
if file.IsNotExist(ttf) {
|
|
||||||
dlmu.Lock()
|
|
||||||
if file.IsNotExist(ttf) {
|
|
||||||
ctx.SendChain(message.Text("正在下载字体文件,请稍后..."))
|
|
||||||
err := file.DownloadTo(site+"sakura.ttf", ttf, false)
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
dlmu.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("下载字体文件完毕"))
|
|
||||||
}
|
|
||||||
dlmu.Unlock()
|
|
||||||
}
|
|
||||||
// 获取该群背景类型,默认车万
|
// 获取该群背景类型,默认车万
|
||||||
kind := "车万"
|
kind := "车万"
|
||||||
gid := ctx.Event.GroupID
|
gid := ctx.Event.GroupID
|
||||||
@ -129,127 +121,93 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 检查背景图片是否存在
|
// 检查背景图片是否存在
|
||||||
folder := base + kind
|
zipfile := images + kind + ".zip"
|
||||||
if file.IsNotExist(folder) {
|
_, err = file.GetLazyData(zipfile, false, false)
|
||||||
dlmu.Lock()
|
|
||||||
if file.IsNotExist(folder) {
|
|
||||||
ctx.SendChain(message.Text("正在下载背景图片,请稍后..."))
|
|
||||||
zipfile := kind + ".zip"
|
|
||||||
zipcache := base + zipfile
|
|
||||||
err := file.DownloadTo(site+zipfile, zipcache, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
dlmu.Unlock()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.SendChain(message.Text("下载背景图片完毕"))
|
|
||||||
err = unpack(zipcache, folder+"/")
|
|
||||||
if err != nil {
|
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
|
||||||
dlmu.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.SendChain(message.Text("解压背景图片完毕"))
|
|
||||||
// 释放空间
|
|
||||||
os.Remove(zipcache)
|
|
||||||
}
|
|
||||||
dlmu.Unlock()
|
|
||||||
}
|
|
||||||
// 生成种子
|
// 生成种子
|
||||||
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
|
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
|
||||||
seed := ctx.Event.UserID + t
|
seed := ctx.Event.UserID + t
|
||||||
|
|
||||||
// 随机获取背景
|
// 随机获取背景
|
||||||
background, err := randimage(folder+"/", seed)
|
background, index, err := randimage(zipfile, seed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 随机获取签文
|
// 随机获取签文
|
||||||
title, text, err := randtext(mikuji, seed)
|
title, text, err := randtext(seed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
digest := md5.Sum(helper.StringToBytes(zipfile + strconv.Itoa(index) + title + text))
|
||||||
|
cachefile := cache + hex.EncodeToString(digest[:])
|
||||||
|
if file.IsExist(cachefile) {
|
||||||
|
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + cachefile))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dlmu.Lock()
|
||||||
|
f, err := os.Create(cachefile)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
|
_ = f.Close()
|
||||||
|
_ = os.Remove(cachefile)
|
||||||
|
dlmu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
// 绘制背景
|
// 绘制背景
|
||||||
d, err := draw(background, title, text)
|
err = draw(background, title, text, f)
|
||||||
|
_ = f.Close()
|
||||||
|
dlmu.Unlock()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR: ", err))
|
ctx.SendChain(message.Text("ERROR: ", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 发送图片
|
// 发送图片
|
||||||
ctx.SendChain(message.Image("base64://" + helper.BytesToString(d)))
|
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + cachefile))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @function unpack 解压资源包
|
// @function randimage 随机选取zip内的文件
|
||||||
// @param tgt 压缩文件位置
|
// @param path zip路径
|
||||||
// @param dest 解压位置
|
|
||||||
// @return 错误信息
|
|
||||||
func unpack(tgt, dest string) error {
|
|
||||||
// 路径目录不存在则创建目录
|
|
||||||
if file.IsNotExist(dest) {
|
|
||||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader, err := zip.OpenReader(tgt)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer reader.Close()
|
|
||||||
// 遍历解压到文件
|
|
||||||
for _, file := range reader.File {
|
|
||||||
// 打开解压文件
|
|
||||||
rc, err := file.Open()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// 打开目标文件
|
|
||||||
w, err := os.OpenFile(dest+file.Name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
|
||||||
if err != nil {
|
|
||||||
rc.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// 复制到文件
|
|
||||||
_, err = io.Copy(w, rc)
|
|
||||||
rc.Close()
|
|
||||||
w.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// @function randimage 随机选取文件夹下的文件
|
|
||||||
// @param path 文件夹路径
|
|
||||||
// @param seed 随机数种子
|
// @param seed 随机数种子
|
||||||
// @return 文件路径 & 错误信息
|
// @return 文件路径 & 错误信息
|
||||||
func randimage(path string, seed int64) (string, error) {
|
func randimage(path string, seed int64) (im image.Image, index int, err error) {
|
||||||
rd, err := ioutil.ReadDir(path)
|
reader, err := zip.OpenReader(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return
|
||||||
}
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
rand.Seed(seed)
|
rand.Seed(seed)
|
||||||
return path + rd[rand.Intn(len(rd))].Name(), nil
|
index = rand.Intn(len(reader.File))
|
||||||
|
file := reader.File[index]
|
||||||
|
f, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
im, _, err = image.Decode(f)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// @function randtext 随机选取签文
|
// @function randtext 随机选取签文
|
||||||
// @param file 文件路径
|
// @param file 文件路径
|
||||||
// @param seed 随机数种子
|
// @param seed 随机数种子
|
||||||
// @return 签名 & 签文 & 错误信息
|
// @return 签名 & 签文 & 错误信息
|
||||||
func randtext(file string, seed int64) (string, string, error) {
|
func randtext(seed int64) (string, string, error) {
|
||||||
data, err := ioutil.ReadFile(file)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
temp := []map[string]string{}
|
|
||||||
if err := json.Unmarshal(data, &temp); err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
rand.Seed(seed)
|
rand.Seed(seed)
|
||||||
r := rand.Intn(len(temp))
|
r := rand.Intn(len(omikujis))
|
||||||
return temp[r]["title"], temp[r]["content"], nil
|
return omikujis[r]["title"], omikujis[r]["content"], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// @function draw 绘制运势图
|
// @function draw 绘制运势图
|
||||||
@ -258,27 +216,23 @@ func randtext(file string, seed int64) (string, string, error) {
|
|||||||
// @param title 签名
|
// @param title 签名
|
||||||
// @param text 签文
|
// @param text 签文
|
||||||
// @return 错误信息
|
// @return 错误信息
|
||||||
func draw(background, title, text string) ([]byte, error) {
|
func draw(back image.Image, title, text string, dst io.Writer) error {
|
||||||
// 加载背景
|
var txtc txt2img.TxtCanvas
|
||||||
back, err := gg.LoadImage(background)
|
txtc.Canvas = gg.NewContext(back.Bounds().Size().Y, back.Bounds().Size().X)
|
||||||
if err != nil {
|
txtc.Canvas.DrawImage(back, 0, 0)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
canvas := gg.NewContext(back.Bounds().Size().Y, back.Bounds().Size().X)
|
|
||||||
canvas.DrawImage(back, 0, 0)
|
|
||||||
// 写标题
|
// 写标题
|
||||||
canvas.SetRGB(1, 1, 1)
|
txtc.Canvas.SetRGB(1, 1, 1)
|
||||||
if err := canvas.LoadFontFace(base+"sakura.ttf", 45); err != nil {
|
if err := txtc.Canvas.LoadFontFace(font, 45); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
sw, _ := canvas.MeasureString(title)
|
sw, _ := txtc.Canvas.MeasureString(title)
|
||||||
canvas.DrawString(title, 140-sw/2, 112)
|
txtc.Canvas.DrawString(title, 140-sw/2, 112)
|
||||||
// 写正文
|
// 写正文
|
||||||
canvas.SetRGB(0, 0, 0)
|
txtc.Canvas.SetRGB(0, 0, 0)
|
||||||
if err := canvas.LoadFontFace(base+"sakura.ttf", 23); err != nil {
|
if err := txtc.Canvas.LoadFontFace(font, 23); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
tw, th := canvas.MeasureString("测")
|
tw, th := txtc.Canvas.MeasureString("测")
|
||||||
tw, th = tw+10, th+10
|
tw, th = tw+10, th+10
|
||||||
r := []rune(text)
|
r := []rune(text)
|
||||||
xsum := rowsnum(len(r), 9)
|
xsum := rowsnum(len(r), 9)
|
||||||
@ -288,7 +242,7 @@ func draw(background, title, text string) ([]byte, error) {
|
|||||||
xnow := rowsnum(i+1, 9)
|
xnow := rowsnum(i+1, 9)
|
||||||
ysum := math.Min(len(r)-(xnow-1)*9, 9)
|
ysum := math.Min(len(r)-(xnow-1)*9, 9)
|
||||||
ynow := i%9 + 1
|
ynow := i%9 + 1
|
||||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(ysum, ynow, th)+320.0)
|
txtc.Canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(ysum, ynow, th)+320.0)
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
div := rowsnum(len(r), 2)
|
div := rowsnum(len(r), 2)
|
||||||
@ -298,23 +252,14 @@ func draw(background, title, text string) ([]byte, error) {
|
|||||||
ynow := i%div + 1
|
ynow := i%div + 1
|
||||||
switch xnow {
|
switch xnow {
|
||||||
case 1:
|
case 1:
|
||||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow, th)+320.0)
|
txtc.Canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow, th)+320.0)
|
||||||
case 2:
|
case 2:
|
||||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow+(9-ysum), th)+320.0)
|
txtc.Canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow+(9-ysum), th)+320.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 转成 base64
|
_, err := txtc.WriteTo(dst)
|
||||||
buffer := new(bytes.Buffer)
|
return err
|
||||||
encoder := base64.NewEncoder(base64.StdEncoding, buffer)
|
|
||||||
var opt jpeg.Options
|
|
||||||
opt.Quality = 70
|
|
||||||
err = jpeg.Encode(encoder, canvas.Image(), &opt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
encoder.Close()
|
|
||||||
return buffer.Bytes(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func offest(total, now int, distance float64) float64 {
|
func offest(total, now int, distance float64) float64 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user