mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-06-30 03:43:25 +00:00
Compare commits
42 Commits
v0.9.24-fi
...
v0.9.26
Author | SHA1 | Date | |
---|---|---|---|
9b41cd8ea2 | |||
e0ab2417c4 | |||
c7ab32fead | |||
8f5b8375a7 | |||
9049018d2f | |||
fffe64651a | |||
a9d53f038f | |||
cec81b7ad8 | |||
dddb3d2299 | |||
f6d37d460c | |||
aca6a3cf28 | |||
d390dd539b | |||
3269387163 | |||
cd09a68e0d | |||
d2d408a8e9 | |||
995737b0b8 | |||
72d62ad7c3 | |||
387d33a01b | |||
65811d4e22 | |||
01dd760b5c | |||
c31169b99b | |||
b5b6117487 | |||
4662f1e170 | |||
ea65e545ad | |||
d67621487d | |||
c4e54446c5 | |||
1d1925208b | |||
741a91cf70 | |||
fef9395890 | |||
50bfc08974 | |||
2005cbccb0 | |||
69cadad155 | |||
a4c6c6d7f3 | |||
6f251e3dec | |||
6101c4d8a9 | |||
9b77f09d2f | |||
e9db10c9b7 | |||
e87de2f6b3 | |||
a1a3e26b0b | |||
92c224be5b | |||
c691aa70ea | |||
ec45d04c81 |
@ -80,13 +80,14 @@
|
|||||||
| ------------------------------------------------------------ |
|
| ------------------------------------------------------------ |
|
||||||
| [私聊信息](https://cqhttp.cc/docs/4.15/#/Post?id=私聊消息) |
|
| [私聊信息](https://cqhttp.cc/docs/4.15/#/Post?id=私聊消息) |
|
||||||
| [群消息](https://cqhttp.cc/docs/4.15/#/Post?id=群消息) |
|
| [群消息](https://cqhttp.cc/docs/4.15/#/Post?id=群消息) |
|
||||||
| [群消息撤回(拓展Event)](docs/cqhttp.md#群消息撤回) |
|
| [群消息撤回(拓展Event)](docs/cqhttp.md#群消息撤回) |
|
||||||
| [好友消息撤回(拓展Event)](docs/cqhttp.md#好友消息撤回) |
|
| [好友消息撤回(拓展Event)](docs/cqhttp.md#好友消息撤回) |
|
||||||
|
| [群内提示事件(拓展Event)(龙王等事件)](docs/cqhttp.md#群内戳一戳) |
|
||||||
| [群管理员变动](https://cqhttp.cc/docs/4.15/#/Post?id=群管理员变动) |
|
| [群管理员变动](https://cqhttp.cc/docs/4.15/#/Post?id=群管理员变动) |
|
||||||
| [群成员减少](https://cqhttp.cc/docs/4.15/#/Post?id=群成员减少) |
|
| [群成员减少](https://cqhttp.cc/docs/4.15/#/Post?id=群成员减少) |
|
||||||
| [群成员增加](https://cqhttp.cc/docs/4.15/#/Post?id=群成员增加) |
|
| [群成员增加](https://cqhttp.cc/docs/4.15/#/Post?id=群成员增加) |
|
||||||
| [群禁言](https://cqhttp.cc/docs/4.15/#/Post?id=群禁言) |
|
| [群禁言](https://cqhttp.cc/docs/4.15/#/Post?id=群禁言) |
|
||||||
| [群文件上传](https://cqhttp.cc/docs/4.15/#/Post?id=群文件上传)|
|
| [群文件上传](https://cqhttp.cc/docs/4.15/#/Post?id=群文件上传) |
|
||||||
| [加好友请求](https://cqhttp.cc/docs/4.15/#/Post?id=加好友请求) |
|
| [加好友请求](https://cqhttp.cc/docs/4.15/#/Post?id=加好友请求) |
|
||||||
| [加群请求/邀请](https://cqhttp.cc/docs/4.15/#/Post?id=加群请求/邀请) |
|
| [加群请求/邀请](https://cqhttp.cc/docs/4.15/#/Post?id=加群请求/邀请) |
|
||||||
|
|
||||||
|
64
coolq/api.go
64
coolq/api.go
@ -125,6 +125,7 @@ func (bot *CQBot) CQSendGroupMessage(groupId int64, i interface{}, autoEscape bo
|
|||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100)
|
||||||
}
|
}
|
||||||
|
log.Infof("发送群 %v(%v) 的消息: %v (%v)", groupId, groupId, m.String(), mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
}
|
}
|
||||||
str = func() string {
|
str = func() string {
|
||||||
@ -151,6 +152,7 @@ func (bot *CQBot) CQSendGroupMessage(groupId int64, i interface{}, autoEscape bo
|
|||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100)
|
||||||
}
|
}
|
||||||
|
log.Infof("发送群 %v(%v) 的消息: %v (%v)", groupId, groupId, str, mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +249,7 @@ func (bot *CQBot) CQSendPrivateMessage(userId int64, i interface{}, autoEscape b
|
|||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100)
|
||||||
}
|
}
|
||||||
|
log.Infof("发送好友 %v(%v) 的消息: %v (%v)", userId, userId, m.String(), mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
}
|
}
|
||||||
str = func() string {
|
str = func() string {
|
||||||
@ -271,6 +274,7 @@ func (bot *CQBot) CQSendPrivateMessage(userId int64, i interface{}, autoEscape b
|
|||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100)
|
||||||
}
|
}
|
||||||
|
log.Infof("发送好友 %v(%v) 的消息: %v (%v)", userId, userId, str, mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,6 +501,27 @@ func (bot *CQBot) CQGetGroupHonorInfo(groupId int64, t string) MSG {
|
|||||||
return OK(msg)
|
return OK(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_stranger_info-%E8%8E%B7%E5%8F%96%E9%99%8C%E7%94%9F%E4%BA%BA%E4%BF%A1%E6%81%AF
|
||||||
|
func (bot *CQBot) CQGetStrangerInfo(userId int64) MSG {
|
||||||
|
info, err := bot.Client.GetSummaryInfo(userId)
|
||||||
|
if err != nil {
|
||||||
|
return Failed(100)
|
||||||
|
}
|
||||||
|
return OK(MSG{
|
||||||
|
"user_id": info.Uin,
|
||||||
|
"nickname": info.Nickname,
|
||||||
|
"sex": func() string {
|
||||||
|
if info.Sex == 1 {
|
||||||
|
return "female"
|
||||||
|
}
|
||||||
|
return "male"
|
||||||
|
}(),
|
||||||
|
"age": info.Age,
|
||||||
|
"level": info.Level,
|
||||||
|
"login_days": info.LoginDays,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=-handle_quick_operation-%E5%AF%B9%E4%BA%8B%E4%BB%B6%E6%89%A7%E8%A1%8C%E5%BF%AB%E9%80%9F%E6%93%8D%E4%BD%9C
|
// https://cqhttp.cc/docs/4.15/#/API?id=-handle_quick_operation-%E5%AF%B9%E4%BA%8B%E4%BB%B6%E6%89%A7%E8%A1%8C%E5%BF%AB%E9%80%9F%E6%93%8D%E4%BD%9C
|
||||||
// https://github.com/richardchien/coolq-http-api/blob/master/src/cqhttp/plugins/web/http.cpp#L376
|
// https://github.com/richardchien/coolq-http-api/blob/master/src/cqhttp/plugins/web/http.cpp#L376
|
||||||
func (bot *CQBot) CQHandleQuickOperation(context, operation gjson.Result) MSG {
|
func (bot *CQBot) CQHandleQuickOperation(context, operation gjson.Result) MSG {
|
||||||
@ -627,11 +652,38 @@ func (bot *CQBot) CQCanSendRecord() MSG {
|
|||||||
return OK(MSG{"yes": true})
|
return OK(MSG{"yes": true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bot *CQBot) CQOcrImage(imageId string) MSG {
|
||||||
|
img, err := bot.makeImageElem("image", map[string]string{"file": imageId}, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("load image error: %v", err)
|
||||||
|
return Failed(100)
|
||||||
|
}
|
||||||
|
rsp, err := bot.Client.ImageOcr(img)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("ocr image error: %v", err)
|
||||||
|
return Failed(100)
|
||||||
|
}
|
||||||
|
return OK(rsp)
|
||||||
|
}
|
||||||
|
|
||||||
func (bot *CQBot) CQReloadEventFilter() MSG {
|
func (bot *CQBot) CQReloadEventFilter() MSG {
|
||||||
global.BootFilter()
|
global.BootFilter()
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bot *CQBot) CQSetGroupPortrait(groupId int64, file, cache string) MSG {
|
||||||
|
if g := bot.Client.FindGroup(groupId); g != nil {
|
||||||
|
img, err := global.FindFile(file, cache, global.IMAGE_PATH)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("set group portrait error: %v", err)
|
||||||
|
return Failed(100)
|
||||||
|
}
|
||||||
|
g.UpdateGroupHeadPortrait(img)
|
||||||
|
return OK(nil)
|
||||||
|
}
|
||||||
|
return Failed(100)
|
||||||
|
}
|
||||||
|
|
||||||
func (bot *CQBot) CQGetStatus() MSG {
|
func (bot *CQBot) CQGetStatus() MSG {
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"app_initialized": true,
|
"app_initialized": true,
|
||||||
@ -655,6 +707,18 @@ func (bot *CQBot) CQGetVersionInfo() MSG {
|
|||||||
"runtime_version": runtime.Version(),
|
"runtime_version": runtime.Version(),
|
||||||
"runtime_os": runtime.GOOS,
|
"runtime_os": runtime.GOOS,
|
||||||
"version": Version,
|
"version": Version,
|
||||||
|
"protocol": func() int {
|
||||||
|
switch client.SystemDeviceInfo.Protocol {
|
||||||
|
case client.AndroidPad:
|
||||||
|
return 0
|
||||||
|
case client.AndroidPhone:
|
||||||
|
return 1
|
||||||
|
case client.AndroidWatch:
|
||||||
|
return 2
|
||||||
|
default:
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ func NewQQBot(cli *client.QQClient, conf *global.JsonConfig) *CQBot {
|
|||||||
bot.Client.OnTempMessage(bot.tempMessageEvent)
|
bot.Client.OnTempMessage(bot.tempMessageEvent)
|
||||||
bot.Client.OnGroupMuted(bot.groupMutedEvent)
|
bot.Client.OnGroupMuted(bot.groupMutedEvent)
|
||||||
bot.Client.OnGroupMessageRecalled(bot.groupRecallEvent)
|
bot.Client.OnGroupMessageRecalled(bot.groupRecallEvent)
|
||||||
|
bot.Client.OnGroupNotify(bot.groupNotifyEvent)
|
||||||
bot.Client.OnFriendMessageRecalled(bot.friendRecallEvent)
|
bot.Client.OnFriendMessageRecalled(bot.friendRecallEvent)
|
||||||
bot.Client.OnJoinGroup(bot.joinGroupEvent)
|
bot.Client.OnJoinGroup(bot.joinGroupEvent)
|
||||||
bot.Client.OnLeaveGroup(bot.leaveGroupEvent)
|
bot.Client.OnLeaveGroup(bot.leaveGroupEvent)
|
||||||
@ -138,6 +139,14 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int
|
|||||||
newElem = append(newElem, gv)
|
newElem = append(newElem, gv)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if i, ok := elem.(*PokeElement); ok {
|
||||||
|
if group := bot.Client.FindGroup(groupId); group != nil {
|
||||||
|
if mem := group.FindMember(i.Target); mem != nil {
|
||||||
|
mem.Poke()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
newElem = append(newElem, elem)
|
newElem = append(newElem, elem)
|
||||||
}
|
}
|
||||||
m.Elements = newElem
|
m.Elements = newElem
|
||||||
|
@ -26,6 +26,14 @@ var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`)
|
|||||||
|
|
||||||
var IgnoreInvalidCQCode = false
|
var IgnoreInvalidCQCode = false
|
||||||
|
|
||||||
|
type PokeElement struct {
|
||||||
|
Target int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *PokeElement) Type() message.ElementType {
|
||||||
|
return message.At
|
||||||
|
}
|
||||||
|
|
||||||
func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []MSG) {
|
func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []MSG) {
|
||||||
ur := false
|
ur := false
|
||||||
if len(raw) != 0 {
|
if len(raw) != 0 {
|
||||||
@ -71,6 +79,11 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M
|
|||||||
"data": map[string]string{"qq": fmt.Sprint(o.Target)},
|
"data": map[string]string{"qq": fmt.Sprint(o.Target)},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case *message.RedBagElement:
|
||||||
|
m = MSG{
|
||||||
|
"type": "redbag",
|
||||||
|
"data": map[string]string{"title": o.Title},
|
||||||
|
}
|
||||||
case *message.ForwardElement:
|
case *message.ForwardElement:
|
||||||
m = MSG{
|
m = MSG{
|
||||||
"type": "forward",
|
"type": "forward",
|
||||||
@ -129,6 +142,8 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M
|
|||||||
"data": map[string]string{"data": o.Content, "resid": fmt.Sprintf("%d", o.Id)},
|
"data": map[string]string{"data": o.Content, "resid": fmt.Sprintf("%d", o.Id)},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
r = append(r, m)
|
r = append(r, m)
|
||||||
}
|
}
|
||||||
@ -159,6 +174,8 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
r += fmt.Sprintf("[CQ:at,qq=%d]", o.Target)
|
r += fmt.Sprintf("[CQ:at,qq=%d]", o.Target)
|
||||||
|
case *message.RedBagElement:
|
||||||
|
r += fmt.Sprintf("[CQ:redbag,title=%s]", o.Title)
|
||||||
case *message.ForwardElement:
|
case *message.ForwardElement:
|
||||||
r += fmt.Sprintf("[CQ:forward,id=%s]", o.ResId)
|
r += fmt.Sprintf("[CQ:forward,id=%s]", o.ResId)
|
||||||
case *message.FaceElement:
|
case *message.FaceElement:
|
||||||
@ -310,46 +327,20 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (message.
|
|||||||
return message.NewText(d["text"]), nil
|
return message.NewText(d["text"]), nil
|
||||||
case "image":
|
case "image":
|
||||||
return bot.makeImageElem(t, d, group)
|
return bot.makeImageElem(t, d, group)
|
||||||
|
case "poke":
|
||||||
|
if !group {
|
||||||
|
return nil, errors.New("todo") // TODO: private poke
|
||||||
|
}
|
||||||
|
t, _ := strconv.ParseInt(d["qq"], 10, 64)
|
||||||
|
return &PokeElement{Target: t}, nil
|
||||||
case "record":
|
case "record":
|
||||||
if !group {
|
if !group {
|
||||||
return nil, errors.New("private voice unsupported now")
|
return nil, errors.New("private voice unsupported now")
|
||||||
}
|
}
|
||||||
f := d["file"]
|
f := d["file"]
|
||||||
var data []byte
|
data, err := global.FindFile(f, d["cache"], global.VOICE_PATH)
|
||||||
if strings.HasPrefix(f, "http") || strings.HasPrefix(f, "https") {
|
if err != nil {
|
||||||
b, err := global.GetBytes(f)
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
data = b
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(f, "base64") {
|
|
||||||
b, err := base64.StdEncoding.DecodeString(strings.ReplaceAll(f, "base64://", ""))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
data = b
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(f, "file") {
|
|
||||||
fu, err := url.Parse(f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(fu.Path, "/") && runtime.GOOS == `windows` {
|
|
||||||
fu.Path = fu.Path[1:]
|
|
||||||
}
|
|
||||||
b, err := ioutil.ReadFile(fu.Path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
data = b
|
|
||||||
}
|
|
||||||
if global.PathExists(path.Join(global.VOICE_PATH, f)) {
|
|
||||||
b, err := ioutil.ReadFile(path.Join(global.VOICE_PATH, f))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
data = b
|
|
||||||
}
|
}
|
||||||
if !global.IsAMRorSILK(data) {
|
if !global.IsAMRorSILK(data) {
|
||||||
return nil, errors.New("unsupported voice file format (please use AMR file for now)")
|
return nil, errors.New("unsupported voice file format (please use AMR file for now)")
|
||||||
|
@ -205,6 +205,65 @@ func (bot *CQBot) groupRecallEvent(c *client.QQClient, e *client.GroupMessageRec
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bot *CQBot) groupNotifyEvent(c *client.QQClient, e client.IGroupNotifyEvent) {
|
||||||
|
group := c.FindGroup(e.From())
|
||||||
|
switch notify := e.(type) {
|
||||||
|
case *client.GroupPokeNotifyEvent:
|
||||||
|
sender := group.FindMember(notify.Sender)
|
||||||
|
receiver := group.FindMember(notify.Receiver)
|
||||||
|
log.Infof("群 %v 内 %v 戳了戳 %v", formatGroupName(group), formatMemberName(sender), formatMemberName(receiver))
|
||||||
|
bot.dispatchEventMessage(MSG{
|
||||||
|
"post_type": "notice",
|
||||||
|
"group_id": group.Code,
|
||||||
|
"notice_type": "notify",
|
||||||
|
"sub_type": "poke",
|
||||||
|
"self_id": c.Uin,
|
||||||
|
"user_id": notify.Sender,
|
||||||
|
"sender_id": notify.Sender,
|
||||||
|
"target_id": notify.Receiver,
|
||||||
|
"time": time.Now().Unix(),
|
||||||
|
})
|
||||||
|
case *client.GroupRedBagLuckyKingNotifyEvent:
|
||||||
|
sender := group.FindMember(notify.Sender)
|
||||||
|
luckyKing := group.FindMember(notify.LuckyKing)
|
||||||
|
log.Infof("群 %v 内 %v 的红包被抢完, %v 是运气王", formatGroupName(group), formatMemberName(sender), formatMemberName(luckyKing))
|
||||||
|
bot.dispatchEventMessage(MSG{
|
||||||
|
"post_type": "notice",
|
||||||
|
"group_id": group.Code,
|
||||||
|
"notice_type": "notify",
|
||||||
|
"sub_type": "lucky_king",
|
||||||
|
"self_id": c.Uin,
|
||||||
|
"user_id": notify.Sender,
|
||||||
|
"sender_id": notify.Sender,
|
||||||
|
"target_id": notify.LuckyKing,
|
||||||
|
"time": time.Now().Unix(),
|
||||||
|
})
|
||||||
|
case *client.MemberHonorChangedNotifyEvent:
|
||||||
|
log.Info(notify.Content())
|
||||||
|
bot.dispatchEventMessage(MSG{
|
||||||
|
"post_type": "notice",
|
||||||
|
"group_id": group.Code,
|
||||||
|
"notice_type": "notify",
|
||||||
|
"sub_type": "honor",
|
||||||
|
"self_id": c.Uin,
|
||||||
|
"user_id": notify.Uin,
|
||||||
|
"time": time.Now().Unix(),
|
||||||
|
"honor_type": func() string {
|
||||||
|
switch notify.Honor {
|
||||||
|
case client.Talkative:
|
||||||
|
return "talkative"
|
||||||
|
case client.Performer:
|
||||||
|
return "performer"
|
||||||
|
case client.Emotion:
|
||||||
|
return "emotion"
|
||||||
|
default:
|
||||||
|
return "ERROR"
|
||||||
|
}
|
||||||
|
}(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -77,7 +77,7 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为:
|
|||||||
| post_message_format | string | 上报信息类型 |
|
| post_message_format | string | 上报信息类型 |
|
||||||
| ignore_invalid_cqcode| bool | 是否忽略错误的CQ码 |
|
| ignore_invalid_cqcode| bool | 是否忽略错误的CQ码 |
|
||||||
| force_fragmented | bool | 是否强制分片发送群长消息 |
|
| force_fragmented | bool | 是否强制分片发送群长消息 |
|
||||||
| heartbeat_interval | int64 | 心跳间隔时间,单位秒,若0则关闭心跳 |
|
| heartbeat_interval | int64 | 心跳间隔时间,单位秒。小于0则关闭心跳,等于0使用默认值(5秒) |
|
||||||
| http_config | object | HTTP API配置 |
|
| http_config | object | HTTP API配置 |
|
||||||
| ws_config | object | Websocket API 配置 |
|
| ws_config | object | Websocket API 配置 |
|
||||||
| ws_reverse_servers | object[] | 反向 Websocket API 配置 |
|
| ws_reverse_servers | object[] | 反向 Websocket API 配置 |
|
||||||
@ -90,3 +90,28 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为:
|
|||||||
> 注2: 分片发送为原酷Q发送长消息的老方案, 发送速度更优/兼容性更好,但在有发言频率限制的群里,可能无法发送。关闭后将优先使用新方案, 能发送更长的消息, 但发送速度更慢,在部分老客户端将无法解析.
|
> 注2: 分片发送为原酷Q发送长消息的老方案, 发送速度更优/兼容性更好,但在有发言频率限制的群里,可能无法发送。关闭后将优先使用新方案, 能发送更长的消息, 但发送速度更慢,在部分老客户端将无法解析.
|
||||||
|
|
||||||
> 注3:关闭心跳服务可能引起断线,请谨慎关闭
|
> 注3:关闭心跳服务可能引起断线,请谨慎关闭
|
||||||
|
|
||||||
|
## 设备信息
|
||||||
|
|
||||||
|
默认生成的设备信息如下所示:
|
||||||
|
|
||||||
|
``` json
|
||||||
|
{
|
||||||
|
"protocol": 0,
|
||||||
|
"display": "xxx",
|
||||||
|
"finger_print": "xxx",
|
||||||
|
"boot_id": "xxx",
|
||||||
|
"proc_version": "xxx",
|
||||||
|
"imei": "xxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
在大部分情况下 我们只需要关心 `protocol` 字段:
|
||||||
|
|
||||||
|
| 值 | 类型 | 限制 |
|
||||||
|
| ---- | ------------- | ----------------------------------------------------- |
|
||||||
|
| 0 | Android Pad | 无法接收 `group_notify` 事件、无法接收口令红包 |
|
||||||
|
| 1 | Android Phone | 无 |
|
||||||
|
| 2 | Android Watch | 除了 `Android Pad` 有的限制外还包括: 无法接收撤回消息 |
|
||||||
|
|
||||||
|
> 注意, 根据协议的不同, 各类消息有所限制
|
@ -18,6 +18,36 @@ Type : `reply`
|
|||||||
|
|
||||||
示例: `[CQ:reply,id=123456]`
|
示例: `[CQ:reply,id=123456]`
|
||||||
|
|
||||||
|
### 红包
|
||||||
|
|
||||||
|
Type: `redbag`
|
||||||
|
|
||||||
|
范围: **接收**
|
||||||
|
|
||||||
|
参数:
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 说明 |
|
||||||
|
| ------ | ------ | ----------- |
|
||||||
|
| title | string | 祝福语/口令 |
|
||||||
|
|
||||||
|
示例: `[CQ:redbag,title=恭喜发财]`
|
||||||
|
|
||||||
|
### 戳一戳
|
||||||
|
|
||||||
|
> 注意:发送戳一戳消息无法撤回,返回的 `message id` 恒定为 `0`
|
||||||
|
|
||||||
|
Type: `poke`
|
||||||
|
|
||||||
|
范围: **发送(仅群聊)**
|
||||||
|
|
||||||
|
参数:
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 说明 |
|
||||||
|
| ------ | ------ | ----------- |
|
||||||
|
| qq | int64 | 需要戳的成员 |
|
||||||
|
|
||||||
|
示例: `[CQ:poke,qq=123456]`
|
||||||
|
|
||||||
### 合并转发
|
### 合并转发
|
||||||
|
|
||||||
Type: `forward`
|
Type: `forward`
|
||||||
@ -134,9 +164,9 @@ Type: `xml`
|
|||||||
|
|
||||||
示例: `[CQ:xml,data=xxxx]`
|
示例: `[CQ:xml,data=xxxx]`
|
||||||
|
|
||||||
####一些xml样例
|
#### 一些xml样例
|
||||||
|
|
||||||
####ps:重要:xml中的value部分,记得html实体化处理后,再打加入到cq码中
|
#### ps:重要:xml中的value部分,记得html实体化处理后,再打加入到cq码中
|
||||||
|
|
||||||
#### qq音乐
|
#### qq音乐
|
||||||
|
|
||||||
@ -362,3 +392,47 @@ Type: `cardimage`
|
|||||||
| `user_id` | int64 | | 好友id |
|
| `user_id` | int64 | | 好友id |
|
||||||
| `message_id` | int64 | | 被撤回的消息id |
|
| `message_id` | int64 | | 被撤回的消息id |
|
||||||
|
|
||||||
|
#### 群内戳一戳
|
||||||
|
|
||||||
|
> 注意:此事件无法在平板和手表协议上触发
|
||||||
|
|
||||||
|
**上报数据**
|
||||||
|
|
||||||
|
| 字段 | 类型 | 可能的值 | 说明 |
|
||||||
|
| ------------- | ------ | -------------- | -------------- |
|
||||||
|
| `post_type` | string | `notice` | 上报类型 |
|
||||||
|
| `notice_type` | string | `notify` | 消息类型 |
|
||||||
|
| `group_id` | int64 | | 群号 |
|
||||||
|
| `sub_type` | string | `poke` | 提示类型 |
|
||||||
|
| `user_id` | int64 | | 发送者id |
|
||||||
|
| `target_id` | int64 | | 被戳者id |
|
||||||
|
|
||||||
|
#### 群红包运气王提示
|
||||||
|
|
||||||
|
> 注意:此事件无法在平板和手表协议上触发
|
||||||
|
|
||||||
|
**上报数据**
|
||||||
|
|
||||||
|
| 字段 | 类型 | 可能的值 | 说明 |
|
||||||
|
| ------------- | ------ | -------------- | -------------- |
|
||||||
|
| `post_type` | string | `notice` | 上报类型 |
|
||||||
|
| `notice_type` | string | `notify` | 消息类型 |
|
||||||
|
| `group_id` | int64 | | 群号 |
|
||||||
|
| `sub_type` | string | `lucky_king` | 提示类型 |
|
||||||
|
| `user_id` | int64 | | 红包发送者id |
|
||||||
|
| `target_id` | int64 | | 运气王id |
|
||||||
|
|
||||||
|
#### 群成员荣誉变更提示
|
||||||
|
|
||||||
|
> 注意:此事件无法在平板和手表协议上触发
|
||||||
|
|
||||||
|
**上报数据**
|
||||||
|
|
||||||
|
| 字段 | 类型 | 可能的值 | 说明 |
|
||||||
|
| ------------- | ------ | -------------- | -------------- |
|
||||||
|
| `post_type` | string | `notice` | 上报类型 |
|
||||||
|
| `notice_type` | string | `notify` | 消息类型 |
|
||||||
|
| `group_id` | int64 | | 群号 |
|
||||||
|
| `sub_type` | string | `honor` | 提示类型 |
|
||||||
|
| `user_id` | int64 | | 成员id |
|
||||||
|
| `honor_type` | string | `talkative:龙王` `performer:群聊之火` `emotion:快乐源泉` | 荣誉类型 |
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# 开始
|
# 开始
|
||||||
|
|
||||||
欢迎来到 go-cqhttp 文档
|
欢迎来到 go-cqhttp 文档 目前还在咕
|
52
global/fs.go
52
global/fs.go
@ -2,11 +2,17 @@ package global
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"runtime"
|
||||||
log "github.com/sirupsen/logrus"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -45,3 +51,45 @@ func Check(err error) {
|
|||||||
func IsAMRorSILK(b []byte) bool {
|
func IsAMRorSILK(b []byte) bool {
|
||||||
return bytes.HasPrefix(b, HEADER_AMR) || bytes.HasPrefix(b, HEADER_SILK)
|
return bytes.HasPrefix(b, HEADER_AMR) || bytes.HasPrefix(b, HEADER_SILK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FindFile(f, cache, PATH string) (data []byte, err error) {
|
||||||
|
data, err = nil, errors.New("can't find the file: "+f)
|
||||||
|
if strings.HasPrefix(f, "http") || strings.HasPrefix(f, "https") {
|
||||||
|
if cache == "" {
|
||||||
|
cache = "1"
|
||||||
|
}
|
||||||
|
hash := md5.Sum([]byte(f))
|
||||||
|
cacheFile := path.Join(CACHE_PATH, hex.EncodeToString(hash[:])+".cache")
|
||||||
|
if PathExists(cacheFile) && cache == "1" {
|
||||||
|
return ioutil.ReadFile(cacheFile)
|
||||||
|
}
|
||||||
|
data, err = GetBytes(f)
|
||||||
|
_ = ioutil.WriteFile(cacheFile, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(f, "base64") {
|
||||||
|
data, err = base64.StdEncoding.DecodeString(strings.ReplaceAll(f, "base64://", ""))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(f, "file") {
|
||||||
|
fu, err := url.Parse(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(fu.Path, "/") && runtime.GOOS == `windows` {
|
||||||
|
fu.Path = fu.Path[1:]
|
||||||
|
}
|
||||||
|
data, err = ioutil.ReadFile(fu.Path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else if PathExists(path.Join(PATH, f)) {
|
||||||
|
data, err = ioutil.ReadFile(path.Join(PATH, f))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
4
go.mod
4
go.mod
@ -3,7 +3,7 @@ module github.com/Mrs4s/go-cqhttp
|
|||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200911100852-71bc19cd42eb
|
github.com/Mrs4s/MiraiGo v0.0.0-20200926101830-afb0ed6368ad
|
||||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
|
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
|
||||||
github.com/gin-gonic/gin v1.6.3
|
github.com/gin-gonic/gin v1.6.3
|
||||||
github.com/go-playground/validator/v10 v10.3.0 // indirect
|
github.com/go-playground/validator/v10 v10.3.0 // indirect
|
||||||
@ -25,7 +25,7 @@ require (
|
|||||||
github.com/xujiajun/nutsdb v0.5.0
|
github.com/xujiajun/nutsdb v0.5.0
|
||||||
github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189
|
github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
|
golang.org/x/sys v0.0.0-20200916084744-dbad9cb7cb7a // indirect
|
||||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
||||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
20
go.sum
20
go.sum
@ -1,15 +1,9 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200909095006-dde8bded28d1 h1:3cmUqA5RaikLx+59SODlBA7tjORQoh4t1w5CzH5bIH8=
|
github.com/Mrs4s/MiraiGo v0.0.0-20200921142226-9a449519db5c h1:TpGiSjI8Pe0YLEQPAVkOV37OFLeJnQ6jxvcDSb/LESY=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200909095006-dde8bded28d1/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
|
github.com/Mrs4s/MiraiGo v0.0.0-20200921142226-9a449519db5c/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200909103204-808a63a78efe h1:O2BW87BwpwZDsn7YFHLfRGFGvTS4OUZsG2UiA13OxcQ=
|
github.com/Mrs4s/MiraiGo v0.0.0-20200926101830-afb0ed6368ad h1:m4KU2n3desxr1L3Idk7qRlf71+77rm0JEMWqd4gmrlQ=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200909103204-808a63a78efe/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
|
github.com/Mrs4s/MiraiGo v0.0.0-20200926101830-afb0ed6368ad/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200910010455-37409b1f6b9c h1:bhVr3W0+WTVN+vgZGlxD4iFSV9L3CmUg/lt91h+Ll18=
|
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200910010455-37409b1f6b9c/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
|
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200910013944-236c0f629099 h1:b+Tmo9h5leZmQokdUu8c2xSIRkkSYoP1z8G+zcwwyRY=
|
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200910013944-236c0f629099/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
|
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200911100852-71bc19cd42eb h1:WRj/3obehfAMTNKfNo+X3NVqXjeNurMk2yy6haNl/Yk=
|
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200911100852-71bc19cd42eb/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
|
|
||||||
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
|
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
|
||||||
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
|
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
@ -70,8 +64,6 @@ github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdA
|
|||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible h1:4mNlp+/SvALIPFpbXV3kxNJJno9iKFWGxSDE13Kl66Q=
|
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
|
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
|
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
|
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
|
||||||
github.com/lestrrat-go/strftime v1.0.3 h1:qqOPU7y+TM8Y803I8fG9c/DyKG3xH/xkng6keC1015Q=
|
github.com/lestrrat-go/strftime v1.0.3 h1:qqOPU7y+TM8Y803I8fG9c/DyKG3xH/xkng6keC1015Q=
|
||||||
@ -148,10 +140,10 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc=
|
|
||||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200916084744-dbad9cb7cb7a h1:chkwkn8HYWVtTE5DCQNKYlkyptadXYY0+PuyaVdyMo4=
|
||||||
|
golang.org/x/sys v0.0.0-20200916084744-dbad9cb7cb7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
||||||
|
33
main.go
33
main.go
@ -10,7 +10,6 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path"
|
"path"
|
||||||
@ -214,6 +213,17 @@ func main() {
|
|||||||
log.Info("Bot将在5秒后登录并开始信息处理, 按 Ctrl+C 取消.")
|
log.Info("Bot将在5秒后登录并开始信息处理, 按 Ctrl+C 取消.")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
log.Info("开始尝试登录并同步消息...")
|
log.Info("开始尝试登录并同步消息...")
|
||||||
|
log.Infof("使用协议: %v", func() string {
|
||||||
|
switch client.SystemDeviceInfo.Protocol {
|
||||||
|
case client.AndroidPad:
|
||||||
|
return "Android Pad"
|
||||||
|
case client.AndroidPhone:
|
||||||
|
return "Android Phone"
|
||||||
|
case client.AndroidWatch:
|
||||||
|
return "Android Watch"
|
||||||
|
}
|
||||||
|
return "未知"
|
||||||
|
}())
|
||||||
cli := client.NewClient(conf.Uin, conf.Password)
|
cli := client.NewClient(conf.Uin, conf.Password)
|
||||||
cli.OnLog(func(c *client.QQClient, e *client.LogEvent) {
|
cli.OnLog(func(c *client.QQClient, e *client.LogEvent) {
|
||||||
switch e.Type {
|
switch e.Type {
|
||||||
@ -226,27 +236,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
cli.OnServerUpdated(func(bot *client.QQClient, e *client.ServerUpdatedEvent) {
|
cli.OnServerUpdated(func(bot *client.QQClient, e *client.ServerUpdatedEvent) {
|
||||||
log.Infof("收到服务器地址更新通知, 将在下一次重连时应用. 服务器地址: %v:%v 服务器位置: %v", e.Servers[0].Server, e.Servers[0].Port, e.Servers[0].Location)
|
log.Infof("收到服务器地址更新通知, 将在下一次重连时应用. ")
|
||||||
_ = ioutil.WriteFile("servers.bin", binary.NewWriterF(func(w *binary.Writer) {
|
|
||||||
w.WriteUInt16(uint16(len(e.Servers)))
|
|
||||||
for _, s := range e.Servers {
|
|
||||||
if !strings.Contains(s.Server, "com") {
|
|
||||||
w.WriteString(s.Server)
|
|
||||||
w.WriteUInt16(uint16(s.Port))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}), 0644)
|
|
||||||
})
|
})
|
||||||
if global.PathExists("servers.bin") {
|
|
||||||
if data, err := ioutil.ReadFile("servers.bin"); err == nil {
|
|
||||||
r := binary.NewReader(data)
|
|
||||||
r.ReadUInt16()
|
|
||||||
cli.CustomServer = &net.TCPAddr{
|
|
||||||
IP: net.ParseIP(r.ReadString()),
|
|
||||||
Port: int(r.ReadUInt16()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rsp, err := cli.Login()
|
rsp, err := cli.Login()
|
||||||
for {
|
for {
|
||||||
global.Check(err)
|
global.Check(err)
|
||||||
|
@ -333,6 +333,11 @@ func (s *httpServer) GetVipInfo(c *gin.Context) {
|
|||||||
c.JSON(200, s.bot.CQGetVipInfo(uid))
|
c.JSON(200, s.bot.CQGetVipInfo(uid))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *httpServer) GetStrangerInfo(c *gin.Context) {
|
||||||
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
||||||
|
c.JSON(200, s.bot.CQGetStrangerInfo(uid))
|
||||||
|
}
|
||||||
|
|
||||||
func (s *httpServer) HandleQuickOperation(c *gin.Context) {
|
func (s *httpServer) HandleQuickOperation(c *gin.Context) {
|
||||||
if c.Request.Method != "POST" {
|
if c.Request.Method != "POST" {
|
||||||
c.AbortWithStatus(404)
|
c.AbortWithStatus(404)
|
||||||
@ -344,6 +349,18 @@ func (s *httpServer) HandleQuickOperation(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *httpServer) OcrImage(c *gin.Context) {
|
||||||
|
img := getParam(c, "image")
|
||||||
|
c.JSON(200, s.bot.CQOcrImage(img))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *httpServer) SetGroupPortrait(c *gin.Context) {
|
||||||
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
||||||
|
file := getParam(c, "file")
|
||||||
|
cache := getParam(c, "cache")
|
||||||
|
c.JSON(200, s.bot.CQSetGroupPortrait(gid, file, cache))
|
||||||
|
}
|
||||||
|
|
||||||
func getParamOrDefault(c *gin.Context, k, def string) string {
|
func getParamOrDefault(c *gin.Context, k, def string) string {
|
||||||
r := getParam(c, k)
|
r := getParam(c, k)
|
||||||
if r != "" {
|
if r != "" {
|
||||||
@ -486,10 +503,19 @@ var httpApi = map[string]func(s *httpServer, c *gin.Context){
|
|||||||
"_get_vip_info": func(s *httpServer, c *gin.Context) {
|
"_get_vip_info": func(s *httpServer, c *gin.Context) {
|
||||||
s.GetVipInfo(c)
|
s.GetVipInfo(c)
|
||||||
},
|
},
|
||||||
|
"get_stranger_info": func(s *httpServer, c *gin.Context) {
|
||||||
|
s.GetStrangerInfo(c)
|
||||||
|
},
|
||||||
"reload_event_filter": func(s *httpServer, c *gin.Context) {
|
"reload_event_filter": func(s *httpServer, c *gin.Context) {
|
||||||
s.ReloadEventFilter(c)
|
s.ReloadEventFilter(c)
|
||||||
},
|
},
|
||||||
|
"set_group_portrait": func(s *httpServer, c *gin.Context) {
|
||||||
|
s.SetGroupPortrait(c)
|
||||||
|
},
|
||||||
".handle_quick_operation": func(s *httpServer, c *gin.Context) {
|
".handle_quick_operation": func(s *httpServer, c *gin.Context) {
|
||||||
s.HandleQuickOperation(c)
|
s.HandleQuickOperation(c)
|
||||||
},
|
},
|
||||||
|
".ocr_image": func(s *httpServer, c *gin.Context) {
|
||||||
|
s.OcrImage(c)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -486,6 +486,9 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
|
|||||||
"can_send_record": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
"can_send_record": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
return bot.CQCanSendRecord()
|
return bot.CQCanSendRecord()
|
||||||
},
|
},
|
||||||
|
"get_stranger_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
|
return bot.CQGetStrangerInfo(p.Get("user_id").Int())
|
||||||
|
},
|
||||||
"get_status": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
"get_status": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
return bot.CQGetStatus()
|
return bot.CQGetStatus()
|
||||||
},
|
},
|
||||||
@ -498,6 +501,12 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
|
|||||||
"reload_event_filter": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
"reload_event_filter": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
return bot.CQReloadEventFilter()
|
return bot.CQReloadEventFilter()
|
||||||
},
|
},
|
||||||
|
".ocr_image": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
|
return bot.CQOcrImage(p.Get("image").Str)
|
||||||
|
},
|
||||||
|
"set_group_portrait": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
|
return bot.CQSetGroupPortrait(p.Get("group_id").Int(), p.Get("file").String(), p.Get("cache").String())
|
||||||
|
},
|
||||||
".handle_quick_operation": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
".handle_quick_operation": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
return bot.CQHandleQuickOperation(p.Get("context"), p.Get("operation"))
|
return bot.CQHandleQuickOperation(p.Get("context"), p.Get("operation"))
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user