1 Star 0 Fork 0

Rison/ExportWeChatMsgForWindows

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
decode_favorite_msg.cpp 25.38 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
#include <QtCore>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>
#include <utility>
#include "chat_message_define.h"
#include "chat_personal_define.h"
extern std::string xml2json(const char* xml_str);
namespace helper {
void ReplaceEmojiMsgToImage(QString& source);
bool DownloadWechatImage(const QString& src_path, QString& dst_path);
QSize GetImageSize(const QString& path);
int GetDatabaseQueryCount(QSqlQuery& query);
QString FavoriteSubHistory2Html(const QList<QVariant>& msgList);
QString FavoriteHistory2Html(const QList<QVariant>& msgList);
QByteArray ReadDataFromFile(const QString& path);
bool SaveContent2File(const QByteArray& data, const QString& path, bool enable_log);
bool CopyFile2Target(const QString& source, const QString& target);
} // namespace helper
namespace {
//全局数据
static QString kSourcePath = TARGET_SOURCE_PATH;
static QString kResourcePath = TARGET_FAVORI_PATH;
static QString kOutputPath =
QDir(TARGET_OUTPUT_PATH + QString("../favorite/")).absolutePath() + "/";
static QStringList kFileVec;
//过滤一些垃圾收藏或者涉及个人隐私的图片等
#ifdef _DEBUG
QSet<int> kSkipSet = {
+138, +185, +296, +352, +386, +398, +421, +506, +579, +586, +622, +623, +624, +630, +667, +701,
+728, +744, +814, +993, 1003, 1004, 1022, 1030, 1047, 1048, 1053, 1059, 1063, 1067, 1069, 1070,
1071, 1076, 1081, 1083, 1093, 1094, 1095, 1096, 1098, 1115, 1118, 1120, 1125, 1126, 1127, 1128,
1137, 1144, 1156, 1174, 1177, 1182, 1189, 1196, 1203, 1207, 1238, 1252, 1253, 1261, 1264, 1273,
1275, 1309, 1310, 1320, 1325, 1326, 1330, 1332, 1333, 1337, 1344, 1345, 1364, 1367, 1373, 1375,
1379, 1388, 1400, 1401, 1407, 1408, 1412, 1420, 1424, 1436, 1438, 1442, 1453, 1454, 1459, 1466,
1467, 1485, 1487, 1491, 1498, 1500, 1501, 1502, 1503, 1504, 1505, 1512, 1519, 1522, 1523, 1524,
1534, 1535, 1539, 1543, 1544, 1562, 1563, 1565, 1573, 1574, 1576, 1578, 1579, 1580, 1583, 1589,
1592, 1594, 1603, 1604, 1606, 1621, 1628, 1629, 1678, 1680, 1691, 1702, 1703, 1710, 1711, 1724,
1741, 1742, 1744, 1750, 1751, 1762, 1766, 1787, 1795, 1797, 1803, 1808, 1810, 1811, 1813, 1826,
1827, 1831, 1833, 1839, 1840, 1846, 1852, 1853, 1856, 1864, 1870, 1887, 1889, 1896, 1922, 1897,
1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1907, 1911, 1923, 1926, 1932, 1935, 1936, 1946,
1950, 1955, 1963, 1964, 1974, 1977, 1981, 1982, 1990, 1991, 1997, 1999, 2003, 2009, 2010, 2014,
2018, 2024, 2032, 2037, 2044, 2048, 2055, 2057, 2066, 2073, 2074, 2076, 2078, 2084, 2086, 2089,
2091, 2093, 2101, 2103, 2104, 2113, 2117, 2119, 2120, 2122, 2124, 2126, 2137, 2138, 2139, 2145,
2146, 2154, 2173, 2185, 2187, 2221, 2271, 2277, 2292, 2302, 2307, 2310, 2326, 2333, 2355, 2362,
2370, 2382, 2406, 2407, 2412, 2420, 2435, 2437, 2438, 2439, 2442, 2443, 2444, 2450, 2454, 2455,
2456, 2461, 2463, 2465, 2466, 2470, 2473, 2492, 2501, 2502, 2504, 2507, 2510, 2511, 2515, 2521,
2527, 2531, 2532, 2534, 2547, 2548, 2555, 2556, 2557, 2558, 2566, 2578, 2585, 2591, 2593, 2595,
2598, 2599, 2602, 2605, 2608, 2610, 2612, 2613, 2614, 2619, 2620, 2624, 2630, 2633, 2638, 2641,
2645, 2647, 2651, 2664, 2665, 2676, 2677, 2680, 2683, 2684, 2688, 2689, 2691, 2692, 2697, 2701,
2703, 2709, 2745, 2757, 2780, 2787, 2788, 2790, 2795, 2849, 2852, 2858, 2864, 2870, 2872, 2888,
2890, 2901, 2914, 2934, 2937, 2967, 2977, 2978, 2981, 2988, 2992, 2996, 3004, 3010, 3014, 3025,
3035, 3047, 3059, 3075, 3076, 3077, 3078, 3098, 3099, 3100, 3101, 3107, 3116, 3119, 3120, 3121,
3189, 3225, 3245, 3246, 3247, 3253, 3258, 3270, 3271, 3272, 3287, 3288, 3302, 3317, 3329, 3342,
3343, 3400, 3403, 3404, 3405, 3413, 3422, 3423, 3426, 3430, 3432, 3439, 3440, 3442, 3443, 3444,
3445, 3446, 3449, 3451, 3454, 3459, 3463, 3534, 3535, 3536, 3537, 3559, 3560, 3561, 3575, 3576,
3577, 3584, 3585, 3601, 3602, 3603, 3622, 3623, 3624, 3635, 3636, 3637, 3642, 3670, 3683, 3688,
3699, 3701, 3725, 3754, 3755, 3756, 3757, 3758, 3787, 3788, 3789, 3790, 3791, 3824, 3830, 3844,
3857, 3858, 3859, 3860, 3861, 3862, 3881, 3883, 3898, 3902, 3906, 3910, 3947, 3948, 3949, 3950,
3969, 3970, 3971, 3972, 4009, 4010, 4012, 4013, 4014, 4015, 4019, 4027, 4038, 4040, 4041, 4042,
4073, 4074, 4096, 4130, 4198, 4199, 4202, 4205, 4206, 4207, 4227, 4231, 4241, 4249, 4254, 4255,
4256, 4330, 4344, 4351, 4358, 4372, 4378, 4383, 4385, 4386, 4387, 4388, 4389, 4390, 4399, 4400,
4419, 4441, 4450, 4456, 4459, 4461, 4462, 4467, 4468, 4474, 4477, 4478, 4495, 4503, 4504, 4509,
4514, 4515, 4516, 4608, 4524, 4525, 4528, 4529, 4530, 4531, 4533, 4539, 4540, 4541, 4542, 4543,
4544, 4554, 4555, 4558, 4610, 4611, 4656, 4658, 4659, 4661, 4666, 4675, 4700, 4707, 4708, 4709,
4710, 4716, 4732, 4733, 4765, 4785, 4786, 4787, 4788, 4805, 4813, 4818, 4829, 4831, 4841, 4845,
4846, 4862, 4891, 4907, 4916, 4982, 5001, 5002, 5042, 5043, 5162, 5179, 5182, 5201, 5207, 5260,
5311, 5312, 5327, 5447, 5462, 5474, 5504, 5536, 5538, 5563, 5646, 5676, 5704, 5789, 5806, 5813,
};
QSet<int> kSkipSet2 = {
1732, 1814, 1847, 1867, 1869, 1871, 1886, 1939, 1942, 1948, 1965, 1967, 1968, 1972, 1985, 2002,
2008, 2016, 2019, 2031, 2035, 2036, 2045, 2046, 2054, 2056, 2058, 2067, 2068, 2069, 2071, 2072,
2079, 2080, 2090, 2094, 2096, 2097, 2099, 2100, 2102, 2105, 2106, 2107, 2111, 2112, 2116, 2125,
2141, 2142, 2155, 2156, 2184, 2198, 2201, 2207, 2209, 2214, 2219, 2236, 2261, 2269, 2283, 2290,
2291, 2294, 2295, 2315, 2321, 2330, 2331, 2334, 2337, 2339, 2340, 2342, 2347, 2351, 2354, 2357,
2363, 2369, 2380, 2381, 2383, 2385, 2394, 2402, 2421, 2425, 2431, 2434, 2448, 2453, 2457, 2467,
2468, 2475, 2479, 2499, 2503, 2506, 2508, 2514, 2518, 2520, 2535, 2542, 2543, 2552, 2561, 2568,
2570, 2573, 2574, 2579, 2580, 2588, 2589, 2594, 2596, 2597, 2600, 2601, 2603, 2604, 2607, 2628,
2632, 2634, 2640, 2646, 2649, 2650, 2652, 2655, 2663, 2666, 2668, 2669, 2670, 2673, 2678, 2685,
2686, 2687, 2698, 2699, 2700, 2702, 2707, 2708, 2710, 2711, 2713, 2715, 2717, 2719, 2731, 2734,
2750, 2754, 2761, 2765, 2772, 2783, 2784, 2799, 2800, 2801, 2808, 2813, 2814, 2825, 2827, 2829,
2832, 2833, 2834, 2850, 2854, 2863, 2877, 2887, 2896, 2902, 2906, 2912, 2924, 2926, 2930, 2931,
2947, 2952, 2962, 2985, 2990, 2991, 2993, 2994, 3005, 3006, 3015, 3017, 3023, 3044, 3050, 3079,
3085, 3088, 3112, 3163, 3170, 3171, 3175, 3182, 3183, 3188, 3248, 3250, 3277, 3278, 3283, 3324,
3325, 3326, 3358, 3390, 3407, 3421, 3431, 3461, 3462, 3484, 3521, 3530, 3565, 3566, 3597, 3641,
3643,
};
#else
QSet<int> kSkipSet;
QSet<int> kSkipSet2;
#endif
QStringList parseFromResourceDir(const QString& resourcePath) {
QStringList res;
QDir dir(resourcePath);
QFileInfoList fileInfoList = dir.entryInfoList();
foreach(const QFileInfo& fileInfo, fileInfoList) {
if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
continue;
if (fileInfo.isFile()) {
res.push_back(fileInfo.fileName());
}
}
return res;
}
void parseResourcesFromDir() {
kFileVec = parseFromResourceDir(kResourcePath + "res/");
}
QString findResourcesWithDataId(const QString& id, bool matchComplete) {
auto target =
std::find_if(kFileVec.begin(), kFileVec.end(), [id, matchComplete](const QString& item) {
return matchComplete ? (item == id) : item.startsWith(id);
});
if (target == kFileVec.end()) {
return QString();
} else {
return *target;
}
}
QMap<QString, QVariant> parseFavitemFromXml(int localIndex, const QString& xmlBuff) {
std::string jsonNode = xml2json(xmlBuff.toStdString().c_str());
QJsonParseError parseJsonErr;
QJsonDocument document =
QJsonDocument::fromJson(QString::fromStdString(jsonNode).toUtf8(), &parseJsonErr);
if (!(parseJsonErr.error == QJsonParseError::NoError)) {
qWarning() << u8"解析第" << localIndex << u8"条数据出错,解析 json文件错误:"
<< parseJsonErr.errorString();
return QMap<QString, QVariant>();
}
return document.object().toVariantMap()["favitem"].toMap();
}
QString getTimeFmt(qlonglong updateTime) {
return QDateTime::fromSecsSinceEpoch(updateTime).toString("yyyy-MM-dd hh:mm:ss");
}
QString copyFavoriteImage(const QString& imageId,
const QString& prefix,
qlonglong updateTime,
QString& thumbImage) {
//拷贝大图
QString resourceBigImage = findResourcesWithDataId(imageId + ".", false);
QString targetBigImage = "images/" + FAV_BIG_IMAGE(imageId);
QString targetOutImage = kOutputPath + prefix + targetBigImage;
if (QFile::exists(targetOutImage)) {
// good
} else if (!resourceBigImage.isEmpty()) {
helper::CopyFile2Target(kResourcePath + "res/" + resourceBigImage, targetOutImage);
} else {
qWarning() << "image id:" << imageId
<< ", big image is not downloaded, time:" << getTimeFmt(updateTime);
}
//拷贝小图
thumbImage = findResourcesWithDataId(imageId + "_th.", false);
QString targetSmallImage = "images/" + FAV_SMALL_IMAGE(imageId);
targetOutImage = kOutputPath + prefix + targetSmallImage;
if (QFile::exists(targetOutImage)) {
// good
thumbImage = targetSmallImage;
} else if (!thumbImage.isEmpty()) {
helper::CopyFile2Target(kResourcePath + "res/" + thumbImage, targetOutImage);
thumbImage = targetSmallImage;
} else if (!resourceBigImage.isEmpty()) {
helper::CopyFile2Target(kOutputPath + prefix + targetBigImage, targetOutImage);
thumbImage = targetSmallImage;
} else {
qWarning() << "image id:" << imageId
<< ", small image is not downloaded, time:" << getTimeFmt(updateTime);
}
return targetBigImage;
}
QString copyFavoriteVideo(const QString& videoId,
const QString& prefix,
qlonglong updateTime,
QString& thumbImage) {
// 拷贝视频
QString resourceVideoPath = findResourcesWithDataId(videoId + ".", false);
QString targetVideoPath = "video/" + FAV_VIDEO_FILE(videoId);
QString targetOutVideo = kOutputPath + prefix + targetVideoPath;
if (QFile::exists(targetOutVideo)) {
// good
} else if (!resourceVideoPath.isEmpty()) {
helper::CopyFile2Target(kResourcePath + "res/" + resourceVideoPath, targetOutVideo);
} else {
qWarning() << "video id:" << videoId
<< ", video is not downloaded, time:" << getTimeFmt(updateTime);
}
// 拷贝小图
thumbImage = findResourcesWithDataId(videoId + "_th.", false);
QString targetThumbPath = "video/" + FAV_VIDEO_THUMB(videoId);
QString targetOutThumb = kOutputPath + prefix + targetThumbPath;
if (QFile::exists(targetOutThumb)) {
// good
thumbImage = targetThumbPath;
} else if (!thumbImage.isEmpty()) {
helper::CopyFile2Target(kResourcePath + "res/" + thumbImage, targetOutThumb);
thumbImage = targetThumbPath;
} else {
qWarning() << "video id:" << videoId
<< ", thumbnail is not downloaded, time:" << getTimeFmt(updateTime);
}
return targetVideoPath;
}
void cleanFavoriteLink(QString& link) {
// 去掉多余的符号
link.replace("&from=timeline", "");
link.replace("from=timeline&", "");
link.replace("#wechat_redirect", "");
link.replace("&isappinstalled=0", "");
if (link.endsWith("#rd")) {
link.chop(3);
}
}
QString copyFavoriteLink(const QString& linkId,
const QString& link,
const QString& prefix,
QString thumbUrl) {
Q_ASSERT(!linkId.isEmpty());
//再找缓存,下载,分析网页
auto resourceThumb = findResourcesWithDataId(linkId + "_th", false);
auto targetLinkThumb = prefix + "link/" + FAV_LINK_THUMB(linkId);
auto targetOutThumb = kOutputPath + targetLinkThumb;
if (QFile::exists(targetOutThumb)) {
// good
} else if (!resourceThumb.isEmpty()) {
helper::CopyFile2Target(kResourcePath + "res/" + resourceThumb, targetOutThumb);
} else if (!thumbUrl.isEmpty()) {
QString tmp = targetOutThumb;
helper::DownloadWechatImage(thumbUrl, tmp);
if (tmp != targetOutThumb) {
QFile::rename(tmp, targetOutThumb);
}
} else {
// TODO 提取链接图标
// if (link.contains("mp.weixin.qq.com")) {
// // TODO 下载微信网页并获得获得缩略图地址
// thumbUrl = "1234567";
//} else if (link.contains("zhihu.com") || link.contains("douban.com") ||
// link.contains("weibo.cn") || link.contains("qq.com") || link.contains("jd.com") ||
// link.contains("cnblogs.com") || link.contains("163.com")) {
// // No thumbnail
// // 知乎应该是有缩略图的,到时候要验证下
// // qWarning() << "link thumbnail not exists, id:" << id << ", url:" << link;
// return QString();
//}
qWarning() << "link thumbnail not exists, id:" << linkId << ", url:" << link;
targetLinkThumb.clear();
}
return targetLinkThumb;
}
QString copyFavoriteFile(const QString& fileId,
const QString& prefix,
const QString& format,
qlonglong updateTime) {
Q_ASSERT(!format.isEmpty());
auto resourceFile = findResourcesWithDataId(fileId + ".", false);
QString targetFile = "files/" + FAV_FILE_RESOURCE(fileId, format);
QString outputFile = kOutputPath + prefix + targetFile;
if (QFile::exists(outputFile)) {
// good
} else if (!resourceFile.isEmpty()) {
helper::CopyFile2Target(kResourcePath + "res/" + resourceFile, outputFile);
} else {
qWarning() << "file id:" << fileId
<< ", file is not downloaded, time:" << getTimeFmt(updateTime);
}
return targetFile;
}
QString saveFavChatHistoryHtml(const QString& title, const QString& content, const QString& path) {
QString temporate = helper::ReadDataFromFile(kOutputPath + "chat/fav_sub_chat_tmp.html");
QString bytes = temporate.arg(title, content);
helper::SaveContent2File(bytes.toUtf8(), path, true);
return path;
}
QString copyFavoriteChatHistory(const QList<QVariant>& msgList) {
for (const QVariant& data : msgList) {
auto dataItem = data.toMap();
auto id = dataItem["@dataid"].toString();
auto type = dataItem["@datatype"].toInt();
QString timeString = dataItem["datasrctime"].toString();
bool is_fmt = timeString.length() == QString("yyyy-MM-dd hh:mm:ss").length();
qint64 time =
QDateTime::fromString(timeString, is_fmt ? "yyyy-MM-dd hh:mm:ss" : "yyyy-M-d hh:mm")
.toSecsSinceEpoch();
if (type == FavType_Text) {
// no need to copy
} else if (type == FavType_Image) {
QString thumbImage;
copyFavoriteImage(id, "chat/", time, thumbImage);
} else if (type == FavType_Video) {
QString thumbImage;
copyFavoriteVideo(id, "chat/", time, thumbImage);
} else if (type == FavType_Link) {
auto link = dataItem["dataitemsource"].toMap()["link"].toString();
if (link.isEmpty()) {
link = dataItem["weburlitem"].toMap()["clean_url"].toString();
}
copyFavoriteLink(id, link, "chat/", QString());
} else if (type == FavType_Location) {
// no need to copy
} else if (type == FavType_File) {
auto fmt = dataItem["datafmt"].toString();
copyFavoriteFile(id, "chat/", fmt, time);
} else if (type == FavType_InnerChatHistory) {
auto title = dataItem["datatitle"].toString();
auto subHistory = dataItem["recordxml"]
.toMap()["recordinfo"]
.toMap()["datalist"]
.toMap()["dataitem"]
.toList();
auto subHtml = helper::FavoriteSubHistory2Html(subHistory);
auto path = kOutputPath + "chat/" + FAV_SUB_HISTORY_HTML(id);
saveFavChatHistoryHtml(title, subHtml, path);
} else if (type == FavType_MiniProgram) {
auto thumb = dataItem["appbranditem"].toMap()["iconurl"].toString();
QString target = kOutputPath + "chat/link/" + FAV_LINK_THUMB(id);
if (thumb.isEmpty()) {
qWarning() << "copy mini program thumb fail, no url, id:" << id;
} else if (!QFile::exists(target)) {
QString tmp = target;
helper::DownloadWechatImage(thumb, tmp);
if (tmp != target) {
QFile::rename(tmp, target);
}
}
} else {
qDebug() << "type:" << type << " unsupport";
}
}
//转为html,相当于笔记类型了。是前面类型的集合,以dataitem为区分
//要想办法根据username找到昵称(备注)和头像
auto html = helper::FavoriteHistory2Html(msgList);
return html;
}
} // namespace
namespace wechat {
//从数据库里面直接读取头像数据 Misc.db,ffd8是jpg,8950是png
void DecodeFavoriteMessage() {
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(kSourcePath + R"(Msg\dec_Favorite.db)");
if (!db.open()) {
qWarning() << "open database failed";
return;
}
//查询微信收藏记录
QSqlQuery query(db);
query.prepare("SELECT * FROM FavItems ORDER BY FavLocalID");
query.exec();
//统计数目
int result_count = helper::GetDatabaseQueryCount(query);
qDebug() << "find " << result_count << " messages";
// 先找出本地目录的map,用于快速查询
parseResourcesFromDir();
QJsonArray jsonArray;
while (query.next()) {
//过滤一些垃圾收藏或者涉及个人隐私的图片等
auto localIndex = query.value("FavLocalID").toInt();
if (kSkipSet.contains(localIndex) || kSkipSet2.contains(localIndex)) {
continue;
}
auto type = query.value("Type").toInt();
auto updateTime = query.value("UpdateTime").toLongLong();
auto xmlBuff = query.value("XmlBuf").toString();
//解析xml数据
auto&& jsonMap = parseFavitemFromXml(localIndex, xmlBuff);
if (jsonMap.isEmpty()) {
continue;
}
auto desc = jsonMap["desc"].toString();
auto title = jsonMap.contains("title") ? jsonMap["title"].toString() : desc;
auto source = jsonMap["source"].toMap();
auto dataItem = jsonMap["datalist"].toMap()["dataitem"].toMap();
auto dataId = dataItem["@dataid"].toString();
auto searchKey = query.value("SearchKey").toString();
if (searchKey.endsWith('\n')) {
searchKey.chop(1);
}
//构造json格式的数据结构
QJsonObject item;
item["m_uiMesLocalID"] = localIndex;
item["m_uiMessageType"] = type;
item["m_nsContent"] = desc;
if (type == FavType_Text) {
helper::ReplaceEmojiMsgToImage(desc);
item["m_nsContent"] = desc;
} else if (type == FavType_Image) {
QString prefix = "normal/";
QString thumbPath;
QString imagePath = copyFavoriteImage(dataId, prefix, updateTime, thumbPath);
if (imagePath.isEmpty()) {
item["m_nsOriginal"] = xmlBuff;
}
item["m_nsContent"] = imagePath.isEmpty() ? imagePath : prefix + imagePath;
item["m_nsThumbnail"] = thumbPath.isEmpty() ? thumbPath : prefix + thumbPath;
if (!imagePath.isEmpty()) {
auto&& size = helper::GetImageSize(kOutputPath + prefix + imagePath);
item["m_nsWidth"] = size.width();
item["m_nsHeight"] = size.height();
}
} else if (type == FavType_Video ||
(type == FavType_Extend && dataItem["@datatype"].toInt() == FavType_Video2)) {
QString prefix = "normal/";
QString thumbPath;
QString videoPath = copyFavoriteVideo(dataId, prefix, updateTime, thumbPath);
if (videoPath.isEmpty()) {
item["m_nsOriginal"] = xmlBuff;
}
item["m_uiMessageType"] = FavType_Video;
item["m_nsContent"] = videoPath.isEmpty() ? videoPath : prefix + videoPath;
item["m_nsThumbnail"] = thumbPath.isEmpty() ? thumbPath : prefix + thumbPath;
} else if (type == FavType_Link) {
auto link = source["link"].toString();
title = dataItem["datatitle"].toString();
desc = dataItem["datadesc"].toString();
if (dataId.isEmpty()) {
dataId = source["@sourceid"].toString();
}
QString thumbUrl;
if (jsonMap.contains("weburlitem")) {
auto dataItem = jsonMap["weburlitem"].toMap();
if (title.isEmpty()) {
title = dataItem["pagetitle"].toString();
}
if (desc.isEmpty()) {
desc = dataItem["pagedesc"].toString();
}
thumbUrl = dataItem["pagethumb_url"].toString();
}
cleanFavoriteLink(link);
item["m_nsTitle"] = title.isEmpty() ? link : title;
item["m_nsContent"] = link;
item["m_nsDescription"] = desc;
item["m_nsThumbnail"] = copyFavoriteLink(dataId, link, "normal/", thumbUrl);
} else if (type == FavType_File) {
auto format = dataItem["datafmt"].toString();
//处理文件名
title = title.isEmpty() ? dataItem["datatitle"].toString() : title;
if (!title.isEmpty() && !title.contains(".")) {
title += QString(".").append(format);
}
QString filePath = copyFavoriteFile(dataId, "normal/", format, updateTime);
if (filePath.isEmpty()) {
item["m_nsOriginal"] = xmlBuff;
} else {
filePath = "normal/" + filePath;
}
item["m_nsFormat"] = format;
item["m_nsTitle"] = title;
item["m_nsContent"] = filePath;
item["m_nsFileExist"] = !filePath.isEmpty();
item["m_nsFileSize"] = dataItem["fullsize"].toLongLong();
} else if (type == FavType_ChatHistory) {
//拷贝资源并转换为html
auto msgList = jsonMap["datalist"].toMap()["dataitem"].toList();
auto historyId =
QString::number(localIndex) + "_" + msgList.at(0).toMap()["@dataid"].toString();
auto path = kOutputPath + "chat/" + FAV_CHAT_HISTORY_HTML(historyId);
//如果本地处理过则无须重复处理
if (!QFile::exists(path)) {
QString html = copyFavoriteChatHistory(msgList);
if (title.isEmpty()) {
title = source["fromusr"].toString();
}
saveFavChatHistoryHtml(title, html, path);
}
//处理emoji表情
if (desc.isEmpty()) {
desc = searchKey;
}
// TODO 273, desc is empty, generate?
helper::ReplaceEmojiMsgToImage(desc);
item["m_nsTitle"] = title;
item["m_nsContent"] = path.mid(kOutputPath.length());
item["m_nsDescription"] = desc;
item["m_nsOriginal"] = xmlBuff;
} else if (type == FavType_Extend) {
qWarning() << u8"其他扩展信息";
} else if (type == FavType_WeChatNote) {
//笔记,TODO,这个也有可能需要自己生成简介
auto noteList = jsonMap["datalist"].toMap()["dataitem"].toList();
if (desc.isEmpty()) {
desc = searchKey;
}
item["m_nsTitle"] = title;
item["m_nsDescription"] = desc;
item["m_nsOriginal"] = xmlBuff;
qWarning() << u8"笔记:要用模板拼接";
} else if (type == FavType_MiniProgram) {
if (title.isEmpty()) {
title = dataItem["datatitle"].toString();
desc = dataItem["datadesc"].toString();
}
auto appItem = jsonMap["appbranditem"].toMap();
auto appId = appItem["appid"].toString();
auto appBrandId = source["brandid"].toString();
auto appIcon = appItem["iconurl"].toString();
auto appDisplayName = appItem["sourcedisplayname"].toString();
// qDebug() << "id: " << appId << ", title:"<< title << ", brand:" << appBrandId <<", name:"
// << appDisplayName;
} else if (type == FavType_ShiPinHao) {
//视频号收藏,只能自己补一些截图和描述了
auto feedItem = jsonMap["finderFeed"].toMap();
auto feedNickName = feedItem["nickname"].toString(); //分享者
auto feedUserName = feedItem["username"].toString();
auto feedAvatar = feedItem["avatar"].toMap()["#text"].toString();
auto thumb =
feedItem["mediaList"].toMap()["media"].toMap()["thumbUrl"].toMap()["#text"].toString();
desc = feedItem["desc"].toString();
// TODO 有缩略图,可以解析下来存储
// qDebug() << u8"视频号:" << desc;
} else {
item["m_nsContent"] = xmlBuff;
qWarning() << "unsupport favorite type:" << type;
}
//更新时间等
item["m_nsSearchKey"] = searchKey;
item["m_uiCreateTime"] = updateTime;
// TODO 处理消息来源
auto fromUser = query.value("FromUser").toString();
auto realUser = query.value("RealChatName").toString();
item["m_nsFromUsr"] = fromUser;
item["m_nsToUsr"] = TARGET_USER;
item["m_nsRealChatName"] = realUser;
jsonArray.push_back(item);
}
//格式化json
QString content = QJsonDocument(jsonArray).toJson(QJsonDocument::Indented);
//读取模板信息并写入到新的文件
QString bytes = helper::ReadDataFromFile(kOutputPath + "js/message_wechat_tmp.js");
helper::SaveContent2File(bytes.arg(content).toUtf8(), kOutputPath + "js/message_fav.js", true);
}
} // namespace wechat
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/rison13/ExportWeChatMsgForWindows.git
git@gitee.com:rison13/ExportWeChatMsgForWindows.git
rison13
ExportWeChatMsgForWindows
ExportWeChatMsgForWindows
master

搜索帮助