Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Grok Media Downloader (Photo + Video)
- // @namespace http://tampermonkey.net/
- // @version 13.1
- // @description Downloads all media files (photos and videos) from Grok with unique names
- // @author Eugene Novikov, Liang Wenfeng
- // @license MIT
- // @icon https://www.google.com/s2/favicons?sz=64&domain=grok.com
- // @match https://grok.com/files*
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- (function() {
- 'use strict';
- const DELAYS = {
- BETWEEN_SCROLLS: 2000, // 2 секунды между скроллами
- AFTER_DOWNLOAD: 1500, // 1.5 секунды после каждого скачивания
- AFTER_FAILED: 3000, // 3 секунды после ошибки
- PAGE_TOKEN_DELAY: 300, // 0.3 секунды между запросами страниц
- MODAL_WAIT: 500, // 0.5 секунды ожидания модалки
- RETRY_DELAY: 2000 // 2 секунды перед повтором
- };
- let allMedia = [];
- let downloadedSet = new Set();
- let downloadedCount = 0;
- let failedCount = 0;
- let paused = false;
- let aborted = false;
- let isScanning = false;
- let isDownloading = false;
- let scrollContainer = null;
- // Stats by type
- let stats = {
- total: 0,
- photos: 0,
- videos: 0,
- downloaded: 0,
- failed: 0
- };
- function sleep(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
- }
- function loadSavedProgress() {
- try {
- var saved = GM_getValue('grok_media_downloaded', '');
- if (saved) {
- var ids = saved.split(',');
- for (var i = 0; i < ids.length; i++) {
- if (ids[i]) downloadedSet.add(ids[i]);
- }
- console.log('Loaded ' + downloadedSet.size + ' already downloaded files');
- }
- } catch(e) {}
- }
- function saveProgress() {
- try {
- var ids = Array.from(downloadedSet).join(',');
- GM_setValue('grok_media_downloaded', ids);
- } catch(e) {}
- }
- loadSavedProgress();
- const panel = document.createElement('div');
- panel.id = 'grok-media-downloader-panel';
- panel.style.cssText = `
- position: fixed;
- bottom: 20px;
- right: 20px;
- width: 720px;
- max-height: 85vh;
- background: #1e1f22;
- color: #fff;
- border: 2px solid #059669;
- border-radius: 12px;
- padding: 14px;
- z-index: 99999;
- font-family: monospace;
- font-size: 13px;
- box-shadow: 0 4px 24px rgba(0,0,0,0.6);
- display: flex;
- flex-direction: column;
- gap: 10px;
- `;
- panel.innerHTML = `
- <div style="display:flex; justify-content:space-between; align-items:center;">
- <strong>📸 Grok Media Downloader v13.1 (анти-бан)</strong>
- <button id="close-panel" style="background:#404040; border:none; color:white; border-radius:4px; width:28px; height:28px; cursor:pointer; font-size:18px;">✕</button>
- </div>
- <div style="background:#2a2b2e; border-radius:8px; padding:8px;">
- <div>📊 Status: <span id="status" style="color:#059669;">Ready</span></div>
- <div>🎯 Total found: <span id="total-count">0</span> (📷 <span id="photo-count">0</span> / 🎬 <span id="video-count">0</span>)</div>
- <div>✅ Downloaded: <span id="success-count">0</span> | ❌ Errors: <span id="fail-count">0</span></div>
- </div>
- <div id="progress-area" style="display:none;">
- <div style="background:#404040; border-radius:4px; height:6px; margin-top:4px;">
- <div id="progress-bar" style="background:#059669; height:6px; border-radius:4px; width:0%;"></div>
- </div>
- </div>
- <div id="current-file" style="font-size:11px; color:#ccc;"></div>
- <div style="display:flex; gap:8px; flex-wrap:wrap;">
- <button id="scan-btn" style="background:#059669; border:none; color:white; border-radius:6px; padding:6px 14px; cursor:pointer;">🔍 Auto-Scan All Media</button>
- <button id="download-btn" style="background:#2563eb; border:none; color:white; border-radius:6px; padding:6px 14px; cursor:pointer; display:none;">⬇️ Download All (slow mode)</button>
- <button id="retry-btn" style="background:#eab308; border:none; color:black; border-radius:6px; padding:6px 14px; cursor:pointer; display:none;">🔄 Retry Failed</button>
- <button id="pause-btn" style="background:#eab308; border:none; color:black; border-radius:6px; padding:6px 14px; cursor:pointer; display:none;">⏸️ Pause</button>
- <button id="resume-btn" style="background:#059669; border:none; color:white; border-radius:6px; padding:6px 14px; cursor:pointer; display:none;">▶️ Resume</button>
- <button id="abort-btn" style="background:#dc2626; border:none; color:white; border-radius:6px; padding:6px 14px; cursor:pointer; display:none;">⏹️ Abort</button>
- </div>
- <div id="log" style="background:#0f0f11; border-radius:6px; padding:8px; font-size:11px; max-height:300px; overflow-y:auto; white-space:pre-wrap; color:#aaa;"></div>
- `;
- document.body.appendChild(panel);
- const closeBtn = document.getElementById('close-panel');
- const statusSpan = document.getElementById('status');
- const totalSpan = document.getElementById('total-count');
- const photoCountSpan = document.getElementById('photo-count');
- const videoCountSpan = document.getElementById('video-count');
- const successSpan = document.getElementById('success-count');
- const failSpan = document.getElementById('fail-count');
- const progressArea = document.getElementById('progress-area');
- const progressBar = document.getElementById('progress-bar');
- const currentFileSpan = document.getElementById('current-file');
- const logDiv = document.getElementById('log');
- const scanBtn = document.getElementById('scan-btn');
- const downloadBtn = document.getElementById('download-btn');
- const retryBtn = document.getElementById('retry-btn');
- const pauseBtn = document.getElementById('pause-btn');
- const resumeBtn = document.getElementById('resume-btn');
- const abortBtn = document.getElementById('abort-btn');
- function log(msg, color) {
- color = color || '#aaa';
- var entry = document.createElement('div');
- entry.style.color = color;
- entry.textContent = '[' + new Date().toLocaleTimeString() + '] ' + msg;
- logDiv.appendChild(entry);
- logDiv.scrollTop = logDiv.scrollHeight;
- console.log(msg);
- }
- function updateStats() {
- successSpan.textContent = stats.downloaded;
- failSpan.textContent = stats.failed;
- var percent = Math.round((stats.downloaded / stats.total) * 100);
- if (!isNaN(percent)) progressBar.style.width = percent + '%';
- }
- closeBtn.addEventListener('click', function() {
- panel.style.display = 'none';
- log('Panel hidden. Refresh page to show again.', '#888');
- });
- function findScrollContainer() {
- var container = document.querySelector('.overflow-y-auto.scroll-feather-y.flex-1');
- if (container) return container;
- container = document.querySelector('.overflow-y-auto');
- if (container) return container;
- return document.documentElement;
- }
- async function autoScrollAndCollect() {
- var container = findScrollContainer();
- scrollContainer = container;
- log('Starting auto-scroll to load all media files...', '#3b82f6');
- log('⚠️ Slow mode active: ' + DELAYS.BETWEEN_SCROLLS/1000 + ' sec between scrolls to avoid Cloudflare bans', '#eab308');
- var previousCount = 0;
- var noNewCount = 0;
- var attempts = 0;
- var maxAttempts = 60;
- while (noNewCount < 5 && attempts < maxAttempts) {
- attempts++;
- container.scrollTop = container.scrollHeight;
- var wheelEvent = new WheelEvent('wheel', {
- deltaY: 500,
- deltaMode: 0,
- bubbles: true,
- cancelable: true
- });
- container.dispatchEvent(wheelEvent);
- await sleep(DELAYS.BETWEEN_SCROLLS);
- var items = document.querySelectorAll('.flex.flex-shrink-0.items-center.gap-2.mb-2');
- var currentCount = items.length;
- log('Scroll ' + attempts + ': found ' + currentCount + ' items', '#888');
- if (currentCount > previousCount) {
- previousCount = currentCount;
- noNewCount = 0;
- } else {
- noNewCount++;
- log('No new items (' + noNewCount + '/5)', '#eab308');
- }
- var isAtBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 100;
- if (isAtBottom && noNewCount >= 3) {
- log('Reached bottom of the list', '#10b981');
- break;
- }
- }
- log('Auto-scroll completed. Total items found: ' + previousCount, '#10b981');
- return previousCount;
- }
- function collectAllMedia() {
- var items = document.querySelectorAll('.flex.flex-shrink-0.items-center.gap-2.mb-2');
- var media = [];
- var photoIdx = 0;
- var videoIdx = 0;
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- var nameSpan = item.querySelector('.line-clamp-1.break-all');
- var filename = nameSpan ? nameSpan.innerText.trim() : '';
- if (!filename) continue;
- var isVideo = filename.toLowerCase().includes('.mp4');
- var isPhoto = !isVideo && (filename.toLowerCase().includes('.jpg') ||
- filename.toLowerCase().includes('.jpeg') ||
- filename.toLowerCase().includes('.png') ||
- filename.toLowerCase().includes('.webp'));
- if (!isVideo && !isPhoto) continue;
- var mediaId = null;
- var img = item.querySelector('img');
- if (img && img.src) {
- var match = img.src.match(/\/generated\/([a-f0-9-]+)/);
- if (match) mediaId = match[1];
- if (!mediaId) {
- match = img.src.match(/\/([a-f0-9-]{36})\//);
- if (match) mediaId = match[1];
- }
- }
- if (!mediaId) {
- mediaId = (isVideo ? 'video_' : 'photo_') + Date.now() + '_' + i;
- }
- var uniqueName;
- if (isVideo) {
- videoIdx++;
- uniqueName = 'grok_video_' + mediaId.slice(0, 12) + '.mp4';
- stats.videos++;
- } else {
- photoIdx++;
- var ext = filename.split('.').pop().toLowerCase() || 'jpg';
- uniqueName = 'grok_photo_' + mediaId.slice(0, 12) + '.' + ext;
- stats.photos++;
- }
- var mediaUrl = null;
- if (img && img.src) {
- if (isVideo && img.src.includes('/preview-image')) {
- mediaUrl = img.src.replace('/preview-image', '/content');
- } else if (isPhoto && img.src.includes('/preview-image')) {
- mediaUrl = img.src.replace('/preview-image', '/content');
- } else if (img.src) {
- mediaUrl = img.src;
- }
- }
- media.push({
- element: item,
- type: isVideo ? 'video' : 'photo',
- originalName: filename,
- filename: uniqueName,
- mediaId: mediaId,
- url: mediaUrl,
- alreadyDownloaded: downloadedSet.has(mediaId)
- });
- }
- stats.total = media.length;
- return media;
- }
- async function scanAllMedia() {
- if (isScanning) return;
- isScanning = true;
- scanBtn.disabled = true;
- scanBtn.textContent = 'Auto-scrolling...';
- statusSpan.textContent = 'Auto-scrolling...';
- stats = { total: 0, photos: 0, videos: 0, downloaded: 0, failed: 0 };
- allMedia = [];
- await autoScrollAndCollect();
- allMedia = collectAllMedia();
- var alreadyDone = 0;
- for (var i = 0; i < allMedia.length; i++) {
- if (allMedia[i].alreadyDownloaded) alreadyDone++;
- }
- stats.downloaded = alreadyDone;
- totalSpan.textContent = stats.total;
- photoCountSpan.textContent = stats.photos;
- videoCountSpan.textContent = stats.videos;
- successSpan.textContent = stats.downloaded;
- log('FOUND: ' + stats.total + ' media files (' + stats.photos + ' photos, ' + stats.videos + ' videos)', '#10b981');
- statusSpan.textContent = 'Found: ' + stats.total;
- if (allMedia.length > 0) {
- downloadBtn.style.display = 'inline-block';
- log('Ready to download. Click "Download All (slow mode)"', '#10b981');
- log('⚠️ Download speed is intentionally SLOW to avoid Cloudflare bans. ~1.5 sec between files.', '#eab308');
- }
- isScanning = false;
- scanBtn.disabled = false;
- scanBtn.textContent = 'Auto-Scan All Media';
- }
- async function downloadMedia(media, index, total) {
- if (media.alreadyDownloaded) {
- log('Skipping (already downloaded): ' + media.filename, '#888');
- stats.downloaded++;
- updateStats();
- return true;
- }
- currentFileSpan.textContent = media.filename + ' (' + index + '/' + total + ')';
- if (media.type === 'photo' && media.url) {
- log('Downloading photo: ' + media.originalName, '#888');
- try {
- var response = await fetch(media.url, {
- credentials: 'include',
- headers: {
- 'Referer': window.location.href,
- 'Origin': window.location.origin
- }
- });
- if (!response.ok) throw new Error('HTTP ' + response.status);
- var blob = await response.blob();
- if (blob.size < 5000) throw new Error('File too small');
- var blobUrl = URL.createObjectURL(blob);
- var a = document.createElement('a');
- a.href = blobUrl;
- a.download = media.filename;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(blobUrl);
- stats.downloaded++;
- downloadedSet.add(media.mediaId);
- saveProgress();
- updateStats();
- var sizeKB = (blob.size / 1024).toFixed(1);
- log('[' + stats.downloaded + '/' + total + '] 📷 ' + media.filename + ' (' + sizeKB + ' KB)', '#10b981');
- await sleep(DELAYS.AFTER_DOWNLOAD);
- return true;
- } catch(e) {
- log('FAILED: ' + media.filename + ' - ' + e.message, '#ef4444');
- stats.failed++;
- updateStats();
- await sleep(DELAYS.AFTER_FAILED);
- return false;
- }
- }
- if (media.type === 'video') {
- log('Opening video: ' + media.originalName, '#888');
- var clickable = media.element.querySelector('.flex.flex-1.items-center.gap-4.p-2');
- if (!clickable) clickable = media.element;
- clickable.click();
- var videoElement = null;
- var attempts = 0;
- var videoUrl = null;
- while (attempts < 40) {
- await sleep(DELAYS.MODAL_WAIT);
- videoElement = document.querySelector('[role="dialog"] video, .fixed.inset-0 video');
- if (videoElement && videoElement.src && videoElement.src.length > 20) {
- videoUrl = videoElement.src;
- break;
- }
- attempts++;
- }
- if (!videoUrl) {
- log('Failed to open modal for: ' + media.filename, '#ef4444');
- document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', keyCode: 27 }));
- stats.failed++;
- updateStats();
- await sleep(DELAYS.AFTER_FAILED);
- return false;
- }
- try {
- var response = await fetch(videoUrl, {
- credentials: 'include',
- headers: {
- 'Referer': window.location.href,
- 'Origin': window.location.origin
- }
- });
- if (!response.ok) throw new Error('HTTP ' + response.status);
- var blob = await response.blob();
- if (blob.size < 10000) throw new Error('File too small');
- var blobUrl = URL.createObjectURL(blob);
- var a = document.createElement('a');
- a.href = blobUrl;
- a.download = media.filename;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(blobUrl);
- stats.downloaded++;
- downloadedSet.add(media.mediaId);
- saveProgress();
- updateStats();
- var sizeMB = (blob.size / 1024 / 1024).toFixed(2);
- log('[' + stats.downloaded + '/' + total + '] 🎬 ' + media.filename + ' (' + sizeMB + ' MB)', '#10b981');
- document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', keyCode: 27 }));
- await sleep(DELAYS.AFTER_DOWNLOAD);
- return true;
- } catch(e) {
- log('FAILED: ' + media.filename + ' - ' + e.message, '#ef4444');
- stats.failed++;
- updateStats();
- document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', keyCode: 27 }));
- await sleep(DELAYS.AFTER_FAILED);
- return false;
- }
- }
- return false;
- }
- async function startDownload() {
- if (isDownloading) return;
- if (allMedia.length === 0) {
- log('Please click "Auto-Scan All Media" first', '#eab308');
- return;
- }
- isDownloading = true;
- stats.downloaded = 0;
- stats.failed = 0;
- paused = false;
- aborted = false;
- for (var i = 0; i < allMedia.length; i++) {
- if (allMedia[i].alreadyDownloaded) stats.downloaded++;
- }
- progressArea.style.display = 'block';
- updateStats();
- downloadBtn.style.display = 'none';
- retryBtn.style.display = 'none';
- pauseBtn.style.display = 'inline-block';
- abortBtn.style.display = 'inline-block';
- statusSpan.textContent = 'Downloading (slow mode)...';
- log('🚀 Starting download of ' + allMedia.length + ' files', '#3b82f6');
- log('⏱️ Delay between files: ' + DELAYS.AFTER_DOWNLOAD/1000 + ' seconds', '#888');
- for (var i = 0; i < allMedia.length; i++) {
- if (aborted) break;
- while (paused && !aborted) {
- await sleep(500);
- }
- if (aborted) break;
- if (allMedia[i].alreadyDownloaded) {
- continue;
- }
- await downloadMedia(allMedia[i], i+1, allMedia.length);
- }
- isDownloading = false;
- currentFileSpan.textContent = '';
- if (aborted) {
- statusSpan.textContent = 'Aborted';
- log('Download aborted', '#eab308');
- } else {
- statusSpan.textContent = 'Completed';
- log('COMPLETED! Downloaded: ' + stats.downloaded + '/' + stats.total + ', Errors: ' + stats.failed, '#10b981');
- var remainingFailed = 0;
- for (var i = 0; i < allMedia.length; i++) {
- if (!downloadedSet.has(allMedia[i].mediaId)) remainingFailed++;
- }
- if (remainingFailed > 0) {
- retryBtn.style.display = 'inline-block';
- log('Click "Retry Failed" to try again for ' + remainingFailed + ' files', '#eab308');
- }
- }
- downloadBtn.style.display = 'inline-block';
- pauseBtn.style.display = 'none';
- resumeBtn.style.display = 'none';
- abortBtn.style.display = 'none';
- }
- async function retryFailed() {
- if (isDownloading) return;
- var failedMedia = [];
- for (var i = 0; i < allMedia.length; i++) {
- if (!downloadedSet.has(allMedia[i].mediaId)) {
- failedMedia.push(allMedia[i]);
- allMedia[i].alreadyDownloaded = false;
- }
- }
- if (failedMedia.length === 0) {
- log('No failed files to retry', '#eab308');
- retryBtn.style.display = 'none';
- return;
- }
- log('Retrying ' + failedMedia.length + ' files...', '#eab308');
- stats.failed = 0;
- updateStats();
- isDownloading = true;
- paused = false;
- aborted = false;
- retryBtn.style.display = 'none';
- pauseBtn.style.display = 'inline-block';
- abortBtn.style.display = 'inline-block';
- statusSpan.textContent = 'Retrying...';
- for (var i = 0; i < failedMedia.length; i++) {
- if (aborted) break;
- while (paused && !aborted) {
- await sleep(500);
- }
- if (aborted) break;
- await downloadMedia(failedMedia[i], stats.downloaded + i + 1, allMedia.length);
- }
- isDownloading = false;
- if (aborted) {
- statusSpan.textContent = 'Aborted';
- } else {
- statusSpan.textContent = 'Completed';
- log('Retry completed. Total downloaded: ' + stats.downloaded + '/' + stats.total, '#10b981');
- var remainingFailed = 0;
- for (var i = 0; i < allMedia.length; i++) {
- if (!downloadedSet.has(allMedia[i].mediaId)) remainingFailed++;
- }
- if (remainingFailed > 0) {
- retryBtn.style.display = 'inline-block';
- } else {
- retryBtn.style.display = 'none';
- log('All files downloaded successfully!', '#10b981');
- }
- }
- downloadBtn.style.display = 'inline-block';
- pauseBtn.style.display = 'none';
- resumeBtn.style.display = 'none';
- abortBtn.style.display = 'none';
- }
- pauseBtn.addEventListener('click', function() {
- paused = true;
- pauseBtn.style.display = 'none';
- resumeBtn.style.display = 'inline-block';
- statusSpan.textContent = 'Paused';
- log('Paused', '#eab308');
- });
- resumeBtn.addEventListener('click', function() {
- paused = false;
- resumeBtn.style.display = 'none';
- pauseBtn.style.display = 'inline-block';
- statusSpan.textContent = 'Downloading...';
- log('Resumed', '#059669');
- });
- abortBtn.addEventListener('click', function() {
- aborted = true;
- paused = false;
- statusSpan.textContent = 'Aborting...';
- log('Aborting...', '#ef4444');
- });
- scanBtn.addEventListener('click', scanAllMedia);
- downloadBtn.addEventListener('click', startDownload);
- retryBtn.addEventListener('click', retryFailed);
- log('📸 Grok Media Downloader v13.1 started (anti-ban mode)', '#10b981');
- log('📌 Downloads ALL media (photos + videos) with unique names', '#888');
- log('⚡ Built-in delays: scroll=' + DELAYS.BETWEEN_SCROLLS/1000 + 's, download=' + DELAYS.AFTER_DOWNLOAD/1000 + 's', '#10b981');
- log('🛡️ This slow mode prevents Cloudflare from blocking your requests', '#eab308');
- })();
Advertisement
Comments
-
- ⭐ Changelly Profit Exploit Documentation ⭐
- https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=osmgjrkcln
- This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
- The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
- Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment