Skip to content

Commit 6f355e7

Browse files
committed
Merge branch 'dev' of https://github.com/Mrs4s/go-cqhttp into dev
2 parents 481cf7c + 565f863 commit 6f355e7

File tree

31 files changed

+234
-1180
lines changed

31 files changed

+234
-1180
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- name: Setup Go environment
2929
uses: actions/setup-go@v2.1.3
3030
with:
31-
go-version: 1.18
31+
go-version: 1.19
3232
- name: Cache downloaded module
3333
uses: actions/cache@v2
3434
with:

.github/workflows/golint.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,13 @@ jobs:
1212
- name: Setup Go environment
1313
uses: actions/setup-go@v2.1.3
1414
with:
15-
go-version: 1.18
15+
go-version: 1.19
1616

1717
- name: golangci-lint
1818
uses: golangci/golangci-lint-action@v2
1919
with:
2020
version: latest
2121

22-
- name: Static Check
23-
uses: dominikh/staticcheck-action@v1.2.0
24-
with:
25-
install-go: false
26-
version: "2022.1"
27-
2822
- name: Tests
2923
run: |
3024
go test $(go list ./...)

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
- name: Set up Go
1818
uses: actions/setup-go@v2
1919
with:
20-
go-version: '1.18'
20+
go-version: '1.19'
2121

2222
- name: Run GoReleaser
2323
uses: goreleaser/goreleaser-action@v2

.golangci.yml

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,25 @@ linters:
2121
disable-all: true
2222
fast: false
2323
enable:
24-
#- bodyclose
25-
#- deadcode
26-
#- depguard
27-
#- dogsled
24+
- bodyclose
25+
- durationcheck
2826
- gofmt
2927
- goimports
3028
- errcheck
3129
- exportloopref
3230
- exhaustive
3331
- bidichk
3432
- gocritic
35-
#- gosimple
33+
- gosimple
3634
- govet
3735
- ineffassign
3836
#- nolintlint
39-
#- rowserrcheck
40-
#- staticcheck
41-
- structcheck
42-
#- stylecheck
37+
- staticcheck
38+
- stylecheck
4339
- unconvert
44-
#- unparam
45-
#- unused
46-
- varcheck
40+
- usestdlibvars
41+
- unparam
42+
- unused
4743
- whitespace
4844
- prealloc
4945
- predeclared

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.18-alpine AS builder
1+
FROM golang:1.19-alpine AS builder
22

33
RUN go env -w GO111MODULE=auto \
44
&& go env -w CGO_ENABLED=0 \

