From 6dad9bb76f36269f3f8586810fea108c11bfa3f7 Mon Sep 17 00:00:00 2001 From: lixiangwuxian Date: Sun, 20 Oct 2024 02:25:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=96=9C=E6=8A=A5/=E6=82=B2=E6=8A=A5?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handler/xibao/xibao.go | 16 ++++++-- model/cq_message.go | 6 +++ service/xibao/image_gen.go | 78 +++++++++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 6 deletions(-) diff --git a/handler/xibao/xibao.go b/handler/xibao/xibao.go index 30d6488..df43b82 100644 --- a/handler/xibao/xibao.go +++ b/handler/xibao/xibao.go @@ -1,9 +1,13 @@ package xibao import ( + "fmt" + "strings" + "git.lxtend.com/qqbot/handler" "git.lxtend.com/qqbot/model" "git.lxtend.com/qqbot/service/xibao" + "github.com/google/uuid" ) func init() { @@ -14,18 +18,22 @@ func init() { } 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{ - 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, FromMsg: msg, } } 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{ - 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, FromMsg: msg, } diff --git a/model/cq_message.go b/model/cq_message.go index c9a0e55..62c30a4 100644 --- a/model/cq_message.go +++ b/model/cq_message.go @@ -5,6 +5,7 @@ import ( "net/url" "regexp" "strconv" + "strings" ) // @某个QQ用户的结构体 @@ -65,6 +66,11 @@ func ParseCQImageMessage(data string) (*CQImageMessage, error) { // 处理URL转义 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 { return nil, fmt.Errorf("URL 转义失败: %v", err) } diff --git a/service/xibao/image_gen.go b/service/xibao/image_gen.go index c7b8f78..861233a 100644 --- a/service/xibao/image_gen.go +++ b/service/xibao/image_gen.go @@ -1,10 +1,14 @@ package xibao import ( + "fmt" "log" "strings" + "git.lxtend.com/qqbot/model" + "git.lxtend.com/qqbot/util" "github.com/fogleman/gg" + "github.com/google/uuid" ) 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) + // 判断是否为图片 + 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 { @@ -30,9 +96,9 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo } if isGood { // 设置文本颜色为红色 - dc.SetRGB(1, 0.1, 0.1) + dc.SetRGB(0.8, 0, 0) } else { - dc.SetRGB(0.1, 0.1, 1) + dc.SetRGB(0, 0, 0.8) } // 将文本按 \n 分割为多行 lines := strings.Split(text, "\n") @@ -43,6 +109,7 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo // 居中绘制每一行 for i, line := range lines { + i = i - len(lines)/2 x := float64(width) / 2 y := startY + float64(i)*lineHeight dc.DrawStringAnchored(line, x, y, 0.5, 0.5) @@ -54,3 +121,10 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo log.Print("无法保存生成的图片:", err) } } + +func isImageCQ(text string) (string, bool) { + if img, err := model.ParseCQImageMessage(text); err == nil { + return img.URL, true + } + return "", false +}