Files
Luncher/server/src/chefie.ts
T
mates 8aef00ab05
CI / Generate TypeScript types (push) Successful in 21s
CI / Build server (push) Successful in 25s
CI / Server unit tests (push) Successful in 55s
CI / Build client (push) Successful in 33s
CI / Playwright E2E tests (push) Successful in 1m20s
CI / Build and push Docker image (push) Successful in 35s
CI / Notify (push) Successful in 2s
fix: počítání částek v haléřích z důvodu přesnosti
2026-05-07 13:09:15 +02:00

126 lines
4.2 KiB
TypeScript

import axios from 'axios';
import { load } from 'cheerio';
import { getPizzaListMock, getSalatListMock } from './mock';
import { Salat } from '../../types/gen/types.gen';
// TODO přesunout do types
type PizzaSize = {
varId: number,
size: string,
pizzaPrice: number,
boxPrice: number,
price: number
}
// TODO přesunout do types
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`;
const salayUrl = `${baseUrl}/salaty.html`;
const buildPizzaUrl = (pizzaUrl: string) => {
return `${baseUrl}/${pizzaUrl}`;
}
// Ceny krabic dle velikosti v haléřích
const boxPrices: { [key: string]: number } = {
"30cm": 1300,
"35cm": 1500,
"40cm": 1800,
"50cm": 2500
}
// Cena obalu pro salát v haléřích
const SALAT_BOX_PRICE = 1300;
/**
* Stáhne a scrapne aktuální pizzy ze stránek Pizza Chefie.
*
* @param mock zda vrátit pouze mock data
*/
export async function downloadPizzy(mock: boolean): Promise<Pizza[]> {
if (mock) {
// Záměrné zpoždění pro testování
return new Promise((resolve) => setTimeout(() => resolve(getPizzaListMock()), 3000));
}
// Získáme seznam pizz
const html = await axios.get(pizzyUrl).then(res => res.data);
const $ = load(html);
const links = $('.vypisproduktu > div > h4 > a');
const urls = [];
for (const element of links) {
if (element.name === 'a' && element.attribs?.href) {
const pizzaUrl = element.attribs?.href;
urls.push(buildPizzaUrl(pizzaUrl));
}
}
// Scrapneme jednotlivé pizzy
const result: Pizza[] = [];
for (const element of urls) {
const pizzaUrl = element;
const pizzaHtml = await axios.get(pizzaUrl).then(res => res.data);
// 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) => {
const varId = Number.parseInt(elm.attribs.href.split('?varianta=')[1].trim());
const size = $($(elm).contents().get(0)).text().trim();
const price = Number.parseInt($($(elm).contents().get(1)).text().trim().split(" Kč")[0]) * 100;
sizes.push({ varId, size, pizzaPrice: price, boxPrice: boxPrices[size], price: price + boxPrices[size] });
})
result.push({
name: name,
ingredients: ingredients,
sizes: sizes,
});
}
return result;
}
/**
* Stáhne a scrapne aktuální saláty ze stránek Pizza Chefie.
* Příplatek za obal je pro každý salát pevně 13 Kč.
*
* @param mock zda vrátit pouze mock data
*/
export async function downloadSalaty(mock: boolean): Promise<Salat[]> {
if (mock) {
return new Promise((resolve) => setTimeout(() => resolve(getSalatListMock()), 1000));
}
const html = await axios.get(salayUrl).then(res => res.data);
const $ = load(html);
const links = $('.vypisproduktu > div > h4 > a');
const urls = [];
for (const element of links) {
if (element.name === 'a' && element.attribs?.href) {
urls.push(buildPizzaUrl(element.attribs.href));
}
}
const result: Salat[] = [];
for (const url of urls) {
const salatHtml = await axios.get(url).then(res => res.data);
const name = $('.produkt > h2', salatHtml).first().text().trim();
const ingredients: string[] = [];
$('.prisady > li', salatHtml).each((i, elm) => {
ingredients.push($(elm).text());
});
const priceText = $('.cena > span', salatHtml).first().text().trim();
const price = Number.parseInt(priceText.split(' Kč')[0]) * 100;
result.push({ name, ingredients, price: price + SALAT_BOX_PRICE });
}
return result;
}