mirror of
https://github.com/badlogic/heissepreise.git
synced 2024-06-30 12:27:15 +02:00
Merge branch 'main' of https://github.com/badlogic/heissepreise
This commit is contained in:
commit
614dddc815
|
@ -2,28 +2,14 @@ const axios = require("axios");
|
|||
const utils = require("./utils");
|
||||
const HITS = Math.floor(30000 + Math.random() * 2000);
|
||||
|
||||
const conversions = {
|
||||
Beutel: { unit: "stk", factor: 1 },
|
||||
Blatt: { unit: "stk", factor: 1 },
|
||||
Bund: { unit: "stk", factor: 1 },
|
||||
g: { unit: "g", factor: 1 },
|
||||
Gramm: { unit: "g", factor: 1 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
Kilogramm: { unit: "g", factor: 1000 },
|
||||
l: { unit: "ml", factor: 1000 },
|
||||
Liter: { unit: "ml", factor: 1000 },
|
||||
Meter: { unit: "cm", factor: 100 },
|
||||
Milliliter: { unit: "ml", factor: 1 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
Paar: { unit: "stk", factor: 1 },
|
||||
Packung: { unit: "stk", factor: 1 },
|
||||
Portion: { unit: "stk", factor: 1 },
|
||||
Rollen: { unit: "stk", factor: 1 },
|
||||
Stk: { unit: "stk", factor: 1 },
|
||||
Stück: { unit: "stk", factor: 1 },
|
||||
Teebeutel: { unit: "stk", factor: 1 },
|
||||
Waschgang: { unit: "wg", factor: 1 },
|
||||
Zentimeter: { unit: "cm", factor: 1 },
|
||||
const units = {
|
||||
beutel: { unit: "stk", factor: 1 },
|
||||
bund: { unit: "stk", factor: 1 },
|
||||
packung: { unit: "stk", factor: 1 },
|
||||
portion: { unit: "stk", factor: 1 },
|
||||
rollen: { unit: "stk", factor: 1 },
|
||||
teebeutel: { unit: "stk", factor: 1 },
|
||||
waschgang: { unit: "wg", factor: 1 },
|
||||
};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
|
@ -31,28 +17,31 @@ exports.getCanonical = function (item, today) {
|
|||
unit = "kg";
|
||||
|
||||
if (item.data.grammagePriceFactor == 1) {
|
||||
if (item.data.grammage.indexOf("Per ") == 0)
|
||||
item.data.grammage = item.data.grammage.replace("Per ", "");
|
||||
if (item.data.grammage.indexOf("Per ") == 0) item.data.grammage = item.data.grammage.replace("Per ", "");
|
||||
const grammage = item.data.grammage !== "" && item.data.grammage.trim().split(" ").length > 1 ? item.data.grammage : item.data.price.unit;
|
||||
if (grammage) [quantity, unit] = grammage.trim().split(" ").splice(0, 2);
|
||||
}
|
||||
|
||||
return utils.convertUnit({
|
||||
id: item.data.articleId,
|
||||
name: item.data.name,
|
||||
price: item.data.price.final,
|
||||
priceHistory: [{ date: today, price: item.data.price.final }],
|
||||
isWeighted : item.data.isWeightArticle,
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.data.attributes && item.data.attributes.includes("s_bio"),
|
||||
url: item.data.canonicalPath,
|
||||
}, conversions, 'billa');
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.data.articleId,
|
||||
name: item.data.name,
|
||||
price: item.data.price.final,
|
||||
priceHistory: [{ date: today, price: item.data.price.final }],
|
||||
isWeighted: item.data.isWeightArticle,
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.data.attributes && item.data.attributes.includes("s_bio"),
|
||||
url: item.data.canonicalPath,
|
||||
},
|
||||
units,
|
||||
"billa"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
const BILLA_SEARCH = `https://shop.billa.at/api/search/full?searchTerm=*&storeId=00-10&pageSize=${HITS}`;
|
||||
return (await axios.get(BILLA_SEARCH)).data.tiles;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "https://shop.billa.at";
|
||||
exports.urlBase = "https://shop.billa.at";
|
||||
|
|
|
@ -1,36 +1,32 @@
|
|||
const axios = require("axios");
|
||||
const utils = require("./utils");
|
||||
|
||||
const conversions = {
|
||||
g: { unit: "g", factor: 1 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
l: { unit: "ml", factor: 1000 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
St: { unit: "stk", factor: 1 },
|
||||
Wl: { unit: "wg", factor: 1 },
|
||||
m: { unit: "cm", factor: 100 },
|
||||
mm: { unit: "cm", factor: 0.1 },
|
||||
Bl: { unit: "stk", factor: 1 },
|
||||
Btl: { unit: "stk", factor: 1 },
|
||||
Paar: { unit: "stk", factor: 1 },
|
||||
Portion: { unit: "stk", factor: 1 },
|
||||
Satz: { unit: "stk", factor: 1 },
|
||||
Tablette: { unit: "stk", factor: 1 },
|
||||
const units = {
|
||||
wl: { unit: "wg", factor: 1 },
|
||||
bl: { unit: "stk", factor: 1 },
|
||||
btl: { unit: "stk", factor: 1 },
|
||||
portion: { unit: "stk", factor: 1 },
|
||||
satz: { unit: "stk", factor: 1 },
|
||||
tablette: { unit: "stk", factor: 1 },
|
||||
};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
let quantity = item.netQuantityContent || item.basePriceQuantity;
|
||||
let unit = item.contentUnit || item.basePriceUnit;
|
||||
return utils.convertUnit({
|
||||
id: item.gtin,
|
||||
name: `${item.brandName} ${item.title}`,
|
||||
price: item.price.value,
|
||||
priceHistory: [{ date: today, price: item.price.value }],
|
||||
unit,
|
||||
quantity,
|
||||
...(item.brandName === "dmBio" || (item.name ? (item.name.startsWith("Bio ") | item.name.startsWith("Bio-")) : false)) && {bio: true},
|
||||
}, conversions, 'dmDe');
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.gtin,
|
||||
name: `${item.brandName} ${item.title}`,
|
||||
price: item.price.value,
|
||||
priceHistory: [{ date: today, price: item.price.value }],
|
||||
unit,
|
||||
quantity,
|
||||
...((item.brandName === "dmBio" || (item.name ? item.name.startsWith("Bio ") | item.name.startsWith("Bio-") : false)) && { bio: true }),
|
||||
},
|
||||
units,
|
||||
"dmDe"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
const DM_BASE_URL = `https://product-search.services.dmtech.com/de/search/crawl?pageSize=1000&`;
|
||||
|
@ -89,6 +85,6 @@ exports.fetchData = async function () {
|
|||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}
|
||||
return dmItems;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "https://www.dm.de/product-p";
|
||||
exports.urlBase = "https://www.dm.de/product-p";
|
||||
|
|
52
stores/dm.js
52
stores/dm.js
|
@ -1,37 +1,33 @@
|
|||
const axios = require("axios");
|
||||
const utils = require("./utils");
|
||||
|
||||
const conversions = {
|
||||
'g': { unit: 'g', factor: 1 },
|
||||
'kg': { unit: 'g', factor: 1000 },
|
||||
'l': { unit: 'ml', factor: 1000 },
|
||||
'ml': { unit: 'ml', factor: 1 },
|
||||
'St': { unit: 'stk', factor: 1 },
|
||||
'Wl': { unit: 'wg', factor: 1 },
|
||||
'm': { unit: 'cm', factor: 100 },
|
||||
'mm': { unit: 'cm', factor: .1 },
|
||||
'Bl': { unit: 'stk', factor: 1 },
|
||||
'Btl': { unit: 'stk', factor: 1 },
|
||||
'Paar': { unit: 'stk', factor: 1 },
|
||||
'Portion': { unit: 'stk', factor: 1 },
|
||||
'Satz': { unit: 'stk', factor: 1 },
|
||||
'Tablette': { unit: 'stk', factor: 1 },
|
||||
'undefined': { unit: 'stk', factor: 1 },
|
||||
const units = {
|
||||
wl: { unit: "wg", factor: 1 },
|
||||
bl: { unit: "stk", factor: 1 },
|
||||
btl: { unit: "stk", factor: 1 },
|
||||
portion: { unit: "stk", factor: 1 },
|
||||
satz: { unit: "stk", factor: 1 },
|
||||
tablette: { unit: "stk", factor: 1 },
|
||||
undefined: { unit: "stk", factor: 1 },
|
||||
};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
let quantity = item.netQuantityContent || item.basePriceQuantity;
|
||||
let unit = item.contentUnit || item.basePriceUnit;
|
||||
return utils.convertUnit({
|
||||
id: item.gtin,
|
||||
name: `${item.brandName} ${item.title}`,
|
||||
price: item.price.value,
|
||||
priceHistory: [{ date: today, price: item.price.value }],
|
||||
unit,
|
||||
quantity,
|
||||
...(item.brandName === "dmBio" || (item.name ? (item.name.startsWith("Bio ") | item.name.startsWith("Bio-")) : false)) && {bio: true},
|
||||
}, conversions, 'dm');
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.gtin,
|
||||
name: `${item.brandName} ${item.title}`,
|
||||
price: item.price.value,
|
||||
priceHistory: [{ date: today, price: item.price.value }],
|
||||
unit,
|
||||
quantity,
|
||||
...((item.brandName === "dmBio" || (item.name ? item.name.startsWith("Bio ") | item.name.startsWith("Bio-") : false)) && { bio: true }),
|
||||
},
|
||||
units,
|
||||
"dm"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
const DM_BASE_URL = `https://product-search.services.dmtech.com/at/search/crawl?pageSize=1000&`;
|
||||
|
@ -90,6 +86,6 @@ exports.fetchData = async function () {
|
|||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}
|
||||
return dmItems;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "https://www.dm.at/product-p";
|
||||
exports.urlBase = "https://www.dm.at/product-p";
|
||||
|
|
|
@ -1,19 +1,9 @@
|
|||
const axios = require("axios");
|
||||
const utils = require("./utils");
|
||||
|
||||
const conversions = {
|
||||
const units = {
|
||||
"": { unit: "stk", factor: 1 },
|
||||
blatt: { unit: "stk", factor: 1 },
|
||||
g: { unit: "g", factor: 1 },
|
||||
gg: { unit: "g", factor: 1 },
|
||||
gramm: { unit: "g", factor: 1 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
cl: { unit: "ml", factor: 100 },
|
||||
l: { unit: "ml", factor: 1000 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
paar: { unit: "stk", factor: 1 },
|
||||
"stk.": { unit: "stk", factor: 1 },
|
||||
stück: { unit: "stk", factor: 1 },
|
||||
er: { unit: "stk", factor: 1 },
|
||||
teebeutel: { unit: "stk", factor: 1 },
|
||||
};
|
||||
|
@ -22,24 +12,28 @@ exports.getCanonical = function (item, today) {
|
|||
// try to read quantity and unit from product name
|
||||
const name = item.ProductName;
|
||||
let [quantity, unit] = utils.parseUnitAndQuantityAtEnd(name);
|
||||
if (conversions[unit] === undefined) {
|
||||
if (units[unit] === undefined) {
|
||||
// fallback: use given quantity and unit (including packaging)
|
||||
quantity = item.Unit;
|
||||
unit = item.UnitType;
|
||||
}
|
||||
|
||||
return utils.convertUnit({
|
||||
id: item.ProductID,
|
||||
name,
|
||||
price: item.Price,
|
||||
priceHistory: [{ date: today, price: item.Price }],
|
||||
isWeighted: item.IsBulk,
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.IsBio,
|
||||
url: `${item.CategorySEOName}/${item.SEOName}`
|
||||
}, conversions, 'hofer');
|
||||
}
|
||||
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.ProductID,
|
||||
name,
|
||||
price: item.Price,
|
||||
priceHistory: [{ date: today, price: item.Price }],
|
||||
isWeighted: item.IsBulk,
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.IsBio,
|
||||
url: `${item.CategorySEOName}/${item.SEOName}`,
|
||||
},
|
||||
units,
|
||||
"hofer"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
const HOFER_BASE_URL = `https://shopservice.roksh.at`;
|
||||
|
@ -82,6 +76,6 @@ exports.fetchData = async function () {
|
|||
}
|
||||
|
||||
return hoferItems;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "https://www.roksh.at/hofer/produkte/";
|
||||
|
|
|
@ -3,19 +3,12 @@ const utils = require("./utils");
|
|||
|
||||
const HITS = Math.floor(30000 + Math.random() * 2000);
|
||||
|
||||
const conversions = {
|
||||
"": {unit: "stk", factor: 1},
|
||||
"dosen": {unit: "stk", factor: 1},
|
||||
"blatt": {unit: "stk", factor: 1},
|
||||
"flasche": {unit: "stk", factor: 1},
|
||||
"flaschen": {unit: "stk", factor: 1},
|
||||
"l": {unit: "ml", factor: 1000},
|
||||
"liter": {unit: "ml", factor: 1000},
|
||||
"ml": {unit: "ml", factor: 1},
|
||||
"g": {unit: "g", factor: 1},
|
||||
"kg": {unit: "g", factor: 1000},
|
||||
"stk.": {unit: "stk", factor: 1},
|
||||
"pkg.": {unit: "stk", factor: 1},
|
||||
const units = {
|
||||
"": { unit: "stk", factor: 1 },
|
||||
dosen: { unit: "stk", factor: 1 },
|
||||
flasche: { unit: "stk", factor: 1 },
|
||||
flaschen: { unit: "stk", factor: 1 },
|
||||
"pkg.": { unit: "stk", factor: 1 },
|
||||
};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
|
@ -43,20 +36,24 @@ exports.getCanonical = function (item, today) {
|
|||
unit = unit.split("-")[0];
|
||||
}
|
||||
|
||||
return utils.convertUnit({
|
||||
id: item.productId,
|
||||
name: `${item.keyfacts?.supplementalDescription?.concat(" ") ?? ""}${item.fullTitle}`,
|
||||
price: item.price.price,
|
||||
priceHistory: [{ date: today, price: item.price.price }],
|
||||
unit,
|
||||
quantity,
|
||||
url: item.canonicalUrl,
|
||||
}, conversions, 'lidl');
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.productId,
|
||||
name: `${item.keyfacts?.supplementalDescription?.concat(" ") ?? ""}${item.fullTitle}`,
|
||||
price: item.price.price,
|
||||
priceHistory: [{ date: today, price: item.price.price }],
|
||||
unit,
|
||||
quantity,
|
||||
url: item.canonicalUrl,
|
||||
},
|
||||
units,
|
||||
"lidl"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function() {
|
||||
exports.fetchData = async function () {
|
||||
const LIDL_SEARCH = `https://www.lidl.at/p/api/gridboxes/AT/de/?max=${HITS}`;
|
||||
return (await axios.get(LIDL_SEARCH)).data.filter(item => !!item.price.price);
|
||||
}
|
||||
return (await axios.get(LIDL_SEARCH)).data.filter((item) => !!item.price.price);
|
||||
};
|
||||
|
||||
exports.urlBase = "https://www.lidl.at"
|
||||
exports.urlBase = "https://www.lidl.at";
|
||||
|
|
|
@ -1,25 +1,13 @@
|
|||
const axios = require("axios");
|
||||
const utils = require("./utils");
|
||||
|
||||
const conversions = {
|
||||
cm: { unit: "cm", factor: 1 },
|
||||
dag: { unit: "g", factor: 10 },
|
||||
dl: { unit: "ml", factor: 10 },
|
||||
const units = {
|
||||
grm: { unit: "g", factor: 1 },
|
||||
kgm: { unit: "g", factor: 1000 },
|
||||
ltr: { unit: "ml", factor: 1000 },
|
||||
mlt: { unit: "ml", factor: 1 },
|
||||
mtr: { unit: "m", factor: 1 },
|
||||
stk: { unit: "stk", factor: 1 },
|
||||
"stk.": { unit: "stk", factor: 1 },
|
||||
g: { unit: "g", factor: 1 },
|
||||
anw: { unit: "stk", factor: 1 },
|
||||
l: { unit: "ml", factor: 1000 },
|
||||
m: { unit: "cm", factor: 100 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
paar: { unit: "stk", factor: 1 },
|
||||
stück: { unit: "stk", factor: 1 },
|
||||
"bl.": { unit: "stk", factor: 1 },
|
||||
pkg: { unit: "stk", factor: 1 },
|
||||
gr: { unit: "g", factor: 1 },
|
||||
|
@ -34,22 +22,26 @@ exports.getCanonical = function (item, today) {
|
|||
quantity = q[0] ?? quantity;
|
||||
unit = q[1];
|
||||
}
|
||||
if (!(unit in conversions)) {
|
||||
if (!(unit in units)) {
|
||||
unit = "stk";
|
||||
}
|
||||
const isWeighted = (item.mixins.productCustomAttributes?.packagingDescription ?? "").startsWith("Gewichtsware");
|
||||
|
||||
return utils.convertUnit({
|
||||
id: item.code,
|
||||
name: item.name[0],
|
||||
isWeighted,
|
||||
price: isWeighted ? item.prices[0].effectiveAmount : item.prices[0].presentationPrice.effectiveAmount,
|
||||
priceHistory: [{ date: today, price: item.prices[0].presentationPrice.effectiveAmount }],
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.mixins.mpreisAttributes.properties?.includes('BIO'),
|
||||
}, conversions, 'mpreis');
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.code,
|
||||
name: item.name[0],
|
||||
isWeighted,
|
||||
price: isWeighted ? item.prices[0].effectiveAmount : item.prices[0].presentationPrice.effectiveAmount,
|
||||
priceHistory: [{ date: today, price: item.prices[0].presentationPrice.effectiveAmount }],
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.mixins.mpreisAttributes.properties?.includes("BIO"),
|
||||
},
|
||||
units,
|
||||
"mpreis"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
const MPREIS_URL = `https://ax2ixv4hll-dsn.algolia.net/1/indexes/prod_mpreis_8450/browse?X-Algolia-API-Key=NmJlMTI0NjY1NGU4MDUwYTRlMmYzYWFjOWFlY2U4MGFkNGZjMDY2NmNjNjQzNWY3OWJlNDY4OTY0ZjEwOTEwYWZpbHRlcnM9cHVibGlzaGVk&X-Algolia-Application-Id=AX2IXV4HLL&X-Algolia-Agent=Vue.js`;
|
||||
|
@ -63,6 +55,6 @@ exports.fetchData = async function () {
|
|||
cursor = res.cursor;
|
||||
}
|
||||
return mpreisItems;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "https://www.mpreis.at/shop/p/"
|
||||
exports.urlBase = "https://www.mpreis.at/shop/p/";
|
||||
|
|
|
@ -2,36 +2,35 @@ const axios = require("axios");
|
|||
const utils = require("./utils");
|
||||
const MAXITEMS = 10000;
|
||||
|
||||
const conversions = {
|
||||
const units = {
|
||||
bd: { unit: "stk", factor: 1 },
|
||||
g: { unit: "g", factor: 1 },
|
||||
gr: { unit: "g", factor: 1 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
lt: { unit: "ml", factor: 1000 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
pk: { unit: "stk", factor: 1 },
|
||||
pa: { unit: "stk", factor: 1 },
|
||||
rl: { unit: "stk", factor: 1 },
|
||||
st: { unit: "stk", factor: 1 },
|
||||
tb: { unit: "stk", factor: 1 },
|
||||
wg: { unit: "wg", factor: 1 },
|
||||
};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
let quantity = item.amount;
|
||||
let unit = item.volumeLabelKey;
|
||||
return utils.convertUnit({
|
||||
id: item.productId,
|
||||
name: item.name,
|
||||
price: item.price.regular.value / 100,
|
||||
priceHistory: [{ date: today, price: item.price.regular.value / 100 }],
|
||||
isWeighted: item.isWeightArticle,
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.name.toLowerCase().includes("bio") && !item.name.toLowerCase().includes("fabio"),
|
||||
url: item.slug,
|
||||
}, conversions, 'penny');
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.productId,
|
||||
name: item.name,
|
||||
price: item.price.regular.value / 100,
|
||||
priceHistory: [{ date: today, price: item.price.regular.value / 100 }],
|
||||
isWeighted: item.isWeightArticle,
|
||||
unit,
|
||||
quantity,
|
||||
bio: item.name.toLowerCase().includes("bio") && !item.name.toLowerCase().includes("fabio"),
|
||||
url: item.slug,
|
||||
},
|
||||
units,
|
||||
"penny"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
hits = 100;
|
||||
|
@ -46,6 +45,6 @@ exports.fetchData = async function () {
|
|||
result = result.concat(data.results);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "https://www.penny.at/produkte/"
|
||||
exports.urlBase = "https://www.penny.at/produkte/";
|
||||
|
|
|
@ -3,31 +3,14 @@ const util = require("util");
|
|||
const exec = util.promisify(require("child_process").exec);
|
||||
const utils = require("./utils");
|
||||
|
||||
const conversions = {
|
||||
Beutel: { unit: "stk", factor: 1 },
|
||||
Blatt: { unit: "stk", factor: 1 },
|
||||
Bund: { unit: "stk", factor: 1 },
|
||||
g: { unit: "g", factor: 1 },
|
||||
Gramm: { unit: "g", factor: 1 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
Kilogramm: { unit: "g", factor: 1 },
|
||||
l: { unit: "ml", factor: 1000 },
|
||||
Liter: { unit: "ml", factor: 1000 },
|
||||
cm: { unit: "cm", factor: 1 },
|
||||
m: { unit: "cm", factor: 100 },
|
||||
Meter: { unit: "cm", factor: 100 },
|
||||
Milliliter: { unit: "ml", factor: 1 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
Paar: { unit: "stk", factor: 1 },
|
||||
Packung: { unit: "stk", factor: 1 },
|
||||
Portion: { unit: "stk", factor: 1 },
|
||||
Rollen: { unit: "stk", factor: 1 },
|
||||
Stk: { unit: "stk", factor: 1 },
|
||||
Stück: { unit: "stk", factor: 1 },
|
||||
stück: { unit: "stk", factor: 1 },
|
||||
Teebeutel: { unit: "stk", factor: 1 },
|
||||
Waschgang: { unit: "wg", factor: 1 },
|
||||
Zentimeter: { unit: "cm", factor: 1 },
|
||||
const units = {
|
||||
beutel: { unit: "stk", factor: 1 },
|
||||
bund: { unit: "stk", factor: 1 },
|
||||
packung: { unit: "stk", factor: 1 },
|
||||
portion: { unit: "stk", factor: 1 },
|
||||
rollen: { unit: "stk", factor: 1 },
|
||||
teebeutel: { unit: "stk", factor: 1 },
|
||||
waschgang: { unit: "wg", factor: 1 },
|
||||
};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
|
@ -61,17 +44,21 @@ exports.getCanonical = function (item, today) {
|
|||
}
|
||||
|
||||
let price = Number.parseFloat(item.currentPrice.split(" ")[0].replace(",", "."));
|
||||
return utils.convertUnit({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
price,
|
||||
priceHistory: [{ date: today, price }],
|
||||
isWeighted: false,
|
||||
unit,
|
||||
quantity,
|
||||
bio: false,
|
||||
}, conversions, "reweDe");
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
price,
|
||||
priceHistory: [{ date: today, price }],
|
||||
isWeighted: false,
|
||||
unit,
|
||||
quantity,
|
||||
bio: false,
|
||||
},
|
||||
units,
|
||||
"reweDe"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
// For some unholy reason, Axios returns 403 when accessing the endpoint
|
||||
|
@ -115,6 +102,6 @@ exports.fetchData = async function () {
|
|||
);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "";
|
||||
exports.urlBase = "";
|
||||
|
|
|
@ -2,24 +2,10 @@ const axios = require("axios");
|
|||
const utils = require("./utils");
|
||||
const HITS = Math.floor(30000 + Math.random() * 2000);
|
||||
|
||||
const conversions = {
|
||||
g: { unit: "g", factor: 1 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
l: { unit: "ml", factor: 1000 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
stk: { unit: "stk", factor: 1 },
|
||||
stück: { unit: "stk", factor: 1 },
|
||||
const units = {
|
||||
"100ml": { unit: "ml", factor: 100 },
|
||||
wg: { unit: "wg", factor: 1 },
|
||||
"500ml": { unit: "ml", factor: 100 },
|
||||
"100g": { unit: "g", factor: 100 },
|
||||
m: { unit: "cm", factor: 100 },
|
||||
cm: { unit: "cm", factor: 100 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
meter: { unit: "cm", factor: 100 },
|
||||
mm: { unit: "cm", factor: 0.1 },
|
||||
"stk.": { unit: "cm", factor: 0.1 },
|
||||
cl: { unit: "ml", factor: 10 },
|
||||
blatt: { unit: "stk", factor: 1 },
|
||||
};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
|
@ -33,19 +19,16 @@ exports.getCanonical = function (item, today) {
|
|||
let description = item.masterValues["short-description-3"] ?? item.masterValues["short-description-2"];
|
||||
if (!description || description.length == 0) {
|
||||
description = (item.masterValues["short-description"] ?? item.masterValues.name).toLowerCase();
|
||||
if (description.endsWith("per kg"))
|
||||
[quantity, unit] = [1, "kg"];
|
||||
else if (description.endsWith("im topf"))
|
||||
[quantity, unit] = [1, "kg"];
|
||||
else
|
||||
[quantity, unit] = [1, "stk."];
|
||||
if (description.endsWith("per kg")) [quantity, unit] = [1, "kg"];
|
||||
else if (description.endsWith("im topf")) [quantity, unit] = [1, "kg"];
|
||||
else [quantity, unit] = [1, "stk."];
|
||||
} else {
|
||||
const s = description.replace(" EINWEG", "").replace(" MEHRWEG", "").trim();
|
||||
const q = utils.parseUnitAndQuantityAtEnd(s);
|
||||
quantity = q[0];
|
||||
unit = q[1];
|
||||
}
|
||||
if (conversions[unit] === undefined) {
|
||||
if (!(unit in units) && !(unit in utils.globalUnits)) {
|
||||
// use price per unit to calculate quantity (less accurate)
|
||||
let [unitPrice, unit_] = item.masterValues["price-per-unit"].split("/");
|
||||
unitPrice = parseFloat(unitPrice.replace("€", ""));
|
||||
|
@ -53,24 +36,28 @@ exports.getCanonical = function (item, today) {
|
|||
unit = unit_.toLowerCase();
|
||||
}
|
||||
|
||||
return utils.convertUnit({
|
||||
id: item.masterValues["code-internal"],
|
||||
sparId: item.masterValues["product-number"],
|
||||
name: item.masterValues.title + " " + (item.masterValues["short-description"] ?? item.masterValues.name).toLowerCase(),
|
||||
price,
|
||||
priceHistory: [{ date: today, price }],
|
||||
unit,
|
||||
quantity,
|
||||
isWeighted: item.masterValues['item-type'] === 'WeightProduct',
|
||||
bio: item.masterValues.biolevel === "Bio",
|
||||
url: item.masterValues.url,
|
||||
}, conversions, 'spar');
|
||||
}
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.masterValues["code-internal"],
|
||||
sparId: item.masterValues["product-number"],
|
||||
name: item.masterValues.title + " " + (item.masterValues["short-description"] ?? item.masterValues.name).toLowerCase(),
|
||||
price,
|
||||
priceHistory: [{ date: today, price }],
|
||||
unit,
|
||||
quantity,
|
||||
isWeighted: item.masterValues["item-type"] === "WeightProduct",
|
||||
bio: item.masterValues.biolevel === "Bio",
|
||||
url: item.masterValues.url,
|
||||
},
|
||||
units,
|
||||
"spar"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
const SPAR_SEARCH = `https://search-spar.spar-ics.com/fact-finder/rest/v4/search/products_lmos_at?query=*&q=*&page=1&hitsPerPage=${HITS}`;
|
||||
const rawItems = (await axios.get(SPAR_SEARCH)).data.hits;
|
||||
return rawItems?.hits || rawItems;
|
||||
}
|
||||
};
|
||||
|
||||
exports.urlBase = "https://www.interspar.at/shop/lebensmittel"
|
||||
exports.urlBase = "https://www.interspar.at/shop/lebensmittel";
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
const axios = require("axios");
|
||||
const utils = require("./utils");
|
||||
const HTMLParser = require("node-html-parser");
|
||||
|
||||
const units = {};
|
||||
|
||||
exports.getCanonical = function (item, today) {
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
price: item.price,
|
||||
priceHistory: [{ date: today, price: item.price }],
|
||||
unit: item.unit,
|
||||
bio: item.name.toLowerCase().includes('bio'),
|
||||
url: item.canonicalUrl,
|
||||
};
|
||||
let [quantity, unit] = utils.parseUnitAndQuantityAtEnd(item.unit.replace("/ EINWEG", "").replace("/ MEHRWEG", ""));
|
||||
return utils.convertUnit(
|
||||
{
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
price: item.price,
|
||||
priceHistory: [{ date: today, price: item.price }],
|
||||
quantity,
|
||||
unit,
|
||||
bio: item.name.toLowerCase().includes("bio"),
|
||||
url: item.canonicalUrl,
|
||||
},
|
||||
units,
|
||||
"unimarkt"
|
||||
);
|
||||
};
|
||||
|
||||
exports.fetchData = async function () {
|
||||
|
@ -50,4 +59,4 @@ exports.fetchData = async function () {
|
|||
return unimarktItems;
|
||||
};
|
||||
|
||||
exports.urlBase = "https://shop.unimarkt.at"
|
||||
exports.urlBase = "https://shop.unimarkt.at";
|
||||
|
|
|
@ -1,12 +1,41 @@
|
|||
exports.globalUnits = {
|
||||
"stk.": { unit: "stk", factor: 1 },
|
||||
blatt: { unit: "stk", factor: 1 },
|
||||
paar: { unit: "stk", factor: 1 },
|
||||
stk: { unit: "stk", factor: 1 },
|
||||
st: { unit: "stk", factor: 1 },
|
||||
stück: { unit: "stk", factor: 1 },
|
||||
mm: { unit: "cm", factor: 0.1 },
|
||||
cm: { unit: "cm", factor: 1 },
|
||||
zentimeter: { unit: "cm", factor: 1 },
|
||||
m: { unit: "cm", factor: 100 },
|
||||
meter: { unit: "cm", factor: 100 },
|
||||
g: { unit: "g", factor: 1 },
|
||||
gramm: { unit: "g", factor: 1 },
|
||||
dag: { unit: "g", factor: 10 },
|
||||
kg: { unit: "g", factor: 1000 },
|
||||
kilogramm: { unit: "g", factor: 1000 },
|
||||
ml: { unit: "ml", factor: 1 },
|
||||
milliliter: { unit: "ml", factor: 1 },
|
||||
dl: { unit: "ml", factor: 10 },
|
||||
cl: { unit: "ml", factor: 100 },
|
||||
l: { unit: "ml", factor: 1000 },
|
||||
liter: { unit: "ml", factor: 1000 },
|
||||
wg: { unit: "wg", factor: 1 },
|
||||
};
|
||||
|
||||
exports.convertUnit = function (item, units, store) {
|
||||
if (!(item.unit in units)) {
|
||||
console.error(`Unknown unit in ${store}: '${item.unit}' in item ${item.name}`);
|
||||
if (typeof item.quantity == "string") item.quantity = parseFloat(item.quantity.replace(",", "."));
|
||||
|
||||
let unit = item.unit;
|
||||
if (typeof unit === "string") unit = unit.toLowerCase();
|
||||
|
||||
const conv = unit in exports.globalUnits ? exports.globalUnits[unit] : units[unit];
|
||||
if (conv === undefined) {
|
||||
console.error(`Unknown unit in ${store}: '${unit}' in item ${item.name}`);
|
||||
return item;
|
||||
}
|
||||
|
||||
if (typeof item.quantity == "string") item.quantity = parseFloat(item.quantity.replace(",", "."));
|
||||
|
||||
const conv = units[item.unit];
|
||||
item.quantity = conv.factor * item.quantity;
|
||||
item.unit = conv.unit;
|
||||
return item;
|
||||
|
|
Loading…
Reference in New Issue
Block a user