diff --git a/.golangci.yml b/.golangci.yml index 6c466b4..6408d8d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -66,6 +66,7 @@ run: issues-exit-code: 1 skip-dirs: - db + - cmd/api-generator tests: true # output configuration options diff --git a/cmd/api-generator/main.go b/cmd/api-generator/main.go new file mode 100644 index 0000000..5f32f8b --- /dev/null +++ b/cmd/api-generator/main.go @@ -0,0 +1,254 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "io" + "os" + "sort" + "strconv" + "strings" +) + +type Param struct { + Name string + Type string + Default string +} + +type Router struct { + Func string + Path string + Aliases []string + Params []Param +} + +type generator struct { + out io.Writer +} + +func (g *generator) WriteString(s string) { + io.WriteString(g.out, s) +} + +func (g *generator) generate(routers []Router) { + g.WriteString("// Code generated by cmd/api-generator. DO NOT EDIT.\n\n") + g.WriteString("package api\n\nimport (\n\n") + g.WriteString("\"github.com/Mrs4s/go-cqhttp/coolq\"\n") + g.WriteString("\"github.com/Mrs4s/go-cqhttp/global\"\n") + g.WriteString(")\n\n") + g.WriteString(`func (c *Caller) call(action string, p Getter) global.MSG { + switch action { + default: + return coolq.Failed(404, "API_NOT_FOUND", "API不存在")` + "\n") + for _, router := range routers { + g.router(router) + } + io.WriteString(g.out, ` }}`) +} + +func (g *generator) router(router Router) { + g.WriteString(`case ` + strconv.Quote(router.Path)) + for _, alias := range router.Aliases { + g.WriteString(`, ` + strconv.Quote(alias)) + } + g.WriteString(":\n") + + for i, p := range router.Params { + if p.Default == "" { + v := "p.Get(" + strconv.Quote(p.Name) + ")" + fmt.Fprintf(g.out, "p%d := %s\n", i, conv(v, p.Type)) + } else { + fmt.Fprintf(g.out, "p%d := %s\n", i, p.Default) + fmt.Fprintf(g.out, "if pt := p.Get(%s); pt.Exists() {\n", strconv.Quote(p.Name)) + fmt.Fprintf(g.out, "p%d = %s\n}\n", i, conv("pt", p.Type)) + } + } + + g.WriteString("\t\treturn c.bot." + router.Func + "(") + for i := range router.Params { + if i != 0 { + g.WriteString(", ") + } + fmt.Fprintf(g.out, "p%d", i) + } + g.WriteString(")\n") +} + +func conv(v, t string) string { + switch t { + default: + panic("unknown type: " + t) + case "gjson.Result": + return v + case "int64": + return v + ".Int()" + case "bool": + return v + ".Bool()" + case "string": + return v + ".String()" + case "int32", "uint32", "int": + return t + "(" + v + ".Int())" + } +} + +func main() { + var routers []Router + src := flag.String("path", "", "source file") + flag.Parse() + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, *src, nil, parser.ParseComments) + if err != nil { + panic(err) + } + + for _, decl := range file.Decls { + switch decl := decl.(type) { + case *ast.FuncDecl: + if decl.Recv == nil { + continue + } + if st, ok := decl.Recv.List[0].Type.(*ast.StarExpr); !ok || st.X.(*ast.Ident).Name != "CQBot" { + continue + } + router := Router{Func: decl.Name.Name} + + // compute params + for _, p := range decl.Type.Params.List { + var typ string + switch t := p.Type.(type) { + case *ast.Ident: + typ = t.Name + case *ast.SelectorExpr: + typ = t.X.(*ast.Ident).Name + "." + t.Sel.Name + } + for _, name := range p.Names { + router.Params = append(router.Params, Param{Name: snakecase(name.Name), Type: typ}) + } + } + + for _, comment := range decl.Doc.List { + annotation, args := match(comment.Text) + switch annotation { + case "": + continue + case "route": + router.Path = args["path"] + if args["alias"] != "" { + router.Aliases = append(router.Aliases, args["alias"]) + } + case "param": + i, err := strconv.Atoi(args["index"]) + if err != nil { + continue + } + if args["name"] != "" { + router.Params[i].Name = args["name"] + } + if args["default"] != "" { + router.Params[i].Default = convDefault(args["default"], router.Params[i].Type) + } + } + } + if router.Path != "" { + routers = append(routers, router) + } else { + println(decl.Name.Name) + } + } + } + + sort.Slice(routers, func(i, j int) bool { + return routers[i].Path < routers[j].Path + }) + + out := new(bytes.Buffer) + g := &generator{out: out} + g.generate(routers) + source, err := format.Source(out.Bytes()) + if err != nil { + panic(err) + } + err = os.WriteFile("api.go", source, 0o644) + if err != nil { + panic(err) + } +} + +func match(text string) (string, map[string]string) { + text = strings.TrimPrefix(text, "//") + text = strings.TrimSpace(text) + if !strings.HasPrefix(text, "@") || !strings.HasSuffix(text, ")") { + return "", nil + } + text = strings.Trim(text, "@)") + cmd, args, ok := cut(text, "(") + if !ok { + return "", nil + } + params := make(map[string]string) + for _, arg := range strings.Split(args, ",") { + k, v, ok := cut(arg, "=") + if !ok { + params[k] = "true" + } + k = strings.TrimSpace(k) + v = strings.TrimSpace(v) + switch v[0] { + case '"': + v, _ = strconv.Unquote(v) + case '`': + v = strings.Trim(v, "`") + } + params[k] = v + } + return cmd, params +} + +func cut(s, sep string) (before, after string, found bool) { + if i := strings.Index(s, sep); i >= 0 { + return s[:i], s[i+len(sep):], true + } + return s, "", false +} + +func isASCIIDigit(c byte) bool { return '0' <= c && c <= '9' } +func isASCIILower(c byte) bool { return 'a' <= c && c <= 'z' } + +// some abbreviations need translation before transforming ro snake case +var replacer = strings.NewReplacer("ID", "Id") + +func snakecase(s string) string { + s = replacer.Replace(s) + t := make([]byte, 0, 32) + for i := 0; i < len(s); i++ { + if isASCIILower(s[i]) || isASCIIDigit(s[i]) { + t = append(t, s[i]) + } else { + t = append(t, '_') + t = append(t, s[i]^0x20) + } + } + return string(t) +} + +func convDefault(s string, t string) string { + switch t { + case "bool": + if s == "true" { + return s + } + case "uint32": + if s != "0" { + return t + "(" + s + ")" + } + default: + panic("unhandled default value type:" + t) + } + return "" +} diff --git a/coolq/api.go b/coolq/api.go index 45d45b5..4078d19 100644 --- a/coolq/api.go +++ b/coolq/api.go @@ -14,9 +14,6 @@ import ( "strings" "time" - "github.com/Mrs4s/go-cqhttp/db" - "github.com/Mrs4s/go-cqhttp/internal/cache" - "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/client" "github.com/Mrs4s/MiraiGo/message" @@ -24,19 +21,24 @@ import ( log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" + "github.com/Mrs4s/go-cqhttp/db" "github.com/Mrs4s/go-cqhttp/global" "github.com/Mrs4s/go-cqhttp/internal/base" + "github.com/Mrs4s/go-cqhttp/internal/cache" "github.com/Mrs4s/go-cqhttp/internal/param" + "github.com/Mrs4s/go-cqhttp/modules/filter" ) // CQGetLoginInfo 获取登录号信息 // // https://git.io/Jtz1I +// @route(path=get_login_info) func (bot *CQBot) CQGetLoginInfo() global.MSG { return OK(global.MSG{"user_id": bot.Client.Uin, "nickname": bot.Client.Nickname}) } // CQGetQiDianAccountInfo 获取企点账号信息 +// @route(path=qidian_get_account_info) func (bot *CQBot) CQGetQiDianAccountInfo() global.MSG { if bot.Client.QiDian == nil { return Failed(100, "QIDIAN_PROTOCOL_REQUEST", "请使用企点协议") @@ -51,6 +53,7 @@ func (bot *CQBot) CQGetQiDianAccountInfo() global.MSG { // CQGetFriendList 获取好友列表 // // https://git.io/Jtz1L +// @route(path=get_friend_list) func (bot *CQBot) CQGetFriendList() global.MSG { fs := make([]global.MSG, 0, len(bot.Client.FriendList)) for _, f := range bot.Client.FriendList { @@ -65,7 +68,7 @@ func (bot *CQBot) CQGetFriendList() global.MSG { // CQGetUnidirectionalFriendList 获取单向好友列表 // -// +// @route(path=get_unidirectional_friend_list) func (bot *CQBot) CQGetUnidirectionalFriendList() global.MSG { list, err := bot.Client.GetUnidirectionalFriendList() if err != nil { @@ -85,7 +88,8 @@ func (bot *CQBot) CQGetUnidirectionalFriendList() global.MSG { // CQDeleteUnidirectionalFriend 删除单向好友 // -// +// @route(path=delete_unidirectional_friend) +// @param(index=0, name=user_id) func (bot *CQBot) CQDeleteUnidirectionalFriend(uin int64) global.MSG { list, err := bot.Client.GetUnidirectionalFriendList() if err != nil { @@ -105,8 +109,8 @@ func (bot *CQBot) CQDeleteUnidirectionalFriend(uin int64) global.MSG { } // CQDeleteFriend 删除好友 -// -// +// @route(path=delete_friend) +// @param(index=0,name="[user_id\x2Cid].0") func (bot *CQBot) CQDeleteFriend(uin int64) global.MSG { if bot.Client.FindFriend(uin) == nil { return Failed(100, "FRIEND_NOT_FOUND", "好友不存在") @@ -121,6 +125,7 @@ func (bot *CQBot) CQDeleteFriend(uin int64) global.MSG { // CQGetGroupList 获取群列表 // // https://git.io/Jtz1t +// @route(path=get_group_list) func (bot *CQBot) CQGetGroupList(noCache bool) global.MSG { gs := make([]global.MSG, 0, len(bot.Client.GroupList)) if noCache { @@ -143,6 +148,7 @@ func (bot *CQBot) CQGetGroupList(noCache bool) global.MSG { // CQGetGroupInfo 获取群信息 // // https://git.io/Jtz1O +// @route(path=get_group_info) func (bot *CQBot) CQGetGroupInfo(groupID int64, noCache bool) global.MSG { group := bot.Client.FindGroup(groupID) if group == nil || noCache { @@ -184,6 +190,7 @@ func (bot *CQBot) CQGetGroupInfo(groupID int64, noCache bool) global.MSG { // CQGetGroupMemberList 获取群成员列表 // // https://git.io/Jtz13 +// @route(path=get_group_member_list) func (bot *CQBot) CQGetGroupMemberList(groupID int64, noCache bool) global.MSG { group := bot.Client.FindGroup(groupID) if group == nil { @@ -207,6 +214,7 @@ func (bot *CQBot) CQGetGroupMemberList(groupID int64, noCache bool) global.MSG { // CQGetGroupMemberInfo 获取群成员信息 // // https://git.io/Jtz1s +// @route(path=get_group_member_info) func (bot *CQBot) CQGetGroupMemberInfo(groupID, userID int64, noCache bool) global.MSG { group := bot.Client.FindGroup(groupID) if group == nil { @@ -232,6 +240,7 @@ func (bot *CQBot) CQGetGroupMemberInfo(groupID, userID int64, noCache bool) glob // CQGetGroupFileSystemInfo 扩展API-获取群文件系统信息 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E4%BF%A1%E6%81%AF +// @route(path=get_group_file_system_info) func (bot *CQBot) CQGetGroupFileSystemInfo(groupID int64) global.MSG { fs, err := bot.Client.GetGroupFileSystem(groupID) if err != nil { @@ -244,6 +253,7 @@ func (bot *CQBot) CQGetGroupFileSystemInfo(groupID int64) global.MSG { // CQGetGroupRootFiles 扩展API-获取群根目录文件列表 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E5%88%97%E8%A1%A8 +// @route(path=get_group_root_files) func (bot *CQBot) CQGetGroupRootFiles(groupID int64) global.MSG { fs, err := bot.Client.GetGroupFileSystem(groupID) if err != nil { @@ -264,6 +274,7 @@ func (bot *CQBot) CQGetGroupRootFiles(groupID int64) global.MSG { // CQGetGroupFilesByFolderID 扩展API-获取群子目录文件列表 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%BE%A4%E5%AD%90%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E5%88%97%E8%A1%A8 +// @route(path=get_group_files_by_folder) func (bot *CQBot) CQGetGroupFilesByFolderID(groupID int64, folderID string) global.MSG { fs, err := bot.Client.GetGroupFileSystem(groupID) if err != nil { @@ -284,6 +295,7 @@ func (bot *CQBot) CQGetGroupFilesByFolderID(groupID int64, folderID string) glob // CQGetGroupFileURL 扩展API-获取群文件资源链接 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%96%87%E4%BB%B6%E8%B5%84%E6%BA%90%E9%93%BE%E6%8E%A5 +// @route(path=get_group_file_url) func (bot *CQBot) CQGetGroupFileURL(groupID int64, fileID string, busID int32) global.MSG { url := bot.Client.GetGroupFileUrl(groupID, fileID, busID) if url == "" { @@ -297,6 +309,7 @@ func (bot *CQBot) CQGetGroupFileURL(groupID int64, fileID string, busID int32) g // CQUploadGroupFile 扩展API-上传群文件 // // https://docs.go-cqhttp.org/api/#%E4%B8%8A%E4%BC%A0%E7%BE%A4%E6%96%87%E4%BB%B6 +// @route(path=upload_group_file) func (bot *CQBot) CQUploadGroupFile(groupID int64, file, name, folder string) global.MSG { if !global.PathExists(file) { log.Errorf("上传群文件 %v 失败: 文件不存在", file) @@ -319,7 +332,7 @@ func (bot *CQBot) CQUploadGroupFile(groupID int64, file, name, folder string) gl // CQGroupFileCreateFolder 拓展API-创建群文件文件夹 // -// +// @route(path=create_group_file_folder) func (bot *CQBot) CQGroupFileCreateFolder(groupID int64, parentID, name string) global.MSG { fs, err := bot.Client.GetGroupFileSystem(groupID) if err != nil { @@ -335,7 +348,8 @@ func (bot *CQBot) CQGroupFileCreateFolder(groupID int64, parentID, name string) // CQGroupFileDeleteFolder 拓展API-删除群文件文件夹 // -// +// @route(path=delete_group_folder) +// @param(index=1, name=folder_id) func (bot *CQBot) CQGroupFileDeleteFolder(groupID int64, id string) global.MSG { fs, err := bot.Client.GetGroupFileSystem(groupID) if err != nil { @@ -351,7 +365,8 @@ func (bot *CQBot) CQGroupFileDeleteFolder(groupID int64, id string) global.MSG { // CQGroupFileDeleteFile 拓展API-删除群文件 // -// +// @route(path=delete_group_file) +// @param(index=1, name=file_id) func (bot *CQBot) CQGroupFileDeleteFile(groupID int64, id string, busID int32) global.MSG { fs, err := bot.Client.GetGroupFileSystem(groupID) if err != nil { @@ -368,6 +383,7 @@ func (bot *CQBot) CQGroupFileDeleteFile(groupID int64, id string, busID int32) g // CQGetWordSlices 隐藏API-获取中文分词 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D-%E9%9A%90%E8%97%8F-api +// @route(path=.get_word_slices) func (bot *CQBot) CQGetWordSlices(content string) global.MSG { slices, err := bot.Client.GetWordSegmentation(content) if err != nil { @@ -379,9 +395,29 @@ func (bot *CQBot) CQGetWordSlices(content string) global.MSG { return OK(global.MSG{"slices": slices}) } +// CQSendMessage 发送消息 +// +// @route(path=send_msg) +// @param(index=2, name=message) +func (bot *CQBot) CQSendMessage(groupID, userID int64, m gjson.Result, messageType string, autoEscape bool) global.MSG { + switch { + case messageType == "group": + return bot.CQSendGroupMessage(groupID, m, autoEscape) + case messageType == "private": + fallthrough + case userID != 0: + return bot.CQSendPrivateMessage(userID, groupID, m, autoEscape) + case groupID != 0: + return bot.CQSendGroupMessage(groupID, m, autoEscape) + } + return global.MSG{} +} + // CQSendGroupMessage 发送群消息 // // https://git.io/Jtz1c +// @route(path=send_group_msg) +// @param(index=1, name=message) func (bot *CQBot) CQSendGroupMessage(groupID int64, m gjson.Result, autoEscape bool) global.MSG { group := bot.Client.FindGroup(groupID) if group == nil { @@ -427,6 +463,8 @@ func (bot *CQBot) CQSendGroupMessage(groupID int64, m gjson.Result, autoEscape b // CQSendGroupForwardMessage 扩展API-发送合并转发(群) // // https://docs.go-cqhttp.org/api/#%E5%8F%91%E9%80%81%E5%90%88%E5%B9%B6%E8%BD%AC%E5%8F%91-%E7%BE%A4 +// @route(path=send_group_forward_msg) +// @param(index=1, name=messages) func (bot *CQBot) CQSendGroupForwardMessage(groupID int64, m gjson.Result) global.MSG { if m.Type != gjson.JSON { return Failed(100) @@ -558,6 +596,8 @@ func (bot *CQBot) CQSendGroupForwardMessage(groupID int64, m gjson.Result) globa // CQSendPrivateMessage 发送私聊消息 // // https://git.io/Jtz1l +// @route(path=send_private_msg) +// @param(index=2, name=message) func (bot *CQBot) CQSendPrivateMessage(userID int64, groupID int64, m gjson.Result, autoEscape bool) global.MSG { var elem []message.IMessageElement if m.Type == gjson.JSON { @@ -584,6 +624,7 @@ func (bot *CQBot) CQSendPrivateMessage(userID int64, groupID int64, m gjson.Resu // CQSetGroupCard 设置群名片(群备注) // // https://git.io/Jtz1B +// @route(path=set_group_card) func (bot *CQBot) CQSetGroupCard(groupID, userID int64, card string) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { if m := g.FindMember(userID); m != nil { @@ -597,6 +638,7 @@ func (bot *CQBot) CQSetGroupCard(groupID, userID int64, card string) global.MSG // CQSetGroupSpecialTitle 设置群组专属头衔 // // https://git.io/Jtz10 +// @route(path=set_group_special_title) func (bot *CQBot) CQSetGroupSpecialTitle(groupID, userID int64, title string) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { if m := g.FindMember(userID); m != nil { @@ -610,6 +652,8 @@ func (bot *CQBot) CQSetGroupSpecialTitle(groupID, userID int64, title string) gl // CQSetGroupName 设置群名 // // https://git.io/Jtz12 +// @route(path=set_group_name) +// @param(index=1, name=group_name) func (bot *CQBot) CQSetGroupName(groupID int64, name string) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { g.UpdateName(name) @@ -621,7 +665,10 @@ func (bot *CQBot) CQSetGroupName(groupID int64, name string) global.MSG { // CQSetGroupMemo 扩展API-发送群公告 // // https://docs.go-cqhttp.org/api/#%E5%8F%91%E9%80%81%E7%BE%A4%E5%85%AC%E5%91%8A -func (bot *CQBot) CQSetGroupMemo(groupID int64, msg string, img string) global.MSG { +// @route(path=_send_group_notice) +// @param(index=1, name=content) +// @param(index=2, name=image) +func (bot *CQBot) CQSetGroupMemo(groupID int64, msg, img string) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { if g.SelfPermission() == client.Member { return Failed(100, "PERMISSION_DENIED", "权限不足") @@ -649,7 +696,10 @@ func (bot *CQBot) CQSetGroupMemo(groupID int64, msg string, img string) global.M // CQSetGroupKick 群组踢人 // // https://git.io/Jtz1V -func (bot *CQBot) CQSetGroupKick(groupID, userID int64, msg string, block bool) global.MSG { +// @route(path=set_group_kick) +// @param(index=2, name=message) +// @param(index=3, name=reject_add_request) +func (bot *CQBot) CQSetGroupKick(groupID int64, userID int64, msg string, block bool) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { if m := g.FindMember(userID); m != nil { err := m.Kick(msg, block) @@ -665,6 +715,8 @@ func (bot *CQBot) CQSetGroupKick(groupID, userID int64, msg string, block bool) // CQSetGroupBan 群组单人禁言 // // https://git.io/Jtz1w +// @route(path=set_group_ban) +// @param(index=2, default=1800) func (bot *CQBot) CQSetGroupBan(groupID, userID int64, duration uint32) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { if m := g.FindMember(userID); m != nil { @@ -684,6 +736,8 @@ func (bot *CQBot) CQSetGroupBan(groupID, userID int64, duration uint32) global.M // CQSetGroupWholeBan 群组全员禁言 // // https://git.io/Jtz1o +// @route(path=set_group_whole_ban) +// @param(index=1, default=true) func (bot *CQBot) CQSetGroupWholeBan(groupID int64, enable bool) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { g.MuteAll(enable) @@ -695,6 +749,7 @@ func (bot *CQBot) CQSetGroupWholeBan(groupID int64, enable bool) global.MSG { // CQSetGroupLeave 退出群组 // // https://git.io/Jtz1K +// @route(path=set_group_leave) func (bot *CQBot) CQSetGroupLeave(groupID int64) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { g.Quit() @@ -706,6 +761,7 @@ func (bot *CQBot) CQSetGroupLeave(groupID int64) global.MSG { // CQGetAtAllRemain 扩展API-获取群 @全体成员 剩余次数 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%BE%A4-%E5%85%A8%E4%BD%93%E6%88%90%E5%91%98-%E5%89%A9%E4%BD%99%E6%AC%A1%E6%95%B0 +// @route(path=get_group_at_all_remain) func (bot *CQBot) CQGetAtAllRemain(groupID int64) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { i, err := bot.Client.GetAtAllRemain(groupID) @@ -720,6 +776,8 @@ func (bot *CQBot) CQGetAtAllRemain(groupID int64) global.MSG { // CQProcessFriendRequest 处理加好友请求 // // https://git.io/Jtz11 +// @route(path=set_friend_add_request) +// @param(index=1, default=true) func (bot *CQBot) CQProcessFriendRequest(flag string, approve bool) global.MSG { req, ok := bot.friendReqCache.Load(flag) if !ok { @@ -736,6 +794,9 @@ func (bot *CQBot) CQProcessFriendRequest(flag string, approve bool) global.MSG { // CQProcessGroupRequest 处理加群请求/邀请 // // https://git.io/Jtz1D +// @route(path=set_group_add_request) +// @param(index=1, name="[sub_type\x2Ctype].0") +// @param(index=3, default=true) func (bot *CQBot) CQProcessGroupRequest(flag, subType, reason string, approve bool) global.MSG { msgs, err := bot.Client.GetGroupSystemMessages() if err != nil { @@ -780,6 +841,7 @@ func (bot *CQBot) CQProcessGroupRequest(flag, subType, reason string, approve bo // CQDeleteMessage 撤回消息 // // https:// git.io/Jtz1y +// @route(path=delete_msg) func (bot *CQBot) CQDeleteMessage(messageID int32) global.MSG { msg, err := db.GetMessageByGlobalID(messageID) if err != nil { @@ -810,6 +872,8 @@ func (bot *CQBot) CQDeleteMessage(messageID int32) global.MSG { // CQSetGroupAdmin 群组设置管理员 // // https://git.io/Jtz1S +// @route(path=set_group_admin) +// @param(index=2, default=true) func (bot *CQBot) CQSetGroupAdmin(groupID, userID int64, enable bool) global.MSG { group := bot.Client.FindGroup(groupID) if group == nil || group.OwnerUin != bot.Client.Uin { @@ -832,6 +896,7 @@ func (bot *CQBot) CQSetGroupAdmin(groupID, userID int64, enable bool) global.MSG // CQGetVipInfo 扩展API-获取VIP信息 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96vip%E4%BF%A1%E6%81%AF +// @route(path=_get_vip_info) func (bot *CQBot) CQGetVipInfo(userID int64) global.MSG { vip, err := bot.Client.GetVipInfo(userID) if err != nil { @@ -852,6 +917,8 @@ func (bot *CQBot) CQGetVipInfo(userID int64) global.MSG { // CQGetGroupHonorInfo 获取群荣誉信息 // // https://git.io/Jtz1H +// @route(path=get_group_honor_info) +// @param(index=1, name=type) func (bot *CQBot) CQGetGroupHonorInfo(groupID int64, t string) global.MSG { msg := global.MSG{"group_id": groupID} convertMem := func(memList []client.HonorMemberInfo) (ret []global.MSG) { @@ -909,6 +976,7 @@ func (bot *CQBot) CQGetGroupHonorInfo(groupID int64, t string) global.MSG { // CQGetStrangerInfo 获取陌生人信息 // // https://git.io/Jtz17 +// @route(path=get_stranger_info) func (bot *CQBot) CQGetStrangerInfo(userID int64) global.MSG { info, err := bot.Client.GetSummaryInfo(userID) if err != nil { @@ -936,6 +1004,7 @@ func (bot *CQBot) CQGetStrangerInfo(userID int64) global.MSG { // CQHandleQuickOperation 隐藏API-对事件执行快速操作 // // https://git.io/Jtz15 +// @route(path=".handle_quick_operation") func (bot *CQBot) CQHandleQuickOperation(context, operation gjson.Result) global.MSG { postType := context.Get("post_type").Str @@ -1025,6 +1094,7 @@ func (bot *CQBot) CQHandleQuickOperation(context, operation gjson.Result) global // CQGetImage 获取图片(修改自OneBot) // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E5%9B%BE%E7%89%87%E4%BF%A1%E6%81%AF +// @route(path=get_image) func (bot *CQBot) CQGetImage(file string) global.MSG { var b []byte var err error @@ -1070,7 +1140,27 @@ func (bot *CQBot) CQGetImage(file string) global.MSG { // CQDownloadFile 扩展API-下载文件到缓存目录 // // https://docs.go-cqhttp.org/api/#%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6%E5%88%B0%E7%BC%93%E5%AD%98%E7%9B%AE%E5%BD%95 -func (bot *CQBot) CQDownloadFile(url string, headers map[string]string, threadCount int) global.MSG { +// @route(path=download_file) +func (bot *CQBot) CQDownloadFile(url string, headers gjson.Result, threadCount int) global.MSG { + h := map[string]string{} + if headers.IsArray() { + for _, sub := range headers.Array() { + str := strings.SplitN(sub.String(), "=", 2) + if len(str) == 2 { + h[str[0]] = str[1] + } + } + } + if headers.Type == gjson.String { + lines := strings.Split(headers.String(), "\r\n") + for _, sub := range lines { + str := strings.SplitN(sub, "=", 2) + if len(str) == 2 { + h[str[0]] = str[1] + } + } + } + hash := md5.Sum([]byte(url)) file := path.Join(global.CachePath, hex.EncodeToString(hash[:])+".cache") if global.PathExists(file) { @@ -1079,7 +1169,7 @@ func (bot *CQBot) CQDownloadFile(url string, headers map[string]string, threadCo return Failed(100, "DELETE_FILE_ERROR", err.Error()) } } - if err := global.DownloadFileMultiThreading(url, file, 0, threadCount, headers); err != nil { + if err := global.DownloadFileMultiThreading(url, file, 0, threadCount, h); err != nil { log.Warnf("下载链接 %v 时出现错误: %v", url, err) return Failed(100, "DOWNLOAD_FILE_ERROR", err.Error()) } @@ -1092,6 +1182,8 @@ func (bot *CQBot) CQDownloadFile(url string, headers map[string]string, threadCo // CQGetForwardMessage 获取合并转发消息 // // https://git.io/Jtz1F +// @route(path=get_forward_msg) +// @param(index=0, name="[message_id\x2Cid].0") func (bot *CQBot) CQGetForwardMessage(resID string) global.MSG { m := bot.Client.GetForwardMessage(resID) if m == nil { @@ -1117,6 +1209,7 @@ func (bot *CQBot) CQGetForwardMessage(resID string) global.MSG { // CQGetMessage 获取消息 // // https://git.io/Jtz1b +// @route(path=get_msg) func (bot *CQBot) CQGetMessage(messageID int32) global.MSG { msg, err := db.GetMessageByGlobalID(messageID) if err != nil { @@ -1149,6 +1242,7 @@ func (bot *CQBot) CQGetMessage(messageID int32) global.MSG { // CQGetGroupSystemMessages 扩展API-获取群文件系统消息 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%BE%A4%E7%B3%BB%E7%BB%9F%E6%B6%88%E6%81%AF +// @route(path=get_group_system_msg) func (bot *CQBot) CQGetGroupSystemMessages() global.MSG { msg, err := bot.Client.GetGroupSystemMessages() if err != nil { @@ -1161,6 +1255,8 @@ func (bot *CQBot) CQGetGroupSystemMessages() global.MSG { // CQGetGroupMessageHistory 获取群消息历史记录 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%B6%88%E6%81%AF%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95 +// @route(path=get_group_msg_history) +// @param(index=1, name=message_seq) func (bot *CQBot) CQGetGroupMessageHistory(groupID int64, seq int64) global.MSG { if g := bot.Client.FindGroup(groupID); g == nil { return Failed(100, "GROUP_NOT_FOUND", "群聊不存在") @@ -1193,6 +1289,7 @@ func (bot *CQBot) CQGetGroupMessageHistory(groupID int64, seq int64) global.MSG // CQGetOnlineClients 扩展API-获取当前账号在线客户端列表 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E8%B4%A6%E5%8F%B7%E5%9C%A8%E7%BA%BF%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%88%97%E8%A1%A8 +// @route(path=get_online_clients) func (bot *CQBot) CQGetOnlineClients(noCache bool) global.MSG { if noCache { if err := bot.Client.RefreshStatus(); err != nil { @@ -1216,6 +1313,7 @@ func (bot *CQBot) CQGetOnlineClients(noCache bool) global.MSG { // CQCanSendImage 检查是否可以发送图片(此处永远返回true) // // https://git.io/Jtz1N +// @route(path=can_send_image) func (bot *CQBot) CQCanSendImage() global.MSG { return OK(global.MSG{"yes": true}) } @@ -1223,6 +1321,7 @@ func (bot *CQBot) CQCanSendImage() global.MSG { // CQCanSendRecord 检查是否可以发送语音(此处永远返回true) // // https://git.io/Jtz1x +// @route(path=can_send_record) func (bot *CQBot) CQCanSendRecord() global.MSG { return OK(global.MSG{"yes": true}) } @@ -1230,6 +1329,8 @@ func (bot *CQBot) CQCanSendRecord() global.MSG { // CQOcrImage 扩展API-图片OCR // // https://docs.go-cqhttp.org/api/#%E5%9B%BE%E7%89%87-ocr +// @route(path=ocr_image, alias=.ocr_image) +// @param(index=0, name=image) func (bot *CQBot) CQOcrImage(imageID string) global.MSG { img, err := bot.makeImageOrVideoElem(map[string]string{"file": imageID}, false, true) if err != nil { @@ -1247,6 +1348,7 @@ func (bot *CQBot) CQOcrImage(imageID string) global.MSG { // CQSetGroupPortrait 扩展API-设置群头像 // // https://docs.go-cqhttp.org/api/#%E8%AE%BE%E7%BD%AE%E7%BE%A4%E5%A4%B4%E5%83%8F +// @route(path=set_group_portrait) func (bot *CQBot) CQSetGroupPortrait(groupID int64, file, cache string) global.MSG { if g := bot.Client.FindGroup(groupID); g != nil { img, err := global.FindFile(file, cache, global.ImagePath) @@ -1263,6 +1365,8 @@ func (bot *CQBot) CQSetGroupPortrait(groupID int64, file, cache string) global.M // CQSetGroupAnonymousBan 群组匿名用户禁言 // // https://git.io/Jtz1p +// @route(path=set_group_anonymous_ban) +// @param(index=1, name="[anonymous_flag\x2Canonymous.flag].0") func (bot *CQBot) CQSetGroupAnonymousBan(groupID int64, flag string, duration int32) global.MSG { if flag == "" { return Failed(100, "INVALID_FLAG", "无效的flag") @@ -1286,6 +1390,7 @@ func (bot *CQBot) CQSetGroupAnonymousBan(groupID int64, flag string, duration in // CQGetStatus 获取运行状态 // // https://git.io/JtzMe +// @route(path=get_status) func (bot *CQBot) CQGetStatus() global.MSG { return OK(global.MSG{ "app_initialized": true, @@ -1301,6 +1406,7 @@ func (bot *CQBot) CQGetStatus() global.MSG { // CQSetEssenceMessage 扩展API-设置精华消息 // // https://docs.go-cqhttp.org/api/#%E8%AE%BE%E7%BD%AE%E7%B2%BE%E5%8D%8E%E6%B6%88%E6%81%AF +// @route(path=set_essence_msg) func (bot *CQBot) CQSetEssenceMessage(messageID int32) global.MSG { msg, err := db.GetGroupMessageByGlobalID(messageID) if err != nil { @@ -1316,6 +1422,7 @@ func (bot *CQBot) CQSetEssenceMessage(messageID int32) global.MSG { // CQDeleteEssenceMessage 扩展API-移出精华消息 // // https://docs.go-cqhttp.org/api/#%E7%A7%BB%E5%87%BA%E7%B2%BE%E5%8D%8E%E6%B6%88%E6%81%AF +// @route(path=delete_essence_msg) func (bot *CQBot) CQDeleteEssenceMessage(messageID int32) global.MSG { msg, err := db.GetGroupMessageByGlobalID(messageID) if err != nil { @@ -1331,12 +1438,13 @@ func (bot *CQBot) CQDeleteEssenceMessage(messageID int32) global.MSG { // CQGetEssenceMessageList 扩展API-获取精华消息列表 // // https://docs.go-cqhttp.org/api/#%E8%8E%B7%E5%8F%96%E7%B2%BE%E5%8D%8E%E6%B6%88%E6%81%AF%E5%88%97%E8%A1%A8 -func (bot *CQBot) CQGetEssenceMessageList(groupCode int64) global.MSG { - g := bot.Client.FindGroup(groupCode) +// @route(path=get_essence_msg_list) +func (bot *CQBot) CQGetEssenceMessageList(groupID int64) global.MSG { + g := bot.Client.FindGroup(groupID) if g == nil { return Failed(100, "GROUP_NOT_FOUND", "群聊不存在") } - msgList, err := bot.Client.GetGroupEssenceMsgList(groupCode) + msgList, err := bot.Client.GetGroupEssenceMsgList(groupID) if err != nil { return Failed(100, "GET_ESSENCE_LIST_FOUND", err.Error()) } @@ -1350,7 +1458,7 @@ func (bot *CQBot) CQGetEssenceMessageList(groupCode int64) global.MSG { "sender_id": m.SenderUin, "operator_id": m.AddDigestUin, } - msg["message_id"] = db.ToGlobalID(groupCode, int32(m.MessageID)) + msg["message_id"] = db.ToGlobalID(groupID, int32(m.MessageID)) list = append(list, msg) } return OK(list) @@ -1359,6 +1467,7 @@ func (bot *CQBot) CQGetEssenceMessageList(groupCode int64) global.MSG { // CQCheckURLSafely 扩展API-检查链接安全性 // // https://docs.go-cqhttp.org/api/#%E6%A3%80%E6%9F%A5%E9%93%BE%E6%8E%A5%E5%AE%89%E5%85%A8%E6%80%A7 +// @route(path=check_url_safely) func (bot *CQBot) CQCheckURLSafely(url string) global.MSG { return OK(global.MSG{ "level": bot.Client.CheckUrlSafely(url), @@ -1368,6 +1477,7 @@ func (bot *CQBot) CQCheckURLSafely(url string) global.MSG { // CQGetVersionInfo 获取版本信息 // // https://git.io/JtwUs +// @route(path=get_version_info) func (bot *CQBot) CQGetVersionInfo() global.MSG { wd, _ := os.Getwd() return OK(global.MSG{ @@ -1406,8 +1516,9 @@ func (bot *CQBot) CQGetVersionInfo() global.MSG { // CQGetModelShow 获取在线机型 // // https://club.vip.qq.com/onlinestatus/set -func (bot *CQBot) CQGetModelShow(modelName string) global.MSG { - variants, err := bot.Client.GetModelShow(modelName) +// @route(path=_get_model_show) +func (bot *CQBot) CQGetModelShow(model string) global.MSG { + variants, err := bot.Client.GetModelShow(model) if err != nil { return Failed(100, "GET_MODEL_SHOW_API_ERROR", "无法获取在线机型") } @@ -1426,8 +1537,9 @@ func (bot *CQBot) CQGetModelShow(modelName string) global.MSG { // CQSetModelShow 设置在线机型 // // https://club.vip.qq.com/onlinestatus/set -func (bot *CQBot) CQSetModelShow(modelName string, modelShow string) global.MSG { - err := bot.Client.SetModelShow(modelName, modelShow) +// @route(path=_set_model_show) +func (bot *CQBot) CQSetModelShow(model, modelShow string) global.MSG { + err := bot.Client.SetModelShow(model, modelShow) if err != nil { return Failed(100, "SET_MODEL_SHOW_API_ERROR", "无法设置在线机型") } @@ -1435,6 +1547,8 @@ func (bot *CQBot) CQSetModelShow(modelName string, modelShow string) global.MSG } // CQMarkMessageAsRead 标记消息已读 +// @route(path=mark_msg_as_read) +// @param(index=0, name=message_id) func (bot *CQBot) CQMarkMessageAsRead(msgID int32) global.MSG { m, err := db.GetMessageByGlobalID(msgID) if err != nil { @@ -1450,6 +1564,14 @@ func (bot *CQBot) CQMarkMessageAsRead(msgID int32) global.MSG { return OK(nil) } +// CQReloadEventFilter 重载事件过滤器 +// +// @route(path=reload_event_filter) +func (bot *CQBot) CQReloadEventFilter(file string) global.MSG { + filter.Add(file) + return OK(nil) +} + // OK 生成成功返回值 func OK(data interface{}) global.MSG { return global.MSG{"data": data, "retcode": 0, "status": "ok"} diff --git a/modules/api/api.go b/modules/api/api.go index 98f022d..5bf68e4 100644 --- a/modules/api/api.go +++ b/modules/api/api.go @@ -1,463 +1,261 @@ -// Package api implements the API route for servers. +// Code generated by cmd/api-generator. DO NOT EDIT. + package api import ( - "strings" - - "github.com/tidwall/gjson" - "github.com/Mrs4s/go-cqhttp/coolq" "github.com/Mrs4s/go-cqhttp/global" - "github.com/Mrs4s/go-cqhttp/internal/param" - "github.com/Mrs4s/go-cqhttp/modules/filter" ) -// Getter 参数获取 -type Getter interface { - Get(string) gjson.Result -} - -// Handler 中间件 -type Handler func(action string, p Getter) global.MSG - -// Caller api route caller -type Caller struct { - bot *coolq.CQBot - handlers []Handler -} - -func getLoginInfo(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQGetLoginInfo() -} - -func getQiDianAccountInfo(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQGetQiDianAccountInfo() -} - -func getFriendList(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQGetFriendList() -} - -func getUnidirectionalFriendList(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQGetUnidirectionalFriendList() -} - -func deleteFriend(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQDeleteFriend(p.Get("[user_id,id].0").Int()) -} - -func deleteUnidirectionalFriend(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQDeleteUnidirectionalFriend(p.Get("user_id").Int()) -} - -func getGroupList(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupList(p.Get("no_cache").Bool()) -} - -func getGroupInfo(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupInfo(p.Get("group_id").Int(), p.Get("no_cache").Bool()) -} - -func getGroupMemberList(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupMemberList(p.Get("group_id").Int(), p.Get("no_cache").Bool()) -} - -func getGroupMemberInfo(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupMemberInfo( - p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("no_cache").Bool(), - ) -} - -func sendMSG(bot *coolq.CQBot, p Getter) global.MSG { - autoEscape := param.EnsureBool(p.Get("auto_escape"), false) - if p.Get("message_type").Str == "private" { - return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("group_id").Int(), p.Get("message"), autoEscape) - } - if p.Get("message_type").Str == "group" { - return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message"), autoEscape) - } - if p.Get("user_id").Int() != 0 { - return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("group_id").Int(), p.Get("message"), autoEscape) - } - if p.Get("group_id").Int() != 0 { - return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message"), autoEscape) - } - return global.MSG{} -} - -func sendGroupMSG(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message"), - param.EnsureBool(p.Get("auto_escape"), false)) -} - -func sendGroupForwardMSG(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSendGroupForwardMessage(p.Get("group_id").Int(), p.Get("messages")) -} - -func sendPrivateMSG(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("group_id").Int(), p.Get("message"), - param.EnsureBool(p.Get("auto_escape"), false)) -} - -func deleteMSG(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQDeleteMessage(int32(p.Get("message_id").Int())) -} - -func setFriendAddRequest(bot *coolq.CQBot, p Getter) global.MSG { - apr := true - if p.Get("approve").Exists() { - apr = p.Get("approve").Bool() - } - return bot.CQProcessFriendRequest(p.Get("flag").Str, apr) -} - -func setGroupAddRequest(bot *coolq.CQBot, p Getter) global.MSG { - subType := p.Get("sub_type").Str - apr := true - if subType == "" { - subType = p.Get("type").Str - } - if p.Get("approve").Exists() { - apr = p.Get("approve").Bool() - } - return bot.CQProcessGroupRequest(p.Get("flag").Str, subType, p.Get("reason").Str, apr) -} - -func setGroupCard(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupCard(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("card").Str) -} - -func setGroupSpecialTitle(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupSpecialTitle(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("special_title").Str) -} - -func setGroupKick(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupKick(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("message").Str, p.Get("reject_add_request").Bool()) -} - -func setGroupBan(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupBan(p.Get("group_id").Int(), p.Get("user_id").Int(), func() uint32 { - if p.Get("duration").Exists() { - return uint32(p.Get("duration").Int()) +func (c *Caller) call(action string, p Getter) global.MSG { + switch action { + default: + return coolq.Failed(404, "API_NOT_FOUND", "API不存在") + case ".get_word_slices": + p0 := p.Get("content").String() + return c.bot.CQGetWordSlices(p0) + case ".handle_quick_operation": + p0 := p.Get("context") + p1 := p.Get("operation") + return c.bot.CQHandleQuickOperation(p0, p1) + case "_get_model_show": + p0 := p.Get("model").String() + return c.bot.CQGetModelShow(p0) + case "_get_vip_info": + p0 := p.Get("user_id").Int() + return c.bot.CQGetVipInfo(p0) + case "_send_group_notice": + p0 := p.Get("group_id").Int() + p1 := p.Get("content").String() + p2 := p.Get("image").String() + return c.bot.CQSetGroupMemo(p0, p1, p2) + case "_set_model_show": + p0 := p.Get("model").String() + p1 := p.Get("model_show").String() + return c.bot.CQSetModelShow(p0, p1) + case "can_send_image": + return c.bot.CQCanSendImage() + case "can_send_record": + return c.bot.CQCanSendRecord() + case "check_url_safely": + p0 := p.Get("url").String() + return c.bot.CQCheckURLSafely(p0) + case "create_group_file_folder": + p0 := p.Get("group_id").Int() + p1 := p.Get("parent_id").String() + p2 := p.Get("name").String() + return c.bot.CQGroupFileCreateFolder(p0, p1, p2) + case "delete_essence_msg": + p0 := int32(p.Get("message_id").Int()) + return c.bot.CQDeleteEssenceMessage(p0) + case "delete_friend": + p0 := p.Get("[user_id,id].0").Int() + return c.bot.CQDeleteFriend(p0) + case "delete_group_file": + p0 := p.Get("group_id").Int() + p1 := p.Get("file_id").String() + p2 := int32(p.Get("bus_id").Int()) + return c.bot.CQGroupFileDeleteFile(p0, p1, p2) + case "delete_group_folder": + p0 := p.Get("group_id").Int() + p1 := p.Get("folder_id").String() + return c.bot.CQGroupFileDeleteFolder(p0, p1) + case "delete_msg": + p0 := int32(p.Get("message_id").Int()) + return c.bot.CQDeleteMessage(p0) + case "delete_unidirectional_friend": + p0 := p.Get("user_id").Int() + return c.bot.CQDeleteUnidirectionalFriend(p0) + case "download_file": + p0 := p.Get("url").String() + p1 := p.Get("headers") + p2 := int(p.Get("thread_count").Int()) + return c.bot.CQDownloadFile(p0, p1, p2) + case "get_essence_msg_list": + p0 := p.Get("group_id").Int() + return c.bot.CQGetEssenceMessageList(p0) + case "get_forward_msg": + p0 := p.Get("[message_id,id].0").String() + return c.bot.CQGetForwardMessage(p0) + case "get_friend_list": + return c.bot.CQGetFriendList() + case "get_group_at_all_remain": + p0 := p.Get("group_id").Int() + return c.bot.CQGetAtAllRemain(p0) + case "get_group_file_system_info": + p0 := p.Get("group_id").Int() + return c.bot.CQGetGroupFileSystemInfo(p0) + case "get_group_file_url": + p0 := p.Get("group_id").Int() + p1 := p.Get("file_id").String() + p2 := int32(p.Get("bus_id").Int()) + return c.bot.CQGetGroupFileURL(p0, p1, p2) + case "get_group_files_by_folder": + p0 := p.Get("group_id").Int() + p1 := p.Get("folder_id").String() + return c.bot.CQGetGroupFilesByFolderID(p0, p1) + case "get_group_honor_info": + p0 := p.Get("group_id").Int() + p1 := p.Get("type").String() + return c.bot.CQGetGroupHonorInfo(p0, p1) + case "get_group_info": + p0 := p.Get("group_id").Int() + p1 := p.Get("no_cache").Bool() + return c.bot.CQGetGroupInfo(p0, p1) + case "get_group_list": + p0 := p.Get("no_cache").Bool() + return c.bot.CQGetGroupList(p0) + case "get_group_member_info": + p0 := p.Get("group_id").Int() + p1 := p.Get("user_id").Int() + p2 := p.Get("no_cache").Bool() + return c.bot.CQGetGroupMemberInfo(p0, p1, p2) + case "get_group_member_list": + p0 := p.Get("group_id").Int() + p1 := p.Get("no_cache").Bool() + return c.bot.CQGetGroupMemberList(p0, p1) + case "get_group_msg_history": + p0 := p.Get("group_id").Int() + p1 := p.Get("message_seq").Int() + return c.bot.CQGetGroupMessageHistory(p0, p1) + case "get_group_root_files": + p0 := p.Get("group_id").Int() + return c.bot.CQGetGroupRootFiles(p0) + case "get_group_system_msg": + return c.bot.CQGetGroupSystemMessages() + case "get_image": + p0 := p.Get("file").String() + return c.bot.CQGetImage(p0) + case "get_login_info": + return c.bot.CQGetLoginInfo() + case "get_msg": + p0 := int32(p.Get("message_id").Int()) + return c.bot.CQGetMessage(p0) + case "get_online_clients": + p0 := p.Get("no_cache").Bool() + return c.bot.CQGetOnlineClients(p0) + case "get_status": + return c.bot.CQGetStatus() + case "get_stranger_info": + p0 := p.Get("user_id").Int() + return c.bot.CQGetStrangerInfo(p0) + case "get_unidirectional_friend_list": + return c.bot.CQGetUnidirectionalFriendList() + case "get_version_info": + return c.bot.CQGetVersionInfo() + case "mark_msg_as_read": + p0 := int32(p.Get("message_id").Int()) + return c.bot.CQMarkMessageAsRead(p0) + case "ocr_image", ".ocr_image": + p0 := p.Get("image").String() + return c.bot.CQOcrImage(p0) + case "qidian_get_account_info": + return c.bot.CQGetQiDianAccountInfo() + case "reload_event_filter": + p0 := p.Get("file").String() + return c.bot.CQReloadEventFilter(p0) + case "send_group_forward_msg": + p0 := p.Get("group_id").Int() + p1 := p.Get("messages") + return c.bot.CQSendGroupForwardMessage(p0, p1) + case "send_group_msg": + p0 := p.Get("group_id").Int() + p1 := p.Get("message") + p2 := p.Get("auto_escape").Bool() + return c.bot.CQSendGroupMessage(p0, p1, p2) + case "send_msg": + p0 := p.Get("group_id").Int() + p1 := p.Get("user_id").Int() + p2 := p.Get("message") + p3 := p.Get("message_type").String() + p4 := p.Get("auto_escape").Bool() + return c.bot.CQSendMessage(p0, p1, p2, p3, p4) + case "send_private_msg": + p0 := p.Get("user_id").Int() + p1 := p.Get("group_id").Int() + p2 := p.Get("message") + p3 := p.Get("auto_escape").Bool() + return c.bot.CQSendPrivateMessage(p0, p1, p2, p3) + case "set_essence_msg": + p0 := int32(p.Get("message_id").Int()) + return c.bot.CQSetEssenceMessage(p0) + case "set_friend_add_request": + p0 := p.Get("flag").String() + p1 := true + if pt := p.Get("approve"); pt.Exists() { + p1 = pt.Bool() } - return 1800 - }()) -} - -func setGroupWholeBan(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupWholeBan(p.Get("group_id").Int(), func() bool { - if p.Get("enable").Exists() { - return p.Get("enable").Bool() + return c.bot.CQProcessFriendRequest(p0, p1) + case "set_group_add_request": + p0 := p.Get("flag").String() + p1 := p.Get("[sub_type,type].0").String() + p2 := p.Get("reason").String() + p3 := true + if pt := p.Get("approve"); pt.Exists() { + p3 = pt.Bool() } - return true - }()) -} - -func setGroupName(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupName(p.Get("group_id").Int(), p.Get("group_name").Str) -} - -func setGroupAdmin(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupAdmin(p.Get("group_id").Int(), p.Get("user_id").Int(), func() bool { - if p.Get("enable").Exists() { - return p.Get("enable").Bool() + return c.bot.CQProcessGroupRequest(p0, p1, p2, p3) + case "set_group_admin": + p0 := p.Get("group_id").Int() + p1 := p.Get("user_id").Int() + p2 := true + if pt := p.Get("enable"); pt.Exists() { + p2 = pt.Bool() } - return true - }()) -} - -func sendGroupNotice(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupMemo(p.Get("group_id").Int(), p.Get("content").Str, p.Get("image").String()) -} - -func setGroupLeave(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupLeave(p.Get("group_id").Int()) -} - -func getImage(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetImage(p.Get("file").Str) -} - -func getForwardMSG(bot *coolq.CQBot, p Getter) global.MSG { - id := p.Get("message_id").Str - if id == "" { - id = p.Get("id").Str - } - return bot.CQGetForwardMessage(id) -} - -func getMSG(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetMessage(int32(p.Get("message_id").Int())) -} - -func downloadFile(bot *coolq.CQBot, p Getter) global.MSG { - headers := map[string]string{} - headersToken := p.Get("headers") - if headersToken.IsArray() { - for _, sub := range headersToken.Array() { - str := strings.SplitN(sub.String(), "=", 2) - if len(str) == 2 { - headers[str[0]] = str[1] - } + return c.bot.CQSetGroupAdmin(p0, p1, p2) + case "set_group_anonymous_ban": + p0 := p.Get("group_id").Int() + p1 := p.Get("[anonymous_flag,anonymous.flag].0").String() + p2 := int32(p.Get("duration").Int()) + return c.bot.CQSetGroupAnonymousBan(p0, p1, p2) + case "set_group_ban": + p0 := p.Get("group_id").Int() + p1 := p.Get("user_id").Int() + p2 := uint32(1800) + if pt := p.Get("duration"); pt.Exists() { + p2 = uint32(pt.Int()) } - } - if headersToken.Type == gjson.String { - lines := strings.Split(headersToken.String(), "\r\n") - for _, sub := range lines { - str := strings.SplitN(sub, "=", 2) - if len(str) == 2 { - headers[str[0]] = str[1] - } + return c.bot.CQSetGroupBan(p0, p1, p2) + case "set_group_card": + p0 := p.Get("group_id").Int() + p1 := p.Get("user_id").Int() + p2 := p.Get("card").String() + return c.bot.CQSetGroupCard(p0, p1, p2) + case "set_group_kick": + p0 := p.Get("group_id").Int() + p1 := p.Get("user_id").Int() + p2 := p.Get("message").String() + p3 := p.Get("reject_add_request").Bool() + return c.bot.CQSetGroupKick(p0, p1, p2, p3) + case "set_group_leave": + p0 := p.Get("group_id").Int() + return c.bot.CQSetGroupLeave(p0) + case "set_group_name": + p0 := p.Get("group_id").Int() + p1 := p.Get("group_name").String() + return c.bot.CQSetGroupName(p0, p1) + case "set_group_portrait": + p0 := p.Get("group_id").Int() + p1 := p.Get("file").String() + p2 := p.Get("cache").String() + return c.bot.CQSetGroupPortrait(p0, p1, p2) + case "set_group_special_title": + p0 := p.Get("group_id").Int() + p1 := p.Get("user_id").Int() + p2 := p.Get("title").String() + return c.bot.CQSetGroupSpecialTitle(p0, p1, p2) + case "set_group_whole_ban": + p0 := p.Get("group_id").Int() + p1 := true + if pt := p.Get("enable"); pt.Exists() { + p1 = pt.Bool() } - } - return bot.CQDownloadFile(p.Get("url").Str, headers, int(p.Get("thread_count").Int())) -} - -func getGroupHonorInfo(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupHonorInfo(p.Get("group_id").Int(), p.Get("type").Str) -} - -func setRestart(_ *coolq.CQBot, _ Getter) global.MSG { - /* - var delay int64 - delay = p.Get("delay").Int() - if delay < 0 { - delay = 0 - } - defer func(delay int64) { - time.Sleep(time.Duration(delay) * time.Millisecond) - Restart <- struct{}{} - }(delay) - */ - return global.MSG{"data": nil, "retcode": 99, "msg": "restart un-supported now", "wording": "restart函数暂不兼容", "status": "failed"} -} - -func canSendImage(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQCanSendImage() -} - -func canSendRecord(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQCanSendRecord() -} - -func getStrangerInfo(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetStrangerInfo(p.Get("user_id").Int()) -} - -func getStatus(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQGetStatus() -} - -func getVersionInfo(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQGetVersionInfo() -} - -func getGroupSystemMSG(bot *coolq.CQBot, _ Getter) global.MSG { - return bot.CQGetGroupSystemMessages() -} - -func getGroupFileSystemInfo(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupFileSystemInfo(p.Get("group_id").Int()) -} - -func getGroupRootFiles(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupRootFiles(p.Get("group_id").Int()) -} - -func getGroupFilesByFolder(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupFilesByFolderID(p.Get("group_id").Int(), p.Get("folder_id").Str) -} - -func getGroupFileURL(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupFileURL(p.Get("group_id").Int(), p.Get("file_id").Str, int32(p.Get("busid").Int())) -} - -func uploadGroupFile(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQUploadGroupFile(p.Get("group_id").Int(), p.Get("file").Str, p.Get("name").Str, p.Get("folder").Str) -} - -func groupFileCreateFolder(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGroupFileCreateFolder(p.Get("group_id").Int(), p.Get("folder_id").Str, p.Get("name").Str) -} - -func deleteGroupFolder(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGroupFileDeleteFolder(p.Get("group_id").Int(), p.Get("folder_id").Str) -} - -func deleteGroupFile(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGroupFileDeleteFile(p.Get("group_id").Int(), p.Get("file_id").Str, int32(p.Get("bus_id").Int())) -} - -func getGroupMsgHistory(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetGroupMessageHistory(p.Get("group_id").Int(), p.Get("message_seq").Int()) -} - -func getVipInfo(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetVipInfo(p.Get("user_id").Int()) -} - -func reloadEventFilter(_ *coolq.CQBot, p Getter) global.MSG { - filter.Add(p.Get("file").String()) - return coolq.OK(nil) -} - -func getGroupAtAllRemain(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetAtAllRemain(p.Get("group_id").Int()) -} - -func ocrImage(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQOcrImage(p.Get("image").Str) -} - -func getOnlineClients(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetOnlineClients(p.Get("no_cache").Bool()) -} - -func getWordSlices(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetWordSlices(p.Get("content").Str) -} - -func setGroupPortrait(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetGroupPortrait(p.Get("group_id").Int(), p.Get("file").String(), p.Get("cache").String()) -} - -func setEssenceMSG(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetEssenceMessage(int32(p.Get("message_id").Int())) -} - -func deleteEssenceMSG(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQDeleteEssenceMessage(int32(p.Get("message_id").Int())) -} - -func getEssenceMsgList(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetEssenceMessageList(p.Get("group_id").Int()) -} - -func checkURLSafely(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQCheckURLSafely(p.Get("url").String()) -} - -func setGroupAnonymousBan(bot *coolq.CQBot, p Getter) global.MSG { - obj := p.Get("anonymous") - flag := p.Get("anonymous_flag") - if !flag.Exists() { - flag = p.Get("flag") - } - if !flag.Exists() && !obj.Exists() { - return coolq.Failed(100, "FLAG_NOT_FOUND", "flag未找到") - } - if !flag.Exists() { - flag = obj.Get("flag") - } - return bot.CQSetGroupAnonymousBan(p.Get("group_id").Int(), flag.String(), int32(p.Get("duration").Int())) -} - -func handleQuickOperation(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQHandleQuickOperation(p.Get("context"), p.Get("operation")) -} - -func getModelShow(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQGetModelShow(p.Get("model").String()) -} - -func setModelShow(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQSetModelShow(p.Get("model").String(), p.Get("model_show").String()) -} - -func markMSGAsRead(bot *coolq.CQBot, p Getter) global.MSG { - return bot.CQMarkMessageAsRead(int32(p.Get("message_id").Int())) -} - -// API 是go-cqhttp当前支持的所有api的映射表 -var API = map[string]func(*coolq.CQBot, Getter) global.MSG{ - "get_login_info": getLoginInfo, - "get_friend_list": getFriendList, - "get_unidirectional_friend_list": getUnidirectionalFriendList, - "delete_friend": deleteFriend, - "delete_unidirectional_friend": deleteUnidirectionalFriend, - "get_group_list": getGroupList, - "get_group_info": getGroupInfo, - "get_group_member_list": getGroupMemberList, - "get_group_member_info": getGroupMemberInfo, - "send_msg": sendMSG, - "send_group_msg": sendGroupMSG, - "send_group_forward_msg": sendGroupForwardMSG, - "send_private_msg": sendPrivateMSG, - "delete_msg": deleteMSG, - "set_friend_add_request": setFriendAddRequest, - "set_group_add_request": setGroupAddRequest, - "set_group_card": setGroupCard, - "set_group_special_title": setGroupSpecialTitle, - "set_group_kick": setGroupKick, - "set_group_ban": setGroupBan, - "set_group_whole_ban": setGroupWholeBan, - "set_group_name": setGroupName, - "set_group_admin": setGroupAdmin, - "_send_group_notice": sendGroupNotice, - "set_group_leave": setGroupLeave, - "get_image": getImage, - "get_forward_msg": getForwardMSG, - "get_msg": getMSG, - "download_file": downloadFile, - "get_group_honor_info": getGroupHonorInfo, - "set_restart": setRestart, - "can_send_image": canSendImage, - "can_send_record": canSendRecord, - "get_stranger_info": getStrangerInfo, - "get_status": getStatus, - "get_version_info": getVersionInfo, - "get_group_system_msg": getGroupSystemMSG, - "get_group_file_system_info": getGroupFileSystemInfo, - "get_group_root_files": getGroupRootFiles, - "get_group_files_by_folder": getGroupFilesByFolder, - "get_group_file_url": getGroupFileURL, - "create_group_file_folder": groupFileCreateFolder, - "delete_group_folder": deleteGroupFolder, - "delete_group_file": deleteGroupFile, - "upload_group_file": uploadGroupFile, - "get_group_msg_history": getGroupMsgHistory, - "_get_vip_info": getVipInfo, - "reload_event_filter": reloadEventFilter, - ".ocr_image": ocrImage, - "ocr_image": ocrImage, - "get_group_at_all_remain": getGroupAtAllRemain, - "get_online_clients": getOnlineClients, - ".get_word_slices": getWordSlices, - "set_group_portrait": setGroupPortrait, - "set_essence_msg": setEssenceMSG, - "delete_essence_msg": deleteEssenceMSG, - "get_essence_msg_list": getEssenceMsgList, - "check_url_safely": checkURLSafely, - "set_group_anonymous_ban": setGroupAnonymousBan, - ".handle_quick_operation": handleQuickOperation, - "qidian_get_account_info": getQiDianAccountInfo, - "_get_model_show": getModelShow, - "_set_model_show": setModelShow, - "mark_msg_as_read": markMSGAsRead, -} - -// Call specific API -func (api *Caller) Call(action string, p Getter) global.MSG { - for _, fn := range api.handlers { - if ret := fn(action, p); ret != nil { - return ret - } - } - if f, ok := API[action]; ok { - return f(api.bot, p) - } - return coolq.Failed(404, "API_NOT_FOUND", "API不存在") -} - -// Use add handlers to the API caller -func (api *Caller) Use(middlewares ...Handler) { - api.handlers = append(api.handlers, middlewares...) -} - -// NewCaller create a new API caller -func NewCaller(bot *coolq.CQBot) *Caller { - return &Caller{ - bot: bot, - handlers: make([]Handler, 0), + return c.bot.CQSetGroupWholeBan(p0, p1) + case "upload_group_file": + p0 := p.Get("group_id").Int() + p1 := p.Get("file").String() + p2 := p.Get("name").String() + p3 := p.Get("folder").String() + return c.bot.CQUploadGroupFile(p0, p1, p2, p3) } } diff --git a/modules/api/caller.go b/modules/api/caller.go new file mode 100644 index 0000000..ee4fea1 --- /dev/null +++ b/modules/api/caller.go @@ -0,0 +1,48 @@ +// Package api implements the API route for servers. +package api + +import ( + "github.com/tidwall/gjson" + + "github.com/Mrs4s/go-cqhttp/coolq" + "github.com/Mrs4s/go-cqhttp/global" +) + +//go:generate go run github.com/Mrs4s/go-cqhttp/cmd/api-generator -path=./../../coolq/api.go + +// Getter 参数获取 +type Getter interface { + Get(string) gjson.Result +} + +// Handler 中间件 +type Handler func(action string, p Getter) global.MSG + +// Caller api route caller +type Caller struct { + bot *coolq.CQBot + handlers []Handler +} + +// Call specific API +func (c *Caller) Call(action string, p Getter) global.MSG { + for _, fn := range c.handlers { + if ret := fn(action, p); ret != nil { + return ret + } + } + return c.call(action, p) +} + +// Use add handlers to the API caller +func (c *Caller) Use(middlewares ...Handler) { + c.handlers = append(c.handlers, middlewares...) +} + +// NewCaller create a new API caller +func NewCaller(bot *coolq.CQBot) *Caller { + return &Caller{ + bot: bot, + handlers: make([]Handler, 0), + } +}