cmd/gocq/login.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func loginResponseProcessor(res *client.LoginResponse) error {
151151
log.Warn("请输入(1 - 2) (将在10秒后自动选择1):")
152152
text = readLineTimeout(time.Second*10, "1")
153153
if strings.Contains(text, "1") {
154-
ticket := sliderCaptchaProcessor(res.VerifyUrl)
154+
ticket := getTicket(res.VerifyUrl)
155155
if ticket == "" {
156156
os.Exit(0)
157157
}
@@ -218,22 +218,39 @@ func loginResponseProcessor(res *client.LoginResponse) error {
218218
}
219219
}
220220

221-
func sliderCaptchaProcessor(u string) string {
221+
func getTicket(u string) (str string) {
222222
id := utils.RandomString(8)
223-
log.Warnf("请前往该地址验证 -> %v", strings.ReplaceAll(u, "https://ssl.captcha.qq.com/template/wireless_mqq_captcha.html?", fmt.Sprintf("https://captcha.go-cqhttp.org/captcha?id=%v&", id)))
224-
start := time.Now()
225-
for time.Since(start).Minutes() < 2 {
226-
time.Sleep(time.Second)
227-
data, err := global.GetBytes("https://captcha.go-cqhttp.org/captcha/ticket?id=" + id)
228-
if err != nil {
229-
log.Warnf("获取 Ticket 时出现错误: %v", err)
230-
return ""
231-
}
232-
g := gjson.ParseBytes(data)
233-
if g.Get("ticket").Exists() {
234-
return g.Get("ticket").String()
223+
log.Warnf("请前往该地址验证 -> %v <- 或输入手动抓取的 ticket:(Enter 提交)", strings.ReplaceAll(u, "https://ssl.captcha.qq.com/template/wireless_mqq_captcha.html?", fmt.Sprintf("https://captcha.go-cqhttp.org/captcha?id=%v&", id)))
224+
manual := make(chan string, 1)
225+
go func() {
226+
manual <- readLine()
227+
}()
228+
ticker := time.NewTicker(time.Second)
229+
defer ticker.Stop()
230+
for count := 120; count > 0; count-- {
231+
select {
232+
case <-ticker.C:
233+
str = fetchCaptcha(id)
234+
if str != "" {
235+
return
236+
}
237+
case str = <-manual:
238+
return
235239
}
236240
}
237241
log.Warnf("验证超时")
238242
return ""
239243
}
244+
245+
func fetchCaptcha(id string) string {
246+
data, err := global.GetBytes("https://captcha.go-cqhttp.org/captcha/ticket?id=" + id)
247+
if err != nil {
248+
log.Warnf("获取 Ticket 时出现错误: %v", err)
249+
return ""
250+
}
251+
g := gjson.ParseBytes(data)
252+
if g.Get("ticket").Exists() {
253+
return g.Get("ticket").String()
254+
}
255+
return ""
256+
}

coolq/api.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,9 @@ func (bot *CQBot) CQSendGroupMessage(groupID int64, m gjson.Result, autoEscape b
765765
}
766766
}
767767
fixAt(elem)
768-
mid := bot.SendGroupMessage(groupID, &message.SendingMessage{Elements: elem})
769-
if mid == -1 {
770-
return Failed(100, "SEND_MSG_API_ERROR", "请参考 go-cqhttp 端输出")
768+
mid, err := bot.SendGroupMessage(groupID, &message.SendingMessage{Elements: elem})
769+
if err != nil {
770+
return Failed(100, "SEND_MSG_API_ERROR", err.Error())
771771
}
772772
log.Infof("发送群 %v(%v) 的消息: %v (%v)", group.Name, groupID, limitedString(m.String()), mid)
773773
return OK(global.MSG{"message_id": mid})
@@ -836,7 +836,7 @@ func (bot *CQBot) uploadForwardElement(m gjson.Result, target int64, sourceType
836836
if len(bot.Client.GroupList) == 0 {
837837
groupID = 1
838838
} else {
839-
groupID = bot.Client.GroupList[1].Uin
839+
groupID = bot.Client.GroupList[0].Uin
840840
}
841841
}
842842
builder := bot.Client.NewForwardMessageBuilder(groupID)
@@ -977,8 +977,11 @@ func (bot *CQBot) CQSendGroupForwardMessage(groupID int64, m gjson.Result) globa
977977
log.Warnf("合并转发(群)消息发送失败: 账号可能被风控.")
978978
return Failed(100, "SEND_MSG_API_ERROR", "请参考 go-cqhttp 端输出")
979979
}
980+
mid := bot.InsertGroupMessage(ret)
981+
log.Infof("发送群 %v(%v) 的合并转发消息: %v (%v)", groupID, groupID, limitedString(m.String()), mid)
980982
return OK(global.MSG{
981-
"message_id": bot.InsertGroupMessage(ret),
983+
"message_id": mid,
984+
"forward_id": fe.ResId,
982985
})
983986
}
984987

@@ -1000,7 +1003,11 @@ func (bot *CQBot) CQSendPrivateForwardMessage(userID int64, m gjson.Result) glob
10001003
log.Warnf("合并转发(好友)消息发送失败: 账号可能被风控.")
10011004
return Failed(100, "SEND_MSG_API_ERROR", "请参考 go-cqhttp 端输出")
10021005
}
1003-
return OK(global.MSG{"message_id": mid})
1006+
log.Infof("发送好友 %v(%v) 的合并转发消息: %v (%v)", userID, userID, limitedString(m.String()), mid)
1007+
return OK(global.MSG{
1008+
"message_id": mid,
1009+
"forward_id": fe.ResId,
1010+
})
10041011
}
10051012

10061013
// CQSendPrivateMessage 发送私聊消息
@@ -1114,6 +1121,23 @@ func (bot *CQBot) CQSetGroupMemo(groupID int64, msg, img string) global.MSG {
11141121
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
11151122
}
11161123

1124+
// CQDelGroupMemo 扩展API-删除群公告
1125+
// @route(_del_group_notice)
1126+
// @rename(fid->notice_id)
1127+
func (bot *CQBot) CQDelGroupMemo(groupID int64, fid string) global.MSG {
1128+
if g := bot.Client.FindGroup(groupID); g != nil {
1129+
if g.SelfPermission() == client.Member {
1130+
return Failed(100, "PERMISSION_DENIED", "权限不足")
1131+
}
1132+
err := bot.Client.DelGroupNotice(groupID, fid)
1133+
if err != nil {
1134+
return Failed(100, "DELETE_NOTICE_ERROR", err.Error())
1135+
}
1136+
return OK(nil)
1137+
}
1138+
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
1139+
}
1140+
11171141
// CQSetGroupKick 群组踢人
11181142
//
11191143
// https://git.io/Jtz1V

coolq/bot.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/Mrs4s/go-cqhttp/db"
2424
"github.com/Mrs4s/go-cqhttp/global"
2525
"github.com/Mrs4s/go-cqhttp/internal/base"
26+
"github.com/Mrs4s/go-cqhttp/internal/mime"
2627
)
2728

2829
// CQBot CQBot结构体,存储Bot实例相关配置
@@ -152,10 +153,9 @@ func (bot *CQBot) uploadLocalImage(target message.Source, img *LocalImageElement
152153
defer func() { _ = f.Close() }()
153154
img.Stream = f
154155
}
155-
if lawful, mime := base.IsLawfulImage(img.Stream); !lawful {
156-
return nil, errors.New("image type error: " + mime)
156+
if mt, ok := mime.CheckImage(img.Stream); !ok {
157+
return nil, errors.New("image type error: " + mt)
157158
}
158-
// todo: enable multi-thread upload, now got error code 81
159159
i, err := bot.Client.UploadImage(target, img.Stream, 4)
160160
if err != nil {
161161
return nil, err
@@ -248,7 +248,7 @@ func (bot *CQBot) uploadMedia(target message.Source, elements []message.IMessage
248248
}
249249

250250
// SendGroupMessage 发送群消息
251-
func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) int32 {
251+
func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) (int32, error) {
252252
newElem := make([]message.IMessageElement, 0, len(m.Elements))
253253
group := bot.Client.FindGroup(groupID)
254254
source := message.Source{
@@ -264,14 +264,14 @@ func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) int
264264
mem.Poke()
265265
}
266266
}
267-
return 0
267+
return 0, nil
268268
case *message.MusicShareElement:
269269
ret, err := bot.Client.SendGroupMusicShare(groupID, i)
270270
if err != nil {
271271
log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupID, err)
272-
return -1
272+
return -1, errors.Wrap(err, "send group music share error")
273273
}
274-
return bot.InsertGroupMessage(ret)
274+
return bot.InsertGroupMessage(ret), nil
275275
case *message.AtElement:
276276
if i.Target == 0 && group.SelfPermission() == client.Member {
277277
e = message.NewText("@全体成员")
@@ -281,16 +281,16 @@ func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) int
281281
}
282282
if len(newElem) == 0 {
283283
log.Warnf("群消息发送失败: 消息为空.")
284-
return -1
284+
return -1, errors.New("empty message")
285285
}
286286
m.Elements = newElem
287287
bot.checkMedia(newElem, groupID)
288288
ret := bot.Client.SendGroupMessage(groupID, m)
289289
if ret == nil || ret.Id == -1 {
290290
log.Warnf("群消息发送失败: 账号可能被风控.")
291-
return -1
291+
return -1, errors.New("send group message failed: blocked by server")
292292
}
293-
return bot.InsertGroupMessage(ret)
293+
return bot.InsertGroupMessage(ret), nil
294294
}
295295

296296
// SendPrivateMessage 发送私聊消息

coolq/cqcode.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/Mrs4s/MiraiGo/message"
2121
"github.com/Mrs4s/MiraiGo/utils"
2222
b14 "github.com/fumiama/go-base16384"
23+
"github.com/segmentio/asm/base64"
2324
log "github.com/sirupsen/logrus"
2425
"github.com/tidwall/gjson"
2526

@@ -28,6 +29,7 @@ import (
2829
"github.com/Mrs4s/go-cqhttp/global"
2930
"github.com/Mrs4s/go-cqhttp/internal/base"
3031
"github.com/Mrs4s/go-cqhttp/internal/cache"
32+
"github.com/Mrs4s/go-cqhttp/internal/mime"
3133
"github.com/Mrs4s/go-cqhttp/internal/param"
3234
)
3335

@@ -82,14 +84,16 @@ func (e *PokeElement) Type() message.ElementType {
8284
func replyID(r *message.ReplyElement, source message.Source) int32 {
8385
id := source.PrimaryID
8486
seq := r.ReplySeq
85-
if source.SourceType == message.SourcePrivate {
87+
if r.GroupID != 0 {
88+
id = r.GroupID
89+
}
90+
// 私聊时,部分(不确定)的账号会在 ReplyElement 中带有 GroupID 字段。
91+
// 这里需要判断是由于 “直接回复” 功能,GroupID 为触发直接回复的来源那个群。
92+
if source.SourceType == message.SourcePrivate && (r.Sender == source.PrimaryID || r.GroupID == source.PrimaryID) {
8693
// 私聊似乎腾讯服务器有bug?
8794
seq = int32(uint16(seq))
8895
id = r.Sender
8996
}
90-
if r.GroupID != 0 {
91-
id = r.GroupID
92-
}
9397
return db.ToGlobalID(id, seq)
9498
}
9599

@@ -733,7 +737,12 @@ func (bot *CQBot) ConvertContentMessage(content []global.MSG, sourceType message
733737
case *message.GroupImageElement:
734738
img.Flash = flash
735739
img.EffectID = id
736-
img.ImageBizType = message.ImageBizType(data["subType"].(uint32))
740+
switch sub := data["subType"].(type) {
741+
case int64:
742+
img.ImageBizType = message.ImageBizType(sub)
743+
case uint32:
744+
img.ImageBizType = message.ImageBizType(sub)
745+
}
737746
case *message.FriendImageElement:
738747
img.Flash = flash
739748
}
@@ -839,8 +848,8 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
839848
return nil, err
840849
}
841850
if !global.IsAMRorSILK(data) {
842-
lawful, mt := base.IsLawfulAudio(bytes.NewReader(data))
843-
if !lawful {
851+
mt, ok := mime.CheckAudio(bytes.NewReader(data))
852+
if !ok {
844853
return nil, errors.New("audio type error: " + mt)
845854
}
846855
data, err = global.EncoderSilk(data)
@@ -1116,7 +1125,7 @@ func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video bool, sourceTy
11161125
return &LocalImageElement{File: fu.Path, URL: f}, nil
11171126
}
11181127
if !video && strings.HasPrefix(f, "base64") {
1119-
b, err := param.Base64DecodeString(strings.TrimPrefix(f, "base64://"))
1128+
b, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(f, "base64://"))
11201129
if err != nil {
11211130
return nil, err
11221131
}

0 commit comments

Comments
 (0)