UNPKG

rsshub

Version:
110 lines (109 loc) 3.85 kB
import { t as getPlaywrightPage } from "./playwright-Dd_brOFk.mjs"; //#region lib/routes/autotrader/index.ts const route = { path: "/:query", categories: ["other"], example: "/autotrader/radius=50&postcode=sw1a1aa&price-to=9000&year-from=2012&body-type=Hatchback&transmission=Automatic&exclude-writeoff-categories=on", parameters: { query: "the search query" }, features: { requirePuppeteer: true }, description: `1. Conduct a search with desired filters on AutoTrader 2. Copy everything in the URL after \`?\`, for example: \`https://www.autotrader.co.uk/car-search?radius=50&postcode=sw1a1aa&price-to=9000&year-from=2012&body-type=Hatchback&transmission=Automatic&exclude-writeoff-categories=on\` will produce \`radius=50&postcode=sw1a1aa&price-to=9000&year-from=2012&body-type=Hatchback&transmission=Automatic&exclude-writeoff-categories=on\``, name: "Search", maintainers: ["HenryQW"], handler }; const rootUrl = "https://www.autotrader.co.uk"; const filterNames = { "body-type": "body_type", "exclude-writeoff-categories": "is_writeoff", "fuel-type": "fuel_type", "price-from": "min_price", "price-to": "max_price", radius: "distance", "year-from": "min_year_manufactured", "year-to": "max_year_manufactured" }; const gqlQuery = ` query SearchResultsListingsGridQuery($filters: [FilterInput!]!, $channel: Channel!, $page: Int, $sortBy: SearchResultsSort, $searchId: String!) { searchResults(input: { facets: [], filters: $filters, channel: $channel, page: $page, sortBy: $sortBy, searchId: $searchId }) { listings { ... on SearchListing { advertId title subTitle attentionGrabber price vehicleLocation images sellerType } } } } `; async function handler(ctx) { const { query } = ctx.req.param(); const searchParams = new URLSearchParams(query); const filters = [{ filter: "price_search_type", selected: ["total"] }]; const keys = new Set(searchParams.keys()); for (const key of keys) { if (key === "page" || key === "sort") continue; const filter = filterNames[key] ?? key.replaceAll("-", "_"); const selected = filter === "is_writeoff" ? ["exclude"] : searchParams.getAll(key); filters.push({ filter, selected }); } const link = `${rootUrl}/car-search?${query}`; const { page, destroy } = await getPlaywrightPage(link); let listings; try { listings = await page.evaluate(async ({ gqlQuery, filters, page, sortBy }) => { return (await (await fetch("/at-gateway?opname=SearchResultsListingsGridQuery", { method: "POST", headers: { "content-type": "application/json", "x-sauron-app-name": "sauron-search-results-app" }, body: JSON.stringify([{ operationName: "SearchResultsListingsGridQuery", variables: { filters, channel: "cars", page, sortBy, searchId: "00000000-0000-0000-0000-000000000000" }, query: gqlQuery }]) })).json())[0].data.searchResults.listings; }, { gqlQuery, filters, page: Number(searchParams.get("page")) || 1, sortBy: searchParams.get("sort") ?? "relevance" }); } finally { await destroy(); } return { title: "Auto Trader", link, item: listings.filter((listing) => listing.advertId).map((listing) => ({ title: `「${listing.price}${listing.title} ${listing.subTitle}`, description: [ listing.attentionGrabber, `${listing.vehicleLocation} · ${listing.sellerType}`, ...(listing.images ?? []).map((image) => `<img src="${image.replace("{resize}", "w1024")}">`) ].join("<br>"), link: `${rootUrl}/car-details/${listing.advertId}`, guid: listing.advertId })) }; } //#endregion export { route };