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

fix golint

This commit is contained in:
Ink-33 2021-01-25 01:04:39 +08:00
parent a74c623cc1
commit 6f5e582213
No known key found for this signature in database
GPG Key ID: 5D8B1D036EFB0D2E
10 changed files with 284 additions and 201 deletions

View File

@ -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)
}

View File

@ -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(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="[分享] %s" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2"><audio cover="%s" src="%s"/><title>%s</title><summary>%s</summary></item><source name="音乐" icon="https://i.gtimg.cn/open/app_icon/01/07/98/56/1101079856_100_m.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=1101079856" action="app" a_actionData="com.tencent.qqmusic" i_actionData="tencent1101079856://" appid="1101079856" /></msg>`,
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中部分字符转义
& -> &amp;
[ -> &#91;
] -> &#93;
*/
func CQCodeEscapeText(raw string) string {
ret := raw
ret = strings.ReplaceAll(ret, "&", "&amp;")
@ -890,12 +924,26 @@ func CQCodeEscapeText(raw string) string {
return ret
}
/*CQCodeEscapeValue 将字符串value中部分字符转义
, -> &#44;
*/
func CQCodeEscapeValue(value string) string {
ret := CQCodeEscapeText(value)
ret = strings.ReplaceAll(ret, ",", "&#44;")
return ret
}
/*CQCodeUnescapeText 将字符串content中部分字符反转义
&amp; -> &
&#91; -> [
&#93; -> ]
*/
func CQCodeUnescapeText(content string) string {
ret := content
ret = strings.ReplaceAll(ret, "&#91;", "[")
@ -904,13 +952,18 @@ func CQCodeUnescapeText(content string) string {
return ret
}
/*CQCodeUnescapeValue 将字符串content中部分字符反转义
, -> &#44;
*/
func CQCodeUnescapeValue(content string) string {
ret := strings.ReplaceAll(content, "&#44;", ",")
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://", ""))

2
coolq/doc.go Normal file
View File

@ -0,0 +1,2 @@
//Package coolq 包含CQBot实例,CQ码处理,消息发送,消息处理等的相关函数与结构体
package coolq

View File

@ -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 {

View File

@ -1,6 +1,7 @@
// +build linux windows darwin
// +build 386 amd64 arm arm64
//Package codec Slik编码核心模块
package codec
import (

2
global/doc.go Normal file
View File

@ -0,0 +1,2 @@
//Package global 包含文件下载,视频音频编码,本地文件缓存处理,消息过滤器,调用速率限制,gocq主配置等的相关函数与结构体
package global

View File

@ -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){
//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": AdminDoConfigReverse, //修改config.json 中的反向ws部分
"do_config_json": AdminDoConfigJson, //直接修改 config.json配置
"get_config_json": AdminGetConfigJson, //拉取 当前的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}))

2
server/doc.go Normal file
View File

@ -0,0 +1,2 @@
//Package server 包含Admin子站,HTTP,WebSocket,反向WebSocket请求处理的相关函数与结构体
package server

View File

@ -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()

View File

@ -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 {