|
| 1 | +// ==UserScript== |
| 2 | +// @name 4ndr0tools - Instagram++ |
| 3 | +// @namespace https://github.com/4ndr0666/userscripts |
| 4 | +// @author 4ndr0666 |
| 5 | +// @license UNLICENSED - RED TEAM USE ONLY |
| 6 | +// @version 1.0.0 |
| 7 | +// @description Entire profile media is DOM-orchestrated with memory sanitation and saves your scrolling spot. |
| 8 | +// @icon https://raw.githubusercontent.com/4ndr0666/4ndr0site/refs/heads/main/static/cyanglassarch.png |
| 9 | +// @match *://*.instagram.com/* |
| 10 | +// @grant none |
| 11 | +// @run-at document-start |
| 12 | +// @downloadURL https://github.com/4ndr0666/userscripts/raw/refs/heads/main/4ndr0tools%20-%20Instagram++.user.js |
| 13 | +// @updateURL https://github.com/4ndr0666/userscripts/raw/refs/heads/main/4ndr0tools%20-%20Instagram++.user.js |
| 14 | +// ==/UserScript== |
| 15 | + |
| 16 | +(function() { |
| 17 | + 'use strict'; |
| 18 | + |
| 19 | + // Configuration for the Virtual Cache |
| 20 | + const CACHE_LIMIT = 50; // Maximum number of media elements to keep in DOM |
| 21 | + const IMAGES_PER_QUERY = 12; |
| 22 | + const VID_VOLUME = 0.02; |
| 23 | + const HEIGHT_PCT = 0.8; |
| 24 | + const WIDTH_PCT = 0.49; |
| 25 | + |
| 26 | + let mediaBuffer = []; // Tracking array for DOM elements |
| 27 | + let MODE = 'profile'; |
| 28 | + let userId = window.userId; |
| 29 | + let notLoaded = true; |
| 30 | + const tempDiv = document.createElement('div'); |
| 31 | + const win = window; |
| 32 | + |
| 33 | + // Trusted Types Policy for modern browser security |
| 34 | + if (win.trustedTypes && win.trustedTypes.createPolicy) { |
| 35 | + win.trustedTypes.createPolicy('default', { |
| 36 | + createHTML: (str) => str |
| 37 | + }); |
| 38 | + } |
| 39 | + |
| 40 | + /** |
| 41 | + * CORE OPTIMIZATION: DOM Virtualization/Pruning |
| 42 | + * This function monitors the number of media items in the DOM. |
| 43 | + * When the limit is reached, it removes the oldest items to free up memory (I/O). |
| 44 | + * To prevent losing position, we replace removed items with a placeholder |
| 45 | + * that maintains the height of the original content. |
| 46 | + */ |
| 47 | + function pruneCache() { |
| 48 | + const container = document.querySelector('#igAllImages'); |
| 49 | + if (!container) return; |
| 50 | + |
| 51 | + // While we exceed the cache limit, remove the oldest (first) elements |
| 52 | + while (mediaBuffer.length > CACHE_LIMIT) { |
| 53 | + const oldItem = mediaBuffer.shift(); |
| 54 | + if (oldItem && oldItem.parentNode) { |
| 55 | + // Get height before removal to prevent layout shift |
| 56 | + const rect = oldItem.getBoundingClientRect(); |
| 57 | + const placeholder = document.createElement('div'); |
| 58 | + placeholder.style.height = `${rect.height}px`; |
| 59 | + placeholder.className = 'media-placeholder'; |
| 60 | + |
| 61 | + oldItem.parentNode.replaceChild(placeholder, oldItem); |
| 62 | + console.log('Cache Pruned: Removed element to prevent crash.'); |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + function addMedia(media, container) { |
| 68 | + let shortcode = media?.shortcode || media?.code; |
| 69 | + let medias = media?.edge_sidecar_to_children?.edges?.map(n => n.node) || |
| 70 | + media?.carousel_media || |
| 71 | + [media]; |
| 72 | + |
| 73 | + for (let i = 0; i < medias.length; i++) { |
| 74 | + let m = medias[i]; |
| 75 | + let wrapper = document.createElement('div'); |
| 76 | + wrapper.className = 'media-wrapper'; |
| 77 | + wrapper.style.display = 'inline-block'; |
| 78 | + |
| 79 | + let a = document.createElement('a'); |
| 80 | + a.href = `https://www.instagram.com/p/${shortcode}/`; |
| 81 | + let un = media?.user?.username || media?.owner?.username; |
| 82 | + let caption = media?.caption?.text || media?.edge_media_to_caption?.edges?.[0]?.node?.text; |
| 83 | + a.title = `${media?.user?.full_name || ''} (${un}) ${caption} [${i + 1}]`; |
| 84 | + |
| 85 | + if (m?.is_video || m?.is_unified_video || m?.video_duration) { |
| 86 | + let vidDiv = document.createElement('div'); |
| 87 | + vidDiv.className = 'vidDiv'; |
| 88 | + let vid = document.createElement('video'); |
| 89 | + vid.src = m?.video_url || m?.video_versions?.reduce((a, b) => Math.max(a.width, a.height) > Math.max(b.width, b.height) ? a : b)?.url; |
| 90 | + vid.controls = true; |
| 91 | + vid.volume = VID_VOLUME; |
| 92 | + vid.loading = "lazy"; // Native browser optimization |
| 93 | + |
| 94 | + a.textContent = 'Link'; |
| 95 | + vidDiv.appendChild(vid); |
| 96 | + vidDiv.appendChild(a); |
| 97 | + wrapper.appendChild(vidDiv); |
| 98 | + } else if (m?.ad_id || m?.label === 'Sponsored') { |
| 99 | + continue; |
| 100 | + } else { |
| 101 | + let img = document.createElement('img'); |
| 102 | + img.src = getBestImage(m); |
| 103 | + img.loading = "lazy"; // Native browser optimization |
| 104 | + a.appendChild(img); |
| 105 | + wrapper.appendChild(a); |
| 106 | + } |
| 107 | + |
| 108 | + container.appendChild(wrapper); |
| 109 | + mediaBuffer.push(wrapper); // Add to our cache tracker |
| 110 | + pruneCache(); // Check if we need to dump old media |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + // --- RE-IMPLEMENTING NECESSARY HELPERS FROM YOUR SCRIPT --- |
| 115 | + |
| 116 | + function getBestImage(media) { |
| 117 | + let bestUrl = null; |
| 118 | + let bestSize = 0; |
| 119 | + let list = media?.display_resources || media?.image_versions2?.candidates; |
| 120 | + if (!list) return ''; |
| 121 | + for (let m of list) { |
| 122 | + let w = m?.width || m?.config_width || 0; |
| 123 | + let h = m?.height || m?.config_height || 0; |
| 124 | + let size = Math.max(w, h); |
| 125 | + if (size > bestSize) { |
| 126 | + bestSize = size; |
| 127 | + bestUrl = m?.url || m?.src; |
| 128 | + } |
| 129 | + } |
| 130 | + return bestUrl; |
| 131 | + } |
| 132 | + |
| 133 | + function loadImages(query_id = 0, query_hash = 0, doc_id = 0, app_id = 936619743392459, asbd_id = 129477, after = null) { |
| 134 | + notLoaded = false; |
| 135 | + app_id = app_id || 936619743392459; |
| 136 | + asbd_id = asbd_id || 129477; |
| 137 | + |
| 138 | + let imageListQueryUrl; |
| 139 | + let init = { responseType: 'json', credentials: 'include', referrerPolicy: 'no-referrer' }; |
| 140 | + |
| 141 | + if (MODE === 'profile') { |
| 142 | + if (!userId) return; |
| 143 | + imageListQueryUrl = `https://i.instagram.com/api/v1/feed/user/${userId}/?count=12${after ? `&max_id=${after}` : ''}`; |
| 144 | + init.headers = { |
| 145 | + 'X-IG-App-ID': app_id, |
| 146 | + 'X-ASBD-ID': asbd_id, |
| 147 | + 'X-CSRFToken': win._sharedData?.config?.csrf_token |
| 148 | + }; |
| 149 | + } |
| 150 | + |
| 151 | + fetch(imageListQueryUrl, init) |
| 152 | + .then(resp => resp.json()) |
| 153 | + .then(json => { |
| 154 | + let timelineMedia = json.data?.user.edge_owner_to_timeline_media; |
| 155 | + let end_cursor = timelineMedia?.page_info.end_cursor || json.next_max_id; |
| 156 | + let mediaList = timelineMedia?.edges.map(n => n.node) || json.items || json.feed_items?.map(n => n.media_or_ad).filter(n => n); |
| 157 | + |
| 158 | + let bigContainer = document.querySelector('#igBigContainer'); |
| 159 | + if (!bigContainer) { |
| 160 | + document.body.innerHTML = '<div id="igBigContainer" style="background:#112;width:100%;height:100%;z-index:999;position:fixed;top:0;left:0;overflow:scroll;"><div id="igAllImages" style="display:block;text-align:center;"></div></div>'; |
| 161 | + bigContainer = document.querySelector('#igBigContainer'); |
| 162 | + styleIt(); |
| 163 | + } |
| 164 | + |
| 165 | + const innerContainer = document.querySelector('#igAllImages'); |
| 166 | + for (let media of mediaList) { |
| 167 | + addMedia(media, innerContainer); |
| 168 | + } |
| 169 | + |
| 170 | + if (end_cursor) { |
| 171 | + bigContainer.onscroll = () => { |
| 172 | + if (bigContainer.scrollHeight - bigContainer.scrollTop - bigContainer.clientHeight < 1000) { |
| 173 | + bigContainer.onscroll = null; |
| 174 | + loadImages(query_id, query_hash, doc_id, app_id, asbd_id, end_cursor); |
| 175 | + } |
| 176 | + }; |
| 177 | + } |
| 178 | + }); |
| 179 | + } |
| 180 | + |
| 181 | + function styleIt() { |
| 182 | + let style = document.createElement('style'); |
| 183 | + style.innerHTML = ` |
| 184 | + #igAllImages img, #igAllImages video { |
| 185 | + max-height: 80vh; |
| 186 | + max-width: 45vw; |
| 187 | + margin: 10px; |
| 188 | + border: 1px solid #333; |
| 189 | + } |
| 190 | + .vidDiv { border: 2px solid green; display: inline-block; } |
| 191 | + .media-placeholder { |
| 192 | + background: #1a1a2e; |
| 193 | + margin: 10px; |
| 194 | + display: inline-block; |
| 195 | + width: 40vw; |
| 196 | + } |
| 197 | + `; |
| 198 | + document.body.appendChild(style); |
| 199 | + } |
| 200 | + |
| 201 | + function pickMode() { |
| 202 | + if (document.location.href.includes('/tagged/')) MODE = 'tagged'; |
| 203 | + else MODE = 'profile'; |
| 204 | + |
| 205 | + userId = userId || document.body.innerHTML.match(/profilePage_(\d+)/)?.[1]; |
| 206 | + if (userId) loadImages(); |
| 207 | + else console.error("User ID not found."); |
| 208 | + } |
| 209 | + |
| 210 | + // Initialize the "Load" button |
| 211 | + const btn = document.createElement('button'); |
| 212 | + btn.innerText = "FORCE LOAD CACHE-SAFE"; |
| 213 | + btn.style = "position:fixed;top:10px;right:10px;z-index:10000;padding:10px;background:red;color:white;border:none;cursor:pointer;"; |
| 214 | + btn.onclick = pickMode; |
| 215 | + document.body.appendChild(btn); |
| 216 | + |
| 217 | +})(); |
0 commit comments