package openwechat import ( "errors" "fmt" "net/url" ) /* 一些网络返回信息的封装 */ // LoginInfo 登录信息 type LoginInfo struct { Ret int `xml:"ret"` WxUin int64 `xml:"wxuin"` IsGrayScale int `xml:"isgrayscale"` Message string `xml:"message"` SKey string `xml:"skey"` WxSid string `xml:"wxsid"` PassTicket string `xml:"pass_ticket"` } func (l LoginInfo) Ok() bool { return l.Ret == 0 } func (l LoginInfo) Err() error { if l.Ok() { return nil } return errors.New(l.Message) } // BaseRequest 初始的请求信息 // 几乎所有的请求都要携带该参数 type BaseRequest struct { Uin int64 Sid, Skey, DeviceID string } type SyncKey struct { Count int List []struct{ Key, Val int64 } } // WebInitResponse 初始化的相应信息 type WebInitResponse struct { Count int ClientVersion int GrayScale int InviteStartCount int MPSubscribeMsgCount int ClickReportInterval int SystemTime int64 ChatSet string SKey string BaseResponse BaseResponse SyncKey SyncKey User *User MPSubscribeMsgList []*MPSubscribeMsg ContactList Members } // MPSubscribeMsg 公众号的订阅信息 type MPSubscribeMsg struct { MPArticleCount int Time int64 UserName string NickName string MPArticleList []*MPArticle } type MPArticle struct { Title string Cover string Digest string Url string } type UserDetailItem struct { UserName string EncryChatRoomId string } type UserDetailItemList []UserDetailItem func NewUserDetailItemList(members Members) UserDetailItemList { var list = make(UserDetailItemList, len(members)) for index, member := range members { item := UserDetailItem{UserName: member.UserName, EncryChatRoomId: member.EncryChatRoomId} list[index] = item } return list } type WebWxSyncResponse struct { AddMsgCount int ContinueFlag int DelContactCount int ModChatRoomMemberCount int ModContactCount int Skey string SyncCheckKey SyncKey SyncKey SyncKey BaseResponse BaseResponse ModChatRoomMemberList Members AddMsgList []*Message } type WebWxContactResponse struct { MemberCount int Seq int64 BaseResponse BaseResponse MemberList []*User } type WebWxBatchContactResponse struct { Count int BaseResponse BaseResponse ContactList []*User } // CheckLoginResponse 检查登录状态的响应body type CheckLoginResponse []byte // RedirectURL 重定向的URL func (c CheckLoginResponse) RedirectURL() (*url.URL, error) { code, err := c.Code() if err != nil { return nil, err } if code != LoginCodeSuccess { return nil, fmt.Errorf("expect status code %s, but got %s", LoginCodeSuccess, code) } results := redirectUriRegexp.FindSubmatch(c) if len(results) != 2 { return nil, errors.New("redirect url does not match") } return url.Parse(string(results[1])) } // Code 获取当前的登录检查状态的代码 func (c CheckLoginResponse) Code() (LoginCode, error) { results := statusCodeRegexp.FindSubmatch(c) if len(results) != 2 { return "", errors.New("error status code match") } code := string(results[1]) return LoginCode(code), nil } // Avatar 获取扫码后的用户头像, base64编码 func (c CheckLoginResponse) Avatar() (string, error) { code, err := c.Code() if err != nil { return "", err } if code != LoginCodeScanned { return "", nil } results := avatarRegexp.FindSubmatch(c) if len(results) != 2 { return "", errors.New("avatar does not match") } return string(results[1]), nil } type MessageResponse struct { BaseResponse BaseResponse LocalID string MsgID string } type UploadResponse struct { BaseResponse BaseResponse MediaId string } type PushLoginResponse struct { Ret string `json:"ret"` Msg string `json:"msg"` UUID string `json:"uuid"` } func (p PushLoginResponse) Ok() bool { return p.Ret == "0" && p.UUID != "" } func (p PushLoginResponse) Err() error { if p.Ok() { return nil } return errors.New(p.Msg) }