1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-05-04 19:17:37 +08:00

rf: move coolq/cqcode to internal/msg

This commit is contained in:
wdvxdr 2023-02-15 22:29:42 +08:00
parent 9c0525b3d4
commit 43dd9aa76d
11 changed files with 193 additions and 191 deletions

View File

@ -177,7 +177,7 @@ func conv(v, t string) string {
switch t { switch t {
default: default:
panic("unknown type: " + t) panic("unknown type: " + t)
case "gjson.Result", "*onebot.Spec", "IDConverter": case "gjson.Result", "*onebot.Spec":
return v return v
case "int64": case "int64":
return v + ".Int()" return v + ".Int()"

View File

@ -27,6 +27,7 @@ import (
"github.com/Mrs4s/go-cqhttp/internal/base" "github.com/Mrs4s/go-cqhttp/internal/base"
"github.com/Mrs4s/go-cqhttp/internal/cache" "github.com/Mrs4s/go-cqhttp/internal/cache"
"github.com/Mrs4s/go-cqhttp/internal/download" "github.com/Mrs4s/go-cqhttp/internal/download"
"github.com/Mrs4s/go-cqhttp/internal/msg"
"github.com/Mrs4s/go-cqhttp/internal/onebot" "github.com/Mrs4s/go-cqhttp/internal/onebot"
"github.com/Mrs4s/go-cqhttp/internal/param" "github.com/Mrs4s/go-cqhttp/internal/param"
"github.com/Mrs4s/go-cqhttp/modules/filter" "github.com/Mrs4s/go-cqhttp/modules/filter"
@ -851,7 +852,7 @@ func (bot *CQBot) uploadForwardElement(m gjson.Result, target int64, sourceType
for i, elem := range elems { for i, elem := range elems {
p := &elems[i] p := &elems[i]
switch o := elem.(type) { switch o := elem.(type) {
case *LocalVideoElement: case *msg.LocalVideo:
w.do(func() { w.do(func() {
gm, err := bot.uploadLocalVideo(source, o) gm, err := bot.uploadLocalVideo(source, o)
if err != nil { if err != nil {
@ -860,7 +861,7 @@ func (bot *CQBot) uploadForwardElement(m gjson.Result, target int64, sourceType
*p = gm *p = gm
} }
}) })
case *LocalImageElement: case *msg.LocalImage:
w.do(func() { w.do(func() {
gm, err := bot.uploadLocalImage(source, o) gm, err := bot.uploadLocalImage(source, o)
if err != nil { if err != nil {

View File

@ -26,6 +26,7 @@ import (
"github.com/Mrs4s/go-cqhttp/global" "github.com/Mrs4s/go-cqhttp/global"
"github.com/Mrs4s/go-cqhttp/internal/base" "github.com/Mrs4s/go-cqhttp/internal/base"
"github.com/Mrs4s/go-cqhttp/internal/mime" "github.com/Mrs4s/go-cqhttp/internal/mime"
"github.com/Mrs4s/go-cqhttp/internal/msg"
"github.com/Mrs4s/go-cqhttp/internal/onebot" "github.com/Mrs4s/go-cqhttp/internal/onebot"
) )
@ -147,7 +148,7 @@ func (w *worker) wait() {
} }
// uploadLocalImage 上传本地图片 // uploadLocalImage 上传本地图片
func (bot *CQBot) uploadLocalImage(target message.Source, img *LocalImageElement) (message.IMessageElement, error) { func (bot *CQBot) uploadLocalImage(target message.Source, img *msg.LocalImage) (message.IMessageElement, error) {
if img.File != "" { if img.File != "" {
f, err := os.Open(img.File) f, err := os.Open(img.File)
if err != nil { if err != nil {
@ -187,20 +188,20 @@ func (bot *CQBot) uploadLocalImage(target message.Source, img *LocalImageElement
} }
// uploadLocalVideo 上传本地短视频至群聊 // uploadLocalVideo 上传本地短视频至群聊
func (bot *CQBot) uploadLocalVideo(target message.Source, v *LocalVideoElement) (*message.ShortVideoElement, error) { func (bot *CQBot) uploadLocalVideo(target message.Source, v *msg.LocalVideo) (*message.ShortVideoElement, error) {
video, err := os.Open(v.File) video, err := os.Open(v.File)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer func() { _ = video.Close() }() defer func() { _ = video.Close() }()
return bot.Client.UploadShortVideo(target, video, v.thumb, 4) return bot.Client.UploadShortVideo(target, video, v.Thumb, 4)
} }
func removeLocalElement(elements []message.IMessageElement) []message.IMessageElement { func removeLocalElement(elements []message.IMessageElement) []message.IMessageElement {
var j int var j int
for i, e := range elements { for i, e := range elements {
switch e.(type) { switch e.(type) {
case *LocalImageElement, *LocalVideoElement: case *msg.LocalImage, *msg.LocalVideo:
case *message.VoiceElement: // 未上传的语音消息, 也删除 case *message.VoiceElement: // 未上传的语音消息, 也删除
case nil: case nil:
default: default:
@ -230,7 +231,7 @@ func (bot *CQBot) uploadMedia(target message.Source, elements []message.IMessage
for i, m := range elements { for i, m := range elements {
p := &elements[i] p := &elements[i]
switch e := m.(type) { switch e := m.(type) {
case *LocalImageElement: case *msg.LocalImage:
w.do(func() { w.do(func() {
m, err := bot.uploadLocalImage(target, e) m, err := bot.uploadLocalImage(target, e)
if err != nil { if err != nil {
@ -248,7 +249,7 @@ func (bot *CQBot) uploadMedia(target message.Source, elements []message.IMessage
*p = m *p = m
} }
}) })
case *LocalVideoElement: case *msg.LocalVideo:
w.do(func() { w.do(func() {
m, err := bot.uploadLocalVideo(target, e) m, err := bot.uploadLocalVideo(target, e)
if err != nil { if err != nil {
@ -274,7 +275,7 @@ func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) (in
m.Elements = bot.uploadMedia(source, m.Elements) m.Elements = bot.uploadMedia(source, m.Elements)
for _, e := range m.Elements { for _, e := range m.Elements {
switch i := e.(type) { switch i := e.(type) {
case *PokeElement: case *msg.Poke:
if group != nil { if group != nil {
if mem := group.FindMember(i.Target); mem != nil { if mem := group.FindMember(i.Target); mem != nil {
mem.Poke() mem.Poke()
@ -319,7 +320,7 @@ func (bot *CQBot) SendPrivateMessage(target int64, groupID int64, m *message.Sen
m.Elements = bot.uploadMedia(source, m.Elements) m.Elements = bot.uploadMedia(source, m.Elements)
for _, e := range m.Elements { for _, e := range m.Elements {
switch i := e.(type) { switch i := e.(type) {
case *PokeElement: case *msg.Poke:
bot.Client.SendFriendPoke(i.Target) bot.Client.SendFriendPoke(i.Target)
return 0 return 0
case *message.MusicShareElement: case *message.MusicShareElement:
@ -421,7 +422,7 @@ func (bot *CQBot) SendGuildChannelMessage(guildID, channelID uint64, m *message.
bot.Client.SendGuildMusicShare(guildID, channelID, i) bot.Client.SendGuildMusicShare(guildID, channelID, i)
return "-1" // todo: fix this return "-1" // todo: fix this
case *message.VoiceElement, *PokeElement: case *message.VoiceElement, *msg.Poke:
log.Warnf("警告: 频道暂不支持发送 %v 消息", i.Type().String()) log.Warnf("警告: 频道暂不支持发送 %v 消息", i.Type().String())
continue continue
} }

View File

@ -25,64 +25,24 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"github.com/Mrs4s/go-cqhttp/coolq/cqcode"
"github.com/Mrs4s/go-cqhttp/db" "github.com/Mrs4s/go-cqhttp/db"
"github.com/Mrs4s/go-cqhttp/global" "github.com/Mrs4s/go-cqhttp/global"
"github.com/Mrs4s/go-cqhttp/internal/base" "github.com/Mrs4s/go-cqhttp/internal/base"
"github.com/Mrs4s/go-cqhttp/internal/cache" "github.com/Mrs4s/go-cqhttp/internal/cache"
"github.com/Mrs4s/go-cqhttp/internal/download" "github.com/Mrs4s/go-cqhttp/internal/download"
"github.com/Mrs4s/go-cqhttp/internal/mime" "github.com/Mrs4s/go-cqhttp/internal/mime"
"github.com/Mrs4s/go-cqhttp/internal/msg"
"github.com/Mrs4s/go-cqhttp/internal/param" "github.com/Mrs4s/go-cqhttp/internal/param"
) )
/* // TODO: move this file to internal/msg, internal/onebot
var matchReg = regexp.MustCompile(`\[CQ:\w+?.*?]`) // TODO: support OneBot V12
var typeReg = regexp.MustCompile(`\[CQ:(\w+)`)
var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`)
*/
// PokeElement 拍一拍
type PokeElement struct {
Target int64
}
// LocalImageElement 本地图片
type LocalImageElement struct {
Stream io.ReadSeeker
File string
URL string
Flash bool
EffectID int32
}
// LocalVideoElement 本地视频
type LocalVideoElement struct {
File string
thumb io.ReadSeeker
}
const ( const (
maxImageSize = 1024 * 1024 * 30 // 30MB maxImageSize = 1024 * 1024 * 30 // 30MB
maxVideoSize = 1024 * 1024 * 100 // 100MB maxVideoSize = 1024 * 1024 * 100 // 100MB
) )
// Type implements the message.IMessageElement.
func (e *LocalImageElement) Type() message.ElementType {
return message.Image
}
// Type impl message.IMessageElement
func (e *LocalVideoElement) Type() message.ElementType {
return message.Video
}
// Type 获取元素类型ID
func (e *PokeElement) Type() message.ElementType {
// Make message.IMessageElement Happy
return message.At
}
func replyID(r *message.ReplyElement, source message.Source) int32 { func replyID(r *message.ReplyElement, source message.Source) int32 {
id := source.PrimaryID id := source.PrimaryID
seq := r.ReplySeq seq := r.ReplySeq
@ -102,11 +62,11 @@ func replyID(r *message.ReplyElement, source message.Source) int32 {
// toElements 将消息元素数组转为MSG数组以用于消息上报 // toElements 将消息元素数组转为MSG数组以用于消息上报
// //
// nolint:govet // nolint:govet
func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.Element) { func toElements(e []message.IMessageElement, source message.Source) (r []msg.Element) {
type pair = cqcode.Pair // simplify code type pair = msg.Pair // simplify code
type pairs = []pair type pairs = []pair
r = make([]cqcode.Element, 0, len(e)) r = make([]msg.Element, 0, len(e))
m := &message.SendingMessage{Elements: e} m := &message.SendingMessage{Elements: e}
reply := m.FirstOrNil(func(e message.IMessageElement) bool { reply := m.FirstOrNil(func(e message.IMessageElement) bool {
_, ok := e.(*message.ReplyElement) _, ok := e.(*message.ReplyElement)
@ -115,7 +75,7 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
if reply != nil && source.SourceType&(message.SourceGroup|message.SourcePrivate) != 0 { if reply != nil && source.SourceType&(message.SourceGroup|message.SourcePrivate) != 0 {
replyElem := reply.(*message.ReplyElement) replyElem := reply.(*message.ReplyElement)
id := replyID(replyElem, source) id := replyID(replyElem, source)
elem := cqcode.Element{ elem := msg.Element{
Type: "reply", Type: "reply",
Data: pairs{ Data: pairs{
{K: "id", V: strconv.FormatInt(int64(id), 10)}, {K: "id", V: strconv.FormatInt(int64(id), 10)},
@ -132,7 +92,7 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
r = append(r, elem) r = append(r, elem)
} }
for i, elem := range e { for i, elem := range e {
var m cqcode.Element var m msg.Element
switch o := elem.(type) { switch o := elem.(type) {
case *message.ReplyElement: case *message.ReplyElement:
if base.RemoveReplyAt && i+1 < len(e) { if base.RemoveReplyAt && i+1 < len(e) {
@ -143,14 +103,14 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
} }
continue continue
case *message.TextElement: case *message.TextElement:
m = cqcode.Element{ m = msg.Element{
Type: "text", Type: "text",
Data: pairs{ Data: pairs{
{K: "text", V: o.Content}, {K: "text", V: o.Content},
}, },
} }
case *message.LightAppElement: case *message.LightAppElement:
m = cqcode.Element{ m = msg.Element{
Type: "json", Type: "json",
Data: pairs{ Data: pairs{
{K: "data", V: o.Content}, {K: "data", V: o.Content},
@ -161,35 +121,35 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
if o.Target != 0 { if o.Target != 0 {
target = strconv.FormatUint(uint64(o.Target), 10) target = strconv.FormatUint(uint64(o.Target), 10)
} }
m = cqcode.Element{ m = msg.Element{
Type: "at", Type: "at",
Data: pairs{ Data: pairs{
{K: "qq", V: target}, {K: "qq", V: target},
}, },
} }
case *message.RedBagElement: case *message.RedBagElement:
m = cqcode.Element{ m = msg.Element{
Type: "redbag", Type: "redbag",
Data: pairs{ Data: pairs{
{K: "title", V: o.Title}, {K: "title", V: o.Title},
}, },
} }
case *message.ForwardElement: case *message.ForwardElement:
m = cqcode.Element{ m = msg.Element{
Type: "forward", Type: "forward",
Data: pairs{ Data: pairs{
{K: "id", V: o.ResId}, {K: "id", V: o.ResId},
}, },
} }
case *message.FaceElement: case *message.FaceElement:
m = cqcode.Element{ m = msg.Element{
Type: "face", Type: "face",
Data: pairs{ Data: pairs{
{K: "id", V: strconv.FormatInt(int64(o.Index), 10)}, {K: "id", V: strconv.FormatInt(int64(o.Index), 10)},
}, },
} }
case *message.VoiceElement: case *message.VoiceElement:
m = cqcode.Element{ m = msg.Element{
Type: "record", Type: "record",
Data: pairs{ Data: pairs{
{K: "file", V: o.Name}, {K: "file", V: o.Name},
@ -197,7 +157,7 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
}, },
} }
case *message.ShortVideoElement: case *message.ShortVideoElement:
m = cqcode.Element{ m = msg.Element{
Type: "video", Type: "video",
Data: pairs{ Data: pairs{
{K: "file", V: o.Name}, {K: "file", V: o.Name},
@ -217,7 +177,7 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
data = append(data, pair{K: "type", V: "show"}) data = append(data, pair{K: "type", V: "show"})
data = append(data, pair{K: "id", V: strconv.FormatInt(int64(o.EffectID), 10)}) data = append(data, pair{K: "id", V: strconv.FormatInt(int64(o.EffectID), 10)})
} }
m = cqcode.Element{ m = msg.Element{
Type: "image", Type: "image",
Data: data, Data: data,
} }
@ -226,7 +186,7 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
{K: "file", V: hex.EncodeToString(o.Md5) + ".image"}, {K: "file", V: hex.EncodeToString(o.Md5) + ".image"},
{K: "url", V: o.Url}, {K: "url", V: o.Url},
} }
m = cqcode.Element{ m = msg.Element{
Type: "image", Type: "image",
Data: data, Data: data,
} }
@ -238,33 +198,33 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
if o.Flash { if o.Flash {
data = append(data, pair{K: "type", V: "flash"}) data = append(data, pair{K: "type", V: "flash"})
} }
m = cqcode.Element{ m = msg.Element{
Type: "image", Type: "image",
Data: data, Data: data,
} }
case *message.DiceElement: case *message.DiceElement:
m = cqcode.Element{ m = msg.Element{
Type: "dice", Type: "dice",
Data: pairs{ Data: pairs{
{K: "value", V: strconv.FormatInt(int64(o.Value), 10)}, {K: "value", V: strconv.FormatInt(int64(o.Value), 10)},
}, },
} }
case *message.FingerGuessingElement: case *message.FingerGuessingElement:
m = cqcode.Element{ m = msg.Element{
Type: "rps", Type: "rps",
Data: pairs{ Data: pairs{
{K: "value", V: strconv.FormatInt(int64(o.Value), 10)}, {K: "value", V: strconv.FormatInt(int64(o.Value), 10)},
}, },
} }
case *message.MarketFaceElement: case *message.MarketFaceElement:
m = cqcode.Element{ m = msg.Element{
Type: "text", Type: "text",
Data: pairs{ Data: pairs{
{K: "text", V: o.Name}, {K: "text", V: o.Name},
}, },
} }
case *message.ServiceElement: case *message.ServiceElement:
m = cqcode.Element{ m = msg.Element{
Type: "xml", Type: "xml",
Data: pairs{ Data: pairs{
{K: "data", V: o.Content}, {K: "data", V: o.Content},
@ -275,14 +235,14 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
m.Type = "json" m.Type = "json"
} }
case *message.AnimatedSticker: case *message.AnimatedSticker:
m = cqcode.Element{ m = msg.Element{
Type: "face", Type: "face",
Data: pairs{ Data: pairs{
{K: "id", V: strconv.FormatInt(int64(o.ID), 10)}, {K: "id", V: strconv.FormatInt(int64(o.ID), 10)},
{K: "type", V: "sticker"}, {K: "type", V: "sticker"},
}, },
} }
case *LocalImageElement: case *msg.LocalImage:
data := pairs{ data := pairs{
{K: "file", V: o.File}, {K: "file", V: o.File},
{K: "url", V: o.URL}, {K: "url", V: o.URL},
@ -290,7 +250,7 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
if o.Flash { if o.Flash {
data = append(data, pair{K: "type", V: "flash"}) data = append(data, pair{K: "type", V: "flash"})
} }
m = cqcode.Element{ m = msg.Element{
Type: "image", Type: "image",
Data: data, Data: data,
} }
@ -536,11 +496,11 @@ func (bot *CQBot) ConvertStringMessage(raw string, sourceType message.SourceType
} }
if i > 0 { if i > 0 {
if base.SplitURL { if base.SplitURL {
for _, txt := range param.SplitURL(cqcode.UnescapeText(raw[:i])) { for _, txt := range param.SplitURL(msg.UnescapeText(raw[:i])) {
r = append(r, message.NewText(txt)) r = append(r, message.NewText(txt))
} }
} else { } else {
r = append(r, message.NewText(cqcode.UnescapeText(raw[:i]))) r = append(r, message.NewText(msg.UnescapeText(raw[:i])))
} }
} }
@ -585,7 +545,7 @@ func (bot *CQBot) ConvertStringMessage(raw string, sourceType message.SourceType
if i+1 > len(raw) { if i+1 > len(raw) {
return return
} }
d[key] = cqcode.UnescapeValue(raw[:i]) d[key] = msg.UnescapeValue(raw[:i])
raw = raw[i:] raw = raw[i:]
i = 0 i = 0
} }
@ -755,7 +715,7 @@ func (bot *CQBot) ConvertContentMessage(content []global.MSG, sourceType message
} }
} }
switch img := e.(type) { switch img := e.(type) {
case *LocalImageElement: case *msg.LocalImage:
img.Flash = flash img.Flash = flash
img.EffectID = id img.EffectID = id
case *message.GroupImageElement: case *message.GroupImageElement:
@ -849,7 +809,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
return img, err return img, err
} }
switch img := img.(type) { switch img := img.(type) {
case *LocalImageElement: case *msg.LocalImage:
img.Flash = flash img.Flash = flash
img.EffectID = int32(id) img.EffectID = int32(id)
case *message.GroupImageElement: case *message.GroupImageElement:
@ -863,14 +823,8 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
return img, err return img, err
case "poke": case "poke":
t, _ := strconv.ParseInt(d["qq"], 10, 64) t, _ := strconv.ParseInt(d["qq"], 10, 64)
return &PokeElement{Target: t}, nil return &msg.Poke{Target: t}, nil
case "tts": case "tts":
defer func() {
if r := recover(); r != nil {
m = nil
err = errors.New("tts 转换失败")
}
}()
data, err := bot.Client.GetTts(d["text"]) data, err := bot.Client.GetTts(d["text"])
if err != nil { if err != nil {
return nil, err return nil, err
@ -1024,10 +978,10 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
return message.NewFingerGuessing(int32(i)), nil return message.NewFingerGuessing(int32(i)), nil
case "xml": case "xml":
resID := d["resid"] resID := d["resid"]
template := cqcode.EscapeValue(d["data"]) template := msg.EscapeValue(d["data"])
i, _ := strconv.ParseInt(resID, 10, 64) i, _ := strconv.ParseInt(resID, 10, 64)
msg := message.NewRichXml(template, i) m := message.NewRichXml(template, i)
return msg, nil return m, nil
case "json": case "json":
resID := d["resid"] resID := d["resid"]
i, _ := strconv.ParseInt(resID, 10, 64) i, _ := strconv.ParseInt(resID, 10, 64)
@ -1064,7 +1018,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
if err != nil { if err != nil {
return nil, err return nil, err
} }
v, ok := file.(*LocalVideoElement) v, ok := file.(*msg.LocalVideo)
if !ok { if !ok {
return file, nil return file, nil
} }
@ -1081,7 +1035,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
} }
data, _ = os.ReadFile(v.File + ".jpg") data, _ = os.ReadFile(v.File + ".jpg")
} }
v.thumb = bytes.NewReader(data) v.Thumb = bytes.NewReader(data)
video, _ := os.Open(v.File) video, _ := os.Open(v.File)
defer video.Close() defer video.Close()
_, _ = video.Seek(4, io.SeekStart) _, _ = video.Seek(4, io.SeekStart)
@ -1135,9 +1089,9 @@ func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video bool, sourceTy
} }
useCacheFile: useCacheFile:
if video { if video {
return &LocalVideoElement{File: cacheFile}, nil return &msg.LocalVideo{File: cacheFile}, nil
} }
return &LocalImageElement{File: cacheFile, URL: f}, nil return &msg.LocalImage{File: cacheFile, URL: f}, nil
} }
if strings.HasPrefix(f, "file") { if strings.HasPrefix(f, "file") {
fu, err := url.Parse(f) fu, err := url.Parse(f)
@ -1158,26 +1112,26 @@ func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video bool, sourceTy
if info.Size() == 0 || info.Size() >= maxVideoSize { if info.Size() == 0 || info.Size() >= maxVideoSize {
return nil, errors.New("invalid video size") return nil, errors.New("invalid video size")
} }
return &LocalVideoElement{File: fu.Path}, nil return &msg.LocalVideo{File: fu.Path}, nil
} }
if info.Size() == 0 || info.Size() >= maxImageSize { if info.Size() == 0 || info.Size() >= maxImageSize {
return nil, errors.New("invalid image size") return nil, errors.New("invalid image size")
} }
return &LocalImageElement{File: fu.Path, URL: f}, nil return &msg.LocalImage{File: fu.Path, URL: f}, nil
} }
if !video && strings.HasPrefix(f, "base64") { if !video && strings.HasPrefix(f, "base64") {
b, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(f, "base64://")) b, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(f, "base64://"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &LocalImageElement{Stream: bytes.NewReader(b), URL: f}, nil return &msg.LocalImage{Stream: bytes.NewReader(b), URL: f}, nil
} }
if !video && strings.HasPrefix(f, "base16384") { if !video && strings.HasPrefix(f, "base16384") {
b, err := b14.UTF82UTF16BE(utils.S2B(strings.TrimPrefix(f, "base16384://"))) b, err := b14.UTF82UTF16BE(utils.S2B(strings.TrimPrefix(f, "base16384://")))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &LocalImageElement{Stream: bytes.NewReader(b14.Decode(b)), URL: f}, nil return &msg.LocalImage{Stream: bytes.NewReader(b14.Decode(b)), URL: f}, nil
} }
rawPath := path.Join(global.ImagePath, f) rawPath := path.Join(global.ImagePath, f)
if video { if video {
@ -1194,7 +1148,7 @@ func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video bool, sourceTy
return nil, errors.New("invalid video") return nil, errors.New("invalid video")
} }
if path.Ext(rawPath) != ".video" { if path.Ext(rawPath) != ".video" {
return &LocalVideoElement{File: rawPath}, nil return &msg.LocalVideo{File: rawPath}, nil
} }
b, _ := os.ReadFile(rawPath) b, _ := os.ReadFile(rawPath)
return bot.readVideoCache(b), nil return bot.readVideoCache(b), nil
@ -1203,7 +1157,7 @@ func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video bool, sourceTy
if sourceType == message.SourceGuildChannel { if sourceType == message.SourceGuildChannel {
cacheFile := path.Join(global.ImagePath, "guild-images", f) cacheFile := path.Join(global.ImagePath, "guild-images", f)
if global.PathExists(cacheFile) { if global.PathExists(cacheFile) {
return &LocalImageElement{File: cacheFile}, nil return &msg.LocalImage{File: cacheFile}, nil
} }
} }
if strings.HasSuffix(f, ".image") { if strings.HasSuffix(f, ".image") {
@ -1222,7 +1176,7 @@ func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video bool, sourceTy
return nil, errors.New("invalid image") return nil, errors.New("invalid image")
} }
if path.Ext(rawPath) != ".image" { if path.Ext(rawPath) != ".image" {
return &LocalImageElement{File: rawPath, URL: u}, nil return &msg.LocalImage{File: rawPath, URL: u}, nil
} }
b, err := os.ReadFile(rawPath) b, err := os.ReadFile(rawPath)
if err != nil { if err != nil {
@ -1283,7 +1237,7 @@ func (bot *CQBot) makeShowPic(elem message.IMessageElement, source string, brief
if brief == "" { if brief == "" {
brief = "&#91;分享&#93;我看到一张很赞的图片,分享给你,快来看!" brief = "&#91;分享&#93;我看到一张很赞的图片,分享给你,快来看!"
} }
if local, ok := elem.(*LocalImageElement); ok { if local, ok := elem.(*msg.LocalImage); ok {
r := rand.Uint32() r := rand.Uint32()
typ := message.SourceGroup typ := message.SourceGroup
if !group { if !group {

View File

@ -1,79 +0,0 @@
// Package cqcode provides CQCode util functions.
package cqcode
import "strings"
// EscapeText 将字符串raw中部分字符转义
//
// - & -> &amp;
// - [ -> &#91;
// - ] -> &#93;
func EscapeText(s string) string {
count := strings.Count(s, "&")
count += strings.Count(s, "[")
count += strings.Count(s, "]")
if count == 0 {
return s
}
// Apply replacements to buffer.
var b strings.Builder
b.Grow(len(s) + count*4)
start := 0
for i := 0; i < count; i++ {
j := start
for index, r := range s[start:] {
if r == '&' || r == '[' || r == ']' {
j += index
break
}
}
b.WriteString(s[start:j])
switch s[j] {
case '&':
b.WriteString("&amp;")
case '[':
b.WriteString("&#91;")
case ']':
b.WriteString("&#93;")
}
start = j + 1
}
b.WriteString(s[start:])
return b.String()
}
// EscapeValue 将字符串value中部分字符转义
//
// - , -> &#44;
// - & -> &amp;
// - [ -> &#91;
// - ] -> &#93;
func EscapeValue(value string) string {
ret := EscapeText(value)
return strings.ReplaceAll(ret, ",", "&#44;")
}
// UnescapeText 将字符串content中部分字符反转义
//
// - &amp; -> &
// - &#91; -> [
// - &#93; -> ]
func UnescapeText(content string) string {
ret := content
ret = strings.ReplaceAll(ret, "&#91;", "[")
ret = strings.ReplaceAll(ret, "&#93;", "]")
ret = strings.ReplaceAll(ret, "&amp;", "&")
return ret
}
// UnescapeValue 将字符串content中部分字符反转义
//
// - &#44; -> ,
// - &amp; -> &
// - &#91; -> [
// - &#93; -> ]
func UnescapeValue(content string) string {
ret := strings.ReplaceAll(content, "&#44;", ",")
return UnescapeText(ret)
}

View File

@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"github.com/Mrs4s/go-cqhttp/coolq/cqcode" "github.com/Mrs4s/go-cqhttp/internal/msg"
) )
var bot = CQBot{} var bot = CQBot{}
@ -44,7 +44,7 @@ const bText = `123456789[]&987654321[]&987654321[]&987654321[]&987654321[]&98765
func BenchmarkCQCodeEscapeText(b *testing.B) { func BenchmarkCQCodeEscapeText(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
ret := bText ret := bText
cqcode.EscapeText(ret) msg.EscapeText(ret)
} }
} }
@ -64,6 +64,6 @@ func TestCQCodeEscapeText(t *testing.T) {
ret = strings.ReplaceAll(ret, "&", "&amp;") ret = strings.ReplaceAll(ret, "&", "&amp;")
ret = strings.ReplaceAll(ret, "[", "&#91;") ret = strings.ReplaceAll(ret, "[", "&#91;")
ret = strings.ReplaceAll(ret, "]", "&#93;") ret = strings.ReplaceAll(ret, "]", "&#93;")
assert.Equal(t, ret, cqcode.EscapeText(rs)) assert.Equal(t, ret, msg.EscapeText(rs))
} }
} }

View File

@ -1,4 +1,5 @@
package cqcode // Package msg 提供了go-cqhttp消息中间表示CQ码处理等等
package msg
import ( import (
"bytes" "bytes"
@ -8,6 +9,85 @@ import (
"github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary"
) )
// @@@ CQ码转义处理 @@@
// EscapeText 将字符串raw中部分字符转义
//
// - & -> &amp;
// - [ -> &#91;
// - ] -> &#93;
func EscapeText(s string) string {
count := strings.Count(s, "&")
count += strings.Count(s, "[")
count += strings.Count(s, "]")
if count == 0 {
return s
}
// Apply replacements to buffer.
var b strings.Builder
b.Grow(len(s) + count*4)
start := 0
for i := 0; i < count; i++ {
j := start
for index, r := range s[start:] {
if r == '&' || r == '[' || r == ']' {
j += index
break
}
}
b.WriteString(s[start:j])
switch s[j] {
case '&':
b.WriteString("&amp;")
case '[':
b.WriteString("&#91;")
case ']':
b.WriteString("&#93;")
}
start = j + 1
}
b.WriteString(s[start:])
return b.String()
}
// EscapeValue 将字符串value中部分字符转义
//
// - , -> &#44;
// - & -> &amp;
// - [ -> &#91;
// - ] -> &#93;
func EscapeValue(value string) string {
ret := EscapeText(value)
return strings.ReplaceAll(ret, ",", "&#44;")
}
// UnescapeText 将字符串content中部分字符反转义
//
// - &amp; -> &
// - &#91; -> [
// - &#93; -> ]
func UnescapeText(content string) string {
ret := content
ret = strings.ReplaceAll(ret, "&#91;", "[")
ret = strings.ReplaceAll(ret, "&#93;", "]")
ret = strings.ReplaceAll(ret, "&amp;", "&")
return ret
}
// UnescapeValue 将字符串content中部分字符反转义
//
// - &#44; -> ,
// - &amp; -> &
// - &#91; -> [
// - &#93; -> ]
func UnescapeValue(content string) string {
ret := strings.ReplaceAll(content, "&#44;", ",")
return UnescapeText(ret)
}
// @@@ 消息中间表示 @@@
// Element single message // Element single message
type Element struct { type Element struct {
Type string Type string

View File

@ -1,4 +1,4 @@
package cqcode package msg
import ( import (
"bytes" "bytes"

44
internal/msg/local.go Normal file
View File

@ -0,0 +1,44 @@
package msg
import (
"io"
"github.com/Mrs4s/MiraiGo/message"
)
// Poke 拍一拍
type Poke struct {
Target int64
}
// Type 获取元素类型ID
func (e *Poke) Type() message.ElementType {
// Make message.IMessageElement Happy
return message.At
}
// LocalImage 本地图片
type LocalImage struct {
Stream io.ReadSeeker
File string
URL string
Flash bool
EffectID int32
}
// Type implements the message.IMessageElement.
func (e *LocalImage) Type() message.ElementType {
return message.Image
}
// LocalVideo 本地视频
type LocalVideo struct {
File string
Thumb io.ReadSeeker
}
// Type impl message.IMessageElement
func (e *LocalVideo) Type() message.ElementType {
return message.Video
}

View File

@ -3,7 +3,7 @@ package onebot
import "fmt" import "fmt"
//go:generate go run github.com/Mrs4s/go-cqhttp/cmd/api-generator -pkg onebot -path=./../../coolq/api.go,./../../coolq/api_v12.go -supported -o supported.go //go:generate go run ./../../cmd/api-generator -pkg onebot -path=./../../coolq/api.go,./../../coolq/api_v12.go -supported -o supported.go
// Spec OneBot Specification // Spec OneBot Specification
type Spec struct { type Spec struct {
@ -23,6 +23,7 @@ var V12 = &Spec{
SupportedActions: supportedV12, SupportedActions: supportedV12,
} }
// ConvertID 根据版本转换ID
func (s *Spec) ConvertID(id any) any { func (s *Spec) ConvertID(id any) any {
if s.Version == 12 { if s.Version == 12 {
return fmt.Sprint(id) return fmt.Sprint(id)

View File

@ -9,7 +9,7 @@ import (
"github.com/Mrs4s/go-cqhttp/internal/onebot" "github.com/Mrs4s/go-cqhttp/internal/onebot"
) )
//go:generate go run github.com/Mrs4s/go-cqhttp/cmd/api-generator -pkg api -path=./../../coolq/api.go,./../../coolq/api_v12.go -o api.go //go:generate go run ./../../cmd/api-generator -pkg api -path=./../../coolq/api.go,./../../coolq/api_v12.go -o api.go
// Getter 参数获取 // Getter 参数获取
type Getter interface { type Getter interface {