Last active
October 27, 2019 12:47
-
-
Save kearlsaint/053f96baafba3e1bcd9fec1e45f34c95 to your computer and use it in GitHub Desktop.
Snippet of code to create a full XML backup of messages from Pulse Messenger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* | |
* Snippet of code to create a full XML backup of messages from Pulse Messenger | |
* https://github.com/klinker-apps/messenger-desktop | |
* | |
* This code utilizes the webapp's core functions. | |
* | |
* Instructions | |
* 1. Log into https://messenger.klinkerapps.com | |
* 2. Wait for the UI to load your conversations | |
* 3. Open Developer Console | |
* 4. Paste the following code | |
* 5. Wait for your data to download(check Network tab) | |
* 6. Download SMSBackupRestore from PlayStore (https://play.google.com/store/apps/details?id=com.riteshsahu.SMSBackupRestore) | |
* 7. Put backup XML file to SD Card | |
* 8. Restore using SMSBackupRestore | |
* | |
* profit 5 cents | |
* | |
* Changelog: | |
* 06 MAY 2018: Changed to multi-query per conversation thread to reduce server load & support slow connections | |
* --> Set custom limit per query @ line 150, default is 20 | |
* Added a bit of log output to console | |
* | |
**/ | |
$(function() { | |
String.prototype.toHtmlEntities = function() { | |
// https://stackoverflow.com/a/4237934 | |
// https://stackoverflow.com/a/27020300 | |
// https://stackoverflow.com/a/32712035 | |
var str = this; | |
if ($.trim(str) != "") { | |
str = str.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); | |
str = str.replace(/&(?!(amp;)|(lt;)|(gt;)|(quot;)|(#39;)|(apos;))/g, "&"); | |
str = str.replace(/([^\\])((\\\\)*)\\(?![\\/{])/g, "$1\\\\$2"); //replaces odd backslash(\\) with even. | |
} | |
return str.replace(/[^\u0009|\u0020-\uD7FF|\uE000-\uFFFD|\uDBFFDFFF-\u10FFFF]/gim, function(s) { | |
return "&#" + s.charCodeAt(0) + ";"; | |
}); | |
}; | |
// modified version for xml export | |
// only decrypts .data | |
// does not convert emojis to web emojis | |
// converts non-xml-safe chars | |
function decryptMessages_forExport(data) { | |
for (var i = data.length - 1; i >= 0; i--) { | |
try { | |
data[i].data = entityEncode(decrypt(data[i].data)); | |
data[i].data = data[i].data.toHtmlEntities(); | |
} catch (err) { | |
data[i].data = ""; | |
} | |
} | |
// remove duplicate messages | |
for (var i = 0; i < data.length; i++) { | |
var currentId = data[i].device_id; | |
for (var j = i + 1; j < data.length; j++) { | |
if (data[j].device_id == currentId) { | |
data.splice(j, 1); | |
j--; | |
} | |
} | |
} | |
return data; | |
} | |
function export_to_xml(data) { | |
/* | |
* data needed for SMSBackupRestore | |
* protocol="0" | |
* address= | |
* date= | |
* type=1(received)/2(sent) | |
* subject="null" | |
* body= | |
* toa="null" | |
* sc_toa="null" | |
* service_center="" | |
* read="1" | |
* status="-1" | |
* locked="0" | |
* date_sent= | |
* readable_date="Jun 4, 2017 23:40:11" | |
* contact_name= | |
*/ | |
// xml headers | |
var xml_string = ""; | |
xml_string += "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>\n"; | |
xml_string += '<?xml-stylesheet type="text/xsl" href="sms.xsl"?>\n'; | |
var msg_string = ""; | |
var msg_count = 0; | |
// loop through each conversation thread | |
for(var i=0, d, m, n, f; i < data.length; i++) { | |
d = data[i]; | |
f = d.name; | |
n = d.number; | |
t = d.messages; | |
// loop through each message | |
for(var j=0, m; j<t.length; j++) { | |
m = t[j]; | |
msg_string += '<sms'; | |
msg_string += ' protocol="0"'; | |
msg_string += ' address="' + n + '"'; | |
msg_string += ' date="' + m.timestamp + '"'; | |
msg_string += ' type="' + (m.message_type+1) + '"'; | |
msg_string += ' subject="null"'; | |
msg_string += ' body="' + m.data + '"'; | |
msg_string += ' toa="null"'; | |
msg_string += ' sc_toa="null"'; | |
msg_string += ' service_center=""'; | |
msg_string += ' read="1"'; | |
msg_string += ' status="-1"'; | |
msg_string += ' locked="0"'; | |
msg_string += ' date_sent="' + m.timestamp + '"'; | |
msg_string += ' readable_date=""'; | |
msg_string += ' contact_name="' + n + '"'; | |
msg_string += '/>\n'; | |
} | |
msg_count += t.length; | |
} | |
xml_string += '<smses count="' + msg_count + '" backup_date="' + new Date().getTime() + '">\n'; | |
xml_string += msg_string; | |
xml_string += '</smses>'; | |
// export to sms | |
var download = document.createElement("a"); | |
download.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(xml_string)); | |
download.setAttribute('download', 'backup-' + new Date().getTime() + '.xml'); | |
$("body").append(download); | |
download.click(); | |
} | |
url="https://api.messenger.klinkerapps.com/api/v1/conversations/index_unarchived?account_id=" + accountId; | |
var messages=[]; | |
var convo_list; | |
var fetched=0; | |
$.get(url).done(function(data) { | |
convo_list = decryptConversations(data); | |
console.log("Fetching " + convo_list.length + " conversation threads..."); | |
for(var i=0; i<convo_list.length; i++) { | |
(function(q, z) { // save val of i to q | |
var t = "https://api.messenger.klinkerapps.com/api/v1/messages?web=true&account_id=" + accountId + "&conversation_id=" + q.device_id + ""; | |
var l = 20, o = 0; // limit, offset | |
var ret = function() { | |
t += "&limit=" + l + "&offset=" + o; | |
$.get(t).done(function(data) { | |
if(data.length <= 0) { | |
// no more messages | |
// mark whole thread as fetched | |
console.log(" --> fetched thread #" + z); | |
fetched++; | |
if(fetched >= convo_list.length) { | |
console.log("Exporting to XML, please check download progress."); | |
export_to_xml(messages); | |
} | |
} else { | |
// decrypt and save messages | |
messages.push({ | |
number: q.phone_numbers, | |
name: q.title, | |
messages: decryptMessages_forExport(data) | |
}); | |
// get next offset | |
o += l; | |
setTimeout(ret, 200); | |
} | |
}); | |
}; | |
console.log(" --> fetching thread #" + z); | |
ret(); | |
})(convo_list[i], i + 1); | |
} | |
}); | |
}); |
Modified the code to paginate the query per thread and hopefully reduce the load. Thanks for the suggestion 👍
Getting an error
}' is not a valid selector
Does this snippet no longer work? Chrome just says "undefined" when ran in the console.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You should probably paginate the
messages
query. That/messages
route will accept alimit
andoffset
query parameter. I recommend a limit of 500, or less, messages per query, just to keep the load a bit lower. The endpoint will time out after 30 seconds.