From 3299e0a3bf7ab18e3ff8b6eeea7de46308e253ee Mon Sep 17 00:00:00 2001 From: lixiangwuxian Date: Fri, 8 Aug 2025 17:54:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=96=9C=E6=8A=A5?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=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 --- go.mod | 1 - go.sum | 9 ----- handler/auth/http_handler.go | 17 ++++++++++ handler/xibao/xibao.go | 66 ++++++++++++++++++++++-------------- service/xibao/image_gen.go | 63 +++++++++++++++++++++++----------- webserver/middleware/auth.go | 13 +++++++ webserver/router.go | 39 ++++++++++++++++----- 7 files changed, 144 insertions(+), 64 deletions(-) create mode 100644 handler/auth/http_handler.go create mode 100644 webserver/middleware/auth.go diff --git a/go.mod b/go.mod index 1b8e923..1e51669 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 github.com/hertz-contrib/cors v0.1.0 - github.com/jmoiron/sqlx v1.4.0 github.com/mattn/go-sqlite3 v1.14.23 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/sashabaranov/go-openai v1.36.1 diff --git a/go.sum b/go.sum index d5baf00..66ae1d2 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= -filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= git.lxtend.com/lixiangwuxian/imagedd v0.0.0-20250515173831-6585d9dd6665 h1:7BI2/KZmvmUEYHewAR4zgoWsl1dmzcGP9mqTqmQdyAg= git.lxtend.com/lixiangwuxian/imagedd v0.0.0-20250515173831-6585d9dd6665/go.mod h1:+G/BR3iv5Yw0bIqZTRcBxpXwcv3bIso+XhN0MTfnjCY= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= @@ -72,8 +70,6 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= -github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= @@ -108,8 +104,6 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= -github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= @@ -135,11 +129,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0= github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= diff --git a/handler/auth/http_handler.go b/handler/auth/http_handler.go new file mode 100644 index 0000000..05ecded --- /dev/null +++ b/handler/auth/http_handler.go @@ -0,0 +1,17 @@ +package auth + +import ( + "context" + + "github.com/cloudwego/hertz/pkg/app" +) + +var tempTokens = make(map[string]string) + +func AcquireTokenHandler(c context.Context, ctx *app.RequestContext) { + +} + +func LoginHandler(c context.Context, ctx *app.RequestContext) { + +} diff --git a/handler/xibao/xibao.go b/handler/xibao/xibao.go index ad50b2f..3177f71 100644 --- a/handler/xibao/xibao.go +++ b/handler/xibao/xibao.go @@ -2,7 +2,7 @@ package xibao import ( "fmt" - "regexp" + "strings" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" @@ -23,17 +23,19 @@ func init() { func xiBao(msg model.Message) (reply *model.Reply) { fileName := uuid.New().String() filePath := util.GenTempFilePath(fmt.Sprintf("%s.png", fileName)) - re := regexp.MustCompile(`\s+`) - tokens := re.Split(msg.RawMsg, 2) - if len(tokens) < 2 { - handler.RegisterLiveHandler(msg.GroupInfo.GroupId, msg.UserId, xiBaoTemp) - return &model.Reply{ - ReplyMsg: "", - ReferOriginMsg: false, - FromMsg: msg, + if len(msg.StructuredMsg) == 1 { + if msg.StructuredMsg[0].GetMessageType() != qq_message.TypeText { + return nil + } else if msg.StructuredMsg[0].(*qq_message.TextMessage).Data.Text == "喜报" { + handler.RegisterLiveHandler(msg.GroupInfo.GroupId, msg.UserId, xiBaoTemp) + return nil } + msg.StructuredMsg[0].(*qq_message.TextMessage).Data.Text = strings.TrimPrefix(msg.StructuredMsg[0].(*qq_message.TextMessage).Data.Text, "喜报 ") + xibao.GenerateCongratulationImageNew(msg.StructuredMsg[0], "./resource/xibao_background.png", filePath, true) + } + if len(msg.StructuredMsg) == 2 { + xibao.GenerateCongratulationImageNew(msg.StructuredMsg[1], "./resource/xibao_background.png", filePath, true) } - xibao.GenerateCongratulationImageNew(tokens[1], "./resource/xibao_background.png", filePath, true) imageMsg := qq_message.ImageMessage{ Type: "image", Data: qq_message.ImageMessageData{ @@ -41,7 +43,7 @@ func xiBao(msg model.Message) (reply *model.Reply) { }, } return &model.Reply{ - ReplyMsg: imageMsg.ToCQString(), + ReplyMsg: imageMsg, ReferOriginMsg: true, FromMsg: msg, } @@ -51,7 +53,13 @@ func xiBaoTemp(msg model.Message) (reply *model.Reply, isTrigger bool) { handler.UnRegisterLiveHandler(msg.GroupInfo.GroupId, msg.UserId) fileName := uuid.New().String() filePath := util.GenTempFilePath(fmt.Sprintf("%s.png", fileName)) - xibao.GenerateCongratulationImageNew(msg.RawMsg, "./resource/xibao_background.png", filePath, true) + var contentMsg qq_message.QQMessage + if len(msg.StructuredMsg) > 0 { + contentMsg = msg.StructuredMsg[0] + } else { + contentMsg = qq_message.NewTextMessage().ParseMessage(msg.RawMsg) + } + xibao.GenerateCongratulationImageNew(contentMsg, "./resource/xibao_background.png", filePath, true) imageMsg := qq_message.ImageMessage{ Type: "image", Data: qq_message.ImageMessageData{ @@ -59,7 +67,7 @@ func xiBaoTemp(msg model.Message) (reply *model.Reply, isTrigger bool) { }, } return &model.Reply{ - ReplyMsg: imageMsg.ToCQString(), + ReplyMsg: imageMsg, ReferOriginMsg: true, FromMsg: msg, }, true @@ -68,17 +76,19 @@ func xiBaoTemp(msg model.Message) (reply *model.Reply, isTrigger bool) { func beiBao(msg model.Message) (reply *model.Reply) { fileName := uuid.New().String() filePath := util.GenTempFilePath(fmt.Sprintf("%s.png", fileName)) - re := regexp.MustCompile(`\s+`) - tokens := re.Split(msg.RawMsg, 2) - if len(tokens) < 2 { - handler.RegisterLiveHandler(msg.GroupInfo.GroupId, msg.UserId, beiBaoTemp) - return &model.Reply{ - ReplyMsg: "", - ReferOriginMsg: false, - FromMsg: msg, + if len(msg.StructuredMsg) == 1 { + if msg.StructuredMsg[0].GetMessageType() != "text" { + return nil + } else if msg.StructuredMsg[0].(*qq_message.TextMessage).Data.Text == "悲报" { + handler.RegisterLiveHandler(msg.GroupInfo.GroupId, msg.UserId, beiBaoTemp) + return nil } + msg.StructuredMsg[0].(*qq_message.TextMessage).Data.Text = strings.TrimPrefix(msg.StructuredMsg[0].(*qq_message.TextMessage).Data.Text, "悲报 ") + xibao.GenerateCongratulationImageNew(msg.StructuredMsg[0], "./resource/beibao_background.png", filePath, false) + } + if len(msg.StructuredMsg) == 2 { + xibao.GenerateCongratulationImageNew(msg.StructuredMsg[1], "./resource/beibao_background.png", filePath, false) } - xibao.GenerateCongratulationImageNew(tokens[1], "./resource/beibao_background.png", filePath, false) imageMsg := qq_message.ImageMessage{ Type: "image", Data: qq_message.ImageMessageData{ @@ -86,7 +96,7 @@ func beiBao(msg model.Message) (reply *model.Reply) { }, } return &model.Reply{ - ReplyMsg: imageMsg.ToCQString(), + ReplyMsg: imageMsg, ReferOriginMsg: true, FromMsg: msg, } @@ -96,7 +106,13 @@ func beiBaoTemp(msg model.Message) (reply *model.Reply, isTrigger bool) { handler.UnRegisterLiveHandler(msg.GroupInfo.GroupId, msg.UserId) fileName := uuid.New().String() filePath := util.GenTempFilePath(fmt.Sprintf("%s.png", fileName)) - xibao.GenerateCongratulationImageNew(msg.RawMsg, "./resource/beibao_background.png", filePath, false) + var contentMsg qq_message.QQMessage + if len(msg.StructuredMsg) > 0 { + contentMsg = msg.StructuredMsg[0] + } else { + contentMsg = qq_message.NewTextMessage().ParseMessage(msg.RawMsg) + } + xibao.GenerateCongratulationImageNew(contentMsg, "./resource/beibao_background.png", filePath, false) imageMsg := qq_message.ImageMessage{ Type: "image", Data: qq_message.ImageMessageData{ @@ -104,7 +120,7 @@ func beiBaoTemp(msg model.Message) (reply *model.Reply, isTrigger bool) { }, } return &model.Reply{ - ReplyMsg: imageMsg.ToCQString(), + ReplyMsg: imageMsg, ReferOriginMsg: true, FromMsg: msg, }, true diff --git a/service/xibao/image_gen.go b/service/xibao/image_gen.go index b12476d..aa319be 100644 --- a/service/xibao/image_gen.go +++ b/service/xibao/image_gen.go @@ -157,7 +157,7 @@ func GenerateCongratulationImage(text string, inputFile, outputFile string, isGo } } -func GenerateCongratulationImageNew(text string, inputFile, outputFile string, isGood bool) { +func GenerateCongratulationImageNew(textOrImg qq_message.QQMessage, inputFile, outputFile string, isGood bool) { baseboard := sprite.NewNamedSpriteBoard() backgroundImageSprite, err := sprite.LoadSpriteFromFile("bg", inputFile) backgroundImageSprite.Index = 0 @@ -166,26 +166,49 @@ func GenerateCongratulationImageNew(text string, inputFile, outputFile string, i return } baseboard.AddSprite(backgroundImageSprite) - var textColor color.RGBA - if isGood { - // 设置文本颜色为红色 - textColor = color.RGBA{R: 255 * 0.8, G: 0, B: 0, A: 255} - } else { - textColor = color.RGBA{R: 0, G: 0, B: 255 * 0.8, A: 255} + if textOrImg.GetMessageType() == qq_message.TypeText { + text := textOrImg.(*qq_message.TextMessage).Data.Text + var textColor color.RGBA + if isGood { + // 设置文本颜色为红色 + textColor = color.RGBA{R: 255 * 0.8, G: 0, B: 0, A: 255} + } else { + textColor = color.RGBA{R: 0, G: 0, B: 255 * 0.8, A: 255} + } + textImage, err := text2img.RenderTextToTrimmedImage(nil, text, 96, textColor, 0, 0) + if err != nil { + log.Print("无法渲染文本:", err) + return + } + textSprite := sprite.Sprite{ + Name: "text", + Images: []image.Image{textImage}, + Position: image.Point{X: backgroundImageSprite.GetCurrentImage().Bounds().Dx()/2 - textImage.Bounds().Dx()/2, Y: backgroundImageSprite.GetCurrentImage().Bounds().Dy()/2 - textImage.Bounds().Dy()/2}, + Index: 1, + } + baseboard.AddSprite(&textSprite) + baseboard.SaveToApng(outputFile) + } else if textOrImg.GetMessageType() == qq_message.TypeImage { + imgMsg := textOrImg.(*qq_message.ImageMessage) + filePath, err := util.DownloadFile(imgMsg.Data.URL, "/tmp/qqbot", false) + if err != nil { + log.Print("无法下载图片:", err) + return + } + im, _, err := sprite.LoadImageFile(filePath) + if err != nil { + log.Print("无法加载图片:", err) + return + } + imgSprite := sprite.Sprite{ + Name: "image", + Images: im, + Position: image.Point{X: backgroundImageSprite.GetCurrentImage().Bounds().Dx()/2 - im[0].Bounds().Dx()/2, Y: backgroundImageSprite.GetCurrentImage().Bounds().Dy()/2 - im[0].Bounds().Dy()/2}, + Index: 1, + } + baseboard.AddSprite(&imgSprite) + baseboard.SaveToApng(outputFile) } - textImage, err := text2img.RenderTextToTrimmedImage(nil, text, 96, textColor, 0, 0) - if err != nil { - log.Print("无法渲染文本:", err) - return - } - textSprite := sprite.Sprite{ - Name: "text", - Images: []image.Image{textImage}, - Position: image.Point{X: backgroundImageSprite.GetCurrentImage().Bounds().Dx()/2 - textImage.Bounds().Dx()/2, Y: backgroundImageSprite.GetCurrentImage().Bounds().Dy()/2 - textImage.Bounds().Dy()/2}, - Index: 1, - } - baseboard.AddSprite(&textSprite) - baseboard.SaveToApng(outputFile) } func isImageCQ(text string) (string, bool) { diff --git a/webserver/middleware/auth.go b/webserver/middleware/auth.go new file mode 100644 index 0000000..994535a --- /dev/null +++ b/webserver/middleware/auth.go @@ -0,0 +1,13 @@ +package middleware + +import ( + "context" + + "github.com/cloudwego/hertz/pkg/app" +) + +func AuthMiddleware() app.HandlerFunc { + return func(c context.Context, ctx *app.RequestContext) { + ctx.Next(c) + } +} diff --git a/webserver/router.go b/webserver/router.go index 34ecbe3..736da61 100644 --- a/webserver/router.go +++ b/webserver/router.go @@ -3,10 +3,12 @@ package webserver import ( "time" + "git.lxtend.com/lixiangwuxian/qqbot/handler/auth" "git.lxtend.com/lixiangwuxian/qqbot/handler/restart" "git.lxtend.com/lixiangwuxian/qqbot/handler/ticket" "git.lxtend.com/lixiangwuxian/qqbot/health" "github.com/cloudwego/hertz/pkg/app/server" + "github.com/cloudwego/hertz/pkg/route" "github.com/hertz-contrib/cors" ) @@ -26,14 +28,33 @@ func StartRouter() { AllowCredentials: true, MaxAge: 12 * time.Hour, })) - healthEngine := herzServer.Group("/health") - healthEngine.GET("/ping", health.HealthHandler) - ticketEngine := herzServer.Group("/ticket") - ticketEngine.GET("", ticket.TicketHandler) - gitEngine := herzServer.Group("/git") - gitEngine.GET("/pull", restart.PullCodeHandler) - gitEngine.GET("/build", restart.BuildBotHandler) - gitEngine.GET("/restart", restart.RestartBotHandler) - gitEngine.GET("/all", restart.AllInOneHandler) + router(herzServer) go herzServer.Run() } + +func router(s *server.Hertz) { + gitRouter(s.Group("/git")) + healthRouter(s.Group("/health")) + ticketRouter(s.Group("/ticket")) + authRouter(s.Group("/auth")) +} + +func gitRouter(g *route.RouterGroup) { + g.GET("/pull", restart.PullCodeHandler) + g.GET("/build", restart.BuildBotHandler) + g.GET("/restart", restart.RestartBotHandler) + g.GET("/all", restart.AllInOneHandler) +} + +func healthRouter(g *route.RouterGroup) { + g.GET("/ping", health.HealthHandler) +} + +func ticketRouter(g *route.RouterGroup) { + g.GET("", ticket.TicketHandler) +} + +func authRouter(g *route.RouterGroup) { + g.GET("/acquire_token", auth.AcquireTokenHandler) + g.GET("/login", auth.LoginHandler) +}