F-List log saver

A simple script to add buttons on login that let you save and load logs into your browser storage.

// ==UserScript==
// @name         F-List log saver
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  A simple script to add buttons on login that let you save and load logs into your browser storage.
// @author       DD
// @match        https://www.f-list.net/chat3/
// @grant        none
// ==/UserScript==


(function() {
    const userscript = document.createElement("script");
    userscript.innerHTML = `
const saveLogs=() => {
    //////////////////////////////////////////////////////////////////////////
    // Parse Local Storage
    //////////////////////////////////////////////////////////////////////////
    const keyList = Object.keys(window.localStorage);
    let storageContent = [];
    let completeJSON = {saved_dbs: {}};

    for(let key of keyList){
        storageContent.push(JSON.parse('{ "key":"' + key + '", "value":"" }'))
    }

    for(let key of storageContent){
        key.value = JSON.parse(window.localStorage.getItem(key.key));
    }

    completeJSON.saved_dbs.local_storage = storageContent;

    //////////////////////////////////////////////////////////////////////////
    // Parse IndexedDB
    //////////////////////////////////////////////////////////////////////////
    storageContent = {};
    let databaseLoopIndex = 0;
    indexedDB.databases().then(databaseList =>{
        for(let database of databaseList){
            const dataBaseLoop=(db, index)=>{
                let dbConnection;
                let request = window.indexedDB.open(db.name, db.version);
                request.onerror=(event) =>{
                    console.log('Error on connect to "'+db.name+'" : ' + event.target.errorCode);
                };
                request.onsuccess=(event) =>{
                    dbConnection = event.target.result;
                    console.log('Connection to "'+db.name+'" established!');
                    let databaseObject = {};

                    let storeIndex = 0;
                    for(let storeName of dbConnection.objectStoreNames){

                        const objectStoreLoop=(pStoreName, pStoreIndex, databaseIndex)=>{
                            databaseObject[pStoreName] = [];
                            let transaction = dbConnection.transaction([pStoreName]);

                            transaction.oncomplete=(event) =>{
                                console.log('Transaction finished on "' + pStoreName);
                                if(pStoreIndex === dbConnection.objectStoreNames.length - 1 &&
                                    databaseIndex === databaseList.length - 1){

                                    function downloadObjectAsJson(exportObj, exportName){
                                        var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
                                        var downloadAnchorNode = document.createElement('a');
                                        downloadAnchorNode.setAttribute("href", dataStr);
                                        downloadAnchorNode.setAttribute("download", exportName + ".json");
                                        document.body.appendChild(downloadAnchorNode); // required for firefox
                                        downloadAnchorNode.click();
                                        downloadAnchorNode.remove();
                                        console.log("Saved successfully!")
                                    }
                                    console.log(completeJSON);
                                    downloadObjectAsJson(completeJSON, "f-list-log");
                                }
                            };

                            transaction.onerror=(event)=>{
                                console.log('Transaction-Error: ' + event.target.errorCode);
                            };

                            transaction.objectStore(pStoreName).getAll().onsuccess=(event) =>{
                                databaseObject[pStoreName] = event.target.result;
                            }
                        }

                        objectStoreLoop(storeName, storeIndex, index);
                        storeIndex++;
                    };
                    storageContent[db.name] = databaseObject;
                };
            }
            dataBaseLoop(database, databaseLoopIndex);
            databaseLoopIndex++;
        }
    });
    completeJSON.saved_dbs.indexed_db = storageContent;
}

const loadLogs=(e)=>{
    const file = e.target.files[0];
    if (!file) {
        return;
    }
    const reader = new FileReader();
    reader.onload = function(e) {
        const contents = e.target.result;
        const totalJSONObject = JSON.parse(contents);
        console.log(totalJSONObject);

        //////////////////////////////////////////////////////////////////////////
        // load Local Storage
        //////////////////////////////////////////////////////////////////////////
        for(let entry of totalJSONObject.saved_dbs.local_storage){
            window.localStorage.setItem(entry.key, JSON.stringify(entry.value));
        }
        //////////////////////////////////////////////////////////////////////////
        // load IndexedDB
        //////////////////////////////////////////////////////////////////////////
        let databaseLoopIndex = 0;
        const databaseList = Object.keys(totalJSONObject.saved_dbs.indexed_db);
        // Need to parse the datestrigns properly into dates
        for(let databaseName of databaseList){
            for(let entry of totalJSONObject.saved_dbs.indexed_db[databaseName].logs){
                entry.time = new Date(entry.time);
            }
        }

        console.log(totalJSONObject);

        for(let database of databaseList){
            const dataBaseLoop=(dbName)=>{
                let request = window.indexedDB.open(dbName, 1);
                request.onerror=(event) =>{
                    console.log('Error on connect to "'+dbName+'" : ' + event.target.errorCode);
                };
                request.onsuccess=(event) =>{
                    const dbConnection = event.target.result;
                    console.log('Connection to "'+dbName+'" established!');

                    let storeIndex = 0;
                    for(let storeName of dbConnection.objectStoreNames){

                        const objectStoreLoop=(pStoreName)=>{
                            const transaction = dbConnection.transaction(pStoreName, "readwrite");

                            transaction.oncomplete=(event) =>{
                                console.log('Transaction finished on "' + pStoreName);
                            };

                            transaction.onerror=(event)=>{
                                console.log('Transaction-Error: ' + event.target.errorCode);
                            };

                            // transaction.objectStore(pStoreName).getAll().onsuccess=(event) =>{
                            // }
                            const objectStoreArray = totalJSONObject.saved_dbs.indexed_db[dbName][pStoreName];
                            let objectStore = transaction.objectStore(pStoreName);
                            objectStoreArray.forEach(element => {
                                objectStore.put(element).onsuccess=(event) => {}
                            });

                        }
                        objectStoreLoop(storeName);
                        storeIndex++;
                    };
                };
                request.onupgradeneeded=(event) => {
                    const dbConnection = event.target.result;
                    dbConnection.createObjectStore("conversations", {autoIncrement: true, keyPath: "id"});

                    const objectStore = dbConnection.createObjectStore("logs", {autoIncrement: true, keyPath: "id"});
                    objectStore.createIndex("conversation", "conversation", {unique: false});
                    objectStore.createIndex("conversation-day", ["conversation", "day"], {unique: false});
                }
            }
            dataBaseLoop(database);
            databaseLoopIndex++;
        }
    };
    reader.readAsText(file);
}

//////////////////////////////////////////////////////////////////////////
// Insert buttons
//////////////////////////////////////////////////////////////////////////
let cardHeader = document.getElementsByClassName("card-body")[0].childNodes[2];

// Execute the code only when connected
if(cardHeader){
    // Show the buttons on the page for Saving and Loading
    let btn_load = document.createElement("input");
    let btn_save = document.createElement("button");

    btn_save.setAttribute("class", "btn btn-primary");
    btn_save.innerText = "Save Logs";
    btn_save.setAttribute("onclick", "saveLogs()");
    cardHeader.appendChild(btn_save);

    // btn_load.setAttribute("class", "btn btn-primary");
    btn_load.innerText = "Load Logs";
    btn_load.setAttribute("type", "file");
    btn_load.setAttribute("id", "btn_load");
    cardHeader.appendChild(btn_load);

    document.getElementById('btn_load')
    .addEventListener('change', loadLogs, false);
}
`;
    document.getElementsByTagName("html")[0].appendChild(userscript);
})();