Instagram full-size media scroll wall

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

当前为 2020-05-12 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        Instagram full-size media scroll wall
// @namespace   driver8.net
// @author      driver8
// @description Creates a scrollable wall of full-size images from any user's instagram page. Just click "Load Images" at the top.
// @match       *://*.instagram.com/*
// @exclude     https://www.instagram.com/p/*
// @exclude     https://instagram.com/p/*
// @version     0.1.2
// @grant       none
// ==/UserScript==

(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 = .8;
    const WIDTH_PCT = .49;
    const VID_VOLUME = 0.02;
    let m = document.body.innerHTML.match(/profilePage_(\d+)/);
    var userId = m && m[1];

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

        var query_hash = false,
            query_id = false;

        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 && loadImages(query_id, query_hash);
            // query_id && query_hash && 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) {
        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};
        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 < 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 = 'Video';
                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() {
        let tempDiv = document.createElement('div');
        tempDiv.innerHTML = `<div style="margin: 20px;font-size: 18px;font-weight: bold;color: #3897F0; cursor: pointer;"><h2>Load Images</h2></div>`;
        let loadButton = tempDiv.firstElementChild;
        loadButton.onclick = getQueryHash;

        (function insertButton() {
            let insAt = document.querySelector('.ZcHy5, ._47KiJ');
            if (insAt) {
                insAt.parentNode.insertBefore(loadButton, insAt);
            } else {
                window.setTimeout(insertButton, 20);
            }
        })();
    }
    startUp();

})();