您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Smugmug Album DownloaD
// ==UserScript== // @name Smugmug Album Downloader // @namespace http://tampermonkey.net/ // @version 0.1 // @description Smugmug Album DownloaD // @author _John#1218 // @supportURL https://github.com/JDipi/Smugmug-Album-Downloader/issues // @match https://*.smugmug.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=smugmug.com // @connect https://photos.smugmug.com/ // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js // @grant GM_download // @grant GM_addStyle // @grant GM_info // ==/UserScript== /***************** IMPORTANT!!! ******************** For this script to work properly, do the following: 1) Go to your Tampermonkey dashboard 2) Click settings 3) Change the 1st option (Config Mode) to "Advanced" 4) Scroll down to "Downloads BETA" 5) Change "Download Mode" to "Browser API" 6) Save and exit, accept the new "Manage Download" permission if prompted. Doing this allows Tampermonkey to save the images to a folder in your default download location, rather than just spewing all the images out. **************************************************/ $(document).ready(() => { $(`<button id="downloadAlb">Download Album</button>`).appendTo( ".sm-gallery-cover-title" ); GM_addStyle(/*css*/ ` .sm-gallery-cover-title { display: flex; gap: 10px; align-items: center; } #downloadAlb { height: 40px; border-radius: 10px; } #downloadAlb:hover { background-color: gray; } .downloadProgressContainer progress { width: 100%; margin: 5px 0px; } .downloadProgressContainer { position: fixed; border-radius: 10px; margin: 10px; z-index: 100; background: #2c2f33; width: fit-content; color: black; padding: 10px; font-weight: bold; width: fit-content; box-shadow: 0px 0px 5px rgba(0, 0, 0, 1) } #downloadProgress { display: flex; justify-content: space-between; color: #99aab5; } #errors > p { color: #ff7171; border: 1px solid #99aab5; margin: 2px 0px; border-radius: 5px; padding: 5px; } #errors a code { color: #9393ff; text-decoration: underline; } #errors { max-height: 270px; overflow: auto; width: 800px; margin: 0px 0px 5px 0px; } #close { background-color: #7289da; border-radius: 8px; padding: 5px; width: 70px; color: white; border: 1px solid #99aab5; cursor: pointer; } #close:hover { background-color: #55659f; } `); $("#downloadAlb").on("click", function (e) { let url = $("link[rel=alternate][type*=rss+xml]").attr("href"); let albumRegex = new RegExp(/\d*_[a-zA-Z\d]*/gm); let domainRegex = new RegExp(/\/\/(.*)(?=\.smugmug\.com)/gm); let albumId = url.match(albumRegex)[0].split("_")[0]; let albumKey = url.match(albumRegex)[0].split("_")[1]; let domain = window.location.href.match(domainRegex); let links = []; const settings = { async: true, crossDomain: true, url: `https:${domain}.smugmug.com/services/api/json/1.4.0?galleryType=album&albumId=${albumId}&albumKey=${albumKey}&PageNumber=2&imageId=0&returnModelList=true&PageSize=5000&method=rpc.gallery.getalbum`, method: "GET", }; $.ajax(settings).done(function (response) { console.log(response); if (GM_info.downloadMode !== "browser") { alert(`Please change the Tampermonkey download mode to browser and read the important comment at the top of the script!!!`) return } if ( !confirm( `You are about to download ${response.Pagination.TotalItems} images. Continue?` ) ) return; for (let image in response.Images) { let picID = response.Images[image].GalleryUrl.split("/").slice(-1)[0]; let height = 0; let largestSize = ""; let ext = ""; // gets largest file of those available for (let size in response.Images[image].Sizes) { if (response.Images[image].Sizes[size].height > height) { height = response.Images[image].Sizes[size].height; largestSize = size; ext = response.Images[image].Sizes[size].ext; } } let url = `https://photos.smugmug.com/photos/${picID}/0/${largestSize}/${picID}-${largestSize}.${ext}`; links.push(url); } let done = 0; $("body").prepend( `<div class="downloadProgressContainer"> <div id="downloadProgress"> Downloading: [/${response.Pagination.TotalItems}] </div> <progress id="dp" value="" max="${response.Pagination.TotalItems}"></progress> <div id="errors"></div> <button id="close">Close</button> </div>` ); $('#close').on('click', function(e) { links = [] done = 0 $('.downloadProgressContainer').remove() }) // checks if the whole list has been run through and displays error / finished message const finish = () => { if (done == links.length) { $("#downloadProgress").text("Finished!"); if ($('#errors').children().length) { $("#downloadProgress").text(`Finished with ${$('#errors').children().length} errors.`); } } } links.forEach((url, i) => { let name = response.Albums[0].Title + "/" + url.split("/").slice(-1)[0]; GM_download({ url, name, onload: (e) => { done += 1; $("#downloadProgress").text( `Downloading: [${done}/${response.Pagination.TotalItems}]` ); $("progress#dp").attr("value", done) finish() }, onerror: (e) => { done += 1 $("#errors").append( `<p>Error: <code>${e.error}</code> for image [${i+1}/${response.Pagination.TotalItems}] <a href="${url}" target="_blank"> <code>${name}</code> </a> </p>` ); finish() }, ontimeout: (e) => { done += 1 $('#errors').append( `<p>The request for image [${i+1}/${response.Pagination.TotalItems}] <a href="${url}" target="_blank"> <code>${name}</code> </a> Timed out</p>` ) finish() } }); }); }); }); });