// ==UserScript==
// @name MZ - Youth Exchange (/16)
// @namespace http://tampermonkey.net/
// @version 2.8
// @description Sends new youth player data to Firebase when exchanging (accepting or rejecting) youth players
// @author Douglas Vieira
// @match https://www.managerzone.com/?p=youth_academy*
// @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com
// @grant GM_xmlhttpRequest
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11
// @connect www.managerzone.com
// @connect u18mz.vercel.app
// @connect youth-exchange-worker.douglasdotv.workers.dev
// @license MIT
// ==/UserScript==
(function () {
'use strict';
console.log("| MZ_Track_Youth_Exchange_Players is running and will save youth exchange data to db. |");
const usernameCountryMap = {
douglaskampl: 'BR', /* Put your username and country/code (for example, 'Brazil' or 'BR') here */
};
const youthExchangePlayerAge = 16;
let username = 'Unknown';
let nationality = 'Unknown';
let storedPlayerData = null;
let dataReady = false;
let lastPlayerID = null;
const currentSeason = document.querySelector('#header-stats-wrapper h5.linked').textContent.match(/(\d+)/)[1];
const showToast = (color, message) => {
Swal.fire({
toast: true,
position: 'bottom-right',
iconColor: color,
icon: color === 'blue' ? 'info' : color === 'green' ? 'success' : color === 'orange' ? 'warning' : 'error',
title: message,
showConfirmButton: false,
timer: 3000,
background: color,
color: 'white'
});
};
const fetchNationality = async (username) => {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: `http://www.managerzone.com/xml/manager_data.php?sport_id=1&username=${username}`,
onload: function (response) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(response.responseText, "text/xml");
const countryShortname = xmlDoc.querySelector('UserData') ? xmlDoc.querySelector('UserData').getAttribute('countryShortname') : 'Not found';
resolve(countryShortname);
},
onerror: function () {
console.log("Error fetching nationality.");
reject(new Error("Failed to fetch nationality"));
}
});
});
};
const getCountryFullName = async (shortName) => {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: 'https://u18mz.vercel.app/json/countries.json',
onload: function (response) {
const countries = JSON.parse(response.responseText);
const country = countries.find(c => c.code === shortName);
resolve(country ? country.name : shortName);
},
onerror: function () {
console.log("Error fetching full country name.");
reject(new Error("Failed to fetch country name"));
}
});
});
};
const sendDataToFirebase = (youthExchangeObj) => {
showToast('blue', 'Sending data...');
GM_xmlhttpRequest({
method: "POST",
url: "https://youth-exchange-worker.douglasdotv.workers.dev/",
headers: {
"Content-Type": "application/json"
},
data: JSON.stringify(youthExchangeObj),
onload: function (response) {
const responseText = response.responseText || 'No additional information provided';
if (response.status >= 200 && response.status < 300) {
showToast('green', `Your player was sent to the database. Thank you for contributing.`);
} else if (response.status === 400) {
showToast('red', `Bad Request (400): ${responseText}`);
} else if (response.status === 401) {
showToast('red', `Unauthorized (401): ${responseText}`);
} else if (response.status === 403) {
showToast('red', `Forbidden (403): ${responseText}`);
} else if (response.status === 404) {
showToast('red', `Not Found (404): ${responseText}`);
} else if (response.status === 500) {
showToast('red', `Server Error (500): ${responseText}`);
} else if (response.status === 503) {
showToast('red', `Service Unavailable (503): ${responseText}`);
} else {
showToast('red', `Unexpected Error (${response.status}): ${responseText}`);
}
console.log(`Data sent. HTTP Status Code: ${response.status}. Response: ${responseText}`);
},
onerror: function (error) {
showToast('red', 'Network Error: Failed to send data');
console.log('Error:', error);
}
});
};
const preparePlayerData = (playerData) => {
return {
id: playerData.playerID,
name: playerData.playerName,
age: youthExchangePlayerAge,
country: nationality,
hp: playerData.hp,
firstHpSkill: playerData.firstHpSkill,
secondHpSkill: playerData.secondHpSkill,
lp: playerData.lp,
firstLpSkill: playerData.firstLpSkill,
secondLpSkill: playerData.secondLpSkill,
trainingSpeed: playerData.trainingSpeed,
totalBalls: parseInt(playerData.totalSkillBalls, 10),
owner: username,
stats: playerData.stats,
season: parseInt(currentSeason, 10),
};
};
const extractPlayerStats = (playerContainer) => {
const stats = {};
const skillsNames = [
"speed", "stamina", "playIntelligence", "passing", "shooting",
"heading", "keeping", "ballControl", "tackling", "aerialPassing", "setPlays",
"experience", "form"
];
const skillsRows = playerContainer.querySelectorAll('.player_skills tr');
skillsRows.forEach((row, index) => {
if (index < skillsNames.length) {
const skillValueElement = row.querySelector('.skillval span');
const skillValue = skillValueElement ? parseInt(skillValueElement.textContent.trim()) : 0;
const skillName = skillsNames[index];
stats[skillName] = skillValue;
}
});
return stats;
};
const extractPlayerData = () => {
const playerContainer = document.getElementById("thePlayers_x");
if (!playerContainer) {
console.error("Player container not found");
return;
}
const currentPlayerID = playerContainer.querySelector('.player_id_span')?.textContent;
if (currentPlayerID === lastPlayerID && storedPlayerData) {
return;
}
lastPlayerID = currentPlayerID;
dataReady = false;
showToast('orange', '/16 running!');
GM_xmlhttpRequest({
method: "GET",
url: `https://www.managerzone.com/ajax.php?p=players&sub=scout_report&pid=null&sport=soccer`,
onload: function (response) {
let responseText = response.responseText.replace(/Trzxyvopaxis/g, '');
const parser = new DOMParser();
const doc = parser.parseFromString(responseText, "text/html");
const dataList = doc.querySelectorAll('dl > dd');
const extractSkillsAndPotentials = (skillContainers) => {
const skills = {
firstHpSkill: "",
secondHpSkill: "",
firstLpSkill: "",
secondLpSkill: ""
};
if (skillContainers.length > 1) {
const hpSkills = Array.from(skillContainers[0].querySelectorAll('li > span:last-child')).map(span => span.textContent.trim());
const lpSkills = Array.from(skillContainers[1].querySelectorAll('li > span:last-child')).map(span => span.textContent.trim());
if (hpSkills.length >= 2) {
skills.firstHpSkill = hpSkills[0];
skills.secondHpSkill = hpSkills[1];
}
if (lpSkills.length >= 2) {
skills.firstLpSkill = lpSkills[0];
skills.secondLpSkill = lpSkills[1];
}
}
return skills;
};
const skillsAndPotentials = extractSkillsAndPotentials(dataList);
const stats = extractPlayerStats(playerContainer);
const playerData = {
playerID: playerContainer.querySelector('.player_id_span').textContent,
playerName: playerContainer.querySelector('.player_name').textContent,
hp: dataList[0].querySelectorAll('.lit').length,
lp: dataList[1].querySelectorAll('.lit').length,
totalSkillBalls: playerContainer.querySelectorAll('tbody > tr')[6].querySelector('.bold').textContent,
trainingSpeed: dataList[2].querySelectorAll('.lit').length,
stats: stats,
...skillsAndPotentials
};
const youthExchangeObj = preparePlayerData(playerData);
storedPlayerData = youthExchangeObj;
dataReady = true;
console.log("Player data extracted and stored:", storedPlayerData);
showToast('green', 'Data is ready to be sent.');
console.log('(Data is ready)');
},
onerror: function () {
console.error("Error fetching player data.");
dataReady = false;
}
});
};
const setUpEventListeners = () => {
const observeRejectButton = () => {
const rejectButton = document.querySelector('#discard_youth_button');
if (rejectButton && !rejectButton.dataset.listenerAdded) {
rejectButton.addEventListener('click', (event) => {
if (!dataReady) {
event.preventDefault();
showToast('red', 'Data is not ready yet. Please wait.');
return;
}
console.log("Reject button clicked.");
sendDataToFirebase(storedPlayerData);
});
rejectButton.dataset.listenerAdded = true;
console.log("Listener added to Reject button.");
}
};
const exchangeButton = document.querySelector('#exchange_button');
if (exchangeButton && !exchangeButton.dataset.listenerAdded) {
exchangeButton.addEventListener('click', (event) => {
if (!dataReady) {
event.preventDefault();
showToast('red', 'Data is not ready yet. Please wait.');
return;
}
console.log("Exchange button clicked.");
sendDataToFirebase(storedPlayerData);
});
exchangeButton.dataset.listenerAdded = true;
console.log("Listener added to Exchange button.");
}
const playerContainer = document.getElementById("thePlayers_x");
if (playerContainer) {
const observer = new MutationObserver(() => {
const currentPlayerID = playerContainer.querySelector('.player_id_span')?.textContent;
if (currentPlayerID && currentPlayerID !== lastPlayerID) {
extractPlayerData();
} else if (!dataReady) {
showToast('orange', '/16 running!');
}
observeRejectButton();
});
observer.observe(playerContainer, { childList: true, subtree: true });
console.log("MutationObserver set up for player container changes.");
extractPlayerData();
observeRejectButton();
} else {
console.log("Player container not found. Cannot observe player data.");
}
};
const checkForPlayerContainer = () => {
const playerContainer = document.getElementById("thePlayers_x");
if (playerContainer) {
setUpEventListeners();
clearInterval(containerCheckInterval);
}
};
const containerCheckInterval = setInterval(checkForPlayerContainer, 1000);
window.addEventListener('load', async () => {
const usernameElement = document.getElementById('header-username');
username = usernameElement ? usernameElement.textContent : 'Unknown';
if (usernameCountryMap[username]) {
nationality = usernameCountryMap[username];
} else {
try {
const countryShortName = await fetchNationality(username);
nationality = await getCountryFullName(countryShortName);
} catch (error) {
console.error(error);
nationality = 'Unknown';
}
}
});
})();