mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-03-25 09:25:51 +00:00
fix: FInal cOop adjustments
This commit is contained in:
parent
71df4eed2f
commit
e66c0ebec1
3 changed files with 58 additions and 37 deletions
|
|
@ -54,13 +54,12 @@ function coopHeaders(ctx, sourcepage) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchText(url, { headers, ua } = {}) {
|
async function coopFetchText(ctx, url, label, { headers } = {}) {
|
||||||
const h = { ...(headers || {}) };
|
return await ctx.http.fetchTextWithRetry(url, label, ctx.store.ua, {
|
||||||
if (ua) h["User-Agent"] = ua;
|
method: "GET",
|
||||||
const res = await fetch(url, { method: "GET", headers: h });
|
headers: headers || {},
|
||||||
const text = await res.text();
|
});
|
||||||
return { status: res.status, text };
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function extractVar(html, re) {
|
function extractVar(html, re) {
|
||||||
const m = String(html || "").match(re);
|
const m = String(html || "").match(re);
|
||||||
|
|
@ -71,24 +70,24 @@ async function fetchText(url, { headers, ua } = {}) {
|
||||||
const coop = ctx.store.coop;
|
const coop = ctx.store.coop;
|
||||||
if (coop.sessionKey && coop.chainId && coop.storeId && coop.appVersion) return;
|
if (coop.sessionKey && coop.chainId && coop.storeId && coop.appVersion) return;
|
||||||
|
|
||||||
const r = await fetchText(REFERER, {
|
const r = await coopFetchText(ctx, REFERER, "coop:bootstrap", {
|
||||||
ua: ctx.store.ua,
|
headers: {
|
||||||
headers: {
|
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||||
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
Referer: REFERER,
|
||||||
Referer: REFERER,
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
|
const html = r?.text || "";
|
||||||
if (r.status !== 200 || !r.text) {
|
if (r?.status !== 200 || !html) {
|
||||||
throw new Error(`coop bootstrap failed: GET ${REFERER} => ${r.status}`);
|
throw new Error(`coop bootstrap failed: GET ${REFERER} => ${r.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values are in <script> var SESSIONKEY = "..."; etc.
|
// Values are in <script> var SESSIONKEY = "..."; etc.
|
||||||
coop.sessionKey = extractVar(r.text, /var\s+SESSIONKEY\s*=\s*"([^"]+)"/i);
|
coop.sessionKey = extractVar(html, /var\s+SESSIONKEY\s*=\s*"([^"]+)"/i);
|
||||||
coop.chainId = extractVar(r.text, /var\s+chainID\s*=\s*"([^"]+)"/i);
|
coop.chainId = extractVar(html, /var\s+chainID\s*=\s*"([^"]+)"/i);
|
||||||
coop.storeId = extractVar(r.text, /var\s+store_unique_id\s*=\s*"([^"]+)"/i);
|
coop.storeId = extractVar(html, /var\s+store_unique_id\s*=\s*"([^"]+)"/i);
|
||||||
coop.appVersion = extractVar(r.text, /var\s+CLIENTVERSION\s*=\s*"([^"]+)"/i);
|
coop.appVersion = extractVar(html, /var\s+CLIENTVERSION\s*=\s*"([^"]+)"/i);
|
||||||
|
|
||||||
if (!coop.sessionKey || !coop.chainId || !coop.storeId || !coop.appVersion) {
|
if (!coop.sessionKey || !coop.chainId || !coop.storeId || !coop.appVersion) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`coop bootstrap missing values: sessionKey=${!!coop.sessionKey} chainId=${!!coop.chainId} storeId=${!!coop.storeId} appVersion=${!!coop.appVersion}`
|
`coop bootstrap missing values: sessionKey=${!!coop.sessionKey} chainId=${!!coop.chainId} storeId=${!!coop.storeId} appVersion=${!!coop.appVersion}`
|
||||||
|
|
@ -267,7 +266,7 @@ async function scanCategoryCoop(ctx, prevDb, report) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.logger.ok(
|
ctx.logger.ok(
|
||||||
`${ctx.catPrefixOut} | Page ${pageStr(done, done)} | ${String(
|
`${ctx.catPrefixOut} | Page ${padLeft(page, 3)} | ${String(
|
||||||
r.status || ""
|
r.status || ""
|
||||||
).padEnd(3)} | items=${padLeft(kept, 3)} | bytes=${kbStr(
|
).padEnd(3)} | items=${padLeft(kept, 3)} | bytes=${kbStr(
|
||||||
r.bytes
|
r.bytes
|
||||||
|
|
@ -345,7 +344,7 @@ function createStore(defaultUa) {
|
||||||
{ key: "scottish-single-malts", label: "Scottish Single Malts", coopSlug: "scottish_single_malts", coopCategoryId: 6, startUrl: `${REFERER}#/category/scottish_single_malts` },
|
{ key: "scottish-single-malts", label: "Scottish Single Malts", coopSlug: "scottish_single_malts", coopCategoryId: 6, startUrl: `${REFERER}#/category/scottish_single_malts` },
|
||||||
{ key: "scottish-blends", label: "Scottish Whisky Blends", coopSlug: "scottish_whisky_blends", coopCategoryId: 5, startUrl: `${REFERER}#/category/scottish_whisky_blends` },
|
{ key: "scottish-blends", label: "Scottish Whisky Blends", coopSlug: "scottish_whisky_blends", coopCategoryId: 5, startUrl: `${REFERER}#/category/scottish_whisky_blends` },
|
||||||
{ key: "american-whiskey", label: "American Whiskey", coopSlug: "american_whiskey", coopCategoryId: 8, startUrl: `${REFERER}#/category/american_whiskey` },
|
{ key: "american-whiskey", label: "American Whiskey", coopSlug: "american_whiskey", coopCategoryId: 8, startUrl: `${REFERER}#/category/american_whiskey` },
|
||||||
{ key: "world-whisky", label: "World / International Whisky", coopSlug: "world_international", coopCategoryId: 10, startUrl: `${REFERER}#/category/world_international` },
|
{ key: "world-whisky", label: "World Whisky", coopSlug: "world_international", coopCategoryId: 10, startUrl: `${REFERER}#/category/world_international` },
|
||||||
{ key: "rum", label: "Rum", coopSlug: "spirits_rum", coopCategoryId: 24, startUrl: `${REFERER}#/category/spirits_rum` },
|
{ key: "rum", label: "Rum", coopSlug: "spirits_rum", coopCategoryId: 24, startUrl: `${REFERER}#/category/spirits_rum` },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ function isRealSku(v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeSkuForDb(raw, { storeLabel, url } = {}) {
|
function normalizeSkuForDb(raw, { storeLabel, url } = {}) {
|
||||||
return normalizeSkuKey(raw, { storeLabel, url });
|
const lab = storeLabel || "";
|
||||||
|
return normalizeSkuKey(raw, { storeLabel: lab, url });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -106,7 +107,10 @@ function mergeDiscoveredIntoDb(prevDb, discovered) {
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
const now = {
|
const now = {
|
||||||
...nowRaw,
|
...nowRaw,
|
||||||
sku: normalizeSkuForDb(nowRaw.sku, { storeLabel: nowRaw.storeLabel, url }),
|
sku: normalizeSkuForDb(nowRaw.sku, {
|
||||||
|
storeLabel: nowRaw.storeLabel || nowRaw.store || "",
|
||||||
|
url,
|
||||||
|
}),
|
||||||
img: normImg(nowRaw.img),
|
img: normImg(nowRaw.img),
|
||||||
removed: false,
|
removed: false,
|
||||||
};
|
};
|
||||||
|
|
@ -119,7 +123,12 @@ function mergeDiscoveredIntoDb(prevDb, discovered) {
|
||||||
if (prevUrlForThisItem === url && prev.removed) {
|
if (prevUrlForThisItem === url && prev.removed) {
|
||||||
const now = {
|
const now = {
|
||||||
...nowRaw,
|
...nowRaw,
|
||||||
sku: normalizeSkuForDb(nowRaw.sku, { storeLabel: nowRaw.storeLabel, url }) || normalizeSkuForDb(prev.sku, { storeLabel: prev.storeLabel, url: prev.url }),
|
sku:
|
||||||
|
normalizeSkuForDb(nowRaw.sku, {
|
||||||
|
storeLabel: nowRaw.storeLabel || nowRaw.store || prev.storeLabel || prev.store || "",
|
||||||
|
url,
|
||||||
|
}) ||
|
||||||
|
normalizeSkuForDb(prev.sku, { storeLabel: prev.storeLabel || prev.store || "", url: prev.url }),
|
||||||
img: normImg(nowRaw.img) || normImg(prev.img),
|
img: normImg(nowRaw.img) || normImg(prev.img),
|
||||||
removed: false,
|
removed: false,
|
||||||
};
|
};
|
||||||
|
|
@ -137,9 +146,13 @@ function mergeDiscoveredIntoDb(prevDb, discovered) {
|
||||||
const prevPrice = normPrice(prev.price);
|
const prevPrice = normPrice(prev.price);
|
||||||
const nowPrice = normPrice(nowRaw.price);
|
const nowPrice = normPrice(nowRaw.price);
|
||||||
|
|
||||||
const prevSku = normalizeSkuForDb(prev.sku, { storeLabel: prev.storeLabel, url: prev.url });
|
const prevSku = normalizeSkuForDb(prev.sku, { storeLabel: prev.storeLabel || prev.store || "", url: prev.url });
|
||||||
const nowSku = normalizeSkuForDb(nowRaw.sku, { storeLabel: nowRaw.storeLabel, url }) || prevSku;
|
const nowSku =
|
||||||
|
normalizeSkuForDb(nowRaw.sku, {
|
||||||
|
storeLabel: nowRaw.storeLabel || nowRaw.store || prev.storeLabel || prev.store || "",
|
||||||
|
url,
|
||||||
|
}) || prevSku;
|
||||||
|
|
||||||
const prevImg = normImg(prev.img);
|
const prevImg = normImg(prev.img);
|
||||||
let nowImg = normImg(nowRaw.img);
|
let nowImg = normImg(nowRaw.img);
|
||||||
if (!nowImg) nowImg = prevImg;
|
if (!nowImg) nowImg = prevImg;
|
||||||
|
|
|
||||||
|
|
@ -232,10 +232,10 @@ function isSoftSkuKey(k) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function isUpcSkuKey(k) {
|
function isUnknownSkuKey2(k) {
|
||||||
const s = String(k || "").trim();
|
return String(k || "").trim().startsWith("u:");
|
||||||
return s.startsWith("upc:") || /^\d{12,14}$/.test(s);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function isABStoreLabel(label) {
|
function isABStoreLabel(label) {
|
||||||
|
|
@ -262,10 +262,19 @@ function scoreCanonical(allRows, skuKey) {
|
||||||
const real = isRealSkuKey(s) ? 1 : 0;
|
const real = isRealSkuKey(s) ? 1 : 0;
|
||||||
const ab = skuIsAB(allRows, s) ? 1 : 0;
|
const ab = skuIsAB(allRows, s) ? 1 : 0;
|
||||||
const bc = skuIsBC(allRows, s) ? 1 : 0;
|
const bc = skuIsBC(allRows, s) ? 1 : 0;
|
||||||
const upc = isUpcSkuKey(s) ? 1 : 0;
|
|
||||||
const soft = isSoftSkuKey(s) ? 1 : 0;
|
const soft = isSoftSkuKey(s) ? 1 : 0;
|
||||||
return real * 100 + ab * 25 - bc * 10 - upc * 60 - soft * 60 + (real ? 0 : -1000);
|
const unk = isUnknownSkuKey2(s) ? 1 : 0;
|
||||||
}
|
|
||||||
|
// Canonical preference:
|
||||||
|
// CSPC (best) > soft (upc/id) > other non-u keys > u: (worst)
|
||||||
|
let base = 0;
|
||||||
|
if (real) base = 1000;
|
||||||
|
else if (soft) base = 200;
|
||||||
|
else if (!unk) base = 100; // some other stable-ish non-u key
|
||||||
|
else base = -1000;
|
||||||
|
|
||||||
|
return base + ab * 25 - bc * 10;
|
||||||
|
}
|
||||||
|
|
||||||
function pickPreferredCanonical(allRows, skuKeys) {
|
function pickPreferredCanonical(allRows, skuKeys) {
|
||||||
let best = "";
|
let best = "";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue