// ==UserScript== // @name Bing Image Creator auto-download // @namespace http://tampermonkey.net/ // @version Alpha-v2 // @license MIT // @description Automatic image downloader for Bing Image Creator. // @match https://www.bing.com/images/create*?*autosavetimer=* // @grant GM_download // @require http://code.jquery.com/jquery-3.4.1.min.js // @downloadURL none // ==/UserScript== // // I just pasted this together from things found scattered around the internet. Primarily: https://github.com/Emperorlou/MidJourneyTools // // To enable periodic downloading of newly-created images, go to a 'recent creations' page, and add "&autosavetimer=60" to the URL; // something like: `https://www.bing.com/images/create/-/1234?autosavetimer=60`. // // This implementation is designed to be left unattended - periodically reloading itself. If you click a link it will disable the script, // unless you remove `?*autosavetimer=*` from `@match` above. (function() { 'use strict'; const downloadables = "img[src$='&pid=ImgGn']"; var activeDownloads = 0; function get_download_url(img) { const src = img.attributes['src'].nodeValue; return src.replace(/\?.*$/, "?pid=ImgGn"); } function get_filename(img, src, ref) { var url = new URL(src); var refurl = new URL(ref); var src_filename = url.pathname.split('/').pop(); var ref_path = refurl.pathname.split('/'); while (ref_path.length && ref_path.shift() != 'create') ; var pageid = (ref_path.length >= 2 && ref_path[1]) || refurl.searchParams.get('id') || ""; var desc = (ref_path.length >= 2 && ref_path[0]) || refurl.searchParams.get('q') || ""; //var desc = img.attr("alt", ""); console.log("page id:", pageid, " src_filename:", src_filename, " description:", desc); return src_filename + "_" + pageid + "_" + desc + ".jpg"; } function reload() { $("#girrcc").load(location.href + " #girrcc a"); //window.location.reload(true); } function find_href(elem) { while (elem) { if (elem.hasAttribute('href')) return elem.href; elem = elem.parentElement; } return null; } $(document).ready(() => { var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = '.saved_image { border: 3px green dashed; }'; document.head.appendChild(style); setInterval(() => { window.renderSavedImageIndicators(); autoSaveNextImage(); }, 500); launchInactivityTimer(); }); function launchInactivityTimer() { var timer; var params = new URLSearchParams(window.location.search); var timeout = params.get('autosavetimer') || 60; window.onload = resetTimer; document.onmousemove = resetTimer; document.onkeydown = resetTimer; function resetTimer() { clearInterval(timer); timer = setInterval(reload, timeout * 1000); } resetTimer(); } function downloadFile(url, filename, referrer) { setUrlBusy(url); const download = GM_download({ url: url, name: filename, saveAs: false, conflictAction: "uniquify", onload: function () { setUrlSaved(url); }, onerror: function () { clearUrlBusy(url); }, ontimeout: function () { clearUrlBusy(url); } }); }; function autoSaveNextImage() { // find thumbnails const allImages = $($(downloadables).get().reverse()); for(const img of allImages) { const src = get_download_url(img); const ref = find_href(img) || "https://www.example.com/"; if (isUrlReady(src)) { const filename = get_filename(img, src, ref); if (filename) { downloadFile(src, filename, ref); } document.dispatchEvent(new Event("mousemove")); // Only start one image per timer loop. Launching multiple downloads simultaneously may be unwise. break; } } } window.renderSavedImageIndicators = () => { const allImages = $(downloadables); for(const img of allImages) { const src = get_download_url(img); if (src && isUrlSaved(src)) $(img).addClass("saved_image"); } } function setUrlBusy(src) { sessionStorage.setItem("busyImage-" + src, Date.now()); activeDownloads++; if (activeDownloads > 1) console.log("concurrent downloads:", activeDownloads); } function clearUrlBusy(src) { sessionStorage.removeItem("busyImage-" + src); activeDownloads--; } function setUrlSaved(src) { localStorage.setItem("savedImage-" + src, true); clearUrlBusy(src); } function isUrlSaved(src) { return localStorage.getItem("savedImage-" + src) === "true" ? true : false; } function isUrlReady(src) { if (!src || isUrlSaved(src)) return false; const stamp = sessionStorage.getItem("busyImage-" + src); if (!stamp) return true; if (Date.now() - stamp < 60000) { console.log("file has been busy too long (lost event?):", src); clearUrlBusy(src); return true; } console.log("still waiting to finish:", src); return false; } })();