ChatGPT模型调用计数器

更新最新ChatGPT-4o mini 模型调用情况,记录并显示你在ChatGPT上调用各模型的次数。右键可以重置计数。

目前為 2024-07-27 提交的版本,檢視 最新版本

// ==UserScript==
// @name         ChatGPT模型调用计数器
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  更新最新ChatGPT-4o mini 模型调用情况,记录并显示你在ChatGPT上调用各模型的次数。右键可以重置计数。
// @author       狐狸的狐狸画
// @match        https://chatgpt.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const modelIcons = {
        'gpt-4o': `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M19.92.897a.447.447 0 0 0-.89-.001c-.12 1.051-.433 1.773-.922 2.262-.49.49-1.21.801-2.262.923a.447.447 0 0 0 0 .888c1.035.117 1.772.43 2.274.922.499.49.817 1.21.91 2.251a.447.447 0 0 0 .89 0c.09-1.024.407-1.76.91-2.263.502-.502 1.238-.82 2.261-.908a.447.447 0 0 0 .001-.891c-1.04-.093-1.76-.411-2.25-.91-.493-.502-.806-1.24-.923-2.273ZM11.993 3.82a1.15 1.15 0 0 0-2.285-.002c-.312 2.704-1.115 4.559-2.373 5.817-1.258 1.258-3.113 2.06-5.817 2.373a1.15 1.15 0 0 0 .003 2.285c2.658.3 4.555 1.104 5.845 2.37 1.283 1.26 2.1 3.112 2.338 5.789a1.15 1.15 0 0 0 2.292-.003c.227-2.631 1.045-4.525 2.336-5.817 1.292-1.291 3.186-2.109 5.817-2.336a1.15 1.15 0 0 0 .003-2.291c-2.677-.238-4.529-1.056-5.789-2.34-1.266-1.29-2.07-3.186-2.37-5.844Z"></path></svg>`,
        'gpt-4': `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M12.001 1.75c.496 0 .913.373.969.866.306 2.705 1.126 4.66 2.44 6 1.31 1.333 3.223 2.17 5.95 2.412a.976.976 0 0 1-.002 1.945c-2.682.232-4.637 1.067-5.977 2.408-1.34 1.34-2.176 3.295-2.408 5.977a.976.976 0 0 1-1.945.002c-.243-2.727-1.08-4.64-2.412-5.95-1.34-1.314-3.295-2.134-6-2.44a.976.976 0 0 1-.002-1.94c2.75-.317 4.665-1.137 5.972-2.444 1.307-1.307 2.127-3.221 2.444-5.972a.976.976 0 0 1 .971-.864Z"></path></svg>`,
        'gpt-4o-mini': `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M12.566 2.11c1.003-1.188 2.93-.252 2.615 1.271L14.227 8h5.697c1.276 0 1.97 1.492 1.146 2.467L11.434 21.89c-1.003 1.19-2.93.253-2.615-1.27L9.772 16H4.076c-1.276 0-1.97-1.492-1.147-2.467L12.565 2.11Z" clip-rule="evenodd"></path></svg>`,
    };

    const originalFetch = window.fetch;
    window.fetch = function(url, options) {
        if (url.includes("/backend-api/conversation") && options && options.method === "POST") {
            try {
                const body = JSON.parse(options.body);
                if (body.model) {
                    updateModelCount(body.model);
                }
            } catch (e) {
                console.error('解析请求体失败:', e);
            }
        }
        return originalFetch.apply(this, arguments);
    };

    function updateModelCount(model) {
        const modelCountKey = 'model_counts';
        const counts = JSON.parse(localStorage.getItem(modelCountKey) || '{}');
        counts[model] = (counts[model] || 0) + 1;
        localStorage.setItem(modelCountKey, JSON.stringify(counts));
        displayCounts();
    }

    function displayCounts() {
        const modelCountKey = 'model_counts';
        const counts = JSON.parse(localStorage.getItem(modelCountKey) || '{}');
        let displayText = '';
        for (let model in counts) {
            const icon = modelIcons[model] || '❓';
            displayText += `<div style="display: flex; align-items: center; margin-right: 10px;">${icon} ${counts[model]}</div>`;
        }

        let displayDiv = document.getElementById('model-count-display');
        if (!displayDiv) {
            displayDiv = document.createElement('div');
            displayDiv.id = 'model-count-display';
            Object.assign(displayDiv.style, {
                display: 'flex',
                position: 'fixed',
                top: '5px',
                left: '450px',
                backgroundColor: 'rgba(0,0,0,0)',
                color: 'rgba(66,66,66,1)',
                padding: '10px',
                borderRadius: '5px',
                zIndex: '1000',
                fontSize: '14px',
                fontWeight: 'bold',
            });

            document.body.appendChild(displayDiv);
        }
        displayDiv.innerHTML = displayText;
    }

    function clearData() {
        localStorage.removeItem('model_counts');
        displayCounts();
    }

    function monitorDOM() {
        const targetNode = document.body;
        const config = { childList: true, subtree: true };
        const callback = function(mutationsList, observer) {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    const addedNodes = mutation.addedNodes;
                    for (const node of addedNodes) {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            const span = node.querySelector('span');
                            if (span && span.textContent.includes('添加 Team 工作空间')) {
                                const aTag = span.closest('a');
                                if (aTag && !aTag.previousElementSibling?.classList.contains('inserted-button')) {
                                    insertDisplayPanel(aTag);
                                }
                            }
                        }
                    }
                }
            }
        };
        const observer = new MutationObserver(callback);
        observer.observe(targetNode, config);
    }

    function insertDisplayPanel(aTag) {
        let displayDiv = document.getElementById('model-count-display');
        if (displayDiv && !aTag.parentNode.contains(displayDiv)) {
            aTag.parentNode.insertBefore(displayDiv, aTag);
        }
    }

    function handleResize() {
        const displayDiv = document.getElementById('model-count-display');
        if (displayDiv) {
            document.body.appendChild(displayDiv);
        }
    }

    window.addEventListener('resize', handleResize);

    // 创建右键菜单
    const contextMenu = document.createElement('div');
    contextMenu.id = 'context-menu';
    contextMenu.style.position = 'absolute';
    contextMenu.style.display = 'none';
    contextMenu.style.backgroundColor = 'white';
    contextMenu.style.border = '1px solid #ccc';
    contextMenu.style.padding = '10px';
    contextMenu.style.zIndex = '1001';

    const clearDataMenuItem = document.createElement('div');
    clearDataMenuItem.textContent = '清除数据';
    clearDataMenuItem.style.cursor = 'pointer';
    clearDataMenuItem.onclick = () => {
        clearData();
        contextMenu.style.display = 'none';
    };

    contextMenu.appendChild(clearDataMenuItem);
    document.body.appendChild(contextMenu);

    // 右键点击事件
    window.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        contextMenu.style.top = `${e.clientY}px`;
        contextMenu.style.left = `${e.clientX}px`;
        contextMenu.style.display = 'block';
    });

    // 点击其他地方隐藏右键菜单
    window.addEventListener('click', () => {
        contextMenu.style.display = 'none';
    });

    displayCounts();
    monitorDOM();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址