F-List log saver

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

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

ستحتاج إلى تثبيت إضافة مثل Stylus لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتتمكن من تثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

(لدي بالفعل مثبت أنماط للمستخدم، دعني أقم بتثبيته!)

// ==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);
})();