// ==UserScript== // @name MZ - GB Message Sender // @namespace douglaskampl // @version 1.2 // @description Sends a guestbook message to multiple users // @author Douglas // @match https://www.managerzone.com/?p=guestbook // @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com // @grant GM_addStyle // @run-at document-idle // @license MIT // @downloadURL https://update.greasyfork.cloud/scripts/528077/MZ%20-%20GB%20Message%20Sender.user.js // @updateURL https://update.greasyfork.cloud/scripts/528077/MZ%20-%20GB%20Message%20Sender.meta.js // ==/UserScript== (function () { 'use strict'; GM_addStyle(` .custom-button { margin-left: 10px; background-color: #74ACDF; color: white; position: relative; overflow: hidden; transition: all 0.3s ease; } .custom-button:hover { background-color: #6B9FD0; transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } .custom-button:after { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: 0.5s; } .custom-button:hover:after { left: 100%; } .modal { display: none; position: fixed; z-index: 9999; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0, 0, 0, 0.7); opacity: 0; transition: opacity 0.3s ease; } .modal.show { opacity: 1; } .modal-content { background-color: #2E2E2E; color: #F5F5F5; margin: 15% auto; padding: 25px; border: 2px solid #F0F0F0; width: 80%; max-width: 600px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); transform: translateY(-50px); opacity: 0; transition: all 0.4s ease; } .modal.show .modal-content { transform: translateY(0); opacity: 1; } .modal-header { border-bottom: 3px solid #74ACDF; padding-bottom: 15px; margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center; } .modal-title { color: #F5F5F5; margin: 0; font-size: 22px; text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3); } .close { color: #F0F0F0; float: right; font-size: 28px; font-weight: bold; cursor: pointer; transition: color 0.2s ease; } .close:hover, .close:focus { color: #74ACDF; text-decoration: none; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 8px; font-weight: bold; color: #74ACDF; } .form-group input, .form-group textarea { width: 100%; padding: 12px; background-color: #3D3D3D; color: #F5F5F5; border: 1px solid #555; border-radius: 6px; box-sizing: border-box; transition: all 0.3s ease; } .form-group input:focus, .form-group textarea:focus { outline: none; border-color: #74ACDF; box-shadow: 0 0 8px rgba(116, 172, 223, 0.5); } .form-group textarea { height: 120px; resize: vertical; } .send-button { background: linear-gradient(to right, #74ACDF, #85C2F5); color: white; padding: 12px 20px; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; letter-spacing: 0.5px; transition: all 0.3s ease; position: relative; overflow: hidden; } .send-button:hover { background: linear-gradient(to right, #85C2F5, #74ACDF); transform: translateY(-2px); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); } .send-button:after { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent); transition: 0.5s; } .send-button:hover:after { left: 100%; } .send-button:disabled { background: #555; cursor: not-allowed; transform: none; box-shadow: none; } .status-area { margin-top: 20px; padding: 15px; border: 1px solid #444; border-radius: 6px; max-height: 180px; overflow-y: auto; display: none; background-color: #222; transition: all 0.3s ease; } .status-area.show { display: block; animation: fadeIn 0.5s ease forwards; } .status-message { margin: 8px 0; padding: 5px 10px; border-radius: 4px; transition: opacity 0.3s ease; animation: slideIn 0.3s ease forwards; } @keyframes slideIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .status-success { color: #7CFC00; background-color: rgba(124, 252, 0, 0.1); border-left: 3px solid #7CFC00; } .status-error { color: #FF6B6B; background-color: rgba(255, 107, 107, 0.1); border-left: 3px solid #FF6B6B; } .status-info { color: #74ACDF; background-color: rgba(116, 172, 223, 0.1); border-left: 3px solid #74ACDF; } .footer { margin-top: 20px; padding-top: 15px; border-top: 1px solid #444; text-align: center; color: #AAA; font-size: 12px; } .footer img { height: 20px; vertical-align: middle; margin-left: 5px; } .progress-bar { height: 4px; width: 0%; background: linear-gradient(to right, #74ACDF, #FCBF49); position: absolute; top: 0; left: 0; transition: width 0.5s ease; } .toggle-container { display: flex; justify-content: center; margin-bottom: 20px; background-color: #222; border-radius: 6px; padding: 4px; width: 100%; } .toggle-option { flex: 1; padding: 10px; text-align: center; cursor: pointer; border-radius: 4px; transition: all 0.3s ease; color: #AAA; } .toggle-option.active { background-color: #74ACDF; color: white; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } .toggle-option:not(.active):hover { background-color: #333; color: #DDD; } .input-container { display: none; } .input-container.active { display: block; animation: fadeIn 0.3s ease; } `); window.addEventListener('load', function() { const postButton = document.getElementById('formpostbutton'); if (!postButton) return; const sendMessagesButton = document.createElement('div'); sendMessagesButton.style.display = 'inline-block'; sendMessagesButton.innerHTML = ` Send Messages  `; postButton.parentNode.insertBefore(sendMessagesButton, postButton.nextSibling); const modal = document.createElement('div'); modal.className = 'modal'; modal.id = 'messageModal'; modal.innerHTML = ` `; document.body.appendChild(modal); const toggleOptions = document.querySelectorAll('.toggle-option'); toggleOptions.forEach(option => { option.addEventListener('click', function() { toggleOptions.forEach(opt => opt.classList.remove('active')); this.classList.add('active'); const targetId = this.getAttribute('data-target'); document.querySelectorAll('.input-container').forEach(container => { container.classList.remove('active'); }); document.getElementById(targetId).classList.add('active'); }); }); document.getElementById('sendMessagesBtn').addEventListener('click', function(e) { e.preventDefault(); const modalEl = document.getElementById('messageModal'); modalEl.style.display = 'block'; setTimeout(() => { modalEl.classList.add('show'); }, 10); }); document.querySelector('.close').addEventListener('click', function() { const modalEl = document.getElementById('messageModal'); modalEl.classList.remove('show'); setTimeout(() => { modalEl.style.display = 'none'; }, 300); }); window.addEventListener('click', function(event) { const modalEl = document.getElementById('messageModal'); if (event.target === modalEl) { modalEl.classList.remove('show'); setTimeout(() => { modalEl.style.display = 'none'; }, 300); } }); document.getElementById('sendButton').addEventListener('click', async function() { const message = document.getElementById('messageText').value.trim(); if (!message) { alert('Please enter a message'); return; } const statusArea = document.getElementById('statusArea'); const statusMessages = document.getElementById('statusMessages'); const progressBar = document.getElementById('progressBar'); statusArea.classList.add('show'); statusMessages.innerHTML = ''; updateProgressBar(progressBar, 0); const activeMode = document.querySelector('.toggle-option.active').getAttribute('data-target'); if (activeMode === 'users-input') { const usersText = document.getElementById('usersInput').value.trim(); if (!usersText) { alert('Please enter at least one username'); return; } const users = usersText.split(',').map(u => u.trim()).filter(u => u); if (users.length === 0) { alert('Please enter valid usernames'); return; } const totalUsers = users.length; let processedUsers = 0; addStatus('Starting to send messages...', 'status-info'); for (const username of users) { try { const userId = await getUserId(username); if (!userId) { addStatus(`Could not find user ID for ${username}`, 'status-error'); continue; } addStatus(`Found user ID: ${userId}`, 'status-info'); await sendMessage(userId, message); addStatus(`Message sent to ${username}`, 'status-success'); processedUsers++; updateProgressBar(progressBar, (processedUsers / totalUsers) * 100); if (processedUsers < totalUsers) { addStatus(`Waiting 5 seconds before sending the next message...`, 'status-info'); await new Promise(resolve => setTimeout(resolve, 5000)); } } catch (error) { addStatus(`Error: ${error.message}`, 'status-error'); } } updateProgressBar(progressBar, 100); addStatus('All messages have been sent!', 'status-success'); } else { const federationId = document.getElementById('federationId').value.trim(); if (!federationId) { alert('Please enter a federation ID'); return; } if (!/^\d+$/.test(federationId)) { alert('Federation ID must be a number'); return; } addStatus(`Starting to fetch federation members for federation ID: ${federationId}...`, 'status-info'); try { const users = await getFederationMembers(federationId); if (users.length === 0) { addStatus('No users found in federation', 'status-error'); return; } addStatus(`Found ${users.length} federation members`, 'status-info'); const totalUsers = users.length; let processedUsers = 0; addStatus('Starting to send messages...', 'status-info'); for (const username of users) { try { const userId = await getUserId(username); if (!userId) { addStatus(`Could not find user ID for ${username}`, 'status-error'); continue; } addStatus(`Found user ID: ${userId}`, 'status-info'); await sendMessage(userId, message); addStatus(`Message sent to ${username}`, 'status-success'); processedUsers++; updateProgressBar(progressBar, (processedUsers / totalUsers) * 100); if (processedUsers < totalUsers) { addStatus(`Waiting 5 seconds before sending the next message...`, 'status-info'); await new Promise(resolve => setTimeout(resolve, 5000)); } } catch (error) { addStatus(`Error: ${error.message}`, 'status-error'); } } updateProgressBar(progressBar, 100); addStatus('All messages have been sent!', 'status-success'); } catch (error) { addStatus(`Error fetching federation members: ${error.message}`, 'status-error'); } } }); async function getFederationMembers(federationId) { const users = []; let offset = 0; let hasMoreMembers = true; while (hasMoreMembers) { addStatus(`Fetching federation members (offset: ${offset})...`, 'status-info'); try { const url = `https://www.managerzone.com/ajax.php?p=federations&sub=federation_members&fid=${federationId}&offset=${offset}&sport=soccer`; const response = await fetch(url); const data = await response.json(); if (!data || !data[0] || !data[0].length) { hasMoreMembers = false; break; } const newUsers = extractUsernames(data[0]); if (newUsers.length === 0) { hasMoreMembers = false; break; } users.push(...newUsers); addStatus(`Found ${newUsers.length} members at offset ${offset}`, 'status-info'); hasMoreMembers = data[1] && data[1].includes(`offset=${offset + 10}`); offset += 10; await new Promise(resolve => setTimeout(resolve, 1000)); } catch (error) { addStatus(`Error fetching members at offset ${offset}: ${error.message}`, 'status-error'); hasMoreMembers = false; } } return [...new Set(users)]; } function extractUsernames(html) { const regex = /\"(?:Epic|Legendary|Elite|Gold|Senior|\"|\s)*\s*([a-zA-Z0-9_-]+)<\/a>/g; const matches = []; let match; while ((match = regex.exec(html)) !== null) { if (match[1] && match[1].trim()) { matches.push(match[1].trim()); } } const simpleRegex = /([a-zA-Z0-9_-]+)<\/a><\/span><\/td>/g; while ((match = simpleRegex.exec(html)) !== null) { if (match[1] && match[1].trim() && !matches.includes(match[1].trim())) { matches.push(match[1].trim()); } } return matches; } function addStatus(message, className) { const statusMessages = document.getElementById('statusMessages'); const messageElement = document.createElement('div'); messageElement.className = `status-message ${className}`; messageElement.textContent = message; statusMessages.appendChild(messageElement); statusMessages.scrollTop = statusMessages.scrollHeight; } function updateProgressBar(progressBar, percentage) { progressBar.style.width = `${percentage}%`; } async function getUserId(username) { const response = await fetch(`https://www.managerzone.com/xml/manager_data.php?sport_id=1&username=${encodeURIComponent(username)}`); const text = await response.text(); const parser = new DOMParser(); const xmlDoc = parser.parseFromString(text, "text/xml"); const userDataElement = xmlDoc.querySelector('UserData'); if (userDataElement && userDataElement.hasAttribute('userId')) { return userDataElement.getAttribute('userId'); } return null; } async function sendMessage(userId, message) { await fetch(`https://www.managerzone.com/ajax.php?p=messageBoard&sub=write&template=1&ident_id=${userId}&sport=soccer`, { method: 'POST', body: new URLSearchParams({ 'msg': message }), headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest' } }); return true; } }); })();