NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name CCO Buff Alarm V2 // @namespace CyberCodeOnline // @version 2.0.1 // @description Simple calibration alert bot for cyber code online // @author Jefreesujit // @match https://cybercodeonline.com/tabs/stats // @icon https://www.google.com/s2/favicons?sz=64&domain=cybercodeonline.com // @grant none // @license MIT // ==/UserScript== /*jshint esversion: 8 */ (function() { 'use strict'; // bot url endpoint const hookUrl = 'https://discord.com/api/webhooks/963049861220032582/0560pIXdu5ScAXDLBsbT7xaHkzeuMhn8lEXcE6BDEQvXr2MOwOuvbniJDFsnUR9c8qtrx'; const role = '<@&960109485618241587>'; // buff to be looked for const buffPrefix = 'calibration'; let messageId, isTimeoutActive = false; const delay = async (timer = 5000) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(timer); }, timer); }); } // calculate the buff score from percentage // Contribution credits: Rejid const getBuffScoreFromPerc = (percent) => { if (percent>=666){ return "+10 Cali"; } if (percent>=400){ return "+9 Cali"; } if (percent>=200){ return "+8 Cali"; } if (percent>=150){ return "+7 Cali"; } if (percent>=100){ return "+6 Cali"; } if (percent>=50){ return "+5 Cali"; } if (percent>=15){ return "+4 Cali"; } if (percent>=10){ return "+3 Cali"; } if (percent>=5){ return "+2 Cali"; } return "No Cali"; }; // Iterate through each active buffs to check for matching buff name // Fetch the percentage score for each buff and sum it up const getBuffPerc = async () => { let buffVal = 0, buffName = ''; const buffContEl = document.querySelector('.z-10 div.flex-row.flex-wrap.mb-2'); const buffArray = []; buffContEl.childNodes.forEach((childEl, index) => { console.log('childEl', childEl); const buffEl = childEl.childNodes[1]; const bt = buffEl.innerText; if (bt.toLowerCase().includes(buffPrefix)) { buffArray.push(childEl); buffName = bt; } }); for (let buffItem of buffArray) { await delay(1000); buffItem.childNodes[1].click(); const buffModal = document.querySelector('div.border.neon.p-2.justify-center.items-center.mr-2'); const buffPerc = buffModal ? buffModal.innerText.split('\n').shift() : '0'; buffModal && document.querySelector('.dialog-backdrop').click(); console.log('buffPerc', buffVal); buffVal += parseInt(buffPerc.replace(/[^0-9]/g,''), 10); } console.log('buffVal after for loop', buffVal); return [buffVal, buffName]; }; // Experimental : Push all events to another events bot const pushEvents = (eventText) => { fetch(`${hookUrl}?wait=true`, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ content: eventText }) }); }; // Send message to bot const sendMessage = async (message) => { const rawResponse = await fetch(`${hookUrl}?wait=true`, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ content: message }) }); const content = await rawResponse.json(); console.log('response', content); return content; }; // Update existing message if messageId already present const updateMessage = async (message, msgId) => { const rawResponse = await fetch(`${hookUrl}/messages/${msgId}`, { method: 'PATCH', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ content: message }) }); const content = await rawResponse.json(); return content; }; // Listen for observed dom mutations and check for matching buff names // Fetch required metadata, construct request payload for sending message to bot const getMessage = async (mutation) => { let message = ''; if (mutation.type == 'childList' && mutation.addedNodes.length) { const newEl = mutation.addedNodes[0]; if (newEl.classList.length === 0) { const buffText = newEl.innerText; if (buffText.toLowerCase().includes(buffPrefix)) { message = `${role} Buff Added `; const activatedBy = newEl.querySelector('.text-mod').innerText; try { const [tBuffPerc, tBuffName] = await getBuffPerc(); const buffScore = getBuffScoreFromPerc(tBuffPerc); message = `**Buff Name**: *${tBuffName}* \n**Buff Value**: ${buffScore} (estimated)\n**Mentions**: ${role} @here \n**Activated By**: *${activatedBy}*`; } catch (e) { console.log('Failed fetching buff percenatage', e); } } console.log(buffText); // pushEvents(buffText); } } return message; }; // Callback handler for observed dom mutations const callback = async (mutationsList) => { for(let mutation of mutationsList) { // console.log('buff object', mutation.type, mutation); const message = await getMessage(mutation); if (message) { if (messageId) { console.log('updateMessage', message, messageId); const { id } = await updateMessage(message, messageId); } else { console.log('sendMessage', message); const { id } = await sendMessage(message); messageId = id; } } } // Persist the messageId for 4 minutes when new matching buff is added. // Whenever a buff is added within that time, update existing message with this messageId // Erase the messageId after 4 minutes (active buff time) and push upcoming event as new buffs if (messageId && !isTimeoutActive) { isTimeoutActive = true; setTimeout(() => { console.log('messageId', messageId) messageId = null; isTimeoutActive = false; }, 240000); } }; // Initialise Script after 10 seconds of page load (wait until page loads fully) setTimeout(() => { const config = { attributes: false, childList: true, subtree: false, characterData: false }; // Buff observable DOM const buffContainerEl = document.querySelector('.h-full.relative.flex-col-reverse.overflow-y-scroll.overflow-x-hidden'); // chat window // const buffContainerEl = document.querySelector('.z-10 div.flex-row.flex-wrap.mb-2'); // buff window try { const observer = new MutationObserver(callback); observer.observe(buffContainerEl, config); console.log('Buff Observable v2 Initialized'); } catch (e) { console.log('Buff Observable v2 Initialization error', e); } }, 10000); })();