Discord Server Search

Search and navigate to a Discord server by name

目前为 2024-10-10 提交的版本。查看 最新版本

// ==UserScript==
// @name         Discord Server Search
// @namespace    Made by @hakav
// @author       @hakav
// @version      2.0
// @description  Search and navigate to a Discord server by name
// @match        https://discord.com/*
// @grant        none
// @icon         https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrWjmWEq2JeU0yKb2ArlyAAJA4QQLkhbuihw&s
// @license      Copyright @hakav
// ==/UserScript==

(function() {
    'use strict';

    // ======= SETTINGS =======
    const defaultPosition = { bottom: '20px', right: '20px' };  // Default position if no saved data
    const popupPositionOffset = '80px'; // Customize popup offset from the bottom
    const localStorageKey = 'searchIconPosition'; // Key for storing position in localStorage
    // ========================

    // Create the search icon
    const searchIcon = document.createElement('div');
    searchIcon.innerHTML = '🔍';
    searchIcon.style.position = 'fixed';
    searchIcon.style.backgroundColor = 'rgba(255, 255, 255, 0.3)';
    searchIcon.style.color = 'black';
    searchIcon.style.border = '2px solid rgba(0, 0, 0, 0.3)';
    searchIcon.style.borderRadius = '50%';
    searchIcon.style.padding = '10px';
    searchIcon.style.cursor = 'pointer';
    searchIcon.style.zIndex = '1000';
    searchIcon.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.2)';
    searchIcon.style.transition = 'background-color 0.3s ease, box-shadow 0.3s ease, transform 0.2s ease';
    document.body.appendChild(searchIcon);

    // Load the saved position from localStorage or use default
    const savedPosition = JSON.parse(localStorage.getItem(localStorageKey));
    if (savedPosition) {
        searchIcon.style.bottom = savedPosition.bottom;
        searchIcon.style.right = savedPosition.right;
    } else {
        searchIcon.style.bottom = defaultPosition.bottom;
        searchIcon.style.right = defaultPosition.right;
    }

    // Hover effects with scaling
    searchIcon.onmouseenter = function() {
        searchIcon.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
        searchIcon.style.boxShadow = '0 0 15px rgba(0, 0, 0, 0.5)';
        searchIcon.style.transform = 'scale(1.1)';
    };

    searchIcon.onmouseleave = function() {
        searchIcon.style.backgroundColor = 'rgba(255, 255, 255, 0.3)';
        searchIcon.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.2)';
        searchIcon.style.transform = 'scale(1)';
    };

    // Draggable functionality
    let isDragging = false;
    let dragOffsetX = 0;
    let dragOffsetY = 0;

    searchIcon.addEventListener('mousedown', function(event) {
        isDragging = true;
        dragOffsetX = event.clientX - searchIcon.getBoundingClientRect().right;
        dragOffsetY = event.clientY - searchIcon.getBoundingClientRect().bottom;
        event.preventDefault();
    });

    document.addEventListener('mousemove', function(event) {
        if (isDragging) {
            // Calculate the new position
            const right = window.innerWidth - event.clientX - dragOffsetX + 'px';
            const bottom = window.innerHeight - event.clientY - dragOffsetY + 'px';

            // Move the search icon
            searchIcon.style.right = right;
            searchIcon.style.bottom = bottom;

            // Save the position in localStorage
            localStorage.setItem(localStorageKey, JSON.stringify({ right: right, bottom: bottom }));
        }
    });

    document.addEventListener('mouseup', function() {
        if (isDragging) {
            isDragging = false;
        }
    });

    // Create the search input popup
    const searchPopup = document.createElement('div');
    searchPopup.style.position = 'fixed';
    searchPopup.style.bottom = popupPositionOffset;
    searchPopup.style.right = '-250px'; // Slide in from outside the screen
    searchPopup.style.backgroundColor = 'white';
    searchPopup.style.padding = '15px';
    searchPopup.style.borderRadius = '5px';
    searchPopup.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
    searchPopup.style.display = 'none';
    searchPopup.style.zIndex = '1001';
    searchPopup.style.opacity = '0';
    searchPopup.style.transition = 'opacity 0.3s ease, transform 0.3s ease, right 0.5s ease';

    const searchInput = document.createElement('input');
    searchInput.placeholder = 'Enter server name...';
    searchInput.style.width = '200px';
    searchInput.style.border = '2px solid #ccc';
    searchInput.style.padding = '5px';
    searchInput.style.transition = 'border-color 0.3s ease';
    searchPopup.appendChild(searchInput);

    searchInput.onfocus = function() {
        searchInput.style.borderColor = '#4A90E2';
    };

    searchInput.onblur = function() {
        searchInput.style.borderColor = '#ccc';
    };

    const searchButton = document.createElement('button');
    searchButton.innerText = 'Search';
    searchButton.style.marginLeft = '10px';
    searchButton.style.padding = '5px 10px';
    searchButton.style.backgroundColor = '#4A90E2';
    searchButton.style.color = 'white';
    searchButton.style.border = 'none';
    searchButton.style.borderRadius = '3px';
    searchButton.style.cursor = 'pointer';
    searchButton.style.transition = 'transform 0.2s ease, background-color 0.3s ease';

    searchButton.onmouseenter = function() {
        searchButton.style.backgroundColor = '#357ABD';
        searchButton.style.transform = 'scale(1.05)';
    };

    searchButton.onmouseleave = function() {
        searchButton.style.backgroundColor = '#4A90E2';
        searchButton.style.transform = 'scale(1)';
    };

    // Search function
    const searchServer = () => {
        const serverName = searchInput.value.trim();
        if (serverName) {
            const servers = Array.from(document.querySelectorAll('[data-list-id="guildsnav"] [aria-label]'));
            const matchedServer = servers.find(server =>
                server.getAttribute('aria-label').toLowerCase().includes(serverName.toLowerCase())
            );

            if (matchedServer) {
                matchedServer.click();
            } else {
                showErrorNotification('Server not found!');
            }
        }
    };

    searchButton.onclick = searchServer;
    searchInput.addEventListener('keydown', function (e) {
        if (e.key === 'Enter') {
            searchServer();
        }
    });

    searchPopup.appendChild(searchButton);
    document.body.appendChild(searchPopup);

    // Show/hide popup animation
    const showPopup = () => {
        searchPopup.style.display = 'block';
        setTimeout(() => {
            searchPopup.style.opacity = '1';
            searchPopup.style.right = '20px';
        }, 10);
    };

    const hidePopup = () => {
        searchPopup.style.opacity = '0';
        searchPopup.style.right = '-250px';
        setTimeout(() => {
            searchPopup.style.display = 'none';
        }, 300);
    };

    searchIcon.onclick = function() {
        if (searchPopup.style.display === 'none' || searchPopup.style.opacity === '0') {
            showPopup();
            searchInput.focus();
        } else {
            hidePopup();
        }
    };

    // Custom notification system
    const showErrorNotification = (message) => {
        const notification = document.createElement('div');
        notification.innerText = message;
        notification.style.position = 'fixed';
        notification.style.bottom = '100px';
        notification.style.right = '20px';
        notification.style.backgroundColor = '#ff6666';
        notification.style.color = 'white';
        notification.style.padding = '10px';
        notification.style.borderRadius = '5px';
        notification.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
        notification.style.zIndex = '1002';
        notification.style.opacity = '0';
        notification.style.transition = 'opacity 0.5s ease';
        document.body.appendChild(notification);

        // Show notification with fade-in
        setTimeout(() => {
            notification.style.opacity = '1';
        }, 10);

        // Hide notification after 3 seconds
        setTimeout(() => {
            notification.style.opacity = '0';
            setTimeout(() => {
                notification.remove();
            }, 500);
        }, 3000);
    };

    // Hide popup when clicking outside with animation
    window.onclick = function(event) {
        if (!searchIcon.contains(event.target) && !searchPopup.contains(event.target)) {
            hidePopup();
        }
    };

})();