Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name xAI Console Tools (Reset + 2K Toggle + JPEG Save)
- // @namespace http://tampermonkey.net/
- // @version 2.1
- // @description Reset button, optional 2K forcing, and JPEG download for xAI Console
- // @match https://console.x.ai/playground/imagine*
- // @match https://console.x.ai/team/*/imagine*
- // @grant none
- // @run-at document-start
- // ==/UserScript==
- (function () {
- 'use strict';
- const TAG = '[xAI Console Tools]';
- const PANEL_ID = 'xai-tools-panel';
- const RESET_BTN_ID = 'xai-reset-btn';
- const TOGGLE_BTN_ID = 'xai-2k-toggle-btn';
- const GAP_PX = 8;
- const JPEG_QUALITY = 0.95;
- const FORCE_2K_KEY = 'gc_force2k_v1';
- const BYPASS_ATTR = 'data-xai-jpeg-bypass';
- function log(msg, type = 'log') {
- const fn =
- type === 'error' ? console.error :
- type === 'warn' ? console.warn :
- console.log;
- fn(`${TAG} ${msg}`);
- }
- function isVisible(el) {
- if (!(el instanceof Element)) return false;
- const style = getComputedStyle(el);
- if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
- return false;
- }
- const rect = el.getBoundingClientRect();
- return rect.width > 0 && rect.height > 0;
- }
- function getText(el) {
- if (!(el instanceof Element)) return '';
- return [
- el.textContent || '',
- el.getAttribute('aria-label') || '',
- el.getAttribute('title') || ''
- ].join(' ').replace(/\s+/g, ' ').trim().toLowerCase();
- }
- function isForce2kEnabled() {
- try {
- return localStorage.getItem(FORCE_2K_KEY) === '1';
- } catch {
- return false;
- }
- }
- function setForce2kEnabled(enabled) {
- try {
- localStorage.setItem(FORCE_2K_KEY, enabled ? '1' : '0');
- } catch {}
- }
- function modifyPayload(originalBody) {
- try {
- const body = JSON.parse(originalBody);
- body.resolution = '2k';
- log('resolution -> 2k', 'warn');
- return JSON.stringify(body);
- } catch (e) {
- log(`modify payload error: ${e.message}`, 'error');
- return originalBody;
- }
- }
- function isImageApiUrl(url) {
- try {
- const u = new URL(url, location.href);
- return /^\/v1\/images(?:\/|$)/.test(u.pathname);
- } catch {
- return typeof url === 'string' && url.includes('/v1/images');
- }
- }
- const nativeFetch = window.fetch.bind(window);
- window.fetch = async function (input, init) {
- let nextInput = input;
- let nextInit = init;
- try {
- if (!isForce2kEnabled()) {
- return nativeFetch(input, init);
- }
- const isReq = input instanceof Request;
- const url = isReq ? input.url : String(input || '');
- const method = ((init && init.method) || (isReq ? input.method : 'GET') || 'GET').toUpperCase();
- if (method === 'POST' && isImageApiUrl(url)) {
- if (typeof init?.body === 'string') {
- nextInit = { ...init, body: modifyPayload(init.body) };
- } else if (isReq && !init) {
- const cloned = input.clone();
- const textBody = await cloned.text();
- const patchedBody = modifyPayload(textBody);
- if (patchedBody !== textBody) {
- nextInput = new Request(input, { body: patchedBody });
- }
- }
- }
- } catch (e) {
- log(`fetch interception error: ${e.message}`, 'error');
- }
- return nativeFetch(nextInput, nextInit);
- };
- function resetLimit() {
- log('Запуск сброса (images + video + credits)', 'warn');
- const lsPatterns = [
- /flushAfter/i,
- /imagine/i,
- /generation/i,
- /grok-imagine/i,
- /mixpanel|mp_/i,
- /distinct_id|device_id/i,
- /_rst|_r/i,
- /event|payload/i,
- /quota|limit|usage|count|reset/i,
- /video|vid|vidgen|grok-imagine-video/i,
- /request_type/i,
- /credit|credits|demand|highdemand|purchase|balance|high demand/i
- ];
- for (let i = localStorage.length - 1; i >= 0; i--) {
- const key = localStorage.key(i);
- if (key && lsPatterns.some(p => p.test(key))) {
- localStorage.removeItem(key);
- console.log('[LS удалён]:', key);
- }
- }
- for (let i = sessionStorage.length - 1; i >= 0; i--) {
- const key = sessionStorage.key(i);
- if (key && lsPatterns.some(p => p.test(key))) {
- sessionStorage.removeItem(key);
- console.log('[Session удалён]:', key);
- }
- }
- const cookiePatterns = [
- 'mp_', 'mixpanel', 'distinct_id', 'device_id',
- 'xai_', 'imagine', 'console', 'grok', '_rst', '_r',
- 'video', 'vid', 'credit', 'demand', 'high', 'purchase', 'balance'
- ];
- document.cookie.split(';').forEach(c => {
- const name = c.split('=')[0]?.trim();
- if (!name) return;
- if (cookiePatterns.some(p => name.toLowerCase().includes(p.toLowerCase()))) {
- ['.x.ai', 'console.x.ai', '.console.x.ai', ''].forEach(d => {
- ['/', '/playground', '/playground/imagine', '/team', ''].forEach(p => {
- document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=${p}${d ? ';domain=' + d : ''}`;
- });
- });
- console.log('[Cookie удалена]:', name);
- }
- });
- const u = new URL(location.href);
- const now = Date.now();
- u.searchParams.set('_r', now);
- u.searchParams.set('_rst', now);
- u.searchParams.set('_rstv', now);
- u.searchParams.set('_vidrst', now);
- location.replace(u.toString());
- }
- function makeBaseButton() {
- const btn = document.createElement('button');
- btn.type = 'button';
- btn.className =
- 'inline-flex items-center justify-center gap-x-2 rounded-full ' +
- 'text-sm font-medium transition-colors focus-visible:outline-none ' +
- 'focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none ' +
- 'disabled:opacity-50 border border-input text-primary ' +
- 'hover:border-primary/15 shadow-sm hover:bg-overlay-hover ' +
- 'h-9 px-4 py-2 bg-surface-l1 pointer-events-auto';
- btn.style.margin = '0';
- btn.style.pointerEvents = 'auto';
- btn.style.transition = 'opacity 0.15s ease, transform 0.12s ease, background-color 0.15s ease, box-shadow 0.15s ease';
- return btn;
- }
- function update2kButton() {
- const btn = document.getElementById(TOGGLE_BTN_ID);
- if (!btn) return;
- const enabled = isForce2kEnabled();
- btn.innerHTML = `<span class="min-w-[78px]">${enabled ? '2K: ON' : '2K: OFF'}</span>`;
- if (enabled) {
- btn.style.background = 'rgba(255, 204, 0, 0.08)';
- btn.style.boxShadow = 'inset 0 0 0 1px rgba(255, 204, 0, 0.35)';
- } else {
- btn.style.background = '';
- btn.style.boxShadow = '';
- }
- }
- function createPanel() {
- if (!document.body || document.getElementById(PANEL_ID)) return;
- const panel = document.createElement('div');
- panel.id = PANEL_ID;
- panel.style.position = 'fixed';
- panel.style.display = 'flex';
- panel.style.gap = `${GAP_PX}px`;
- panel.style.alignItems = 'center';
- panel.style.zIndex = '9999';
- panel.style.opacity = '0';
- panel.style.pointerEvents = 'auto';
- panel.style.transition = 'opacity 0.15s ease';
- panel.style.left = '16px';
- panel.style.top = '16px';
- const toggleBtn = makeBaseButton();
- toggleBtn.id = TOGGLE_BTN_ID;
- toggleBtn.title = 'Включить или выключить форсирование 2K';
- toggleBtn.style.minWidth = '110px';
- toggleBtn.addEventListener('click', () => {
- const next = !isForce2kEnabled();
- setForce2kEnabled(next);
- update2kButton();
- positionPanel();
- log(`2K forcing ${next ? 'enabled' : 'disabled'}`, 'warn');
- });
- const resetBtn = makeBaseButton();
- resetBtn.id = RESET_BTN_ID;
- resetBtn.innerHTML = `
- <svg class="size-4 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
- <path d="M3 12a9 9 0 1 0 9-9 9 9 0 0 0-9 9Z"></path>
- <path d="m15 3-3 3 3 3"></path>
- </svg>
- <span class="min-w-[90px]">Сбросить лимит</span>
- `;
- resetBtn.addEventListener('click', resetLimit);
- panel.appendChild(toggleBtn);
- panel.appendChild(resetBtn);
- document.body.appendChild(panel);
- update2kButton();
- }
- function findToolbarAnchor() {
- return Array.from(document.querySelectorAll('button[aria-haspopup="menu"]')).find(el => {
- if (!isVisible(el)) return false;
- const span = el.querySelector('span');
- const chevron = el.querySelector('svg.lucide-chevrons-up-down');
- return span?.textContent?.trim() === 'Image' && chevron;
- });
- }
- function isViewerOpen() {
- const controls = Array.from(document.querySelectorAll('button, a, [role="button"]')).filter(el => {
- if (!isVisible(el)) return false;
- if (el.closest(`#${PANEL_ID}`)) return false;
- return true;
- });
- const hasDownload = controls.some(el => /\bdownload\b/.test(getText(el)));
- const hasEdit = controls.some(el => /\bedit\b/.test(getText(el)));
- return hasDownload && hasEdit;
- }
- function positionPanel() {
- const panel = document.getElementById(PANEL_ID);
- if (!panel) return;
- if (isViewerOpen()) {
- panel.style.opacity = '0';
- panel.style.pointerEvents = 'none';
- return;
- }
- const target = findToolbarAnchor();
- if (!target) {
- panel.style.opacity = '0';
- panel.style.pointerEvents = 'none';
- return;
- }
- const rect = target.getBoundingClientRect();
- const panelRect = panel.getBoundingClientRect();
- let left = rect.left - panelRect.width - GAP_PX;
- let top = rect.top + ((rect.height - panelRect.height) / 2);
- if (left < 16) left = 16;
- if (top < 12) top = 12;
- panel.style.left = `${left}px`;
- panel.style.top = `${top}px`;
- panel.style.opacity = '1';
- panel.style.pointerEvents = 'auto';
- }
- function scoreImage(img) {
- const rect = img.getBoundingClientRect();
- const w = img.naturalWidth || rect.width || 0;
- const h = img.naturalHeight || rect.height || 0;
- return w * h;
- }
- function isVariantImage(img) {
- if (!(img instanceof HTMLImageElement)) return false;
- if (!isVisible(img)) return false;
- const src = img.currentSrc || img.src || '';
- const alt = (img.alt || '').toLowerCase();
- if (!src) return false;
- const looksRelevant =
- src.startsWith('data:image/') ||
- src.startsWith('blob:') ||
- src.startsWith('http') ||
- alt.includes('variant');
- if (!looksRelevant) return false;
- const w = img.naturalWidth || img.width || 0;
- const h = img.naturalHeight || img.height || 0;
- return w >= 256 && h >= 256;
- }
- function findImageNearTrigger(trigger) {
- let node = trigger.closest('button, a, [role="button"]');
- for (let i = 0; i < 10 && node; i++, node = node.parentElement) {
- const imgs = Array.from(node.querySelectorAll('img')).filter(isVariantImage);
- if (imgs.length) {
- imgs.sort((a, b) => scoreImage(b) - scoreImage(a));
- return imgs[0];
- }
- }
- const all = Array.from(document.querySelectorAll('img')).filter(isVariantImage);
- all.sort((a, b) => scoreImage(b) - scoreImage(a));
- return all[0] || null;
- }
- function loadImage(src) {
- return new Promise((resolve, reject) => {
- const img = new Image();
- img.decoding = 'async';
- img.onload = () => resolve(img);
- img.onerror = () => reject(new Error('image load failed'));
- img.src = src;
- });
- }
- function canvasToBlob(canvas, type, quality) {
- return new Promise((resolve, reject) => {
- canvas.toBlob(blob => {
- if (blob) resolve(blob);
- else reject(new Error('canvas.toBlob failed'));
- }, type, quality);
- });
- }
- async function imageSrcToJpegBlob(src) {
- const img = await loadImage(src);
- const width = img.naturalWidth || img.width;
- const height = img.naturalHeight || img.height;
- if (!width || !height) {
- throw new Error('invalid image dimensions');
- }
- const canvas = document.createElement('canvas');
- canvas.width = width;
- canvas.height = height;
- const ctx = canvas.getContext('2d', { alpha: false });
- ctx.fillStyle = '#ffffff';
- ctx.fillRect(0, 0, width, height);
- ctx.drawImage(img, 0, 0);
- return await canvasToBlob(canvas, 'image/jpeg', JPEG_QUALITY);
- }
- function pad2(n) {
- return String(n).padStart(2, '0');
- }
- function makeTimestamp() {
- const d = new Date();
- return `${pad2(d.getDate())}.${pad2(d.getMonth() + 1)}.${d.getFullYear()} ${pad2(d.getHours())}-${pad2(d.getMinutes())}-${pad2(d.getSeconds())}`;
- }
- function sanitizePart(text) {
- return String(text || '')
- .replace(/[\\/:*?"<>|]+/g, ' ')
- .replace(/\s+/g, ' ')
- .trim();
- }
- function makeFilename(img) {
- return `Grok Console - ${makeTimestamp()}.jpg`;
- }
- function downloadBlob(blob, filename) {
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = filename;
- a.style.display = 'none';
- document.body.appendChild(a);
- a.click();
- a.remove();
- setTimeout(() => URL.revokeObjectURL(url), 30000);
- }
- function markBypass(el) {
- if (!(el instanceof Element)) return;
- el.setAttribute(BYPASS_ATTR, '1');
- setTimeout(() => {
- try {
- el.removeAttribute(BYPASS_ATTR);
- } catch {}
- }, 300);
- }
- function invokeOriginalDownload(trigger) {
- if (!(trigger instanceof HTMLElement)) return;
- markBypass(trigger);
- trigger.click();
- }
- function isDownloadTrigger(el) {
- if (!(el instanceof Element)) return false;
- const trigger = el.closest('button, a, [role="button"]');
- if (!trigger) return false;
- if (trigger.getAttribute(BYPASS_ATTR) === '1') return false;
- if (trigger.id === RESET_BTN_ID || trigger.id === TOGGLE_BTN_ID) return false;
- if (trigger.closest(`#${PANEL_ID}`)) return false;
- const text = getText(trigger);
- return /\bdownload\b|\bsave\b/.test(text);
- }
- function installDownloadInterceptor() {
- document.addEventListener('click', async (event) => {
- const target = event.target;
- if (!(target instanceof Element)) return;
- if (!isDownloadTrigger(target)) return;
- const trigger = target.closest('button, a, [role="button"]');
- if (!trigger) return;
- const img = findImageNearTrigger(trigger);
- if (!img) {
- log('download clicked, but image not found; fallback to native', 'warn');
- return;
- }
- const src = img.currentSrc || img.src || '';
- if (!src) {
- log('image src empty; fallback to native', 'warn');
- return;
- }
- event.preventDefault();
- event.stopPropagation();
- if (typeof event.stopImmediatePropagation === 'function') {
- event.stopImmediatePropagation();
- }
- try {
- const jpegBlob = await imageSrcToJpegBlob(src);
- const filename = makeFilename(img);
- downloadBlob(jpegBlob, filename);
- log(`saved as jpeg: ${filename}`);
- } catch (e) {
- log(`jpeg conversion failed, fallback to native: ${e.message}`, 'error');
- invokeOriginalDownload(trigger);
- }
- }, true);
- }
- function initUi() {
- createPanel();
- positionPanel();
- const mo = new MutationObserver(() => {
- createPanel();
- positionPanel();
- });
- mo.observe(document.documentElement, {
- childList: true,
- subtree: true,
- attributes: true,
- attributeFilter: ['class', 'style', 'hidden', 'data-state', 'aria-hidden']
- });
- const throttled = (() => {
- let raf = 0;
- return () => {
- cancelAnimationFrame(raf);
- raf = requestAnimationFrame(positionPanel);
- };
- })();
- window.addEventListener('resize', throttled);
- window.addEventListener('scroll', throttled, { passive: true });
- setTimeout(positionPanel, 150);
- setTimeout(positionPanel, 500);
- setTimeout(positionPanel, 1200);
- }
- installDownloadInterceptor();
- if (document.readyState !== 'loading') {
- initUi();
- } else {
- document.addEventListener('DOMContentLoaded', initUi, { once: true });
- }
- log(`ready; 2K forcing is ${isForce2kEnabled() ? 'ON' : 'OFF'}`, 'warn');
- })();
Advertisement