From 1ff49f0669cbaff4689024972e53f18c87a845cb Mon Sep 17 00:00:00 2001 From: wukko Date: Sat, 20 Apr 2024 20:33:34 +0600 Subject: [PATCH] instagram: use different endpoint and fallback to two other options --- src/modules/processing/services/instagram.js | 140 +++++++++++++++---- 1 file changed, 112 insertions(+), 28 deletions(-) diff --git a/src/modules/processing/services/instagram.js b/src/modules/processing/services/instagram.js index b5e2228d..d27a5693 100644 --- a/src/modules/processing/services/instagram.js +++ b/src/modules/processing/services/instagram.js @@ -60,39 +60,99 @@ async function request(url, cookie, method = 'GET', requestData) { return data.json(); } -async function getPost(id) { - let data; - try { - const cookie = getCookie('instagram'); - let dtsgId; - - if (cookie) { - dtsgId = await findDtsgId(cookie); +async function requestHTML(id, cookie = {}) { + const data = await fetch(`https://www.instagram.com/p/${id}/embed/captioned/`, { + headers: { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "Accept-Language": "en-GB,en;q=0.9", + "Cache-Control": "max-age=0", + "Dnt": "1", + "Priority": "u=0, i", + "Sec-Ch-Ua": 'Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99', + "Sec-Ch-Ua-Mobile": "?0", + "Sec-Ch-Ua-Platform": "macOS", + "Sec-Fetch-Dest": "document", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-Site": "none", + "Sec-Fetch-User": "?1", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", + ...cookie } + }).then(r => r.text()); - const url = new URL('https://www.instagram.com/api/graphql/'); + let embedData = JSON.parse(data?.match(/"init",\[\],\[(.*?)\]\],/)[1]); - const requestData = { - jazoest: '26406', - variables: JSON.stringify({ - shortcode: id, - __relay_internal__pv__PolarisShareMenurelayprovider: false - }), - doc_id: '7153618348081770' - }; - if (dtsgId) { - requestData.fb_dtsg = dtsgId; + if (!embedData || !embedData?.contextJSON) return false; + + embedData = JSON.parse(embedData.contextJSON); + + return embedData; +} +async function requestGQL(id, cookie) { + let dtsgId; + + if (cookie) { + dtsgId = await findDtsgId(cookie); + } + const url = new URL('https://www.instagram.com/api/graphql/'); + + const requestData = { + jazoest: '26406', + variables: JSON.stringify({ + shortcode: id, + __relay_internal__pv__PolarisShareMenurelayprovider: false + }), + doc_id: '7153618348081770' + }; + if (dtsgId) { + requestData.fb_dtsg = dtsgId; + } + + return (await request(url, cookie, 'POST', requestData)) + .data + ?.xdt_api__v1__media__shortcode__web_info + ?.items + ?.[0]; +} + +async function extractOldPost(data, id) { + const sidecar = data?.gql_data?.shortcode_media?.edge_sidecar_to_children; + if (sidecar) { + const picker = sidecar.edges.filter(e => e.node?.display_url) + .map(e => { + const type = e.node?.is_video ? "video" : "photo"; + const url = type === "video" ? e.node?.video_url : e.node?.display_url; + + return { + type, url, + /* thumbnails have `Cross-Origin-Resource-Policy` + ** set to `same-origin`, so we need to proxy them */ + thumb: createStream({ + service: "instagram", + type: "default", + u: e.node?.display_url, + filename: "image.jpg" + }) + } + }); + + if (picker.length) return { picker } + } else if (data?.gql_data?.shortcode_media?.video_url) { + return { + urls: data.shortcode_media.video_url, + filename: `instagram_${id}.mp4`, + audioFilename: `instagram_${id}_audio` } + } else if (data?.gql_data?.shortcode_media?.display_url) { + return { + urls: data.gql_data?.shortcode_media.display_url, + isPhoto: true + } + } +} - data = (await request(url, cookie, 'POST', requestData)) - .data - ?.xdt_api__v1__media__shortcode__web_info - ?.items - ?.[0]; - } catch {} - - if (!data) return { error: 'ErrorCouldntFetch' }; - +async function extractNewPost(data, id) { const carousel = data.carousel_media; if (carousel) { const picker = carousel.filter(e => e?.image_versions2) @@ -133,7 +193,31 @@ async function getPost(id) { isPhoto: true } } +} +async function getPost(id) { + let data, result, dataType = 'old'; + try { + const cookie = getCookie('instagram'); + + data = await requestHTML(id); + if (!data) data = await requestHTML(id, cookie); + + if (!data) { + dataType = 'new'; + data = await requestGQL(id, cookie); + } + } catch {} + + if (!data) return { error: 'ErrorCouldntFetch' }; + + if (dataType === 'new') { + result = extractNewPost(data, id) + } else { + result = extractOldPost(data, id) + } + + if (result) return result; return { error: 'ErrorEmptyDownload' } }