From ce5e526ff5a011a09cda8f8c3079f52477eb5d94 Mon Sep 17 00:00:00 2001 From: zhouhua Date: Wed, 3 Feb 2021 23:29:28 +0800 Subject: [PATCH 1/2] Upgrade to support iTunes 12.11 and wechat 8.0 --- WechatExport/Form1.cs | 61 ++++++++++++++++++++++------------------- WechatExport/wechat.cs | 62 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 28 deletions(-) diff --git a/WechatExport/Form1.cs b/WechatExport/Form1.cs index 69b987d..0188927 100644 --- a/WechatExport/Form1.cs +++ b/WechatExport/Form1.cs @@ -24,8 +24,8 @@ public Form1() private void LoadManifests() { comboBox1.Items.Clear(); - string s = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - s = MyPath.Combine(s, "Apple Computer", "MobileSync", "Backup"); + string s = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + s = MyPath.Combine(s, "Apple", "MobileSync", "Backup"); try { DirectoryInfo d = new DirectoryInfo(s); @@ -232,40 +232,45 @@ void Run() } AddLog("找到" + friendcount + "个好友/聊天室"); AddLog("查找对话"); - wechat.GetChatSessions(conn, out List chats); - AddLog("找到" + chats.Count + "个对话"); + var count = wechat.GetChatSessions(conn, userBase, out Dictionary> chats); + AddLog("找到" + count + "个对话"); var emojidown = new HashSet(); var chatList = new List(); - foreach (var chat in chats) + foreach (var pair in chats) { - var hash = chat; - string displayname = chat, id = displayname; - Friend friend = null; - if (friends.ContainsKey(hash)) + var c = pair.Key; + foreach (var chat in pair.Value) { - friend = friends[hash]; - displayname = friend.DisplayName(); - AddLog("处理与" + displayname + "的对话"); - id = friend.ID(); - } - else AddLog("未找到好友信息,用默认名字代替"); - if (radioButton4.Checked) - { - if (wechat.SaveTextRecord(conn, Path.Combine(userSaveBase, id + ".txt"), displayname, id, myself, chat, friend, friends, out int count)) AddLog("成功处理" + count + "条"); - else AddLog("失败"); - } - else if(radioButton3.Checked) - { - if (wechat.SaveHtmlRecord(conn, userBase, userSaveBase, displayname, id, myself, chat, friend, friends, out int count, out HashSet _emojidown)) + var hash = chat; + string displayname = chat, id = displayname; + Friend friend = null; + if (friends.ContainsKey(hash)) + { + friend = friends[hash]; + displayname = friend.DisplayName(); + AddLog("处理与" + displayname + "的对话"); + id = friend.ID(); + } + else AddLog("未找到好友信息,用默认名字代替"); + if (radioButton4.Checked) { - AddLog("成功处理" + count + "条"); - chatList.Add(new DisplayItem() { pic = "Portrait/" + (friend != null ? friend.FindPortrait() : "DefaultProfileHead@2x.png"), text = displayname, link = id + ".html" }); + if (wechat.SaveTextRecord(c, Path.Combine(userSaveBase, id + ".txt"), displayname, id, myself, chat, friend, friends, out int msgcnt)) AddLog("成功处理" + msgcnt + "条"); + else AddLog("失败"); + } + else if (radioButton3.Checked) + { + if (wechat.SaveHtmlRecord(c, userBase, userSaveBase, displayname, id, myself, chat, friend, friends, out int msgcnt, out HashSet _emojidown)) + { + AddLog("成功处理" + msgcnt + "条"); + chatList.Add(new DisplayItem() { pic = "Portrait/" + (friend != null ? friend.FindPortrait() : "DefaultProfileHead@2x.png"), text = displayname, link = id + ".html" }); + } + else AddLog("失败"); + emojidown.UnionWith(_emojidown); } - else AddLog("失败"); - emojidown.UnionWith(_emojidown); } + + c.Close(); } - conn.Close(); if(radioButton3.Checked) wechat.MakeListHTML(chatList, Path.Combine(userSaveBase, "聊天记录.html")); var portraitdir = Path.Combine(userSaveBase, "Portrait"); Directory.CreateDirectory(portraitdir); diff --git a/WechatExport/wechat.cs b/WechatExport/wechat.cs index 31cfc68..7d79a56 100644 --- a/WechatExport/wechat.cs +++ b/WechatExport/wechat.cs @@ -56,6 +56,24 @@ public bool OpenWCDBContact(string userBase, out SQLiteConnection conn) return succ; } + + public bool OpenMessageSqlite(string userBase, out SQLiteConnection conn) + { + bool succ = false; + conn = null; + try + { + conn = new SQLiteConnection + { + ConnectionString = "data source=" + GetBackupFilePath(MyPath.Combine(userBase, "DB", "WCDB_Contact.sqlite")) + ";version=3" + }; + conn.Open(); + succ = true; + } + catch (Exception) { } + return succ; + } + public bool GetUserBasics(string uid, string userBase, out Friend friend) { friend = new Friend() { UsrName = uid, NickName = "我", alias = null, PortraitRequired=true }; @@ -244,6 +262,50 @@ public bool GetChatSessions(SQLiteConnection conn, out List sessions) return succ; } + public int GetChatSessions(SQLiteConnection conn, string userBase, out Dictionary> sessions) + { + sessions = new Dictionary>(); + if (!GetChatSessions(conn, out List chats)) + { + return 0; + } + sessions.Add(conn, chats); + + int i = 0, count = chats.Count; + while (true) + { + i++; + string msgfilename = GetBackupFilePath(MyPath.Combine(userBase, "DB", "message_" + i + ".sqlite")); + if (!File.Exists(msgfilename)) + { + break; + } + + SQLiteConnection msgconn; + try + { + msgconn = new SQLiteConnection + { + ConnectionString = "data source=" + msgfilename + ";version=3" + }; + msgconn.Open(); + } + catch (Exception e) + { + System.Console.Out.Write(e); + return -1; + } + + if (!GetChatSessions(msgconn, out chats)) + { + return -1; + } + count += chats.Count; + sessions.Add(msgconn, chats); + } + return count; + } + public bool SaveTextRecord(SQLiteConnection conn, string path, string displayname, string id, Friend myself, string table, Friend friend, Dictionary friends, out int count) { bool succ = false; From 8b33dc19b7d393a3509464bf0185271fdf73b7bd Mon Sep 17 00:00:00 2001 From: zhouhua Date: Wed, 3 Feb 2021 23:30:03 +0800 Subject: [PATCH 2/2] Export videos and files --- WechatExport/wechat.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/WechatExport/wechat.cs b/WechatExport/wechat.cs index 7d79a56..5beecb3 100644 --- a/WechatExport/wechat.cs +++ b/WechatExport/wechat.cs @@ -349,7 +349,7 @@ public bool SaveTextRecord(SQLiteConnection conn, string path, string displaynam } if (type == 34) message = "[语音]"; else if (type == 47) message = "[表情]"; - else if (type == 62) message = "[小视频]"; + else if (type == 62 || type == 43) message = "[小视频]"; else if (type == 50) message = "[视频/语音通话]"; else if (type == 3) message = "[图片]"; else if (type == 48) message = "[位置]"; @@ -476,7 +476,7 @@ public bool SaveHtmlRecord(SQLiteConnection conn, string userBase, string path,s } else message = "[表情]"; } - else if (type == 62) + else if (type == 62 || type == 43) { var hasthum = RequireResource(MyPath.Combine(userBase, "Video", table, msgid + ".video_thum"), Path.Combine(assetsdir, msgid + "_thum.jpg")); var hasvid = RequireResource(MyPath.Combine(userBase, "Video", table, msgid + ".mp4"), Path.Combine(assetsdir, msgid + ".mp4")); @@ -508,7 +508,21 @@ public bool SaveHtmlRecord(SQLiteConnection conn, string userBase, string path,s if (message.Contains("2001<")) message = "[红包]"; else if (message.Contains("2000<")) message = "[转账]"; else if (message.Contains("17<")) message = "[实时位置共享]"; - else if (message.Contains("6<")) message = "[文件]"; + else if (message.Contains("6<")) + { + var match1 = Regex.Match(message, @"(.+?)<\/fileext>"); + var match2 = Regex.Match(message, @"(.+?)<\/title>"); + if (match1.Success && match2.Success) + { + var hasfile = RequireResource(MyPath.Combine(userBase, "OpenData", table, msgid + "." + match1.Groups[1].Value), Path.Combine(assetsdir, match2.Groups[1].Value)); + if (hasfile) message = "<a href=\"" + id + "_files/" + match2.Groups[1].Value + "\">" + match2.Groups[1].Value + "</a>"; + else message = match2.Groups[1].Value + "(文件丢失)"; + } + else + { + message = "[文件]"; + } + } else { var match1 = Regex.Match(message, @"<title>(.+?)<\/title>");