119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
import $ from 'cheerio';
|
|
import rp from 'request-promise';
|
|
import os from 'os';
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
|
|
type PizzaSize = {
|
|
size: string,
|
|
pizzaPrice: number,
|
|
boxPrice: number,
|
|
price: number
|
|
}
|
|
|
|
type Pizza = {
|
|
name: string,
|
|
ingredients: string[],
|
|
sizes: PizzaSize[],
|
|
}
|
|
|
|
// TODO mělo by být konfigurovatelné proměnnou z prostředí s tímhle jako default
|
|
const baseUrl = 'https://www.pizzachefie.cz';
|
|
const pizzyUrl = `${baseUrl}/pizzy.html?pobocka=plzen`;
|
|
|
|
// URL na Food API - získání jídelních lístků restaurací
|
|
const foodUrl = process.env.FOOD_API_URL || 'http://localhost:3002';
|
|
|
|
const buildPizzaUrl = (pizzaUrl: string) => {
|
|
return `${baseUrl}/${pizzaUrl}`;
|
|
}
|
|
|
|
// Ceny krabic dle velikosti
|
|
const boxPrices: { [key: string]: number } = {
|
|
"30cm": 13,
|
|
"35cm": 15,
|
|
"40cm": 18,
|
|
"50cm": 25
|
|
}
|
|
|
|
/**
|
|
* Stáhne a scrapne aktuální pizzy ze stránek Pizza Chefie.
|
|
*/
|
|
const downloadPizzy = async () => {
|
|
// Získáme seznam pizz
|
|
const html = await rp(pizzyUrl);
|
|
const links = $('.vypisproduktu > div > h4 > a', html)
|
|
const urls = [];
|
|
for (let i = 0; i < links.length; i++) {
|
|
if (links[i].name === 'a' && links[i].attribs?.href) {
|
|
const pizzaUrl = links[i].attribs?.href;
|
|
urls.push(buildPizzaUrl(pizzaUrl));
|
|
}
|
|
}
|
|
// Scrapneme jednotlivé pizzy
|
|
const result: Pizza[] = [];
|
|
for (let i = 0; i < urls.length; i++) {
|
|
const pizzaUrl = urls[i];
|
|
const pizzaHtml = await rp(pizzaUrl);
|
|
// Název
|
|
const name = $('.produkt > h2', pizzaHtml).first().text()
|
|
// Přísady
|
|
const ingredients: string[] = []
|
|
const ingredientsHtml = $('.prisady > li', pizzaHtml);
|
|
ingredientsHtml.each((i, elm) => {
|
|
ingredients.push($(elm).text());
|
|
})
|
|
// Velikosti
|
|
const sizes: PizzaSize[] = [];
|
|
const a = $('.varianty > li > a', pizzaHtml);
|
|
a.each((i, elm) => {
|
|
// TODO nedoděláno
|
|
// const size = $('span', elm).text();
|
|
// const priceKc = $(elm).text().split(size).pop().trim();
|
|
// const price = Number.parseInt(priceKc.split(" Kč")[0]);
|
|
// sizes.push({ size: size, pizzaPrice: price, boxPrice: boxPrices[size], price: price + boxPrices[size] });
|
|
})
|
|
result.push({
|
|
name: name,
|
|
ingredients: ingredients,
|
|
sizes: sizes,
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Vrátí pizzy z tempu, nebo čerstvě stažené, pokud v tempu nejsou.
|
|
*/
|
|
export const fetchPizzy = async () => {
|
|
const tmpDir = os.tmpdir();
|
|
const date_ob = new Date();
|
|
const date = ("0" + date_ob.getDate()).slice(-2);
|
|
const month = ("0" + (date_ob.getMonth() + 1)).slice(-2);
|
|
const year = date_ob.getFullYear();
|
|
const dateStr = year + "-" + month + "-" + date;
|
|
const dataPath = path.join(tmpDir, `chefie-${dateStr}.json`);
|
|
|
|
if (fs.existsSync(dataPath)) {
|
|
console.log(`Soubor pro ${dataPath} již existuje, bude použit.`);
|
|
const rawdata = fs.readFileSync(dataPath);
|
|
return JSON.parse(rawdata.toString());
|
|
} else {
|
|
console.log(`Soubor pro ${dataPath} neexistuje, stahuji...`);
|
|
const pizzy = await downloadPizzy();
|
|
fs.writeFileSync(dataPath, JSON.stringify(pizzy));
|
|
console.log(`Zapsán ${dataPath}`);
|
|
return pizzy;
|
|
}
|
|
}
|
|
|
|
// TODO tohle sem absolutně nepatří! dát do vlastní servisky!
|
|
export const fetchFood = async () => {
|
|
try {
|
|
const json = await rp(foodUrl);
|
|
return JSON.parse(json);
|
|
} catch (error) {
|
|
console.error("Chyba při volání Food API", error);
|
|
return {};
|
|
}
|
|
} |