diff --git a/src/kijiji.ts b/src/kijiji.ts new file mode 100644 index 0000000..fe10c95 --- /dev/null +++ b/src/kijiji.ts @@ -0,0 +1,92 @@ +import { parseHTML } from "linkedom"; + +type SearchListing = { + name: string; + listingLink: string; +}; + +interface ApolloState { + [key: string]: { + [key: string]: unknown; + url: string; + title: string; + }; +} + +const searchQuery = "playstation 5"; + +// const exampleSearchHTML = Bun.file("./example-kijiji-search.html"); +// const exampleSearchHTMLData = await exampleSearchHTML.text(); + +function extractSearchListingsFromNextData(htmlString: string) { + const { document } = parseHTML(htmlString); + const nextData = document.getElementById("__NEXT_DATA__"); + + if (!nextData) { + console.error("Could not find __NEXT_DATA__ script element."); + return []; + } + + try { + if (!nextData.textContent) { + console.error("__NEXT_DATA__ element is empty!"); + return []; + } + const jsonData = JSON.parse(nextData.textContent); + const apolloState: ApolloState = jsonData.props.pageProps.__APOLLO_STATE__; + + const listingsKeys: string[] = []; + + for (const key in apolloState) { + if (key.includes("Listing")) { + listingsKeys.push(key); + } + } + + const searchListings: (SearchListing | undefined)[] = listingsKeys.map( + (key) => { + const listing = apolloState[key]; + if (!listing) return undefined; + return { + listingLink: listing.url, + name: listing.title, + }; + }, + ); + + console.log(searchListings); + + return searchListings; + } catch (error) { + console.error("Error parsing __NEXT_DATA__:", error); + return []; + } +} + +const makeKijijiRequest = async (url: string): Promise => { + const request = await fetch(url, { + headers: { + accept: + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "accept-language": "en-GB,en-US;q=0.9,en;q=0.8", + "cache-control": "max-age=0", + priority: "u=0, i", + "sec-ch-ua": '"Not)A;Brand";v="8", "Chromium";v="138"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Linux"', + "sec-fetch-dest": "document", + "sec-fetch-mode": "navigate", + "sec-fetch-site": "same-origin", + "sec-fetch-user": "?1", + "upgrade-insecure-requests": "1", + }, + body: null, + method: "GET", + }); + + return await request.text(); +}; + +// https://www.kijiji.ca/b-canada/${searchQuery}/k0l0?dc=true&view=list + +// extractSearchListingsFromNextData(await kijijiRequest.text());