// ==UserScript==
// @name Discord Server Search
// @namespace Made by @hakav
// @version 3.0.1
// @description Search and navigate to a Discord server by name with real-time suggestions
// @match https://discord.com/*
// @grant none
// @icon https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrWjmWEq2JeU0yKb2ArlyAAJA4QQLkhbuihw&s
// @license Copyright @hakav
// ==/UserScript==
(function() {
'use strict';
const recentSearches = [];
let highlightedIndex = -1;
const createSearchIcon = () => {
const searchIcon = document.createElement('div');
searchIcon.innerHTML = '🔍';
searchIcon.style.position = 'fixed';
searchIcon.style.bottom = '20px';
searchIcon.style.right = '20px';
searchIcon.style.backgroundColor = 'rgba(128, 0, 128, 0.3)'; // Purple background
searchIcon.style.color = 'white';
searchIcon.style.border = '2px solid rgba(255, 255, 255, 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);
searchIcon.onmouseenter = () => {
searchIcon.style.backgroundColor = 'rgba(128, 0, 128, 0.6)';
searchIcon.style.boxShadow = '0 0 15px rgba(0, 0, 0, 0.5)';
searchIcon.style.transform = 'scale(1.1)';
};
searchIcon.onmouseleave = () => {
searchIcon.style.backgroundColor = 'rgba(128, 0, 128, 0.3)';
searchIcon.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.2)';
searchIcon.style.transform = 'scale(1)';
};
const searchPopup = document.createElement('div');
searchPopup.style.position = 'fixed';
searchPopup.style.bottom = '80px';
searchPopup.style.right = '-220px'; // Start hidden, reduced width
searchPopup.style.backgroundColor = 'black'; // Black background
searchPopup.style.padding = '10px'; // Reduced padding
searchPopup.style.borderRadius = '15px';
searchPopup.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.3)';
searchPopup.style.zIndex = '1001';
searchPopup.style.display = 'none'; // Initially hidden
searchPopup.style.opacity = '0';
searchPopup.style.transition = 'opacity 0.3s ease, right 0.5s ease';
document.body.appendChild(searchPopup);
const searchInput = document.createElement('input');
searchInput.placeholder = 'Server name...'; // Shortened placeholder
searchInput.style.width = '100%'; // Full width
searchInput.style.border = '2px solid purple'; // Purple border
searchInput.style.borderRadius = '5px'; // Less rounded corners
searchInput.style.padding = '6px'; // Reduced padding
searchInput.style.backgroundColor = 'rgba(128, 0, 128, 0.1)'; // Light purple background
searchInput.style.color = 'white'; // White text
searchInput.style.fontSize = '14px'; // Smaller font size
searchPopup.appendChild(searchInput);
const searchButton = document.createElement('button');
searchButton.innerText = 'Search';
searchButton.style.marginLeft = '5px'; // Reduced margin
searchButton.style.borderRadius = '5px'; // Less rounded corners
searchButton.style.padding = '6px 10px'; // Reduced padding
searchButton.style.backgroundColor = 'purple'; // Purple background
searchButton.style.color = 'white';
searchButton.style.border = 'none';
searchButton.style.cursor = 'pointer';
searchButton.style.fontSize = '14px'; // Smaller font size
searchPopup.appendChild(searchButton);
const clearButton = document.createElement('button');
clearButton.innerText = 'Clear';
clearButton.style.marginLeft = '5px';
clearButton.style.borderRadius = '5px';
clearButton.style.padding = '6px 10px';
clearButton.style.backgroundColor = 'red'; // Red background for clear
clearButton.style.color = 'white';
clearButton.style.border = 'none';
clearButton.style.cursor = 'pointer';
clearButton.style.fontSize = '14px';
searchPopup.appendChild(clearButton);
const loadingIndicator = document.createElement('div');
loadingIndicator.style.display = 'none';
loadingIndicator.innerText = 'Loading...';
loadingIndicator.style.color = 'white';
loadingIndicator.style.fontSize = '12px';
searchPopup.appendChild(loadingIndicator);
const suggestionBox = document.createElement('div');
suggestionBox.style.position = 'absolute';
suggestionBox.style.top = '40px'; // Adjusted for better positioning
suggestionBox.style.left = '0';
suggestionBox.style.backgroundColor = 'black'; // Black background
suggestionBox.style.border = '1px solid purple'; // Purple border
suggestionBox.style.width = '100%'; // Full width
suggestionBox.style.zIndex = '1002';
suggestionBox.style.display = 'none';
suggestionBox.style.maxHeight = '120px'; // Reduced max height
suggestionBox.style.overflowY = 'auto'; // Scroll for longer lists
suggestionBox.style.borderRadius = '5px'; // Less rounded corners
suggestionBox.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)'; // Soft shadow
searchPopup.appendChild(suggestionBox);
const showPopup = () => {
searchPopup.style.display = 'block';
setTimeout(() => {
searchPopup.style.opacity = '1';
searchPopup.style.right = '20px'; // Slide it into view
}, 10);
};
const hidePopup = () => {
searchPopup.style.opacity = '0';
searchPopup.style.right = '-220px'; // Slide it back out
setTimeout(() => {
searchPopup.style.display = 'none';
suggestionBox.style.display = 'none'; // Hide suggestion box
}, 300);
};
searchIcon.onclick = () => {
if (searchPopup.style.display === 'none' || searchPopup.style.opacity === '0') {
showPopup();
searchInput.focus();
} else {
hidePopup();
}
};
window.onclick = (event) => {
if (!searchIcon.contains(event.target) && !searchPopup.contains(event.target)) {
hidePopup();
}
};
const debounce = (func, delay) => {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
};
const searchServers = debounce(() => {
const query = searchInput.value.trim().toLowerCase();
suggestionBox.innerHTML = ''; // Clear previous suggestions
if (query) {
loadingIndicator.style.display = 'block'; // Show loading
const servers = Array.from(document.querySelectorAll('[data-list-id="guildsnav"] [aria-label]'));
const matchedServers = servers.filter(server =>
server.getAttribute('aria-label').toLowerCase().includes(query)
);
if (matchedServers.length > 0) {
matchedServers.forEach(server => {
const suggestionItem = document.createElement('div');
suggestionItem.textContent = server.getAttribute('aria-label');
suggestionItem.style.padding = '5px';
suggestionItem.style.cursor = 'pointer';
suggestionItem.style.color = 'white'; // White text for suggestions
suggestionItem.style.fontSize = '14px'; // Smaller font size
suggestionItem.onclick = () => {
searchInput.value = server.getAttribute('aria-label');
suggestionBox.style.display = 'none';
server.click(); // Click the server to open it
};
suggestionItem.onmouseenter = () => suggestionItem.style.backgroundColor = 'rgba(128, 0, 128, 0.3)'; // Highlight on hover
suggestionItem.onmouseleave = () => suggestionItem.style.backgroundColor = 'black'; // Reset background
suggestionBox.appendChild(suggestionItem);
});
suggestionBox.style.display = 'block';
} else {
suggestionBox.innerHTML = '<div style="color: white; padding: 5px;">No servers found.</div>';
suggestionBox.style.display = 'block';
}
loadingIndicator.style.display = 'none'; // Hide loading
} else {
suggestionBox.style.display = 'none';
}
}, 300); // Debounce delay of 300ms
searchInput.addEventListener('input', searchServers);
searchButton.onclick = () => {
const serverName = searchInput.value.trim();
if (serverName) {
recentSearches.push(serverName);
const servers = Array.from(document.querySelectorAll('[data-list-id="guildsnav"] [aria-label]'));
const matchedServer = servers.find(server =>
server.getAttribute('aria-label').toLowerCase() === serverName.toLowerCase()
);
if (matchedServer) {
matchedServer.click(); // Click the server to navigate
} else {
console.log('Server not found!');
}
}
};
clearButton.onclick = () => {
searchInput.value = '';
suggestionBox.style.display = 'none';
};
searchInput.addEventListener('keydown', (e) => {
const suggestionItems = Array.from(suggestionBox.children);
if (e.key === 'ArrowDown') {
highlightedIndex = Math.min(highlightedIndex + 1, suggestionItems.length - 1);
} else if (e.key === 'ArrowUp') {
highlightedIndex = Math.max(highlightedIndex - 1, 0);
}
suggestionItems.forEach((item, index) => {
item.style.backgroundColor = index === highlightedIndex ? 'rgba(128, 0, 128, 0.3)' : 'black';
});
if (e.key === 'Enter' && highlightedIndex >= 0) {
suggestionItems[highlightedIndex].click();
}
});
};
// Wait for the window to fully load before creating the icon
window.onload = createSearchIcon;
})();