RunPod Balance Hours Remaining

Add hours remaining to balance display on RunPod

// ==UserScript==
// @license MIT 
// @name         RunPod Balance Hours Remaining
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Add hours remaining to balance display on RunPod
// @author       You
// @match        https://www.runpod.io/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function formatTimeRemaining(hours) {
        if (!isFinite(hours) || isNaN(hours)) return "-- remaining";
        
        const totalHours = Math.floor(hours);
        const minutes = Math.round((hours - totalHours) * 60);

        if (totalHours === 0) {
            return `${minutes}m remaining`;
        } else if (minutes === 0) {
            return `${totalHours}h remaining`;
        } else {
            return `${totalHours}h ${minutes}m remaining`;
        }
    }

    function updateHoursRemaining(balance, spendPerHr) {
        const balanceDiv = document.evaluate(
            '/html/body/div[1]/div[1]/div[2]/div[2]/div/div[2]/div/div/a/button/div/div[1]',
            document,
            null,
            XPathResult.FIRST_ORDERED_NODE_TYPE,
            null
        ).singleNodeValue;

        if (balanceDiv) {
            // Check if values are valid numbers and spendPerHr is not zero
            if (!isFinite(balance) || !isFinite(spendPerHr) || spendPerHr === 0) {
                console.log('RunPod Hours Script - Invalid values:', {balance, spendPerHr});
                return;
            }

            const hoursRemaining = balance / spendPerHr;
            let hoursDiv = document.getElementById('hours-remaining');

            if (!hoursDiv) {
                hoursDiv = document.createElement('div');
                hoursDiv.id = 'hours-remaining';
                hoursDiv.style.fontSize = '10px';
                hoursDiv.style.color = '#94a3b8';
                hoursDiv.style.fontWeight = '600';
                balanceDiv.after(hoursDiv);
            }

            hoursDiv.textContent = formatTimeRemaining(hoursRemaining);
        }
    }

    // Monitor XHR responses for GraphQL data
    const originalFetch = window.fetch;
    window.fetch = async function(...args) {
        const response = await originalFetch.apply(this, args);
        if (response.url.includes('api.runpod.io/graphql')) {
            response.clone().json().then(data => {
                if (data.data?.myself) {
                    const balance = parseFloat(data.data.myself.clientBalance);
                    const spendPerHr = parseFloat(data.data.myself.currentSpendPerHr);
                    console.log('RunPod Hours Script - Received values:', {balance, spendPerHr});
                    updateHoursRemaining(balance, spendPerHr);
                }
            }).catch(error => {
                console.error('RunPod Hours Script - Error processing response:', error);
            });
        }
        return response;
    };
})();

QingJ © 2025

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