你需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式
你需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式
你需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式
你需要先安装一款用户样式管理器扩展后才能安装此样式
你需要先安装一款用户样式管理器扩展后才能安装此样式
你需要先安装一款用户样式管理器扩展后才能安装此样式
(我已安装用户样式管理器,立即安装用户样式!)
// ==UserScript==
// @name IMVU Badge Granting Automation (Improved UI with URL-based Username)
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Automate badge granting on IMVU avatars page with pop-out interface and clean layout
// @author heapsofjoy
// @match https://avatars.imvu.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Extract username from the URL
const getUsernameFromUrl = () => {
const url = window.location.href; // Get the current URL
console.log("Current URL:", url); // Debugging: check if URL is correct
const match = url.match(/https:\/\/avatars\.imvu\.com\/([A-Za-z0-9_]+)/); // Match the username part in the URL
if (match) {
console.log("Username extracted from URL:", match[1]); // Debugging: show username extracted
return match[1];
} else {
console.error("Username extraction failed from URL."); // Error if username isn't found
return null;
}
};
// Fetch CID for the entered username
const getCid = (name) => {
return fetch(`https://api.imvu.com/user?username=${name}`, { credentials: 'include' })
.then(response => response.json())
.then(data => {
return Object.entries(data.denormalized)[0][1].data.legacy_cid;
})
.catch(err => {
console.error("Error fetching CID:", err); // Debugging: if fetch fails
});
};
// Start granting badges
let cancelGranting = false; // Flag to control the cancellation of the badge granting process
const startGrantingBadges = async (referrer, outputBox, titleElement) => {
const cid = await getCid(referrer);
if (!cid) {
showProgress(outputBox, 'Error: Unable to get CID for the username.');
return;
}
// Function to grant a badge
const func = async (i) => {
if (cancelGranting) return; // Stop if the user has clicked the stop button
// Grant the badge
const response = await fetch('https://avatars.imvu.com/api/service/grant_badge.php', {
credentials: 'include', // Include credentials (cookies/session info)
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
},
referrer: `https://avatars.imvu.com/${referrer}`,
body: `sauce=${IMVU.sauce}&badgeid=badge-${cid}-${i}`,
method: 'POST',
mode: 'cors',
});
// If the badge was granted (check for successful response)
if (response.ok) {
showProgress(outputBox, `Granted badge #${i}`);
} else {
showProgress(outputBox, `Failed to grant badge #${i}. Trying next.`);
}
};
// Recursive function to iterate badge granting
const recursive = async (i) => {
if (cancelGranting) return; // Stop if the user has clicked the stop button
setTimeout(async () => {
await func(i); // Try granting the badge
recursive(i + 1); // Move to the next badge
}, 2500); // Delay between badge granting
};
// Update the title to indicate the process is running
titleElement.innerText = `Granting badges for ${referrer}...`;
// Start the recursive badge granting process
recursive(1);
};
// Show progress in the output box
const showProgress = (outputBox, message) => {
outputBox.textContent += `\n${message}`;
outputBox.scrollTop = outputBox.scrollHeight; // Scroll to the bottom
};
// Create pop-out button to toggle the interface visibility
const createPopoutButton = () => {
const button = document.createElement('button');
button.innerText = '▶'; // Use a play button icon for a more intuitive look
button.style.position = 'fixed';
button.style.bottom = '20px';
button.style.right = '20px';
button.style.width = '40px';
button.style.height = '40px';
button.style.borderRadius = '50%';
button.style.backgroundColor = '#4CAF50';
button.style.color = 'white';
button.style.border = 'none';
button.style.fontSize = '20px';
button.style.cursor = 'pointer';
button.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)';
button.style.transition = 'background-color 0.3s, transform 0.3s';
// Hover effect
button.addEventListener('mouseover', () => {
button.style.backgroundColor = '#45a049';
button.style.transform = 'scale(1.1)';
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = '#4CAF50';
button.style.transform = 'scale(1)';
});
// Toggle pop-out box visibility
button.addEventListener('click', () => {
const popoutBox = document.getElementById('badge-granting-box');
popoutBox.style.display = (popoutBox.style.display === 'none' || !popoutBox.style.display) ? 'block' : 'none';
});
document.body.appendChild(button);
};
// Create the interface container
const createInterfaceBox = () => {
const box = document.createElement('div');
box.id = 'badge-granting-box';
box.style.position = 'fixed';
box.style.bottom = '20px';
box.style.right = '20px';
box.style.width = '320px';
box.style.height = '400px';
box.style.backgroundColor = '#fff';
box.style.border = '1px solid #ccc';
box.style.borderRadius = '8px';
box.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)';
box.style.padding = '15px';
box.style.display = 'none'; // Initially hidden
// Add Title Above Output Box
const titleElement = document.createElement('h3');
titleElement.innerText = 'Initializing...';
titleElement.style.textAlign = 'center';
titleElement.style.marginBottom = '10px';
titleElement.style.fontSize = '18px';
titleElement.style.fontWeight = 'bold';
box.appendChild(titleElement);
// Create output box for displaying progress
const outputBox = document.createElement('div');
outputBox.style.height = '250px';
outputBox.style.overflowY = 'auto';
outputBox.style.backgroundColor = '#f8f8f8';
outputBox.style.border = '1px solid #ccc';
outputBox.style.borderRadius = '5px';
outputBox.style.fontSize = '14px';
outputBox.style.padding = '10px';
outputBox.style.whiteSpace = 'pre-wrap'; // Preserve line breaks
box.appendChild(outputBox);
// Create run and stop buttons
const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex';
buttonContainer.style.justifyContent = 'space-between';
buttonContainer.style.marginTop = '10px';
// Run Button
const runButton = document.createElement('button');
runButton.innerText = 'Run';
runButton.style.flex = '1';
runButton.style.padding = '10px';
runButton.style.backgroundColor = '#4CAF50';
runButton.style.color = 'white';
runButton.style.border = 'none';
runButton.style.borderRadius = '5px';
runButton.style.cursor = 'pointer';
runButton.addEventListener('click', () => {
const username = getUsernameFromUrl(); // Get username from the URL
if (username) {
showProgress(outputBox, 'Starting badge granting...');
startGrantingBadges(username, outputBox, titleElement);
} else {
showProgress(outputBox, 'Error: Could not extract username.');
}
});
// Stop Button
const stopButton = document.createElement('button');
stopButton.innerText = 'Stop';
stopButton.style.flex = '1';
stopButton.style.padding = '10px';
stopButton.style.backgroundColor = '#f44336';
stopButton.style.color = 'white';
stopButton.style.border = 'none';
stopButton.style.borderRadius = '5px';
stopButton.style.cursor = 'pointer';
stopButton.addEventListener('click', () => {
cancelGranting = true; // Stop the granting process
showProgress(outputBox, 'Process stopped.');
titleElement.innerText = 'Stopped';
});
buttonContainer.appendChild(runButton);
buttonContainer.appendChild(stopButton);
box.appendChild(buttonContainer);
document.body.appendChild(box);
};
// Initialize everything
createPopoutButton();
createInterfaceBox();
})();