1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/ivy-1996-openwechat

Клонировать/Скачать
caller.go 21 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
多吃点苹果 Отправлено 10.06.2024 05:22 afd0c22
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
package openwechat
import (
"bytes"
"context"
"encoding/json"
"encoding/xml"
"errors"
"io"
"net/url"
"os"
)
// Caller 调用请求和解析请求
// 上层模块可以直接获取封装后的请求结果
type Caller struct {
Client *Client
}
// NewCaller Constructor for Caller
func NewCaller(client *Client) *Caller {
return &Caller{Client: client}
}
// DefaultCaller Default Constructor for Caller
func DefaultCaller() *Caller {
return NewCaller(DefaultClient())
}
// GetLoginUUID 获取登录的uuid
func (c *Caller) GetLoginUUID(ctx context.Context) (string, error) {
resp, err := c.Client.GetLoginUUID(ctx)
if err != nil {
return "", err
}
defer func() { _ = resp.Body.Close() }()
var buffer bytes.Buffer
if _, err = buffer.ReadFrom(resp.Body); err != nil {
return "", err
}
// 正则匹配uuid字符串
results := uuidRegexp.FindSubmatch(buffer.Bytes())
if len(results) != 2 {
// 如果没有匹配到,可能微信的接口做了修改,或者当前机器的ip被加入了黑名单
return "", errors.New("uuid does not match")
}
return string(results[1]), nil
}
// CheckLogin 检查是否登录成功
func (c *Caller) CheckLogin(ctx context.Context, uuid, tip string) (CheckLoginResponse, error) {
resp, err := c.Client.CheckLogin(ctx, uuid, tip)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
var buffer bytes.Buffer
if _, err := buffer.ReadFrom(resp.Body); err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
// GetLoginInfo 获取登录信息
func (c *Caller) GetLoginInfo(ctx context.Context, path *url.URL) (*LoginInfo, error) {
// 从响应体里面获取需要跳转的url
query := path.Query()
query.Set("version", "v2")
path.RawQuery = query.Encode()
resp, err := c.Client.GetLoginInfo(ctx, path)
if err != nil {
return nil, err
}
// 微信 v2 版本修复了301 response missing Location header 的问题
defer func() { _ = resp.Body.Close() }()
bs, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var loginInfo LoginInfo
// xml结构体序列化储存
// 为什么这里不直接使用resp.Body?
// 因为要确保传入的reader实现了 io.ByteReader 接口
// https://github.com/eatmoreapple/openwechat/pull/345
if err = xml.NewDecoder(bytes.NewBuffer(bs)).Decode(&loginInfo); err != nil {
return nil, err
}
if err = loginInfo.Err(); err != nil {
return nil, err
}
// set domain
c.Client.Domain = WechatDomain(path.Host)
return &loginInfo, nil
}
// WebInit 获取初始化信息
func (c *Caller) WebInit(ctx context.Context, request *BaseRequest) (*WebInitResponse, error) {
resp, err := c.Client.WebInit(ctx, request)
if err != nil {
return nil, err
}
var webInitResponse WebInitResponse
defer func() { _ = resp.Body.Close() }()
if err = json.NewDecoder(resp.Body).Decode(&webInitResponse); err != nil {
return nil, err
}
if err = webInitResponse.BaseResponse.Err(); err != nil {
return nil, err
}
return &webInitResponse, nil
}
type CallerCommonOptions struct {
BaseRequest *BaseRequest
WebInitResponse *WebInitResponse
LoginInfo *LoginInfo
}
type CallerWebWxStatusNotifyOptions CallerCommonOptions
// WebWxStatusNotify 通知手机已登录
func (c *Caller) WebWxStatusNotify(ctx context.Context, opt *CallerWebWxStatusNotifyOptions) error {
notifyOpt := &ClientWebWxStatusNotifyOptions{
BaseRequest: opt.BaseRequest,
WebInitResponse: opt.WebInitResponse,
LoginInfo: opt.LoginInfo,
}
resp, err := c.Client.WebWxStatusNotify(ctx, notifyOpt)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
type CallerSyncCheckOptions CallerCommonOptions
// SyncCheck 异步获取是否有新的消息
func (c *Caller) SyncCheck(ctx context.Context, opt *CallerSyncCheckOptions) (*SyncCheckResponse, error) {
syncCheckOption := &ClientSyncCheckOptions{
BaseRequest: opt.BaseRequest,
WebInitResponse: opt.WebInitResponse,
LoginInfo: opt.LoginInfo,
}
resp, err := c.Client.SyncCheck(ctx, syncCheckOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
var buffer bytes.Buffer
if _, err = buffer.ReadFrom(resp.Body); err != nil {
return nil, err
}
return NewSyncCheckResponse(buffer.Bytes())
}
// WebWxGetContact 获取所有的联系人
func (c *Caller) WebWxGetContact(ctx context.Context, info *LoginInfo) (Members, error) {
var members Members
var reqs int64
for {
resp, err := c.Client.WebWxGetContact(ctx, info.SKey, reqs)
if err != nil {
return nil, err
}
var item WebWxContactResponse
if err = json.NewDecoder(resp.Body).Decode(&item); err != nil {
_ = resp.Body.Close()
return nil, err
}
if err = resp.Body.Close(); err != nil {
return nil, err
}
if err = item.BaseResponse.Err(); err != nil {
return nil, err
}
members = append(members, item.MemberList...)
if item.Seq == 0 || item.Seq == reqs {
break
}
reqs = item.Seq
}
return members, nil
}
// WebWxBatchGetContact 获取联系人的详情
// 注: Members参数的长度不要大于50
func (c *Caller) WebWxBatchGetContact(ctx context.Context, members Members, request *BaseRequest) (Members, error) {
resp, err := c.Client.WebWxBatchGetContact(ctx, members, request)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
var item WebWxBatchContactResponse
if err = json.NewDecoder(resp.Body).Decode(&item); err != nil {
return nil, err
}
if err = item.BaseResponse.Err(); err != nil {
return nil, err
}
return item.ContactList, nil
}
type CallerWebWxSyncOptions CallerCommonOptions
// WebWxSync 获取新的消息接口
func (c *Caller) WebWxSync(ctx context.Context, opt *CallerWebWxSyncOptions) (*WebWxSyncResponse, error) {
wxSyncOption := &ClientWebWxSyncOptions{
BaseRequest: opt.BaseRequest,
WebInitResponse: opt.WebInitResponse,
LoginInfo: opt.LoginInfo,
}
resp, err := c.Client.WebWxSync(ctx, wxSyncOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
var webWxSyncResponse WebWxSyncResponse
if err = json.NewDecoder(resp.Body).Decode(&webWxSyncResponse); err != nil {
return nil, err
}
return &webWxSyncResponse, nil
}
type CallerWebWxSendMsgOptions struct {
LoginInfo *LoginInfo
BaseRequest *BaseRequest
Message *SendMessage
}
// WebWxSendMsg 发送消息接口
func (c *Caller) WebWxSendMsg(ctx context.Context, opt *CallerWebWxSendMsgOptions) (*SentMessage, error) {
wxSendMsgOption := &ClientWebWxSendMsgOptions{
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
Message: opt.Message,
}
resp, err := c.Client.WebWxSendMsg(ctx, wxSendMsgOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.SentMessage(opt.Message)
}
// WebWxSendEmoticon 发送表情接口
func (c *Caller) WebWxSendEmoticon(ctx context.Context, md5 string, reader io.Reader, opt *CallerWebWxSendAppMsgOptions) (*SentMessage, error) {
md5OrMediaid := md5
if reader != nil {
file, cb, err := readerToFile(reader)
if err != nil {
return nil, err
}
defer cb()
// 首先尝试上传图片
var mediaId string
{
uploadMediaOption := &CallerUploadMediaOptions{
FromUserName: opt.FromUserName,
ToUserName: opt.ToUserName,
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
}
resp, err := c.UploadMedia(ctx, file, uploadMediaOption)
if err != nil {
return nil, err
}
mediaId = resp.MediaId
}
md5OrMediaid = mediaId
}
msg := NewEmoticonSendMessage(opt.FromUserName, opt.ToUserName, md5OrMediaid)
wxSendMsgOption := &ClientWebWxSendMsgOptions{
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
Message: msg,
}
resp, err := c.Client.WebWxSendEmoticon(ctx, wxSendMsgOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.SentMessage(msg)
}
type CallerWebWxOplogOptions struct {
RemarkName string
ToUserName string
BaseRequest *BaseRequest
}
// WebWxOplog 修改用户备注接口
func (c *Caller) WebWxOplog(ctx context.Context, opt *CallerWebWxOplogOptions) error {
wxOpLogOption := &ClientWebWxOplogOption{
RemarkName: opt.RemarkName,
UserName: opt.ToUserName,
BaseRequest: opt.BaseRequest,
}
resp, err := c.Client.WebWxOplog(ctx, wxOpLogOption)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
type CallerUploadMediaOptions struct {
FromUserName string
ToUserName string
BaseRequest *BaseRequest
LoginInfo *LoginInfo
}
func (c *Caller) UploadMedia(ctx context.Context, file *os.File, opt *CallerUploadMediaOptions) (*UploadResponse, error) {
// 首先尝试上传图片
clientWebWxUploadMediaByChunkOpt := &ClientWebWxUploadMediaByChunkOptions{
FromUserName: opt.FromUserName,
ToUserName: opt.ToUserName,
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
}
resp, err := c.Client.WebWxUploadMediaByChunk(ctx, file, clientWebWxUploadMediaByChunkOpt)
// 无错误上传成功之后获取请求结果,判断结果是否正常
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
var item UploadResponse
if err = json.NewDecoder(resp.Body).Decode(&item); err != nil {
return &item, err
}
if err = item.BaseResponse.Err(); err != nil {
return &item, err
}
if len(item.MediaId) == 0 {
return &item, errors.New("upload failed")
}
return &item, nil
}
type CallerUploadMediaCommonOptions struct {
FromUserName string
ToUserName string
BaseRequest *BaseRequest
LoginInfo *LoginInfo
}
type CallerWebWxSendImageMsgOptions CallerUploadMediaCommonOptions
// WebWxSendImageMsg 发送图片消息接口
func (c *Caller) WebWxSendImageMsg(ctx context.Context, reader io.Reader, opt *CallerWebWxSendImageMsgOptions) (*SentMessage, error) {
file, cb, err := readerToFile(reader)
if err != nil {
return nil, err
}
defer cb()
// 首先尝试上传图片
var mediaId string
{
uploadMediaOption := &CallerUploadMediaOptions{
FromUserName: opt.FromUserName,
ToUserName: opt.ToUserName,
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
}
resp, err := c.UploadMedia(ctx, file, uploadMediaOption)
if err != nil {
return nil, err
}
mediaId = resp.MediaId
}
// 构造新的图片类型的信息
msg := NewMediaSendMessage(MsgTypeImage, opt.FromUserName, opt.ToUserName, mediaId)
// 发送图片信息
sendImageOption := &ClientWebWxSendMsgOptions{
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
Message: msg,
}
resp, err := c.Client.WebWxSendMsgImg(ctx, sendImageOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.SentMessage(msg)
}
type CallerWebWxSendFileOptions CallerUploadMediaCommonOptions
func (c *Caller) WebWxSendFile(ctx context.Context, reader io.Reader, opt *CallerWebWxSendFileOptions) (*SentMessage, error) {
file, cb, err := readerToFile(reader)
if err != nil {
return nil, err
}
defer cb()
uploadMediaOption := &CallerUploadMediaOptions{
FromUserName: opt.FromUserName,
ToUserName: opt.ToUserName,
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
}
resp, err := c.UploadMedia(ctx, file, uploadMediaOption)
if err != nil {
return nil, err
}
// 构造新的文件类型的信息
stat, _ := file.Stat()
appMsg := newFileAppMessage(stat, resp.MediaId)
content, err := appMsg.XmlByte()
if err != nil {
return nil, err
}
msg := NewSendMessage(AppMessage, string(content), opt.FromUserName, opt.ToUserName, "")
return c.WebWxSendAppMsg(ctx, msg, opt.BaseRequest)
}
type CallerWebWxSendAppMsgOptions CallerUploadMediaCommonOptions
func (c *Caller) WebWxSendVideoMsg(ctx context.Context, reader io.Reader, opt *CallerWebWxSendAppMsgOptions) (*SentMessage, error) {
file, cb, err := readerToFile(reader)
if err != nil {
return nil, err
}
defer cb()
var mediaId string
{
uploadMediaOption := &CallerUploadMediaOptions{
FromUserName: opt.FromUserName,
ToUserName: opt.ToUserName,
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
}
resp, err := c.UploadMedia(ctx, file, uploadMediaOption)
if err != nil {
return nil, err
}
mediaId = resp.MediaId
}
// 构造新的图片类型的信息
msg := NewMediaSendMessage(MsgTypeVideo, opt.FromUserName, opt.ToUserName, mediaId)
resp, err := c.Client.WebWxSendVideoMsg(ctx, opt.BaseRequest, msg)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.SentMessage(msg)
}
// WebWxSendAppMsg 发送媒体消息
func (c *Caller) WebWxSendAppMsg(ctx context.Context, msg *SendMessage, req *BaseRequest) (*SentMessage, error) {
resp, err := c.Client.WebWxSendAppMsg(ctx, msg, req)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.SentMessage(msg)
}
// Logout 用户退出
func (c *Caller) Logout(ctx context.Context, info *LoginInfo) error {
resp, err := c.Client.Logout(ctx, info)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
type CallerAddFriendIntoChatRoomOptions struct {
BaseRequest *BaseRequest
LoginInfo *LoginInfo
Group *Group
GroupLength int
Friends []*Friend
}
// AddFriendIntoChatRoom 拉好友入群
func (c *Caller) AddFriendIntoChatRoom(ctx context.Context, opt *CallerAddFriendIntoChatRoomOptions) error {
if len(opt.Friends) == 0 {
return errors.New("no friends found")
}
inviteMemberList := make([]string, len(opt.Friends))
for i, friend := range opt.Friends {
inviteMemberList[i] = friend.UserName
}
clientAddMemberIntoChatRoomOption := &ClientAddMemberIntoChatRoomOption{
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
Group: opt.Group.UserName,
GroupLength: opt.GroupLength,
InviteMemberList: inviteMemberList,
}
resp, err := c.Client.AddMemberIntoChatRoom(ctx, clientAddMemberIntoChatRoomOption)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
type CallerRemoveFriendFromChatRoomOptions struct {
BaseRequest *BaseRequest
LoginInfo *LoginInfo
Group *Group
Members []*User
}
// RemoveFriendFromChatRoom 从群聊中移除用户
func (c *Caller) RemoveFriendFromChatRoom(ctx context.Context, opt *CallerRemoveFriendFromChatRoomOptions) error {
if len(opt.Members) == 0 {
return errors.New("no users found")
}
users := make([]string, len(opt.Members))
for i, member := range opt.Members {
users[i] = member.UserName
}
req := &ClientRemoveMemberFromChatRoomOption{
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
Group: opt.Group.UserName,
DelMemberList: users,
}
resp, err := c.Client.RemoveMemberFromChatRoom(ctx, req)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
type CallerWebWxVerifyUserOptions struct {
VerifyContent string
RecommendInfo RecommendInfo
BaseRequest *BaseRequest
LoginInfo *LoginInfo
}
// WebWxVerifyUser 同意加好友请求
func (c *Caller) WebWxVerifyUser(ctx context.Context, opt *CallerWebWxVerifyUserOptions) error {
webWxVerifyUserOption := &ClientWebWxVerifyUserOption{
BaseRequest: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
VerifyContent: opt.VerifyContent,
RecommendInfo: opt.RecommendInfo,
}
resp, err := c.Client.WebWxVerifyUser(ctx, webWxVerifyUserOption)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
// WebWxRevokeMsg 撤回消息操作
func (c *Caller) WebWxRevokeMsg(ctx context.Context, msg *SentMessage, request *BaseRequest) error {
resp, err := c.Client.WebWxRevokeMsg(ctx, msg, request)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
type CallerWebWxStatusAsReadOptions struct {
BaseRequest *BaseRequest
LoginInfo *LoginInfo
Message *Message
}
// WebWxStatusAsRead 将消息设置为已读
func (c *Caller) WebWxStatusAsRead(ctx context.Context, opt *CallerWebWxStatusAsReadOptions) error {
statusAsReadOption := &ClientWebWxStatusAsReadOption{
Request: opt.BaseRequest,
LoginInfo: opt.LoginInfo,
Message: opt.Message,
}
resp, err := c.Client.WebWxStatusAsRead(ctx, statusAsReadOption)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
type CallerWebWxRelationPinOptions struct {
BaseRequest *BaseRequest
User *User
Op uint8
}
// WebWxRelationPin 将联系人是否置顶
func (c *Caller) WebWxRelationPin(ctx context.Context, opt *CallerWebWxRelationPinOptions) error {
webWxRelationPinOption := &ClientWebWxRelationPinOption{
Request: opt.BaseRequest,
Op: opt.Op,
RemarkName: opt.User.RemarkName,
UserName: opt.User.UserName,
}
resp, err := c.Client.WebWxRelationPin(ctx, webWxRelationPinOption)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
// WebWxPushLogin 免扫码登陆接口
func (c *Caller) WebWxPushLogin(ctx context.Context, uin int64) (*PushLoginResponse, error) {
resp, err := c.Client.WebWxPushLogin(ctx, uin)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
var item PushLoginResponse
if err = json.NewDecoder(resp.Body).Decode(&item); err != nil {
return nil, err
}
return &item, nil
}
type CallerWebWxCreateChatRoomOptions struct {
BaseRequest *BaseRequest
LoginInfo *LoginInfo
Topic string
Friends Friends
}
// WebWxCreateChatRoom 创建群聊
func (c *Caller) WebWxCreateChatRoom(ctx context.Context, opt *CallerWebWxCreateChatRoomOptions) (*Group, error) {
if len(opt.Friends) == 0 {
return nil, errors.New("create group with no friends")
}
friends := make([]string, len(opt.Friends))
for i, friend := range opt.Friends {
friends[i] = friend.UserName
}
webWxCreateChatRoomOption := &ClientWebWxCreateChatRoomOption{
Request: opt.BaseRequest,
Topic: opt.Topic,
Friends: friends,
LoginInfo: opt.LoginInfo,
}
resp, err := c.Client.WebWxCreateChatRoom(ctx, webWxCreateChatRoomOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
var item struct {
BaseResponse BaseResponse
ChatRoomName string
}
if err = json.NewDecoder(resp.Body).Decode(&item); err != nil {
return nil, err
}
if err = item.BaseResponse.Err(); err != nil {
return nil, err
}
group := Group{User: &User{UserName: item.ChatRoomName}}
return &group, nil
}
type CallerWebWxRenameChatRoomOptions struct {
NewTopic string
BaseRequest *BaseRequest
LoginInfo *LoginInfo
Group *Group
}
// WebWxRenameChatRoom 群组重命名
func (c *Caller) WebWxRenameChatRoom(ctx context.Context, opt *CallerWebWxRenameChatRoomOptions) error {
webWxRenameChatRoomOption := &ClientWebWxRenameChatRoomOption{
Request: opt.BaseRequest,
NewTopic: opt.NewTopic,
Group: opt.Group.UserName,
LoginInfo: opt.LoginInfo,
}
resp, err := c.Client.WebWxRenameChatRoom(ctx, webWxRenameChatRoomOption)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
parser := MessageResponseParser{resp.Body}
return parser.Err()
}
// SetMode 设置Client的模式
func (c *Client) SetMode(mode Mode) {
c.mode = mode
}
// MessageResponseParser 消息响应解析器
type MessageResponseParser struct {
Reader io.Reader
}
// Err 解析错误
func (p *MessageResponseParser) Err() error {
var item struct{ BaseResponse BaseResponse }
if err := json.NewDecoder(p.Reader).Decode(&item); err != nil {
return err
}
if err := item.BaseResponse.Err(); err != nil {
return err
}
return nil
}
// MsgID 解析消息ID
func (p *MessageResponseParser) MsgID() (string, error) {
var messageResp MessageResponse
if err := json.NewDecoder(p.Reader).Decode(&messageResp); err != nil {
return "", err
}
if err := messageResp.BaseResponse.Err(); err != nil {
return "", err
}
return messageResp.MsgID, nil
}
// SentMessage 返回 SentMessage
func (p *MessageResponseParser) SentMessage(msg *SendMessage) (*SentMessage, error) {
msgID, err := p.MsgID()
if err != nil {
return nil, err
}
return &SentMessage{MsgId: msgID, SendMessage: msg}, nil
}
func readerToFile(reader io.Reader) (file *os.File, cb func(), err error) {
var ok bool
if file, ok = reader.(*os.File); ok {
return file, func() {}, nil
}
file, err = os.CreateTemp("", "*")
if err != nil {
return nil, nil, err
}
cb = func() {
_ = file.Close()
_ = os.Remove(file.Name())
}
_, err = io.Copy(file, reader)
if err != nil {
cb()
return nil, nil, err
}
_, err = file.Seek(0, io.SeekStart)
if err != nil {
cb()
return nil, nil, err
}
return file, cb, nil
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/ivy-1996-openwechat.git
git@api.gitlife.ru:oschina-mirror/ivy-1996-openwechat.git
oschina-mirror
ivy-1996-openwechat
ivy-1996-openwechat
master