WeChatFerry/clients/go/wcf/wcf.go
2023-07-28 13:49:26 +08:00

483 lines
9.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package wcf
import (
logs "github.com/danbai225/go-logs"
"go.nanomsg.org/mangos/v3"
"go.nanomsg.org/mangos/v3/protocol"
"go.nanomsg.org/mangos/v3/protocol/pair1"
_ "go.nanomsg.org/mangos/v3/transport/all"
"google.golang.org/protobuf/proto"
"strconv"
"strings"
)
type Client struct {
add string
socket protocol.Socket
RecvTxt bool
}
func (c *Client) conn() error {
socket, err := pair1.NewSocket()
if err != nil {
return err
}
err = socket.Dial(c.add)
if err != nil {
return err
}
c.socket = socket
return err
}
func (c *Client) send(data []byte) error {
return c.socket.Send(data)
}
func (c *Client) Recv() (*Response, error) {
msg := &Response{}
recv, err := c.socket.Recv()
if err != nil {
return msg, err
}
err = proto.Unmarshal(recv, msg)
return msg, err
}
func (c *Client) Close() error {
c.DisableRecvTxt()
return c.socket.Close()
}
func (c *Client) IsLogin() bool {
err := c.send(genFunReq(Functions_FUNC_IS_LOGIN).build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
if recv.GetStatus() == 1 {
return true
}
return false
}
func (c *Client) GetSelfWXID() string {
err := c.send(genFunReq(Functions_FUNC_GET_SELF_WXID).build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStr()
}
func (c *Client) GetMsgTypes() map[int32]string {
err := c.send(genFunReq(Functions_FUNC_GET_MSG_TYPES).build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetTypes().GetTypes()
}
func (c *Client) GetContacts() []*RpcContact {
err := c.send(genFunReq(Functions_FUNC_GET_CONTACTS).build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetContacts().GetContacts()
}
func (c *Client) GetDBNames() []string {
err := c.send(genFunReq(Functions_FUNC_GET_DB_NAMES).build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetDbs().Names
}
func (c *Client) GetDBTables(tab string) []*DbTable {
req := genFunReq(Functions_FUNC_GET_DB_TABLES)
str := &Request_Str{Str: tab}
req.Msg = str
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetTables().GetTables()
}
func (c *Client) ExecDBQuery(db, sql string) []*DbRow {
req := genFunReq(Functions_FUNC_EXEC_DB_QUERY)
q := Request_Query{
Query: &DbQuery{
Db: db,
Sql: sql,
},
}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetRows().GetRows()
}
/*AcceptFriend 接收好友请求
* 接收好友请求
*
* @param v3 xml.attrib["encryptusername"] // 加密的用户名
* @param v4 xml.attrib["ticket"] // Ticket
* @param scene 17 // 添加方式17 名片30 扫码
*/
func (c *Client) AcceptFriend(v3, v4 string, scene int32) int32 {
req := genFunReq(Functions_FUNC_ACCEPT_FRIEND)
q := Request_V{
V: &Verification{
V3: v3,
V4: v4,
Scene: scene,
}}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
func (c *Client) AddChatroomMembers(roomID, wxIDs string) int32 {
req := genFunReq(Functions_FUNC_ADD_ROOM_MEMBERS)
q := Request_M{
M: &AddMembers{Roomid: roomID, Wxids: wxIDs},
}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
/*
ReceiveTransfer 接收转账
string wxid = 1; // 转账人
string tfid = 2; // 转账id transferid
string taid = 3; // Transaction id
*/
func (c *Client) ReceiveTransfer(wxid, tfid, taid string) int32 {
req := genFunReq(Functions_FUNC_RECV_TRANSFER)
q := Request_Tf{
Tf: &Transfer{
Wxid: wxid,
Tfid: tfid,
Taid: taid,
},
}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
// RefreshPYQ 刷新朋友圈
func (c *Client) RefreshPYQ() int32 {
req := genFunReq(Functions_FUNC_REFRESH_PYQ)
q := Request_Ui64{
Ui64: 0,
}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
// DecryptImage 解密图片 加密路径,解密路径
func (c *Client) DecryptImage(src, dst string) int32 {
req := genFunReq(Functions_FUNC_DECRYPT_IMAGE)
q := Request_Dec{
Dec: &DecPath{Src: src, Dst: dst},
}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
func (c *Client) AddChatRoomMembers(roomId string, wxIds []string) int32 {
req := genFunReq(Functions_FUNC_ADD_ROOM_MEMBERS)
q := Request_M{
M: &AddMembers{Roomid: roomId,
Wxids: strings.Join(wxIds, ",")},
}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
func (c *Client) DelChatRoomMembers(roomId string, wxIds []string) int32 {
req := genFunReq(Functions_FUNC_DEL_ROOM_MEMBERS)
q := Request_M{
M: &AddMembers{Roomid: roomId,
Wxids: strings.Join(wxIds, ",")},
}
req.Msg = &q
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
func (c *Client) GetUserInfo() *UserInfo {
err := c.send(genFunReq(Functions_FUNC_GET_USER_INFO).build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetUi()
}
/*
SendTxt
@param msg: 消息内容(如果是 @ 消息则需要有跟 @ 的人数量相同的 @
@param receiver: 消息接收人,私聊为 wxidwxid_xxxxxxxxxxxxxx群聊为roomidxxxxxxxxxx@chatroom
@param ates: 群聊时要 @ 的人(私聊时为空字符串),多个用逗号分隔。@所有人 用notify@all必须是群主或者管理员才有权限
*/
func (c *Client) SendTxt(msg string, receiver string, ates []string) int32 {
req := genFunReq(Functions_FUNC_SEND_TXT)
req.Msg = &Request_Txt{
Txt: &TextMsg{
Msg: msg,
Receiver: receiver,
Aters: strings.Join(ates, ","),
},
}
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
/*
SendIMG
path 绝对路径InBot
*/
func (c *Client) SendIMG(path string, receiver string) int32 {
req := genFunReq(Functions_FUNC_SEND_IMG)
req.Msg = &Request_File{
File: &PathMsg{
Path: path,
Receiver: receiver,
},
}
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
/*
SendFile
path 绝对路径InBot
*/
func (c *Client) SendFile(path string, receiver string) int32 {
req := genFunReq(Functions_FUNC_SEND_FILE)
req.Msg = &Request_File{
File: &PathMsg{
Path: path,
Receiver: receiver,
},
}
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
func (c *Client) SendXml(path, content, receiver string, Type int32) int32 {
req := genFunReq(Functions_FUNC_SEND_XML)
req.Msg = &Request_Xml{
Xml: &XmlMsg{
Receiver: receiver,
Content: content,
Path: path,
Type: Type,
},
}
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
func (c *Client) SendEmotion(path, receiver string) int32 {
req := genFunReq(Functions_FUNC_SEND_EMOTION)
req.Msg = &Request_File{
File: &PathMsg{
Path: path,
Receiver: receiver,
},
}
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
return recv.GetStatus()
}
func (c *Client) EnableRecvTxt() int32 {
req := genFunReq(Functions_FUNC_ENABLE_RECV_TXT)
req.Msg = &Request_Flag{
Flag: true,
}
err := c.send(req.build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
c.RecvTxt = true
return recv.GetStatus()
}
func (c *Client) DisableRecvTxt() int32 {
err := c.send(genFunReq(Functions_FUNC_DISABLE_RECV_TXT).build())
if err != nil {
logs.Err(err)
}
recv, err := c.Recv()
if err != nil {
logs.Err(err)
}
c.RecvTxt = false
return recv.GetStatus()
}
func (c *Client) OnMSG(f func(msg *WxMsg)) error {
socket, err := pair1.NewSocket()
if err != nil {
return err
}
_ = socket.SetOption(mangos.OptionRecvDeadline, 2000)
_ = socket.SetOption(mangos.OptionSendDeadline, 2000)
err = socket.Dial(addPort(c.add))
if err != nil {
return err
}
defer socket.Close()
for c.RecvTxt {
msg := &Response{}
recv, err := socket.Recv()
if err != nil {
return err
}
_ = proto.Unmarshal(recv, msg)
go f(msg.GetWxmsg())
}
return err
}
func NewWCF(add string) (*Client, error) {
if add == "" {
add = "tcp://127.0.0.1:10086"
}
client := &Client{add: add}
err := client.conn()
return client, err
}
type cmdMSG struct {
*Request
}
func (c *cmdMSG) build() []byte {
marshal, _ := proto.Marshal(c)
return marshal
}
func genFunReq(fun Functions) *cmdMSG {
return &cmdMSG{
&Request{Func: fun,
Msg: nil},
}
}
func addPort(add string) string {
parts := strings.Split(add, ":")
port, _ := strconv.Atoi(parts[2])
newPort := port + 1
return parts[0] + ":" + parts[1] + ":" + strconv.Itoa(newPort)
}