forked from lxh/go-wxhelper
✨ 完善微信机器人相关接口(wxhelper接口还未全部实现)
This commit is contained in:
parent
08821977b4
commit
3fbc6780a0
25
api/admin/robot/delete.go
Normal file
25
api/admin/robot/delete.go
Normal file
@ -0,0 +1,25 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"unicode/utf8"
|
||||
"wechat-robot/pkg/response"
|
||||
robotService "wechat-robot/service/robot"
|
||||
)
|
||||
|
||||
// DeleteById
|
||||
// @description: 删除机器人
|
||||
// @param ctx
|
||||
func DeleteById(ctx *gin.Context) {
|
||||
var id = ctx.Param("id")
|
||||
if utf8.RuneCountInString(id) != 32 {
|
||||
response.New(ctx).SetMsg("参数错误").Fail()
|
||||
return
|
||||
}
|
||||
// 删除数据
|
||||
if err := robotService.DeleteById(id); err != nil {
|
||||
response.New(ctx).SetMsg("删除失败").SetError(err).Fail()
|
||||
} else {
|
||||
response.New(ctx).SetMsg("删除成功").Success()
|
||||
}
|
||||
}
|
31
api/admin/robot/save.go
Normal file
31
api/admin/robot/save.go
Normal file
@ -0,0 +1,31 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
robotParam "wechat-robot/model/param/robot"
|
||||
"wechat-robot/pkg/response"
|
||||
robotService "wechat-robot/service/robot"
|
||||
)
|
||||
|
||||
// Save
|
||||
// @description: 保存机器人
|
||||
// @param ctx
|
||||
func Save(ctx *gin.Context) {
|
||||
var p robotParam.Save
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
response.New(ctx).SetMsg("参数错误").SetError(err).Fail()
|
||||
return
|
||||
}
|
||||
|
||||
// 参数校验
|
||||
if p.Id == "" && (p.HookApi == "" || p.Version == 0) {
|
||||
response.New(ctx).SetMsg("参数错误").Fail()
|
||||
return
|
||||
}
|
||||
|
||||
if err := robotService.Save(p); err != nil {
|
||||
response.New(ctx).SetMsg("保存失败").SetError(err).Fail()
|
||||
return
|
||||
}
|
||||
response.New(ctx).SetMsg("保存成功").Success()
|
||||
}
|
26
api/admin/robot/select.go
Normal file
26
api/admin/robot/select.go
Normal file
@ -0,0 +1,26 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
robotParam "wechat-robot/model/param/robot"
|
||||
"wechat-robot/pkg/response"
|
||||
robotService "wechat-robot/service/robot"
|
||||
)
|
||||
|
||||
// GetAll
|
||||
// @description: 获取所有机器人
|
||||
// @param ctx
|
||||
func GetAll(ctx *gin.Context) {
|
||||
var p robotParam.GetAll
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
response.New(ctx).SetMsg("参数错误").SetError(err).Fail()
|
||||
return
|
||||
}
|
||||
|
||||
records, err := robotService.GetAll(p)
|
||||
if err != nil {
|
||||
response.New(ctx).SetMsg("数据获取失败").SetError(err).Fail()
|
||||
return
|
||||
}
|
||||
response.New(ctx).SetData(records).Success()
|
||||
}
|
1
go.mod
1
go.mod
@ -13,6 +13,7 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1
|
||||
github.com/go-playground/validator/v10 v10.17.0
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/go-resty/resty/v2 v2.11.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/mojocn/base64Captcha v1.3.6
|
||||
github.com/spf13/viper v1.18.2
|
||||
|
13
go.sum
13
go.sum
@ -315,6 +315,8 @@ github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QX
|
||||
github.com/go-redis/redis/v8 v8.0.0-beta.5/go.mod h1:Mm9EH/5UMRx680UIryN6rd5XFn/L7zORPqLV+1D5thQ=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
|
||||
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
|
||||
github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
@ -985,6 +987,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -1076,6 +1079,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -1176,11 +1181,15 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1190,6 +1199,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
@ -1198,6 +1208,9 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -15,6 +15,10 @@ type Robot struct {
|
||||
DataSavePath string `json:"dataSavePath" gorm:"type:varchar(255);comment:'微信保存目录'"` // 微信保存目录
|
||||
DbKey string `json:"dbKey" gorm:"type:varchar(255);comment:'数据库的SQLCipher的加密key'"` // 数据库的SQLCipher的加密key,可以使用该key配合decrypt.py解密数据库
|
||||
HookApi string `json:"hookApi" gorm:"type:varchar(255);comment:'hook接口地址'"` // hook接口地址
|
||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:'备注'"` // 备注
|
||||
Version int `json:"version" gorm:"type:int;comment:'版本号'"` // 版本号
|
||||
VncUrl string `json:"vncUrl" gorm:"type:varchar(255);comment:'vnc地址'"` // vnc地址
|
||||
Tag string `json:"tag" gorm:"type:varchar(255);comment:'标签'"` // 标签
|
||||
}
|
||||
|
||||
// TableName
|
||||
|
13
model/param/robot/robot.go
Normal file
13
model/param/robot/robot.go
Normal file
@ -0,0 +1,13 @@
|
||||
package robot
|
||||
|
||||
import "wechat-robot/pkg/wxhelper"
|
||||
|
||||
// Save
|
||||
// @description: 保存机器人
|
||||
type Save struct {
|
||||
Id string `json:"id" form:"id"` // id
|
||||
HookApi string `json:"hookApi" form:"hookApi"` // hook接口地址
|
||||
Version wxhelper.WeChatVersion `json:"version" form:"version"` // 版本
|
||||
VncUrl string `json:"vncUrl" form:"vncUrl"` // vnc地址
|
||||
Remark string `json:"remark" form:"remark"` // 备注
|
||||
}
|
8
model/param/robot/select.go
Normal file
8
model/param/robot/select.go
Normal file
@ -0,0 +1,8 @@
|
||||
package robot
|
||||
|
||||
// GetAll
|
||||
// @description: 查询所有机器人入参
|
||||
type GetAll struct {
|
||||
Keyword string `json:"keyword" form:"keyword"` // 关键字
|
||||
Tag string `json:"tag" form:"tag"` // 标签
|
||||
}
|
20
model/robot/chatroom.go
Normal file
20
model/robot/chatroom.go
Normal file
@ -0,0 +1,20 @@
|
||||
package model
|
||||
|
||||
// ChatRoomDetailInfo
|
||||
// @description: 群聊详情
|
||||
type ChatRoomDetailInfo struct {
|
||||
Admin string `json:"admin"` // 群主微信
|
||||
ChatRoomId string `json:"chatRoomId"` // 群Id
|
||||
Notice string `json:"notice"` // 群公告
|
||||
Xml string `json:"xml"` // 不知道是啥玩意儿
|
||||
}
|
||||
|
||||
// GroupUser
|
||||
// @description: 群成员返回结果
|
||||
type GroupUser struct {
|
||||
Admin string `json:"admin"` // 群主微信
|
||||
AdminNickname string `json:"adminNickname"` // 群主昵称
|
||||
ChatRoomId string `json:"chatRoomId"` // 群Id
|
||||
MemberNickname string `json:"memberNickname"` // 成员昵称 `^G`切割
|
||||
Members string `json:"members"` // 成员Id `^G`切割
|
||||
}
|
26
model/robot/friend.go
Normal file
26
model/robot/friend.go
Normal file
@ -0,0 +1,26 @@
|
||||
package model
|
||||
|
||||
// FriendItem
|
||||
// @description: 好友列表数据
|
||||
type FriendItem struct {
|
||||
CustomAccount string `json:"customAccount"` // 微信号
|
||||
EncryptName string `json:"encryptName"` // 不知道
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Pinyin string `json:"pinyin"` // 昵称拼音大写首字母
|
||||
PinyinAll string `json:"pinyinAll"` // 昵称全拼
|
||||
Reserved1 int `json:"reserved1"` // 未知
|
||||
Reserved2 int `json:"reserved2"` // 未知
|
||||
Type int `json:"type"` // 类型
|
||||
VerifyFlag int `json:"verifyFlag"` // 未知
|
||||
WxId string `json:"wxid"` // 微信原始Id
|
||||
}
|
||||
|
||||
// ContactProfile
|
||||
// @description: 好友资料
|
||||
type ContactProfile struct {
|
||||
Account string `json:"account"` // 账号
|
||||
HeadImage string `json:"headImage"` // 头像
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
V3 string `json:"v3"` // v3
|
||||
WxId string `json:"wxid"` // 微信Id
|
||||
}
|
9
model/robot/response.go
Normal file
9
model/robot/response.go
Normal file
@ -0,0 +1,9 @@
|
||||
package model
|
||||
|
||||
// Response
|
||||
// @description: 基础返回结构体
|
||||
type Response[T any] struct {
|
||||
Code int `json:"code"` // 状态码
|
||||
Data T `json:"data"` // 数据
|
||||
Msg string `json:"msg"` // 消息
|
||||
}
|
18
model/robot/userinfo.go
Normal file
18
model/robot/userinfo.go
Normal file
@ -0,0 +1,18 @@
|
||||
package model
|
||||
|
||||
// UserInfo
|
||||
// @description: 机器人用户信息
|
||||
type UserInfo struct {
|
||||
WxId string `json:"wxid"` // 微信Id
|
||||
Account string `json:"account"` // 微信号
|
||||
Name string `json:"name"` // 昵称
|
||||
HeadImage string `json:"headImage"` // 头像
|
||||
Mobile string `json:"mobile"` // 手机
|
||||
Signature string `json:"signature"` // 个人签名
|
||||
Country string `json:"country"` // 国家
|
||||
Province string `json:"province"` // 省
|
||||
City string `json:"city"` // 城市
|
||||
CurrentDataPath string `json:"currentDataPath"` // 当前数据目录,登录的账号目录
|
||||
DataSavePath string `json:"dataSavePath"` // 微信保存目录
|
||||
DbKey string `json:"dbKey"` // 数据库的SQLCipher的加密key,可以使用该key配合decrypt.py解密数据库
|
||||
}
|
44
pkg/wxhelper/base.go
Normal file
44
pkg/wxhelper/base.go
Normal file
@ -0,0 +1,44 @@
|
||||
package wxhelper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
robotModel "wechat-robot/model/robot"
|
||||
"wechat-robot/utils"
|
||||
)
|
||||
|
||||
// CheckLogin
|
||||
// @description: 检查是否登录
|
||||
// @receiver wx
|
||||
// @return flag
|
||||
func (wx wxHelper) CheckLogin() (flag bool) {
|
||||
var api string
|
||||
if api, flag = wx.version.GetApi("CheckLogin"); !flag {
|
||||
return
|
||||
}
|
||||
// 调用接口
|
||||
var resp robotModel.Response[any]
|
||||
_ = utils.HttpClientUtils().Post(wx.host+api, nil, &resp, 0)
|
||||
return resp.Code == 1
|
||||
}
|
||||
|
||||
// UserInfo
|
||||
// @description: 获取机器人信息
|
||||
// @receiver wx
|
||||
// @return data
|
||||
// @return err
|
||||
func (wx wxHelper) UserInfo() (data robotModel.UserInfo, err error) {
|
||||
var api string
|
||||
var flag bool
|
||||
if api, flag = wx.version.GetApi("UserInfo"); !flag {
|
||||
err = errors.New("不支持的接口")
|
||||
return
|
||||
}
|
||||
// 调用接口
|
||||
var resp robotModel.Response[robotModel.UserInfo]
|
||||
if err = utils.HttpClientUtils().Post(wx.host+api, nil, &resp, 0); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data = resp.Data
|
||||
return
|
||||
}
|
61
pkg/wxhelper/chatroom.go
Normal file
61
pkg/wxhelper/chatroom.go
Normal file
@ -0,0 +1,61 @@
|
||||
package wxhelper
|
||||
|
||||
import robotModel "wechat-robot/model/robot"
|
||||
|
||||
// GetChatRoomDetailInfo
|
||||
// @description: 获取群聊详情
|
||||
// @receiver wx
|
||||
// @param chatRoomId
|
||||
// @return data
|
||||
func (wx wxHelper) GetChatRoomDetailInfo(chatRoomId string) (data robotModel.ChatRoomDetailInfo) {
|
||||
return
|
||||
}
|
||||
|
||||
// AddMemberToChatRoom
|
||||
// @description: 添加群成员
|
||||
// @receiver wx
|
||||
// @param chatRoomId
|
||||
// @param memberWxIds
|
||||
// @return err
|
||||
func (wx wxHelper) AddMemberToChatRoom(chatRoomId string, memberWxIds []string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// DelMemberFromChatRoom
|
||||
// @description: 删除群成员
|
||||
// @receiver wx
|
||||
// @param chatRoomId
|
||||
// @param memberWxIds
|
||||
// @return err
|
||||
func (wx wxHelper) DelMemberFromChatRoom(chatRoomId string, memberWxIds []string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetMemberFromChatRoom
|
||||
// @description: 获取群成员
|
||||
// @receiver wx
|
||||
// @param chatRoomId
|
||||
// @return data
|
||||
func (wx wxHelper) GetMemberFromChatRoom(chatRoomId string) (data robotModel.GroupUser) {
|
||||
return
|
||||
}
|
||||
|
||||
// InviteMemberToChatRoom
|
||||
// @description: 邀请入群
|
||||
// @receiver wx
|
||||
// @param chatRoomId
|
||||
// @param memberWxIds
|
||||
// @return err
|
||||
func (wx wxHelper) InviteMemberToChatRoom(chatRoomId string, memberWxIds []string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ModifyChatRoomNickname
|
||||
// @description: 修改群内昵称
|
||||
// @receiver wx
|
||||
// @param wxId
|
||||
// @param nickname
|
||||
// @return err
|
||||
func (wx wxHelper) ModifyChatRoomNickname(wxId, nickname string) (err error) {
|
||||
return
|
||||
}
|
79
pkg/wxhelper/constant.go
Normal file
79
pkg/wxhelper/constant.go
Normal file
@ -0,0 +1,79 @@
|
||||
package wxhelper
|
||||
|
||||
// WeChatVersion 微信版本
|
||||
type WeChatVersion int
|
||||
|
||||
// 微信版本
|
||||
const (
|
||||
WechatVersion39223 WeChatVersion = 39223
|
||||
WechatVersion39581 WeChatVersion = 39581
|
||||
WechatVersion39825 WeChatVersion = 39825
|
||||
)
|
||||
|
||||
// 接口映射
|
||||
var apiMap = map[WeChatVersion]map[string]string{
|
||||
WechatVersion39223: v39223ApiMap,
|
||||
WechatVersion39581: v39581ApiMap,
|
||||
WechatVersion39825: v39581ApiMap,
|
||||
}
|
||||
|
||||
var v39223ApiMap = map[string]string{
|
||||
"CheckLogin": "/api/?type=0",
|
||||
"UserInfo": "/api/?type=1",
|
||||
"SendTextMsg": "/api/?type=2",
|
||||
"SendAtTest": "/api/?type=3",
|
||||
"SendFileMsg": "/api/?type=6",
|
||||
"SendImagesMsg": "/api/?type=5",
|
||||
"SendCustomEmotionMsg": "",
|
||||
"GetContactList": "/api/?type=46",
|
||||
"GetChatRoomDetailInfo": "/api/?type=47",
|
||||
"AddMemberToChatRoom": "/api/?type=28",
|
||||
"DelMemberFromChatRoom": "/api/?type=27",
|
||||
"GetMemberFromChatRoom": "/api/?type=25",
|
||||
"GetContactProfile": "/api/?type=25",
|
||||
"InviteMemberToChatRoom": "",
|
||||
"ModifyChatRoomNickname": "/api/?type=31",
|
||||
"StartHook": "/api/?type=9",
|
||||
"StopHook": "/api/?type=10",
|
||||
"DownloadAttach": "/api/?type=56",
|
||||
"DecodeImage": "/api/?type=48",
|
||||
}
|
||||
|
||||
var v39581ApiMap = map[string]string{
|
||||
"CheckLogin": "/api/checkLogin",
|
||||
"UserInfo": "/api/userInfo",
|
||||
"SendTextMsg": "/api/sendTextMsg",
|
||||
"SendAtTest": "/api/sendAtText",
|
||||
"SendFileMsg": "/api/sendFileMsg",
|
||||
"SendImagesMsg": "/api/sendImagesMsg",
|
||||
"SendCustomEmotionMsg": "/api/sendCustomEmotion",
|
||||
"GetContactList": "/api/getContactList",
|
||||
"GetChatRoomDetailInfo": "/api/getChatRoomDetailInfo",
|
||||
"AddMemberToChatRoom": "/api/addMemberToChatRoom",
|
||||
"DelMemberFromChatRoom": "/api/delMemberFromChatRoom",
|
||||
"GetMemberFromChatRoom": "/api/getMemberFromChatRoom",
|
||||
"GetContactProfile": "/api/getContactProfile",
|
||||
"InviteMemberToChatRoom": "/api/InviteMemberToChatRoom",
|
||||
"ModifyChatRoomNickname": "/api/modifyNickname",
|
||||
"QuitChatRoom": "/api/quitChatRoom",
|
||||
"StartHook": "/api/hookSyncMsg",
|
||||
"StopHook": "/api/unhookSyncMsg",
|
||||
"DownloadAttach": "/api/downloadAttach",
|
||||
"DecodeImage": "/api/decodeImage",
|
||||
}
|
||||
|
||||
// GetApi
|
||||
// @description: 获取接口地址
|
||||
// @receiver v
|
||||
// @return string
|
||||
func (v WeChatVersion) GetApi(code string) (api string, ok bool) {
|
||||
var am map[string]string
|
||||
// 判断版本是否支持
|
||||
if am, ok = apiMap[v]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取接口
|
||||
api, ok = am[code]
|
||||
return
|
||||
}
|
21
pkg/wxhelper/contact.go
Normal file
21
pkg/wxhelper/contact.go
Normal file
@ -0,0 +1,21 @@
|
||||
package wxhelper
|
||||
|
||||
import robotModel "wechat-robot/model/robot"
|
||||
|
||||
// GetContactList
|
||||
// @description: 获取联系人列表
|
||||
// @receiver wx
|
||||
// @return []robotModel.FriendItem
|
||||
func (wx wxHelper) GetContactList() (friends []robotModel.FriendItem) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetContactProfile
|
||||
// @description: 获取好友资料
|
||||
// @receiver wx
|
||||
// @param wxId
|
||||
// @return robotModel.ContactProfile
|
||||
func (wx wxHelper) GetContactProfile(wxId string) (profile robotModel.ContactProfile) {
|
||||
return
|
||||
}
|
20
pkg/wxhelper/file.go
Normal file
20
pkg/wxhelper/file.go
Normal file
@ -0,0 +1,20 @@
|
||||
package wxhelper
|
||||
|
||||
// DownloadAttach
|
||||
// @description: 下载附件
|
||||
// @receiver wx
|
||||
// @param msgId
|
||||
// @return err
|
||||
func (wx wxHelper) DownloadAttach(msgId int) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeImage
|
||||
// @description: 解码图片
|
||||
// @receiver wx
|
||||
// @param filePath
|
||||
// @param storeDir
|
||||
// @return err
|
||||
func (wx wxHelper) DecodeImage(filePath, storeDir string) (err error) {
|
||||
return
|
||||
}
|
19
pkg/wxhelper/hook.go
Normal file
19
pkg/wxhelper/hook.go
Normal file
@ -0,0 +1,19 @@
|
||||
package wxhelper
|
||||
|
||||
// StartHook
|
||||
// @description: 启动hook
|
||||
// @receiver wx
|
||||
// @param tcpIp
|
||||
// @param tcpPort
|
||||
// @return err
|
||||
func (wx wxHelper) StartHook(tcpIp string, tcpPort int) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// StopHook
|
||||
// @description: 停止hook
|
||||
// @receiver wx
|
||||
// @return err
|
||||
func (wx wxHelper) StopHook() (err error) {
|
||||
return
|
||||
}
|
46
pkg/wxhelper/message.go
Normal file
46
pkg/wxhelper/message.go
Normal file
@ -0,0 +1,46 @@
|
||||
package wxhelper
|
||||
|
||||
// SendTextMsg
|
||||
// @description: 发送文字消息
|
||||
// @receiver wx
|
||||
// @param toUserId
|
||||
// @param atUserId
|
||||
// @param msg
|
||||
// @return err
|
||||
func (wx wxHelper) SendTextMsg(toUserId, atUserId, msg string) (err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SendFileMsg
|
||||
// @description: 发送文件消息
|
||||
// @receiver wx
|
||||
// @param toUserId
|
||||
// @param filePath
|
||||
// @return err
|
||||
func (wx wxHelper) SendFileMsg(toUserId, filePath string) (err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SendImagesMsg
|
||||
// @description: 发送图片消息
|
||||
// @receiver wx
|
||||
// @param toUserId
|
||||
// @param imagePath
|
||||
// @return err
|
||||
func (wx wxHelper) SendImagesMsg(toUserId, imagePath string) (err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SendCustomEmotionMsg
|
||||
// @description: 发送自定义表情消息
|
||||
// @receiver wx
|
||||
// @param toUserId
|
||||
// @param emotionPath
|
||||
// @return err
|
||||
func (wx wxHelper) SendCustomEmotionMsg(toUserId string, emotionPath string) (err error) {
|
||||
|
||||
return
|
||||
}
|
52
pkg/wxhelper/wxhelper.go
Normal file
52
pkg/wxhelper/wxhelper.go
Normal file
@ -0,0 +1,52 @@
|
||||
package wxhelper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"slices"
|
||||
robotModel "wechat-robot/model/robot"
|
||||
)
|
||||
|
||||
type wxHelper struct {
|
||||
host string // hook接口地址
|
||||
version WeChatVersion // 微信版本
|
||||
}
|
||||
|
||||
// Api
|
||||
// @description: 微信助手接口
|
||||
type Api interface {
|
||||
CheckLogin() bool // 检查是否登录
|
||||
UserInfo() (robotModel.UserInfo, error) // 获取机器人信息
|
||||
SendTextMsg(toUserId, atUserId, msg string) error // 发送文字消息
|
||||
SendFileMsg(toUserId, filePath string) error // 发送文件消息
|
||||
SendImagesMsg(toUserId, imagePath string) error // 发送图片消息
|
||||
SendCustomEmotionMsg(toUserId string, emotionPath string) error // 发送自定义表情消息
|
||||
GetContactList() []robotModel.FriendItem // 获取联系人列表
|
||||
GetChatRoomDetailInfo(chatRoomId string) robotModel.ChatRoomDetailInfo // 获取群聊详情
|
||||
AddMemberToChatRoom(chatRoomId string, memberWxIds []string) error // 添加群成员
|
||||
DelMemberFromChatRoom(chatRoomId string, memberWxIds []string) error // 删除群成员
|
||||
GetMemberFromChatRoom(chatRoomId string) robotModel.GroupUser // 获取群成员
|
||||
GetContactProfile(wxId string) robotModel.ContactProfile // 获取好友资料
|
||||
InviteMemberToChatRoom(chatRoomId string, memberWxIds []string) error // 邀请入群
|
||||
ModifyChatRoomNickname(wxId, nickname string) error // 修改群内昵称
|
||||
StartHook(tcpIp string, tcpPort int) error // 开启消息监听 - 暂时只支持tcp,因为http有点儿不太好使
|
||||
StopHook() error // 关闭消息监听
|
||||
DownloadAttach(msgId int) error // 下载附件
|
||||
DecodeImage(filePath, storeDir string) error // 解码图片
|
||||
}
|
||||
|
||||
// New
|
||||
// @description: 创建微信助手
|
||||
// @param host
|
||||
// @return Api
|
||||
func New(host string, version WeChatVersion) (Api, error) {
|
||||
// 判断微信版本是否支持
|
||||
keys := make([]WeChatVersion, 0, len(apiMap))
|
||||
for k := range apiMap {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
if !slices.Contains(keys, version) {
|
||||
return nil, errors.New("不支持的微信版本")
|
||||
}
|
||||
|
||||
return &wxHelper{host: host, version: version}, nil
|
||||
}
|
15
router/admin/robot.go
Normal file
15
router/admin/robot.go
Normal file
@ -0,0 +1,15 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
robotApi "wechat-robot/api/admin/robot"
|
||||
)
|
||||
|
||||
// robot
|
||||
// @description: 机器人相关接口
|
||||
// @param g
|
||||
func robot(g *gin.RouterGroup) {
|
||||
g.GET("", robotApi.GetAll) // 获取所有机器人
|
||||
g.POST("", robotApi.Save) // 保存机器人
|
||||
g.DELETE("/:id", robotApi.DeleteById) // 删除机器人
|
||||
}
|
@ -13,5 +13,6 @@ func InitRoute(g *gin.RouterGroup) {
|
||||
|
||||
g.Use(middleware.AuthorizeToken())
|
||||
menu(g.Group("/menu")) // 菜单相关
|
||||
robot(g.Group("/robot")) // 机器人相关
|
||||
aiAssistant(g.Group("/ai-assistant")) // AI助手相关
|
||||
}
|
||||
|
16
service/robot/delete.go
Normal file
16
service/robot/delete.go
Normal file
@ -0,0 +1,16 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"wechat-robot/internal/database"
|
||||
"wechat-robot/model/entity"
|
||||
)
|
||||
|
||||
// DeleteById
|
||||
// @description: 删除机器人
|
||||
// @param id
|
||||
// @return err
|
||||
func DeleteById(id string) (err error) {
|
||||
// 删除数据
|
||||
err = database.Client.Where("id = ?", id).Delete(&entity.Robot{}).Error
|
||||
return
|
||||
}
|
70
service/robot/save.go
Normal file
70
service/robot/save.go
Normal file
@ -0,0 +1,70 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"wechat-robot/internal/database"
|
||||
"wechat-robot/model/entity"
|
||||
robotParam "wechat-robot/model/param/robot"
|
||||
"wechat-robot/pkg/wxhelper"
|
||||
)
|
||||
|
||||
// Save
|
||||
// @description: 保存机器人
|
||||
// @param p
|
||||
// @return err
|
||||
func Save(p robotParam.Save) (err error) {
|
||||
if p.Id != "" {
|
||||
// 是修改,暂时只支持修改备注
|
||||
err = database.Client.Model(&entity.Robot{}).Where("id = ?", p.Id).Update("remark", p.Remark).Error
|
||||
return
|
||||
}
|
||||
// 新增
|
||||
|
||||
// 获取机器人信息,如果获取失败,就返回错误信息
|
||||
cli, err := wxhelper.New(p.HookApi, p.Version)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
isLogin := cli.CheckLogin()
|
||||
log.Printf("机器人是否登录: %v", isLogin)
|
||||
if !isLogin {
|
||||
err = errors.New("机器人未登录")
|
||||
return
|
||||
}
|
||||
|
||||
// 取出登录账号信息
|
||||
info, err := cli.UserInfo()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log.Printf("机器人Id: %s", info.WxId)
|
||||
log.Printf("机器人微信号: %s", info.Account)
|
||||
log.Printf("机器人名称: %s", info.Name)
|
||||
|
||||
// 先查询是否存在
|
||||
var ent entity.Robot
|
||||
var count int64
|
||||
if err = database.Client.Model(&ent).Where("wxid = ?", info.WxId).Count(&count).Error; err != nil {
|
||||
return
|
||||
}
|
||||
if count > 0 {
|
||||
err = errors.New("机器人已存在")
|
||||
return
|
||||
}
|
||||
|
||||
ent.WxId = info.WxId
|
||||
ent.Account = info.Account
|
||||
ent.Nickname = info.Name
|
||||
ent.Avatar = info.HeadImage
|
||||
ent.Mobile = info.Mobile
|
||||
ent.CurrentDataPath = info.CurrentDataPath
|
||||
ent.DataSavePath = info.DataSavePath
|
||||
ent.DbKey = info.DbKey
|
||||
ent.HookApi = p.HookApi
|
||||
ent.Remark = p.Remark
|
||||
ent.Version = int(p.Version)
|
||||
ent.VncUrl = p.VncUrl
|
||||
err = database.Client.Create(&ent).Error
|
||||
return
|
||||
}
|
@ -1 +1,25 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"wechat-robot/internal/database"
|
||||
"wechat-robot/model/entity"
|
||||
robotParam "wechat-robot/model/param/robot"
|
||||
)
|
||||
|
||||
// GetAll
|
||||
// @description: 查询所有机器人
|
||||
// @param p robotParam.GetAll 查询所有机器人入参
|
||||
// @return records []entity.Robot 查询所有机器人返回值
|
||||
// @return err error 查询所有机器人返回值
|
||||
func GetAll(p robotParam.GetAll) (records []entity.Robot, err error) {
|
||||
tx := database.Client.Order("created_at desc")
|
||||
if p.Keyword != "" {
|
||||
tx.Where("nickname LIKE @keyword OR remark LIKE @keyword", sql.Named("keyword", "%"+p.Keyword+"%"))
|
||||
}
|
||||
if p.Tag != "" {
|
||||
tx.Where("tag LIKE ?", "%"+p.Tag+"%")
|
||||
}
|
||||
err = tx.Find(&records).Error
|
||||
return
|
||||
}
|
||||
|
53
utils/httpclient.go
Normal file
53
utils/httpclient.go
Normal file
@ -0,0 +1,53 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type HttpClient interface {
|
||||
Post(api string, param map[string]any, response any, retryCount int) (err error)
|
||||
}
|
||||
|
||||
type httpClient struct{}
|
||||
|
||||
// HttpClientUtils
|
||||
// @description: Http客户端工具
|
||||
// @return HttpClient
|
||||
func HttpClientUtils() HttpClient {
|
||||
return &httpClient{}
|
||||
}
|
||||
|
||||
// Post
|
||||
// @description: 发送Post请求
|
||||
// @receiver c
|
||||
// @param api
|
||||
// @param param
|
||||
// @param response
|
||||
// @param retryCount
|
||||
// @return err
|
||||
func (c httpClient) Post(api string, param map[string]any, response any, retryCount int) (err error) {
|
||||
if retryCount > 5 {
|
||||
log.Printf("重试五次失败,停止发送")
|
||||
return
|
||||
}
|
||||
|
||||
pbs, _ := json.Marshal(param)
|
||||
|
||||
var r *resty.Response
|
||||
r, err = resty.New().R().
|
||||
SetHeader("Content-Type", "application/json;chartset=utf-8").
|
||||
SetBody(string(pbs)).
|
||||
SetResult(response).
|
||||
Post(api)
|
||||
if err != nil {
|
||||
log.Printf("请求失败: %s", err.Error())
|
||||
// 休眠五秒后重新发送
|
||||
time.Sleep(5 * time.Second)
|
||||
return c.Post(api, param, response, retryCount+1)
|
||||
}
|
||||
log.Printf("请求结果: %s", r.String())
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue
Block a user