diff --git a/coolq/api.go b/coolq/api.go index 35a5d1d..bcb7830 100644 --- a/coolq/api.go +++ b/coolq/api.go @@ -791,6 +791,7 @@ func (bot *CQBot) CQSendGuildChannelMessage(guildID, channelID uint64, m gjson.R func (bot *CQBot) uploadForwardElement(m gjson.Result, groupID int64) *message.ForwardElement { ts := time.Now().Add(-time.Minute * 5) fm := message.NewForwardMessage() + source := message.Source{SourceType: message.SourceGroup, PrimaryID: groupID} var lazyUpload []func() var wg sync.WaitGroup @@ -798,11 +799,22 @@ func (bot *CQBot) uploadForwardElement(m gjson.Result, groupID int64) *message.F for i, elem := range elems { iescape := i switch o := elem.(type) { - case *LocalImageElement, *LocalVideoElement: + case *LocalVideoElement: wg.Add(1) lazyUpload = append(lazyUpload, func() { defer wg.Done() - gm, err := bot.uploadMedia(o, groupID, true) + gm, err := bot.uploadLocalVideo(source, o) + if err != nil { + log.Warnf("警告: 群 %d %s上传失败: %v", groupID, o.Type().String(), err) + } else { + elems[iescape] = gm + } + }) + case *LocalImageElement: + wg.Add(1) + lazyUpload = append(lazyUpload, func() { + defer wg.Done() + gm, err := bot.uploadLocalImage(source, o) if err != nil { log.Warnf("警告: 群 %d %s上传失败: %v", groupID, o.Type().String(), err) } else { diff --git a/coolq/bot.go b/coolq/bot.go index 931c99b..00a53c8 100644 --- a/coolq/bot.go +++ b/coolq/bot.go @@ -129,8 +129,8 @@ func (bot *CQBot) OnEventPush(f func(e *Event)) { bot.lock.Unlock() } -// UploadLocalImageAsGroup 上传本地图片至群聊 -func (bot *CQBot) UploadLocalImageAsGroup(groupCode int64, img *LocalImageElement) (i *message.GroupImageElement, err error) { +// uploadLocalImage 上传本地图片 +func (bot *CQBot) uploadLocalImage(target message.Source, img *LocalImageElement) (i message.IMessageElement, err error) { if img.File != "" { f, err := os.Open(img.File) if err != nil { @@ -142,16 +142,19 @@ func (bot *CQBot) UploadLocalImageAsGroup(groupCode int64, img *LocalImageElemen if lawful, mime := base.IsLawfulImage(img.Stream); !lawful { return nil, errors.New("image type error: " + mime) } - i, err = bot.Client.UploadGroupImage(groupCode, img.Stream, 4) - if i != nil { + i, err = bot.Client.UploadImage(target, img.Stream, 4) + switch i := i.(type) { + case *message.GroupImageElement: i.Flash = img.Flash i.EffectID = img.EffectID + case *message.FriendImageElement: + i.Flash = img.Flash } return } -// UploadLocalVideo 上传本地短视频至群聊 -func (bot *CQBot) UploadLocalVideo(target message.Source, v *LocalVideoElement) (*message.ShortVideoElement, error) { +// uploadLocalVideo 上传本地短视频至群聊 +func (bot *CQBot) uploadLocalVideo(target message.Source, v *LocalVideoElement) (*message.ShortVideoElement, error) { video, err := os.Open(v.File) if err != nil { return nil, err @@ -160,55 +163,52 @@ func (bot *CQBot) UploadLocalVideo(target message.Source, v *LocalVideoElement) return bot.Client.UploadShortVideo(target, video, v.thumb, 4) } -// UploadLocalImageAsPrivate 上传本地图片至私聊 -func (bot *CQBot) UploadLocalImageAsPrivate(userID int64, img *LocalImageElement) (i *message.FriendImageElement, err error) { - if img.File != "" { - f, err := os.Open(img.File) - if err != nil { - return nil, errors.Wrap(err, "open image error") +func (bot *CQBot) uploadMedia(target message.Source, elements []message.IMessageElement) []message.IMessageElement { + var j int + for _, m := range elements { + raw := m // upload failed will make m nil, so copy it + var err error + switch e := m.(type) { + case *LocalImageElement: + m, err = bot.uploadLocalImage(target, e) + case *message.VoiceElement: + if target.SourceType == message.SourceGuildChannel { + continue // todo + } + m, err = bot.Client.UploadVoice(target, bytes.NewReader(e.Data)) + case *LocalVideoElement: + m, err = bot.uploadLocalVideo(target, e) } - defer func() { _ = f.Close() }() - img.Stream = f - } - if lawful, mime := base.IsLawfulImage(img.Stream); !lawful { - return nil, errors.New("image type error: " + mime) - } - i, err = bot.Client.UploadPrivateImage(userID, img.Stream) - if i != nil { - i.Flash = img.Flash - } - return -} - -// UploadLocalImageAsGuildChannel 上传本地图片至频道 -func (bot *CQBot) UploadLocalImageAsGuildChannel(guildID, channelID uint64, img *LocalImageElement) (*message.GuildImageElement, error) { - if img.File != "" { - f, err := os.Open(img.File) if err != nil { - return nil, errors.Wrap(err, "open image error") + var source string + switch target.SourceType { // nolint:exhaustive + case message.SourceGroup: + source = "群" + case message.SourcePrivate: + source = "私聊" + case message.SourceGuildChannel: + source = "频道" + } + log.Warnf("警告: %s %d %s上传失败: %v", source, target.PrimaryID, raw.Type().String(), err) + continue } - defer func() { _ = f.Close() }() - img.Stream = f + elements[j] = m + j++ } - if lawful, mime := base.IsLawfulImage(img.Stream); !lawful { - return nil, errors.New("image type error: " + mime) - } - return bot.Client.GuildService.UploadGuildImage(guildID, channelID, img.Stream) + return elements[:j] } // SendGroupMessage 发送群消息 func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) int32 { newElem := make([]message.IMessageElement, 0, len(m.Elements)) group := bot.Client.FindGroup(groupID) + source := message.Source{ + SourceType: message.SourceGroup, + PrimaryID: groupID, + } + m.Elements = bot.uploadMedia(source, m.Elements) for _, e := range m.Elements { switch i := e.(type) { - case *LocalImageElement, *message.VoiceElement, *LocalVideoElement: - i, err := bot.uploadMedia(i, groupID, true) - if err != nil { - log.Warnf("警告: 群 %d 消息%s上传失败: %v", groupID, e.Type().String(), err) - continue - } - e = i case *PokeElement: if group != nil { if mem := group.FindMember(i.Target); mem != nil { @@ -247,15 +247,13 @@ func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) int // SendPrivateMessage 发送私聊消息 func (bot *CQBot) SendPrivateMessage(target int64, groupID int64, m *message.SendingMessage) int32 { newElem := make([]message.IMessageElement, 0, len(m.Elements)) + source := message.Source{ + SourceType: message.SourcePrivate, + PrimaryID: target, + } + m.Elements = bot.uploadMedia(source, m.Elements) for _, e := range m.Elements { switch i := e.(type) { - case *LocalImageElement, *message.VoiceElement, *LocalVideoElement: - i, err := bot.uploadMedia(i, target, false) - if err != nil { - log.Warnf("警告: 私聊 %d 消息%s上传失败: %v", target, e.Type().String(), err) - continue - } - e = i case *PokeElement: bot.Client.SendFriendPoke(i.Target) return 0 @@ -344,33 +342,19 @@ func (bot *CQBot) SendPrivateMessage(target int64, groupID int64, m *message.Sen // SendGuildChannelMessage 发送频道消息 func (bot *CQBot) SendGuildChannelMessage(guildID, channelID uint64, m *message.SendingMessage) string { newElem := make([]message.IMessageElement, 0, len(m.Elements)) + source := message.Source{ + SourceType: message.SourceGuildChannel, + PrimaryID: int64(guildID), + SecondaryID: int64(channelID), + } + m.Elements = bot.uploadMedia(source, m.Elements) for _, e := range m.Elements { switch i := e.(type) { - case *LocalImageElement: - n, err := bot.UploadLocalImageAsGuildChannel(guildID, channelID, i) - if err != nil { - log.Warnf("警告: 频道 %d 消息%s上传失败: %v", channelID, e.Type().String(), err) - continue - } - e = n - - case *LocalVideoElement: - n, err := bot.UploadLocalVideo(message.Source{ - SourceType: message.SourceGuildChannel, - PrimaryID: int64(guildID), - SecondaryID: int64(channelID), - }, i) - if err != nil { - log.Warnf("警告: 频道 %d 消息%s上传失败: %v", channelID, e.Type().String(), err) - continue - } - e = n - case *message.MusicShareElement: bot.Client.SendGuildMusicShare(guildID, channelID, i) return "-1" // todo: fix this - case *LocalVoiceElement, *PokeElement: + case *message.VoiceElement, *PokeElement: log.Warnf("警告: 频道暂不支持发送 %v 消息", i.Type().String()) continue } @@ -575,28 +559,6 @@ func formatMemberName(mem *client.GroupMemberInfo) string { return fmt.Sprintf("%s(%d)", mem.DisplayName(), mem.Uin) } -func (bot *CQBot) uploadMedia(raw message.IMessageElement, target int64, group bool) (message.IMessageElement, error) { - switch m := raw.(type) { - case *LocalImageElement: - if group { - return bot.UploadLocalImageAsGroup(target, m) - } - return bot.UploadLocalImageAsPrivate(target, m) - case *message.VoiceElement: - if group { - return bot.Client.UploadGroupPtt(target, bytes.NewReader(m.Data)) - } - return bot.Client.UploadPrivatePtt(target, bytes.NewReader(m.Data)) - case *LocalVideoElement: - source := message.Source{ - SourceType: message.SourceGroup, - PrimaryID: target, - } - return bot.UploadLocalVideo(source, m) - } - return nil, errors.New("unsupported message element type") -} - // encodeMessageID 临时先这样, 暂时用不上 func encodeMessageID(target int64, seq int32) string { return hex.EncodeToString(binary.NewWriterF(func(w *binary.Writer) { diff --git a/coolq/cqcode.go b/coolq/cqcode.go index 5434d8d..48c1cf1 100644 --- a/coolq/cqcode.go +++ b/coolq/cqcode.go @@ -51,12 +51,6 @@ type LocalImageElement struct { EffectID int32 } -// LocalVoiceElement 本地语音 -type LocalVoiceElement struct { - message.VoiceElement - Stream io.ReadSeeker -} - // LocalVideoElement 本地视频 type LocalVideoElement struct { File string @@ -85,7 +79,7 @@ func (e *PokeElement) Type() message.ElementType { } func replyID(r *message.ReplyElement, source message.Source) int32 { - id := int64(source.PrimaryID) + id := source.PrimaryID seq := r.ReplySeq if source.SourceType == message.SourcePrivate { // 私聊似乎腾讯服务器有bug? @@ -1321,9 +1315,13 @@ func (bot *CQBot) makeShowPic(elem message.IMessageElement, source string, brief if brief == "" { brief = "[分享]我看到一张很赞的图片,分享给你,快来看!" } - if _, ok := elem.(*LocalImageElement); ok { + if local, ok := elem.(*LocalImageElement); ok { r := rand.Uint32() - e, err := bot.uploadMedia(elem, int64(r), group) + typ := message.SourceGroup + if !group { + typ = message.SourcePrivate + } + e, err := bot.uploadLocalImage(message.Source{SourceType: typ, PrimaryID: int64(r)}, local) if err != nil { log.Warnf("警告: 图片上传失败: %v", err) return nil, err diff --git a/go.mod b/go.mod index 2ee23ee..d4a5d59 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/Microsoft/go-winio v0.5.1 - github.com/Mrs4s/MiraiGo v0.0.0-20220221093105-1e32793eef06 + github.com/Mrs4s/MiraiGo v0.0.0-20220221153544-6b5e7d35f04d github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc github.com/fumiama/go-hide-param v0.1.4 github.com/gabriel-vasile/mimetype v1.4.0 diff --git a/go.sum b/go.sum index f8c754d..780331e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Mrs4s/MiraiGo v0.0.0-20220221093105-1e32793eef06 h1:9V7AhNUPJ1vqLAoXjwLdpv06hJWs15UdgYbKaHww60s= -github.com/Mrs4s/MiraiGo v0.0.0-20220221093105-1e32793eef06/go.mod h1:T66Ua3SOfpJMx+DcfQxk95MeR8RmvAVmjYSkoQQ8nwI= +github.com/Mrs4s/MiraiGo v0.0.0-20220221153544-6b5e7d35f04d h1:qnots7MzDtJHOvHPRG60gehAw2pUPBGa0GKBsUQNjRM= +github.com/Mrs4s/MiraiGo v0.0.0-20220221153544-6b5e7d35f04d/go.mod h1:T66Ua3SOfpJMx+DcfQxk95MeR8RmvAVmjYSkoQQ8nwI= github.com/RomiChan/protobuf v0.0.0-20220213164748-44b69c8bdec0 h1:8CK7Hg+CRGTFhpjvp5V+7wd8/TkuZ6fSuztLVV3bwoQ= github.com/RomiChan/protobuf v0.0.0-20220213164748-44b69c8bdec0/go.mod h1:CKKOWC7mBxd36zxsCB1V8DTrwlTNRQvkSVbYqyUiGEE= github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0= diff --git a/internal/param/param.go b/internal/param/param.go index 99e0e76..fd86b74 100644 --- a/internal/param/param.go +++ b/internal/param/param.go @@ -30,7 +30,7 @@ func EnsureBool(p interface{}, defaultVal bool) bool { if !j.Exists() { return defaultVal } - switch j.Type { + switch j.Type { // nolint: exhaustive case gjson.True: return true case gjson.False: