diff --git a/coolq/bot.go b/coolq/bot.go index 162a893..557cef5 100644 --- a/coolq/bot.go +++ b/coolq/bot.go @@ -28,6 +28,7 @@ import ( var json = jsoniter.ConfigCompatibleWithStandardLibrary +//CQBot CQBot结构体,存储Bot实例相关配置 type CQBot struct { Client *client.QQClient @@ -38,10 +39,13 @@ type CQBot struct { oneWayMsgCache sync.Map } +//MSG 消息Map type MSG map[string]interface{} +//ForceFragmented 是否启用强制分片 var ForceFragmented = false +//NewQQBot 初始化一个QQBot实例 func NewQQBot(cli *client.QQClient, conf *global.JSONConfig) *CQBot { bot := &CQBot{ Client: cli, @@ -102,10 +106,12 @@ func NewQQBot(cli *client.QQClient, conf *global.JSONConfig) *CQBot { return bot } +//OnEventPush 注册事件上报函数 func (bot *CQBot) OnEventPush(f func(m MSG)) { bot.events = append(bot.events, f) } +//GetMessage 获取给定消息id对应的消息 func (bot *CQBot) GetMessage(mid int32) MSG { if bot.db != nil { m := MSG{} @@ -123,6 +129,7 @@ func (bot *CQBot) GetMessage(mid int32) MSG { return nil } +//UploadLocalImageAsGroup 上传本地图片至群聊 func (bot *CQBot) UploadLocalImageAsGroup(groupCode int64, img *LocalImageElement) (*message.GroupImageElement, error) { if img.Stream != nil { return bot.Client.UploadGroupImage(groupCode, img.Stream) @@ -130,6 +137,7 @@ func (bot *CQBot) UploadLocalImageAsGroup(groupCode int64, img *LocalImageElemen return bot.Client.UploadGroupImageByFile(groupCode, img.File) } +//UploadLocalVideo 上传本地短视频至群聊 func (bot *CQBot) UploadLocalVideo(target int64, v *LocalVideoElement) (*message.ShortVideoElement, error) { if v.File != "" { video, err := os.Open(v.File) @@ -146,9 +154,10 @@ func (bot *CQBot) UploadLocalVideo(target int64, v *LocalVideoElement) (*message return &v.ShortVideoElement, nil } -func (bot *CQBot) UploadLocalImageAsPrivate(userId int64, img *LocalImageElement) (*message.FriendImageElement, error) { +//UploadLocalImageAsPrivate 上传本地图片至私聊 +func (bot *CQBot) UploadLocalImageAsPrivate(userID int64, img *LocalImageElement) (*message.FriendImageElement, error) { if img.Stream != nil { - return bot.Client.UploadPrivateImage(userId, img.Stream) + return bot.Client.UploadPrivateImage(userID, img.Stream) } // need update. f, err := os.Open(img.File) @@ -156,41 +165,42 @@ func (bot *CQBot) UploadLocalImageAsPrivate(userId int64, img *LocalImageElement return nil, err } defer f.Close() - return bot.Client.UploadPrivateImage(userId, f) + return bot.Client.UploadPrivateImage(userID, f) } -func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int32 { +//SendGroupMessage 发送群消息 +func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) int32 { var newElem []message.IMessageElement for _, elem := range m.Elements { if i, ok := elem.(*LocalImageElement); ok { - gm, err := bot.UploadLocalImageAsGroup(groupId, i) + gm, err := bot.UploadLocalImageAsGroup(groupID, i) if err != nil { - log.Warnf("警告: 群 %v 消息图片上传失败: %v", groupId, err) + log.Warnf("警告: 群 %v 消息图片上传失败: %v", groupID, err) continue } newElem = append(newElem, gm) continue } if i, ok := elem.(*message.VoiceElement); ok { - gv, err := bot.Client.UploadGroupPtt(groupId, bytes.NewReader(i.Data)) + gv, err := bot.Client.UploadGroupPtt(groupID, bytes.NewReader(i.Data)) if err != nil { - log.Warnf("警告: 群 %v 消息语音上传失败: %v", groupId, err) + log.Warnf("警告: 群 %v 消息语音上传失败: %v", groupID, err) continue } newElem = append(newElem, gv) continue } if i, ok := elem.(*LocalVideoElement); ok { - gv, err := bot.UploadLocalVideo(groupId, i) + gv, err := bot.UploadLocalVideo(groupID, i) if err != nil { - log.Warnf("警告: 群 %v 消息短视频上传失败: %v", groupId, err) + log.Warnf("警告: 群 %v 消息短视频上传失败: %v", groupID, err) continue } newElem = append(newElem, gv) continue } if i, ok := elem.(*PokeElement); ok { - if group := bot.Client.FindGroup(groupId); group != nil { + if group := bot.Client.FindGroup(groupID); group != nil { if mem := group.FindMember(i.Target); mem != nil { mem.Poke() return 0 @@ -198,15 +208,15 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int } } if i, ok := elem.(*GiftElement); ok { - bot.Client.SendGroupGift(uint64(groupId), uint64(i.Target), i.GiftId) + bot.Client.SendGroupGift(uint64(groupID), uint64(i.Target), i.GiftID) return 0 } if i, ok := elem.(*QQMusicElement); ok { var msgStyle uint32 = 4 - if i.MusicUrl == "" { + if i.MusicURL == "" { msgStyle = 0 // fix vip song } - ret, err := bot.Client.SendGroupRichMessage(groupId, 100497308, 1, msgStyle, client.RichClientInfo{ + ret, err := bot.Client.SendGroupRichMessage(groupID, 100497308, 1, msgStyle, client.RichClientInfo{ Platform: 1, SdkVersion: "0.0.0", PackageName: "com.tencent.qqmusic", @@ -214,18 +224,18 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int }, &message.RichMessage{ Title: i.Title, Summary: i.Summary, - Url: i.Url, - PictureUrl: i.PictureUrl, - MusicUrl: i.MusicUrl, + Url: i.URL, + PictureUrl: i.PictureURL, + MusicUrl: i.MusicURL, }) if err != nil { - log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupId, err) + log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupID, err) return -1 } return bot.InsertGroupMessage(ret) } if i, ok := elem.(*CloudMusicElement); ok { - ret, err := bot.Client.SendGroupRichMessage(groupId, 100495085, 1, 4, client.RichClientInfo{ + ret, err := bot.Client.SendGroupRichMessage(groupID, 100495085, 1, 4, client.RichClientInfo{ Platform: 1, SdkVersion: "0.0.0", PackageName: "com.netease.cloudmusic", @@ -233,18 +243,18 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int }, &message.RichMessage{ Title: i.Title, Summary: i.Summary, - Url: i.Url, - PictureUrl: i.PictureUrl, - MusicUrl: i.MusicUrl, + Url: i.URL, + PictureUrl: i.PictureURL, + MusicUrl: i.MusicURL, }) if err != nil { - log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupId, err) + log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupID, err) return -1 } return bot.InsertGroupMessage(ret) } if i, ok := elem.(*MiguMusicElement); ok { - ret, err := bot.Client.SendGroupRichMessage(groupId, 1101053067, 1, 4, client.RichClientInfo{ + ret, err := bot.Client.SendGroupRichMessage(groupID, 1101053067, 1, 4, client.RichClientInfo{ Platform: 1, SdkVersion: "0.0.0", PackageName: "cmccwm.mobilemusic", @@ -252,12 +262,12 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int }, &message.RichMessage{ Title: i.Title, Summary: i.Summary, - Url: i.Url, - PictureUrl: i.PictureUrl, - MusicUrl: i.MusicUrl, + Url: i.URL, + PictureUrl: i.PictureURL, + MusicUrl: i.MusicURL, }) if err != nil { - log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupId, err) + log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupID, err) return -1 } return bot.InsertGroupMessage(ret) @@ -270,7 +280,7 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int } m.Elements = newElem bot.checkMedia(newElem) - ret := bot.Client.SendGroupMessage(groupId, m, ForceFragmented) + ret := bot.Client.SendGroupMessage(groupID, m, ForceFragmented) if ret == nil || ret.Id == -1 { log.Warnf("群消息发送失败: 账号可能被风控.") return -1 @@ -278,6 +288,7 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int return bot.InsertGroupMessage(ret) } +//SendPrivateMessage 发送私聊消息 func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) int32 { var newElem []message.IMessageElement for _, elem := range m.Elements { @@ -314,7 +325,7 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in } if i, ok := elem.(*QQMusicElement); ok { var msgStyle uint32 = 4 - if i.MusicUrl == "" { + if i.MusicURL == "" { msgStyle = 0 // fix vip song } bot.Client.SendFriendRichMessage(target, 100497308, 1, msgStyle, client.RichClientInfo{ @@ -325,9 +336,9 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in }, &message.RichMessage{ Title: i.Title, Summary: i.Summary, - Url: i.Url, - PictureUrl: i.PictureUrl, - MusicUrl: i.MusicUrl, + Url: i.URL, + PictureUrl: i.PictureURL, + MusicUrl: i.MusicURL, }) return 0 } @@ -340,9 +351,9 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in }, &message.RichMessage{ Title: i.Title, Summary: i.Summary, - Url: i.Url, - PictureUrl: i.PictureUrl, - MusicUrl: i.MusicUrl, + Url: i.URL, + PictureUrl: i.PictureURL, + MusicUrl: i.MusicURL, }) return 0 } @@ -355,9 +366,9 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in }, &message.RichMessage{ Title: i.Title, Summary: i.Summary, - Url: i.Url, - PictureUrl: i.PictureUrl, - MusicUrl: i.MusicUrl, + Url: i.URL, + PictureUrl: i.PictureURL, + MusicUrl: i.MusicURL, }) return 0 } @@ -392,6 +403,7 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in return id } +//InsertGroupMessage 群聊消息入数据库 func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 { val := MSG{ "message-id": m.Id, @@ -402,7 +414,7 @@ func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 { "time": m.Time, "message": ToStringMessage(m.Elements, m.GroupCode, true), } - id := ToGlobalId(m.GroupCode, m.Id) + id := toGlobalID(m.GroupCode, m.Id) if bot.db != nil { buf := new(bytes.Buffer) if err := gob.NewEncoder(buf).Encode(val); err != nil { @@ -417,6 +429,7 @@ func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 { return id } +//InsertPrivateMessage 私聊消息入数据库 func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage) int32 { val := MSG{ "message-id": m.Id, @@ -426,7 +439,7 @@ func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage) int32 { "time": m.Time, "message": ToStringMessage(m.Elements, m.Sender.Uin, true), } - id := ToGlobalId(m.Sender.Uin, m.Id) + id := toGlobalID(m.Sender.Uin, m.Id) if bot.db != nil { buf := new(bytes.Buffer) if err := gob.NewEncoder(buf).Encode(val); err != nil { @@ -441,10 +454,12 @@ func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage) int32 { return id } -func ToGlobalId(code int64, msgId int32) int32 { - return int32(crc32.ChecksumIEEE([]byte(fmt.Sprintf("%d-%d", code, msgId)))) +//toGlobalID 构建`code`-`msgID`的字符串并返回其CRC32 Checksum的值 +func toGlobalID(code int64, msgID int32) int32 { + return int32(crc32.ChecksumIEEE([]byte(fmt.Sprintf("%d-%d", code, msgID)))) } +//Release 释放Bot实例 func (bot *CQBot) Release() { if bot.db != nil { _ = bot.db.Close() @@ -535,7 +550,8 @@ func formatMemberName(mem *client.GroupMemberInfo) string { return fmt.Sprintf("%s(%d)", mem.DisplayName(), mem.Uin) } -func (m MSG) ToJson() string { +//ToJSON 生成JSON字符串 +func (m MSG) ToJSON() string { b, _ := json.Marshal(m) return string(b) } diff --git a/coolq/cqcode.go b/coolq/cqcode.go index 4032e1a..82debbb 100644 --- a/coolq/cqcode.go +++ b/coolq/cqcode.go @@ -34,67 +34,83 @@ var typeReg = regexp.MustCompile(`\[CQ:(\w+)`) var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`) */ +//IgnoreInvalidCQCode 是否忽略无效CQ码 var IgnoreInvalidCQCode = false -var SplitUrl = false + +//SplitURL 是否分割URL +var SplitURL = false const maxImageSize = 1024 * 1024 * 30 // 30MB const maxVideoSize = 1024 * 1024 * 100 // 100MB - +//PokeElement 拍一拍 type PokeElement struct { Target int64 } +//GiftElement 礼物 type GiftElement struct { Target int64 - GiftId message.GroupGift + GiftID message.GroupGift } +//MusicElement 音乐 type MusicElement struct { Title string Summary string - Url string - PictureUrl string - MusicUrl string + URL string + PictureURL string + MusicURL string } +//QQMusicElement QQ音乐 type QQMusicElement struct { MusicElement } +//CloudMusicElement 网易云音乐 type CloudMusicElement struct { MusicElement } +//MiguMusicElement 咪咕音乐 type MiguMusicElement struct { MusicElement } +//LocalImageElement 本地图片 type LocalImageElement struct { message.ImageElement Stream io.ReadSeeker File string } +//LocalVoiceElement 本地语音 type LocalVoiceElement struct { message.VoiceElement Stream io.ReadSeeker } +//LocalVideoElement 本地视频 type LocalVideoElement struct { message.ShortVideoElement File string thumb io.ReadSeeker } +//Type 获取元素类型ID func (e *GiftElement) Type() message.ElementType { + //Make message.IMessageElement Happy return message.At } +//Type 获取元素类型ID func (e *MusicElement) Type() message.ElementType { + //Make message.IMessageElement Happy return message.Service } -var GiftId = [...]message.GroupGift{ +//GiftID 礼物ID数组 +var GiftID = [...]message.GroupGift{ message.SweetWink, message.HappyCola, message.LuckyBracelet, @@ -111,15 +127,18 @@ var GiftId = [...]message.GroupGift{ message.LoveMask, } +//Type 获取元素类型ID func (e *PokeElement) Type() message.ElementType { + //Make message.IMessageElement Happy return message.At } -func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []MSG) { +//ToArrayMessage 将消息元素数组转为MSG数组以用于消息上报 +func ToArrayMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r []MSG) { r = []MSG{} ur := false - if len(raw) != 0 { - ur = raw[0] + if len(isRaw) != 0 { + ur = isRaw[0] } m := &message.SendingMessage{Elements: e} reply := m.FirstOrNil(func(e message.IMessageElement) bool { @@ -129,7 +148,7 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M if reply != nil { r = append(r, MSG{ "type": "reply", - "data": map[string]string{"id": fmt.Sprint(ToGlobalId(code, reply.(*message.ReplyElement).ReplySeq))}, + "data": map[string]string{"id": fmt.Sprint(toGlobalID(id, reply.(*message.ReplyElement).ReplySeq))}, }) } for _, elem := range e { @@ -266,10 +285,11 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M return } -func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r string) { +//ToStringMessage 将消息元素数组转为字符串以用于消息上报 +func ToStringMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r string) { ur := false - if len(raw) != 0 { - ur = raw[0] + if len(isRaw) != 0 { + ur = isRaw[0] } // 方便 m := &message.SendingMessage{Elements: e} @@ -278,7 +298,7 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st return ok }) if reply != nil { - r += fmt.Sprintf("[CQ:reply,id=%d]", ToGlobalId(code, reply.(*message.ReplyElement).ReplySeq)) + r += fmt.Sprintf("[CQ:reply,id=%d]", toGlobalID(id, reply.(*message.ReplyElement).ReplySeq)) } for _, elem := range e { switch o := elem.(type) { @@ -344,7 +364,8 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st return } -func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMessageElement) { +//ConvertStringMessage 将消息字符串转为消息元素数组 +func (bot *CQBot) ConvertStringMessage(msg string, isGroup bool) (r []message.IMessageElement) { index := 0 stat := 0 rMsg := []rune(msg) @@ -369,7 +390,7 @@ func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMes } saveTempText := func() { if len(tempText) != 0 { - if SplitUrl { + if SplitURL { for _, t := range global.SplitURL(CQCodeUnescapeValue(string(tempText))) { r = append(r, message.NewText(t)) } @@ -421,7 +442,7 @@ func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMes ReplySeq: org["message-id"].(int32), Sender: org["sender"].(message.Sender).Uin, Time: org["time"].(int32), - Elements: bot.ConvertStringMessage(org["message"].(string), group), + Elements: bot.ConvertStringMessage(org["message"].(string), isGroup), }, }, r...) return @@ -441,7 +462,7 @@ func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMes ReplySeq: int32(0), Sender: sender, Time: int32(msgTime), - Elements: bot.ConvertStringMessage(customText, group), + Elements: bot.ConvertStringMessage(customText, isGroup), }, }, r...) return @@ -453,7 +474,7 @@ func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMes return } } - elem, err := bot.ToElement(t, params, group) + elem, err := bot.ToElement(t, params, isGroup) if err != nil { org := "[CQ:" + string(cqCode) + "]" if !IgnoreInvalidCQCode { @@ -500,10 +521,11 @@ func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMes return } -func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message.IMessageElement) { +//ConvertObjectMessage 将消息JSON对象转为消息元素数组 +func (bot *CQBot) ConvertObjectMessage(m gjson.Result, isGroup bool) (r []message.IMessageElement) { convertElem := func(e gjson.Result) { t := e.Get("type").Str - if t == "reply" && group { + if t == "reply" && isGroup { if len(r) > 0 { if _, ok := r[0].(*message.ReplyElement); ok { log.Warnf("警告: 一条信息只能包含一个 Reply 元素.") @@ -520,7 +542,7 @@ func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message. ReplySeq: org["message-id"].(int32), Sender: org["sender"].(message.Sender).Uin, Time: org["time"].(int32), - Elements: bot.ConvertStringMessage(org["message"].(string), group), + Elements: bot.ConvertStringMessage(org["message"].(string), isGroup), }, }, r...) return @@ -540,7 +562,7 @@ func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message. ReplySeq: int32(0), Sender: sender, Time: int32(msgTime), - Elements: bot.ConvertStringMessage(customText, group), + Elements: bot.ConvertStringMessage(customText, isGroup), }, }, r...) return @@ -555,7 +577,7 @@ func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message. d[key.Str] = value.String() return true }) - elem, err := bot.ToElement(t, d, group) + elem, err := bot.ToElement(t, d, isGroup) if err != nil { log.Warnf("转换CQ码到MiraiGo Element时出现错误: %v 将忽略本段CQ码.", err) return @@ -568,7 +590,7 @@ func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message. } } if m.Type == gjson.String { - return bot.ConvertStringMessage(m.Str, group) + return bot.ConvertStringMessage(m.Str, isGroup) } if m.IsArray() { for _, e := range m.Array() { @@ -582,12 +604,14 @@ func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message. } // ToElement 将解码后的CQCode转换为Element. +// // 返回 interface{} 存在三种类型 +// // message.IMessageElement []message.IMessageElement nil -func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interface{}, err error) { +func (bot *CQBot) ToElement(t string, d map[string]string, isGroup bool) (m interface{}, err error) { switch t { case "text": - if SplitUrl { + if SplitURL { var ret []message.IMessageElement for _, text := range global.SplitURL(d["text"]) { ret = append(ret, message.NewText(text)) @@ -596,7 +620,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf } return message.NewText(d["text"]), nil case "image": - img, err := bot.makeImageOrVideoElem(d, false, group) + img, err := bot.makeImageOrVideoElem(d, false, isGroup) if err != nil { return nil, err } @@ -605,7 +629,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf return img, nil } if i, ok := img.(*LocalImageElement); ok { // 秀图,闪照什么的就直接传了吧 - if group { + if isGroup { img, err = bot.UploadLocalImageAsGroup(1, i) } else { img, err = bot.UploadLocalImageAsPrivate(1, i) @@ -637,7 +661,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf t, _ := strconv.ParseInt(d["qq"], 10, 64) return &PokeElement{Target: t}, nil case "gift": - if !group { + if !isGroup { return nil, errors.New("private gift unsupported") // no free private gift } t, _ := strconv.ParseInt(d["qq"], 10, 64) @@ -645,7 +669,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf if id < 0 || id >= 14 { return nil, errors.New("invalid gift id") } - return &GiftElement{Target: t, GiftId: GiftId[id]}, nil + return &GiftElement{Target: t, GiftID: GiftID[id]}, nil case "tts": defer func() { if r := recover(); r != nil { @@ -703,7 +727,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf mid := info.Get("track_info.mid").Str albumMid := info.Get("track_info.album.mid").Str pinfo, _ := global.GetBytes("http://u.y.qq.com/cgi-bin/musicu.fcg?g_tk=2034008533&uin=0&format=json&data={\"comm\":{\"ct\":23,\"cv\":0},\"url_mid\":{\"module\":\"vkey.GetVkeyServer\",\"method\":\"CgiGetVkey\",\"param\":{\"guid\":\"4311206557\",\"songmid\":[\"" + mid + "\"],\"songtype\":[0],\"uin\":\"0\",\"loginflag\":1,\"platform\":\"23\"}}}&_=1599039471576") - jumpUrl := "https://i.y.qq.com/v8/playsong.html?platform=11&appshare=android_qq&appversion=10030010&hosteuin=oKnlNenz7i-s7c**&songmid=" + mid + "&type=0&appsongtype=1&_wv=1&source=qq&ADTAG=qfshare" + jumpURL := "https://i.y.qq.com/v8/playsong.html?platform=11&appshare=android_qq&appversion=10030010&hosteuin=oKnlNenz7i-s7c**&songmid=" + mid + "&type=0&appsongtype=1&_wv=1&source=qq&ADTAG=qfshare" purl := gjson.ParseBytes(pinfo).Get("url_mid.data.midurlinfo.0.purl").Str preview := "http://y.gtimg.cn/music/photo_new/T002R180x180M000" + albumMid + ".jpg" if len(aid) < 2 { @@ -716,9 +740,9 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf return &QQMusicElement{MusicElement: MusicElement{ Title: name, Summary: content, - Url: jumpUrl, - PictureUrl: preview, - MusicUrl: purl, + URL: jumpURL, + PictureURL: preview, + MusicURL: purl, }}, nil } if d["type"] == "163" { @@ -730,9 +754,9 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf return nil, errors.New("song not found") } name := info.Get("name").Str - jumpUrl := "https://y.music.163.com/m/song/" + d["id"] - musicUrl := "http://music.163.com/song/media/outer/url?id=" + d["id"] - picUrl := info.Get("album.picUrl").Str + jumpURL := "https://y.music.163.com/m/song/" + d["id"] + musicURL := "http://music.163.com/song/media/outer/url?id=" + d["id"] + picURL := info.Get("album.picUrl").Str artistName := "" if info.Get("artists.0").Exists() { artistName = info.Get("artists.0.name").Str @@ -740,9 +764,9 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf return &CloudMusicElement{MusicElement{ Title: name, Summary: artistName, - Url: jumpUrl, - PictureUrl: picUrl, - MusicUrl: musicUrl, + URL: jumpURL, + PictureURL: picURL, + MusicURL: musicURL, }}, nil } if d["type"] == "custom" { @@ -750,31 +774,31 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf return &QQMusicElement{MusicElement{ Title: d["title"], Summary: d["content"], - Url: d["url"], - PictureUrl: d["image"], - MusicUrl: d["purl"], + URL: d["url"], + PictureURL: d["image"], + MusicURL: d["purl"], }}, nil } if d["subtype"] == "163" { return &CloudMusicElement{MusicElement{ Title: d["title"], Summary: d["content"], - Url: d["url"], - PictureUrl: d["image"], - MusicUrl: d["purl"], + URL: d["url"], + PictureURL: d["image"], + MusicURL: d["purl"], }}, nil } if d["subtype"] == "migu" { return &MiguMusicElement{MusicElement{ Title: d["title"], Summary: d["content"], - Url: d["url"], - PictureUrl: d["image"], - MusicUrl: d["purl"], + URL: d["url"], + PictureURL: d["image"], + MusicURL: d["purl"], }}, nil } xml := fmt.Sprintf(``, - XmlEscape(d["title"]), d["url"], d["image"], d["audio"], XmlEscape(d["title"]), XmlEscape(d["content"])) + XMLEscape(d["title"]), d["url"], d["image"], d["audio"], XMLEscape(d["title"]), XMLEscape(d["content"])) return &message.ServiceElement{ Id: 60, Content: xml, @@ -783,14 +807,14 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf } return nil, errors.New("unsupported music type: " + d["type"]) case "xml": - resId := d["resid"] + resID := d["resid"] template := CQCodeEscapeValue(d["data"]) - i, _ := strconv.ParseInt(resId, 10, 64) + i, _ := strconv.ParseInt(resID, 10, 64) msg := message.NewRichXml(template, i) return msg, nil case "json": - resId := d["resid"] - i, _ := strconv.ParseInt(resId, 10, 64) + resID := d["resid"] + i, _ := strconv.ParseInt(resID, 10, 64) if i == 0 { //默认情况下走小程序通道 msg := message.NewLightApp(CQCodeUnescapeValue(d["data"])) @@ -818,17 +842,17 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf if maxHeight == 0 { maxHeight = 1000 } - img, err := bot.makeImageOrVideoElem(d, false, group) + img, err := bot.makeImageOrVideoElem(d, false, isGroup) if err != nil { return nil, errors.New("send cardimage faild") } - return bot.makeShowPic(img, source, icon, minWidth, minHeight, maxWidth, maxHeight, group) + return bot.makeShowPic(img, source, icon, minWidth, minHeight, maxWidth, maxHeight, isGroup) case "video": cache := d["cache"] if cache == "" { cache = "1" } - file, err := bot.makeImageOrVideoElem(d, true, group) + file, err := bot.makeImageOrVideoElem(d, true, isGroup) if err != nil { return nil, err } @@ -876,12 +900,22 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf return nil, nil } -func XmlEscape(c string) string { +//XMLEscape 将字符串c转义为XML字符串 +func XMLEscape(c string) string { buf := new(bytes.Buffer) _ = xml2.EscapeText(buf, []byte(c)) return buf.String() } +/*CQCodeEscapeText 将字符串raw中部分字符转义 + +& -> & + +[ -> [ + +] -> ] + +*/ func CQCodeEscapeText(raw string) string { ret := raw ret = strings.ReplaceAll(ret, "&", "&") @@ -890,12 +924,26 @@ func CQCodeEscapeText(raw string) string { return ret } +/*CQCodeEscapeValue 将字符串value中部分字符转义 + +, -> , + +*/ func CQCodeEscapeValue(value string) string { ret := CQCodeEscapeText(value) ret = strings.ReplaceAll(ret, ",", ",") return ret } +/*CQCodeUnescapeText 将字符串content中部分字符反转义 + +& -> & + +[ -> [ + +] -> ] + +*/ func CQCodeUnescapeText(content string) string { ret := content ret = strings.ReplaceAll(ret, "[", "[") @@ -904,13 +952,18 @@ func CQCodeUnescapeText(content string) string { return ret } +/*CQCodeUnescapeValue 将字符串content中部分字符反转义 + +, -> , + +*/ func CQCodeUnescapeValue(content string) string { ret := strings.ReplaceAll(content, ",", ",") ret = CQCodeUnescapeText(ret) return ret } -// 图片 elem 生成器,单独拎出来,用于公用 +//makeImageOrVideoElem 图片 elem 生成器,单独拎出来,用于公用 func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video, group bool) (message.IMessageElement, error) { f := d["file"] if strings.HasPrefix(f, "http") || strings.HasPrefix(f, "https") { @@ -986,9 +1039,8 @@ func (bot *CQBot) makeImageOrVideoElem(d map[string]string, video, group bool) ( Name: r.ReadString(), Uuid: r.ReadAvailable(), }}, nil - } else { - return &LocalVideoElement{File: rawPath}, nil } + return &LocalVideoElement{File: rawPath}, nil } if strings.HasPrefix(f, "base64") { b, err := base64.StdEncoding.DecodeString(strings.ReplaceAll(f, "base64://", "")) diff --git a/coolq/doc.go b/coolq/doc.go new file mode 100644 index 0000000..66c9407 --- /dev/null +++ b/coolq/doc.go @@ -0,0 +1,2 @@ +//Package coolq 包含CQBot实例,CQ码处理,消息发送,消息处理等的相关函数与结构体 +package coolq diff --git a/coolq/event.go b/coolq/event.go index a2dfcd1..56a3d74 100644 --- a/coolq/event.go +++ b/coolq/event.go @@ -23,11 +23,11 @@ func SetMessageFormat(f string) { } //ToFormattedMessage 将给定[]message.IMessageElement转换为通过coolq.SetMessageFormat所定义的消息上报格式 -func ToFormattedMessage(e []message.IMessageElement, id int64, raw ...bool) (r interface{}) { +func ToFormattedMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r interface{}) { if format == "string" { - r = ToStringMessage(e, id, raw...) + r = ToStringMessage(e, id, isRaw...) } else if format == "array" { - r = ToArrayMessage(e, id, raw...) + r = ToArrayMessage(e, id, isRaw...) } return } @@ -164,7 +164,7 @@ func (bot *CQBot) groupMutedEvent(c *client.QQClient, e *client.GroupMuteEvent) func (bot *CQBot) groupRecallEvent(c *client.QQClient, e *client.GroupMessageRecalledEvent) { g := c.FindGroup(e.GroupCode) - gid := ToGlobalId(e.GroupCode, e.MessageId) + gid := toGlobalID(e.GroupCode, e.MessageId) log.Infof("群 %v 内 %v 撤回了 %v 的消息: %v.", formatGroupName(g), formatMemberName(g.FindMember(e.OperatorUin)), formatMemberName(g.FindMember(e.AuthorUin)), gid) bot.dispatchEventMessage(MSG{ @@ -258,7 +258,7 @@ func (bot *CQBot) friendNotifyEvent(c *client.QQClient, e client.INotifyEvent) { func (bot *CQBot) friendRecallEvent(c *client.QQClient, e *client.FriendMessageRecalledEvent) { f := c.FindFriend(e.FriendUin) - gid := ToGlobalId(e.FriendUin, e.MessageId) + gid := toGlobalID(e.FriendUin, e.MessageId) if f != nil { log.Infof("好友 %v(%v) 撤回了消息: %v", f.Nickname, f.Uin, gid) } else { diff --git a/global/codec/codec.go b/global/codec/codec.go index 6b053db..e515644 100644 --- a/global/codec/codec.go +++ b/global/codec/codec.go @@ -1,6 +1,7 @@ // +build linux windows darwin // +build 386 amd64 arm arm64 +//Package codec Slik编码核心模块 package codec import ( diff --git a/global/doc.go b/global/doc.go new file mode 100644 index 0000000..210f1c3 --- /dev/null +++ b/global/doc.go @@ -0,0 +1,2 @@ +//Package global 包含文件下载,视频音频编码,本地文件缓存处理,消息过滤器,调用速率限制,gocq主配置等的相关函数与结构体 +package global diff --git a/server/apiAdmin.go b/server/apiAdmin.go index deab769..50d8fcf 100644 --- a/server/apiAdmin.go +++ b/server/apiAdmin.go @@ -30,12 +30,16 @@ import ( var json = jsoniter.ConfigCompatibleWithStandardLibrary +//WebInput 网页输入channel var WebInput = make(chan string, 1) //长度1,用于阻塞 +//Console 控制台channel var Console = make(chan os.Signal, 1) +//Restart 重启信号监听channel var Restart = make(chan struct{}, 1) +//JSONConfig go-cqhttp配置 var JSONConfig *global.JSONConfig type webServer struct { @@ -46,23 +50,25 @@ type webServer struct { Console *bufio.Reader } +//WebServer Admin子站的Server var WebServer = &webServer{} -// admin 子站的 路由映射 -var HttpuriAdmin = map[string]func(s *webServer, c *gin.Context){ - "do_restart": AdminDoRestart, //热重启 - "do_process_restart": AdminProcessRestart, //进程重启 - "get_web_write": AdminWebWrite, //获取是否验证码输入 - "do_web_write": AdminDoWebWrite, //web上进行输入操作 - "do_restart_docker": AdminDoRestartDocker, //直接停止(依赖supervisord/docker)重新拉起 - "do_config_base": AdminDoConfigBase, //修改config.json中的基础部分 - "do_config_http": AdminDoConfigHttp, //修改config.json的http部分 - "do_config_ws": AdminDoConfigWs, //修改config.json的正向ws部分 - "do_config_reverse": AdminDoConfigReverse, //修改config.json 中的反向ws部分 - "do_config_json": AdminDoConfigJson, //直接修改 config.json配置 - "get_config_json": AdminGetConfigJson, //拉取 当前的config.json配置 +//APIAdminRoutingTable Admin子站的路由映射 +var APIAdminRoutingTable = map[string]func(s *webServer, c *gin.Context){ + "do_restart": AdminDoRestart, //热重启 + "do_process_restart": AdminProcessRestart, //进程重启 + "get_web_write": AdminWebWrite, //获取是否验证码输入 + "do_web_write": AdminDoWebWrite, //web上进行输入操作 + "do_restart_docker": AdminDoRestartDocker, //直接停止(依赖supervisord/docker)重新拉起 + "do_config_base": AdminDoConfigBase, //修改config.json中的基础部分 + "do_config_http": AdminDoConfigHTTP, //修改config.json的http部分 + "do_config_ws": AdminDoConfigWS, //修改config.json的正向ws部分 + "do_config_reverse": AdminDoConfigReverseWS, //修改config.json 中的反向ws部分 + "do_config_json": AdminDoConfigJSON, //直接修改 config.json配置 + "get_config_json": AdminGetConfigJSON, //拉取 当前的config.json配置 } +//Failed 构建失败返回MSG func Failed(code int, msg string) coolq.MSG { return coolq.MSG{"data": nil, "retcode": code, "status": "failed", "msg": msg} } @@ -266,7 +272,7 @@ func (s *webServer) Dologin() { global.BootFilter() global.InitCodec() coolq.IgnoreInvalidCQCode = conf.IgnoreInvalidCQCode - coolq.SplitUrl = conf.FixURL + coolq.SplitURL = conf.FixURL coolq.ForceFragmented = conf.ForceFragmented log.Info("资源初始化完成, 开始处理信息.") log.Info("アトリは、高性能ですから!") @@ -321,14 +327,14 @@ func (s *webServer) Dologin() { func (s *webServer) admin(c *gin.Context) { action := c.Param("action") log.Debugf("WebServer接收到cgi调用: %v", action) - if f, ok := HttpuriAdmin[action]; ok { + if f, ok := APIAdminRoutingTable[action]; ok { f(s, c) } else { c.JSON(200, coolq.Failed(404)) } } -// 获取当前配置文件信息 +//GetConf 获取当前配置文件信息 func GetConf() *global.JSONConfig { if JSONConfig != nil { return JSONConfig @@ -337,7 +343,7 @@ func GetConf() *global.JSONConfig { return conf } -// admin 控制器 登录验证 +//AuthMiddleWare Admin控制器登录验证 func AuthMiddleWare() gin.HandlerFunc { return func(c *gin.Context) { conf := GetConf() @@ -431,7 +437,7 @@ func (s *webServer) DoReLogin() { // TODO: 协议层的 ReLogin s.Dologin() //关闭之前的 server if OldConf.HTTPConfig != nil && OldConf.HTTPConfig.Enabled { - HttpServer.ShutDown() + cqHTTPServer.ShutDown() } //if OldConf.WSConfig != nil && OldConf.WSConfig.Enabled { // server.WsShutdown() @@ -444,9 +450,9 @@ func (s *webServer) DoReLogin() { // TODO: 协议层的 ReLogin func (s *webServer) UpServer() { conf := GetConf() if conf.HTTPConfig != nil && conf.HTTPConfig.Enabled { - go HttpServer.Run(fmt.Sprintf("%s:%d", conf.HTTPConfig.Host, conf.HTTPConfig.Port), conf.AccessToken, s.bot) + go cqHTTPServer.Run(fmt.Sprintf("%s:%d", conf.HTTPConfig.Host, conf.HTTPConfig.Port), conf.AccessToken, s.bot) for k, v := range conf.HTTPConfig.PostUrls { - NewHttpClient().Run(k, v, conf.HTTPConfig.Timeout, s.bot) + newHTTPClient().Run(k, v, conf.HTTPConfig.Timeout, s.bot) } } if conf.WSConfig != nil && conf.WSConfig.Enabled { @@ -461,9 +467,9 @@ func (s *webServer) UpServer() { func (s *webServer) ReloadServer() { conf := GetConf() if conf.HTTPConfig != nil && conf.HTTPConfig.Enabled { - go HttpServer.Run(fmt.Sprintf("%s:%d", conf.HTTPConfig.Host, conf.HTTPConfig.Port), conf.AccessToken, s.bot) + go cqHTTPServer.Run(fmt.Sprintf("%s:%d", conf.HTTPConfig.Host, conf.HTTPConfig.Port), conf.AccessToken, s.bot) for k, v := range conf.HTTPConfig.PostUrls { - NewHttpClient().Run(k, v, conf.HTTPConfig.Timeout, s.bot) + newHTTPClient().Run(k, v, conf.HTTPConfig.Timeout, s.bot) } } for _, rc := range conf.ReverseServers { @@ -471,7 +477,7 @@ func (s *webServer) ReloadServer() { } } -// 热重启 +//AdminDoRestart 热重启 func AdminDoRestart(s *webServer, c *gin.Context) { s.bot.Release() s.bot = nil @@ -480,19 +486,19 @@ func AdminDoRestart(s *webServer, c *gin.Context) { c.JSON(200, coolq.OK(coolq.MSG{})) } -// 进程重启 +//AdminProcessRestart 进程重启 func AdminProcessRestart(s *webServer, c *gin.Context) { Restart <- struct{}{} c.JSON(200, coolq.OK(coolq.MSG{})) } -// 冷重启 +//AdminDoRestartDocker 冷重启 func AdminDoRestartDocker(s *webServer, c *gin.Context) { Console <- os.Kill c.JSON(200, coolq.OK(coolq.MSG{})) } -// web输入 html 页面 +//AdminWebWrite web输入html页面 func AdminWebWrite(s *webServer, c *gin.Context) { pic := global.ReadAllText("captcha.jpg") var picbase64 string @@ -509,14 +515,14 @@ func AdminWebWrite(s *webServer, c *gin.Context) { })) } -// web输入 处理 +//AdminDoWebWrite web输入处理 func AdminDoWebWrite(s *webServer, c *gin.Context) { input := c.PostForm("input") WebInput <- input c.JSON(200, coolq.OK(coolq.MSG{})) } -// 普通配置修改 +//AdminDoConfigBase 普通配置修改 func AdminDoConfigBase(s *webServer, c *gin.Context) { conf := GetConf() conf.Uin, _ = strconv.ParseInt(c.PostForm("uin"), 10, 64) @@ -536,8 +542,8 @@ func AdminDoConfigBase(s *webServer, c *gin.Context) { } } -// http配置修改 -func AdminDoConfigHttp(s *webServer, c *gin.Context) { +//AdminDoConfigHTTP HTTP配置修改 +func AdminDoConfigHTTP(s *webServer, c *gin.Context) { conf := GetConf() p, _ := strconv.ParseUint(c.PostForm("port"), 10, 16) conf.HTTPConfig.Port = uint16(p) @@ -561,8 +567,8 @@ func AdminDoConfigHttp(s *webServer, c *gin.Context) { } } -// ws配置修改 -func AdminDoConfigWs(s *webServer, c *gin.Context) { +//AdminDoConfigWS ws配置修改 +func AdminDoConfigWS(s *webServer, c *gin.Context) { conf := GetConf() p, _ := strconv.ParseUint(c.PostForm("port"), 10, 16) conf.WSConfig.Port = uint16(p) @@ -581,8 +587,8 @@ func AdminDoConfigWs(s *webServer, c *gin.Context) { } } -// 反向ws配置修改 -func AdminDoConfigReverse(s *webServer, c *gin.Context) { +//AdminDoConfigReverseWS 反向ws配置修改 +func AdminDoConfigReverseWS(s *webServer, c *gin.Context) { conf := GetConf() conf.ReverseServers[0].ReverseAPIURL = c.PostForm("reverse_api_url") conf.ReverseServers[0].ReverseURL = c.PostForm("reverse_url") @@ -603,11 +609,11 @@ func AdminDoConfigReverse(s *webServer, c *gin.Context) { } } -// config.json配置修改 -func AdminDoConfigJson(s *webServer, c *gin.Context) { +//AdminDoConfigJSON config.hjson配置修改 +func AdminDoConfigJSON(s *webServer, c *gin.Context) { conf := GetConf() - Json := c.PostForm("json") - err := json.Unmarshal([]byte(Json), &conf) + JSON := c.PostForm("json") + err := json.Unmarshal([]byte(JSON), &conf) if err != nil { log.Warnf("尝试加载配置文件 %v 时出现错误: %v", "config.hjson", err) c.JSON(200, Failed(502, "保存 config.hjson 时出现错误:"+fmt.Sprintf("%v", err))) @@ -622,8 +628,8 @@ func AdminDoConfigJson(s *webServer, c *gin.Context) { } } -// 拉取config.json配置 -func AdminGetConfigJson(s *webServer, c *gin.Context) { +//AdminGetConfigJSON 拉取config.hjson配置 +func AdminGetConfigJSON(s *webServer, c *gin.Context) { conf := GetConf() c.JSON(200, coolq.OK(coolq.MSG{"config": conf})) diff --git a/server/doc.go b/server/doc.go new file mode 100644 index 0000000..75e6fab --- /dev/null +++ b/server/doc.go @@ -0,0 +1,2 @@ +//Package server 包含Admin子站,HTTP,WebSocket,反向WebSocket请求处理的相关函数与结构体 +package server diff --git a/server/http.go b/server/http.go index 4eb1d6e..fad621f 100644 --- a/server/http.go +++ b/server/http.go @@ -24,7 +24,7 @@ import ( type httpServer struct { engine *gin.Engine bot *coolq.CQBot - Http *http.Server + HTTP *http.Server } type httpClient struct { @@ -34,7 +34,9 @@ type httpClient struct { timeout int32 } -var HttpServer = &httpServer{} +var cqHTTPServer = &httpServer{} + +//Debug 是否启用Debug模式 var Debug = false func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) { @@ -84,11 +86,11 @@ func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) { go func() { log.Infof("CQ HTTP 服务器已启动: %v", addr) - s.Http = &http.Server{ + s.HTTP = &http.Server{ Addr: addr, Handler: s.engine, } - if err := s.Http.ListenAndServe(); err != nil && err != http.ErrServerClosed { + if err := s.HTTP.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Error(err) log.Infof("HTTP 服务启动失败, 请检查端口是否被占用.") log.Warnf("将在五秒后退出.") @@ -98,7 +100,7 @@ func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) { }() } -func NewHttpClient() *httpClient { +func newHTTPClient() *httpClient { return &httpClient{} } @@ -123,7 +125,7 @@ func (c *httpClient) onBotPushEvent(m coolq.MSG) { } if c.secret != "" { mac := hmac.New(sha1.New, []byte(c.secret)) - _, err := mac.Write([]byte(m.ToJson())) + _, err := mac.Write([]byte(m.ToJSON())) if err != nil { log.Error(err) return nil @@ -141,12 +143,12 @@ func (c *httpClient) onBotPushEvent(m coolq.MSG) { return nil }).Do() if err != nil { - log.Warnf("上报Event数据 %v 到 %v 失败: %v", m.ToJson(), c.addr, err) + log.Warnf("上报Event数据 %v 到 %v 失败: %v", m.ToJSON(), c.addr, err) return } - log.Debugf("上报Event数据 %v 到 %v", m.ToJson(), c.addr) + log.Debugf("上报Event数据 %v 到 %v", m.ToJSON(), c.addr) if gjson.Valid(res) { - c.bot.CQHandleQuickOperation(gjson.Parse(m.ToJson()), gjson.Parse(res)) + c.bot.CQHandleQuickOperation(gjson.Parse(m.ToJSON()), gjson.Parse(res)) } } @@ -154,7 +156,7 @@ func (s *httpServer) HandleActions(c *gin.Context) { global.RateLimit(context.Background()) action := strings.ReplaceAll(c.Param("action"), "_async", "") log.Debugf("HTTPServer接收到API调用: %v", action) - if f, ok := httpApi[action]; ok { + if f, ok := httpAPI[action]; ok { f(s, c) } else { c.JSON(200, coolq.Failed(404)) @@ -202,13 +204,13 @@ func GetGroupRootFiles(s *httpServer, c *gin.Context) { c.JSON(200, s.bot.CQGetGroupRootFiles(gid)) } -func GetGroupFilesByFolderId(s *httpServer, c *gin.Context) { +func GetGroupFilesByFolderID(s *httpServer, c *gin.Context) { gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64) - folderId := getParam(c, "folder_id") - c.JSON(200, s.bot.CQGetGroupFilesByFolderID(gid, folderId)) + folderID := getParam(c, "folder_id") + c.JSON(200, s.bot.CQGetGroupFilesByFolderID(gid, folderID)) } -func GetGroupFileUrl(s *httpServer, c *gin.Context) { +func GetGroupFileURL(s *httpServer, c *gin.Context) { gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64) fid := getParam(c, "file_id") busid, _ := strconv.ParseInt(getParam(c, "busid"), 10, 32) @@ -356,11 +358,11 @@ func SetRestart(s *httpServer, c *gin.Context) { } func GetForwardMessage(s *httpServer, c *gin.Context) { - resId := getParam(c, "message_id") - if resId == "" { - resId = getParam(c, "id") + resID := getParam(c, "message_id") + if resID == "" { + resID = getParam(c, "id") } - c.JSON(200, s.bot.CQGetForwardMessage(resId)) + c.JSON(200, s.bot.CQGetForwardMessage(resID)) } func GetGroupSystemMessage(s *httpServer, c *gin.Context) { @@ -534,7 +536,7 @@ func getParamWithType(c *gin.Context, k string) (string, gjson.Type) { return "", gjson.Null } -var httpApi = map[string]func(s *httpServer, c *gin.Context){ +var httpAPI = map[string]func(s *httpServer, c *gin.Context){ "get_login_info": GetLoginInfo, "get_friend_list": GetFriendList, "get_group_list": GetGroupList, @@ -543,8 +545,8 @@ var httpApi = map[string]func(s *httpServer, c *gin.Context){ "get_group_member_info": GetGroupMemberInfo, "get_group_file_system_info": GetGroupFileSystemInfo, "get_group_root_files": GetGroupRootFiles, - "get_group_files_by_folder": GetGroupFilesByFolderId, - "get_group_file_url": GetGroupFileUrl, + "get_group_files_by_folder": GetGroupFilesByFolderID, + "get_group_file_url": GetGroupFileURL, "send_msg": SendMessage, "send_group_msg": SendGroupMessage, "send_group_forward_msg": SendGroupForwardMessage, @@ -589,7 +591,7 @@ var httpApi = map[string]func(s *httpServer, c *gin.Context){ func (s *httpServer) ShutDown() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - if err := s.Http.Shutdown(ctx); err != nil { + if err := s.HTTP.Shutdown(ctx); err != nil { log.Fatal("http Server Shutdown:", err) } <-ctx.Done() diff --git a/server/websocket.go b/server/websocket.go index ccf0c43..06f8a6b 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -25,7 +25,7 @@ type webSocketServer struct { handshake string } -//WebSocketClient Websocket客户端实例 +//WebSocketClient WebSocket客户端实例 type WebSocketClient struct { conf *global.GoCQReverseWebSocketConfig token string @@ -58,7 +58,7 @@ func (s *webSocketServer) Run(addr, authToken string, b *coolq.CQBot) { http.HandleFunc("/api", s.api) http.HandleFunc("/", s.any) go func() { - log.Infof("CQ Websocket 服务器已启动: %v", addr) + log.Infof("CQ WebSocket 服务器已启动: %v", addr) log.Fatal(http.ListenAndServe(addr, nil)) }() } @@ -87,7 +87,7 @@ func (c *WebSocketClient) Run() { } func (c *WebSocketClient) connectAPI() { - log.Infof("开始尝试连接到反向Websocket API服务器: %v", c.conf.ReverseAPIURL) + log.Infof("开始尝试连接到反向WebSocket API服务器: %v", c.conf.ReverseAPIURL) header := http.Header{ "X-Client-Role": []string{"API"}, "X-Self-ID": []string{strconv.FormatInt(c.bot.Client.Uin, 10)}, @@ -98,20 +98,20 @@ func (c *WebSocketClient) connectAPI() { } conn, _, err := websocket.DefaultDialer.Dial(c.conf.ReverseAPIURL, header) if err != nil { - log.Warnf("连接到反向Websocket API服务器 %v 时出现错误: %v", c.conf.ReverseAPIURL, err) + log.Warnf("连接到反向WebSocket API服务器 %v 时出现错误: %v", c.conf.ReverseAPIURL, err) if c.conf.ReverseReconnectInterval != 0 { time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval)) c.connectAPI() } return } - log.Infof("已连接到反向Websocket API服务器 %v", c.conf.ReverseAPIURL) + log.Infof("已连接到反向WebSocket API服务器 %v", c.conf.ReverseAPIURL) wrappedConn := &webSocketConn{Conn: conn} go c.listenAPI(wrappedConn, false) } func (c *WebSocketClient) connectEvent() { - log.Infof("开始尝试连接到反向Websocket Event服务器: %v", c.conf.ReverseEventURL) + log.Infof("开始尝试连接到反向WebSocket Event服务器: %v", c.conf.ReverseEventURL) header := http.Header{ "X-Client-Role": []string{"Event"}, "X-Self-ID": []string{strconv.FormatInt(c.bot.Client.Uin, 10)}, @@ -122,7 +122,7 @@ func (c *WebSocketClient) connectEvent() { } conn, _, err := websocket.DefaultDialer.Dial(c.conf.ReverseEventURL, header) if err != nil { - log.Warnf("连接到反向Websocket Event服务器 %v 时出现错误: %v", c.conf.ReverseEventURL, err) + log.Warnf("连接到反向WebSocket Event服务器 %v 时出现错误: %v", c.conf.ReverseEventURL, err) if c.conf.ReverseReconnectInterval != 0 { time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval)) c.connectEvent() @@ -134,15 +134,15 @@ func (c *WebSocketClient) connectEvent() { c.bot.Client.Uin, time.Now().Unix()) err = conn.WriteMessage(websocket.TextMessage, []byte(handshake)) if err != nil { - log.Warnf("反向Websocket 握手时出现错误: %v", err) + log.Warnf("反向WebSocket 握手时出现错误: %v", err) } - log.Infof("已连接到反向Websocket Event服务器 %v", c.conf.ReverseEventURL) + log.Infof("已连接到反向WebSocket Event服务器 %v", c.conf.ReverseEventURL) c.eventConn = &webSocketConn{Conn: conn} } func (c *WebSocketClient) connectUniversal() { - log.Infof("开始尝试连接到反向Websocket Universal服务器: %v", c.conf.ReverseURL) + log.Infof("开始尝试连接到反向WebSocket Universal服务器: %v", c.conf.ReverseURL) header := http.Header{ "X-Client-Role": []string{"Universal"}, "X-Self-ID": []string{strconv.FormatInt(c.bot.Client.Uin, 10)}, @@ -153,7 +153,7 @@ func (c *WebSocketClient) connectUniversal() { } conn, _, err := websocket.DefaultDialer.Dial(c.conf.ReverseURL, header) if err != nil { - log.Warnf("连接到反向Websocket Universal服务器 %v 时出现错误: %v", c.conf.ReverseURL, err) + log.Warnf("连接到反向WebSocket Universal服务器 %v 时出现错误: %v", c.conf.ReverseURL, err) if c.conf.ReverseReconnectInterval != 0 { time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval)) c.connectUniversal() @@ -165,7 +165,7 @@ func (c *WebSocketClient) connectUniversal() { c.bot.Client.Uin, time.Now().Unix()) err = conn.WriteMessage(websocket.TextMessage, []byte(handshake)) if err != nil { - log.Warnf("反向Websocket 握手时出现错误: %v", err) + log.Warnf("反向WebSocket 握手时出现错误: %v", err) } wrappedConn := &webSocketConn{Conn: conn} @@ -195,7 +195,7 @@ func (c *WebSocketClient) listenAPI(conn *webSocketConn, u bool) { func (c *WebSocketClient) onBotPushEvent(m coolq.MSG) { if c.eventConn != nil { - log.Debugf("向WS服务器 %v 推送Event: %v", c.eventConn.RemoteAddr().String(), m.ToJson()) + log.Debugf("向WS服务器 %v 推送Event: %v", c.eventConn.RemoteAddr().String(), m.ToJSON()) conn := c.eventConn conn.Lock() defer conn.Unlock() @@ -210,7 +210,7 @@ func (c *WebSocketClient) onBotPushEvent(m coolq.MSG) { } } if c.universalConn != nil { - log.Debugf("向WS服务器 %v 推送Event: %v", c.universalConn.RemoteAddr().String(), m.ToJson()) + log.Debugf("向WS服务器 %v 推送Event: %v", c.universalConn.RemoteAddr().String(), m.ToJSON()) conn := c.universalConn conn.Lock() defer conn.Unlock() @@ -230,7 +230,7 @@ func (s *webSocketServer) event(w http.ResponseWriter, r *http.Request) { if s.token != "" { if auth := r.URL.Query().Get("access_token"); auth != s.token { if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) != 2 || auth[1] != s.token { - log.Warnf("已拒绝 %v 的 Websocket 请求: Token鉴权失败", r.RemoteAddr) + log.Warnf("已拒绝 %v 的 WebSocket 请求: Token鉴权失败", r.RemoteAddr) w.WriteHeader(401) return } @@ -238,17 +238,17 @@ func (s *webSocketServer) event(w http.ResponseWriter, r *http.Request) { } c, err := upgrader.Upgrade(w, r, nil) if err != nil { - log.Warnf("处理 Websocket 请求时出现错误: %v", err) + log.Warnf("处理 WebSocket 请求时出现错误: %v", err) return } err = c.WriteMessage(websocket.TextMessage, []byte(s.handshake)) if err != nil { - log.Warnf("Websocket 握手时出现错误: %v", err) + log.Warnf("WebSocket 握手时出现错误: %v", err) c.Close() return } - log.Infof("接受 Websocket 连接: %v (/event)", r.RemoteAddr) + log.Infof("接受 WebSocket 连接: %v (/event)", r.RemoteAddr) conn := &webSocketConn{Conn: c} @@ -261,7 +261,7 @@ func (s *webSocketServer) api(w http.ResponseWriter, r *http.Request) { if s.token != "" { if auth := r.URL.Query().Get("access_token"); auth != s.token { if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) != 2 || auth[1] != s.token { - log.Warnf("已拒绝 %v 的 Websocket 请求: Token鉴权失败", r.RemoteAddr) + log.Warnf("已拒绝 %v 的 WebSocket 请求: Token鉴权失败", r.RemoteAddr) w.WriteHeader(401) return } @@ -269,10 +269,10 @@ func (s *webSocketServer) api(w http.ResponseWriter, r *http.Request) { } c, err := upgrader.Upgrade(w, r, nil) if err != nil { - log.Warnf("处理 Websocket 请求时出现错误: %v", err) + log.Warnf("处理 WebSocket 请求时出现错误: %v", err) return } - log.Infof("接受 Websocket 连接: %v (/api)", r.RemoteAddr) + log.Infof("接受 WebSocket 连接: %v (/api)", r.RemoteAddr) conn := &webSocketConn{Conn: c} go s.listenAPI(conn) } @@ -281,7 +281,7 @@ func (s *webSocketServer) any(w http.ResponseWriter, r *http.Request) { if s.token != "" { if auth := r.URL.Query().Get("access_token"); auth != s.token { if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) != 2 || auth[1] != s.token { - log.Warnf("已拒绝 %v 的 Websocket 请求: Token鉴权失败", r.RemoteAddr) + log.Warnf("已拒绝 %v 的 WebSocket 请求: Token鉴权失败", r.RemoteAddr) w.WriteHeader(401) return } @@ -289,16 +289,16 @@ func (s *webSocketServer) any(w http.ResponseWriter, r *http.Request) { } c, err := upgrader.Upgrade(w, r, nil) if err != nil { - log.Warnf("处理 Websocket 请求时出现错误: %v", err) + log.Warnf("处理 WebSocket 请求时出现错误: %v", err) return } err = c.WriteMessage(websocket.TextMessage, []byte(s.handshake)) if err != nil { - log.Warnf("Websocket 握手时出现错误: %v", err) + log.Warnf("WebSocket 握手时出现错误: %v", err) c.Close() return } - log.Infof("接受 Websocket 连接: %v (/)", r.RemoteAddr) + log.Infof("接受 WebSocket 连接: %v (/)", r.RemoteAddr) conn := &webSocketConn{Conn: c} s.eventConn = append(s.eventConn, conn) s.listenAPI(conn) @@ -353,9 +353,9 @@ func (s *webSocketServer) onBotPushEvent(m coolq.MSG) { defer s.eventConnMutex.Unlock() for i, l := 0, len(s.eventConn); i < l; i++ { conn := s.eventConn[i] - log.Debugf("向WS客户端 %v 推送Event: %v", conn.RemoteAddr().String(), m.ToJson()) + log.Debugf("向WS客户端 %v 推送Event: %v", conn.RemoteAddr().String(), m.ToJSON()) conn.Lock() - if err := conn.WriteMessage(websocket.TextMessage, []byte(m.ToJson())); err != nil { + if err := conn.WriteMessage(websocket.TextMessage, []byte(m.ToJSON())); err != nil { _ = conn.Close() next := i + 1 if next >= l {