feat: 喜报/悲报支持图片
This commit is contained in:
parent
235d22a4c0
commit
6dad9bb76f
@ -1,9 +1,13 @@
|
|||||||
package xibao
|
package xibao
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"git.lxtend.com/qqbot/handler"
|
"git.lxtend.com/qqbot/handler"
|
||||||
"git.lxtend.com/qqbot/model"
|
"git.lxtend.com/qqbot/model"
|
||||||
"git.lxtend.com/qqbot/service/xibao"
|
"git.lxtend.com/qqbot/service/xibao"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -14,18 +18,22 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func xiBao(msg model.Message) (reply model.Reply) {
|
func xiBao(msg model.Message) (reply model.Reply) {
|
||||||
xibao.GenerateCongratulationImage(msg.RawMsg[len("喜报 "):], "./resource/xibao_background.png", "./tmp/xibao.png", true)
|
fileName := uuid.New().String()
|
||||||
|
filePath := "./tmp/" + fileName + ".png"
|
||||||
|
xibao.GenerateCongratulationImage(strings.Split(msg.RawMsg, " ")[1], "./resource/xibao_background.png", filePath, true)
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: "[CQ:image,file=file:///root/qqbot/tmp/xibao.png]",
|
ReplyMsg: fmt.Sprintf("[CQ:image,file=file:///root/qqbot/tmp/%s]", fileName+".png"),
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func beiBao(msg model.Message) (reply model.Reply) {
|
func beiBao(msg model.Message) (reply model.Reply) {
|
||||||
xibao.GenerateCongratulationImage(msg.RawMsg[len("悲报 "):], "./resource/beibao_background.png", "./tmp/beibao.png", false)
|
fileName := uuid.New().String()
|
||||||
|
filePath := "./tmp/" + fileName + ".png"
|
||||||
|
xibao.GenerateCongratulationImage(strings.Split(msg.RawMsg, " ")[1], "./resource/beibao_background.png", filePath, false)
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: "[CQ:image,file=file:///root/qqbot/tmp/beibao.png]",
|
ReplyMsg: fmt.Sprintf("[CQ:image,file=file:///root/qqbot/tmp/%s]", fileName+".png"),
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @某个QQ用户的结构体
|
// @某个QQ用户的结构体
|
||||||
@ -65,6 +66,11 @@ func ParseCQImageMessage(data string) (*CQImageMessage, error) {
|
|||||||
|
|
||||||
// 处理URL转义
|
// 处理URL转义
|
||||||
decodedURL, err := url.QueryUnescape(matches[4])
|
decodedURL, err := url.QueryUnescape(matches[4])
|
||||||
|
|
||||||
|
decodedURL = strings.ReplaceAll(decodedURL, ",", ",")
|
||||||
|
decodedURL = strings.ReplaceAll(decodedURL, "[", "[")
|
||||||
|
decodedURL = strings.ReplaceAll(decodedURL, "]", "]")
|
||||||
|
decodedURL = strings.ReplaceAll(decodedURL, "&", "&")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("URL 转义失败: %v", err)
|
return nil, fmt.Errorf("URL 转义失败: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
package xibao
|
package xibao
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.lxtend.com/qqbot/model"
|
||||||
|
"git.lxtend.com/qqbot/util"
|
||||||
"github.com/fogleman/gg"
|
"github.com/fogleman/gg"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenerateCongratulationImage(text string, inputFile, outputFile string, isGood bool) {
|
func GenerateCongratulationImage(text string, inputFile, outputFile string, isGood bool) {
|
||||||
@ -22,6 +26,68 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo
|
|||||||
|
|
||||||
// 将背景图片绘制到画布上
|
// 将背景图片绘制到画布上
|
||||||
dc.DrawImage(im, 0, 0)
|
dc.DrawImage(im, 0, 0)
|
||||||
|
// 判断是否为图片
|
||||||
|
if imgUrl, ok := isImageCQ(text); ok {
|
||||||
|
fileName := uuid.New().String() + ".jpg"
|
||||||
|
filePath := "./tmp/" + fileName
|
||||||
|
|
||||||
|
if err := util.DownloadFile(imgUrl, filePath); err != nil {
|
||||||
|
log.Print("无法下载图片:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
imC, err := gg.LoadImage(filePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Print("无法加载图片:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
widthC := imC.Bounds().Dx()
|
||||||
|
heightC := imC.Bounds().Dy()
|
||||||
|
dcC := gg.NewContext(widthC, heightC)
|
||||||
|
dcC.DrawImage(imC, 0, 0)
|
||||||
|
|
||||||
|
// 保存原始状态
|
||||||
|
dcC.Push()
|
||||||
|
|
||||||
|
scaleFactor := 1.0
|
||||||
|
|
||||||
|
// 根据高度比例进行缩放
|
||||||
|
if float64(heightC) > float64(height)/1.5 {
|
||||||
|
scaleFactor = (float64(height) / 1.5) / float64(heightC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据宽度比例进行缩放
|
||||||
|
if float64(widthC) > float64(width)/1.1 {
|
||||||
|
scaleFactor = (float64(width) / 1.1) / float64(widthC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 针对宽高较小的情况进行缩放
|
||||||
|
if heightC < height/5 && widthC < width/4 {
|
||||||
|
if float64(widthC)*(float64(height)/5)/float64(heightC) > float64(width/4) {
|
||||||
|
scaleFactor = (float64(height) / 5) / float64(heightC)
|
||||||
|
log.Print(fmt.Sprintf("图片高度过小,已缩放至高度的 %f 倍", scaleFactor))
|
||||||
|
} else {
|
||||||
|
scaleFactor = (float64(width) / 4) / float64(widthC)
|
||||||
|
log.Print(fmt.Sprintf("图片宽度过小,已缩放至宽度的 %f 倍", scaleFactor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用缩放比例
|
||||||
|
// 计算缩放后的图像尺寸
|
||||||
|
newWidth := int(float64(widthC) * scaleFactor)
|
||||||
|
newHeight := int(float64(heightC) * scaleFactor)
|
||||||
|
|
||||||
|
// 创建一个新的上下文,使用缩放后的尺寸
|
||||||
|
dcScaledC := gg.NewContext(newWidth, newHeight)
|
||||||
|
|
||||||
|
// 将原始图像缩放并绘制到新的上下文中
|
||||||
|
dcScaledC.Scale(scaleFactor, scaleFactor)
|
||||||
|
dcScaledC.DrawImage(imC, 0, 0)
|
||||||
|
|
||||||
|
// 在最终画布上绘制缩放后的图像
|
||||||
|
dc.DrawImageAnchored(dcScaledC.Image(), width/2, height/2, 0.5, 0.5)
|
||||||
|
dc.SavePNG(outputFile)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 设置字体和大小,字体文件需要自备,放在合适的路径
|
// 设置字体和大小,字体文件需要自备,放在合适的路径
|
||||||
if err := dc.LoadFontFace("./resource/font.ttf", 96); err != nil {
|
if err := dc.LoadFontFace("./resource/font.ttf", 96); err != nil {
|
||||||
@ -30,9 +96,9 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo
|
|||||||
}
|
}
|
||||||
if isGood {
|
if isGood {
|
||||||
// 设置文本颜色为红色
|
// 设置文本颜色为红色
|
||||||
dc.SetRGB(1, 0.1, 0.1)
|
dc.SetRGB(0.8, 0, 0)
|
||||||
} else {
|
} else {
|
||||||
dc.SetRGB(0.1, 0.1, 1)
|
dc.SetRGB(0, 0, 0.8)
|
||||||
}
|
}
|
||||||
// 将文本按 \n 分割为多行
|
// 将文本按 \n 分割为多行
|
||||||
lines := strings.Split(text, "\n")
|
lines := strings.Split(text, "\n")
|
||||||
@ -43,6 +109,7 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo
|
|||||||
|
|
||||||
// 居中绘制每一行
|
// 居中绘制每一行
|
||||||
for i, line := range lines {
|
for i, line := range lines {
|
||||||
|
i = i - len(lines)/2
|
||||||
x := float64(width) / 2
|
x := float64(width) / 2
|
||||||
y := startY + float64(i)*lineHeight
|
y := startY + float64(i)*lineHeight
|
||||||
dc.DrawStringAnchored(line, x, y, 0.5, 0.5)
|
dc.DrawStringAnchored(line, x, y, 0.5, 0.5)
|
||||||
@ -54,3 +121,10 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo
|
|||||||
log.Print("无法保存生成的图片:", err)
|
log.Print("无法保存生成的图片:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isImageCQ(text string) (string, bool) {
|
||||||
|
if img, err := model.ParseCQImageMessage(text); err == nil {
|
||||||
|
return img.URL, true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user