twitter-click-and-save
twitter-click-and-save copied to clipboard
Export, import, merge history
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.
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
In Firefox input.click(); does not work (from the browser's console).
You need manually click here to open the file selector:

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.
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.


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.
Ah, got it, it worked that time, thank you!
You've got to be kidding me. This import overwrites existing entries and doesn't merge them?! I lost all my history again...
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).
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();
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