1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-06-30 20:03:24 +00:00

Compare commits

...

5 Commits

Author SHA1 Message Date
56ca382a9b reverse websocket supported. 2020-07-26 05:13:08 +08:00
549525236d websocket echo field supported. 2020-07-25 20:35:15 +08:00
f19c76d4e1 update README.md 2020-07-25 08:37:25 +08:00
700a056a17 Merge branch 'master' of https://github.com/Mrs4s/go-cqhttp 2020-07-25 08:36:25 +08:00
2a6b9925f8 quick operation supported. 2020-07-25 08:36:07 +08:00
8 changed files with 335 additions and 75 deletions

View File

@ -2,12 +2,14 @@
使用 [mirai](https://github.com/mamoe/mirai) 以及 [MiraiGo](https://github.com/Mrs4s/MiraiGo) 开发的cqhttp golang原生实现, 并在[cqhttp原版](https://github.com/richardchien/coolq-http-api)的基础上做了部分修改和拓展.
文档暂时可查看 `docs` 目录, 目前还在撰写中.
测试版可前往 Release 下载
# 兼容性
#### 接口
- [x] HTTP API
- [x] 反向HTTP POST (暂不支持回复)
- [x] 反向HTTP POST
- [x] 正向Websocket
- [ ] 反向Websocket (开发中)
- [x] 反向Websocket (测试中)
#### 实现
<details>
<summary>已实现API</summary>

View File

@ -1,11 +1,13 @@
package coolq
import (
"fmt"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/go-cqhttp/global"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"io/ioutil"
"os"
"path"
@ -232,6 +234,63 @@ func (bot *CQBot) CQDeleteMessage(messageId int32) MSG {
return OK(nil)
}
// 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
func (bot *CQBot) CQHandleQuickOperation(context, operation gjson.Result) MSG {
postType := context.Get("post_type").Str
switch postType {
case "message":
msgType := context.Get("message_type").Str
reply := operation.Get("reply").Str
if reply != "" {
at := true
if operation.Get("at_sender").Exists() {
at = operation.Get("at_sender").Bool()
}
if msgType == "group" && at {
if at {
reply = fmt.Sprintf("[CQ:at,qq=%d]%s", context.Get("user_id").Int(), reply)
}
bot.CQSendGroupMessage(context.Get("group_id").Int(), reply)
}
if msgType == "private" {
bot.CQSendPrivateMessage(context.Get("user_id").Int(), reply)
}
}
if msgType == "group" {
anonymous := context.Get("anonymous")
isAnonymous := anonymous.Type == gjson.Null
if operation.Get("delete").Bool() {
bot.CQDeleteMessage(int32(context.Get("message_id").Int()))
}
if operation.Get("kick").Bool() && !isAnonymous {
bot.CQSetGroupKick(context.Get("group_id").Int(), context.Get("user_id").Int(), "")
}
if operation.Get("ban").Bool() {
var duration uint32 = 30 * 60
if operation.Get("ban_duration").Exists() {
duration = uint32(operation.Get("ban_duration").Uint())
}
// unsupported anonymous ban yet
if !isAnonymous {
bot.CQSetGroupBan(context.Get("group_id").Int(), context.Get("user_id").Int(), duration)
}
}
}
case "request":
reqType := context.Get("request_type").Str
if context.Get("approve").Bool() {
if reqType == "friend" {
bot.CQProcessFriendRequest(context.Get("flag").Str, true)
}
if reqType == "group" {
bot.CQProcessGroupRequest(context.Get("flag").Str, context.Get("sub_type").Str, true)
}
}
}
return OK(nil)
}
func (bot *CQBot) CQGetImage(file string) MSG {
if !global.PathExists(path.Join(global.IMAGE_PATH, file)) {
return Failed(100)

View File

@ -38,7 +38,7 @@ func NewQQBot(cli *client.QQClient, conf *global.JsonConfig) *CQBot {
opt.EntryIdxMode = nutsdb.HintBPTSparseIdxMode
db, err := nutsdb.Open(opt)
if err != nil {
log.Fatalf("打开数据库失败, 如果频繁遇到此问题请关闭数据库功能。")
log.Fatalf("打开数据库失败, 如果频繁遇到此问题请清理 data/db 文件夹或关闭数据库功能。")
}
bot.db = db
gob.Register(message.Sender{})

View File

@ -10,10 +10,11 @@ type JsonConfig struct {
Password string `json:"password"`
EnableDB bool `json:"enable_db"`
AccessToken string `json:"access_token"`
Reconnect bool `json:"reconnect"`
ReconnectDelay int `json:"reconnect_delay"`
ReLogin bool `json:"relogin"`
ReLoginDelay int `json:"relogin_delay"`
HttpConfig *GoCQHttpConfig `json:"http_config"`
WSConfig *GoCQWebsocketConfig `json:"ws_config"`
ReverseServers []*GoCQReverseWebsocketConfig `json:"ws_reverse_servers"`
}
type CQHttpApiConfig struct {
@ -48,6 +49,14 @@ type GoCQWebsocketConfig struct {
Port uint16 `json:"port"`
}
type GoCQReverseWebsocketConfig struct {
Enabled bool `json:"enabled"`
ReverseUrl string `json:"reverse_url"`
ReverseApiUrl string `json:"reverse_api_url"`
ReverseEventUrl string `json:"reverse_event_url"`
ReverseReconnectInterval uint16 `json:"reverse_reconnect_interval"`
}
func DefaultConfig() *JsonConfig {
return &JsonConfig{
EnableDB: true,
@ -62,6 +71,15 @@ func DefaultConfig() *JsonConfig {
Host: "0.0.0.0",
Port: 6700,
},
ReverseServers: []*GoCQReverseWebsocketConfig{
{
Enabled: false,
ReverseUrl: "ws://you_websocket_universal.server",
ReverseApiUrl: "ws://you_websocket_api.server",
ReverseEventUrl: "ws://you_websocket_event.server",
ReverseReconnectInterval: 3000,
},
},
}
}

1
go.mod
View File

@ -15,5 +15,6 @@ require (
github.com/tidwall/gjson v1.6.0
github.com/xujiajun/nutsdb v0.5.0
golang.org/x/image v0.0.0-20200618115811-c13761719519
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
)

11
main.go
View File

@ -131,18 +131,21 @@ func main() {
if conf.HttpConfig != nil && conf.HttpConfig.Enabled {
server.HttpServer.Run(fmt.Sprintf("%s:%d", conf.HttpConfig.Host, conf.HttpConfig.Port), conf.AccessToken, b)
for k, v := range conf.HttpConfig.PostUrls {
server.NewClient().Run(k, v, b)
server.NewHttpClient().Run(k, v, b)
}
}
if conf.WSConfig != nil && conf.WSConfig.Enabled {
server.WebsocketServer.Run(fmt.Sprintf("%s:%d", conf.WSConfig.Host, conf.WSConfig.Port), conf.AccessToken, b)
}
for _, rc := range conf.ReverseServers {
server.NewWebsocketClient(rc, conf.AccessToken, b).Run()
}
log.Info("资源初始化完成, 开始处理信息.")
log.Info("アトリは、高性能ですから!")
cli.OnDisconnected(func(bot *client.QQClient, e *client.ClientDisconnectedEvent) {
if conf.Reconnect {
log.Warnf("Bot已离线将在 %v 秒后尝试重连.", conf.ReconnectDelay)
time.Sleep(time.Second * time.Duration(conf.ReconnectDelay))
if conf.ReLogin {
log.Warnf("Bot已离线将在 %v 秒后尝试重连.", conf.ReLoginDelay)
time.Sleep(time.Second * time.Duration(conf.ReLoginDelay))
rsp, err := cli.Login()
if err != nil {
log.Fatalf("重连失败: %v", err)

View File

@ -142,13 +142,15 @@ func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) {
s.engine.Any("/get_version_info", s.GetVersionInfo)
s.engine.Any("/get_version_info_async", s.GetVersionInfo)
s.engine.Any("/.handle_quick_operation", s.HandleQuickOperation)
go func() {
log.Infof("CQ HTTP 服务器已启动: %v", addr)
log.Fatal(s.engine.Run(addr))
}()
}
func NewClient() *httpClient {
func NewHttpClient() *httpClient {
return &httpClient{}
}
@ -161,10 +163,10 @@ func (c *httpClient) Run(addr, secret string, bot *coolq.CQBot) {
}
func (c *httpClient) onBotPushEvent(m coolq.MSG) {
err := gout.POST(c.addr).SetJSON(m).SetHeader(func() gout.H {
var res string
err := gout.POST(c.addr).SetJSON(m).BindBody(&res).SetHeader(func() gout.H {
h := gout.H{
"X-Self_ID": c.bot.Client.Uin,
"X-Client-Role": "Universal",
"X-Self-ID": c.bot.Client.Uin,
"User-Agent": "CQHttp/4.15.0",
}
if c.secret != "" {
@ -176,6 +178,10 @@ func (c *httpClient) onBotPushEvent(m coolq.MSG) {
}()).SetTimeout(time.Second * 5).Do()
if err != nil {
log.Warnf("上报Event数据到 %v 失败: %v", c.addr, err)
return
}
if gjson.Valid(res) {
c.bot.CQHandleQuickOperation(gjson.Parse(m.ToJson()), gjson.Parse(res))
}
}
@ -278,8 +284,8 @@ func (s *httpServer) SetGroupKick(c *gin.Context) {
func (s *httpServer) SetGroupBan(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
time, _ := strconv.ParseInt(getParam(c, "duration"), 10, 64)
c.JSON(200, s.bot.CQSetGroupBan(gid, uid, uint32(time)))
i, _ := strconv.ParseInt(getParam(c, "duration"), 10, 64)
c.JSON(200, s.bot.CQSetGroupBan(gid, uid, uint32(i)))
}
func (s *httpServer) SetWholeBan(c *gin.Context) {
@ -313,6 +319,17 @@ func (s *httpServer) GetVersionInfo(c *gin.Context) {
c.JSON(200, s.bot.CQGetVersionInfo())
}
func (s *httpServer) HandleQuickOperation(c *gin.Context) {
if c.Request.Method != "POST" {
c.AbortWithStatus(404)
return
}
if i, ok := c.Get("json_body"); ok {
body := i.(gjson.Result)
c.JSON(200, s.bot.CQHandleQuickOperation(body.Get("context"), body.Get("operation")))
}
}
func getParamOrDefault(c *gin.Context, k, def string) string {
r := getParam(c, k)
if r != "" {

View File

@ -3,10 +3,13 @@ package server
import (
"fmt"
"github.com/Mrs4s/go-cqhttp/coolq"
"github.com/Mrs4s/go-cqhttp/global"
"github.com/gorilla/websocket"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
wsc "golang.org/x/net/websocket"
"net/http"
"strconv"
"strings"
"sync"
"time"
@ -21,6 +24,13 @@ type websocketServer struct {
}
type websocketClient struct {
conf *global.GoCQReverseWebsocketConfig
token string
bot *coolq.CQBot
pushLock *sync.Mutex
universalConn *wsc.Conn
eventConn *wsc.Conn
}
var WebsocketServer = &websocketServer{}
@ -46,6 +56,149 @@ func (s *websocketServer) Run(addr, authToken string, b *coolq.CQBot) {
}()
}
func NewWebsocketClient(conf *global.GoCQReverseWebsocketConfig, authToken string, b *coolq.CQBot) *websocketClient {
return &websocketClient{conf: conf, token: authToken, bot: b, pushLock: new(sync.Mutex)}
}
func (c *websocketClient) Run() {
if !c.conf.Enabled {
return
}
if c.conf.ReverseApiUrl != "" {
c.connectApi()
}
if c.conf.ReverseEventUrl != "" {
c.connectEvent()
}
if c.conf.ReverseUrl != "" {
c.connectUniversal()
}
c.bot.OnEventPush(c.onBotPushEvent)
}
func (c *websocketClient) connectApi() {
log.Infof("开始尝试连接到反向Websocket API服务器: %v", c.conf.ReverseApiUrl)
wsConf, err := wsc.NewConfig(c.conf.ReverseApiUrl, c.conf.ReverseApiUrl)
if err != nil {
log.Warnf("连接到反向Websocket API服务器 %v 时出现致命错误: %v", c.conf.ReverseApiUrl, err)
return
}
wsConf.Header["X-Client-Role"] = []string{"API"}
wsConf.Header["X-Self-ID"] = []string{strconv.FormatInt(c.bot.Client.Uin, 10)}
wsConf.Header["User-Agent"] = []string{"CQHttp/4.15.0"}
if c.token != "" {
wsConf.Header["Authorization"] = []string{"Token " + c.token}
}
conn, err := wsc.DialConfig(wsConf)
if err != nil {
log.Warnf("连接到反向Websocket API服务器 %v 时出现错误: %v", c.conf.ReverseApiUrl, err)
if c.conf.ReverseReconnectInterval != 0 {
time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval))
c.connectApi()
}
return
}
log.Infof("已连接到反向Websocket API服务器 %v", c.conf.ReverseApiUrl)
go c.listenApi(conn, false)
}
func (c *websocketClient) connectEvent() {
log.Infof("开始尝试连接到反向Websocket Event服务器: %v", c.conf.ReverseEventUrl)
wsConf, err := wsc.NewConfig(c.conf.ReverseEventUrl, c.conf.ReverseEventUrl)
if err != nil {
log.Warnf("连接到反向Websocket Event服务器 %v 时出现致命错误: %v", c.conf.ReverseApiUrl, err)
return
}
wsConf.Header["X-Client-Role"] = []string{"Event"}
wsConf.Header["X-Self-ID"] = []string{strconv.FormatInt(c.bot.Client.Uin, 10)}
wsConf.Header["User-Agent"] = []string{"CQHttp/4.15.0"}
if c.token != "" {
wsConf.Header["Authorization"] = []string{"Token " + c.token}
}
conn, err := wsc.DialConfig(wsConf)
if err != nil {
log.Warnf("连接到反向Websocket API服务器 %v 时出现错误: %v", c.conf.ReverseApiUrl, err)
if c.conf.ReverseReconnectInterval != 0 {
time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval))
c.connectApi()
}
return
}
log.Infof("已连接到反向Websocket Event服务器 %v", c.conf.ReverseEventUrl)
c.eventConn = conn
}
func (c *websocketClient) connectUniversal() {
log.Infof("开始尝试连接到反向Websocket Universal服务器: %v", c.conf.ReverseUrl)
wsConf, err := wsc.NewConfig(c.conf.ReverseUrl, c.conf.ReverseUrl)
if err != nil {
log.Warnf("连接到反向Websocket Universal服务器 %v 时出现致命错误: %v", c.conf.ReverseUrl, err)
return
}
wsConf.Header["X-Client-Role"] = []string{"Universal"}
wsConf.Header["X-Self-ID"] = []string{strconv.FormatInt(c.bot.Client.Uin, 10)}
wsConf.Header["User-Agent"] = []string{"CQHttp/4.15.0"}
if c.token != "" {
wsConf.Header["Authorization"] = []string{"Token " + c.token}
}
conn, err := wsc.DialConfig(wsConf)
if err != nil {
log.Warnf("连接到反向Websocket Universal服务器 %v 时出现错误: %v", c.conf.ReverseUrl, err)
if c.conf.ReverseReconnectInterval != 0 {
time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval))
c.connectUniversal()
}
return
}
go c.listenApi(conn, true)
c.universalConn = conn
}
func (c *websocketClient) listenApi(conn *wsc.Conn, u bool) {
defer conn.Close()
for {
buf := make([]byte, 10240)
l, err := conn.Read(buf)
if err != nil {
break
}
j := gjson.ParseBytes(buf[:l])
t := strings.ReplaceAll(j.Get("action").Str, "_async", "")
if f, ok := wsApi[t]; ok {
ret := f(c.bot, j.Get("params"))
if j.Get("echo").Exists() {
ret["echo"] = j.Get("echo").Value()
}
_, _ = conn.Write([]byte(ret.ToJson()))
}
}
if c.conf.ReverseReconnectInterval != 0 {
time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval))
if u {
c.connectUniversal()
return
}
c.connectApi()
}
}
func (c *websocketClient) onBotPushEvent(m coolq.MSG) {
c.pushLock.Lock()
defer c.pushLock.Unlock()
if c.eventConn != nil {
if _, err := c.eventConn.Write([]byte(m.ToJson())); err != nil {
_ = c.eventConn.Close()
if c.conf.ReverseReconnectInterval != 0 {
time.Sleep(time.Millisecond * time.Duration(c.conf.ReverseReconnectInterval))
c.connectEvent()
}
}
}
if c.universalConn != nil {
_, _ = c.universalConn.Write([]byte(m.ToJson()))
}
}
func (s *websocketServer) event(w http.ResponseWriter, r *http.Request) {
if s.token != "" {
if r.URL.Query().Get("access_token") != s.token && strings.SplitN(r.Header.Get("Authorization"), " ", 2)[1] != s.token {
@ -114,9 +267,13 @@ func (s *websocketServer) listenApi(c *websocket.Conn) {
if t == websocket.TextMessage {
j := gjson.ParseBytes(payload)
t := strings.ReplaceAll(j.Get("action").Str, "_async", "") //TODO: async support
log.Infof("API调用: %v", j.Get("action").Str)
//log.Infof("API调用: %v", j.Get("action").Str)
if f, ok := wsApi[t]; ok {
_ = c.WriteMessage(websocket.TextMessage, []byte(f(s.bot, j.Get("params"))))
ret := f(s.bot, j.Get("params"))
if j.Get("echo").Exists() {
ret["echo"] = j.Get("echo").Value()
}
_ = c.WriteJSON(ret)
}
}
}
@ -139,54 +296,54 @@ func (s *websocketServer) onBotPushEvent(m coolq.MSG) {
}
}
var wsApi = map[string]func(*coolq.CQBot, gjson.Result) string{
"get_login_info": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetLoginInfo().ToJson()
var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
"get_login_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetLoginInfo()
},
"get_friend_list": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetFriendList().ToJson()
"get_friend_list": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetFriendList()
},
"get_group_list": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetGroupList().ToJson()
"get_group_list": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupList()
},
"get_group_info": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetGroupInfo(p.Get("group_id").Int()).ToJson()
"get_group_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupInfo(p.Get("group_id").Int())
},
"get_group_member_list": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetGroupMemberList(p.Get("group_id").Int()).ToJson()
"get_group_member_list": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupMemberList(p.Get("group_id").Int())
},
"get_group_member_info": func(bot *coolq.CQBot, p gjson.Result) string {
"get_group_member_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupMemberInfo(
p.Get("group_id").Int(), p.Get("user_id").Int(),
p.Get("no_cache").Bool(),
).ToJson()
)
},
"send_msg": func(bot *coolq.CQBot, p gjson.Result) string {
"send_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
if p.Get("group_id").Int() != 0 {
return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message").Str).ToJson()
return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message").Str)
}
if p.Get("user_id").Int() != 0 {
return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("message").Str).ToJson()
return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("message").Str)
}
return ""
return coolq.MSG{}
},
"send_group_msg": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message").Str).ToJson()
"send_group_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message").Str)
},
"send_private_msg": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("message").Str).ToJson()
"send_private_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("message").Str)
},
"delete_msg": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQDeleteMessage(int32(p.Get("message_id").Int())).ToJson()
"delete_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQDeleteMessage(int32(p.Get("message_id").Int()))
},
"set_friend_add_request": func(bot *coolq.CQBot, p gjson.Result) string {
"set_friend_add_request": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
apr := true
if p.Get("approve").Exists() {
apr = p.Get("approve").Bool()
}
return bot.CQProcessFriendRequest(p.Get("flag").Str, apr).ToJson()
return bot.CQProcessFriendRequest(p.Get("flag").Str, apr)
},
"set_group_add_request": func(bot *coolq.CQBot, p gjson.Result) string {
"set_group_add_request": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
subType := p.Get("sub_type").Str
apr := true
if subType == "" {
@ -195,47 +352,50 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) string{
if p.Get("approve").Exists() {
apr = p.Get("approve").Bool()
}
return bot.CQProcessGroupRequest(p.Get("flag").Str, subType, apr).ToJson()
return bot.CQProcessGroupRequest(p.Get("flag").Str, subType, apr)
},
"set_group_card": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQSetGroupCard(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("card").Str).ToJson()
"set_group_card": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupCard(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("card").Str)
},
"set_group_special_title": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQSetGroupSpecialTitle(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("special_title").Str).ToJson()
"set_group_special_title": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupSpecialTitle(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("special_title").Str)
},
"set_group_kick": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQSetGroupKick(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("message").Str).ToJson()
"set_group_kick": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupKick(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("message").Str)
},
"set_group_ban": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQSetGroupBan(p.Get("group_id").Int(), p.Get("user_id").Int(), uint32(p.Get("duration").Int())).ToJson()
"set_group_ban": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupBan(p.Get("group_id").Int(), p.Get("user_id").Int(), uint32(p.Get("duration").Int()))
},
"set_group_whole_ban": func(bot *coolq.CQBot, p gjson.Result) string {
"set_group_whole_ban": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupWholeBan(p.Get("group_id").Int(), func() bool {
if p.Get("enable").Exists() {
return p.Get("enable").Bool()
}
return true
}()).ToJson()
}())
},
"set_group_name": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQSetGroupName(p.Get("group_id").Int(), p.Get("name").Str).ToJson()
"set_group_name": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupName(p.Get("group_id").Int(), p.Get("name").Str)
},
"get_image": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetImage(p.Get("file").Str).ToJson()
"get_image": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetImage(p.Get("file").Str)
},
"get_group_msg": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetGroupMessage(int32(p.Get("message_id").Int())).ToJson()
"get_group_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupMessage(int32(p.Get("message_id").Int()))
},
"can_send_image": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQCanSendImage().ToJson()
"can_send_image": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQCanSendImage()
},
"can_send_record": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQCanSendRecord().ToJson()
"can_send_record": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQCanSendRecord()
},
"get_status": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetStatus().ToJson()
"get_status": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetStatus()
},
"get_version_info": func(bot *coolq.CQBot, p gjson.Result) string {
return bot.CQGetVersionInfo().ToJson()
"get_version_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetVersionInfo()
},
".handle_quick_operation": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQHandleQuickOperation(p.Get("context"), p.Get("operation"))
},
}