Skip to content

Instantly share code, notes, and snippets.

@filiptronicek
Created May 8, 2023 21:19
Show Gist options
  • Save filiptronicek/caa62908afed876f562f7a5f1a1145a6 to your computer and use it in GitHub Desktop.
Save filiptronicek/caa62908afed876f562f7a5f1a1145a6 to your computer and use it in GitHub Desktop.
Instagram automated story downloader
wget --content-disposition --trust-server-names -i urls.txt
function downloadURLsTxt() {
try {
const urls = JSON.parse(localStorage.getItem("urls"));
if (!urls || !Array.isArray(urls)) {
throw new Error("No URLs found in localStorage");
}
const urlContent = urls.join("\n");
const blob = new Blob([urlContent], { type: "text/plain;charset=utf-8" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "urls.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
console.log("Downloaded: urls.txt");
} catch (error) {
console.error("Failed to download urls.txt:", error);
}
}
// ==UserScript==
// @name Instagram Story Saver
// @version 2.8
// @description Click a button to open the IG story video/image in new tab. IG stories can then be viewed/downloaded.
// @author navchandar
// @copyright 2019, navchandar (https://openuserjs.org/users/navchandar)
// @license MIT
// @match https://www.instagram.com/*
// @match https://www.instagram.com/stories/*
// excludes *
// @grant GM_openInTab
// @grant GM_addStyle
// @homepage https://navchandar.github.io/
// @homepage https://github.com/navchandar/
// @homepageURL https://navchandar.github.io/
// @contributionURL https://paypal.me/navchandar
// @contributionAmount $1.00
// @supportURL https://openuserjs.org/scripts/navchandar/Instagram_Story_Saver/issues
// @setupURL https://openuserjs.org/install/navchandar/Instagram_Story_Saver.user.js
// @icon https://cdn.iconscout.com/icon/free/png-256/instagram-53-151118.png
// @namespace https://greasyfork.org/users/302262
// ==/UserScript==
function getElementsByXPath(xpath, parent) {
let results = [];
let query = document.evaluate(xpath, parent || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i = 0, length = query.snapshotLength; i < length; ++i) {
results.push(query.snapshotItem(i))
}
return results
}
window.urls = [];
function has(String, search) {
try {
if (String.indexOf(search) > -1) {
return !0
}
}
catch (err) { }
return !1
}
function openStory(zEvent) {
let parent = document.elementFromPoint(innerWidth / 2, innerHeight / 2).parentNode.parentNode.parentNode.parentNode,
video = parent.querySelector("video source"),
image = parent.querySelector("img");
if (!video && !image) {
parent = document.elementFromPoint(innerWidth / 2, innerHeight / 2).parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
video = parent.querySelector("video source");
image = parent.querySelector("img");
}
if (!video && !image) {
parent = document.elementFromPoint(innerWidth / 2, innerHeight / 2).parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
video = parent.querySelector("video source");
image = parent.querySelector("img");
}
if (video) {
console.info(video.getAttribute("src"), false);
}
else if (image) {
console.info(GetFirstSrcsetUrl(image.getAttribute("srcset")), false);
}
else {
console.log("Nothing img/video found to open.")
}
}
function GetFirstSrcsetUrl(imageSrc) {
var firstUrl = /(^http.*?) /g.exec(imageSrc)[0];
window.urls.push(firstUrl);
// Persist in local storage
localStorage.setItem("urls", JSON.stringify(window.urls));
return firstUrl
}
function AddButton() {
var t = document.createElement("div");
t.innerHTML = '<button id="myButton" title="Click to open this Story" type="button">OPEN</button>', t.setAttribute("id", "myContainer"), document.body.appendChild(t), document.getElementById("myButton").addEventListener("click", openStory, !1), GM_addStyle("#myContainer{position:fixed;bottom:0;left:49%;right:48%;margin:0;width:3.5%;height:3%;text-align:center}\n#myButton{opacity:.55;cursor:pointer;background-color:#262626;color:#fff;font-size:7px;border-radius:7px;padding:0}#myButton:hover{color:#fff;opacity:.65}")
}
function sleep(e) {
return new Promise(n => setTimeout(n, e))
}
async function sleepFunc() {
await sleep(1e3)
}
function findNext() {
const next = getElementsByXPath("//button[@aria-label='Next']");
if (next.length > 0) {
next[0].click();
}
}
function Login() {
// Auto login if creds autofilled
setTimeout(function() {
sleepFunc();
var login = getElementsByXPath("//*[text() = 'Log In']");
if (login.length > 0) {
login[0].click();
}
var notNow = getElementsByXPath("(//button[text()='Not Now'])[1]");
if (notNow.length > 0) {
notNow[0].click();
}
}, 2000)
// click the link NOT NOW after login!!
var NotNow = getElementsByXPath("//a[@href='/']");
if (NotNow.length > 0) {
NotNow[0].click();
}
}
function HideBtn() {
document.getElementById("myButton").style.visibility = "hidden"
}
function UnHideBtn() {
document.getElementById("myButton").style.visibility = "visible"
}
function AddShortcut() {
document.addEventListener('keydown', keyHandler);
function keyHandler(event) {
if (window.location.href === 'https://www.instagram.com/') return;
// alt + x
if (event.altKey && event.keyCode === 88) {
document.getElementById("myButton").click();
}
}
}
! function() {
"use strict";
AddButton(), HideBtn(), Login(), AddShortcut(), setInterval(function() {
var t = window.location.href;
const url = new URL(t);
if (url.hostname !== "www.instagram.com" || !url.pathname.includes("stories")) {
HideBtn();
return;
}
UnHideBtn();
findNext();
document.querySelector("#myButton").click();
}, 1e3)
}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment