tt/core/callapi.go
2024-05-28 08:47:31 +08:00

382 lines
16 KiB
Go
Raw Permalink 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 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)
}