public bool SaveTextRecord(SQLiteConnection conn, string path, string displayname, string id, Friend myself, string table, Friend friend, Dictionary <string, Friend> friends, out int count) { bool succ = false; count = 0; try { Dictionary <string, string> chatremark = null; if (id.EndsWith("@chatroom") && friend != null && friend.dbContactChatRoom != null) { chatremark = ReadChatRoomRemark(friend.dbContactChatRoom); } using (var cmd = new SQLiteCommand(conn)) { cmd.CommandText = "SELECT CreateTime,Message,Des,Type FROM Chat_" + table; using (var reader = cmd.ExecuteReader()) using (var sw = new StreamWriter(path)) { while (reader.Read()) { try { var unixtime = reader.GetInt32(0); var message = reader.GetString(1); var des = reader.GetInt32(2); var type = reader.GetInt32(3); var txtsender = (type == 10000 ? "[系统消息]" : (des == 1 ? displayname : myself.DisplayName())); if (id.EndsWith("@chatroom") && type != 10000 && des == 1) { var enter = message.IndexOf(":\n"); if (enter > 0 && enter + 2 < message.Length) { txtsender = message.Substring(0, enter); message = message.Substring(enter + 2); if (chatremark.ContainsKey(txtsender)) { txtsender = chatremark[txtsender]; } else if (friends.ContainsKey(txtsender)) { txtsender = friends[txtsender].DisplayName(); } } } if (id.EndsWith("@chatroom") && des == 0) { if (chatremark.ContainsKeySafe(myself.UsrName)) { txtsender = chatremark[myself.UsrName]; } else if (chatremark.ContainsKeySafe(myself.alias)) { txtsender = chatremark[myself.alias]; } } if (type == 34) { message = "[语音]"; } else if (type == 47) { message = "[表情]"; } else if (type == 62) { message = "[小视频]"; } else if (type == 50) { message = "[视频/语音通话]"; } else if (type == 3) { message = "[图片]"; } else if (type == 48) { message = "[位置]"; } else if (type == 49) { if (message.Contains("<type>2001<") || message.Contains("<type><![CDATA[2001]]><")) { message = "[红包]"; } else if (message.Contains("<type>2000<") || message.Contains("<type><![CDATA[2000]]><")) { message = "[转账]"; } else if (message.Contains("<type>17<") || message.Contains("<type><![CDATA[17]]><")) { message = "[实时位置共享]"; } else if (message.Contains("<type>6<") || message.Contains("<type><![CDATA[6]]><")) { message = "[文件]"; } else { message = "[链接]"; } } else if (type == 42) { message = "[名片]"; } sw.WriteLine(txtsender + "(" + FromUnixTime(unixtime).ToLocalTime().ToString() + ")" + ": " + message); count++; } catch (Exception) { } } } } succ = true; } catch (Exception) { } return(succ); }
public bool SaveHtmlRecord(SQLiteConnection conn, string userBase, string path, string displayname, string id, Friend myself, string table, Friend friend, Dictionary <string, Friend> friends, out int count, out HashSet <DownloadTask> emojidown) { bool succ = false; emojidown = new HashSet <DownloadTask>(); count = 0; try { Dictionary <string, string> chatremark = new Dictionary <string, string>(); if (id.EndsWith("@chatroom") && friend != null && friend.dbContactChatRoom != null) { chatremark = ReadChatRoomRemark(friend.dbContactChatRoom); } using (var cmd = new SQLiteCommand(conn)) { cmd.CommandText = "SELECT CreateTime,Message,Des,Type,MesLocalID FROM Chat_" + table; using (var reader = cmd.ExecuteReader()) { var assetsdir = Path.Combine(path, id + "_files"); Directory.CreateDirectory(assetsdir); using (var sw = new StreamWriter(Path.Combine(path, id + ".html"))) { sw.WriteLine(@"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">"); sw.WriteLine(@"<html xmlns=""http://www.w3.org/1999/xhtml""><head><meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" /><title>" + displayname + " - 微信聊天记录</title></head>"); sw.WriteLine(@"<body><table width=""600"" border=""0"" style=""font-size:12px;border-collapse:separate;border-spacing:0px 20px;word-break:break-all;table-layout:fixed;word-wrap:break-word;"" align=""center"">"); while (reader.Read()) { try { var unixtime = reader.GetInt32(0); var message = reader.GetString(1); var des = reader.GetInt32(2); var type = reader.GetInt32(3); var msgid = reader.GetInt32(4); if (type == 10000) { sw.WriteLine(@"<tr><td width=""80""> </td><td width=""100""> </td><td>系统消息: " + message + @"</td></tr>"); continue; } var ts = ""; if (id.EndsWith("@chatroom")) { if (des == 0) { var txtsender = myself.DisplayName(); if (chatremark.ContainsKeySafe(myself.UsrName)) { txtsender = chatremark[myself.UsrName]; } else if (chatremark.ContainsKeySafe(myself.alias)) { txtsender = chatremark[myself.alias]; } ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + myself.FindPortrait() + @""" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } else { var enter = message.IndexOf(":\n"); if (enter > 0 && enter + 2 < message.Length) { var txtsender = message.Substring(0, enter); var senderid = txtsender; message = message.Substring(enter + 2); if (chatremark.ContainsKeySafe(txtsender)) { txtsender = chatremark[txtsender]; } else if (friends.ContainsKeySafe(txtsender)) { txtsender = friends[txtsender].DisplayName(); } if (friends.ContainsKeySafe(senderid)) { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + friends[senderid].FindPortrait() + @""" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } else { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/[email protected]"" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } } else { ts += @"<tr><td width=""80"" align=""center""> </td>"; } } } else { if (des == 0) { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + myself.FindPortrait() + @""" width=""50"" height=""50"" /><br />" + myself.DisplayName() + @"</td>"; } else if (friend != null) { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/" + friend.FindPortrait() + @""" width=""50"" height=""50"" /><br />" + friend.DisplayName() + @"</td>"; } else { ts += @"<tr><td width=""80"" align=""center""><img src=""Portrait/[email protected]"" width=""50"" height=""50"" /><br />" + displayname + @"</td>"; } } if (type == 34) { var voicelen = -1; var match = Regex.Match(message, @"voicelength=""(\d+?)"""); if (match.Success) { voicelen = int.Parse(match.Groups[1].Value); } var audiosrc = GetBackupFilePath(MyPath.Combine(userBase, "Audio", table, msgid + ".aud")); if (audiosrc == null) { message = voicelen == -1 ? "[语音]" : "[语音 " + DisplayTime(voicelen) + "]"; } else { ShellWait("silk_v3_decoder.exe", "\"" + audiosrc + "\" 1.pcm"); ShellWait("lame.exe", "-r -s 24000 --preset voice 1.pcm \"" + Path.Combine(assetsdir, msgid + ".mp3") + "\""); message = "<audio controls><source src=\"" + id + "_files/" + msgid + ".mp3\" type=\"audio/mpeg\"><a href=\"" + id + "_files/" + msgid + ".mp3\">播放</a></audio>"; } } else if (type == 47) { var match = Regex.Match(message, @"cdnurl ?= ?""(.+?)"""); if (match.Success) { var localfile = RemoveCdata(match.Groups[1].Value); var match2 = Regex.Match(localfile, @"\/(\w+?)\/\w*$"); if (!match2.Success) { localfile = RandomString(10); } else { localfile = match2.Groups[1].Value; } emojidown.Add(new DownloadTask() { url = match.Groups[1].Value, filename = localfile + ".gif" }); message = "<img src=\"Emoji/" + localfile + ".gif\" style=\"max-width:100px;max-height:60px\" />"; } else { message = "[表情]"; } } else if (type == 62) { 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")); if (hasthum && hasvid) { message = "<video controls poster=\"" + id + "_files/" + msgid + "_thum.jpg\"><source src=\"" + id + "_files/" + msgid + ".mp4\" type=\"video/mp4\"><a href=\"" + id + "_files/" + msgid + ".mp4\">播放</a></video>"; } else if (hasthum) { message = "<img src=\"" + id + "_files/" + msgid + "_thum.jpg\" /> (视频丢失)"; } else if (hasvid) { message = "<video controls><source src=\"" + id + "_files/" + msgid + ".mp4\" type=\"video/mp4\"><a href=\"" + id + "_files/" + msgid + ".mp4\">播放</a></video>"; } else { message = "[视频]"; } } else if (type == 50) { message = "[视频/语音通话]"; } else if (type == 3) { var hasthum = RequireResource(MyPath.Combine(userBase, "Img", table, msgid + ".pic_thum"), Path.Combine(assetsdir, msgid + "_thum.jpg")); var haspic = RequireResource(MyPath.Combine(userBase, "Img", table, msgid + ".pic"), Path.Combine(assetsdir, msgid + ".jpg")); if (hasthum && haspic) { message = "<a href=\"" + id + "_files/" + msgid + ".jpg\"><img src=\"" + id + "_files/" + msgid + "_thum.jpg\" style=\"max-width:100px;max-height:60px\" /></a>"; } else if (hasthum) { message = "<img src=\"" + id + "_files/" + msgid + "_thum.jpg\" style=\"max-width:100px;max-height:60px\" />"; } else if (haspic) { message = "<img src=\"" + id + "_files/" + msgid + ".jpg\" style=\"max-width:100px;max-height:60px\" />"; } else { message = "[图片]"; } } else if (type == 48) { var match1 = Regex.Match(message, @"x ?= ?""(.+?)"""); var match2 = Regex.Match(message, @"y ?= ?""(.+?)"""); var match3 = Regex.Match(message, @"label ?= ?""(.+?)"""); if (match1.Success && match2.Success && match3.Success) { message = "[位置 (" + RemoveCdata(match2.Groups[1].Value) + "," + RemoveCdata(match1.Groups[1].Value) + ") " + RemoveCdata(match3.Groups[1].Value) + "]"; } else { message = "[位置]"; } } else if (type == 49) { if (message.Contains("<type>2001<")) { message = "[红包]"; } else if (message.Contains("<type>2000<")) { message = "[转账]"; } else if (message.Contains("<type>17<")) { message = "[实时位置共享]"; } else if (message.Contains("<type>6<")) { message = "[文件]"; } else { var match1 = Regex.Match(message, @"<title>(.+?)<\/title>"); var match2 = Regex.Match(message, @"<des>(.*?)<\/des>"); var match3 = Regex.Match(message, @"<url>(.+?)<\/url>"); var match4 = Regex.Match(message, @"<thumburl>(.+?)<\/thumburl>"); if (match1.Success && match3.Success) { message = ""; if (match4.Success) { message += "<img src=\"" + RemoveCdata(match4.Groups[1].Value) + "\" style=\"float:left;max-width:100px;max-height:60px\" />"; } message += "<a href=\"" + RemoveCdata(match3.Groups[1].Value) + "\"><b>" + RemoveCdata(match1.Groups[1].Value) + "</b></a>"; if (match2.Success) { message += "<br />" + RemoveCdata(match2.Groups[1].Value); } } else { message = "[链接]"; } } } else if (type == 42) { var match1 = Regex.Match(message, "nickname ?= ?\"(.+?)\""); var match2 = Regex.Match(message, "smallheadimgurl ?= ?\"(.+?)\""); if (match1.Success) { message = ""; if (match2.Success) { message += "<img src=\"" + RemoveCdata(match2.Groups[1].Value) + "\" style=\"float:left;max-width:100px;max-height:60px\" />"; } message += "[名片] " + RemoveCdata(match1.Groups[1].Value); } else { message = "[名片]"; } } else { message = SafeHTML(message); } ts += @"<td width=""100"" align=""center"">" + FromUnixTime(unixtime).ToLocalTime().ToString().Replace(" ", "<br />") + "</td>"; ts += @"<td>" + message + @"</td></tr>"; sw.WriteLine(ts); count++; } catch (Exception) { } } sw.WriteLine(@"</body></html>"); } } } succ = true; } catch (Exception) { } return(succ); }
void Run() { var saveBase = textBox1.Text; //读取文本框中的保存地址 Directory.CreateDirectory(saveBase); //创建这个文件夹 该函数为创建多级文件夹 AddLog("分析文件夹结构"); //((IPhoneBackup)comboBox1.SelectedItem).path 找到苹果备份的文件夹的绝对路径 wechat = new WeChatInterface(((IPhoneBackup)comboBox1.SelectedItem).path, files92); wechat.BuildFilesDictionary(); AddLog("查找UID"); var UIDs = wechat.FindUIDs(); AddLog("找到" + UIDs.Count + "个账号的消息记录"); var uidList = new List <DisplayItem>(); foreach (var uid in UIDs) { var userBase = Path.Combine("Documents", uid); AddLog("开始处理UID: " + uid); AddLog("读取账号信息"); if (wechat.GetUserBasics(uid, userBase, out Friend myself)) { AddLog("微信号:" + myself.ID() + " 昵称:" + myself.DisplayName()); } else { AddLog("没有找到本人信息,用默认值替代"); } var userSaveBase = Path.Combine(saveBase, myself.ID()); Directory.CreateDirectory(userSaveBase); AddLog("正在打开数据库"); if (!wechat.OpenMMSqlite(userBase, out SQLiteConnection conn))//conn { AddLog("打开MM.sqlite失败,跳过"); continue; } if (wechat.OpenWCDBContact(userBase, out SQLiteConnection wcdb))//wcdb { AddLog("存在WCDB,与旧版好友列表合并使用"); } AddLog("读取好友列表"); if (!wechat.GetFriendsDict(conn, wcdb, myself, out Dictionary <string, Friend> friends, out int friendcount)) { AddLog("读取好友列表失败,跳过"); continue; } AddLog("找到" + friendcount + "个好友/聊天室"); AddLog("查找对话"); wechat.GetChatSessions(conn, out List <string> chats); AddLog("找到" + chats.Count + "个对话"); var emojidown = new HashSet <DownloadTask>(); var chatList = new List <DisplayItem>(); foreach (var chat in chats) { 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) { 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 <DownloadTask> _emojidown)) { AddLog("成功处理" + count + "条"); chatList.Add(new DisplayItem() { pic = "Portrait/" + (friend != null ? friend.FindPortrait() : "*****@*****.**"), text = displayname, link = id + ".html" }); } else { AddLog("失败"); } emojidown.UnionWith(_emojidown); } } conn.Close(); if (radioButton3.Checked) { wechat.MakeListHTML(chatList, Path.Combine(userSaveBase, "聊天记录.html")); } var portraitdir = Path.Combine(userSaveBase, "Portrait"); Directory.CreateDirectory(portraitdir); var downlist = new HashSet <DownloadTask>(); foreach (var item in friends) { var tfriend = item.Value; if (!tfriend.PortraitRequired) { continue; } if (tfriend.Portrait != null && tfriend.Portrait != "") { downlist.Add(new DownloadTask() { url = tfriend.Portrait, filename = tfriend.ID() + ".jpg" }); } //if (tfriend.PortraitHD != null && tfriend.PortraitHD != "") downlist.Add(new DownloadTask() { url = tfriend.PortraitHD, filename = tfriend.ID() + "_hd.jpg" }); } var downloader = new Downloader(6); if (downlist.Count > 0) { AddLog("下载" + downlist.Count + "个头像"); foreach (var item in downlist) { downloader.AddTask(item.url, Path.Combine(portraitdir, item.filename)); } try { File.Copy("res\\[email protected]", Path.Combine(portraitdir, "*****@*****.**")); } catch (Exception) { } } var emojidir = Path.Combine(userSaveBase, "Emoji"); Directory.CreateDirectory(emojidir); if (emojidown != null && emojidown.Count > 0) { AddLog("下载" + emojidown.Count + "个表情"); foreach (var item in emojidown) { downloader.AddTask(item.url, Path.Combine(emojidir, item.filename)); } } uidList.Add(new DisplayItem() { pic = myself.ID() + "/Portrait/" + myself.FindPortrait(), text = myself.DisplayName(), link = myself.ID() + "/聊天记录.html" }); downloader.StartDownload(); downloader.WaitToEnd(); AddLog("完成当前账号"); }
void AndroidRun() { int maxCount = int.MaxValue; if (!softReg.GetIsReg()) { maxCount = 10; MessageBox.Show("非注册用户暂时支持部分导出 \n如果导出全量信息请到https://www.weixinxqm.com/购买注册!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } var saveBase = savePathTextBox.Text; Directory.CreateDirectory(saveBase); AddLog("分析文件夹结构"); AndroidWeChatInterface wechat = null; if (string.IsNullOrEmpty(resPathTextBox.Text)) { wechat = new AndroidWeChatInterface(wechatPathTextBox.Text); } else { wechat = new AndroidWeChatInterface(wechatPathTextBox.Text, resPathTextBox.Text); } wechat.Init(); AddLog("查找UID"); var users = wechat.users; AddLog("找到" + users.Count + "个账号的消息记录"); var uidList = new List <DisplayItem>(); foreach (var user in users) { user.Init(); AddLog("开始处理UID: " + user.uid); AddLog("打开数据库"); if (!user.OpenMMSqlite()) { AddLog("无法打开数据库"); continue; } AddLog("读取账号信息"); if (!user.GetUserBasics()) { AddLog("没有找到本人信息,用默认值替代"); } Friend myself = user.myself; AddLog("微信号:" + myself.ID() + " 昵称:" + myself.DisplayName()); AddLog("读取好友列表"); if (!user.GetFriendsDict(out int friendcount)) { AddLog("获取好友列表失败,跳过"); continue; } if (!user.GetChatRoomMember(out int chatroomCount)) { AddLog("获取聊天室用户列表失败,跳过"); continue; } AddLog("找到" + (friendcount - chatroomCount) + "个好友"); AddLog("找到" + chatroomCount + "个聊天室"); AddLog("查找对话:"); user.GetChatSessions(out List <string> chats); AddLog("找到" + chats.Count + "个对话"); var userSaveBase = Path.Combine(saveBase, myself.ID()); Directory.CreateDirectory(userSaveBase); user.userSaveDir = userSaveBase; AddLog("导出好友列表:"); if (user.saveFriends(maxCount, out int exportCount)) { AddLog("导出" + exportCount + "个好友"); } else { AddLog("导出好友列表出错"); } var emojidown = new HashSet <DownloadTask>(); var chatList = new List <DisplayItem>(); if (htmlRadioButton.Checked) { try { AddLog("复制头像:"); user.CopyResource(); File.Copy("res\\[email protected]", Path.Combine(userSaveBase, "avatar", "*****@*****.**")); } catch (Exception) { } } foreach (var chat in chats) { string displayname = chat; Friend friend = user.GetFriend(chat); if (friend != null) { displayname = friend.DisplayName(); AddLog("处理与" + displayname + "的对话"); } else { AddLog("未找到好友信息,用默认名字代替"); } if (textRadioButton.Checked) { if (user.SaveTextRecord(chat, maxCount, out int count)) { AddLog("成功处理" + count + "条"); } else { AddLog("失败"); } } else if (htmlRadioButton.Checked) { if (user.SaveHtmlRecord(chat, maxCount, out int count, out HashSet <DownloadTask> _emojidown)) { AddLog("成功处理" + count + "条"); chatList.Add(new DisplayItem() { pic = "avatar/" + (friend != null ? friend.GetAndroidUserAvatar() : "*****@*****.**"), text = displayname, link = chat + ".html" }); } else { AddLog("失败"); } emojidown.UnionWith(_emojidown); } } if (htmlRadioButton.Checked) { BaseWeChat.MakeListHTML(chatList, Path.Combine(userSaveBase, "聊天记录.html")); } var downloader = new Downloader(6); var emojidir = Path.Combine(userSaveBase, "Emoji"); Directory.CreateDirectory(emojidir); if (emojidown != null && emojidown.Count > 0) { AddLog("下载" + emojidown.Count + "个表情"); foreach (var item in emojidown) { downloader.AddTask(item.url, Path.Combine(emojidir, item.filename)); } } uidList.Add(new DisplayItem() { pic = myself.ID() + "/avatar/" + user.myself.GetAndroidUserAvatar(), text = myself.DisplayName(), link = myself.ID() + "/聊天记录.html" }); downloader.StartDownload(); downloader.WaitToEnd(); AddLog("完成当前账号"); }
void run() { var saveBase = textBox1.Text; Directory.CreateDirectory(saveBase); AddLog("分析文件夹结构"); wechat = new WeChatInterface(currentBackup, files92); wechat.BuildFilesDictionary(weixinapp); AddLog("查找UID"); var UIDs = wechat.FindUIDs(); AddLog("找到" + UIDs.Count + "个账号的消息记录"); foreach (var uid in UIDs) { var userBase = Path.Combine("Documents", uid); AddLog("开始处理UID: " + uid); AddLog("读取账号信息"); Friend myself; if (wechat.GetUserBasics(uid, userBase, out myself)) { AddLog("微信号:" + myself.ID() + " 昵称:" + myself.DisplayName()); } else { AddLog("没有找到本人信息,用默认值替代"); } var userSaveBase = Path.Combine(saveBase, myself.ID()); Directory.CreateDirectory(userSaveBase); AddLog("正在打开数据库"); SQLiteConnection conn, wcdb; if (!wechat.OpenMMSqlite(userBase, out conn)) { AddLog("打开MM.sqlite失败,跳过"); continue; } if (wechat.OpenWCDBContact(userBase, out wcdb)) { AddLog("存在WCDB,与旧版好友列表合并使用"); } AddLog("读取好友列表"); Dictionary <string, Friend> friends; int friendcount; if (!wechat.GetFriendsDict(conn, wcdb, myself, out friends, out friendcount)) { AddLog("读取好友列表失败,跳过"); continue; } AddLog("找到" + friendcount + "个好友/聊天室"); AddLog("查找对话"); List <string> chats; wechat.GetChatSessions(conn, out chats); AddLog("找到" + chats.Count + "个对话"); var emojidown = new HashSet <DownloadTask>(); foreach (var chat in chats) { 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) { int count; if (wechat.SaveTextRecord(conn, Path.Combine(userSaveBase, id + ".txt"), displayname, id, myself, chat, friend, friends, out count)) { AddLog("成功处理" + count + "条"); } else { AddLog("失败"); } } else if (radioButton3.Checked) { int count; HashSet <DownloadTask> _emojidown; if (wechat.SaveHtmlRecord(conn, userBase, userSaveBase, displayname, id, myself, chat, friend, friends, out count, out _emojidown)) { AddLog("成功处理" + count + "条"); } else { AddLog("失败"); } emojidown.UnionWith(_emojidown); } } var portraitdir = Path.Combine(userSaveBase, "Portrait"); Directory.CreateDirectory(portraitdir); var downlist = new HashSet <DownloadTask>(); foreach (var item in friends) { var tfriend = item.Value; if (!tfriend.PortraitRequired) { continue; } if (tfriend.Portrait != null && tfriend.Portrait != "") { downlist.Add(new DownloadTask() { url = tfriend.Portrait, filename = tfriend.ID() + ".jpg" }); } //if (tfriend.PortraitHD != null && tfriend.PortraitHD != "") downlist.Add(new DownloadTask() { url = tfriend.PortraitHD, filename = tfriend.ID() + "_hd.jpg" }); } var downloader = new Downloader(6); if (downlist.Count > 0) { AddLog("下载" + downlist.Count + "个头像"); foreach (var item in downlist) { downloader.AddTask(item.url, Path.Combine(portraitdir, item.filename)); } try { File.Copy("*****@*****.**", Path.Combine(portraitdir, "*****@*****.**")); } catch (Exception) { } } var emojidir = Path.Combine(userSaveBase, "Emoji"); Directory.CreateDirectory(emojidir); if (emojidown != null && emojidown.Count > 0) { AddLog("下载" + emojidown.Count + "个表情"); foreach (var item in emojidown) { downloader.AddTask(item.url, Path.Combine(emojidir, item.filename)); } } downloader.StartDownload(); downloader.WaitToEnd(); AddLog("完成当前账号"); } AddLog("任务结束"); groupBox1.Enabled = groupBox3.Enabled = groupBox4.Enabled = true; button2.Enabled = true; wechat = null; MessageBox.Show("处理完成"); }
public bool SaveHtmlRecord(string talker, int maxCount, out int count, out HashSet <DownloadTask> emojidown) { bool succ = false; emojidown = new HashSet <DownloadTask>(); count = 0; try { Friend friend = friends[talker]; Dictionary <string, string> chatremark = null; if (talker.EndsWith("@chatroom") && chatRoomUserDict != null) { if (chatRoomUserDict.ContainsKey(talker)) { chatremark = chatRoomUserDict[talker]; } } var messages = dbConn.Table <Message>().Where(t => t.Talker == talker).OrderByDescending(t => t.CreateTime).ToList(); using (var sw = new StreamWriter(Path.Combine(userSaveDir, talker + ".html"))) { sw.WriteLine(@"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">"); sw.WriteLine(@"<html xmlns=""http://www.w3.org/1999/xhtml""><head><meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" /><title>" + friend.DisplayName() + " - 微信聊天记录</title></head>"); sw.WriteLine(@"<body><table width=""600"" border=""0"" style=""font-size:12px;border-collapse:separate;border-spacing:0px 20px;word-break:break-all;table-layout:fixed;word-wrap:break-word;"" align=""center"">"); foreach (var msg in messages) { try { var unixtime = msg.CreateTime; unixtime = unixtime / 1000; var message = msg.Content; var des = msg.IsSend; var type = msg.Type; if (type == 10000) { sw.WriteLine(@"<tr><td width=""80""> </td><td width=""100""> </td><td>系统消息: " + message + @"</td></tr>"); continue; } var ts = ""; if (talker.EndsWith("@chatroom")) { if (des == 1) { var txtsender = myself.DisplayName(); if (chatremark.ContainsKeySafe(myself.UsrName)) { txtsender = chatremark[myself.UsrName]; } else if (chatremark.ContainsKeySafe(myself.alias)) { txtsender = chatremark[myself.alias]; } ts += @"<tr><td width=""80"" align=""center""><img src=""avatar/" + myself.GetAndroidUserAvatar() + @""" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } else { var enter = message.IndexOf(":\n"); if (enter > 0 && enter + 2 < message.Length) { var txtsender = message.Substring(0, enter); var senderid = txtsender; message = message.Substring(enter + 2); if (chatremark.ContainsKeySafe(txtsender)) { txtsender = chatremark[txtsender]; } else if (friends.ContainsKeySafe(txtsender)) { txtsender = friends[txtsender].DisplayName(); } if (friends.ContainsKeySafe(senderid)) { ts += @"<tr><td width=""80"" align=""center""><img src=""avatar/" + GetUserAvatar(senderid) + @""" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } else { ts += @"<tr><td width=""80"" align=""center""><img src=""avatar/[email protected]"" width=""50"" height=""50"" /><br />" + txtsender + @"</td>"; } } else { ts += @"<tr><td width=""80"" align=""center""> </td>"; } } } else { if (des == 1) { ts += @"<tr><td width=""80"" align=""center""><img src=""avatar/" + myself.GetAndroidUserAvatar() + @""" width=""50"" height=""50"" /><br />" + myself.DisplayName() + @"</td>"; } else if (friend != null) { ts += @"<tr><td width=""80"" align=""center""><img src=""avatar/" + friend.GetAndroidUserAvatar() + @""" width=""50"" height=""50"" /><br />" + friend.DisplayName() + @"</td>"; } else { ts += @"<tr><td width=""80"" align=""center""><img src=""avatar/[email protected]"" width=""50"" height=""50"" /><br />" + friend.DisplayName() + @"</td>"; } } if (type == 34) { var voicelen = -1; string[] audioMsg = message.Split(':'); if (audioMsg.Length == 3) { voicelen = int.Parse(audioMsg[1]); } if (hasRes) { var audiosrc = GetVoicePath(msg.ImgPath); if (audiosrc == null) { message = voicelen == -1 ? "[语音]" : "[语音 " + Utils.DisplayTime(voicelen) + "]"; } else { Utils.ShellWait("lib\\silk_v3_decoder.exe", "\"" + audiosrc + "\" 1.pcm"); Utils.ShellWait("lib\\lame.exe", "-r -s 24000 --preset voice 1.pcm \"" + Path.Combine(userSaveDir, "voice2", msg.MsgId + ".mp3") + "\""); message = "<audio controls><source src=\"voice2/" + msg.MsgId + ".mp3\" type=\"audio/mpeg\"><a href=\"voice2" + msg.MsgId + ".mp3\">播放</a></audio>"; } } else { message = voicelen == -1 ? "[语音]" : "[语音 " + Utils.DisplayTime(voicelen) + "]"; } } else if (type == 47) { var match = Regex.Match(message, @"cdnurl ?= ?""(.+?)"""); if (match.Success) { var localfile = Utils.RemoveCdata(match.Groups[1].Value); var match2 = Regex.Match(localfile, @"\/(\w+?)\/\w*$"); if (!match2.Success) { localfile = Utils.RandomString(10); } else { localfile = match2.Groups[1].Value; } emojidown.Add(new DownloadTask() { url = match.Groups[1].Value, filename = localfile + ".gif" }); message = "<img src=\"Emoji/" + localfile + ".gif\" style=\"max-width:100px;max-height:60px\" />"; } else { message = "[表情]"; } } else if (type == 62) { message = "[视频]"; } else if (type == 50) { message = "[视频/语音通话]"; } else if (type == 3) { if (hasRes && GetImagePath(msg.ImgPath, out string thumPath, out string bigPath)) { if (thumPath != null && bigPath != null) { message = "<a href=\"image2/" + bigPath + "\"><img src=\"image2/" + thumPath + "\" style=\"max-width:100px;max-height:60px\" /></a>"; } else if (thumPath != null) { message = "<img src=\"image2/" + thumPath + "\" style=\"max-width:100px;max-height:60px\" />"; } else if (bigPath != null) { message = "<img src=\"image2/" + bigPath + "\" style=\"max-width:100px;max-height:60px\" />"; } } else { message = "[图片]"; } } else if (type == 48) { var match1 = Regex.Match(message, @"x ?= ?""(.+?)"""); var match2 = Regex.Match(message, @"y ?= ?""(.+?)"""); var match3 = Regex.Match(message, @"label ?= ?""(.+?)"""); if (match1.Success && match2.Success && match3.Success) { message = "[位置 (" + Utils.RemoveCdata(match2.Groups[1].Value) + "," + Utils.RemoveCdata(match1.Groups[1].Value) + ") " + Utils.RemoveCdata(match3.Groups[1].Value) + "]"; } else { message = "[位置]"; } } else if (type == 49) { if (message.Contains("<type>2001<")) { message = "[红包]"; } else if (message.Contains("<type>2000<")) { message = "[转账]"; } else if (message.Contains("<type>17<")) { message = "[实时位置共享]"; } else if (message.Contains("<type>6<")) { message = "[文件]"; } else { var match1 = Regex.Match(message, @"<title>(.+?)<\/title>"); var match2 = Regex.Match(message, @"<des>(.*?)<\/des>"); var match3 = Regex.Match(message, @"<url>(.+?)<\/url>"); var match4 = Regex.Match(message, @"<thumburl>(.+?)<\/thumburl>"); if (match1.Success && match3.Success) { message = ""; if (match4.Success) { message += "<img src=\"" + Utils.RemoveCdata(match4.Groups[1].Value) + "\" style=\"float:left;max-width:100px;max-height:60px\" />"; } message += "<a href=\"" + Utils.RemoveCdata(match3.Groups[1].Value) + "\"><b>" + Utils.RemoveCdata(match1.Groups[1].Value) + "</b></a>"; if (match2.Success) { message += "<br />" + Utils.RemoveCdata(match2.Groups[1].Value); } } else { message = "[链接]"; } } } else if (type == 42) { var match1 = Regex.Match(message, "nickname ?= ?\"(.+?)\""); var match2 = Regex.Match(message, "smallheadimgurl ?= ?\"(.+?)\""); if (match1.Success) { message = ""; if (match2.Success) { message += "<img src=\"" + Utils.RemoveCdata(match2.Groups[1].Value) + "\" style=\"float:left;max-width:100px;max-height:60px\" />"; } message += "[名片] " + Utils.RemoveCdata(match1.Groups[1].Value); } else { message = "[名片]"; } } else { message = Utils.SafeHTML(message); } ts += @"<td width=""100"" align=""center"">" + FromUnixTime(unixtime).ToLocalTime().ToString().Replace(" ", "<br />") + "</td>"; ts += @"<td>" + message + @"</td></tr>"; sw.WriteLine(ts); count++; if (count > maxCount) { break; } } catch (Exception) { } }
private void IphoneRun() { int maxCount = int.MaxValue; if (!softReg.GetIsReg()) { maxCount = 10; MessageBox.Show("非注册用户暂时支持部分导出 \n如果导出全量信息请到https://www.weixinxqm.com/购买注册!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } var saveBase = textBox1.Text; Directory.CreateDirectory(saveBase); AddLog("分析文件夹结构"); IphoneWeChatInterface wechat = new IphoneWeChatInterface(((IPhoneBackup)comboBox1.SelectedItem).path, files92); wechat.BuildFilesDictionary(); AddLog("查找UID"); var UIDs = wechat.FindUIDs(); AddLog("找到" + UIDs.Count + "个账号的消息记录"); var uidList = new List <DisplayItem>(); int delta = 90 / ((UIDs.Count > 0 ? UIDs.Count : 1) * 5); foreach (var uid in UIDs) { var userBase = Path.Combine("Documents", uid); AddLog("开始处理UID: " + uid); AddLog("读取账号信息"); if (wechat.GetUserBasics(uid, userBase, out Friend myself)) { AddLog("微信号:" + myself.ID() + " 昵称:" + myself.DisplayName()); } else { AddLog("没有找到本人信息,用默认值替代"); } var userSaveBase = Path.Combine(saveBase, myself.ID()); Directory.CreateDirectory(userSaveBase); AddLog("正在打开数据库"); if (!wechat.OpenMMSqlite(userBase, out System.Data.SQLite.SQLiteConnection conn)) { AddLog("打开MM.sqlite失败,跳过"); continue; } if (wechat.OpenWCDBContact(userBase, out SQLiteConnection wcdb)) { AddLog("存在WCDB,与旧版好友列表合并使用"); } AddLog("读取好友列表"); if (!wechat.GetFriendsDict(conn, wcdb, myself, out Dictionary <string, Friend> friends, out int friendcount)) { AddLog("读取好友列表失败,跳过"); continue; } AddLog("找到" + friendcount + "个好友/聊天室"); AddLog("导出好友列表:"); BaseWeChat.saveFriends(Path.Combine(userSaveBase, "好友列表.txt"), friends, maxCount, out int exportCount); AddLog("导出" + exportCount + "个好友"); conn.Close(); wcdb.Close(); var emojidown = new HashSet <DownloadTask>(); var chatList = new List <DisplayItem>(); var messageDBs = wechat.FindMessageDB(uid); foreach (var messageDB in messageDBs) { if (!wechat.OpenMessageSqlite(messageDB, out SQLiteConnection msgConn)) { AddLog("读取" + messageDB + "出错,跳过"); continue; } AddLog("查找对话:" + messageDB); wechat.GetChatSessions(msgConn, out List <string> chats); AddLog("找到" + chats.Count + "个对话"); foreach (var chat in chats) { 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 (textRadioButton.Checked) { if (wechat.SaveTextRecord(msgConn, Path.Combine(userSaveBase, id + ".txt"), displayname, id, myself, chat, friend, friends, maxCount, out int count)) { AddLog("成功处理" + count + "条"); } else { AddLog("失败"); } } else if (htmlRadioButton.Checked) { if (wechat.SaveHtmlRecord(msgConn, userBase, userSaveBase, displayname, id, myself, chat, friend, friends, maxCount, out int count, out HashSet <DownloadTask> _emojidown)) { AddLog("成功处理" + count + "条"); chatList.Add(new DisplayItem() { pic = "Portrait/" + (friend != null ? friend.FindPortrait() : "*****@*****.**"), text = displayname, link = id + ".html" }); } else { AddLog("失败"); } emojidown.UnionWith(_emojidown); } } msgConn.Close(); } if (htmlRadioButton.Checked) { BaseWeChat.MakeListHTML(chatList, Path.Combine(userSaveBase, "聊天记录.html")); } var portraitdir = Path.Combine(userSaveBase, "Portrait"); Directory.CreateDirectory(portraitdir); var downlist = new HashSet <DownloadTask>(); foreach (var item in friends) { var tfriend = item.Value; if (!tfriend.PortraitRequired) { continue; } if (tfriend.Portrait != null && tfriend.Portrait != "") { downlist.Add(new DownloadTask() { url = tfriend.Portrait, filename = tfriend.ID() + ".jpg" }); } //if (tfriend.PortraitHD != null && tfriend.PortraitHD != "") downlist.Add(new DownloadTask() { url = tfriend.PortraitHD, filename = tfriend.ID() + "_hd.jpg" }); } var downloader = new Downloader(6); if (downlist.Count > 0) { AddLog("下载" + downlist.Count + "个头像"); foreach (var item in downlist) { downloader.AddTask(item.url, Path.Combine(portraitdir, item.filename)); } try { File.Copy("res\\[email protected]", Path.Combine(portraitdir, "*****@*****.**")); } catch (Exception) { } } var emojidir = Path.Combine(userSaveBase, "Emoji"); Directory.CreateDirectory(emojidir); if (emojidown != null && emojidown.Count > 0) { AddLog("下载" + emojidown.Count + "个表情"); foreach (var item in emojidown) { downloader.AddTask(item.url, Path.Combine(emojidir, item.filename)); } } uidList.Add(new DisplayItem() { pic = myself.ID() + "/Portrait/" + myself.FindPortrait(), text = myself.DisplayName(), link = myself.ID() + "/聊天记录.html" }); downloader.StartDownload(); downloader.WaitToEnd(); AddLog("完成当前账号"); }