IMVU CID Fetcher

Fetch your IMVU CID with a minimal, sleek UI and avatar preview.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         IMVU CID Fetcher
// @namespace    http://brightlittlestars.moe/
// @version      1.5.01
// @description  Fetch your IMVU CID with a minimal, sleek UI and avatar preview.
// @author
// @match        *://www.imvu.com/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    const primaryColor = "#0084AC";

    // Prevent duplicate script instances
    if (document.getElementById("toggleCidFetcher") || document.getElementById("cidFetcher")) return;

    // Create toggle button
    const toggleButton = document.createElement("div");
    toggleButton.id = "toggleCidFetcher";
    toggleButton.style = `
        position: fixed; top: 10px; right: 10px; width: 25px; height: 25px;
        background-color: ${primaryColor}; color: white; font-size: 16px;
        font-weight: bold; cursor: pointer; display: flex; align-items: center;
        justify-content: center; border-radius: 50%; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); z-index: 9999;
    `;
    toggleButton.textContent = "→";
    document.body.appendChild(toggleButton);

    // Create input box
    const inputDiv = document.createElement("div");
    inputDiv.id = "cidFetcher";
    inputDiv.style = `
        position: fixed; top: 10px; right: -270px; width: 250px; background-color: white;
        border: 1px solid #ccc; border-radius: 5px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        padding: 10px; transition: right 0.3s ease-in-out; z-index: 9998;
    `;
    inputDiv.innerHTML = `
        <label for="inputMode" style="font-size: 14px; font-weight: bold;">Select Input Mode:</label>
        <div style="margin: 5px 0;">
            <input type="radio" id="manualMode" name="inputMode" value="manual" style="margin-right: 5px;">
            <label for="manualMode">CID</label>
            <input type="radio" id="fetchMode" name="inputMode" value="fetch" checked style="margin-left: 15px; margin-right: 5px;">
            <label for="fetchMode">Username</label>
        </div>
        <label for="imvuInput" style="font-size: 14px; font-weight: bold;">Enter Username or CID:</label>
        <input type="text" id="imvuInput" placeholder="Username or CID" style="width: 95%; margin-top: 5px; padding: 5px; font-size: 14px; border: 1px solid #ccc; border-radius: 3px;">
        <button id="processInput" style="width: 100%; margin-top: 10px; padding: 8px; font-size: 14px; background-color: ${primaryColor}; color: white; border: none; border-radius: 3px; cursor: pointer;">Submit</button>
        <div id="output" style="margin-top: 10px; font-size: 13px;"></div>
    `;
    document.body.appendChild(inputDiv);

    // Toggle functionality
    toggleButton.addEventListener("click", () => {
        inputDiv.style.right = inputDiv.style.right === "10px" ? "-270px" : "10px";
        toggleButton.textContent = inputDiv.style.right === "10px" ? "→" : "←";
    });

    async function processInput() {
        const inputMode = document.querySelector('input[name="inputMode"]:checked').value;
        const inputValue = document.getElementById("imvuInput").value.trim();
        const outputDiv = document.getElementById("output");

        if (!inputValue) {
            outputDiv.textContent = "Please enter a value!";
            outputDiv.style.color = "red";
            return;
        }

        if (inputMode === "manual") {
            // Manual mode: Use input as CID directly
            displayCidData(inputValue);
        } else {
            // Fetch mode: Fetch CID using username
            outputDiv.innerHTML = `<div style="width: 24px; height: 24px; border: 2px solid #ccc; border-top: 2px solid ${primaryColor}; border-radius: 50%; animation: spin 1s linear infinite; margin: auto;"></div>`;
            outputDiv.style.color = "black";

            const url = `https://www.imvu.com/shop/web_search.php?keywords=${encodeURIComponent(inputValue)}&within=creator_name`;

            try {
                const response = await fetch(url);
                const text = await response.text();
                const match = text.match(/image_avatar\.php\?cid=(\d+)/);

                if (match && match[1]) {
                    displayCidData(match[1]);
                } else {
                    outputDiv.textContent = "User not found! Ensure the username/CID is correct.";
                    outputDiv.style.color = "red";
                }
            } catch (error) {
                console.error("Error fetching CID:", error);
                outputDiv.textContent = "Error fetching data!";
                outputDiv.style.color = "red";
            }
        }
    }

    async function displayCidData(cid) {
        const outputDiv = document.getElementById("output");

        try {
            const apiUrl = `https://api.imvu.com/user/user-${cid}`;
            const apiResponse = await fetch(apiUrl);
            const apiData = await apiResponse.json();


            const userData = apiData.denormalized[`https://api.imvu.com/user/user-${cid}`];

if (userData) {
                    const avatarThumbnailUrl = userData.data?.thumbnail_url;
                    const tagline = userData.data?.tagline || "No tagline provided.";
                    const interests = userData.data?.interests || "No interests provided.";

                    const avatarCardUrl = `https://client-dynamic.imvu.com/api/avatarcard.php?cid=${cid}&viewer_cid=`;
                    const NEXTavatarCardUrl = `https://api.imvu.com/user/user-${cid}`;
                    const HomepageUrl = `https://www.imvu.com/catalog/web_mypage.php?user=${cid}`;
                    const ShopUrl = `https://www.imvu.com/shop/web_search.php?manufacturers_id=${cid}`;
                    const onlineStatusIcon = userData.data.online
                   ? `<span style="color: green; font-size: 12px;">🟢</span>` // Green for online
                   : `<span style="color: red; font-size: 12px;">🔴</span>`; // Red for offline

outputDiv.innerHTML = `
    <div style="border: 1px solid #ccc; border-radius: 10px; padding: 15px; max-width: 300px; background-color: #f9f9f9; text-align: center; font-family: Arial, sans-serif; max-height: 650px; overflow-y: auto;">
        <h3 style="margin: 0; color: ${primaryColor}; font-size: 16px; margin-bottom: 5px;">
            ${userData.data.username}
        </h3>

        <img src="${avatarThumbnailUrl}" alt="Avatar Image" style="width: 140px; height: 200px; object-fit: cover; border-radius: 8px; margin-bottom: 10px; border: 1px solid #ddd;">
        <h3 style="margin: 0; color: ${primaryColor}; font-size: 16px; margin-bottom: 5px;">Avatar Information</h3>

        <p style="margin: 5px 0; font-size: 12px; font-weight: bold; color: #333;">${onlineStatusIcon} CID: <span style="font-weight: normal;">${cid}</span></p>

        <div style="display: flex; justify-content: center; align-items: center; gap: 15px; margin-bottom: 5px; font-size: 12px; color: #555;">
            <div style="display: flex; align-items: center;">
                <span style="font-weight: bold; margin-right: 2px;">Age:</span>
                <span>${userData.data.age || "N/A"}</span>
            </div>
            <div style="display: flex; align-items: center;">
                <span style="font-weight: bold; margin-right: 2px;">Gender:</span>
                <span>${userData.data.gender || "N/A"}</span>
            </div>
            <div style="display: flex; align-items: center;">
                <span style="font-weight: bold; margin-right: 2px;">Country:</span>
                <span>${userData.data.country || "N/A"}</span>
            </div>
        </div>

        <p style="margin: 10px 0; font-size: 12px; font-weight: bold; color: ${primaryColor};">Tagline:</p>
        <div style="border: 1px solid #ccc; border-radius: 5px; max-height: 50px; overflow-y: auto; padding: 5px; font-size: 12px; background-color: #f9f9f9; text-align: left;">
            ${tagline || "No tagline available."}
        </div>

        <p style="margin: 10px 0; font-size: 12px; font-weight: bold; color: ${primaryColor};">Interests:</p>
        <div style="border: 1px solid #ccc; border-radius: 5px; max-height: 50px; overflow-y: auto; padding: 5px; font-size: 12px; background-color: #f9f9f9; text-align: left;">
            ${interests || "No interests available."}
        </div>

        <hr style="border: none; border-top: 1px solid #ddd; margin: 10px 0;">

        <div style="text-align: left;">
            <h4 style="margin: 5px 0; font-size: 12px; color: ${primaryColor};">Quick Links:</h4>
            <a href="${HomepageUrl}" target="_blank" style="display: block; color: ${primaryColor}; text-decoration: none; font-size: 12px; margin-bottom: 5px;">
                🏠 Homepage
            </a>
            <a href="${ShopUrl}" target="_blank" style="display: block; color: ${primaryColor}; text-decoration: none; font-size: 12px; margin-bottom: 5px;">
                🛍️ Shop
            </a>
        </div>

        <hr style="border: none; border-top: 1px solid #ddd; margin: 10px 0;">

        <div style="text-align: left;">
            <h4 style="margin: 5px 0; font-size: 12px; color: ${primaryColor}; cursor: pointer;" id="toggleAdvancedLinks">
                Advanced Links <span style="font-size: 10px;">▼</span>
            </h4>
            <div id="advancedLinks" style="display: none; margin-left: 10px;">
                <a href="${avatarCardUrl}" target="_blank" style="display: block; color: ${primaryColor}; text-decoration: none; font-size: 12px; margin-bottom: 5px;">
                    📇 Avatar Card URL
                </a>
                <a href="${NEXTavatarCardUrl}" target="_blank" style="display: block; color: ${primaryColor}; text-decoration: none; font-size: 12px;">
                    🔗 Next Avatar Card URL
                </a>
            </div>
        </div>
    </div>
`;

  // Add event listener for toggling advanced links
document.getElementById("toggleAdvancedLinks").addEventListener("click", () => {
    const advancedLinks = document.getElementById("advancedLinks");
    const toggleText = document.querySelector("#toggleAdvancedLinks span");
    if (advancedLinks.style.display === "none") {
        advancedLinks.style.display = "block";
        toggleText.textContent = "▲"; // Change arrow to up
    } else {
        advancedLinks.style.display = "none";
        toggleText.textContent = "▼"; // Change arrow to down
    }
});
            } else {
                outputDiv.textContent = "User data not found!";
                outputDiv.style.color = "red";
            }
        } catch (error) {
            console.error("Error displaying CID data:", error);
            outputDiv.textContent = "Error displaying data!";
            outputDiv.style.color = "red";
        }
    }

    document.getElementById("processInput").addEventListener("click", processInput);
})();