Shows ratelimit information on Grok
当前为
// ==UserScript==
// @name Grok ratelimit indicator
// @namespace https://6942020.xyz/
// @version 1.0
// @description Shows ratelimit information on Grok
// @author WadeGrimridge
// @match https://grok.com/*
// @license MIT
// @grant none
// ==/UserScript==
(function () {
"use strict";
let rateInfoElement = null;
const modelRateLimits = {
"grok-latest": null,
"grok-3": null,
};
const modelDisplayNames = {
"grok-latest": "Grok 2",
"grok-3": "Grok 3",
};
function formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return remainingSeconds > 0
? `${minutes}m ${remainingSeconds}s`
: `${minutes}m`;
}
async function fetchRateLimit(modelName, attempt = 1) {
try {
const response = await fetch("/rest/rate-limits", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ requestKind: "DEFAULT", modelName }),
});
if (response.status === 401 && attempt <= 10) {
await new Promise((resolve) => setTimeout(resolve, 2500));
return fetchRateLimit(modelName, attempt + 1);
}
const data = await response.json();
if (
data.remainingQueries !== undefined &&
data.totalQueries !== undefined
) {
updateRateInfo(data, modelName);
}
} catch (error) {
console.error(`[grok-ratelimit] Rate limit fetch failed:`, error);
if (attempt > 10 && rateInfoElement) {
rateInfoElement.textContent = "Couldn't fetch ratelimit info";
}
}
}
function createRateInfoElement() {
const targetDiv = document.querySelector(
'main div:has(> a[aria-label="Home page"])'
);
if (targetDiv && !rateInfoElement) {
rateInfoElement = document.createElement("div");
rateInfoElement.className = "ml-2 text-sm";
rateInfoElement.textContent = "Fetching ratelimit info...";
targetDiv.appendChild(rateInfoElement);
(async () => {
await fetchRateLimit("grok-3");
await fetchRateLimit("grok-latest");
})();
}
}
function updateRateInfo(data, modelName) {
if (rateInfoElement) {
modelRateLimits[modelName] = data;
const lines = [];
const displayOrder = ["grok-3", "grok-latest"];
for (const model of displayOrder) {
const data = modelRateLimits[model];
if (data) {
const timeStr = formatTime(data.windowSizeSeconds);
lines.push(
`${modelDisplayNames[model]}: ${data.remainingQueries}/${data.totalQueries} (${timeStr})`
);
}
}
rateInfoElement.textContent = lines.join(" | ");
}
}
const originalFetch = window.fetch;
window.fetch = async function (...args) {
const [resource, options] = args;
const url =
resource instanceof Request ? resource.url : resource.toString();
if (url.includes("/rest/rate-limits")) {
const requestBody = JSON.parse(options.body);
const modelName = requestBody.modelName;
const response = await originalFetch.apply(this, args);
const clone = response.clone();
clone.json().then((data) => {
if (
data.remainingQueries !== undefined &&
data.totalQueries !== undefined
) {
updateRateInfo(data, modelName);
}
});
return response;
}
return originalFetch.apply(this, args);
};
function waitForElement() {
const targetDiv = document.querySelector(
'main div:has(> a[aria-label="Home page"])'
);
if (targetDiv) {
createRateInfoElement();
} else {
requestAnimationFrame(waitForElement);
}
}
waitForElement();
})();