diff --git a/.gitignore b/.gitignore index a14702c..f35b2ad 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json # Finder (MacOS) folder config .DS_Store + +wishlist.json +missing_items.json diff --git a/getWishlist.mjs b/getWishlist.mjs index 4e82f96..e0ea851 100644 --- a/getWishlist.mjs +++ b/getWishlist.mjs @@ -1,12 +1,25 @@ import bcfetch from 'bandcamp-fetch'; -const fs = require("fs"); +import fs from 'fs/promises'; // Using the promise-based version of fs for clean async/await const username = 'noschxl'; async function fetchEntireWishlist() { - let allWishlistItems = []; + let previousWishlist = []; - // Set the initial parameters using the username + // 1. Try to load the previous wishlist to compare against + try { + const fileData = await fs.readFile('wishlist.json', 'utf8'); + previousWishlist = JSON.parse(fileData); + console.log(`Loaded ${previousWishlist.length} previous items from wishlist.json for comparison.`); + } catch (error) { + if (error.code === 'ENOENT') { + console.log('No existing wishlist.json found. This must be the first run!'); + } else { + console.error('Error reading wishlist.json:', error); + } + } + + let allWishlistItems = []; let currentParams = { target: username, imageFormat: 'art_app_large' @@ -15,47 +28,64 @@ async function fetchEntireWishlist() { let hasMorePages = true; let pageCount = 1; - console.log(`Starting wishlist scrape for user: ${username}...`); + console.log(`\nStarting wishlist scrape for user: ${username}...`); - // Loop will keep running as long as Bandcamp returns a continuation token + // 2. Scrape the current wishlist while (hasMorePages) { console.log(`Fetching page ${pageCount}...`); try { const result = await bcfetch.fan.getWishlist(currentParams); - // Add the items from the current page to our master list - // (Assuming the library returns the array inside an 'items' property) if (result && result.items) { allWishlistItems.push(...result.items); } - // Check if there are more pages to fetch if (result.continuation) { - // Update the target with the continuation object for the next loop iteration currentParams.target = result.continuation; pageCount++; } else { - // No continuation token means we've hit the end of the wishlist hasMorePages = false; } } catch (error) { console.error(`Error fetching page ${pageCount}:`, error); - break; // Exit the loop if something goes wrong + break; } } console.log(`\nDone! Successfully scraped ${allWishlistItems.length} items from your wishlist.`); - // You can now write `allWishlistItems` to a JSON file using Node's 'fs' module - // console.log(JSON.stringify(allWishlistItems, null, 2)); - fs.writeFile('wishlist.json', JSON.stringify(allWishlistItems, null, 2), (err) => { - if (err) { - console.error('Error writing to file', err); + // 3. Compare the old list against the new list + if (previousWishlist.length > 0) { + // Create a Set of all the current IDs for fast, easy lookup + const currentIds = new Set(allWishlistItems.map(item => item.id)); + + // Filter the previous list to find items whose IDs are missing from the current scrape + const missingItems = previousWishlist.filter(item => !currentIds.has(item.id)); + + if (missingItems.length > 0) { + console.log(`\nWARNING: ${missingItems.length} item(s) have disappeared since the last run!`); + + missingItems.forEach(item => { + console.log(`- ${item.artist.name} : ${item.name}`); + console.log(` Old URL: ${item.url}\n`); + }); + + // Optional: Save the missing items to a separate file so you don't lose their metadata + await fs.writeFile('missing_items.json', JSON.stringify(missingItems, null, 2)); + console.log('Saved missing items to missing_items.json'); } else { - console.log('Data written to file'); + console.log('\nAll good! No items have disappeared since your last run.'); } - }) + } + + // 4. Overwrite wishlist.json with the new, up-to-date data for the next run + try { + await fs.writeFile('wishlist.json', JSON.stringify(allWishlistItems, null, 2)); + console.log('Successfully updated wishlist.json with current data.'); + } catch (error) { + console.error('Error writing to wishlist.json:', error); + } } fetchEntireWishlist();