Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export, import, merge history #12

Open
AlttiRi opened this issue Sep 25, 2022 · 10 comments
Open

Export, import, merge history #12

AlttiRi opened this issue Sep 25, 2022 · 10 comments
Labels
enhancement New feature or request fixed

Comments

@AlttiRi
Copy link
Owner

AlttiRi commented Sep 25, 2022

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: #12 (comment) 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
Copy link
Owner Author

AlttiRi commented Oct 24, 2022

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: #12 (comment)

@AlttiRi
Copy link
Owner Author

AlttiRi commented Oct 24, 2022

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

You need manually click here to open the file selector:

image

@biggestsonicfan
Copy link

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.

@AlttiRi
Copy link
Owner Author

AlttiRi commented Oct 24, 2022

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
Copy link
Owner Author

AlttiRi commented Oct 24, 2022

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.

@biggestsonicfan
Copy link

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

@biggestsonicfan
Copy link

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

@AlttiRi
Copy link
Owner Author

AlttiRi commented Nov 25, 2022

Yes, this temporal workaround overwrites.

I did not write, that it does merge:
#12 (comment)
Here is the export and the import code snippets only.

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

@AlttiRi
Copy link
Owner Author

AlttiRi commented Nov 25, 2022

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
Copy link
Owner Author

AlttiRi commented Jul 5, 2023

Finally, made it.

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

0838777 Migrate to new LocalStorage names
fe50907 Support "continuous migration"
85da601 Add listeners for historyHelper (export/import/merge history)
ee6664c Add verify, onDone/onError for "import"/"merge"
af79609 Add the browser name in the export file name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fixed
Projects
None yet
Development

No branches or pull requests

2 participants