ARS to USD converter for shuffle.com (text + numbers)
// ==UserScript==
// @name xd2shuffle
// @namespace http://tampermonkey.net/
// @version 7.7.7.8
// @description ARS to USD converter for shuffle.com (text + numbers)
// @author fusi | @loficat on tg | codedfusi on github | Modified by user
// @match *://*.shuffle.com/*
// @grant none
// @run-at document-start
// @license MIT
// ==/UserScript==
(function () {
// ==========================================
// SET THE EXCHANGE RATE HERE
// Example: 1 USD = 1400 ARS
// ==========================================
const USD_RATE = 1400; // <-- CHANGE THIS NUMBER to the current rate
// Store modified nodes to avoid double processing
const processedTextNodes = new WeakSet();
const processedImages = new WeakSet();
// Helper: Convert ARS number string to USD formatted string
function convertARStextToUSD(text) {
// Match numbers that could be ARS amounts (including commas and decimals)
// This looks for patterns like: 1,234,567.89 or 1.234.567,89 or just 1234
const arsNumberPattern = /(\b[\d,]+(?:\.\d+)?\b)|(\b[\d.]+(?:,\d+)?\b)/g;
return text.replace(arsNumberPattern, (match) => {
// Clean the match: remove commas (for US style) or dots (for EU style)
let cleanNumber = match.replace(/,/g, '');
// If it has a dot and then exactly 2 digits at the end, it might be decimal
// For EU style like 1.234,56 -> replace dot with empty and comma with dot
if (cleanNumber.includes('.') && cleanNumber.includes(',')) {
cleanNumber = cleanNumber.replace(/\./g, '').replace(/,/, '.');
} else if (cleanNumber.includes(',')) {
// If only commas, treat as decimal separator (EU)
cleanNumber = cleanNumber.replace(/,/, '.');
}
const arsValue = parseFloat(cleanNumber);
if (isNaN(arsValue)) return match;
const usdValue = arsValue / USD_RATE;
// Format USD with 2 decimal places, using US notation
return usdValue.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
});
}
function processTextNode(node) {
if (node.nodeType === 3 && node.nodeValue && !processedTextNodes.has(node)) {
let original = node.nodeValue;
let modified = false;
let newValue = original;
// Replace ARS symbol with $
if (newValue.includes("ARS")) {
newValue = newValue.replace(/ARS/g, "$");
modified = true;
}
// Convert ARS numbers to USD (if text contains numbers)
if (/\d/.test(newValue)) {
const converted = convertARStextToUSD(newValue);
if (converted !== newValue) {
newValue = converted;
modified = true;
}
}
if (modified) {
node.nodeValue = newValue;
processedTextNodes.add(node);
}
}
}
function processImageElement(el) {
if (el.nodeType === 1 && el.hasAttribute("src") && !processedImages.has(el)) {
const src = el.getAttribute("src");
if (src && src.includes("/icons/fiat/ARS.svg")) {
el.setAttribute("src", src.replace("/icons/fiat/ARS.svg", "/icons/fiat/USD.svg"));
processedImages.add(el);
}
}
}
function walkAndProcess(root) {
if (!root) return;
// Process text nodes
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
let node;
while ((node = walker.nextNode())) {
processTextNode(node);
}
// Process image elements
const images = root.querySelectorAll('img[src*="/icons/fiat/ARS.svg"]');
images.forEach(img => processImageElement(img));
}
// MutationObserver callback to handle dynamically added content
function onMutation(mutations) {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
for (const addedNode of mutation.addedNodes) {
if (addedNode.nodeType === 1) {
walkAndProcess(addedNode);
} else if (addedNode.nodeType === 3) {
processTextNode(addedNode);
}
}
}
}
// Also periodically re-check text nodes that might have changed value
// (We use a weak set so we only reprocess if the node was garbage collected)
}
// Start the script once the DOM is ready
document.addEventListener("DOMContentLoaded", () => {
walkAndProcess(document.body);
const observer = new MutationObserver(onMutation);
observer.observe(document.body, {
childList: true,
subtree: true
});
});
})();