Skip to content

Commit

Permalink
Escape brackets in meal plan title in Markdown
Browse files Browse the repository at this point in the history
If the meal plan is for today or for a date in past, (heute) or
(vergangen) is appended to it. The bot sends the meal plan in the
Markdown style of Telegram. There, brackets are reserved characters and
must therefore be escaped with \\. In the inline queries, the brackets
are not escaped because Markdown is not used there.

Closes #34
ikelax committed Jan 7, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 44945e8 commit 0de61ac
Showing 2 changed files with 70 additions and 16 deletions.
43 changes: 30 additions & 13 deletions mealplans.js
Original file line number Diff line number Diff line change
@@ -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("#", "\\.");
}

/**
43 changes: 40 additions & 3 deletions tests/mealplans.spec.js
Original file line number Diff line number Diff line change
@@ -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)`,
);
});

0 comments on commit 0de61ac

Please sign in to comment.