twitter-click-and-save icon indicating copy to clipboard operation
twitter-click-and-save copied to clipboard

Export, import, merge history

Open AlttiRi opened this issue 3 years ago • 10 comments
trafficstars

I need to implement export, import, merge download history.

However, I need to totally refactor the related code. Make the localStorage values names more clear.

~Also I need to change the archive format for videos, since there multi-videos tweets. At least for new ones. So, I need to keep for videos the new and old history arrays.~


Temporary, you can use in the browsers console the follow code snippets: https://github.com/AlttiRi/twitter-click-and-save/issues/12#issuecomment-1326920033 for exporting, importing, merging the history. Just open the browser's console on https://twitter.com and paste the required code snippet. For importing/merging click on the web page first to focus the page of the web site.

AlttiRi avatar Sep 25 '22 00:09 AlttiRi

While it is not implemented you can manually import/export (history + settings) by running the follow code in the browser's console:

The outdated version

To export:

let exportObject = [
    "ujs-click-n-save-settings",
    "ujs-images-history-by",
    "ujs-twitter-downloaded-images-names",
    "ujs-twitter-downloaded-image-tweet-ids", 
    "ujs-twitter-downloaded-video-tweet-ids"
    ].reduce((acc, name) => {
        const value = localStorage.getItem(name);
        if (value === null) {
            return acc;
        }
        acc[name] = localStorage.getItem(name);
        return acc;
    }, {});
downloadBlob(new Blob([JSON.stringify(exportObject)]), "ujs-c'n's-export.json");
function downloadBlob(blob, name, url) {
    const anchor = document.createElement("a");
    anchor.setAttribute("download", name || "");
    const blobUrl = URL.createObjectURL(blob);
    anchor.href = blobUrl + (url ? ("#" + url) : "");
    anchor.click();
    setTimeout(() => URL.revokeObjectURL(blobUrl), 8000);
}

To import:

let input = document.createElement("input");
input.type = "file";
input.accept = "application/json";
document.body.prepend(input);
input.addEventListener("change", async event => {
    const json = JSON.parse(await input.files[0].text());

    console.log("json", json);
    globalThis.json = json;

    Object.entries(json).forEach(([key, value]) => {
        localStorage.setItem(key, value);
    });
});
input.click();

The new code snippets: https://github.com/AlttiRi/twitter-click-and-save/issues/12#issuecomment-1326920033

AlttiRi avatar Oct 24 '22 14:10 AlttiRi

In Firefox input.click(); does not work (from the browser's console).

You need manually click here to open the file selector:

image

AlttiRi avatar Oct 24 '22 14:10 AlttiRi

On twitter the button is unclickable due to the twitter logo. Going to another site it allows me to click the button and select the file but nothing happens.

biggestsonicfan avatar Oct 24 '22 18:10 biggestsonicfan

It should be done exactly on https://twitter.com origin.

Each "site" (origin) has its own LocalStorage database.


Just checked it works fine for me.

image

image

AlttiRi avatar Oct 24 '22 18:10 AlttiRi

Also input.click(); (to open the file chooser automatically) works, if you click on the web site first (just click on any element, for example, on a text) before running the script in the console.

AlttiRi avatar Oct 24 '22 18:10 AlttiRi

Ah, got it, it worked that time, thank you!

biggestsonicfan avatar Oct 24 '22 18:10 biggestsonicfan

You've got to be kidding me. This import overwrites existing entries and doesn't merge them?! I lost all my history again...

biggestsonicfan avatar Nov 24 '22 23:11 biggestsonicfan

Yes, this temporal workaround overwrites.

I did not write, that it does merge: https://github.com/AlttiRi/twitter-click-and-save/issues/12#issuecomment-1289141835 Here is the export and the import code snippets only.

The merge option should be the third option (export, import and merge).

AlttiRi avatar Nov 25 '22 00:11 AlttiRi

Here is the new versions. They use the new, more correct, form of the JSON file (no more "[\"abcd\",\"qwert\"]", now it's ["abcd","qwert"]).

With the merge code snippet.


ONLY FOR THE OLD VERSION

To export:

let exportObject = [
    "ujs-click-n-save-settings",
    "ujs-images-history-by",
    "ujs-twitter-downloaded-images-names",
    "ujs-twitter-downloaded-image-tweet-ids",
    "ujs-twitter-downloaded-video-tweet-ids"
].reduce((acc, name) => {
    const value = localStorage.getItem(name);
    if (value === null) {
        return acc;
    }
    acc[name] = JSON.parse(value);
    return acc;
}, {});
downloadBlob(new Blob([JSON.stringify(exportObject)]), "ujs-tcas-export.json");
function downloadBlob(blob, name, url) {
    const anchor = document.createElement("a");
    anchor.setAttribute("download", name || "");
    const blobUrl = URL.createObjectURL(blob);
    anchor.href = blobUrl + (url ? ("#" + url) : "");
    anchor.click();
    setTimeout(() => URL.revokeObjectURL(blobUrl), 8000);
}

To import:

let importInput = document.createElement("input");
importInput.type = "file";
importInput.accept = "application/json";
document.body.prepend(importInput);
importInput.addEventListener("change", async event => {
    const json = JSON.parse(await importInput.files[0].text());

    console.log("json", json);
    globalThis.json = json;

    Object.entries(json).forEach(([key, value]) => {
        localStorage.setItem(key, JSON.stringify(value));
    });
});
importInput.click();

To merge:

let mergeInput = document.createElement("input");
mergeInput.type = "file";
mergeInput.accept = "application/json";
document.body.prepend(mergeInput);
mergeInput.addEventListener("change", async event => {
    const json = JSON.parse(await mergeInput.files[0].text());

    console.log("json", json);
    globalThis.json = json;

    Object.entries(json).forEach(([key, value]) => {
        const existedValue = JSON.parse(localStorage.getItem(key));
        if (Array.isArray(existedValue)) {
            value = [...new Set([...existedValue, ...value])];
        }
        localStorage.setItem(key, JSON.stringify(value));
    });
});
mergeInput.click();

AlttiRi avatar Nov 25 '22 00:11 AlttiRi

Finally, made it.

  • three buttons: "export", "import", "merge".
  • changed LocalStorare keys for unification.

https://github.com/AlttiRi/twitter-click-and-save/commit/0838777aff678d3f5cd9fb56d2f86926e28b5509 Migrate to new LocalStorage names https://github.com/AlttiRi/twitter-click-and-save/commit/fe50907298303691aa44a1844b70c12ee2b133c0 Support "continuous migration" https://github.com/AlttiRi/twitter-click-and-save/commit/85da601bd5125aaa83b92a040d9bc30eb1da7eff Add listeners for historyHelper (export/import/merge history) https://github.com/AlttiRi/twitter-click-and-save/commit/ee6664c90f282003d9b2b9a7c10fcb29bc462133 Add verify, onDone/onError for "import"/"merge" https://github.com/AlttiRi/twitter-click-and-save/commit/af79609d717b1f2288aaf3a5c2cbbbf6b1203f12 Add the browser name in the export file name

AlttiRi avatar Jul 05 '23 18:07 AlttiRi