|
(function(){ |
|
|
|
const WORKSPACE_ID = 'YOUR-WORKSPACE-ID', |
|
DB_NAME = 'reduxPersistence', |
|
DB_VERSION = 2, |
|
STORE = 'reduxPersistenceStore'; |
|
|
|
function main(db) { |
|
if (WORKSPACE_ID === 'YOUR-WORKSPACE-ID') { |
|
alert('Please, change the WORKSPACE_ID'); |
|
return; |
|
} |
|
|
|
let transaction = db.transaction([STORE], 'readonly'); |
|
let objectStore = transaction.objectStore(STORE); |
|
|
|
let result = {}; |
|
objectStore.openCursor().onsuccess = function (event) { |
|
let cursor = event.target.result; |
|
if (cursor) { |
|
if (cursor.key.includes(WORKSPACE_ID)) { |
|
result[cursor.key] = cursor.value; |
|
} |
|
cursor.continue(); |
|
} else { |
|
showWidgets(result); |
|
} |
|
} |
|
} |
|
|
|
function showWidgets(db) { |
|
// Building blobs |
|
let full = JSON.stringify(db, null, 2); |
|
let blobs = {full: createTextBlob(full)}; |
|
let dump = db[Object.keys(db)[0]]; |
|
|
|
if (!dump.channels || !dump.members || !dump.messages) { |
|
console.log('RAW database:', db); |
|
alert('Error. See console output.'); |
|
return; |
|
} |
|
|
|
let nestedObjFix = (o) => o.hasOwnProperty('internalUseOnlyByIdMap') |
|
? o.internalUseOnlyByIdMap : o; |
|
|
|
let chats = nestedObjFix(dump.channels); |
|
let members = nestedObjFix(dump.members); |
|
|
|
for (let id in dump.messages) { |
|
let text = ''; |
|
let chat = dump.messages[id]; |
|
|
|
for (let ts in chat) { |
|
let message = chat[ts]; |
|
let time = new Date(message.ts * 1000).toISOString(); |
|
let sender = members[message.user] ? members[message.user].real_name : message.user; |
|
|
|
text += `${time} ${sender}:\n${message.text}\n${'_'.repeat(80)}\n\n` |
|
} |
|
|
|
blobs[id] = createTextBlob(text); |
|
} |
|
|
|
// Rendering widgets |
|
let root = window._slackExportRootElement = window._slackExportRootElement || document.createElement('div'); |
|
root.innerHTML = ` |
|
<style> |
|
.et_dd{padding:20px;margin:20px 0 20px 20px;width:200px;height:64px;} |
|
.et_dl{cursor:pointer;color:#fff;display:inline-block;text-align:center;background-color:green;padding:20px;margin: 20px 20px 20px -2px;width:200px;height:64px;} |
|
</style>`; |
|
|
|
document.body.insertBefore(root, document.body.firstChild); |
|
|
|
let downloadLink = html2Node('<a class="et_dl">Download</a>'); |
|
let chatsDropdown = html2Node(` |
|
<select class="et_dd"> |
|
<option data-href="${blobs.full}" data-download="indexedDB_${WORKSPACE_ID}.json"> |
|
Full Backup as JSON |
|
</option> |
|
</select>`); |
|
|
|
chatsDropdown.addEventListener('change', function (e) { |
|
let selected = e.target[e.target.selectedIndex]; |
|
downloadLink.setAttribute('href', selected.getAttribute('data-href')); |
|
downloadLink.setAttribute('download', selected.getAttribute('data-download')); |
|
}); |
|
|
|
for (let id in chats) { |
|
let chat = chats[id]; |
|
|
|
if (!dump.messages[id]) continue; |
|
|
|
chatsDropdown.appendChild(html2Node(` |
|
<option data-href="${blobs[id]}" data-download="chat_${chat.name}_${id}.txt" title="${chat.purpose.value || ''}"> |
|
${members[chat.user] ? members[chat.user].real_name : chat.name} |
|
</option>`)); |
|
} |
|
|
|
root.appendChild(chatsDropdown); |
|
root.appendChild(downloadLink); |
|
window.scrollTo(0, 0); |
|
} |
|
|
|
function html2Node(html) { |
|
let template = document.createElement('template'); |
|
html = html.trim(); |
|
template.innerHTML = html; |
|
return template.content.firstChild; |
|
} |
|
|
|
function createTextBlob(text) { |
|
return window.URL.createObjectURL(new Blob([text], {'type': 'text/plain;charset=utf-8;'})); |
|
} |
|
|
|
let request = indexedDB.open(DB_NAME, DB_VERSION); |
|
request.onsuccess = function () { |
|
main(request.result); |
|
} |
|
request.onerror = function (event) { |
|
console.log(request.errorCode); |
|
} |
|
|
|
})(); |