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