diff --git a/README.md b/README.md index 6c10ed9..75b8495 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # wechatcmd [![star this repo](http://github-svg-buttons.herokuapp.com/star.svg?user=liushuchun&repo=wechatcmd&style=flat&background=1081C1)](http://github.com/liushuchun/wechatcmd) [![fork this repo](http://github-svg-buttons.herokuapp.com/fork.svg?user=liushuchun&repo=wechatcmd&style=flat&background=1081C1)](http://github.com/liushuchun/wechatcmd/fork) ![Build](https://img.shields.io/appveyor/ci/gruntjs/grunt.svg) ================= ## 微信命令行版本 -开发这个命令行版本,是为了更加方便聊天哦,对于习惯用命令行的同学,可能会比较喜欢。 +开发这个命令行版本,一是为了熟悉微信的接口,二是方便咱们习惯命令行的同学。 -项目还是半成品,欢迎有兴趣的朋友一起加入开发。 +项目还是远未完成,热烈欢迎有兴趣的朋友一起加入开发。 -有什么建议可以提pr。谢谢。 +有什么建议可以提issue。谢谢,也欢迎直接提PR。 ### 功能特性 diff --git a/main.go b/main.go index 3f269ea..790a9fd 100644 --- a/main.go +++ b/main.go @@ -92,6 +92,7 @@ func main() { logger.Fatalf("拉取联系人失败:%v\n", err) return } + if err := wechat.TestCheck(); err != nil { logger.Fatalf("检查状态失败:%v\n", err) return diff --git a/ui/layout.go b/ui/layout.go index e2fb7da..21fd121 100644 --- a/ui/layout.go +++ b/ui/layout.go @@ -171,12 +171,15 @@ func (l *Layout) displayMsgIn() { case msg = <-l.chatIn: fmt.Println("聊天消息进入:%v", msg) case msg = <-l.msgIn: - fmt.Println("各类消息进入:%v", msg) + text := msg.String() + l.msgInBox.Text = l.msgInBox.Text + text + ui.Render(l.msgInBox) case <-l.closeChan: break } } + return } func (l *Layout) NextUser() { diff --git a/wechat/wechat.go b/wechat/wechat.go index 7de9ef5..a0e016b 100644 --- a/wechat/wechat.go +++ b/wechat/wechat.go @@ -61,14 +61,14 @@ type Wechat struct { SyncHost string SyncKey SyncKey Users []string - InitContactList []User //谈话的人 - MemberList []*Member // - ContactList []User //好友 - GroupList []string //群 - GroupMemberList []string //群友 - PublicUserList []User //公众号 - SpecialUserList []User //特殊账号 - AutoReplyMode bool //default false + InitContactList []User //谈话的人 + MemberList []Member // + ContactList []Member //好友 + GroupList []string //群 + GroupMemberList []string //群友 + PublicUserList []Member //公众号 + SpecialUserList []Member //特殊账号 + AutoReplyMode bool //default false AutoOpen bool Interactive bool TotalMember int @@ -79,6 +79,8 @@ type Wechat struct { Client *http.Client Request *BaseRequest Log *log.Logger + MemberMap map[string]Member + ChatSet []string } func NewWechat(logger *log.Logger) *Wechat { @@ -110,6 +112,7 @@ func NewWechat(logger *log.Logger) *Wechat { SaveFolder: path.Join(root, "saved"), QrImagePath: filepath.Join(root, "qr.jpg"), Log: logger, + MemberMap: make(map[string]Member), } } @@ -287,6 +290,8 @@ func (w *Wechat) Login() (err error) { for _, contact := range newResp.ContactList { w.InitContactList = append(w.InitContactList, contact) } + + w.ChatSet = strings.Split(newResp.ChatSet, ",") w.User = newResp.User w.SyncKey = newResp.SyncKey w.SyncKeyStr = "" diff --git a/wechat/wechat_func.go b/wechat/wechat_func.go index a9a97b0..6ab26c8 100644 --- a/wechat/wechat_func.go +++ b/wechat/wechat_func.go @@ -11,6 +11,7 @@ import ( "net/url" "regexp" "strconv" + "strings" "time" ) @@ -21,16 +22,57 @@ func (w *Wechat) GetContacts() (err error) { if err := w.Send(apiURI, nil, resp); err != nil { return err } - w.MemberList, w.TotalMember = make([]*Member, 0, resp.MemberCount/5*2), resp.MemberCount - for _, member := range resp.MemberList { - if member.IsNormal(w.User.UserName) { - w.MemberList = append(w.MemberList, member) + + w.MemberList = resp.MemberList + w.TotalMember = resp.MemberCount + for _, member := range w.MemberList { + w.MemberMap[member.UserName] = member + } + + for _, user := range w.ChatSet { + exist := false + for _, initUser := range w.InitContactList { + if user == initUser.UserName { + exist = true + break + } } + if !exist { + value, ok := w.MemberMap[user] + if ok { + contact := User{ + UserName: value.UserName, + NickName: value.NickName, + Signature: value.Signature, + } + + w.InitContactList = append(w.InitContactList, contact) + } + } + } + return } -func (w *Wechat) getSyncMsg() (msgs []Message, err error) { +func (w *Wechat) getRoomMembers(roomID string) (map[string]string, error) { + url := fmt.Sprintf("%s/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s", w.BaseUri, w.GetUnixTime(), w.Request.PassTicket) + params := make(map[string]interface{}) + params["BaseRequest"] = *w.Request + params["Count"] = 1 + params["List"] = []map[string]string{} + l := []map[string]string{} + params["List"] = append(l, map[string]string{ + "UserName": roomID, + "ChatRoomId": "", + }) + members := []string{} + stats := make(map[string]string) + fmt.Println(members, stats, url) + return nil, nil +} + +func (w *Wechat) getSyncMsg() (msgs []interface{}, err error) { name := "webwxsync" syncResp := new(SyncResp) url := fmt.Sprintf("%s/%s?sid=%s&pass_ticket=%s&skey=%s", w.BaseUri, name, w.Request.Wxsid, w.Request.PassTicket, w.Request.Skey) @@ -88,8 +130,33 @@ func (w *Wechat) SyncDaemon(msgIn chan Message) { w.Log.Printf("w.getSyncMsg() error:%+v\n", err) } - for _, msg := range msgs { - msgIn <- msg + for _, m := range msgs { + msg := Message{} + msgType := m.(map[string]interface{})["MsgType"].(float64) + msg.MsgType = int(msgType) + msg.FromUserName = m.(map[string]interface{})["FromUserName"].(string) + if nickNameFrom, ok := w.MemberMap[msg.FromUserName]; ok { + msg.FromUserNickName = nickNameFrom.NickName + } + + msg.ToUserName = m.(map[string]interface{})["ToUserName"].(string) + if nickNameTo, ok := w.MemberMap[msg.ToUserName]; ok { + msg.ToUserNickName = nickNameTo.NickName + } + + msg.Content = m.(map[string]interface{})["Content"].(string) + msg.Content = strings.Replace(msg.Content, "<", "<", -1) + msg.Content = strings.Replace(msg.Content, ">", ">", -1) + msg.Content = strings.Replace(msg.Content, " ", " ", 1) + if msg.MsgType == 1 { + msgIn <- msg + if msg.FromUserName[:2] == "@@" { + //群消息,暂时不处理 + } else { + + } + } + } case 4: //通讯录更新 w.GetContacts() @@ -102,10 +169,12 @@ func (w *Wechat) SyncDaemon(msgIn chan Message) { } default: w.Log.Printf("the resp:%+v", resp) + time.Sleep(time.Second * 4) + continue } - time.Sleep(time.Second * 4) + } } diff --git a/wechat/wechat_params.go b/wechat/wechat_params.go index 94c9f46..a4f27da 100644 --- a/wechat/wechat_params.go +++ b/wechat/wechat_params.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "strings" - "time" ) type Config struct { @@ -40,10 +39,12 @@ type Message struct { MediaId string FileName string FileSize string + FromUserNickName string + ToUserNickName string } func (m Message) String() string { - return time.Now().Format("2006-01-02 15:04:05") + " " + m.FromUserName + "->" + m.ToUserName + ":\n " + m.Content + "\n" + return m.FromUserNickName + "->" + m.ToUserNickName + ":\n " + m.Content + "\n" } type AppInfo struct { @@ -129,33 +130,11 @@ func (r *Response) Error() error { return fmt.Errorf("message:[%s]", r.BaseResponse.ErrMsg) } -type User struct { - UserName string `json:"UserName"` - Uin int `json:"Uin"` - NickName string `json:"NickName"` - HeadImgUrl string `json:"HeadImgUrl" xml:""` - RemarkName string `json:"RemarkName" xml:""` - PYInitial string `json:"PYInitial" xml:""` - PYQuanPin string `json:"PYQuanPin" xml:""` - RemarkPYInitial string `json:"RemarkPYInitial" xml:""` - RemarkPYQuanPin string `json:"RemarkPYQuanPin" xml:""` - HideInputBarFlag int `json:"HideInputBarFlag" xml:""` - StarFriend int `json:"StarFriend" xml:""` - Sex int `json:"Sex" xml:""` - Signature string `json:"Signature" xml:""` - AppAccountFlag int `json:"AppAccountFlag" xml:""` - VerifyFlag int `json:"VerifyFlag" xml:""` - ContactFlag int `json:"ContactFlag" xml:""` - WebWxPluginSwitch int `json:"WebWxPluginSwitch" xml:""` - HeadImgFlag int `json:"HeadImgFlag" xml:""` - SnsFlag int `json:"SnsFlag" xml:""` -} - type MemberResp struct { Response MemberCount int ChatRoomName string - MemberList []*Member + MemberList []Member Seq int } @@ -175,6 +154,28 @@ func (this *Member) IsSpecail() bool { return false } +type User struct { + UserName string `json:"UserName"` + Uin int `json:"Uin"` + NickName string `json:"NickName"` + HeadImgUrl string `json:"HeadImgUrl" xml:""` + RemarkName string `json:"RemarkName" xml:""` + PYInitial string `json:"PYInitial" xml:""` + PYQuanPin string `json:"PYQuanPin" xml:""` + RemarkPYInitial string `json:"RemarkPYInitial" xml:""` + RemarkPYQuanPin string `json:"RemarkPYQuanPin" xml:""` + HideInputBarFlag int `json:"HideInputBarFlag" xml:""` + StarFriend int `json:"StarFriend" xml:""` + Sex int `json:"Sex" xml:""` + Signature string `json:"Signature" xml:""` + AppAccountFlag int `json:"AppAccountFlag" xml:""` + VerifyFlag int `json:"VerifyFlag" xml:""` + ContactFlag int `json:"ContactFlag" xml:""` + WebWxPluginSwitch int `json:"WebWxPluginSwitch" xml:""` + HeadImgFlag int `json:"HeadImgFlag" xml:""` + SnsFlag int `json:"SnsFlag" xml:""` +} + type Member struct { Uin int UserName string @@ -229,9 +230,9 @@ type SyncParams struct { type SyncResp struct { Response - SyncKey SyncKey `json:"SyncKey"` - ContinueFlag int `json:"ContinueFlag"` - AddMsgList []Message `json:"AddMsgList"` + SyncKey SyncKey `json:"SyncKey"` + ContinueFlag int `json:"ContinueFlag"` + AddMsgList []interface{} `json:"AddMsgList"` } type NotifyResp struct {