AI Navigation Bar

Automatically clicks the "Try GPT-5" button and adds navigation buttons to AI chat services

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         AI Navigation Bar
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Automatically clicks the "Try GPT-5" button and adds navigation buttons to AI chat services
// @author       You
// @match        https://m365.cloud.microsoft/*
// @match        https://claude.ai/*
// @match        https://chatgpt.com/*
// @match        https://chat.deepseek.com/*
// @match        https://gemini.google.com/*
// @match        https://www.perplexity.ai/*
// @grant        GM_xmlhttpRequest
// @connect      favicon.yandex.net
// @homepage     https://greasyfork.org/en/scripts/550204-ai-navigation-bar
// ==/UserScript==
(function() {
    'use strict';

    // Navigation buttons configuration
    const navButtons = [
        { name: 'M365', url: 'https://m365.cloud.microsoft' },
        { name: 'Gemini', url: 'https://gemini.google.com' },
        { name: 'Anthropic', url: 'https://claude.ai' },
        { name: 'ChatGPT', url: 'https://chatgpt.com' },
        { name: 'DeepSeek', url: 'https://chat.deepseek.com' },
        { name: 'Perplexity', url: 'https://www.perplexity.ai' }
    ];

    // Cache for favicon data URLs
    const faviconCache = {};

    // Extract domain from URL
    function getDomain(url) {
        try {
            const hostname = new URL(url).hostname;
            return hostname;
        } catch (e) {
            console.error('Invalid URL:', url);
            return '';
        }
    }

    // Check if URL matches current domain
    function isSameDomain(url) {
        try {
            const targetDomain = new URL(url).hostname;
            const currentDomain = window.location.hostname;
            return targetDomain === currentDomain;
        } catch (e) {
            return false;
        }
    }

    // Fetch favicon using GM_xmlhttpRequest and convert to data URL
    function getFaviconDataUrl(domain) {
        return new Promise((resolve) => {
            if (faviconCache[domain]) {
                resolve(faviconCache[domain]);
                return;
            }

            const faviconUrl = `https://favicon.yandex.net/favicon/v2/${domain}?size=32`;

            GM_xmlhttpRequest({
                method: 'GET',
                url: faviconUrl,
                responseType: 'blob',
                onload: function(response) {
                    const reader = new FileReader();
                    reader.onloadend = function() {
                        faviconCache[domain] = reader.result;
                        console.log(`✓ Favicon loaded for ${domain}`);
                        resolve(reader.result);
                    };
                    reader.readAsDataURL(response.response);
                },
                onerror: function(error) {
                    console.error(`✗ Favicon failed for ${domain}:`, error);
                    resolve(null);
                }
            });
        });
    }

    // Create navigation bar
    async function createNavigationBar() {
        // Check if nav bar already exists
        if (document.getElementById('ai-nav-bar')) return;

        const navBar = document.createElement('div');
        navBar.id = 'ai-nav-bar';
        navBar.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            background: transparent;
            padding: 6px;
            display: flex;
            gap: 6px;
            justify-content: center;
            align-items: center;
            z-index: 999999;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            pointer-events: none;
        `;

        for (const btn of navButtons) {
            const button = document.createElement('button');
            const isCurrentSite = isSameDomain(btn.url);

            button.style.cssText = `
                background: rgba(45, 45, 45, 0.9);
                color: #e0e0e0;
                border: 1px solid #404040;
                padding: 5px 12px;
                border-radius: 20px;
                cursor: pointer;
                font-weight: 600;
                font-size: 12px;
                transition: all 0.3s ease;
                box-shadow: 0 2px 4px rgba(0,0,0,0.3);
                backdrop-filter: blur(10px);
                pointer-events: auto;
                display: flex;
                align-items: center;
                gap: 6px;
                ${isCurrentSite ? 'opacity: 0.3; border-color: #606060;' : ''}
            `;

            // Extract domain and fetch favicon as data URL
            const domain = getDomain(btn.url);
            if (domain) {
                const faviconDataUrl = await getFaviconDataUrl(domain);

                if (faviconDataUrl) {
                    const favicon = document.createElement('img');
                    favicon.src = faviconDataUrl;
                    favicon.alt = btn.name;
                    favicon.style.cssText = `
                        width: 16px;
                        height: 16px;
                        object-fit: contain;
                        flex-shrink: 0;
                    `;

                    button.appendChild(favicon);
                }
            }

            // Add text
            const text = document.createElement('span');
            text.textContent = btn.name;
            button.appendChild(text);

            // Hover effects
            button.onmouseenter = () => {
                button.style.background = 'rgba(61, 61, 61, 0.95)';
                button.style.borderColor = '#505050';
                button.style.transform = 'translateY(-1px)';
                button.style.boxShadow = '0 3px 6px rgba(0,0,0,0.4)';
            };
            button.onmouseleave = () => {
                button.style.background = 'rgba(45, 45, 45, 0.9)';
                button.style.borderColor = isCurrentSite ? '#606060' : '#404040';
                button.style.transform = 'translateY(0)';
                button.style.boxShadow = '0 2px 4px rgba(0,0,0,0.3)';
            };

            button.onclick = () => {
                if (isSameDomain(btn.url)) {
                    // Same domain: reload in current tab
                    window.location.href = btn.url;
                } else {
                    // Different domain: open in new tab
                    window.open(btn.url, '_blank');
                }
            };

            navBar.appendChild(button);
        }

        // Add to page
        document.body.insertBefore(navBar, document.body.firstChild);

        console.log('Navigation bar created successfully!');
    }

    // Original auto-click functionality
    let attempts = 0;
    const maxAttempts = 20;
    const delay = 500;
    const editorDelay = 1000;
    let buttonClicked = false;
    let editorClicked = false;

    function findAndClickButton() {
        if (buttonClicked) return;
        attempts++;
        console.log(`Attempt ${attempts}: Looking for GPT-5 button...`);
        const buttons = document.querySelectorAll('button[aria-pressed="false"]');
        let found = false;
        buttons.forEach(button => {
            if (button.textContent.includes("Try GPT-5") && !buttonClicked) {
                console.log("Found GPT-5 button, clicking...");
                button.click();
                found = true;
                buttonClicked = true;
                setTimeout(() => {
                    findAndClickEditor();
                }, editorDelay);
            }
        });
        if (found) {
            console.log("GPT-5 button clicked successfully!");
            observer.disconnect();
            return;
        }
        if (attempts < maxAttempts && !buttonClicked) {
            setTimeout(findAndClickButton, delay);
        } else if (!buttonClicked) {
            console.log("Max attempts reached, GPT-5 button not found");
        }
    }

    function findAndClickEditor() {
        if (editorClicked) return;
        console.log("Looking for chat editor element...");
        const editorElement = document.getElementById('m365-chat-editor-target-element');
        if (editorElement) {
            console.log("Found chat editor element, clicking...");
            editorElement.click();
            editorClicked = true;
            console.log("Chat editor element clicked successfully!");
        } else {
            console.log("Chat editor element not found yet");
        }
    }

    // Initialize navigation bar with delay
    function initNavigationBar() {
        // Wait for page to fully load and settle
        setTimeout(() => {
            createNavigationBar();

            // Re-check periodically in case it gets hidden or removed
            // Run checks every 2 seconds for the first 1 minute
            let checkCount = 0;
            const maxChecks = 30; // 30 checks × 2 seconds = 1 minute

            const intervalId = setInterval(() => {
                checkCount++;

                if (!document.getElementById('ai-nav-bar')) {
                    console.log('Navigation bar was removed, recreating...');
                    createNavigationBar();
                }

                // Stop checking after 2 minutes
                if (checkCount >= maxChecks) {
                    clearInterval(intervalId);
                    console.log('Navigation bar monitoring stopped after 1 minute');
                }
            }, 2000);
        }, 300); // Wait 0.3 seconds after page load
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initNavigationBar);
    } else if (document.readyState === 'interactive') {
        initNavigationBar();
    } else {
        // Page already fully loaded
        initNavigationBar();
    }

    // Original auto-click initialization (M365 ONLY)
    const isM365 = window.location.hostname.includes('m365.cloud.microsoft');

    if (isM365) {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => {
                setTimeout(findAndClickButton, 1000);
            });
        } else {
            setTimeout(findAndClickButton, 1000);
        }

        window.addEventListener('load', () => {
            setTimeout(findAndClickButton, 2000);
        });

        const observer = new MutationObserver((mutations) => {
            if (buttonClicked) return;
            mutations.forEach((mutation) => {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    mutation.addedNodes.forEach((node) => {
                        if (node.nodeType === 1 && (node.tagName === 'BUTTON' || node.querySelector('button'))) {
                            setTimeout(findAndClickButton, 500);
                        }
                    });
                }
            });
        });

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

        setTimeout(() => {
            observer.disconnect();
            console.log("MutationObserver disconnected");
        }, 30000);
    }
})();