基于佬的脚本,使用Grok-4和claude 4修改的。
如果没效果可以尝试到主页刷新看下
// ==UserScript==
// @name Grok速率限制监视器
// @namespace http://tampermonkey.net/
// @version 2.0
// @description 现代、带动画的速率限制监视器,支持暗/亮模式 - 更新以适应新 Grok 接口,显示token和努力等级
// @author Grok-4 (修改)
// @match https://grok.com/*
// @grant none
// ==/UserScript==
(function () {
"use strict";
// 配置
const UPDATE_INTERVAL = 60000 * 5; // 每 5 分钟更新一次
const DISPLAY_MODES = [
{
name: "TOTAL_TOKENS",
displayName: "总token",
iconColor: "#4CAF50",
darkColor: "#88E388",
lightColor: "#2D882D",
},
{
name: "LOW_EFFORT",
displayName: "低努力 (1点)",
iconColor: "#2196F3",
darkColor: "#90CAF9",
lightColor: "#0D47A1",
},
{
name: "HIGH_EFFORT",
displayName: "高努力 (4点)",
iconColor: "#FF9800",
darkColor: "#FFCC80",
lightColor: "#E65100",
},
{
name: "WINDOW_TIME",
displayName: "重置时间",
iconColor: "#9C27B0",
darkColor: "#CE93D8",
lightColor: "#6A1B9A",
},
];
let updateTimer = null; // 存储更新定时器
let lastFetchTime = 0; // 跟踪最后获取时间
let currentData = null; // 存储当前数据
let limitsPopup = null; // 存储弹出窗口元素
let isDarkMode = true; // 默认暗模式,将被检测
let isPinned = false; // 跟踪弹出窗口是否固定
let buttonElement = null; // 存储按钮元素引用
let hideTimeout = null; // 用于延迟隐藏的定时器
// 辅助函数:检测颜色模式
function detectColorMode() {
// 检查 body 或 html 是否有暗背景
const bodyBg = window.getComputedStyle(document.body).backgroundColor;
const htmlBg = window.getComputedStyle(
document.documentElement
).backgroundColor;
// 将 RGB 转换为亮度
function getBrightness(color) {
// 提取 RGB 值
const rgb = color.match(/\d+/g);
if (!rgb) return 255; // 如果无法确定,默认亮模式
// 计算亮度(简单近似)
return (
(parseInt(rgb[0]) * 299 +
parseInt(rgb[1]) * 587 +
parseInt(rgb[2]) * 114) /
1000
);
}
const bodyBrightness = getBrightness(bodyBg);
const htmlBrightness = getBrightness(htmlBg);
// 如果 body 或 html 有暗背景,则视为暗模式
const brightness = Math.min(bodyBrightness, htmlBrightness);
return brightness < 128; // 低于 128 视为暗模式
}
// 设置外部点击监听器
function setupOutsideClickListener() {
document.addEventListener("click", (event) => {
if (!isPinned) return;
// 检查点击是否在弹出窗口外部
if (limitsPopup && !limitsPopup.contains(event.target)) {
// 检查是否点击了按钮
if (buttonElement && !buttonElement.contains(event.target)) {
isPinned = false;
hideLimitsPopup();
}
}
});
}
// 查找侧边栏的合适容器
function findSidebarContainer() {
// 尝试多个选择器以找到侧边栏菜单容器
const selectors = [
// 查找侧边栏内容区域
'[data-sidebar="content"]',
// 查找侧边栏菜单组
'[data-sidebar="group"]',
// 查找具有侧边栏菜单的 ul 元素
'[data-sidebar="menu"]',
// 回退选项
'.flex.min-h-0.flex-col.overflow-auto'
];
for (const selector of selectors) {
const container = document.querySelector(selector);
if (container) {
console.log(`找到侧边栏容器,选择器:${selector}`);
return container;
}
}
return null;
}
// 创建侧边栏菜单项
function createSidebarButton() {
let attempts = 0;
const maxAttempts = 20;
const interval = setInterval(() => {
attempts++;
if (attempts >= maxAttempts) {
clearInterval(interval);
console.error('无法找到速率限制按钮的合适侧边栏容器');
return;
}
const sidebarContent = findSidebarContainer();
if (sidebarContent) {
clearInterval(interval);
// 更新暗模式检测
isDarkMode = detectColorMode();
// 创建菜单组容器
const menuGroup = document.createElement("div");
menuGroup.setAttribute("data-sidebar", "group");
menuGroup.className = "relative flex w-full min-w-0 flex-col px-1.5 py-[2px] shrink-0 transition-[width,transform,opacity] duration-200";
// 创建菜单列表
const menuList = document.createElement("ul");
menuList.setAttribute("data-sidebar", "menu");
menuList.className = "flex w-full min-w-0 flex-col cursor-default";
// 创建菜单项
const menuItem = document.createElement("li");
menuItem.setAttribute("data-sidebar", "menu-item");
menuItem.className = "group/menu-item whitespace-nowrap font-semibold mx-1 relative";
// 创建按钮元素 (模仿其他菜单项的结构)
buttonElement = document.createElement("div");
buttonElement.id = "rate-limits-button";
buttonElement.setAttribute("role", "button");
buttonElement.setAttribute("tabindex", "0");
buttonElement.setAttribute("aria-label", "速率限制");
buttonElement.className = "peer/menu-button flex items-center gap-2 overflow-hidden rounded-xl text-left outline-none ring-sidebar-ring transition-[width,height,padding] focus-visible:ring-1 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 [&>span:last-child]:truncate [&>svg]:shrink-0 text-sm h-[36px] border-transparent data-[state=open]:hover:bg-button-ghost-hover data-[active=true]:bg-button-ghost-active aria-expanded:bg-button-ghost-hover hover:bg-transparent active:bg-transparent cursor-default hover:text-fg-secondary w-full flex flex-row justify-start gap-1 bg-background text-secondary text-sm rounded-xl p-[0.375rem] border-transparent cursor-pointer hover:text-primary hover:!bg-button-ghost-hover";
buttonElement.setAttribute("data-sidebar", "menu-button");
buttonElement.setAttribute("data-active", "false");
buttonElement.setAttribute("data-state", "closed");
// 创建图标容器
const iconContainer = document.createElement("div");
iconContainer.setAttribute("data-sidebar", "icon");
iconContainer.className = "size-6 flex items-center justify-center shrink-0";
// 创建 SVG 图标
iconContainer.innerHTML = `
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="stroke-[2]">
<path d="M12 6V12L16 14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.63604 5.63603C7.5 3.77207 10.125 2.5 13 2.5C18.6944 2.5 23.25 7.05558 23.25 12.75C23.25 18.4444 18.6944 23 13 23C7.30558 23 2.75 18.4444 2.75 12.75C2.75 11 3.125 9.36907 3.75 8" stroke="currentColor" stroke-linecap="round"/>
</svg>
`;
// 创建文本标签和token状态指示器
const textContainer = document.createElement("div");
textContainer.className = "flex items-center gap-2 flex-1";
const textLabel = document.createElement("span");
textLabel.style.opacity = "1";
textLabel.textContent = "速率限制";
const tokenBadge = document.createElement("span");
tokenBadge.id = "token-badge";
tokenBadge.className = "px-1.5 py-0.5 text-xs rounded-full font-medium";
tokenBadge.style.cssText = `
background-color: ${isDarkMode ? "rgba(76, 175, 80, 0.2)" : "rgba(76, 175, 80, 0.1)"};
color: ${isDarkMode ? "#88E388" : "#2D882D"};
min-width: 28px;
text-align: center;
`;
tokenBadge.textContent = "—";
textContainer.appendChild(textLabel);
textContainer.appendChild(tokenBadge);
// 组装按钮
buttonElement.appendChild(iconContainer);
buttonElement.appendChild(textContainer);
// 组装菜单结构
menuItem.appendChild(buttonElement);
menuList.appendChild(menuItem);
menuGroup.appendChild(menuList);
// 将菜单组添加到侧边栏内容的合适位置
// 查找最后一个菜单组,在其后插入
const existingGroups = sidebarContent.querySelectorAll('[data-sidebar="group"]');
if (existingGroups.length > 0) {
const lastGroup = existingGroups[existingGroups.length - 1];
lastGroup.insertAdjacentElement('afterend', menuGroup);
} else {
sidebarContent.appendChild(menuGroup);
}
// 添加点击事件处理程序
buttonElement.addEventListener("click", (e) => {
e.stopPropagation();
if (
!limitsPopup ||
getComputedStyle(limitsPopup).display === "none"
) {
showLimitsPopup(e);
isPinned = true;
} else if (isPinned) {
isPinned = false;
hideLimitsPopup();
} else {
isPinned = true;
}
});
// 添加悬停事件
buttonElement.addEventListener("mouseenter", (e) => {
if (!isPinned) {
clearTimeout(hideTimeout);
showLimitsPopup(e);
}
});
buttonElement.addEventListener("mouseleave", (e) => {
if (!isPinned) {
hideTimeout = setTimeout(() => {
hideLimitsPopup();
}, 200); // 延迟 200ms 隐藏,以允许鼠标移动到弹出窗口
}
});
// 设置主题变化观察器
const observer = new MutationObserver((mutations) => {
const newDarkMode = detectColorMode();
if (newDarkMode !== isDarkMode) {
isDarkMode = newDarkMode;
if (limitsPopup) {
updatePopupTheme();
}
updateTokenBadge();
}
});
observer.observe(document.body, {
attributes: true,
childList: false,
subtree: false,
});
// 设置外部点击监听器
setupOutsideClickListener();
console.log('速率限制按钮已成功添加到侧边栏');
// 初始获取数据
fetchRateLimit();
return buttonElement;
}
}, 500);
}
// 更新token徽章
function updateTokenBadge() {
const tokenBadge = document.getElementById("token-badge");
if (!tokenBadge || !currentData) return;
const remaining = currentData.remainingTokens || 0;
const total = currentData.totalTokens || 140;
tokenBadge.textContent = remaining.toString();
// 根据剩余比例更新颜色
const percentage = total > 0 ? remaining / total : 0;
let bgColor, textColor;
if (percentage <= 0.2) {
// 低 - 红色
bgColor = isDarkMode ? "rgba(255, 50, 50, 0.2)" : "rgba(255, 50, 50, 0.1)";
textColor = isDarkMode ? "#FF8A80" : "#C62828";
} else if (percentage <= 0.5) {
// 中等 - 橙色
bgColor = isDarkMode ? "rgba(255, 150, 0, 0.2)" : "rgba(255, 150, 0, 0.1)";
textColor = isDarkMode ? "#FFCC80" : "#E65100";
} else {
// 良好 - 绿色
bgColor = isDarkMode ? "rgba(76, 175, 80, 0.2)" : "rgba(76, 175, 80, 0.1)";
textColor = isDarkMode ? "#88E388" : "#2D882D";
}
tokenBadge.style.backgroundColor = bgColor;
tokenBadge.style.color = textColor;
}
// 根据暗/亮模式更新弹出窗口主题
function updatePopupTheme() {
if (!limitsPopup) return;
if (isDarkMode) {
limitsPopup.style.backgroundColor = "rgba(28, 30, 33, 0.95)";
limitsPopup.style.color = "#e0e0e0";
limitsPopup.style.border = "1px solid rgba(255, 255, 255, 0.1)";
limitsPopup.style.boxShadow = "0 3px 20px rgba(0, 0, 0, 0.5)";
} else {
limitsPopup.style.backgroundColor = "rgba(250, 250, 250, 0.95)";
limitsPopup.style.color = "#333333";
limitsPopup.style.border = "1px solid rgba(0, 0, 0, 0.1)";
limitsPopup.style.boxShadow = "0 3px 20px rgba(0, 0, 0, 0.15)";
}
// 更新显示项
DISPLAY_MODES.forEach((mode) => {
const indicator = document.getElementById(
`${mode.name.toLowerCase()}-indicator`
);
const label = document.getElementById(`${mode.name.toLowerCase()}-label`);
const value = document.getElementById(`${mode.name.toLowerCase()}-value`);
if (indicator && label && value) {
indicator.style.backgroundColor = mode.iconColor;
label.style.color = isDarkMode ? "#ffffff" : "#333333";
value.style.color = isDarkMode ? mode.darkColor : mode.lightColor;
}
});
// 更新分隔线
const divider = document.querySelector("#limit-monitor .divider");
if (divider) {
divider.style.borderBottomColor = isDarkMode
? "rgba(255, 255, 255, 0.15)"
: "rgba(0, 0, 0, 0.1)";
}
// 更新刷新按钮
const refreshBtn = document.querySelector("#limit-monitor .refresh-btn");
if (refreshBtn) {
refreshBtn.style.color = isDarkMode ? "#ffffff" : "#333333";
refreshBtn.style.backgroundColor = isDarkMode
? "rgba(255, 255, 255, 0.1)"
: "rgba(0, 0, 0, 0.05)";
}
}
// 创建并显示限制弹出窗口,带动画
function showLimitsPopup(event) {
if (limitsPopup) {
// 根据按钮动态更新位置
const buttonRect = buttonElement.getBoundingClientRect();
limitsPopup.style.left = `${buttonRect.right + 8}px`; // 按钮右侧 8px
limitsPopup.style.top = `${buttonRect.top}px`;
limitsPopup.style.right = 'auto';
limitsPopup.style.opacity = "1";
limitsPopup.style.transform = "translateX(0) scale(1)";
limitsPopup.style.display = "block";
return;
}
// 更新暗模式检测
isDarkMode = detectColorMode();
limitsPopup = document.createElement("div");
limitsPopup.id = "limit-monitor";
limitsPopup.style.cssText = `
position: fixed;
background-color: ${
isDarkMode
? "rgba(28, 30, 33, 0.95)"
: "rgba(250, 250, 250, 0.95)"
};
border-radius: 12px;
padding: 16px;
color: ${isDarkMode ? "#e0e0e0" : "#333333"};
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Arial, sans-serif;
font-size: 14px;
z-index: 10000;
box-shadow: ${
isDarkMode
? "0 3px 20px rgba(0, 0, 0, 0.5)"
: "0 3px 20px rgba(0, 0, 0, 0.15)"
};
min-width: 280px;
user-select: none;
border: 1px solid ${
isDarkMode ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.1)"
};
transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
transform: translateX(-10px) scale(0.98);
opacity: 0;
backdrop-filter: blur(8px);
`;
// 根据按钮设置初始位置 (侧边栏按钮的右侧)
const buttonRect = buttonElement.getBoundingClientRect();
limitsPopup.style.left = `${buttonRect.right + 8}px`;
limitsPopup.style.top = `${buttonRect.top}px`;
limitsPopup.style.right = 'auto';
// 创建带有标题和刷新按钮的头部
const header = document.createElement("div");
header.style.cssText = `
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
`;
const title = document.createElement("div");
title.style.cssText = `
font-weight: 600;
font-size: 15px;
letter-spacing: 0.3px;
display: flex;
align-items: center;
gap: 8px;
`;
// 为标题添加图标
title.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 6V12L16 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.63604 5.63603C7.5 3.77207 10.125 2.5 13 2.5C18.6944 2.5 23.25 7.05558 23.25 12.75C23.25 18.4444 18.6944 23 13 23C7.30558 23 2.75 18.4444 2.75 12.75C2.75 11 3.125 9.36907 3.75 8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
Token使用情况
`;
header.appendChild(title);
// 添加刷新按钮
const refreshBtn = document.createElement("button");
refreshBtn.className = "refresh-btn";
refreshBtn.title = "刷新限制";
refreshBtn.style.cssText = `
background: ${
isDarkMode ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)"
};
border: none;
border-radius: 6px;
color: ${isDarkMode ? "#ffffff" : "#333333"};
cursor: pointer;
font-size: 16px;
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
padding: 0;
`;
refreshBtn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 12C4 7.58172 7.58172 4 12 4C15.0796 4 17.7429 5.73685 19 8.27323L19 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M20 12C20 16.4183 16.4183 20 12 20C8.92038 20 6.25708 18.2632 5 15.7268L5 20" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
`;
refreshBtn.onmouseover = () => {
refreshBtn.style.background = isDarkMode
? "rgba(255, 255, 255, 0.2)"
: "rgba(0, 0, 0, 0.1)";
refreshBtn.style.transform = "rotate(30deg)";
};
refreshBtn.onmouseout = () => {
refreshBtn.style.background = isDarkMode
? "rgba(255, 255, 255, 0.1)"
: "rgba(0, 0, 0, 0.05)";
refreshBtn.style.transform = "rotate(0deg)";
};
refreshBtn.onclick = (e) => {
e.stopPropagation();
// 点击时添加旋转动画
refreshBtn.style.transition =
"transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)";
refreshBtn.style.transform = "rotate(360deg)";
// 动画结束后重置
setTimeout(() => {
refreshBtn.style.transition = "all 0.2s ease";
refreshBtn.style.transform = "rotate(0deg)";
}, 500);
fetchRateLimit();
};
header.appendChild(refreshBtn);
limitsPopup.appendChild(header);
// 添加分隔线
const divider = document.createElement("div");
divider.className = "divider";
divider.style.cssText = `
border-bottom: 1px solid ${
isDarkMode ? "rgba(255, 255, 255, 0.15)" : "rgba(0, 0, 0, 0.1)"
};
margin-bottom: 12px;
`;
limitsPopup.appendChild(divider);
// 创建显示项的容器
const itemsContainer = document.createElement("div");
itemsContainer.style.cssText = `
display: flex;
flex-direction: column;
gap: 12px;
`;
// 为每个显示项创建元素,带现代样式
DISPLAY_MODES.forEach((mode) => {
const itemDiv = document.createElement("div");
itemDiv.style.cssText = `
display: flex;
align-items: center;
gap: 12px;
`;
// 添加颜色指示器
const indicator = document.createElement("div");
indicator.id = `${mode.name.toLowerCase()}-indicator`;
indicator.style.cssText = `
width: 8px;
height: 8px;
border-radius: 50%;
background-color: ${mode.iconColor};
flex-shrink: 0;
`;
itemDiv.appendChild(indicator);
// 添加标签
const itemLabel = document.createElement("span");
itemLabel.id = `${mode.name.toLowerCase()}-label`;
itemLabel.textContent = mode.displayName;
itemLabel.style.cssText = `
font-weight: 500;
color: ${isDarkMode ? "#ffffff" : "#333333"};
flex-grow: 1;
`;
itemDiv.appendChild(itemLabel);
// 添加值,带药丸样式
const itemValue = document.createElement("div");
itemValue.style.cssText = `
padding: 4px 10px;
border-radius: 12px;
background-color: ${
isDarkMode
? "rgba(255, 255, 255, 0.1)"
: "rgba(0, 0, 0, 0.05)"
};
font-weight: 600;
font-size: 13px;
min-width: 70px;
text-align: center;
transition: all 0.3s ease;
`;
const valueText = document.createElement("span");
valueText.id = `${mode.name.toLowerCase()}-value`;
valueText.textContent = "—";
valueText.style.cssText = `
color: ${isDarkMode ? mode.darkColor : mode.lightColor};
transition: color 0.3s ease;
`;
itemValue.appendChild(valueText);
itemDiv.appendChild(itemValue);
itemsContainer.appendChild(itemDiv);
});
limitsPopup.appendChild(itemsContainer);
document.body.appendChild(limitsPopup);
// 添加鼠标事件
limitsPopup.addEventListener("mouseenter", () => {
if (!isPinned) {
clearTimeout(hideTimeout);
clearTimeout(limitsPopup.hideTimeout);
}
});
limitsPopup.addEventListener("mouseleave", (e) => {
if (!isPinned) {
hideTimeout = setTimeout(() => {
hideLimitsPopup();
}, 200); // 延迟 200ms 隐藏
}
});
// 附加后触发动画
setTimeout(() => {
limitsPopup.style.opacity = "1";
limitsPopup.style.transform = "translateX(0) scale(1)";
}, 10);
// 获取初始数据
fetchRateLimit();
}
// 隐藏限制弹出窗口,带动画
function hideLimitsPopup() {
if (limitsPopup) {
limitsPopup.style.opacity = "0";
limitsPopup.style.transform = "translateX(-10px) scale(0.98)";
limitsPopup.hideTimeout = setTimeout(() => {
limitsPopup.style.display = "none";
}, 250);
}
}
// 将秒格式化为可读时间字符串
function formatTime(seconds) {
if (seconds < 60) {
return `${seconds}s`;
} else if (seconds < 3600) {
return `${Math.floor(seconds / 60)}m`;
} else {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
}
}
// 获取速率限制数据
async function fetchRateLimit() {
try {
// 为显示项添加加载效果
DISPLAY_MODES.forEach((mode) => {
const element = document.getElementById(`${mode.name.toLowerCase()}-value`);
if (element) {
element.textContent = "···";
// 脉冲动画
const parent = element.parentElement;
if (parent) {
parent.style.animation = "pulse 1.5s infinite";
parent.style.animationTimingFunction = "ease-in-out";
}
}
});
const response = await fetch("https://grok.com/rest/rate-limits", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
requestKind: "DEFAULT",
modelName: "grok-3", // 默认使用grok-3,但新接口应该返回统一数据
}),
});
if (!response.ok) {
throw new Error(`HTTP 错误!状态: ${response.status}`);
}
const data = await response.json();
lastFetchTime = Date.now();
currentData = data;
updateAllDisplays(data);
updateTokenBadge();
return data;
} catch (error) {
console.error(`获取速率限制出错:`, error);
// 显示错误状态
DISPLAY_MODES.forEach((mode) => {
const element = document.getElementById(`${mode.name.toLowerCase()}-value`);
if (element) {
element.textContent = "错误";
const parent = element.parentElement;
if (parent) {
parent.style.animation = "none";
parent.style.backgroundColor = isDarkMode
? "rgba(255, 50, 50, 0.2)"
: "rgba(255, 50, 50, 0.1)";
setTimeout(() => {
parent.style.backgroundColor = isDarkMode
? "rgba(255, 255, 255, 0.1)"
: "rgba(0, 0, 0, 0.05)";
}, 1000);
}
}
});
}
}
// 更新所有显示项
function updateAllDisplays(data) {
if (!data) return;
// 更新总token
const totalElement = document.getElementById("total_tokens-value");
if (totalElement) {
const remaining = data.remainingTokens || 0;
const total = data.totalTokens || 140;
totalElement.textContent = `${remaining}/${total}`;
// 根据剩余比例设置背景色
const percentage = total > 0 ? remaining / total : 0;
const parent = totalElement.parentElement;
if (parent) {
parent.style.animation = "none";
if (percentage <= 0.2) {
parent.style.backgroundColor = isDarkMode ? "rgba(255, 50, 50, 0.2)" : "rgba(255, 50, 50, 0.1)";
} else if (percentage <= 0.5) {
parent.style.backgroundColor = isDarkMode ? "rgba(255, 150, 0, 0.2)" : "rgba(255, 150, 0, 0.1)";
} else {
parent.style.backgroundColor = isDarkMode ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)";
}
}
}
// 更新低努力
const lowEffortElement = document.getElementById("low_effort-value");
if (lowEffortElement && data.lowEffortRateLimits) {
const remaining = data.lowEffortRateLimits.remainingQueries || 0;
lowEffortElement.textContent = `${remaining}次`;
const parent = lowEffortElement.parentElement;
if (parent) {
parent.style.animation = "none";
parent.style.backgroundColor = isDarkMode ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)";
}
}
// 更新高努力
const highEffortElement = document.getElementById("high_effort-value");
if (highEffortElement && data.highEffortRateLimits) {
const remaining = data.highEffortRateLimits.remainingQueries || 0;
highEffortElement.textContent = `${remaining}次`;
const parent = highEffortElement.parentElement;
if (parent) {
parent.style.animation = "none";
parent.style.backgroundColor = isDarkMode ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)";
}
}
// 更新窗口时间
const windowElement = document.getElementById("window_time-value");
if (windowElement) {
const windowSize = data.windowSizeSeconds || 7200; // 默认2小时
windowElement.textContent = formatTime(windowSize);
const parent = windowElement.parentElement;
if (parent) {
parent.style.animation = "none";
parent.style.backgroundColor = isDarkMode ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)";
}
}
// 添加视觉反馈
DISPLAY_MODES.forEach((mode) => {
const element = document.getElementById(`${mode.name.toLowerCase()}-value`);
if (element) {
const pulseColor = isDarkMode ? "#FFFFFF" : "#000000";
element.style.color = pulseColor;
setTimeout(() => {
element.style.color = isDarkMode ? mode.darkColor : mode.lightColor;
}, 300);
}
});
}
// 调度定期更新
function scheduleUpdates() {
// 清除任何现有定时器
if (updateTimer) {
clearInterval(updateTimer);
}
// 设置新定时器
updateTimer = setInterval(() => {
// 如果固定或弹出窗口可见,则获取数据
if (
isPinned ||
(limitsPopup && getComputedStyle(limitsPopup).display !== "none")
) {
fetchRateLimit();
}
}, UPDATE_INTERVAL);
}
// 拦截 fetch 以监视网站中的速率限制请求
function interceptFetch() {
const originalFetch = window.fetch;
window.fetch = async function (input, init) {
const response = await originalFetch(input, init);
// 克隆响应以避免消耗它
const responseClone = response.clone();
try {
// 检查这是否是速率限制请求
if (input && input.toString().includes("rate-limits")) {
responseClone
.json()
.then((data) => {
console.log("速率限制响应:", data);
currentData = data;
lastFetchTime = Date.now();
// 如果弹出窗口存在,则更新显示
if (limitsPopup) {
updateAllDisplays(data);
}
// 更新token徽章
updateTokenBadge();
// 重置定时器
if (updateTimer) {
clearInterval(updateTimer);
updateTimer = setInterval(() => {
if (
isPinned ||
(limitsPopup &&
getComputedStyle(limitsPopup).display !== "none")
) {
fetchRateLimit();
}
}, UPDATE_INTERVAL);
}
})
.catch((e) => {
console.error("解析响应出错:", e);
});
}
} catch (e) {
console.error("fetch 拦截器出错:", e);
}
return response;
};
}
// 将 CSS 动画添加到文档
function addStyles() {
const styleElement = document.createElement("style");
styleElement.textContent = `
@keyframes pulse {
0% { opacity: 0.7; }
50% { opacity: 1; }
100% { opacity: 0.7; }
}
`;
document.head.appendChild(styleElement);
}
// 初始化
function init() {
// 添加所需样式
addStyles();
// 创建侧边栏按钮
createSidebarButton();
// 调度更新
scheduleUpdates();
// 拦截 fetch 请求
interceptFetch();
}
// 当页面完全加载时启动脚本
if (document.readyState === 'loading') {
window.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();









