From b5aed78e5accbfdd4a0657eea4a48141d9231378 Mon Sep 17 00:00:00 2001 From: cosmo Date: Tue, 5 Dec 2023 17:42:06 +0800 Subject: [PATCH] beta79 --- Processor/Processor.go | 26 ++++++++ config/config.go | 13 ++++ handlers/message_parser.go | 12 ++-- handlers/send_group_msg.go | 128 +++++++++++++++++++++++++++++++++++- template/config_template.go | 1 + 5 files changed, 175 insertions(+), 5 deletions(-) diff --git a/Processor/Processor.go b/Processor/Processor.go index 493f0759..2619bba1 100644 --- a/Processor/Processor.go +++ b/Processor/Processor.go @@ -274,13 +274,18 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} var err error var now, new, newpro1, newpro2 string var realid, realid2 string + var guildid, guilduserid string switch v := data.(type) { case *dto.WSGroupATMessageData: realid = v.Author.ID case *dto.WSATMessageData: realid = v.Author.ID + guildid = v.GuildID + guilduserid = v.Author.ID case *dto.WSMessageData: realid = v.Author.ID + guildid = v.GuildID + guilduserid = v.Author.ID case *dto.WSDirectMessageData: realid = v.Author.ID case *dto.WSC2CMessageData: @@ -320,6 +325,27 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} virtualValueIncluded = contains(masterIDs, new) } + //unlock指令 + if Type == "guild" && strings.HasPrefix(cleanedMessage, config.GetUnlockPrefix()) { + dm := &dto.DirectMessageToCreate{ + SourceGuildID: guildid, + RecipientID: guilduserid, + } + cdm, err := p.Api.CreateDirectMessage(context.TODO(), dm) + if err != nil { + mylog.Printf("unlock指令创建dm失败:%v", err) + } + msg := &dto.MessageToCreate{ + Content: "欢迎使用Gensokyo框架部署QQ机器人", + MsgType: 0, + MsgID: "", + } + _, err = p.Api.PostDirectMessage(context.TODO(), cdm, msg) + if err != nil { + mylog.Printf("unlock指令发送失败:%v", err) + } + } + // me指令处理逻辑 if strings.HasPrefix(cleanedMessage, config.GetMePrefix()) { if err != nil { diff --git a/config/config.go b/config/config.go index 7af3419a..c7e7b69a 100644 --- a/config/config.go +++ b/config/config.go @@ -91,6 +91,7 @@ type Settings struct { ReconnecTimes int `yaml:"reconnect_times"` HeartBeatInterval int `yaml:"heart_beat_interval"` LaunchReconectTimes int `yaml:"launch_reconnect_times"` + UnlockPrefix string `yaml:"unlock_prefix"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -1093,3 +1094,15 @@ func GetLaunchReconectTimes() int { } return instance.Settings.LaunchReconectTimes } + +// 获取GetUnlockPrefix +func GetUnlockPrefix() string { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to UnlockPrefix value.") + return "/unlock" + } + return instance.Settings.UnlockPrefix +} diff --git a/handlers/message_parser.go b/handlers/message_parser.go index 67ff5db8..b03ba32d 100644 --- a/handlers/message_parser.go +++ b/handlers/message_parser.go @@ -147,21 +147,25 @@ func parseMessageContent(paramsMessage callapi.ParamsContent) (string, map[strin } else { localRecordPattern = regexp.MustCompile(`\[CQ:record,file=file://([^\]]+?)\]`) } - urlImagePattern := regexp.MustCompile(`\[CQ:image,file=https?://(.+)\]`) + httpUrlImagePattern := regexp.MustCompile(`\[CQ:image,file=http://(.+)\]`) + httpsUrlImagePattern := regexp.MustCompile(`\[CQ:image,file=https://(.+)\]`) base64ImagePattern := regexp.MustCompile(`\[CQ:image,file=base64://(.+)\]`) base64RecordPattern := regexp.MustCompile(`\[CQ:record,file=base64://(.+)\]`) - urlRecordPattern := regexp.MustCompile(`\[CQ:record,file=https?://(.+)\]`) + httpUrlRecordPattern := regexp.MustCompile(`\[CQ:record,file=http://(.+)\]`) + httpsUrlRecordPattern := regexp.MustCompile(`\[CQ:record,file=https://(.+)\]`) patterns := []struct { key string pattern *regexp.Regexp }{ {"local_image", localImagePattern}, - {"url_image", urlImagePattern}, + {"url_image", httpUrlImagePattern}, + {"url_images", httpsUrlImagePattern}, {"base64_image", base64ImagePattern}, {"base64_record", base64RecordPattern}, {"local_record", localRecordPattern}, - {"url_record", urlRecordPattern}, + {"url_record", httpUrlRecordPattern}, + {"url_records", httpsUrlRecordPattern}, } foundItems := make(map[string][]string) diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index ce2d5b2c..a15ec981 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -533,6 +533,71 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText newpiclink = "http://" + imageURLs[0] } + // 发链接图片 + return &dto.RichMediaMessage{ + EventID: id, + FileType: 1, // 1代表图片 + URL: newpiclink, // 新图片链接 + Content: "", // 这个字段文档没有了 + SrvSendMsg: false, + } + } else if imageURLs, ok := foundItems["url_images"]; ok && len(imageURLs) > 0 { + var newpiclink string + if config.GetUrlPicTransfer() { + // 从URL下载图片 + resp, err := http.Get("https://" + imageURLs[0]) + if err != nil { + mylog.Printf("Error downloading the image: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 下载图片失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, // 默认文本类型 + } + } + defer resp.Body.Close() + + // 读取图片数据 + imageData, err := io.ReadAll(resp.Body) + if err != nil { + mylog.Printf("Error reading the image data: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 读取图片数据失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, + } + } + + // 转换为base64 + base64Encoded := base64.StdEncoding.EncodeToString(imageData) + + // 上传图片并获取新的URL + newURL, err := images.UploadBase64ImageToServer(base64Encoded) + if err != nil { + mylog.Printf("Error uploading base64 encoded image: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 上传图片失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, + } + } + // 将图片链接缩短 避免 url not allow + // if config.GetLotusValue() { + // // 连接到另一个gensokyo + // newURL = url.GenerateShortURL(newURL) + // } else { + // // 自己是主节点 + // newURL = url.GenerateShortURL(newURL) + // // 使用getBaseURL函数来获取baseUrl并与newURL组合 + // newURL = url.GetBaseURL() + "/url/" + newURL + // } + newpiclink = newURL + } else { + newpiclink = "https://" + imageURLs[0] + } + // 发链接图片 return &dto.RichMediaMessage{ EventID: id, @@ -624,7 +689,68 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText if err != nil { mylog.Printf("Error uploading base64 encoded image: %v", err) return &dto.MessageToCreate{ - Content: "错误: 上传图片失败", + Content: "错误: 上传语音失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, + } + } + + // 发链接语音 + return &dto.RichMediaMessage{ + EventID: id, + FileType: 3, // 3代表语音 + URL: newURL, // 新语音链接 + Content: "", // 这个字段文档没有了 + SrvSendMsg: false, + } + } else if imageURLs, ok := foundItems["url_records"]; ok && len(imageURLs) > 0 { + // 从URL下载语音 + resp, err := http.Get("https://" + imageURLs[0]) + if err != nil { + mylog.Printf("Error downloading the record: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 下载语音失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, // 默认文本类型 + } + } + defer resp.Body.Close() + + // 读取语音数据 + recordData, err := io.ReadAll(resp.Body) + if err != nil { + mylog.Printf("Error reading the record data: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 读取语音数据失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, + } + } + //判断并转码 + if !silk.IsAMRorSILK(recordData) { + mt, ok := silk.CheckAudio(bytes.NewReader(recordData)) + if !ok { + mylog.Errorf("voice type error: " + mt) + return nil + } + recordData = silk.EncoderSilk(recordData) + mylog.Errorf("音频转码ing") + if err != nil { + return nil + } + } + // 转换为base64 + base64Encoded := base64.StdEncoding.EncodeToString(recordData) + + // 上传语音并获取新的URL + newURL, err := images.UploadBase64RecordToServer(base64Encoded) + if err != nil { + mylog.Printf("Error uploading base64 encoded image: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 上传语音失败", MsgID: id, MsgSeq: msgseq, MsgType: 0, diff --git a/template/config_template.go b/template/config_template.go index 0df0aa95..2d7a3899 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -115,6 +115,7 @@ settings: bind_prefix : "/bind" #需设置 #增强配置项 master_id 可触发 me_prefix : "/me" #需设置 #增强配置项 master_id 可触发 + unlock_prefix : "/unlock" #频道私信卡住了? gsk可以帮到你 在任意子频道发送unlock 你会收到来自机器人的频道私信 #穿透\cos\oss类配置(可选!) frp_port : "0" #不使用请保持为0,frp的端口,frp有内外端口,请在frp软件设置gensokyo的port,并将frp显示的对外端口填入这里