JDipi / Smugmug-Album-Downloader

Downloads high quality images from SmugMug albums
GNU General Public License v3.0
3 stars 1 forks source link

Unable to download using the button on a private gallery #5

Open noahkrueger opened 1 month ago

noahkrueger commented 1 month ago

I'm have the script set up with Tampermonkey, running in Chrome, and the correct setting enabled for downloads. When I click the button on a private gallery (requires password), I don't see any progress. It hangs in this state:

image

Any ideas?

JDipi commented 1 month ago

I changed the code and tested it out with my own private gallery I made, try it out and let me know if it works for you also.

noahkrueger commented 1 month ago

Thanks for the quick update! Your script worked except that it would swamp the SmugMug server and kill the request. I could only get about halfway through the 824 images and it would simply die. The other problem I encountered was that running the script pegged the CPU at 100%.

The following script was able to help me overcome both of those issues. It doesn't have the progress bar, but if you open up the browser console it shows what the script is doing.

// ==UserScript== // @name Smugmug Album Downloader // @namespace http://tampermonkey.net/ // @version 0.1 // @description Smugmug Album Downloader // @author Your Name // @match https://*.smugmug.com/* // @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js // @grant GM_download // @grant GM_addStyle // @grant GM_info // ==/UserScript==

(function() { 'use strict';

// Wait for the page to fully load
window.onload = function() {
    console.log('Page has loaded');

    // Verify if the target element exists before inserting the button
    if ($(".sm-gallery-cover-title").length > 0) {
        console.log('Found .sm-gallery-cover-title');

        // Append the download button to the .sm-gallery-cover-title element
        $(`<button id="downloadAlb">Download Album</button>`).appendTo(".sm-gallery-cover-title");

        GM_addStyle(`
          .sm-gallery-cover-title {
            display: flex;
            gap: 10px;
            align-items: center;
          }
          #downloadAlb {
            height: 40px;
            border-radius: 10px;
          }
          #downloadAlb:hover {
            background-color: gray;
          }
        `);

        // Handle button click event
        $("#downloadAlb").on("click", async function () {
            try {
                let albumId, albumKey;

                // Try to extract album information from link or fallback to script method
                let linkElement = $("link[rel='alternate'][type*='rss+xml']");

                if (linkElement.length > 0) {
                    let url = linkElement.attr("href");
                    let albumRegex = url.match(/\d*_[a-zA-Z\d]*/gm)[0].split("_");
                    albumId = albumRegex[0];
                    albumKey = albumRegex[1];
                } else {
                    console.log('RSS link not found, falling back to script method.');

                    let raw = $('script[crossorigin][type=module]:not(script[src])')["0"].outerHTML;
                    albumId = raw.match(/albumId":(\d*)/)[1];
                    albumKey = raw.match(/albumKey":"(.+?)"/)[1];
                }

                console.log(`Album ID: ${albumId}, Album Key: ${albumKey}`);

                const settings = {
                    async: true,
                    crossDomain: true,
                    url: `https://${document.location.hostname}/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",
                };

                console.log('Starting the API request...');

                const response = await $.ajax(settings);
                console.log('API response received:', response);

                if (response.Images && response.Images.length > 0) {
                    console.log(`Total Images Found: ${response.Images.length}`);

                    for (let image of response.Images) {
                        let picID = image.GalleryUrl.split("/").slice(-1)[0];
                        let height = 0;
                        let largestSize = "";
                        let ext = "";

                        // Get the largest image size
                        for (let size in image.Sizes) {
                            if (image.Sizes[size].usable && image.Sizes[size].height > height) {
                                height = image.Sizes[size].height;
                                largestSize = size;
                                ext = image.Sizes[size].ext;
                            }
                        }

                        let imageUrl = `https://photos.smugmug.com/photos/${picID}/0/${largestSize}/${picID}-${largestSize}.${ext}`;
                        console.log(`Downloading Image: ${imageUrl}`);

                        GM_download({
                            url: imageUrl,
                            name: `${picID}-${largestSize}.${ext}`,
                            onload: () => {
                                console.log(`Download complete: ${picID}`);
                            },
                            onerror: (e) => {
                                console.error(`Error downloading image ${picID}:`, e);
                            }
                        });

                        await new Promise(resolve => setTimeout(resolve, 500));
                    }
                } else {
                    console.log('No images found in the response.');
                }
            } catch (error) {
                console.error('Error:', error);
            }
        });
    } else {
        console.log('.sm-gallery-cover-title not found, button not inserted.');
    }
};

})();

JDipi commented 1 month ago

Thanks for this! I'll see if I can implement the changes to my script. I'll get to it eventually. I'm adding some other features and reworking the design, too.