diff --git a/mealplans.js b/mealplans.js index 4811a7d..100dfeb 100644 --- a/mealplans.js +++ b/mealplans.js @@ -30,16 +30,22 @@ async function fetchMealplans() { * @param {*} mealplans an object with meal plans * @param {string | number} timestamp the timestamp of the date * @param {string} defaultMessage the default message in case no meal plan is found + * @param {number | string} today the date of today, only required for tests * @returns {string} the meal plan for the date or the default message if no meal plan is found */ -function getMealplanOnDate(mealplans, timestamp, defaultMessage) { +function getMealplanOnDate( + mealplans, + timestamp, + defaultMessage, + today = Date.now(), +) { const mealplan = findMealplanOnDate(mealplans, timestamp); if (mealplan === undefined) { return defaultMessage + "\n\n" + linkToMealplan; } - return formatMealplan(mealplan); + return formatMealplan(mealplan, today); } /** @@ -49,26 +55,37 @@ function getMealplanOnDate(mealplans, timestamp, defaultMessage) { * information which is excluded in the formatted meal plan. * * @param {*} mealplan the meal plan to format + * @param {number | string} today the date of today, only required for tests * @returns {string} the formatted meal plan */ -function formatMealplan(mealplan) { +function formatMealplan(mealplan, today = Date.now()) { const counters = mealplan.counters.filter((meal) => meal.id !== "info"); - const title = `__*${getMealplanTitle(mealplan.date)}*__`.replaceAll( - ".", - "\\.", - ); + const title = `__*${getMealplanTitle(mealplan.date, today)}*__`; const formattedCounters = counters .map((counter) => formatCounter(counter)) - .join("\n\n") - // Characters that have to be escaped in the Markdown style of Telegram. - // https://core.telegram.org/bots/api#markdownv2-style + .join("\n\n"); + + const formattedMealplan = title + "\n\n" + formattedCounters; + + return escapeReservedCharacters(formattedMealplan) + "\n\n" + linkToMealplan; +} + +/** + * Escapes characters that are reserved in the + * {@link https://core.telegram.org/bots/api#markdownv2-style|Markdown style of Telegram}. + * + * @param {string} string the string to escape + * @returns the escaped string + */ +function escapeReservedCharacters(string) { + return string .replaceAll("-", "\\-") .replaceAll("(", "\\(") - .replaceAll(")", "\\)"); - - return title + "\n\n" + formattedCounters + "\n\n" + linkToMealplan; + .replaceAll(")", "\\)") + .replaceAll(".", "\\.") + .replaceAll("#", "\\."); } /** diff --git a/tests/mealplans.spec.js b/tests/mealplans.spec.js index c8b64e0..f2b647f 100644 --- a/tests/mealplans.spec.js +++ b/tests/mealplans.spec.js @@ -53,7 +53,12 @@ describe("getMealplanOnDate", () => { it("returns the formatted meal plan", () => { expect( - getMealplanOnDate(original_mealplans, "2025-01-31T00:00:00.000Z", ""), + getMealplanOnDate( + original_mealplans, + "2025-01-31T00:00:00.000Z", + "", + "2024-01-11T00:00:00.000Z", + ), ).toBe(`__*Freitag, 31\\.01\\.2025*__ __*Wahlessen \\- Aufgang C*__ @@ -65,7 +70,9 @@ Changshou Nudelsuppe mit Rindfleisch für ???€ describe("formatMealplan", () => { it("formats a meal plan with only one counter", () => { - expect(formatMealplan(original_mealplans.days[5])).toBe( + expect( + formatMealplan(original_mealplans.days[5], "1000-10-10T00:00:00.000Z"), + ).toBe( `__*Montag, 27\\.01\\.2025*__ __*Wahlessen \\- Aufgang C*__ @@ -77,7 +84,9 @@ Basmatireis \\(aus biologischem Anbau\\) }); it("formats a meal plan with many counters", () => { - expect(formatMealplan(original_mealplans.days[1])).toBe( + expect( + formatMealplan(original_mealplans.days[1], "2025-01-06T00:00:00.000Z"), + ).toBe( `__*Dienstag, 07\\.01\\.2025*__ __*Menü 1 \\- Aufgang B*__ @@ -111,6 +120,34 @@ Pizza Diavolo mit Peperoni, Salami und Paprika für ???€ Pizza vegetarisch mit Oliven, Paprika,Broccoli und getrockneten Tomaten für ???€ +[Speiseplan](https://mensaar.de/#/menu/sb)`, + ); + }); + + it("escapes the brackets for (heute) in the meal plan title", () => { + expect( + formatMealplan(original_mealplans.days[8], "2025-01-30T01:30:25.200Z"), + ).toBe( + `__*Donnerstag, 30\\.01\\.2025 \\(heute\\)*__ + +__*Wahlessen \\- Aufgang C*__ +Kourou gedämpfter Schweinebauch für ???€ +Basmatireis \\(aus biologischem Anbau\\) +Broccoligemüse + +[Speiseplan](https://mensaar.de/#/menu/sb)`, + ); + }); + + it("escapes the brackets for (vergangen) in the meal plan title", () => { + expect( + formatMealplan(original_mealplans.days[7], "2025-03-14T11:05:00.000Z"), + ).toBe( + `__*Mittwoch, 29\\.01\\.2025 \\(vergangen\\)*__ + +__*Wahlessen \\- Aufgang C*__ +Gebratene Nudeln mit Sojastreifen für ???€ + [Speiseplan](https://mensaar.de/#/menu/sb)`, ); });