您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add hours remaining and total spend rate to balance display on Vast.ai
当前为
- // ==UserScript==
- // @license MIT
- // @name Vast.ai Balance Hours Remaining
- // @namespace http://tampermonkey.net/
- // @version 0.1
- // @description Add hours remaining and total spend rate to balance display on Vast.ai
- // @author You
- // @match https://cloud.vast.ai/*
- // @grant GM_xmlhttpRequest
- // ==/UserScript==
- (function() {
- 'use strict';
- let lastCredit = 0;
- let totalSpendRate = 0;
- 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 updateDisplay() {
- const creditDiv = document.evaluate(
- '/html/body/div[1]/div[1]/header/div[2]/span[1]',
- document,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
- if (creditDiv) {
- // Add or update hours remaining
- let hoursDiv = document.getElementById('hours-remaining');
- if (!hoursDiv) {
- hoursDiv = document.createElement('span');
- hoursDiv.id = 'hours-remaining';
- hoursDiv.style.fontSize = '14px';
- hoursDiv.style.marginLeft = '10px';
- creditDiv.after(hoursDiv);
- }
- const hoursRemaining = totalSpendRate > 0 ? lastCredit / totalSpendRate : 0;
- hoursDiv.textContent = ``;
- hoursDiv.innerHTML = `<span style="color: green; font-weight: bold">($${totalSpendRate.toFixed(3)}/hr)</span> <span style="color: #66cc66; font-weight: bold">${formatTimeRemaining(hoursRemaining)}</span>`;
- }
- }
- function fetchData() {
- // Fetch current user data
- fetch('https://cloud.vast.ai/api/v0/users/current/')
- .then(response => response.json())
- .then(data => {
- lastCredit = data.credit;
- })
- .catch(error => console.error('Error fetching user data:', error));
- // Fetch instances data
- fetch('https://cloud.vast.ai/api/v0/instances/')
- .then(response => response.json())
- .then(data => {
- totalSpendRate = 0;
- if (data.instances && Array.isArray(data.instances)) {
- data.instances.forEach(instance => {
- if (instance.search && instance.search.totalHour) {
- totalSpendRate += instance.search.totalHour;
- }
- });
- }
- updateDisplay();
- })
- .catch(error => console.error('Error fetching instances data:', error));
- }
- // Initial fetch
- fetchData();
- // Update every 30 seconds
- setInterval(fetchData, 30000);
- // Monitor XHR responses
- const originalFetch = window.fetch;
- window.fetch = async function(...args) {
- const response = await originalFetch.apply(this, args);
- const url = args[0].toString();
- if (url.includes('/api/v0/users/current/') || url.includes('/api/v0/instances/')) {
- fetchData();
- }
- return response;
- };
- })();