diff --git a/clients/gohttp/README.md b/clients/gohttp/README.md index d952f33..a42688a 100644 --- a/clients/gohttp/README.md +++ b/clients/gohttp/README.md @@ -1,44 +1,54 @@ -# 微信 REST API +# WeChat Rest 基于 [WeChatFerry RPC](https://github.com/lich0821/WeChatFerry/tree/master/WeChatFerry) 实现,主要特性如下: - 使用 Go 语言编写,无运行时依赖 -- 基于 HTTP 提供操作接口,无缝对接大多数编程语言 -- 支持 HTTP 接口授权,参见 [配置说明](#配置说明) -- 消息中的 Xml 尽可能转为 Object +- 提供 HTTP 接口,便于对接各类编程语言 +- 提供 Websocket 接口,接收推送的新消息 +- 支持 HTTP/WS 接口授权,参见 [配置说明](#配置说明) +- 支持作为 SDK 使用,参见 [wcferry/README.md](https://github.com/opentdp/wechat-rest/wcferry/README.md) +- 内置 AI 机器人,参见 [wclient/README.md](https://github.com/opentdp/wechat-rest/wclient/README.md) +- 内置 Web 管理界面,参见 `http://localhost:7600/` +- 内置 Api 调试工具,参见 `http://localhost:7600/swagger/` +- 尽可能将消息中的 Xml 转为 Object,便于前端解析 -> 此源码仅提供 HTTP REST API 能力,其他能力可参考 [wechat-rest](https://github.com/opentdp/wechat-rest) 相关说明 +> 为保证客户端纯粹性,此包仅提供 HTTP 和 Websocket 接口能力,完整功能可参考 [wechat-rest](https://github.com/opentdp/wechat-rest) 项目说明 -## 使用方法 +## 快速开始 -1、下载并安装 [WeChatSetup-3.9.2.23](https://github.com/opentdp/wechat-rest/releases/download/v0.0.1/WeChatSetup-3.9.2.23.exe),其他版本不支持 +1、下载并安装 [WeChatSetup-3.9.2.23.exe](https://github.com/opentdp/wechat-rest/releases/download/v0.0.1/WeChatSetup-3.9.2.23.exe) 和 [wechat-rest.zip](https://github.com/opentdp/wechat-rest/releases) -2、下载 [WeChatFerry](https://github.com/lich0821/WeChatFerry/releases),解压后,将2个dll文件复制到当前目录,其他文件可忽略 +- 非开发者请直接下载编译好的二进制文件,不要下载源码 -3、双击 `start.bat` 将自动启动微信和接口服务,扫码登录 +2、双击 `wrest.exe` 将自动启动微信和接口服务,扫码登录微信 -> 初始化时出现 **Attempt to access invalid address** 错误信息可以忽略 +- 初始化时若出现 *Attempt to access invalid address* 信息可忽略 -4、浏览器打开 `http://localhost:7600` 查看支持的接口 +3、修改 [config.yml](./config.yml) 配置机器人参数,重启 **wrest.exe** 后生效 + +- 请使用 `Ctrl + C` 终止 **wrest.exe**,切勿直接关闭任务窗口 +- 重启时,提示端口被占用,请退出微信后重试 ## 配置说明 -启动 `wrest` 时将自动创建一个默认配置文件,完整配置说明可参考开源仓库中的 [config.yml](./config.yml) +启动时将自动创建一个默认配置文件,完整配置可参考开源仓库中的 [config.yml](./config.yml) -- 应使用 `Ctrl + C` 终止 **wrest**,而非直接关闭 **wrest** 窗口 -- 若设置了 `token`,请求时需携带 **header** 信息: `Authorization: Bearer $token` +- 如设置了 `token`,请求接口时需携带 **header** 信息: `Authorization: Bearer $token` ## 开发说明 -### 编译须知 +- 查看和调试*HTTP*接口文档,请使用浏览器打开 `http://localhost:7600` -由于微信和WCF均为32位应用,所以`go`也必须以`32`位模式编译,务必设置 `GOARCH` 环境变量为 `386` +- 由于微信和*WCF*均为32位应用,对接*bot*和*sdk*部分,必须设置环境变量 `GOARCH=386` -### 生成 OpenApi 文档 +### API 模块 -```shell -go get github.com/swaggo/swag/cmd/swag -go install github.com/swaggo/swag/cmd/swag +实现了 HTTP 接口,详情查看 [httpd/README.md](https://github.com/opentdp/wechat-rest/httpd/README.md) -swag init --parseDependency -g httpd/server.go -o public/swag -ot json -``` +### BOT 模块 + +实现了群聊机器人,详情查看 [wclient/README.md](https://github.com/opentdp/wechat-rest/wclient/README.md) + +### SDK 模块 + +实现了 WCF 客户端,详情查看 [wcferry/README.md](https://github.com/opentdp/wechat-rest/wcferry/README.md) diff --git a/clients/gohttp/args/args.go b/clients/gohttp/args/args.go index edb5a3b..0a44cae 100644 --- a/clients/gohttp/args/args.go +++ b/clients/gohttp/args/args.go @@ -1,31 +1,8 @@ package args -import ( - "embed" -) +// 日志配置 -// 调试模式 - -var Debug bool - -// 嵌入目录 - -var Efs *embed.FS - -// Http 服务参数 - -var Httpd = struct { - Address string `yaml:"address"` - Token string `yaml:"token"` - Swag bool `yaml:"swag"` -}{ - Address: "127.0.0.1:7600", - Swag: true, -} - -// 日志参数 - -var Logger = struct { +var Log = struct { Dir string `yaml:"dir"` Level string `yaml:"level"` Target string `yaml:"target"` @@ -35,14 +12,24 @@ var Logger = struct { Target: "stdout", } -// Wcf 服务参数 +// Web 服务 + +var Web = struct { + Address string `yaml:"address"` + Swagger bool `yaml:"swagger"` + Token string `yaml:"token"` +}{ + Address: "127.0.0.1:7600", + Swagger: true, +} + +// Wcf 服务 var Wcf = struct { Address string `yaml:"address"` - SdkLibrary string `yaml:"sdkLibrary"` WeChatAuto bool `yaml:"wechatAuto"` MsgPrinter bool `yaml:"msgPrinter"` }{ - Address: "127.0.0.1:10080", - SdkLibrary: "sdk.dll", + Address: "127.0.0.1:7601", + WeChatAuto: true, } diff --git a/clients/gohttp/args/build.go b/clients/gohttp/args/build.go new file mode 100644 index 0000000..376fb04 --- /dev/null +++ b/clients/gohttp/args/build.go @@ -0,0 +1,31 @@ +package args + +import ( + "embed" +) + +// 调试模式 + +var Debug bool + +// 嵌入目录 + +var Efs *embed.FS + +// 版本信息 + +const Version = "0.10.0" +const BuildVersion = "240106" + +// 应用描述 + +const AppName = "TDP Wrest" +const AppSummary = "智能聊天机器人" + +// 输出说明 +func init() { + + println(AppName, AppSummary) + println("Version:", Version, "build", BuildVersion) + +} diff --git a/clients/gohttp/args/unmarshal.go b/clients/gohttp/args/unmarshal.go index 492cd1f..18caabe 100644 --- a/clients/gohttp/args/unmarshal.go +++ b/clients/gohttp/args/unmarshal.go @@ -12,9 +12,9 @@ func (c *Config) Unmarshal() { // 读取默认配置 mp := map[string]any{ - "httpd": &Httpd, - "logger": &Logger, - "wcf": &Wcf, + "log": &Log, + "web": &Web, + "wcf": &Wcf, } c.Koanf.Load(confmap.Provider(mp, "."), nil) @@ -27,14 +27,14 @@ func (c *Config) Unmarshal() { // 初始化日志 - if Logger.Dir != "" && Logger.Dir != "." { - os.MkdirAll(Logger.Dir, 0755) + if Log.Dir != "" && Log.Dir != "." { + os.MkdirAll(Log.Dir, 0755) } logman.SetDefault(&logman.Config{ - Level: Logger.Level, - Target: Logger.Target, - Storage: Logger.Dir, + Level: Log.Level, + Target: Log.Target, + Storage: Log.Dir, Filename: "wrest", }) diff --git a/clients/gohttp/config.yml b/clients/gohttp/config.yml index b5859ea..5bf5f81 100644 --- a/clients/gohttp/config.yml +++ b/clients/gohttp/config.yml @@ -1,18 +1,17 @@ -# HTTP 接口 -httpd: - address: 127.0.0.1:7600 # Api 监听地址 - token: "" # 使用 Token 验证请求 - swag: true # 是否启用 OpenApi 文档 - # 运行日志 -logger: +log: dir: logs # 日志目录 level: info # 日志级别 target: stdout # 日志输出方式 -# WeChat Ferry +# Web 服务 +web: + address: 127.0.0.1:7600 # 监听地址 + swagger: true # 是否启用 OpenApi 文档 + token: "" # 使用 Token 验证请求 + +# Wcf 服务 wcf: - address: 127.0.0.1:10080 # Rpc 监听地址 - sdkLibrary: wcferry/libs/sdk.dll # Sdk 路径 + address: 127.0.0.1:7601 # Rpc 监听地址 wechatAuto: true # 是否跟随启停微信 msgPrinter: false # 是否打印收到的消息 diff --git a/clients/gohttp/go.mod b/clients/gohttp/go.mod index 38bfdbb..07e396b 100644 --- a/clients/gohttp/go.mod +++ b/clients/gohttp/go.mod @@ -6,8 +6,10 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/knadh/koanf v1.5.0 github.com/knadh/koanf/v2 v2.0.1 - github.com/opentdp/go-helper v0.5.5-0.20240109013403-7323088c3f39 - github.com/opentdp/wechat-rest v0.8.1 + github.com/mitchellh/mapstructure v1.5.0 + github.com/opentdp/go-helper v0.5.7 + github.com/opentdp/wechat-rest v0.10.1 + golang.org/x/net v0.20.0 ) require ( @@ -24,7 +26,7 @@ require ( github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.16.0 // indirect + github.com/go-playground/validator/v10 v10.17.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect @@ -35,7 +37,6 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -48,7 +49,6 @@ require ( golang.org/x/arch v0.7.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.17.0 // indirect diff --git a/clients/gohttp/go.sum b/clients/gohttp/go.sum index 212ce9e..c3af5e0 100644 --- a/clients/gohttp/go.sum +++ b/clients/gohttp/go.sum @@ -91,8 +91,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= -github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74= +github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= @@ -248,10 +248,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/opentdp/go-helper v0.5.5-0.20240109013403-7323088c3f39 h1:qIzCCWpIPhzZq9ZXevYuqBV3w4F/D8/SK+W6UjKhSf0= -github.com/opentdp/go-helper v0.5.5-0.20240109013403-7323088c3f39/go.mod h1:9m+t/2x1CmjZ9YQP37+xECCO84eqMnsxnRE/7y37GjE= -github.com/opentdp/wechat-rest v0.8.1 h1:2M7BFYCotM3gJkGxJ3mOczmftByxqRNSj4Q2Ec96Dws= -github.com/opentdp/wechat-rest v0.8.1/go.mod h1:F3rutIf4PahHxPGuAm3wlM6d1S7nznaU/ZNrk0dMEDA= +github.com/opentdp/go-helper v0.5.7 h1:6NPodNpmc37qt7urS6n/mA2Jk3DQTHA0rlh2qXa8dKI= +github.com/opentdp/go-helper v0.5.7/go.mod h1:9m+t/2x1CmjZ9YQP37+xECCO84eqMnsxnRE/7y37GjE= +github.com/opentdp/wechat-rest v0.10.1 h1:P+yIKang4ckAOB10+7kbm/2V/0Punx2ElxDLL+Dp0Cw= +github.com/opentdp/wechat-rest v0.10.1/go.mod h1:JCrwAaKhosZ9oyEhN6R09XA4ACP31xn/0VL3DOY5VF0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= diff --git a/clients/gohttp/httpd/README.md b/clients/gohttp/httpd/README.md index da652f9..31f2b22 100644 --- a/clients/gohttp/httpd/README.md +++ b/clients/gohttp/httpd/README.md @@ -37,5 +37,9 @@ go get github.com/swaggo/swag/cmd/swag go install github.com/swaggo/swag/cmd/swag -swag init --parseDependency -g httpd/server.go -o public/swag -ot json +swag init --parseDependency -g httpd/server.go -o public/swagger -ot json ``` + +## 生成 OpenApi 客户端 + +将生成的 `swagger.json` 上传至 `https://editor.swagger.io` 生成对应的客户端 diff --git a/clients/gohttp/httpd/midware/guard.go b/clients/gohttp/httpd/midware/guard.go index 3d81eb8..1f004b5 100644 --- a/clients/gohttp/httpd/midware/guard.go +++ b/clients/gohttp/httpd/midware/guard.go @@ -12,13 +12,15 @@ func ApiGuard(c *gin.Context) { token := "" + // 取回 Token authcode := c.GetHeader("Authorization") parts := strings.SplitN(authcode, " ", 2) if len(parts) == 2 && parts[0] == "Bearer" { token = parts[1] } - if token != args.Httpd.Token { + // 校验 Token + if token != args.Web.Token { c.Set("Error", gin.H{"Code": 401, "Message": "操作未授权"}) c.Set("ExitCode", 401) c.Abort() @@ -26,9 +28,9 @@ func ApiGuard(c *gin.Context) { } -func SwagGuard(c *gin.Context) { +func SwaggerGuard(c *gin.Context) { - if !args.Httpd.Swag && strings.HasPrefix(c.Request.URL.Path, "/swag") { + if !args.Web.Swagger && strings.HasPrefix(c.Request.URL.Path, "/swagger") { c.Header("Content-Type", "text/html; charset=utf-8") c.String(200, "功能已禁用") c.Abort() diff --git a/clients/gohttp/httpd/server.go b/clients/gohttp/httpd/server.go index 70dad6b..64a9930 100644 --- a/clients/gohttp/httpd/server.go +++ b/clients/gohttp/httpd/server.go @@ -9,7 +9,7 @@ import ( ) // @title WeChat Rest Api -// @version v0.5.0 +// @version v0.10.0 // @description 基于 WeChatFerry RPC 实现的微信接口,使用 Go 语言编写,无第三方运行时依赖,易于对接任意编程语言。 // @contact.name WeChatRest // @contact.url https://github.com/opentdp/wechat-rest @@ -29,12 +29,12 @@ func Server() { wcfrest.Route(api) // Swagger 守卫 - httpd.Use(midware.SwagGuard) + httpd.Use(midware.SwaggerGuard) // 前端文件路由 httpd.StaticEmbed("/", "public", args.Efs) // 启动 HTTP 服务 - httpd.Server(args.Httpd.Address) + httpd.Server(args.Web.Address) } diff --git a/clients/gohttp/httpd/wcfrest/controller.go b/clients/gohttp/httpd/wcfrest/controller.go index bff2b95..747b34a 100644 --- a/clients/gohttp/httpd/wcfrest/controller.go +++ b/clients/gohttp/httpd/wcfrest/controller.go @@ -4,7 +4,9 @@ import ( "strings" "github.com/gin-gonic/gin" - "github.com/opentdp/go-helper/strutil" + "github.com/mitchellh/mapstructure" + "github.com/opentdp/go-helper/logman" + "golang.org/x/net/websocket" "github.com/opentdp/wechat-rest/wcferry" ) @@ -13,10 +15,22 @@ type Controller struct { *wcferry.Client } +// 通用结果 +type CommonPayload struct { + // 是否成功 + Success bool `json:"success,omitempty"` + // 返回结果 + Result string `json:"result,omitempty"` + // 错误信息 + Error error `json:"error,omitempty"` +} + // @Summary 检查登录状态 // @Produce json // @Success 200 {object} bool -// @Router /is_login [get] +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /is_login [post] func (wc *Controller) isLogin(c *gin.Context) { c.Set("Payload", wc.CmdClient.IsLogin()) @@ -26,7 +40,9 @@ func (wc *Controller) isLogin(c *gin.Context) { // @Summary 获取登录账号wxid // @Produce json // @Success 200 {object} string -// @Router /self_wxid [get] +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /self_wxid [post] func (wc *Controller) getSelfWxid(c *gin.Context) { c.Set("Payload", wc.CmdClient.GetSelfWxid()) @@ -35,50 +51,45 @@ func (wc *Controller) getSelfWxid(c *gin.Context) { // @Summary 获取登录账号个人信息 // @Produce json -// @Success 200 {object} wcferry.UserInfo -// @Router /user_info [get] -func (wc *Controller) getUserInfo(c *gin.Context) { +// @Success 200 {object} UserInfoPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /self_info [post] +func (wc *Controller) getSelfInfo(c *gin.Context) { - c.Set("Payload", wc.CmdClient.GetUserInfo()) + c.Set("Payload", wc.CmdClient.GetSelfInfo()) } -// @Summary 获取完整通讯录 -// @Produce json -// @Success 200 {object} []wcferry.RpcContact -// @Router /contacts [get] -func (wc *Controller) getContacts(c *gin.Context) { - - c.Set("Payload", wc.CmdClient.GetContacts()) - +type UserInfoPayload struct { + // 用户 id + Wxid string `json:"wxid,omitempty"` + // 昵称 + Name string `json:"name,omitempty"` + // 手机号 + Mobile string `json:"mobile,omitempty"` + // 文件/图片等父路径 + Home string `json:"home,omitempty"` } -// @Summary 获取好友列表 +// @Summary 获取所有消息类型 // @Produce json -// @Success 200 {object} []wcferry.RpcContact -// @Router /friends [get] -func (wc *Controller) getFriends(c *gin.Context) { +// @Success 200 {object} map[int32]string +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /msg_types [post] +func (wc *Controller) getMsgTypes(c *gin.Context) { - c.Set("Payload", wc.CmdClient.GetFriends()) - -} - -// @Summary 根据wxid获取个人信息 -// @Produce json -// @Param wxid path string true "wxid" -// @Success 200 {object} wcferry.RpcContact -// @Router /user_info/{wxid} [get] -func (wc *Controller) getUserInfoByWxid(c *gin.Context) { - - wxid := c.Param("wxid") - c.Set("Payload", wc.CmdClient.GetInfoByWxid(wxid)) + c.Set("Payload", wc.CmdClient.GetMsgTypes()) } // @Summary 获取数据库列表 // @Produce json // @Success 200 {object} []string -// @Router /db_names [get] +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /db_names [post] func (wc *Controller) getDbNames(c *gin.Context) { c.Set("Payload", wc.CmdClient.GetDbNames()) @@ -87,20 +98,41 @@ func (wc *Controller) getDbNames(c *gin.Context) { // @Summary 获取数据库表列表 // @Produce json -// @Param db path string true "数据库名" -// @Success 200 {object} []wcferry.DbTable -// @Router /db_tables/{db} [get] +// @Param body body GetDbTablesRequest true "获取数据库表列表参数" +// @Success 200 {object} []DbTablePayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /db_tables [post] func (wc *Controller) getDbTables(c *gin.Context) { - db := c.Param("db") - c.Set("Payload", wc.CmdClient.GetDbTables(db)) + var req GetDbTablesRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.Set("Error", err) + return + } + c.Set("Payload", wc.CmdClient.GetDbTables(req.Db)) + +} + +type DbTablePayload struct { + // 表名 + Name string `json:"name,omitempty"` + // 建表 SQL + Sql string `json:"sql,omitempty"` +} + +type GetDbTablesRequest struct { + // 数据库名称 + Db string `json:"db"` } // @Summary 执行数据库查询 // @Produce json -// @Param body body DbSqlQueryRequest true "数据库查询请求参数" -// @Success 200 {object} map[string]any +// @Param body body DbSqlQueryRequest true "数据库查询参数" +// @Success 200 {object} []map[string]any +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /db_query_sql [post] func (wc *Controller) dbSqlQuery(c *gin.Context) { @@ -114,38 +146,19 @@ func (wc *Controller) dbSqlQuery(c *gin.Context) { } -// @Summary 获取所有消息类型 -// @Produce json -// @Success 200 {object} map[int32]string -// @Router /msg_types [get] -func (wc *Controller) getMsgTypes(c *gin.Context) { - - c.Set("Payload", wc.CmdClient.GetMsgTypes()) - -} - -// @Summary 刷新朋友圈 -// @Produce json -// @Param id path int true "朋友圈id" -// @Success 200 {object} RespPayload -// @Router /refresh_pyq/{id} [get] -func (wc *Controller) refreshPyq(c *gin.Context) { - - id := c.Param("id") - pyqid := uint64(strutil.ToUint(id)) - - status := wc.CmdClient.RefreshPyq(pyqid) - - c.Set("Payload", RespPayload{ - Success: status == 1, - }) - +type DbSqlQueryRequest struct { + // 数据库名称 + Db string `json:"db"` + // 待执行的 SQL + Sql string `json:"sql"` } // @Summary 获取群列表 // @Produce json -// @Success 200 {object} []wcferry.RpcContact -// @Router /chatrooms [get] +// @Success 200 {object} []ContactPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /chatrooms [post] func (wc *Controller) getChatRooms(c *gin.Context) { c.Set("Payload", wc.CmdClient.GetChatRooms()) @@ -154,67 +167,102 @@ func (wc *Controller) getChatRooms(c *gin.Context) { // @Summary 获取群成员列表 // @Produce json -// @Param roomid path string true "群id" -// @Success 200 {object} []wcferry.RpcContact -// @Router /chatroom_members/{roomid} [get] +// @Param body body GetChatRoomMembersRequest true "获取群成员列表参数" +// @Success 200 {object} []ContactPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /chatroom_members [post] func (wc *Controller) getChatRoomMembers(c *gin.Context) { - roomid := c.Param("roomid") - c.Set("Payload", wc.CmdClient.GetChatRoomMembers(roomid)) - -} - -// @Summary 获取群成员昵称 -// @Produce json -// @Param wxid path string true "wxid" -// @Param roomid path string true "群id" -// @Success 200 {object} string -// @Router /alias_in_chatroom/{wxid}/{roomid} [get] -func (wc *Controller) getAliasInChatRoom(c *gin.Context) { - - wxid := c.Param("wxid") - roomid := c.Param("roomid") - c.Set("Payload", wc.CmdClient.GetAliasInChatRoom(wxid, roomid)) - -} - -// @Summary 邀请群成员 -// @Produce json -// @Param body body wcferry.MemberMgmt true "增删群成员请求参数" -// @Success 200 {object} RespPayload -// @Router /invite_chatroom_members [post] -func (wc *Controller) inviteChatroomMembers(c *gin.Context) { - - var req wcferry.MemberMgmt + var req GetChatRoomMembersRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return } - status := wc.CmdClient.InviteChatroomMembers(req.Roomid, req.Wxids) + c.Set("Payload", wc.CmdClient.GetChatRoomMembers(req.Roomid)) - c.Set("Payload", RespPayload{ +} + +type GetChatRoomMembersRequest struct { + // 群聊 id + Roomid string `json:"roomid"` +} + +// @Summary 获取群成员昵称 +// @Produce json +// @Param body body GetAliasInChatRoomRequest true "获取群成员昵称参数" +// @Success 200 {object} string +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /alias_in_chatroom [post] +func (wc *Controller) getAliasInChatRoom(c *gin.Context) { + + var req GetAliasInChatRoomRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.Set("Error", err) + return + } + + c.Set("Payload", wc.CmdClient.GetAliasInChatRoom(req.Wxid, req.Roomid)) + +} + +type GetAliasInChatRoomRequest struct { + // 群聊 id + Roomid string `json:"roomid"` + // 用户 id + Wxid string `json:"wxid"` +} + +// @Summary 邀请群成员 +// @Produce json +// @Param body body ChatroomMembersRequest true "管理群成员参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /invite_chatroom_members [post] +func (wc *Controller) inviteChatroomMembers(c *gin.Context) { + + var req ChatroomMembersRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.Set("Error", err) + return + } + + status := wc.CmdClient.InviteChatroomMembers(req.Roomid, strings.Join(req.Wxids, ",")) + + c.Set("Payload", CommonPayload{ Success: status == 1, }) } +type ChatroomMembersRequest struct { + // 群聊 id + Roomid string `json:"roomid"` + // 用户 id 列表 + Wxids []string `json:"wxids"` +} + // @Summary 添加群成员 // @Produce json -// @Param body body wcferry.MemberMgmt true "增删群成员请求参数" -// @Success 200 {object} RespPayload +// @Param body body ChatroomMembersRequest true "管理群成员参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /add_chatroom_members [post] func (wc *Controller) addChatRoomMembers(c *gin.Context) { - var req wcferry.MemberMgmt + var req ChatroomMembersRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return } - status := wc.CmdClient.AddChatRoomMembers(req.Roomid, req.Wxids) + status := wc.CmdClient.AddChatRoomMembers(req.Roomid, strings.Join(req.Wxids, ",")) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 1, }) @@ -222,20 +270,22 @@ func (wc *Controller) addChatRoomMembers(c *gin.Context) { // @Summary 删除群成员 // @Produce json -// @Param body body wcferry.MemberMgmt true "增删群成员请求参数" -// @Success 200 {object} RespPayload +// @Param body body ChatroomMembersRequest true "管理群成员参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /del_chatroom_members [post] func (wc *Controller) delChatRoomMembers(c *gin.Context) { - var req wcferry.MemberMgmt + var req ChatroomMembersRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return } - status := wc.CmdClient.DelChatRoomMembers(req.Roomid, req.Wxids) + status := wc.CmdClient.DelChatRoomMembers(req.Roomid, strings.Join(req.Wxids, ",")) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 1, }) @@ -243,72 +293,104 @@ func (wc *Controller) delChatRoomMembers(c *gin.Context) { // @Summary 撤回消息 // @Produce json -// @Param msgid path int true "消息id" -// @Success 200 {object} RespPayload -// @Router /revoke_msg/{msgid} [get] +// @Param body body RevokeMsgRequest true "撤回消息参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /revoke_msg [post] func (wc *Controller) revokeMsg(c *gin.Context) { - id := c.Param("msgid") - msgid := uint64(strutil.ToUint(id)) + var req RevokeMsgRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.Set("Error", err) + return + } - status := wc.CmdClient.RevokeMsg(msgid) + status := wc.CmdClient.RevokeMsg(req.Msgid) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 1, }) } +type RevokeMsgRequest struct { + // 消息 id + Msgid uint64 `json:"msgid"` +} + // @Summary 转发消息 // @Produce json -// @Param body body wcferry.ForwardMsg true "转发消息请求参数" -// @Success 200 {object} RespPayload +// @Param body body ForwardMsgRequest true "转发消息参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /forward_msg [post] func (wc *Controller) forwardMsg(c *gin.Context) { - var req wcferry.ForwardMsg + var req ForwardMsgRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return } - status := wc.CmdClient.ForwardMsg(req.Id, req.Receiver) + status := wc.CmdClient.ForwardMsg(req.Id, strings.Join(req.Receiver, ",")) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 1, }) } +type ForwardMsgRequest struct { + // 待转发消息 id + Id uint64 `json:"id"` + // 转发接收人或群的 id 列表 + Receiver []string `json:"receiver"` +} + // @Summary 发送文本消息 // @Produce json -// @Param body body wcferry.TextMsg true "文本消息请求参数" -// @Success 200 {object} RespPayload +// @Param body body SendTxtRequest true "发送文本消息参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /send_txt [post] func (wc *Controller) sendTxt(c *gin.Context) { - var req wcferry.TextMsg + var req SendTxtRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return } - status := wc.CmdClient.SendTxt(req.Msg, req.Receiver, req.Aters) + status := wc.CmdClient.SendTxt(req.Msg, req.Receiver, strings.Join(req.Aters, ",")) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 0, }) } +type SendTxtRequest struct { + // 消息内容 + Msg string `json:"msg"` + // 接收人或群的 id + Receiver string `json:"receiver"` + // 需要 At 的用户 id 列表 + Aters []string `json:"aters"` +} + // @Summary 发送图片消息 // @Produce json -// @Param body body wcferry.PathMsg true "图片消息请求参数" -// @Success 200 {object} RespPayload +// @Param body body SendImgRequest true "发送图片消息参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /send_img [post] func (wc *Controller) sendImg(c *gin.Context) { - var req wcferry.PathMsg + var req SendImgRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return @@ -316,20 +398,29 @@ func (wc *Controller) sendImg(c *gin.Context) { status := wc.CmdClient.SendImg(req.Path, req.Receiver) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 0, }) } +type SendImgRequest struct { + // 图片路径 + Path string `json:"path"` + // 接收人或群的 id + Receiver string `json:"receiver"` +} + // @Summary 发送文件消息 // @Produce json -// @Param body body wcferry.PathMsg true "文件消息请求参数" -// @Success 200 {object} RespPayload +// @Param body body SendFileRequest true "发送文件消息参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /send_file [post] func (wc *Controller) sendFile(c *gin.Context) { - var req wcferry.PathMsg + var req SendFileRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return @@ -337,20 +428,29 @@ func (wc *Controller) sendFile(c *gin.Context) { status := wc.CmdClient.SendFile(req.Path, req.Receiver) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 0, }) } +type SendFileRequest struct { + // 文件路径 + Path string `json:"path"` + // 接收人或群的 id + Receiver string `json:"receiver"` +} + // @Summary 发送卡片消息 // @Produce json -// @Param body body wcferry.RichText true "卡片消息请求参数" -// @Success 200 {object} RespPayload +// @Param body body SendRichTextRequest true "发送卡片消息参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /send_rich_text [post] func (wc *Controller) sendRichText(c *gin.Context) { - var req wcferry.RichText + var req SendRichTextRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return @@ -358,20 +458,39 @@ func (wc *Controller) sendRichText(c *gin.Context) { status := wc.CmdClient.SendRichText(req.Name, req.Account, req.Title, req.Digest, req.Url, req.Thumburl, req.Receiver) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 0, }) } +type SendRichTextRequest struct { + // 左下显示的名字 + Name string `json:"name"` + // 填公众号 id 可以显示对应的头像(gh_ 开头的) + Account string `json:"account"` + // 标题,最多两行 + Title string `json:"title"` + // 摘要,三行 + Digest string `json:"digest"` + // 点击后跳转的链接 + Url string `json:"url"` + // 缩略图的链接 + Thumburl string `json:"thumburl"` + // 接收人或群的 id + Receiver string `json:"receiver"` +} + // @Summary 拍一拍群友 // @Produce json -// @Param body body wcferry.PatMsg true "拍一拍请求参数" -// @Success 200 {object} RespPayload +// @Param body body SendPatMsgRequest true "拍一拍群友参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /send_pat_msg [post] func (wc *Controller) sendPatMsg(c *gin.Context) { - var req wcferry.PatMsg + var req SendPatMsgRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return @@ -379,16 +498,25 @@ func (wc *Controller) sendPatMsg(c *gin.Context) { status := wc.CmdClient.SendPatMsg(req.Roomid, req.Wxid) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 1, }) } +type SendPatMsgRequest struct { + // 群 id + Roomid string `json:"roomid"` + // 用户 id + Wxid string `json:"wxid"` +} + // @Summary 获取语音消息 // @Produce json -// @Param body body GetAudioMsgRequest true "语音消息请求参数" -// @Success 200 {object} RespPayload +// @Param body body GetAudioMsgRequest true "获取语音消息参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /get_audio_msg [post] func (wc *Controller) getAudioMsg(c *gin.Context) { @@ -400,14 +528,14 @@ func (wc *Controller) getAudioMsg(c *gin.Context) { if req.Timeout > 0 { resp, err := wc.CmdClient.GetAudioMsgTimeout(req.Msgid, req.Dir, req.Timeout) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: resp != "", Result: resp, Error: err, }) } else { resp := wc.CmdClient.GetAudioMsg(req.Msgid, req.Dir) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: resp != "", Result: resp, }) @@ -415,10 +543,21 @@ func (wc *Controller) getAudioMsg(c *gin.Context) { } +type GetAudioMsgRequest struct { + // 消息 id + Msgid uint64 `json:"msgid"` + // 存储路径 + Dir string `json:"path"` + // 超时重试次数 + Timeout int `json:"timeout"` +} + // @Summary 获取OCR识别结果 // @Produce json -// @Param body body GetOcrRequest true "文本请求参数" -// @Success 200 {object} RespPayload +// @Param body body GetOcrRequest true "获取OCR识别结果参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /get_ocr_result [post] func (wc *Controller) getOcrResult(c *gin.Context) { @@ -430,14 +569,14 @@ func (wc *Controller) getOcrResult(c *gin.Context) { if req.Timeout > 0 { resp, err := wc.CmdClient.GetOcrResultTimeout(req.Extra, req.Timeout) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: resp != "", Result: resp, Error: err, }) } else { resp, stat := wc.CmdClient.GetOcrResult(req.Extra) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: stat == 0, Result: resp, }) @@ -445,10 +584,19 @@ func (wc *Controller) getOcrResult(c *gin.Context) { } +type GetOcrRequest struct { + // 消息中的 extra 字段 + Extra string `json:"extra"` + // 超时重试次数 + Timeout int `json:"timeout"` +} + // @Summary 下载图片 // @Produce json // @Param body body DownloadImageRequest true "下载图片参数" -// @Success 200 {object} RespPayload +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /download_image [post] func (wc *Controller) downloadImage(c *gin.Context) { @@ -460,7 +608,7 @@ func (wc *Controller) downloadImage(c *gin.Context) { resp, err := wc.CmdClient.DownloadImage(req.Msgid, req.Extra, req.Dir, req.Timeout) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: resp != "", Result: resp, Error: err, @@ -468,10 +616,23 @@ func (wc *Controller) downloadImage(c *gin.Context) { } +type DownloadImageRequest struct { + // 消息 id + Msgid uint64 `json:"msgid"` + // 消息中的 extra 字段 + Extra string `json:"extra"` + // 存储路径 + Dir string `json:"dir"` + // 超时重试次数 + Timeout int `json:"timeout"` +} + // @Summary 下载附件 // @Produce json // @Param body body DownloadAttachRequest true "下载附件参数" -// @Success 200 {object} RespPayload +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /download_attach [post] func (wc *Controller) downloadAttach(c *gin.Context) { @@ -483,20 +644,175 @@ func (wc *Controller) downloadAttach(c *gin.Context) { status := wc.CmdClient.DownloadAttach(req.Msgid, req.Thumb, req.Extra) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 0, }) } +type DownloadAttachRequest struct { + // 消息 id + Msgid uint64 `json:"msgid"` + // 消息中的 thumb 字段 + Thumb string `json:"thumb"` + // 消息中的 extra 字段 + Extra string `json:"extra"` +} + +// @Summary 获取头像列表 +// @Produce json +// @Param body body GetAvatarsRequest true "获取头像列表参数" +// @Success 200 {object} []AvatarPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /avatars [post] +func (wc *Controller) getAvatars(c *gin.Context) { + + var req GetAvatarsRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.Set("Error", err) + return + } + + sql := "SELECT usrName as UsrName, bigHeadImgUrl as BigHeadImgUrl, smallHeadImgUrl as SmallHeadImgUrl FROM ContactHeadImgUrl" + + if len(req.Wxids) > 0 { + for i, v := range req.Wxids { + req.Wxids[i] = strings.ReplaceAll(v, "'", "''") + } + sql += " WHERE usrName IN ('" + strings.Join(req.Wxids, "','") + "')" + } + + res := wc.CmdClient.DbSqlQuery("MicroMsg.db", sql) + + var result []AvatarPayload + if mapstructure.Decode(res, &result) == nil { + c.Set("Payload", result) + } else { + c.Set("Payload", res) + } + +} + +type GetAvatarsRequest struct { + // 用户 id 列表 + Wxids []string `json:"wxids"` +} + +type AvatarPayload struct { + // 用户 id + UsrName string `json:"usr_name,omitempty"` + // 大头像 url + BigHeadImgUrl string `json:"big_head_img_url,omitempty"` + // 小头像 url + SmallHeadImgUrl string `json:"small_head_img_url,omitempty"` +} + +// @Summary 获取完整通讯录 +// @Produce json +// @Success 200 {object} []ContactPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /contacts [post] +func (wc *Controller) getContacts(c *gin.Context) { + + c.Set("Payload", wc.CmdClient.GetContacts()) + +} + +type ContactPayload struct { + // 用户 id + Wxid string `json:"wxid,omitempty"` + // 微信号 + Code string `json:"code,omitempty"` + // 备注 + Remark string `json:"remark,omitempty"` + // 昵称 + Name string `json:"name,omitempty"` + // 国家 + Country string `json:"country,omitempty"` + // 省/州 + Province string `json:"province,omitempty"` + // 城市 + City string `json:"city,omitempty"` + // 性别 + Gender int32 `json:"gender,omitempty"` +} + +// @Summary 获取好友列表 +// @Produce json +// @Success 200 {object} []ContactPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /friends [post] +func (wc *Controller) getFriends(c *gin.Context) { + + c.Set("Payload", wc.CmdClient.GetFriends()) + +} + +// @Summary 根据wxid获取个人信息 +// @Produce json +// @Param body body GetInfoByWxidRequest true "根据wxid获取个人信息参数" +// @Success 200 {object} ContactPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /user_info [post] +func (wc *Controller) getInfoByWxid(c *gin.Context) { + + var req GetInfoByWxidRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.Set("Error", err) + return + } + + c.Set("Payload", wc.CmdClient.GetInfoByWxid(req.Wxid)) + +} + +type GetInfoByWxidRequest struct { + // 用户 id + Wxid string `json:"wxid"` +} + +// @Summary 刷新朋友圈 +// @Produce json +// @Param body body RefreshPyqRequest true "刷新朋友圈参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /refresh_pyq [post] +func (wc *Controller) refreshPyq(c *gin.Context) { + + var req RefreshPyqRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.Set("Error", err) + return + } + + status := wc.CmdClient.RefreshPyq(req.Id) + + c.Set("Payload", CommonPayload{ + Success: status == 1, + }) + +} + +type RefreshPyqRequest struct { + // 分页 id + Id uint64 `json:"id"` +} + // @Summary 接受好友请求 // @Produce json -// @Param body body wcferry.Verification true "接受好友请求参数" -// @Success 200 {object} RespPayload +// @Param body body AcceptNewFriendRequest true "接受好友参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /accept_new_friend [post] func (wc *Controller) acceptNewFriend(c *gin.Context) { - var req wcferry.Verification + var req AcceptNewFriendRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return @@ -504,20 +820,31 @@ func (wc *Controller) acceptNewFriend(c *gin.Context) { status := wc.CmdClient.AcceptNewFriend(req.V3, req.V4, req.Scene) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 1, }) } +type AcceptNewFriendRequest struct { + // 加密的用户名 + V3 string `json:"v3"` + // 验证信息 Ticket + V4 string `json:"v4"` + // 添加方式:17 名片,30 扫码 + Scene int32 `json:"scene"` +} + // @Summary 接受转账 // @Produce json -// @Param body body wcferry.Transfer true "接受转账请求参数" -// @Success 200 {object} RespPayload +// @Param body body ReceiveTransferRequest true "接受转账参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /receive_transfer [post] func (wc *Controller) receiveTransfer(c *gin.Context) { - var req wcferry.Transfer + var req ReceiveTransferRequest if err := c.ShouldBindJSON(&req); err != nil { c.Set("Error", err) return @@ -525,16 +852,27 @@ func (wc *Controller) receiveTransfer(c *gin.Context) { status := wc.CmdClient.ReceiveTransfer(req.Wxid, req.Tfid, req.Taid) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: status == 1, }) } +type ReceiveTransferRequest struct { + // 转账人 + Wxid string `json:"wxid,omitempty"` + // 转账id transferid + Tfid string `json:"tfid,omitempty"` + // Transaction id + Taid string `json:"taid,omitempty"` +} + // @Summary 开启推送消息到URL // @Produce json -// @Param body body ReceiverRequest true "消息推送请求参数" -// @Success 200 {object} RespPayload +// @Param body body ReceiverRequest true "推送消息到URL参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /enable_receiver [post] func (wc *Controller) enabledReceiver(c *gin.Context) { @@ -550,17 +888,24 @@ func (wc *Controller) enabledReceiver(c *gin.Context) { } err := wc.enableUrlReceiver(req.Url) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: err == nil, Error: err, }) } +type ReceiverRequest struct { + // 接收推送消息的 url + Url string `json:"url"` +} + // @Summary 关闭推送消息到URL // @Produce json -// @Param body body ReceiverRequest true "消息推送请求参数" -// @Success 200 {object} RespPayload +// @Param body body ReceiverRequest true "推送消息到URL参数" +// @Success 200 {object} CommonPayload +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" // @Router /disable_receiver [post] func (wc *Controller) disableReceiver(c *gin.Context) { @@ -571,9 +916,36 @@ func (wc *Controller) disableReceiver(c *gin.Context) { } err := wc.disableUrlReceiver(req.Url) - c.Set("Payload", RespPayload{ + c.Set("Payload", CommonPayload{ Success: err == nil, Error: err, }) } + +// @Summary 推送消息到Socket +// @Produce json +// @Tags websocket +// @Success 101 {string} string "Switching Protocols 响应" +// @Failure 400 {string} string "非法请求" +// @Failure 500 {string} string "内部服务器错误" +// @Router /socket_receiver [get] +func (wc *Controller) socketReceiver(c *gin.Context) { + + h := websocket.Handler(func(ws *websocket.Conn) { + wc.enableSocketReceiver(ws) + for { + var rq string + if err := websocket.Message.Receive(ws, &rq); err != nil { + logman.Error("read:error", "error", err) + break + } + } + wc.disableSocketReceiver(ws) + }) + + h.ServeHTTP(c.Writer, c.Request) + + c.Set("Payload", "连接已关闭") + +} diff --git a/clients/gohttp/httpd/wcfrest/receiver.go b/clients/gohttp/httpd/wcfrest/receiver.go index 542d988..772dbfa 100644 --- a/clients/gohttp/httpd/wcfrest/receiver.go +++ b/clients/gohttp/httpd/wcfrest/receiver.go @@ -5,41 +5,48 @@ import ( "github.com/opentdp/go-helper/logman" "github.com/opentdp/go-helper/request" + "golang.org/x/net/websocket" "github.com/opentdp/wechat-rest/wcferry" ) -var urlReceiverStat = false +var urlReceiverKey = "" var urlReceiverList = map[string]bool{} +var socketReceiverKey = "" +var socketReceiverList = map[*websocket.Conn]bool{} + func (wc *Controller) enableUrlReceiver(url string) error { - if !urlReceiverStat { - err := wc.EnrollReceiver(true, func(msg *wcferry.WxMsg) { + logman.Info("enable receiver", "url", url) + + if urlReceiverKey == "" { + key, err := wc.EnrollReceiver(true, func(msg *wcferry.WxMsg) { ret := wcferry.ParseWxMsg(msg) - for url := range urlReceiverList { - logman.Info("forward msg", "url", url, "Id", ret.Id) - go request.JsonPost(url, ret, request.H{}) + for u := range urlReceiverList { + logman.Info("call receiver", "url", u, "Id", ret.Id) + go request.JsonPost(u, ret, request.H{}) } }) if err != nil { return err } + urlReceiverKey = key } if _, ok := urlReceiverList[url]; ok { return errors.New("url already exists") } - urlReceiverStat = true urlReceiverList[url] = true - return nil } func (wc *Controller) disableUrlReceiver(url string) error { + logman.Info("disable receiver", "url", url) + if _, ok := urlReceiverList[url]; !ok { return errors.New("url not exists") } @@ -47,10 +54,52 @@ func (wc *Controller) disableUrlReceiver(url string) error { delete(urlReceiverList, url) if len(urlReceiverList) == 0 { - if err := wc.DisableReceiver(false); err != nil { - return err - } - urlReceiverStat = false + return wc.DisableReceiver(urlReceiverKey) + } + + return nil + +} + +func (wc *Controller) enableSocketReceiver(ws *websocket.Conn) error { + + logman.Info("enable receiver", "socket", ws.RemoteAddr().String()) + + if len(socketReceiverList) == 0 { + key, err := wc.EnrollReceiver(true, func(msg *wcferry.WxMsg) { + ret := wcferry.ParseWxMsg(msg) + for w := range socketReceiverList { + logman.Info("call receiver", "socket", ws.RemoteAddr().String(), "Id", ret.Id) + go websocket.JSON.Send(w, ret) + } + }) + if err != nil { + return err + } + socketReceiverKey = key + } + + if _, ok := socketReceiverList[ws]; ok { + return errors.New("socket already exists") + } + + socketReceiverList[ws] = true + return nil + +} + +func (wc *Controller) disableSocketReceiver(ws *websocket.Conn) error { + + logman.Info("disable receiver", "socket", ws.RemoteAddr().String()) + + if _, ok := socketReceiverList[ws]; !ok { + return errors.New("socket not exists") + } + + delete(socketReceiverList, ws) + + if len(socketReceiverList) == 0 { + return wc.DisableReceiver(socketReceiverKey) } return nil diff --git a/clients/gohttp/httpd/wcfrest/router.go b/clients/gohttp/httpd/wcfrest/router.go index 3fc3e62..3218f62 100644 --- a/clients/gohttp/httpd/wcfrest/router.go +++ b/clients/gohttp/httpd/wcfrest/router.go @@ -2,50 +2,53 @@ package wcfrest import ( "github.com/gin-gonic/gin" + "github.com/opentdp/wechat-rest/wclient" ) func Route(rg *gin.RouterGroup) { - ctrl := Controller{wclient.Register()} + ctrl := &Controller{wclient.Register()} - rg.GET("is_login", ctrl.isLogin) - rg.GET("self_wxid", ctrl.getSelfWxid) - rg.GET("user_info", ctrl.getUserInfo) - rg.GET("contacts", ctrl.getContacts) - rg.GET("friends", ctrl.getFriends) - rg.GET("user_info/:wxid", ctrl.getUserInfoByWxid) + rg.POST("is_login", ctrl.isLogin) + rg.POST("self_wxid", ctrl.getSelfWxid) + rg.POST("self_info", ctrl.getSelfInfo) + rg.POST("msg_types", ctrl.getMsgTypes) - rg.GET("db_names", ctrl.getDbNames) - rg.GET("db_tables/:db", ctrl.getDbTables) + rg.POST("db_names", ctrl.getDbNames) + rg.POST("db_tables", ctrl.getDbTables) rg.POST("db_query_sql", ctrl.dbSqlQuery) - rg.GET("msg_types", ctrl.getMsgTypes) - rg.GET("refresh_pyq/:id", ctrl.refreshPyq) - - rg.GET("chatrooms", ctrl.getChatRooms) - rg.GET("chatroom_members/:roomid", ctrl.getChatRoomMembers) - rg.GET("alias_in_chatroom/:wxid/:roomid", ctrl.getAliasInChatRoom) + rg.POST("chatrooms", ctrl.getChatRooms) + rg.POST("chatroom_members", ctrl.getChatRoomMembers) + rg.POST("alias_in_chatroom", ctrl.getAliasInChatRoom) rg.POST("invite_chatroom_members", ctrl.inviteChatroomMembers) rg.POST("add_chatroom_members", ctrl.addChatRoomMembers) rg.POST("del_chatroom_members", ctrl.delChatRoomMembers) - rg.GET("revoke_msg/:msgid", ctrl.revokeMsg) + rg.POST("revoke_msg", ctrl.revokeMsg) rg.POST("forward_msg", ctrl.forwardMsg) rg.POST("send_txt", ctrl.sendTxt) rg.POST("send_img", ctrl.sendImg) rg.POST("send_file", ctrl.sendFile) rg.POST("send_rich_text", ctrl.sendRichText) rg.POST("send_pat_msg", ctrl.sendPatMsg) - rg.POST("get_audio_msg", ctrl.getAudioMsg) - rg.POST("get_ocr_result", ctrl.getOcrResult) + rg.POST("audio_msg", ctrl.getAudioMsg) + rg.POST("ocr_result", ctrl.getOcrResult) rg.POST("download_image", ctrl.downloadImage) rg.POST("download_attach", ctrl.downloadAttach) + rg.POST("avatars", ctrl.getAvatars) + rg.POST("contacts", ctrl.getContacts) + rg.POST("friends", ctrl.getFriends) + rg.POST("user_info", ctrl.getInfoByWxid) + rg.POST("refresh_pyq", ctrl.refreshPyq) rg.POST("accept_new_friend", ctrl.acceptNewFriend) rg.POST("receive_transfer", ctrl.receiveTransfer) rg.POST("enable_receiver", ctrl.enabledReceiver) rg.POST("disable_receiver", ctrl.disableReceiver) + rg.GET("socket_receiver", ctrl.socketReceiver) + } diff --git a/clients/gohttp/httpd/wcfrest/types.go b/clients/gohttp/httpd/wcfrest/types.go deleted file mode 100644 index 79ef94b..0000000 --- a/clients/gohttp/httpd/wcfrest/types.go +++ /dev/null @@ -1,47 +0,0 @@ -package wcfrest - -// 执行结果 -type RespPayload struct { - Success bool `json:"success,omitempty"` - Result string `json:"result,omitempty"` - Error error `json:"error,omitempty"` -} - -// 数据库查询参数 -type DbSqlQueryRequest struct { - Db string `json:"db"` - Sql string `json:"sql"` -} - -// 消息转发参数 -type ReceiverRequest struct { - Url string `json:"url"` -} - -// 获取音频消息参数 -type GetAudioMsgRequest struct { - Msgid uint64 `json:"msgid"` - Dir string `json:"path"` - Timeout int `json:"timeout"` -} - -// 获取OCR识别参数 -type GetOcrRequest struct { - Extra string `json:"extra"` - Timeout int `json:"timeout"` -} - -// 下载图片参数 -type DownloadImageRequest struct { - Msgid uint64 `json:"msgid"` - Extra string `json:"extra"` - Dir string `json:"dir"` - Timeout int `json:"timeout"` -} - -// 下载附件参数 -type DownloadAttachRequest struct { - Msgid uint64 `json:"msgid"` - Thumb string `json:"thumb"` - Extra string `json:"extra"` -} diff --git a/clients/gohttp/public/assets/icon.png b/clients/gohttp/public/assets/icon.png new file mode 100644 index 0000000..c0bb037 Binary files /dev/null and b/clients/gohttp/public/assets/icon.png differ diff --git a/clients/gohttp/public/assets/image/icon.svg b/clients/gohttp/public/assets/image/icon.svg deleted file mode 100644 index bfb4e71..0000000 --- a/clients/gohttp/public/assets/image/icon.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/clients/gohttp/public/assets/logo.png b/clients/gohttp/public/assets/logo.png new file mode 100644 index 0000000..b4e0da0 Binary files /dev/null and b/clients/gohttp/public/assets/logo.png differ diff --git a/clients/gohttp/public/index.html b/clients/gohttp/public/index.html index 1f8210b..4b23856 100644 --- a/clients/gohttp/public/index.html +++ b/clients/gohttp/public/index.html @@ -5,14 +5,14 @@ - + WeChat Rest diff --git a/clients/gohttp/public/swag/swagger.json b/clients/gohttp/public/swag/swagger.json deleted file mode 100644 index 865264c..0000000 --- a/clients/gohttp/public/swag/swagger.json +++ /dev/null @@ -1,1108 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "基于 WeChatFerry RPC 实现的微信接口,使用 Go 语言编写,无第三方运行时依赖,易于对接任意编程语言。", - "title": "WeChat Rest Api", - "contact": { - "name": "WeChatRest", - "url": "https://github.com/opentdp/wechat-rest" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "v0.5.0" - }, - "basePath": "/api", - "paths": { - "/accept_new_friend": { - "post": { - "produces": [ - "application/json" - ], - "summary": "接受好友请求", - "parameters": [ - { - "description": "接受好友请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.Verification" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/add_chatroom_members": { - "post": { - "produces": [ - "application/json" - ], - "summary": "添加群成员", - "parameters": [ - { - "description": "增删群成员请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.MemberMgmt" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/alias_in_chatroom/{wxid}/{roomid}": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取群成员昵称", - "parameters": [ - { - "type": "string", - "description": "wxid", - "name": "wxid", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "群id", - "name": "roomid", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/chatroom_members/{roomid}": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取群成员列表", - "parameters": [ - { - "type": "string", - "description": "群id", - "name": "roomid", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/wcferry.RpcContact" - } - } - } - } - } - }, - "/chatrooms": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取群列表", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/wcferry.RpcContact" - } - } - } - } - } - }, - "/contacts": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取完整通讯录", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/wcferry.RpcContact" - } - } - } - } - } - }, - "/db_names": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取数据库列表", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/db_query_sql": { - "post": { - "produces": [ - "application/json" - ], - "summary": "执行数据库查询", - "parameters": [ - { - "description": "数据库查询请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcfrest.DbSqlQueryRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/db_tables/{db}": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取数据库表列表", - "parameters": [ - { - "type": "string", - "description": "数据库名", - "name": "db", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/wcferry.DbTable" - } - } - } - } - } - }, - "/del_chatroom_members": { - "post": { - "produces": [ - "application/json" - ], - "summary": "删除群成员", - "parameters": [ - { - "description": "增删群成员请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.MemberMgmt" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/disable_receiver": { - "post": { - "produces": [ - "application/json" - ], - "summary": "关闭推送消息到URL", - "parameters": [ - { - "description": "消息推送请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcfrest.ReceiverRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/download_attach": { - "post": { - "produces": [ - "application/json" - ], - "summary": "下载附件", - "parameters": [ - { - "description": "下载附件参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcfrest.DownloadAttachRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/download_image": { - "post": { - "produces": [ - "application/json" - ], - "summary": "下载图片", - "parameters": [ - { - "description": "下载图片参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcfrest.DownloadImageRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/enable_receiver": { - "post": { - "produces": [ - "application/json" - ], - "summary": "开启推送消息到URL", - "parameters": [ - { - "description": "消息推送请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcfrest.ReceiverRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/forward_msg": { - "post": { - "produces": [ - "application/json" - ], - "summary": "转发消息", - "parameters": [ - { - "description": "转发消息请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.ForwardMsg" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/friends": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取好友列表", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/wcferry.RpcContact" - } - } - } - } - } - }, - "/get_audio_msg": { - "post": { - "produces": [ - "application/json" - ], - "summary": "获取语音消息", - "parameters": [ - { - "description": "语音消息请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcfrest.GetAudioMsgRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/get_ocr_result": { - "post": { - "produces": [ - "application/json" - ], - "summary": "获取OCR识别结果", - "parameters": [ - { - "description": "文本请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcfrest.GetOcrRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/invite_chatroom_members": { - "post": { - "produces": [ - "application/json" - ], - "summary": "邀请群成员", - "parameters": [ - { - "description": "增删群成员请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.MemberMgmt" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/is_login": { - "get": { - "produces": [ - "application/json" - ], - "summary": "检查登录状态", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/msg_types": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取所有消息类型", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/receive_transfer": { - "post": { - "produces": [ - "application/json" - ], - "summary": "接受转账", - "parameters": [ - { - "description": "接受转账请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.Transfer" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/refresh_pyq/{id}": { - "get": { - "produces": [ - "application/json" - ], - "summary": "刷新朋友圈", - "parameters": [ - { - "type": "integer", - "description": "朋友圈id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/revoke_msg/{msgid}": { - "get": { - "produces": [ - "application/json" - ], - "summary": "撤回消息", - "parameters": [ - { - "type": "integer", - "description": "消息id", - "name": "msgid", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/self_wxid": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取登录账号wxid", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/send_file": { - "post": { - "produces": [ - "application/json" - ], - "summary": "发送文件消息", - "parameters": [ - { - "description": "文件消息请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.PathMsg" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/send_img": { - "post": { - "produces": [ - "application/json" - ], - "summary": "发送图片消息", - "parameters": [ - { - "description": "图片消息请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.PathMsg" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/send_pat_msg": { - "post": { - "produces": [ - "application/json" - ], - "summary": "拍一拍群友", - "parameters": [ - { - "description": "拍一拍请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.PatMsg" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/send_rich_text": { - "post": { - "produces": [ - "application/json" - ], - "summary": "发送卡片消息", - "parameters": [ - { - "description": "卡片消息请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.RichText" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/send_txt": { - "post": { - "produces": [ - "application/json" - ], - "summary": "发送文本消息", - "parameters": [ - { - "description": "文本消息请求参数", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wcferry.TextMsg" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcfrest.RespPayload" - } - } - } - } - }, - "/user_info": { - "get": { - "produces": [ - "application/json" - ], - "summary": "获取登录账号个人信息", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcferry.UserInfo" - } - } - } - } - }, - "/user_info/{wxid}": { - "get": { - "produces": [ - "application/json" - ], - "summary": "根据wxid获取个人信息", - "parameters": [ - { - "type": "string", - "description": "wxid", - "name": "wxid", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/wcferry.RpcContact" - } - } - } - } - } - }, - "definitions": { - "wcferry.DbTable": { - "type": "object", - "properties": { - "name": { - "description": "表名", - "type": "string" - }, - "sql": { - "description": "建表 SQL", - "type": "string" - } - } - }, - "wcferry.ForwardMsg": { - "type": "object", - "properties": { - "id": { - "description": "待转发消息 ID", - "type": "integer" - }, - "receiver": { - "description": "转发接收目标,群为 roomId,个人为 wxid", - "type": "string" - } - } - }, - "wcferry.MemberMgmt": { - "type": "object", - "properties": { - "roomid": { - "description": "要加的群ID", - "type": "string" - }, - "wxids": { - "description": "要加群的人列表,逗号分隔", - "type": "string" - } - } - }, - "wcferry.PatMsg": { - "type": "object", - "properties": { - "roomid": { - "description": "群 id", - "type": "string" - }, - "wxid": { - "description": "wxid", - "type": "string" - } - } - }, - "wcferry.PathMsg": { - "type": "object", - "properties": { - "path": { - "description": "要发送的图片的路径", - "type": "string" - }, - "receiver": { - "description": "消息接收人", - "type": "string" - } - } - }, - "wcferry.RichText": { - "type": "object", - "properties": { - "account": { - "description": "公众号 id", - "type": "string" - }, - "digest": { - "description": "摘要", - "type": "string" - }, - "name": { - "description": "显示名字", - "type": "string" - }, - "receiver": { - "description": "接收人", - "type": "string" - }, - "thumburl": { - "description": "缩略图", - "type": "string" - }, - "title": { - "description": "标题", - "type": "string" - }, - "url": { - "description": "链接", - "type": "string" - } - } - }, - "wcferry.RpcContact": { - "type": "object", - "properties": { - "city": { - "description": "城市", - "type": "string" - }, - "code": { - "description": "微信号", - "type": "string" - }, - "country": { - "description": "国家", - "type": "string" - }, - "gender": { - "description": "性别", - "type": "integer" - }, - "name": { - "description": "微信昵称", - "type": "string" - }, - "province": { - "description": "省/州", - "type": "string" - }, - "remark": { - "description": "备注", - "type": "string" - }, - "wxid": { - "description": "微信 id", - "type": "string" - } - } - }, - "wcferry.TextMsg": { - "type": "object", - "properties": { - "aters": { - "description": "要@的人列表,逗号分隔", - "type": "string" - }, - "msg": { - "description": "要发送的消息内容", - "type": "string" - }, - "receiver": { - "description": "消息接收人,当为群时可@", - "type": "string" - } - } - }, - "wcferry.Transfer": { - "type": "object", - "properties": { - "taid": { - "description": "Transaction id", - "type": "string" - }, - "tfid": { - "description": "转账id transferid", - "type": "string" - }, - "wxid": { - "description": "转账人", - "type": "string" - } - } - }, - "wcferry.UserInfo": { - "type": "object", - "properties": { - "home": { - "description": "文件/图片等父路径", - "type": "string" - }, - "mobile": { - "description": "手机号", - "type": "string" - }, - "name": { - "description": "昵称", - "type": "string" - }, - "wxid": { - "description": "微信ID", - "type": "string" - } - } - }, - "wcferry.Verification": { - "type": "object", - "properties": { - "scene": { - "description": "添加方式:17 名片,30 扫码", - "type": "integer" - }, - "v3": { - "description": "加密的用户名", - "type": "string" - }, - "v4": { - "description": "Ticket", - "type": "string" - } - } - }, - "wcfrest.DbSqlQueryRequest": { - "type": "object", - "properties": { - "db": { - "type": "string" - }, - "sql": { - "type": "string" - } - } - }, - "wcfrest.DownloadAttachRequest": { - "type": "object", - "properties": { - "extra": { - "type": "string" - }, - "msgid": { - "type": "integer" - }, - "thumb": { - "type": "string" - } - } - }, - "wcfrest.DownloadImageRequest": { - "type": "object", - "properties": { - "dir": { - "type": "string" - }, - "extra": { - "type": "string" - }, - "msgid": { - "type": "integer" - }, - "timeout": { - "type": "integer" - } - } - }, - "wcfrest.GetAudioMsgRequest": { - "type": "object", - "properties": { - "msgid": { - "type": "integer" - }, - "path": { - "type": "string" - }, - "timeout": { - "type": "integer" - } - } - }, - "wcfrest.GetOcrRequest": { - "type": "object", - "properties": { - "extra": { - "type": "string" - }, - "timeout": { - "type": "integer" - } - } - }, - "wcfrest.ReceiverRequest": { - "type": "object", - "properties": { - "url": { - "type": "string" - } - } - }, - "wcfrest.RespPayload": { - "type": "object", - "properties": { - "error": {}, - "result": { - "type": "string" - }, - "success": { - "type": "boolean" - } - } - } - } -} \ No newline at end of file diff --git a/clients/gohttp/public/swag/index.html b/clients/gohttp/public/swagger/index.html similarity index 91% rename from clients/gohttp/public/swag/index.html rename to clients/gohttp/public/swagger/index.html index 443938f..473c1bf 100644 --- a/clients/gohttp/public/swag/index.html +++ b/clients/gohttp/public/swagger/index.html @@ -5,7 +5,7 @@ - + WeChat Rest Document diff --git a/clients/gohttp/public/swagger/swagger.json b/clients/gohttp/public/swagger/swagger.json new file mode 100644 index 0000000..3b561d3 --- /dev/null +++ b/clients/gohttp/public/swagger/swagger.json @@ -0,0 +1,1701 @@ +{ + "swagger": "2.0", + "info": { + "description": "基于 WeChatFerry RPC 实现的微信接口,使用 Go 语言编写,无第三方运行时依赖,易于对接任意编程语言。", + "title": "WeChat Rest Api", + "contact": { + "name": "WeChatRest", + "url": "https://github.com/opentdp/wechat-rest" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "v0.8.0" + }, + "basePath": "/api", + "paths": { + "/accept_new_friend": { + "post": { + "produces": [ + "application/json" + ], + "summary": "接受好友请求", + "parameters": [ + { + "description": "接受好友参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.AcceptNewFriendRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/add_chatroom_members": { + "post": { + "produces": [ + "application/json" + ], + "summary": "添加群成员", + "parameters": [ + { + "description": "管理群成员参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.ChatroomMembersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/alias_in_chatroom": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取群成员昵称", + "parameters": [ + { + "description": "获取群成员昵称参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.GetAliasInChatRoomRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/avatars": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取头像列表", + "parameters": [ + { + "description": "获取头像列表参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.GetAvatarsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/wcfrest.AvatarPayload" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/chatroom_members": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取群成员列表", + "parameters": [ + { + "description": "获取群成员列表参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.GetChatRoomMembersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/wcfrest.ContactPayload" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/chatrooms": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取群列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/wcfrest.ContactPayload" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/contacts": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取完整通讯录", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/wcfrest.ContactPayload" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/db_names": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取数据库列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/db_query_sql": { + "post": { + "produces": [ + "application/json" + ], + "summary": "执行数据库查询", + "parameters": [ + { + "description": "数据库查询参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.DbSqlQueryRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/db_tables": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取数据库表列表", + "parameters": [ + { + "description": "获取数据库表列表参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.GetDbTablesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/wcfrest.DbTablePayload" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/del_chatroom_members": { + "post": { + "produces": [ + "application/json" + ], + "summary": "删除群成员", + "parameters": [ + { + "description": "管理群成员参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.ChatroomMembersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/disable_receiver": { + "post": { + "produces": [ + "application/json" + ], + "summary": "关闭推送消息到URL", + "parameters": [ + { + "description": "推送消息到URL参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.ReceiverRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/download_attach": { + "post": { + "produces": [ + "application/json" + ], + "summary": "下载附件", + "parameters": [ + { + "description": "下载附件参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.DownloadAttachRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/download_image": { + "post": { + "produces": [ + "application/json" + ], + "summary": "下载图片", + "parameters": [ + { + "description": "下载图片参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.DownloadImageRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/enable_receiver": { + "post": { + "produces": [ + "application/json" + ], + "summary": "开启推送消息到URL", + "parameters": [ + { + "description": "推送消息到URL参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.ReceiverRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/forward_msg": { + "post": { + "produces": [ + "application/json" + ], + "summary": "转发消息", + "parameters": [ + { + "description": "转发消息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.ForwardMsgRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/friends": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取好友列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/wcfrest.ContactPayload" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/get_audio_msg": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取语音消息", + "parameters": [ + { + "description": "获取语音消息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.GetAudioMsgRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/get_ocr_result": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取OCR识别结果", + "parameters": [ + { + "description": "获取OCR识别结果参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.GetOcrRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/invite_chatroom_members": { + "post": { + "produces": [ + "application/json" + ], + "summary": "邀请群成员", + "parameters": [ + { + "description": "管理群成员参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.ChatroomMembersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/is_login": { + "post": { + "produces": [ + "application/json" + ], + "summary": "检查登录状态", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/msg_types": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取所有消息类型", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/receive_transfer": { + "post": { + "produces": [ + "application/json" + ], + "summary": "接受转账", + "parameters": [ + { + "description": "接受转账参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.ReceiveTransferRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/refresh_pyq": { + "post": { + "produces": [ + "application/json" + ], + "summary": "刷新朋友圈", + "parameters": [ + { + "description": "刷新朋友圈参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.RefreshPyqRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/revoke_msg": { + "post": { + "produces": [ + "application/json" + ], + "summary": "撤回消息", + "parameters": [ + { + "description": "撤回消息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.RevokeMsgRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/self_info": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取登录账号个人信息", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.UserInfoPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/self_wxid": { + "post": { + "produces": [ + "application/json" + ], + "summary": "获取登录账号wxid", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/send_file": { + "post": { + "produces": [ + "application/json" + ], + "summary": "发送文件消息", + "parameters": [ + { + "description": "发送文件消息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.SendFileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/send_img": { + "post": { + "produces": [ + "application/json" + ], + "summary": "发送图片消息", + "parameters": [ + { + "description": "发送图片消息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.SendImgRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/send_pat_msg": { + "post": { + "produces": [ + "application/json" + ], + "summary": "拍一拍群友", + "parameters": [ + { + "description": "拍一拍群友参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.SendPatMsgRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/send_rich_text": { + "post": { + "produces": [ + "application/json" + ], + "summary": "发送卡片消息", + "parameters": [ + { + "description": "发送卡片消息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.SendRichTextRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/send_txt": { + "post": { + "produces": [ + "application/json" + ], + "summary": "发送文本消息", + "parameters": [ + { + "description": "发送文本消息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.SendTxtRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.CommonPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/socket_receiver": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "websocket" + ], + "summary": "推送消息到Socket", + "responses": { + "101": { + "description": "Switching Protocols 响应", + "schema": { + "type": "string" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + }, + "/user_info": { + "post": { + "produces": [ + "application/json" + ], + "summary": "根据wxid获取个人信息", + "parameters": [ + { + "description": "根据wxid获取个人信息参数", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/wcfrest.GetInfoByWxidRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/wcfrest.ContactPayload" + } + }, + "400": { + "description": "非法请求", + "schema": { + "type": "string" + } + }, + "500": { + "description": "内部服务器错误", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "wcfrest.AcceptNewFriendRequest": { + "type": "object", + "properties": { + "scene": { + "description": "添加方式:17 名片,30 扫码", + "type": "integer" + }, + "v3": { + "description": "加密的用户名", + "type": "string" + }, + "v4": { + "description": "验证信息 Ticket", + "type": "string" + } + } + }, + "wcfrest.AvatarPayload": { + "type": "object", + "properties": { + "big_head_img_url": { + "description": "大头像 url", + "type": "string" + }, + "small_head_img_url": { + "description": "小头像 url", + "type": "string" + }, + "usr_name": { + "description": "用户 id", + "type": "string" + } + } + }, + "wcfrest.ChatroomMembersRequest": { + "type": "object", + "properties": { + "roomid": { + "description": "群聊 id", + "type": "string" + }, + "wxids": { + "description": "用户 id 列表", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "wcfrest.CommonPayload": { + "type": "object", + "properties": { + "error": { + "description": "错误信息" + }, + "result": { + "description": "返回结果", + "type": "string" + }, + "success": { + "description": "是否成功", + "type": "boolean" + } + } + }, + "wcfrest.ContactPayload": { + "type": "object", + "properties": { + "city": { + "description": "城市", + "type": "string" + }, + "code": { + "description": "微信号", + "type": "string" + }, + "country": { + "description": "国家", + "type": "string" + }, + "gender": { + "description": "性别", + "type": "integer" + }, + "name": { + "description": "昵称", + "type": "string" + }, + "province": { + "description": "省/州", + "type": "string" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "wxid": { + "description": "用户 id", + "type": "string" + } + } + }, + "wcfrest.DbSqlQueryRequest": { + "type": "object", + "properties": { + "db": { + "description": "数据库名称", + "type": "string" + }, + "sql": { + "description": "待执行的 SQL", + "type": "string" + } + } + }, + "wcfrest.DbTablePayload": { + "type": "object", + "properties": { + "name": { + "description": "表名", + "type": "string" + }, + "sql": { + "description": "建表 SQL", + "type": "string" + } + } + }, + "wcfrest.DownloadAttachRequest": { + "type": "object", + "properties": { + "extra": { + "description": "消息中的 extra 字段", + "type": "string" + }, + "msgid": { + "description": "消息 id", + "type": "integer" + }, + "thumb": { + "description": "消息中的 thumb 字段", + "type": "string" + } + } + }, + "wcfrest.DownloadImageRequest": { + "type": "object", + "properties": { + "dir": { + "description": "存储路径", + "type": "string" + }, + "extra": { + "description": "消息中的 extra 字段", + "type": "string" + }, + "msgid": { + "description": "消息 id", + "type": "integer" + }, + "timeout": { + "description": "超时重试次数", + "type": "integer" + } + } + }, + "wcfrest.ForwardMsgRequest": { + "type": "object", + "properties": { + "id": { + "description": "待转发消息 id", + "type": "integer" + }, + "receiver": { + "description": "转发接收人或群的 id 列表", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "wcfrest.GetAliasInChatRoomRequest": { + "type": "object", + "properties": { + "roomid": { + "description": "群聊 id", + "type": "string" + }, + "wxid": { + "description": "用户 id", + "type": "string" + } + } + }, + "wcfrest.GetAudioMsgRequest": { + "type": "object", + "properties": { + "msgid": { + "description": "消息 id", + "type": "integer" + }, + "path": { + "description": "存储路径", + "type": "string" + }, + "timeout": { + "description": "超时重试次数", + "type": "integer" + } + } + }, + "wcfrest.GetAvatarsRequest": { + "type": "object", + "properties": { + "wxids": { + "description": "用户 id 列表", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "wcfrest.GetChatRoomMembersRequest": { + "type": "object", + "properties": { + "roomid": { + "description": "群聊 id", + "type": "string" + } + } + }, + "wcfrest.GetDbTablesRequest": { + "type": "object", + "properties": { + "db": { + "description": "数据库名称", + "type": "string" + } + } + }, + "wcfrest.GetInfoByWxidRequest": { + "type": "object", + "properties": { + "wxid": { + "description": "用户 id", + "type": "string" + } + } + }, + "wcfrest.GetOcrRequest": { + "type": "object", + "properties": { + "extra": { + "description": "消息中的 extra 字段", + "type": "string" + }, + "timeout": { + "description": "超时重试次数", + "type": "integer" + } + } + }, + "wcfrest.ReceiveTransferRequest": { + "type": "object", + "properties": { + "taid": { + "description": "Transaction id", + "type": "string" + }, + "tfid": { + "description": "转账id transferid", + "type": "string" + }, + "wxid": { + "description": "转账人", + "type": "string" + } + } + }, + "wcfrest.ReceiverRequest": { + "type": "object", + "properties": { + "url": { + "description": "接收推送消息的 url", + "type": "string" + } + } + }, + "wcfrest.RefreshPyqRequest": { + "type": "object", + "properties": { + "id": { + "description": "分页 id", + "type": "integer" + } + } + }, + "wcfrest.RevokeMsgRequest": { + "type": "object", + "properties": { + "msgid": { + "description": "消息 id", + "type": "integer" + } + } + }, + "wcfrest.SendFileRequest": { + "type": "object", + "properties": { + "path": { + "description": "文件路径", + "type": "string" + }, + "receiver": { + "description": "接收人或群的 id", + "type": "string" + } + } + }, + "wcfrest.SendImgRequest": { + "type": "object", + "properties": { + "path": { + "description": "图片路径", + "type": "string" + }, + "receiver": { + "description": "接收人或群的 id", + "type": "string" + } + } + }, + "wcfrest.SendPatMsgRequest": { + "type": "object", + "properties": { + "roomid": { + "description": "群 id", + "type": "string" + }, + "wxid": { + "description": "用户 id", + "type": "string" + } + } + }, + "wcfrest.SendRichTextRequest": { + "type": "object", + "properties": { + "account": { + "description": "填公众号 id 可以显示对应的头像(gh_ 开头的)", + "type": "string" + }, + "digest": { + "description": "摘要,三行", + "type": "string" + }, + "name": { + "description": "左下显示的名字", + "type": "string" + }, + "receiver": { + "description": "接收人或群的 id", + "type": "string" + }, + "thumburl": { + "description": "缩略图的链接", + "type": "string" + }, + "title": { + "description": "标题,最多两行", + "type": "string" + }, + "url": { + "description": "点击后跳转的链接", + "type": "string" + } + } + }, + "wcfrest.SendTxtRequest": { + "type": "object", + "properties": { + "aters": { + "description": "需要 At 的用户 id 列表", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "description": "消息内容", + "type": "string" + }, + "receiver": { + "description": "接收人或群的 id", + "type": "string" + } + } + }, + "wcfrest.UserInfoPayload": { + "type": "object", + "properties": { + "home": { + "description": "文件/图片等父路径", + "type": "string" + }, + "mobile": { + "description": "手机号", + "type": "string" + }, + "name": { + "description": "昵称", + "type": "string" + }, + "wxid": { + "description": "用户 id", + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/clients/gohttp/start.bat b/clients/gohttp/start-dev.bat similarity index 97% rename from clients/gohttp/start.bat rename to clients/gohttp/start-dev.bat index 7bbb50b..e0829e9 100644 --- a/clients/gohttp/start.bat +++ b/clients/gohttp/start-dev.bat @@ -18,3 +18,5 @@ if exist .local.yml ( ) else ( go run main.go ) + +cmd /k