feat: Přidání funkce pro manuální refresh jidel.
This commit is contained in:
@@ -1,11 +1,52 @@
|
||||
import express, { Request, Response } from "express";
|
||||
import { getLogin, getTrusted } from "../auth";
|
||||
import { addChoice, getDateForWeekIndex, getToday, removeChoice, removeChoices, updateDepartureTime, updateNote, getRestaurantMenu } from "../service";
|
||||
import { addChoice, getDateForWeekIndex, getToday, removeChoice, removeChoices, updateDepartureTime, updateNote, getRestaurantMenu, fetchRestaurantWeekMenuData, saveRestaurantWeekMenu } from "../service";
|
||||
import { getDayOfWeekIndex, parseToken, getFirstWorkDayOfWeek } from "../utils";
|
||||
import { getWebsocket } from "../websocket";
|
||||
import { callNotifikace } from "../notifikace";
|
||||
import { AddChoiceData, ChangeDepartureTimeData, RemoveChoiceData, RemoveChoicesData, UdalostEnum, UpdateNoteData } from "../../../types/gen/types.gen";
|
||||
|
||||
|
||||
// RateLimit na refresh endpoint
|
||||
interface RateLimitEntry {
|
||||
count: number;
|
||||
resetTime: number;
|
||||
}
|
||||
const rateLimits: Record<string, RateLimitEntry> = {};
|
||||
const RATE_LIMIT = 1; // maximální počet požadavků za minutu
|
||||
const RATE_LIMIT_WINDOW = 30 * 60 * 1000; // je to v ms (x * 1min)
|
||||
|
||||
// Kontrola ratelimitu
|
||||
function checkRateLimit(key: string, limit: number = RATE_LIMIT): boolean {
|
||||
const now = Date.now();
|
||||
|
||||
// Vyčištění starých záznamů
|
||||
Object.keys(rateLimits).forEach(k => {
|
||||
if (rateLimits[k].resetTime < now) {
|
||||
delete rateLimits[k];
|
||||
}
|
||||
});
|
||||
|
||||
// Kontrola, že záznam existuje a platí
|
||||
if (rateLimits[key] && rateLimits[key].resetTime > now) {
|
||||
// Záznam platí a kontroluje se limit
|
||||
if (rateLimits[key].count >= limit) {
|
||||
return false; // Překročen limit
|
||||
}
|
||||
|
||||
// ++ xd
|
||||
rateLimits[key].count++;
|
||||
return true;
|
||||
} else {
|
||||
// + klic
|
||||
rateLimits[key] = {
|
||||
count: 1,
|
||||
resetTime: now + RATE_LIMIT_WINDOW
|
||||
};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ověří a vrátí index dne v týdnu z požadavku, za předpokladu, že byl předán, a je zároveň
|
||||
* roven nebo vyšší indexu dnešního dne.
|
||||
@@ -144,21 +185,77 @@ router.post("/jdemeObed", async (req, res, next) => {
|
||||
// /api/food/refresh?type=week&heslo=docasnyheslo
|
||||
router.get("/refresh", async (req: Request, res: Response) => {
|
||||
const { type, heslo } = req.query as { type?: string; heslo?: string };
|
||||
if (heslo !== "docasnyheslo") {
|
||||
if (heslo !== "docasnyheslo" && heslo !== "tohleheslopavelnesmizjistit123") {
|
||||
return res.status(403).json({ error: "Neplatné heslo" });
|
||||
}
|
||||
if (type !== "week") {
|
||||
if (!checkRateLimit("refresh") && heslo !== "tohleheslopavelnesmizjistit123") {
|
||||
return res.status(429).json({ error: "Refresh už se zavolal, chvíli počkej :))" });
|
||||
}
|
||||
if (type !== "week" && type !== "day") {
|
||||
return res.status(400).json({ error: "Neznámý typ refresh" });
|
||||
}
|
||||
if (type === "day") {
|
||||
return res.status(400).json({ error: "ještě neumim TODO..." });
|
||||
}
|
||||
try {
|
||||
// Pro všechny restaurace refreshni menu na aktuální týden
|
||||
const restaurants = ["SLADOVNICKA", "TECHTOWER", "ZASTAVKAUMICHALA", "SENKSERIKOVA"] as const;
|
||||
const firstDay = getFirstWorkDayOfWeek(getToday());
|
||||
const results: Record<string, any> = {};
|
||||
const successfulRestaurants: string[] = [];
|
||||
const failedRestaurants: string[] = [];
|
||||
|
||||
// Nejdříve načíst všechna data bez ukládání
|
||||
for (const rest of restaurants) {
|
||||
results[rest] = await getRestaurantMenu(rest, firstDay, true);
|
||||
try {
|
||||
const weekData = await fetchRestaurantWeekMenuData(rest, firstDay);
|
||||
results[rest] = weekData;
|
||||
|
||||
// Kontrola validity dat
|
||||
if (weekData && weekData.length > 0 &&
|
||||
weekData.some(dayMenu => dayMenu && dayMenu.length > 0)) {
|
||||
successfulRestaurants.push(rest);
|
||||
} else {
|
||||
failedRestaurants.push(rest);
|
||||
results[rest] = { error: "Žádná validní data" };
|
||||
}
|
||||
} catch (error) {
|
||||
failedRestaurants.push(rest);
|
||||
results[rest] = { error: `Chyba při načítání: ${error}` };
|
||||
}
|
||||
}
|
||||
res.status(200).json({ ok: true, refreshed: results });
|
||||
|
||||
// Pokud se nepodařilo načíst žádnou restauraci
|
||||
if (successfulRestaurants.length === 0) {
|
||||
return res.status(400).json({
|
||||
error: "Nepodařilo se získat validní data z žádné restaurace",
|
||||
failed: failedRestaurants,
|
||||
results: results
|
||||
});
|
||||
}
|
||||
|
||||
// Uložit pouze validní data
|
||||
for (const rest of successfulRestaurants) {
|
||||
try {
|
||||
await saveRestaurantWeekMenu(rest as any, firstDay, results[rest]);
|
||||
} catch (error) {
|
||||
console.error(`Chyba při ukládání dat pro ${rest}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Připravit odpověď
|
||||
const response: any = {
|
||||
ok: true,
|
||||
refreshed: results,
|
||||
successful: successfulRestaurants
|
||||
};
|
||||
|
||||
if (failedRestaurants.length > 0) {
|
||||
response.warning = `Nepodařilo se načíst: ${failedRestaurants.join(', ')}`;
|
||||
response.failed = failedRestaurants;
|
||||
}
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (e: any) {
|
||||
res.status(500).json({ error: e?.message || "Chyba při refreshi" });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user