Instagram full-size media scroll wall

Creates a scrollable wall of full-size images from any user's instagram page. Just click the "Load Images" button at the top.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Instagram full-size media scroll wall
// @author      deltabravozulu + driver8
// @description Creates a scrollable wall of full-size images from any user's instagram page. Just click the "Load Images" button at the top.
// @include     /^https?://www\.instagram\.com/[\s\S\w\W\d\D]+$/
// @exclude     https://www.instagram.com/p/*
// @exclude     https://instagram.com/p/*
// @exclude     https://www.instagram.com/
// @exclude     https://instagram.com/
// @version     0.2.0[deltabravozulu]
// @grant       none
// @namespace https://greasyfork.org/users/774364
// ==/UserScript==

//readd to user script later after generating feed wall
// @match       *://*.instagram.com/*


(function () {
	"use strict";

	console.log("hi insta scroll");
	// https://www.instagram.com/graphql/query/?query_hash=<hash>&variables={%22shortcode%22:%22<shortcode>%22}

	const IMAGES_PER_QUERY = 12;
	const NTH_TO_LAST_IMAGE = 3;
	const HEIGHT_PCT = 0.8;
	const WIDTH_PCT = 0.49;
	const VID_VOLUME = 0.02;
	let m = document.body.innerHTML.match(/profilePage_(\d+)/);
	var userId = m && m[1];
	var notLoaded = true;

	function getQueryHash() {
		let allScripts = Array.from(document.getElementsByTagName("script"));
		let PostPageContainer = allScripts.find(
			(el) => el.src && el.src.match(/ProfilePageContainer.js/)
		);
		let FeedPageContainer = allScripts.find(
			(el) => el.src && el.src.match(/FeedPageContainer.js/)
		);
		let ConsumerLibCommons = allScripts.find(
			(el) => el.src && el.src.match(/ConsumerLibCommons.js/)
		);
		let Consumer = allScripts.find(
			(el) => el.src && el.src.match(/Consumer.js/)
		);
		//NotificationLandingPage.js


		var query_hash = false,
			query_id = false;

		if (typeof ConsumerLibCommons !== "undefined") {
			console.log("ConsumerLibCommons is defined");
			fetch(ConsumerLibCommons.src)
				.then((resp) => {
					console.log("resp 1", resp);
					return resp.text();
				})
				.then((text) => {
					let m = text.match(
						/profilePosts\.byUserId\.get.*?queryId:"([a-f0-9]+)"/
						//profilePosts.byUserId.get(n))||void 0===s?void 0:s.pagination},queryId:"e5555555555555555555555555555508"
					); 
					console.log("queryId m", m);
					query_id = m && m[1];
					query_id && notLoaded && loadImages(query_id, query_hash);
					// query_id && query_hash && loadImages(query_id, query_hash);
				});
		}

		if (typeof PostPageContainer !== "undefined") {
			console.log("PostPageContainer is defined");

			fetch(PostPageContainer.src)
				.then((resp) => {
					console.log("resp 1", resp);
					return resp.text();
				})
				.then((text) => {
					let m = text.match(
						/profilePosts\.byUserId\.get.*?queryId:"([a-f0-9]+)"/
					); //profilePosts.byUserId.get(n))||void 0===s?void 0:s.pagination},queryId:"e5555555555555555555555555555508"
					console.log("queryId m", m);
					query_id = m && m[1];
					query_id && notLoaded && loadImages(query_id, query_hash);
					// query_id && query_hash && loadImages(query_id, query_hash);
				});
		}

		if (typeof FeedPageContainer !== "undefined") {
			console.log("FeedPageContainer is defined");
			fetch(FeedPageContainer.src)
				.then((resp) => {
					console.log("resp 1", resp);
					return resp.text();
				})
				.then((text) => {
					let m = text.match(
						/profilePosts\.byUserId\.get.*?queryId:"([a-f0-9]+)"/
					); //profilePosts.byUserId.get(n))||void 0===s?void 0:s.pagination},queryId:"e5555555555555555555555555555508"
					console.log("queryId m", m);
					query_id = m && m[1];
					query_id && notLoaded && loadImages(query_id, query_hash);
					// query_id && query_hash && loadImages(query_id, query_hash);
				});
		}

		// l.pagination},queryId:"15b55555555555555555555555555551"
		if (typeof Consumer !== "undefined") {
			console.log("Consumer is defined");
			fetch(Consumer.src)
				.then((resp) => {
					console.log("resp 1", resp);
					return resp.text();
				})
				.then((text) => {
					//let m = text.match(/l\.pagination\},queryId:"([a-f0-9]+)"/); //const s="05555555555555555555555555555554",E="
					let m = text.match(
						/profilePosts\.byUserId\.get[^;]+queryId:\s*"([a-f0-9]+)"/
					);
					console.log("queryId m", m);
					query_id = m && m[1];
					query_id && notLoaded && loadImages(query_id, query_hash);
				});
		}
	}

	//         fetch(Consumer.src)
	//         .then(resp => {
	//             console.log('resp 1', resp);
	//             return resp.text();
	//         })
	//         .then(text => {
	//             let m = text.match(/const s="([a-f0-9]+)",E="/); //const s="05555555555555555555555555555554",E="
	//             m = m || text.match(/var u="([a-f0-9]+)",s="/);
	//             console.log('query_hash m', m);
	//             query_hash = m && m[1];
	//             query_hash && query_id && loadImages(query_id, query_hash);
	//         });

	// https://www.instagram.com/graphql/query/?query_hash=<queryhash>&variables=%7B%22id%22%3A%22<profle_id>%22%2C%22first%22%3A12%2C%22after%22%3A%22<after_code>%3D%3D%22%7D
	function loadImages(query_id, query_hash, after) {
		notLoaded = false;
		console.log("id", query_id, "hash", query_hash);

		// let userIdMetaTag = document.querySelector('head > meta[property="instapp:owner_user_id"]');
		// let userId = userIdMetaTag && userIdMetaTag.content;
		let m = document.body.innerHTML.match(/profilePage_(\d+)/);
		userId = userId || (m && m[1]);
		if (!userId) return;
		let queryVariables = { id: userId, first: IMAGES_PER_QUERY };
		//et queryVariables = { "id":"123456789","first":12 };

		if (after) queryVariables.after = after;
		let queryVariablesString = encodeURIComponent(
			JSON.stringify(queryVariables)
		);
		let imageListQueryUrl = `https://www.instagram.com/graphql/query/?query_hash=${query_id}&variables=${queryVariablesString}`;

		fetch(imageListQueryUrl, { responseType: "json" })
			.then((resp) => {
				console.log("resp 1", resp);
				return resp.json();
			})
			.then((json) => {
				console.log("json", json);

				let timelineMedia = json.data.user.edge_owner_to_timeline_media;
				let end_cursor = timelineMedia.page_info.end_cursor;
				let mediaList = timelineMedia.edges.map((n) => n.node);
				console.log("media list", mediaList);

				let bigContainer = document.querySelector("#igBigContainer");
				// Create the main container if it doesn't exist
				if (!bigContainer) {
					let tempDiv = document.createElement("div");
					tempDiv.innerHTML = `<div id="igBigContainer" style="background-color: #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>`;
					bigContainer = tempDiv.firstElementChild;
					document.body.innerHTML = "";
					document.body.appendChild(bigContainer);

					let imgStyle = document.createElement("style");
					imgStyle.type = "text/css";
					setMaxSize(imgStyle);
					document.body.appendChild(imgStyle);
					window.addEventListener("resize", (evt) =>
						setMaxSize(imgStyle)
					);
					styleIt();
				}
				let innerContainer = bigContainer.firstElementChild;

				for (let media of mediaList) {
					addMedia(media, innerContainer);
				}

				if (end_cursor) {
					console.log("end_cursor", end_cursor);
					let triggerImage = document.querySelector(
						"#igAllImages a:nth-last-of-type(3)"
					);
					bigContainer.onscroll = (evt) => {
						let vh =
							document.documentElement.clientHeight ||
							window.innerHeight ||
							0;
						if (
							triggerImage.getBoundingClientRect().top - 800 <
							vh
						) {
							bigContainer.onscroll = null;
							console.log("loading next set of images");
							loadImages(query_id, query_hash, end_cursor);
						}
					};
				}
			});
	}

	function getBestImage(media) {
		return media.display_resources.reduce((a, b) =>
			a.width > b.width ? a : b
		).src;
	}

	function addMedia(media, container) {
		let shortcode = media.shortcode;
		let medias = media.edge_sidecar_to_children
			? media.edge_sidecar_to_children.edges.map((n) => n.node)
			: [media];
		for (let m of medias) {
			let a = document.createElement("a");
			a.href = `https://www.instagram.com/p/${shortcode}/`;
			if (m.is_video) {
				let vid = document.createElement("video");
				vid.src = m.video_url;
				vid.controls = true;
				vid.volume = VID_VOLUME;
				a.textContent = "Link";
				container.appendChild(vid);
				container.appendChild(a);
			} else {
				a.innerHTML += `<img src="${getBestImage(m)}">`;
				container.appendChild(a);
			}
		}
	}

	function setMaxSize(userStyle) {
		let vw = document.documentElement.clientWidth || window.innerWidth || 0;
		let vh =
			document.documentElement.clientHeight || window.innerHeight || 0;
		userStyle.innerHTML = `
#igAllImages img, #igAllImages video {
  max-height: ${vh * HEIGHT_PCT}px;
  max-width: ${vw * WIDTH_PCT}px;
}
`;
	}

	function styleIt() {
		let userStyle = document.createElement("style");
		userStyle.type = "text/css";
		userStyle.innerHTML = `
#igAllImages video {
  border: green solid 2px;
`;
		document.body.appendChild(userStyle);
	}

	function startUp() {
		"use strict";
		var svgImageWallBtn = `<img height="24" width="24" src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNDAwIDQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTc4LjcgMGMxMS45IDMuOCAxNS4zIDEyLjMgMTUuMyAyNC4zLS4zIDEwMi43LS4yIDIwNS41LS4yIDMwOC4yIDAgMTQuMi03LjQgMjEuNy0yMS41IDIxLjdoLTE1MC45Yy0xNCAwLTIxLjQtNy40LTIxLjQtMjEuNHYtMjQ1LjgtNC42aDEyLjd2MjE3LjhjMi0xLjUgMy41LTIuNCA0LjYtMy41IDI0LjktMjQuNiA0OS43LTQ5LjIgNzQuNi03My44IDExLjgtMTEuNiAyMy43LTIzLjEgMzUuNS0zNC44IDYuNi02LjUgOS42LTYuNiAxNi4zLjEgMTEuMSAxMSAyMi4yIDIyLjEgMzMuMiAzMy4zLjcuNyAxLjIgMS43IDIuOCAyIC4xLTEuMi4yLTIuNC4yLTMuNiAwLTY2IDAtMTMyIC4xLTE5OCAwLTcuMS0yLjEtOS4xLTkuMi05LjFoLTE0OC45Yy03IDAtOS4yIDIuMy05LjIgOS4zdjIyaC0xMi4yYy4yLTEwLjEtLjUtMjAuNC41LTMwLjQuNy03LjMgNi45LTExLjEgMTMuMy0xMy43em0xLjQgMjQ2LjJjLTE1LjctMTctMjkuOC0zMi40LTQ0LjEtNDcuOC00MS42IDQwLjktODIuMyA4MC45LTEyMy4yIDEyMS4xdjEzLjZjMCA1LjcgMi40IDguMyA4LjIgOC4zIDUwLjUuMSAxMDEuMSAwIDE1MS42IDAgNC44IDAgNy40LTIuNSA3LjQtNy4zLjItMzAuNC4xLTYwLjcuMS04Ny45em0zOSA4LjNjOS41IDEwLjggMTcuNCAxOS44IDI1LjMgMjguOCAxLjEtLjggMS41LTEuMSAxLjktMS40IDEzLTEyLjcgMjUuOS0yNS40IDM4LjktMzguMSAxOC44LTE4LjUgMzcuNi0zNy4xIDU2LjUtNTUuNyA0LjUtNC41IDguNi00LjUgMTMuMi4xIDEwLjMgMTAuMiAyMC41IDIwLjQgMzEuMyAzMS4xdi05MS4yaDEzLjh2MjUyYzAgMTEuNC04LjUgMTkuOC0xOS45IDE5LjhoLTE1NC44Yy0xMC44IDAtMTktOC4yLTE5LTE5di0zMTYuNWMwLTEwLjYgOC4yLTE4LjggMTguNy0xOC44aDE1NS4yYzExLjIgMCAxOS43IDguNSAxOS44IDE5LjYuMSA4LjEgMCAxNi4zIDAgMjQuNmgtMTMuN3YtMjIuOWMwLTYuMy0yLjItOC41LTguNi04LjVoLTE1MC4xYy01LjkgMC04LjYgMi4yLTguNiA3LjMgMCA2NC4yLjEgMTI4LjIuMSAxODguOHptMzYuMyAzN2MxNy4zIDE4LjEgMzQuMyAzNS45IDUxIDUzLjQtMi43IDIuOS01LjQgNS44LTguMyA5LTI2LjItMjUuNy01Mi4yLTUxLjItNzkuMS03Ny42djEwMS4xYzAgNy45IDEuOCA5LjggOS43IDkuOGgxNDguNWM3IDAgOS4xLTIuMSA5LjEtOS4ydi04Ni41LTQ5LjhjLTEzLjktMTUuMS0yNS45LTI4LjMtMzgtNDEuNC0zMS43IDMxLjEtNjIuNiA2MS41LTkyLjkgOTEuMnoiLz48cGF0aCBkPSJtNzcuOCAzMS41YzIzLjQtLjMgNDQuMiAxOS40IDQ1IDQxLjUuOSAyNi45LTE4LjggNDYuNi00My45IDQ3LjItMjUuNC42LTQ2LjMtMTguNi00Ni41LTQyLjItLjItMjYuOSAxOC42LTQ2LjIgNDUuNC00Ni41em0tMzIuNSA0NC43Yy4xIDE2LjkgMTQuOCAzMS40IDMyLjIgMzEgMTcuMy0uNCAzMi4xLTEyLjYgMzIuMS0zMS40IDAtMTkuMS0xNS45LTMxLjEtMzIuMy0zMS4zLTE3LjUtLjEtMzIuMSAxNC42LTMyIDMxLjd6bTMwMi40LTV2MTIuNGgtODkuOXYtMTIuNHptMzguOSAzMS42aDEzLjF2MTIuNGgtMTMuMXptLTM4Ni40LTMzLjV2LTEyLjJoMTIuNHYxMi4yem0zNzMuNSAxNC40aC0xMi40di0xMi40aDEyLjR6Ii8+PC9zdmc+"></img>`;

		var checkExistTimer = setInterval(function () {
			let homeSelector = "nav span img";
			let menuAndStorySelector = "header button > span";
			let profileSelector = "header section svg circle";

			// check profile
			if (document.getElementsByClassName("imagewall-btn").length === 0) {
				if (document.querySelector(profileSelector)) {
					addCustomBtnProfile(
						document.querySelector(profileSelector),
						"black",
						append2Header
					);
				} else if (document.querySelector(menuAndStorySelector)) {
				} else if (document.querySelector(homeSelector)) {
					addCustomBtnHome(
						document.querySelector(homeSelector),
						"black",
						append2Header
					);
				}
			}
		}, 500);

		function append2Header(node, btn) {
			node.parentNode.parentNode.parentNode.appendChild(
				btn,
				node.parentNode.parentNode
			);
		}

		function addCustomBtnProfile(node, iconColor, appendNode) {
			// add button and set onclick handler
			let imageWallBtn = createCustomBtn(
				svgImageWallBtn,
				iconColor,
				"imagewall-btn",
				"16px",
				"8px"
			);
			appendNode(node, imageWallBtn);
		}
		function addCustomBtnHome(node, iconColor, appendNode) {
			// add button and set onclick handler
			let imageWallBtn = createCustomBtn(
				svgImageWallBtn,
				iconColor,
				"imagewall-btn Fifk5",
				"16px",
				"inherit"
			);
			appendNode(node, imageWallBtn);
		}

		function createCustomBtn(
			svg,
			iconColor,
			className,
			marginLeft,
			marginTop
		) {
			let newBtn = document.createElement("div");
			newBtn.innerHTML = svg.replace("%color", iconColor);
			newBtn.setAttribute("class", "custom-btn " + className);
			newBtn.setAttribute("target", "_blank");
			newBtn.setAttribute(
				"style",
				"cursor: pointer;margin-left: " +
					marginLeft +
					";margin-top: " +
					marginTop +
					";"
			);
			newBtn.onclick = getQueryHash;
			if (className.includes("imagewall-btn")) {
				newBtn.setAttribute("title", "Load Image Wall");
			}
			return newBtn;
		}
	}
	startUp();
})();