Search with Gemini

Lets you use Gemini as a custom search engine. Reads 'prompt' parameter from URL and automatically submits it to Gemini chat.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Search with Gemini
// @namespace    https://github.com/alexey-kudryavtsev/
// @version      2025.07.27.1
// @description  Lets you use Gemini as a custom search engine. Reads 'prompt' parameter from URL and automatically submits it to Gemini chat.
// @author       Alexey Kudryavtsev
// @match        https://gemini.google.com/*
// @grant        none
// @run-at       document-start
// @license      Apache-2.0
// @homepageURL  https://github.com/alexey-kudryavtsev/search-with-gemini
// @supportURL   https://github.com/alexey-kudryavtsev/search-with-gemini/issues
// ==/UserScript==


(function() {
    'use strict';

    // --- Configuration ---
    const log = (message) => console.log(`[Gemini Userscript] ${message}`);
    const PROMPT_SELECTOR = '.ql-editor[contenteditable="true"] > p';
    const SUBMIT_BUTTON_SELECTOR = 'button[aria-label="Send message"]';

    log('Script initialized (document-start).');

    // Ensure window.geminiScript object exists
    if (typeof window.geminiScript === 'undefined') {
        window.geminiScript = {};
    }

    // --- Early Execution: Extract prompt and clean URL ---
    const currentUrl = new URL(window.location.href);
    const promptValue = currentUrl.searchParams.get('prompt');

    if (promptValue) {
        log(`Found 'prompt' URL parameter during early execution: "${promptValue}"`);
        window.geminiScript.currentPrompt = promptValue; // Store the prompt
        currentUrl.searchParams.delete('prompt'); // Remove the 'prompt' parameter

        // Replace the URL in the browser's history without reloading
        const cleanUrl = currentUrl.pathname + currentUrl.search + currentUrl.hash;
        history.replaceState(null, '', cleanUrl);
        log(`🧹 URL cleaned. New URL: ${cleanUrl}`);
    } else {
        log("No 'prompt' URL parameter found during early execution. Script is idle for prefill.");
        window.geminiScript.currentPrompt = null; // Ensure it's explicitly null if not found
    }

    /**
     * Finds the prompt input, fills it, finds the submit button, and clicks it.
     * This function will be called AFTER the document is ready.
     * @param {string} textToFill - The prompt text to inject.
     */
    function prefillThenSubmit(textToFill) {
        log('🕵️‍♂️ Starting observer for the input field...');
        const inputObserver = new MutationObserver((mutations, inputObs) => {
            const promptInput = document.querySelector(PROMPT_SELECTOR);
            if (promptInput) {
                log('✅ Step 1: Input field found.');
                inputObs.disconnect();

                // Inject prompt text
                promptInput.textContent = textToFill;
                log(`📝 Text set to: "${textToFill}"`);

                // Now, wait for the submit button to become available
                const submitObserver = new MutationObserver((mutations, submitObs) => {
                    const submitButton = document.querySelector(SUBMIT_BUTTON_SELECTOR);
                    // Also check that it's not disabled
                    if (submitButton && !submitButton.disabled) {
                        log('✅ Step 2: Submit button found and enabled.');
                        submitObs.disconnect();

                        submitButton.click();
                        log('🚀 Prompt submitted!');
                    }
                });

                submitObserver.observe(document.body, {
                    childList: true,
                    subtree: true,
                    attributes: true // Also watch for attribute changes like 'disabled'
                });
            }
        });

        inputObserver.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    // --- Main Execution (after document is ready) ---
    // Wait for the DOM to be fully loaded before trying to interact with elements
    document.addEventListener('DOMContentLoaded', () => {
        log('DOMContentLoaded fired. Executing main logic.');
        if (window.geminiScript.currentPrompt) {
            prefillThenSubmit(window.geminiScript.currentPrompt);
        } else {
            log("No prompt stored from early execution. No prefill action needed.");
        }
    });

})();