gemini_mod_drive

Google Drive Functions for Google Gemini Mod

Questo script non dovrebbe essere installato direttamente. È una libreria per altri script da includere con la chiave // @require https://update.greasyfork.org/scripts/584956/1864001/gemini_mod_drive.js

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Advertisement:

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

Advertisement:

/**
 * gemini_mod_drive.js
 * Contains Google Drive Authorization and API logic for the Gemini Mod Userscript.
 */

window.GeminiMod = window.GeminiMod || {};

window.GeminiMod.drive = {
    STORAGE_KEY_GDRIVE_TOKEN: 'gemini_gdrive_token',
    STORAGE_KEY_GDRIVE_CLIENT_ID: 'gemini_gdrive_client_id',

    getGoogleDriveToken: async function () {
        return await GM_getValue(this.STORAGE_KEY_GDRIVE_TOKEN);
    },

    getGoogleDriveClientId: async function () {
        return await GM_getValue(this.STORAGE_KEY_GDRIVE_CLIENT_ID);
    },

    initiateGoogleDriveAuth: async function () {
        const clientId = await this.getGoogleDriveClientId();
        if (!clientId) {
            GeminiMod.utils.displayUserscriptMessage("Please enter your Google Cloud Client ID in the settings first.");
            return;
        }

        const redirectUri = window.location.origin + "/app";
        const scope = "https://www.googleapis.com/auth/drive.file";
        const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=token&scope=${encodeURIComponent(scope)}&state=gdrive_auth_v1&include_granted_scopes=true&prompt=consent`;

        const width = 500;
        const height = 600;
        const left = (window.screen.width / 2) - (width / 2);
        const top = (window.screen.height / 2) - (height / 2);
        window.open(authUrl, "_blank", `width=${width},height=${height},top=${top},left=${left}`);
    },

    handleAuthCallback: function () {
        const hash = window.location.hash;
        if (hash && hash.includes("access_token") && hash.includes("state=gdrive_auth_v1")) {
            const params = new URLSearchParams(hash.substring(1));
            const token = params.get("access_token");
            if (token) {
                if (window.opener) {
                    window.opener.postMessage({ type: "GDRIVE_TOKEN", token: token }, window.location.origin);
                    window.close();
                } else {
                    console.log("Gemini Mod: Token received but no opener found.");
                }
            }
        }
    },

    setupAuthMessageListener: function (rendererCallback) {
        window.addEventListener("message", async (event) => {
            if (event.origin !== window.location.origin) return;
            if (event.data && event.data.type === "GDRIVE_TOKEN") {
                await GM_setValue(this.STORAGE_KEY_GDRIVE_TOKEN, event.data.token);
                GeminiMod.utils.displayUserscriptMessage("Google Drive connected successfully!", false);
                if (rendererCallback) rendererCallback();
            }
        });
    },

    saveToDrive: async function (currentSettings) {
        const token = await this.getGoogleDriveToken();
        if (!token) {
            GeminiMod.utils.displayUserscriptMessage("Google Drive not connected.");
            return;
        }

        GeminiMod.utils.displayUserscriptMessage("Saving settings to Google Drive...", false);

        const dataToSave = {
            ...currentSettings,
            timestamp: Date.now(),
            version: 1
        };
        const fileContent = JSON.stringify(dataToSave, null, 2);
        const fileName = "gemini_userscript_settings.json";

        GM_xmlhttpRequest({
            method: "GET",
            url: "https://www.googleapis.com/drive/v3/files?q=name='" + fileName + "' and trashed=false",
            headers: { "Authorization": "Bearer " + token },
            onload: (response) => {
                try {
                    const result = JSON.parse(response.responseText);
                    if (result.error) throw new Error(result.error.message);

                    const existingFile = result.files && result.files.length > 0 ? result.files[0] : null;

                    if (existingFile) {
                        this.updateDriveFile(existingFile.id, fileContent, token);
                    } else {
                        this.createDriveFile(fileName, fileContent, token);
                    }
                } catch (e) {
                    console.error("GDrive Search Error:", e);
                    GeminiMod.utils.displayUserscriptMessage("Failed to search Drive: " + e.message);
                }
            }
        });
    },

    createDriveFile: function (name, content, token) {
        const metadata = {
            name: name,
            mimeType: 'application/json'
        };

        const form = new FormData();
        form.append('metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json' }));
        form.append('file', new Blob([content], { type: 'application/json' }));

        GM_xmlhttpRequest({
            method: "POST",
            url: "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
            headers: { "Authorization": "Bearer " + token },
            data: form,
            onload: function (response) {
                if (response.status >= 200 && response.status < 300) {
                    GeminiMod.utils.displayUserscriptMessage("Settings saved to Google Drive successfully!", false);
                } else {
                    GeminiMod.utils.displayUserscriptMessage("Failed to create file on Drive.");
                    console.error("GDrive Create Error:", response.responseText);
                }
            }
        });
    },

    updateDriveFile: function (fileId, content, token) {
        GM_xmlhttpRequest({
            method: "PATCH",
            url: "https://www.googleapis.com/upload/drive/v3/files/" + fileId + "?uploadType=media",
            headers: { "Authorization": "Bearer " + token, "Content-Type": "application/json" },
            data: content,
            onload: function (response) {
                if (response.status >= 200 && response.status < 300) {
                    GeminiMod.utils.displayUserscriptMessage("Settings updated on Google Drive successfully!", false);
                } else {
                    GeminiMod.utils.displayUserscriptMessage("Failed to update file on Drive.");
                    console.error("GDrive Update Error:", response.responseText);
                }
            }
        });
    },

    loadFromDrive: async function (onLoadSuccess) {
        const token = await this.getGoogleDriveToken();
        if (!token) {
            GeminiMod.utils.displayUserscriptMessage("Google Drive not connected.");
            return;
        }

        GeminiMod.utils.displayUserscriptMessage("Loading settings from Google Drive...", false);

        const fileName = "gemini_userscript_settings.json";

        GM_xmlhttpRequest({
            method: "GET",
            url: "https://www.googleapis.com/drive/v3/files?q=name='" + fileName + "' and trashed=false",
            headers: { "Authorization": "Bearer " + token },
            onload: (response) => {
                try {
                    const result = JSON.parse(response.responseText);
                    if (result.error) throw new Error(result.error.message);

                    const existingFile = result.files && result.files.length > 0 ? result.files[0] : null;

                    if (existingFile) {
                        this.downloadDriveFile(existingFile.id, token, onLoadSuccess);
                    } else {
                        GeminiMod.utils.displayUserscriptMessage("No backup file (" + fileName + ") found on Drive.");
                    }
                } catch (e) {
                    GeminiMod.utils.displayUserscriptMessage("Failed to search Drive: " + e.message);
                }
            }
        });
    },

    downloadDriveFile: function (fileId, token, onLoadSuccess) {
        GM_xmlhttpRequest({
            method: "GET",
            url: "https://www.googleapis.com/drive/v3/files/" + fileId + "?alt=media",
            headers: { "Authorization": "Bearer " + token },
            onload: async function (response) {
                try {
                    const data = JSON.parse(response.responseText);
                    await onLoadSuccess(data);
                } catch (e) {
                    GeminiMod.utils.displayUserscriptMessage("Failed to parse downloaded file: " + e.message);
                }
            }
        });
    },

    // --- File Backup/Restore ---

    exportSettingsToFile: function (dataToSave) {
        const fullData = {
            ...dataToSave,
            timestamp: Date.now(),
            version: 1,
            // gdriveClientId: GM_getValue(STORAGE_KEY_GDRIVE_CLIENT_ID) // Caller must provide this if needed
        };
        const blob = new Blob([JSON.stringify(fullData, null, 2)], { type: "application/json" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `gemini_settings_backup_${new Date().toISOString().slice(0, 10)}.json`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
        GeminiMod.utils.displayUserscriptMessage("Settings exported to file!", false);
    },

    importSettingsFromFile: function (file, onImportSuccess) {
        const reader = new FileReader();
        reader.onload = async (e) => {
            try {
                const data = JSON.parse(e.target.result);
                if (data && data.toolbarItems && data.folders) {
                    GeminiMod.utils.showConfirmationDialog("This will overwrite your current settings with the imported file. Continue?", async () => {
                        await onImportSuccess(data);
                    }, "Import", "dialog-btn-confirm");
                } else {
                    GeminiMod.utils.displayUserscriptMessage("Invalid backup file.");
                }
            } catch (err) {
                GeminiMod.utils.displayUserscriptMessage("Error reading file: " + err.message);
            }
        };
        reader.readAsText(file);
    }
};