天天看點

微信聊天記錄導出

public class Client
    {
        public Client(User user)
        {
            this.User = user;
            this.HttpHelper = new HttpHelper(Encoding.UTF8);
        }

        public User User { get; private set; }

        public HttpHelper HttpHelper { get; private set; }

        public bool IsLogin { get; private set; }

        public string Token { get; private set; }

        private string frommsgid;

        private readonly static string loginUrl = "https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN";
        private readonly static string loginActiveUrl = "https://mp.weixin.qq.com/cgi-bin/login";
        private readonly static string messageUrl = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&count=20&day=7&token={0}&lang=zh_CN";
        private readonly static string messagePageUrl = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&action=&keyword=&frommsgid={0}&offset={1}&count=20&day=7&filterivrmsg=&token={2}&lang=zh_CN";

        private Regex pageTotalRegex = new Regex("total_count : (?<value>\\d+),");
        private Regex msgRegex = new Regex("list : [(](?<value>[\\s\\S]+?)[)].msg_item");
        private Regex tokenRegex = new Regex("token=(?<value>\\d+)");
        private Regex fidRegex = new Regex("frommsgid[\\s]?:[\\s]?\"(?<value>\\d+)\"");

        public void Login()
        {
            IsLogin = false;
            string data = string.Format("username={0}&pwd={1}&imgcode=&f=json", User.Uname, User.EnPassword.ToLower());
            HttpHelper.GetHtml(loginUrl);
            string html = HttpHelper.PostHtml(loginActiveUrl, data, "https://mp.weixin.qq.com/");
            LoginResult result = JsonConvert.DeserializeObject<LoginResult>(html);
            if (result.base_resp.ret == 0)
            {
                IsLogin = true;
                Token = tokenRegex.Match(result.redirect_url).Groups["value"].Value;
                html = HttpHelper.GetHtml(string.Format("https://mp.weixin.qq.com{0}", result.redirect_url), "https://mp.weixin.qq.com/");
            }
        }

        public Message[] ExportMessage()
        {
            List<Message> list = new List<Message>();

            string html = HttpHelper.GetHtml(string.Format(messageUrl, Token), "https://mp.weixin.qq.com/");
            var msgList = ReadMessage(html);
            if (msgList != null)
            {
                list.AddRange(msgList);
            }

            int pageTotal = GetPageTotal(html);
            for (var i = 1; i < pageTotal; i++)
            {
                html = HttpHelper.GetHtml(string.Format(messagePageUrl, frommsgid, i * 20, Token), "https://mp.weixin.qq.com/");
                msgList = ReadMessage(html);

                if (msgList != null)
                {
                    list.AddRange(msgList);
                }
            }

            return list.ToArray();
        }

        public int GetPageTotal(string html)
        {
            string pTotal = pageTotalRegex.Match(html).Groups["value"].Value;
            int total = string.IsNullOrEmpty(pTotal) ? 1 : Convert.ToInt32(pTotal);
            return ((total - 1) / 20) + 1;
        }

        public string GetFormId(string html)
        {
            return fidRegex.Match(html).Groups["value"].Value;
        }

        private Message[] ReadMessage(string html)
        {
            frommsgid = GetFormId(html);
            string messageInfo = msgRegex.Match(html).Groups["value"].Value;
            MessageList msgList = JsonConvert.DeserializeObject<MessageList>(messageInfo);
            OnReadMessageCompleted(new MessageEventArgs(msgList.msg_item));
            return msgList.msg_item;
        }

        public event EventHandler<MessageEventArgs> ReadMessageCompleted;
        private void OnReadMessageCompleted(MessageEventArgs e)
        {
            if (ReadMessageCompleted != null)
            {
                ReadMessageCompleted(this, e);
            }
        }
    }

    public class LoginResult
    {
        public BaseResponse base_resp { get; set; }

        public string redirect_url { get; set; }
    }

    public class BaseResponse
    {
        public int ret { get; set; }

        public string err_msg { get; set; }
    }

    public class MessageList
    {
        public Message[] msg_item { get; set; }
    }

    public class Message
    {
        public string id { get; set; }

        public int type { get; set; }

        public string fakeid { get; set; }

        public string nick_name { get; set; }

        [JsonConverter(typeof(UnixDateTimeConverter))]
        public DateTime date_time { get; set; }

        public string content { get; set; }

        public string source { get; set; }

        public int msg_status { get; set; }

        public string remark_name { get; set; }

        public int has_reply { get; set; }

        public string refuse_reason { get; set; }

        public long to_uin { get; set; }
    }

    public class SendState
    {
        public int total { get; set; }

        public int succ { get; set; }

        public int fail { get; set; }
    }

    public class UnixDateTimeConverter : DateTimeConverterBase
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType != JsonToken.Integer)
            {
                throw new Exception(String.Format("日期格式錯誤,got {0}.", reader.TokenType));
            }
            var ticks = (long)reader.Value;
            var date = new DateTime(1970, 1, 1);
            date = date.AddSeconds(ticks);
            return date;
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            long ticks;
            if (value is DateTime)
            {
                var epoc = new DateTime(1970, 1, 1);
                var delta = ((DateTime)value) - epoc;
                if (delta.TotalSeconds < 0)
                {
                    throw new ArgumentOutOfRangeException("時間格式錯誤.1");
                }
                ticks = (long)delta.TotalSeconds;
            }
            else
            {
                throw new Exception("時間格式錯誤.2");
            }
            writer.WriteValue(ticks);
        }
    }