Skip to content

Instantly share code, notes, and snippets.

@lukekarrys
Created May 1, 2021 03:01
Show Gist options
  • Save lukekarrys/0ca15ff77e2603afcf04e593f449ba00 to your computer and use it in GitHub Desktop.
Save lukekarrys/0ca15ff77e2603afcf04e593f449ba00 to your computer and use it in GitHub Desktop.
Script to find specific refurb macs for sale
import { JSDOM, VirtualConsole } from "jsdom";
import fetch from "node-fetch";
const appleUrl = (p) => {
return new URL(p, `https://www.apple.com`);
};
const fetchPage = async (url) => {
const res = await fetch(appleUrl(url));
const html = await res.text();
return new JSDOM(html, {
runScripts: "dangerously",
virtualConsole: new VirtualConsole(),
});
};
const allSpecs = [
"Chip",
"Memory",
"Storage",
"Charging and Expansion",
"Video Support and Camera",
"Audio",
"Wireless",
].map((t) => t.toLowerCase());
const indent = (arr, l = 0) =>
arr
.map((i) => (Array.isArray(i) ? indent(i, l + 1) : " ".repeat(l * 2) + i))
.join("\n");
const main = async ({ filterProduct, includeSpecs = allSpecs }) => {
const page = await fetchPage("/shop/refurbished/mac/2020-mac-mini");
const products = await Promise.all(
page.window.REFURB_GRID_BOOTSTRAP.tiles
.filter(filterProduct)
.map(async (p) => {
const product = await fetchPage(p.productDetailsUrl);
const data = product.window.pageLevelData;
const title = data.PDPContent.productTitle;
const specs = data.TechSpecs.tiles.groups.items.filter(
(p) => p.value.mutiValueAttributeSelector?.groupTitleFromAsset
);
const specsDisplay = specs
.map((p) => {
return {
title: p.value.mutiValueAttributeSelector.groupTitleFromAsset,
specs: p.value.mutiValueAttributeSelector.attributeList.items.map(
(i) => i.value.replace(/<sup>\d+<\/sup>/g, "")
),
};
})
.filter((s) => includeSpecs.includes(s.title.toLowerCase()))
.flatMap((s) => [s.title, s.specs]);
const displayUrl = appleUrl(p.productDetailsUrl);
displayUrl.search = "";
return indent([title, [displayUrl.toString(), ...specsDisplay]]);
})
);
return products.join(`\n${"-".repeat(40)}\n`);
};
main({
filterProduct: (p) => {
return (
p.filters.dimensions.refurbClearModel === "macmini" &&
p.title.match(/\bM1\b/)
);
},
includeSpecs: ["storage", "memory", "chip"],
})
.then(console.log)
.catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment