package message import ( "encoding/json" "fmt" "net/url" "regexp" "strings" ) type ImageMessage struct { Type string `json:"type"` Data ImageMessageData `json:"data"` } type ImageMessageData struct { URL string `json:"url,omitzero"` Summary string `json:"summary,omitzero"` File string `json:"file,omitzero"` Key string `json:"key,omitzero"` EmojiID string `json:"emoji_id,omitzero"` PackageID string `json:"emoji_package_id,omitzero"` SubType string `json:"sub_type,omitzero"` FileID string `json:"file_id,omitzero"` FileSize string `json:"file_size,omitzero"` FileUnique string `json:"file_unique,omitzero"` } func init() { RegisterMessageType(TypeImage, func() CQMessage { return NewImageMessage() }) } func NewImageMessage() *ImageMessage { return &ImageMessage{ Type: TypeImage, Data: ImageMessageData{}, } } func (msg *ImageMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } func (msg *ImageMessage) ToCQString() string { if msg.Data.URL == "" && msg.Data.File == "" { return "" } // URL 转义 escapedURL, _ := url.QueryUnescape(msg.Data.URL) escapedURL = strings.ReplaceAll(escapedURL, ",", ",") escapedURL = strings.ReplaceAll(escapedURL, "[", "[") escapedURL = strings.ReplaceAll(escapedURL, "]", "]") escapedURL = strings.ReplaceAll(escapedURL, "&", "&") // 构造 CQ:image 字符串 cqString := fmt.Sprintf("[CQ:image,file=%s,sub_type=%s,file_id=%s,url=%s,file_size=%s,file_unique=%s]", msg.Data.File, msg.Data.SubType, msg.Data.FileID, escapedURL, msg.Data.FileSize, msg.Data.FileUnique) return cqString } func (msg *ImageMessage) ParseMessage(data string) error { // 使用正则表达式提取各个字段 re := regexp.MustCompile(`\[CQ:image,(.*?)\]`) matches := re.FindStringSubmatch(data) if len(matches) != 2 { return fmt.Errorf("invalid image message format") } attrs := make(map[string]string) pairs := strings.Split(matches[1], ",") for _, pair := range pairs { if kv := strings.SplitN(pair, "=", 2); len(kv) == 2 { attrs[kv[0]] = kv[1] } } msg.Data.URL = attrs["url"] msg.Data.URL, _ = url.QueryUnescape(msg.Data.URL) msg.Data.URL = strings.ReplaceAll(msg.Data.URL, ",", ",") msg.Data.URL = strings.ReplaceAll(msg.Data.URL, "[", "[") msg.Data.URL = strings.ReplaceAll(msg.Data.URL, "]", "]") msg.Data.URL = strings.ReplaceAll(msg.Data.URL, "&", "&") msg.Data.Summary = attrs["summary"] msg.Data.File = attrs["file"] msg.Data.Key = attrs["key"] msg.Data.EmojiID = attrs["emoji_id"] msg.Data.PackageID = attrs["emoji_package_id"] msg.Data.SubType = attrs["sub_type"] msg.Data.FileID = attrs["file_id"] msg.Data.FileSize = attrs["file_size"] msg.Data.FileUnique = attrs["file_unique"] // URL是必需的字段(接收图片时) if msg.Data.URL == "" { return fmt.Errorf("missing required url field") } return nil }