tt/core/callapi.go

382 lines
16 KiB
Go
Raw Normal View History

2024-05-28 08:47:31 +08:00
package core
import (
"bytes"
"fmt"
"github.com/goWxHook/goWxHook/utils/json"
"io"
"log/slog"
"net/http"
"time"
)
const (
MtDebugLog = 11024 // debug消息
loginSuccessMsg = 11025 // 登录成功
MtUserLogin = 11025 // 登录消息
MtUserLogout = 11026 // 注销消息
MtSqlQuery = 11027 // 数据库查询消息
MtDataOwnerMsg = 11028 // 获取我的信息消息
MtDataWxidMsg = 11029 // 获取单个好友信息
MtDataFriendsMsg = 11030 // 获取好友列表消息
MtDataChatroomsMsg = 11031 // 获取群聊列表消息
MtDataChatroomMembersMsg = 11032 // 获取群成员消息
MtDataPublicsMsg = 11033 // 获取公众号消息
MtUpdateWxidMsg = 11034 // 从网络更新单个好友信息消息
MtUpdateRoomMemberMsg = 11035 // 从网络更新群成员信息消息
MtSendTextmsg = 11036 // 发送文本消息
MtSendChatroomAtmsg = 11037 // 发送群@消息
MtSendCardmsg = 11038 // 发送名片消息
MtSendLinkmsg = 11039 // 发送链接消息
MtSendImgmsg = 11040 // 发送图片消息
MtSendFilemsg = 11041 // 发送文件消息
MtSendVideomsg = 11042 // 发送视频消息
MtSendGifmsg = 11043 // 发送gif消息
MtRecvTextMsg = 11046 // 接收文本消息
MtRecvPictureMsg = 11047 // 接收图片消息
MtRecvVoiceMsg = 11048 // 接收视频消息
MtRecvFriendMsg = 11049 // 接收申请好友消息
MtRecvCardMsg = 11050 // 接收名片消息
MtRecvVideoMsg = 11051 // 接收视频消息
MtRecvEmojiMsg = 11052 // 接收表情消息
MtRecvLocationMsg = 11053 // 接收位置消息
MtRecvLinkMsg = 11054 // 接收链接消息
MtRecvFileMsg = 11055 // 接收文件消息
MtRecvMiniappMsg = 11056 // 接收小程序消息
MtRecvWcpayMsg = 11057 // 接收好友转账消息
MtRecvSystemMsg = 11058 // 接收系统消息
MtRecvRevokeMsg = 11059 // 接收撤回消息
MtRecvOtherMsg = 11060 // 接收其他未知消息
MtRecvOtherAppMsg = 11061 // 接收应用类型未知消息
MtAddFriendMsg = 11062 // 发送加好友消息
MtModFriendRemarkMsg = 11063 // 发送修改好友备注消息
MtDelFriendMsg = 11064 // 发送删除好友消息
MtAcceptFriendMsg = 11065 // 发送同意加好友申请消息
MtAcceptWcpayMsg = 11066 // 发送接收好友转帐消息
MtAcceptRoomMsg = 11067 // 发送同意进群邀请消息
MtCreateRoomMsg = 11068 // 发送创建群聊消息
MtInviteToRoomMsg = 11069 // 发送邀请好友进群消息40人以下
MtInviteToRoomReqMsg = 11070 // 发送邀请好友进群消息40人以上
MtDelRoomMemberMsg = 11071 // 发送删除群成员消息
MtModRoomNameMsg = 11072 // 发送修改群名称消息
MtModRoomNoticeMsg = 11073 // 发送修改群通知消息
MtModRoomMemberNameMsg = 11074 // 发送修改我在本群的昵称消息
MtModRoomShowNameMsg = 11075 // 发送修改显示群昵称消息
MtSaveRoomToContactMsg = 11076 // 发送保存到联系人消息
MtQuitDelRoomMsg = 11077 // 发送退出并删除群消息
MtModRecvNotifyMsg = 11078 // 发送消息免打扰消息
MtModChatSessionTopMsg = 11079 // 发送置顶消息
MtZombieCheckMsg = 11080 // 发送无痕清粉消息
MtAutoAcceptFriendMsg = 11081 // 发送自动同意好友申请消息
MtAutoAcceptWcpayMsg = 11082 // 发送自动同意好友转帐消息
MtAutoAcceptRoomMsg = 11083 // 发送自动进群邀请消息
MtAutoAcceptCardMsg = 11084 // 发送自动加名片消息
MtDecryptImgMsg = 11085 // 发送解密图片消息
MtOpenBrowserMsg = 11086 // 发送打开浏览器消息
MtRefreshLoginQrcode = 11087 // 刷新登录二维码
MtSwitchSessionMsg = 11090 // 发送切换当前会话消息
MtSearchWxUserMsg = 11096 // 搜索微信用户
MtAddSearchUserMsg = 11097 // 添加搜索的微信用户
MtVoiceToTextMsg = 11112 // 语音消息转文本(旧)
MtSendXmlMsg = 11113 // 发送XML原始消息
MtLogoutMsg = 11104 // 发送注销登录消息
MtExitMsg = 11105 // 发送退出微信消息
MtClearChatRecordMsg = 11108 // 清除聊天记录
MtGetCollectListMsg = 11109 // 获取收藏列表
MtSendCollectMsg = 11110 // 发送收藏(旧)
MtSendCollectMsgByMsgId = 11111 // 收藏指定消息(旧)
MtGetWorkWxChatRoomMsg = 11129 // 获取企业微信群
MtGetWorkWxChatRoomMemberMsg = 11130 //获取企业微信群成员
MtGetWorkWxUserListMsg = 11132 // 获取企业微信好友
MtGetChatRoomInviteRelationMsg = 11134 // 获取群成员邀请关系(协议)
MtGetA8KeyMsg = 11135 // A8Key接口
MtGetMiniProgramCodeMsg = 11136 // 获取小程序授权code
MtAddTagMsg = 11137 // 添加标签
MtDeleteTagMsg = 11138 // 删除标签
MtModifyTagMsg = 11139 // 修改标签
MtAddTagToUserMsg = 11140 // 批量给用户加标签
MtGetTagListByWxidMsg = 11141 // 获取指定好友的所有标签
MtGetTagListMsg = 11142 // 获取标签列表
MtGetMomentMsg = 11145 // 获取朋友圈
MtCommentMomentMsg = 11146 // 朋友圈评论
MtLikeMomentMsg = 11147 // 朋友圈点赞
MtSendMomentMsg = 11148 // 朋友圈发表
MtUploadMomentImageMsg = 11149 // 朋友圈上传图片
MtGetFriendMomentMsg = 11150 // 获取好友朋友圈
MtVideoMomentInitMsg = 11160 // 视频号初始化
MtVideoMomentSearchMsg = 11161 // 视频号搜索
MtLiveEnterMsg = 11162 //进入直播间
MtLiveGetChangeInfoMsg = 11163 // 获取直播间变动信息(人气,实时发言等)
MtLiveSendMsg = 11164 // 发送直播间消息
MtVideoMomentFollowMsg = 11167 // 关注博主
MtVideoMomentLikeMsg = 11168 // 视频号点赞
MtVideoMomentVideoDetailMsg = 11169 // 查看视频详细信息(包含评论)
MtVideoMomentUserHomeMsg = 11170 // 视频号用户主页
MtLiveGetOnlineUserMsg = 11172 // 获取直播间在线人员
MtGetFriendDetailMsg = 11174 // 获取好友详细信息(协议)
MtLiveGetShelfMsg = 11186 // 获取直播间货架
MtVideoMomentCreateVirtualNickNameMsg = 11194 // 视频号创建虚拟昵称
MtVideoMomentSwitchVirtualNickNameMsg = 11195 // 视频号切换虚拟昵称
MtVideoMomentDeleteVirtualNickNameMsg = 11197 // 视频号删除虚拟昵称
MtVideoMomentGetSessionIdMsg = 11202 // 获取视频号私信sessionId
MtVideoMomentSendMsg = 11203 // 发送视频号私信
MtCdnSendXmlMsg = 11214 // 发送XML原始消息
MtCdnInitialMsg = 11228 // CDN初始化
MtCdnUploadFileMsg = 11229 // CDN上传
MtCdnDownloadFileMsg = 11230 // CDN下载
MtCdnSendImageMsg = 11231 // 发送图片消息
MtCdnSendVideoMsg = 11233 // 发送视频消息
MtCdnSendFileMsg = 11235 // 发送文件消息
MtCdnSendCardLinkMsg = 11236 // 发送链接卡片消息
MtCdnSendTextMsg = 11237 // 发送文本消息
MtCdnSendLocationMsg = 11238 // 发送位置
MtCdnSendCardMsg = 11239 // 发送名片
MtCdnSendAtTextMsg = 11240 // 发送At消息
MtCdnSendGifMsg = 11241 // 发送动图消息
MtCdnSendMiniProgramMsg = 11242 // 发送小程序
MtCdnSendVideoMomentMsg = 11243 // 发送视频号
MtCdnSendRevokeMsg = 11244 // 撤回消息
MtForwardMsg = 11245 // 转发任意类型消息
MtCreateRoomByProtocolMsg = 11246 // 创建群聊(协议)
MtWorkWxCdnDownloadMsg = 11253 // 企业微信CDN
MtCdnSendGifMsgNew = 11254 // 发送动图消息New
)
type RespJson struct {
Error int `json:"error"`
Msg string `json:"msg"`
Data any `json:"data"`
}
type WxApi struct {
UserInfo UserClientInfo
TimeOut int // 上传大文件时记得手动拉长超时
}
func debugOutput(msg string) {
if GlobalDebug {
slog.Debug(msg)
}
}
// Ping 📡 微信与服务的健康脉动,轻触即刻,安心无边
// 骑上代码的独角兽,驰骋在微信与服务的和谐旋律中;
// 若路遇荆棘错误翩翩WxError的信使将携谜团(-1)翩然而至。
func (*WxApi) Ping() error {
// 抛出魔法飞毯,直抵全球通讯站(GlobalCallUrl)/ping
resp, err := http.Get(GlobalCallUrl + "/ping")
if err != nil {
// 魔法失效WxError的封印(-1)悄然降临,记录下不解之谜
return WxError{-1, err.Error()}
}
defer resp.Body.Close() // 隐身术,抹去所有痕迹,不留下一丝涟漪
// 倾听回响,秘密文字在耳边低语
data, err := io.ReadAll(resp.Body)
if err != nil {
// 文字破碎WxError的警告(-2)再次响起
return WxError{-2, err.Error()}
}
// 古卷解读将回响化为RespJson的智慧之光
rjson := RespJson{}
json.Unmarshal(data, &rjson)
// 密文比对10000是神秘的共鸣密码
if rjson.Error != 10000 {
// 密码失真WxError的困惑(-rjson.Error)引领着归途
return WxError{rjson.Error, rjson.Msg}
}
// 脉动稳健,旅程圆满,一切安好
return nil
}
// GetUserWeChatVersion 探索微信的奥秘维度
// 跨越星辰大海,追寻新版图的圣杯传说;
// 若遭逢风暴空荡的圣杯将裹挟WxError的失落归来。
func (*WxApi) GetUserWeChatVersion() (string, error) {
// 出发,以光年速度驶向微信版本的时空节点
resp, err := http.Get(GlobalCallUrl + "/GetUserWeChatVersion")
if err != nil {
// 时空乱流WxError的幻影(-1)携破碎梦想现身
return "", WxError{-1, err.Error()}
}
defer resp.Body.Close() // 关闭时空裂隙,以防异界侵袭
// 接纳圣杯的微光,倾听宇宙的低语
data, err := io.ReadAll(resp.Body)
if err != nil {
// 信息迷失WxError(-2)的哀歌在虚空中回荡
return "", WxError{-2, err.Error()}
}
// 古老符文解析揭示RespJson的宇宙密语
rjson := RespJson{}
_ = json.Unmarshal(data, &rjson)
// 密令确认10000是真理的指引
if rjson.Error != 10000 {
// 光芒黯淡WxError(-rjson.Error)载着谜团回归
return "", WxError{rjson.Error, rjson.Msg}
}
// 圣杯显现,微信版图的最新座标(version)闪耀而出
return rjson.Data.(map[string]any)["version"].(string), nil
}
// InjectWeChat 微信灵魂注入术,让微信与服务融为一体
// 邀请全球通讯站,完成神秘仪式;
// 若召唤失败WxError的诅咒将随之降临。
func (w *WxApi) InjectWeChat() (u *UserClientInfo, r error) {
sl := make(chan int)
wait := wxInitiativeCallQueue.GetWithSetDefault(loginSuccessMsg, &wxCallQueue{
Send: make(chan string),
Resp: make(chan string),
})
go func() {
go func() {
wait.Send <- "1"
}()
const timeout = 99999
// 等待密信,或迎接时间的审判
select {
case message := <-wait.Resp:
sr := WxLoginInfoResp{}
err := json.Unmarshal([]byte(message), &sr)
if err != nil {
r = WxError{-3, "login timeout"}
sl <- 0
break
}
w.UserInfo = sr.Data
registerPid[sr.Data.Pid] = true
sl <- 1
// return &w.UserInfo, nil
break
case <-time.After(time.Duration(timeout) * time.Second):
r = WxError{-3, "login timeout"}
sl <- 0
break
}
//if w.UserInfo.Wxid != "" || r != nil {
// break
//}
}()
// 释放灵能,向宇宙宣告召唤
resp, err := http.Get(GlobalCallUrl + "/InjectWeChat")
if err != nil {
// 灵能消散WxError的阴霾笼罩(-1)
return nil, WxError{-1, err.Error()}
}
defer resp.Body.Close() // 收敛气息,防止泄露
// 汇聚反馈,领悟回应的奥秘
data, err := io.ReadAll(resp.Body)
if err != nil {
close(wait.Send)
close(wait.Resp)
wxInitiativeCallQueue.Delete(loginSuccessMsg)
// 奥秘难解WxError的迷雾笼罩(-2)
return nil, WxError{-2, err.Error()}
}
<-sl
if r != nil {
return nil, r
}
// 解析神秘符号揭示RespJson的真谛
var rjson RespJson
_ = json.Unmarshal(data, &rjson)
// 检验仪式成功10000为灵能共鸣的证明
if rjson.Error != 10000 {
// 引力失衡WxError的警告回荡
return nil, WxError{rjson.Error, rjson.Msg}
}
// 仪式圆满,灵能注入,无误返回
return &w.UserInfo, nil
}
// sendWeChatData 📨 内部秘法,向微信投递加密情报
// 注册ID、客户端ID、JSON数据及超时时限编织跨越次元的信使
// 若信使迷失WxError的幽灵将悄然而至揭示暗影的谜团。
func (*WxApi) sendWeChatData(registerID, ClientID int, JsonData string, timeout int) (rstr string, rerr error) {
// 符文编织,信使的护甲,信息封存
jsonBytes, _ := json.Marshal(map[string]interface{}{
"ClientId": ClientID,
"JsonData": JsonData,
})
var wait *wxCallQueue
if registerID != 0 {
wait = wxInitiativeCallQueue.GetWithSetDefault(registerID, &wxCallQueue{
Send: make(chan string),
Resp: make(chan string),
})
}
go func() {
go func() {
if registerID != 0 {
wait.Send <- "1"
}
}()
// 飞翔吧,信使!目标:全球通讯站/SendWeChatData
url := GlobalCallUrl + "/SendWeChatData"
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
if err != nil {
rerr = WxError{
ErrorCode: -1,
Message: fmt.Sprintf("Error crafting message: %v", err),
}
return
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
rerr = WxError{
ErrorCode: -2,
Message: fmt.Sprintf("Error delivering message: %v", err),
}
return
}
defer resp.Body.Close()
}()
if registerID != 0 {
if timeout == 0 {
timeout = 999999
}
if timeout > 0 {
select {
case message := <-wait.Resp:
return message, nil
case <-time.After(time.Duration(timeout) * time.Second):
return "", WxError{-3, "request timeout"}
}
}
}
return
}
// internalCall
func (w *WxApi) internalCall(registerID, timeout, Type int, JsonData any, trace any) (string, error) {
send := map[string]interface{}{
"type": Type,
}
if JsonData != nil {
send["data"] = JsonData
}
if trace != nil {
send["trace"] = trace
}
jsonBytes, _ := json.Marshal(send)
return w.sendWeChatData(registerID, 1, string(jsonBytes), timeout)
}