// ==UserScript== // @name Evolve Idle Cloud Save // @namespace https://github.com/Alistair1231/my-userscripts/ // @version 1.0.0 // @description Automatically upload your evolve save to a gist // @author Alistair1231 // @match https://pmotschmann.github.io/Evolve/ // @icon https://icons.duckduckgo.com/ip2/github.io.ico // @grant GM.xmlhttpRequest // @grant GM.setValue // @grant GM.getValue // @license GPL-3.0 // @require https://cdn.jsdelivr.net/gh/Alistair1231/my-userscripts@232b1d6f0a0a6eb47fcccb94e6346d8230562154/lib.js // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_listValues // @require https://cdn.jsdelivr.net/gh/Alistair1231/my-userscripts@232b1d6f0a0a6eb47fcccb94e6346d8230562154/libValues.js // @grant GM_xmlhttpRequest // @require https://cdn.jsdelivr.net/gh/Alistair1231/my-userscripts@232b1d6f0a0a6eb47fcccb94e6346d8230562154/libRequest.js // @downloadURL none // ==/UserScript== // https://greasyfork.org/en/scripts/490376-automatic-evolve-save-upload-to-gist // https://github.com/Alistair1231/my-userscripts/raw/master/EvolveIdleSavegameBackup.user.js /* # Evolve Idle Cloud Save Automatically upload your evolve save to a gist, on first run you will be prompted to enter your Gist ID and Personal Access Token. These will be saved as cleartext in the Userscript storage. The token should have the `gist` scope. The Gist, has to be created manually, and the ID should be entered in the settings. Exporting is always done to the filename specified in the settings. Import can be done from any file in the Gist. (e.g. after changing PCs). Automatic backup is done every 15 minutes. Manual backup can be done by clicking the "Save to" button. The script also exposes the `evolveCloudSave` object to the window for manual use. */ (async function () { "use strict"; const lib = { ...libDefault, ...libRequest, ...libValues }; const evolveCloudSave = { // Create an overlay to collect secrets from the user openSettings: () => { const saveSettings = () => { const gistId = document.getElementById("gist_id").value.trim(); const token = document.getElementById("gist_token").value.trim(); const fileName = document.getElementById("file_name").value.trim() || "save.txt"; if (!gistId || !token) { alert("Gist ID and Token are required!"); return; } lib.settings.gistId = gistId; lib.settings.token = token; lib.settings.fileName = fileName; document.body.removeChild(overlay); }; const fillCurrentSettings = () => { document.getElementById("gist_id").value = lib.settings.gistId || ""; document.getElementById("gist_token").value = lib.settings.token || ""; document.getElementById("file_name").value = lib.settings.fileName || "save.txt"; }; let overlay = document.createElement("div"); overlay.innerHTML = `
You will need a GistID and a Personal Access Token to use this cloud-save script. They will be saved as cleartext in the Userscript storage!
`; document.body.appendChild(overlay); // clicking on overlay and esc handling overlay.addEventListener("click", (e) => { if (e.target.id === "settings_overlay") { document.body.removeChild(overlay); } }); document.addEventListener("keydown", (e) => { if (e.key === "Escape") { if (document.getElementById("settings_overlay")) { document.body.removeChild(overlay); } } }); document.getElementById("save_button").addEventListener("click", (e) => { e.preventDefault(); saveSettings(); }); fillCurrentSettings(); }, getFiles: async (request) => { const files = await request.get(""); return JSON.parse(files).files; }, createOrUpdateFile: async (request, filename, content) => { const files = await evolveCloudSave.getFiles(request); if (files[filename] === undefined) { return request.post("", { files: { [filename]: { content } } }); } else { return request.patch("", { files: { [filename]: { content } } }); } }, makeBackup: async (request) => { const saveString = unsafeWindow.exportGame(); const response = await evolveCloudSave.createOrUpdateFile( request, lib.settings.filename, saveString, ); return response; }, getBackup: async (request) => { const files = await evolveCloudSave.getFiles(request); const filename = document.getElementById("cloudsave_fileSelect").value; const content = files[filename].content; document.querySelector("textarea#importExport").value = content; }, addButtons: async (request) => { const buttons = document.createElement("div"); let files = await evolveCloudSave.getFiles(request); const filenames = Object.keys(files); buttons.innerHTML = `
`; const div = document.querySelectorAll("div.importExport")[1]; div.appendChild(buttons); document .getElementById("cloudsave_importGistButton") .addEventListener("click", () => { evolveCloudSave.getBackup(request); }); document .getElementById("cloudsave_exportGistButton") .addEventListener("click", async () => { await evolveCloudSave.makeBackup(request); const successMessage = document.getElementById("success_message"); successMessage.style.display = "block"; setTimeout(() => { successMessage.style.transition = "opacity 1s"; successMessage.style.opacity = "0"; setTimeout(() => { successMessage.style.display = "none"; successMessage.style.opacity = "1"; }, 1000); }, 2000); }); document .getElementById("cloudsave_settingsButton") .addEventListener("click", () => { evolveCloudSave.openSettings(request); }); }, init: async () => { const request = new lib.Request( `https://api.github.com/gists/${lib.settings.gistId}`, { Authorization: `token ${lib.settings.token}`, }, ); evolveCloudSave.addButtons(request); }, }; lib.waitFor("div#main", () => { if (lib.settings.gistId === undefined || lib.settings.token === undefined) { evolveCloudSave.openSettings(); return; } else { evolveCloudSave.init(); // run every 15 minutes setInterval(evolveCloudSave.makeBackup, 1000 * 60 * 15); // export for manual use unsafeWindow.evolveCloudSave = evolveCloudSave; unsafeWindow.evolveCloudSave.settings = lib.settings; } }); })();