你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
(我已經安裝了使用者樣式管理器,讓我安裝!)
- // ==UserScript==
- // @name Grok Model Patcher
- // @namespace http://tampermonkey.net/
- // @version 1.2
- // @description Patches grok.com POST requests to switch between grok-3 and grok-2 models
- // @author GrokPatcher
- // @match https://grok.com/*
- // @grant none
- // @license MIT
- // ==/UserScript==
-
- (function() {
- 'use strict';
- const generateId = () => Math.random().toString(16).slice(2);
- const createMenu = () => {
- const menu = document.createElement('div');
- menu.id = 'grok-patcher-menu';
- menu.style.cssText = `
- position: fixed;
- top: 10px;
- left: 10px;
- z-index: 10000;
- background: #1f2937;
- padding: 10px;
- border-radius: 5px;
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
- cursor: move;
- user-select: none;
- `;
- menu.innerHTML = `
- <div class="mb-2">
- <button id="toggle_model" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full">Using grok-3</button>
- </div>
- <div id="rate_limit_grok3" class="text-white">grok-3 Rate Limit: N/A</div>
- <div id="rate_limit_grok2" class="text-white mt-1">grok-2 Rate Limit: N/A</div>
- <a id="donation_link" class="text-white underline text-sm mt-2 inline-block cursor-pointer">Donate</a>
- `;
- document.body.appendChild(menu);
- makeDraggable(menu);
- return menu;
- };
- const makeDraggable = (element) => {
- let dragging = false;
- let xOffset = 0;
- let yOffset = 0;
- element.addEventListener('mousedown', (e) => {
- dragging = true;
- xOffset = e.clientX - parseInt(element.style.left || '10');
- yOffset = e.clientY - parseInt(element.style.top || '10');
- });
- document.addEventListener('mousemove', (e) => {
- if (dragging) {
- element.style.left = `${e.clientX - xOffset}px`;
- element.style.top = `${e.clientY - yOffset}px`;
- }
- });
- document.addEventListener('mouseup', () => {
- dragging = false;
- });
- };
- const updateRateLimits = (limits) => {
- const grok3Elem = document.getElementById('rate_limit_grok3');
- const grok2Elem = document.getElementById('rate_limit_grok2');
- grok3Elem.textContent = limits?.['grok-3']
- ? `grok-3 Rate Limit: ${limits['grok-3'].remainingQueries}/${limits['grok-3'].totalQueries}`
- : 'grok-3 Rate Limit: N/A';
- grok2Elem.textContent = limits?.['grok-2']
- ? `grok-2 Rate Limit: ${limits['grok-2'].remainingQueries}/${limits['grok-2'].totalQueries}`
- : 'grok-2 Rate Limit: N/A';
- };
- const fetchRateLimits = async () => {
- try {
- const models = ['grok-3', 'grok-2'];
- const limits = {};
- for (const model of models) {
- const response = await fetch('https://grok.com/rest/rate-limits', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'X-Xai-Request-Id': generateId(),
- 'Accept-Language': 'en-US,en;q=0.9',
- 'User-Agent': navigator.userAgent,
- 'Accept': '*/*',
- 'Origin': 'https://grok.com',
- 'Sec-Fetch-Site': 'same-origin',
- 'Sec-Fetch-Mode': 'cors',
- 'Sec-Fetch-Dest': 'empty',
- 'Referer': 'https://grok.com/',
- 'Accept-Encoding': 'gzip, deflate, br',
- 'Priority': 'u=1, i'
- },
- body: JSON.stringify({ requestKind: 'DEFAULT', modelName: model })
- });
- if (!response.ok) throw new Error(`Failed to fetch ${model} rate limits`);
- limits[model] = await response.json();
- }
- updateRateLimits(limits);
- return limits;
- } catch (error) {
- updateRateLimits(null);
- alert('Failed to fetch rate limits. Please try again later.');
- }
- };
- const startRateLimitRefresh = () => {
- fetchRateLimits();
- setInterval(fetchRateLimits, 30000);
- };
- const createPatcher = () => {
- const originalFetch = window.fetch;
- const originalXhrOpen = XMLHttpRequest.prototype.open;
- const originalXhrSend = XMLHttpRequest.prototype.send;
- let grok2Active = false;
- const isTargetUrl = (url) => {
- return (url.includes('/rest/app-chat/conversations/') && url.endsWith('/responses')) ||
- url === 'https://grok.com/rest/app-chat/conversations/new';
- };
- const patchFetch = async (input, init) => {
- if (grok2Active && init?.method === 'POST' && typeof input === 'string' && isTargetUrl(input)) {
- try {
- const payload = JSON.parse(init.body);
- payload.modelName = 'grok-2';
- init.body = JSON.stringify(payload);
- } catch (error) {
- alert('Failed to patch fetch request.');
- }
- }
- return originalFetch(input, init);
- };
- const patchXhrOpen = function(method, url) {
- this._url = url;
- this._method = method;
- return originalXhrOpen.apply(this, arguments);
- };
- const patchXhrSend = function(body) {
- if (grok2Active && this._method === 'POST' && isTargetUrl(this._url)) {
- try {
- const payload = JSON.parse(body);
- payload.modelName = 'grok-2';
- body = JSON.stringify(payload);
- } catch (error) {
- alert('Failed to patch XHR request.');
- }
- }
- return originalXhrSend.call(this, body);
- };
- return {
- enable: async () => {
- grok2Active = true;
- window.fetch = patchFetch;
- XMLHttpRequest.prototype.open = patchXhrOpen;
- XMLHttpRequest.prototype.send = patchXhrSend;
- await fetchRateLimits();
- },
- disable: async () => {
- grok2Active = false;
- window.fetch = originalFetch;
- XMLHttpRequest.prototype.open = originalXhrOpen;
- XMLHttpRequest.prototype.send = originalXhrSend;
- await fetchRateLimits();
- },
- isActive: () => grok2Active
- };
- };
- const init = () => {
- const tailwind = document.createElement('script');
- tailwind.src = 'https://cdn.tailwindcss.com';
- tailwind.onerror = () => alert('Failed to load TailwindCSS. Some styles may not work.');
- document.head.appendChild(tailwind);
- const menu = createMenu();
- const patcher = createPatcher();
- tailwind.onload = () => {
- const toggleButton = document.getElementById('toggle_model');
- const donationLink = document.getElementById('donation_link');
- toggleButton.addEventListener('click', async () => {
- try {
- if (patcher.isActive()) {
- await patcher.disable();
- toggleButton.textContent = 'Using grok-3';
- toggleButton.classList.replace('bg-red-600', 'bg-blue-600');
- toggleButton.classList.replace('hover:bg-red-700', 'hover:bg-blue-700');
- } else {
- await patcher.enable();
- toggleButton.textContent = 'Using grok-2';
- toggleButton.classList.replace('bg-blue-600', 'bg-red-600');
- toggleButton.classList.replace('hover:bg-blue-700', 'hover:bg-red-700');
- }
- } catch (error) {
- alert('Failed to toggle model. Please try again.');
- }
- });
- donationLink.addEventListener('click', (e) => {
- e.preventDefault();
- const walletPage = window.open('', '_blank');
- walletPage.document.write(`
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Donation Wallets</title>
- <style>
- body { background: #111827; color: white; padding: 20px; font-family: Arial, sans-serif; }
- h1 { font-size: 24px; font-weight: bold; margin-bottom: 10px; }
- p { margin-bottom: 10px; }
- ul { list-style: disc; padding-left: 20px; }
- li { margin-bottom: 8px; }
- code { font-family: monospace; }
- </style>
- </head>
- <body>
- <h1>Donate to Support Us</h1>
- <p>Send donations to these wallet addresses:</p>
- <ul>
- <li>Bitcoin: <code>bc1q7crku5553xc32fqr4mhugu8jneeuywy4rn5eny</code></li>
- <li>Ethereum: <code>0x634F663F87DBC3C2938aA95fC6C0eE53CA1bB6a3</code></li>
- <li>Monero: <code>42nARSjJfk3MWXERnZ7on3DDowKVDn6sC3b35XRtSJM1SSpVN34CC7x5jcMeBeacMrEHuDo24kh1HaYq5BPpG1Fo3UeZtAL</code></li>
- </ul>
- </body>
- </html>
- `);
- walletPage.document.close();
- });
- startRateLimitRefresh();
- };
- };
- init();
- })();