Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edit card example via server bot #29

Merged
merged 1 commit into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion functions/db/user/user-set-server-bot-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ export type ServerBotState =
type: "deckSelected";
cardFront: string;
cardBack: string;
cardExample: string | null;
deckId: number;
editingField?: "cardFront" | "cardBack";
editingField?: "cardFront" | "cardBack" | "cardExample";
};

export const userSetServerBotState = async (
Expand Down
1 change: 1 addition & 0 deletions functions/server-bot/callback-query-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum CallbackQueryType {
Deck = "deck",
ConfirmCreateCard = "confirm",
EditFront = "edit-front",
EditExample = "edit-example",
EditBack = "edit-back",
Cancel = "cancel",
}
6 changes: 3 additions & 3 deletions functions/server-bot/escape-markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ const SPECIAL_CHARS = [
"{",
"}",
".",
"!"
"!",
];

// https://core.telegram.org/bots/api#markdownv2-style
export const escapeMarkdown = (text: string) => {
SPECIAL_CHARS.forEach(char => {
const regex = new RegExp(`\\${char}`, 'g');
SPECIAL_CHARS.forEach((char) => {
const regex = new RegExp(`\\${char}`, "g");
text = text.replace(regex, `\\${char}`);
});
return text;
Expand Down
47 changes: 40 additions & 7 deletions functions/server-bot/on-callback-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,37 @@ import {
import { sendCardCreateConfirmMessage } from "./send-card-create-confirm-message.ts";
import { DatabaseException } from "../db/database-exception.ts";

type CallbackQueryEdit =
| CallbackQueryType.EditFront
| CallbackQueryType.EditBack
| CallbackQueryType.EditExample;

const callbackQueryEditTypeToField = (data: CallbackQueryEdit) => {
switch (data) {
case CallbackQueryType.EditFront:
return "cardFront";
case CallbackQueryType.EditBack:
return "cardBack";
case CallbackQueryType.EditExample:
return "cardExample";
default:
return data satisfies never;
}
};

const callbackQueryToHumanReadable = (data: CallbackQueryEdit) => {
switch (data) {
case CallbackQueryType.EditFront:
return "front";
case CallbackQueryType.EditBack:
return "back";
case CallbackQueryType.EditExample:
return "example";
default:
return data satisfies never;
}
};

export const onCallbackQuery = (envSafe: EnvSafe) => async (ctx: Context) => {
assert(ctx.callbackQuery);
assert(ctx.from);
Expand All @@ -34,6 +65,7 @@ export const onCallbackQuery = (envSafe: EnvSafe) => async (ctx: Context) => {
type: "deckSelected",
cardBack: state.cardBack,
cardFront: state.cardFront,
cardExample: null,
deckId,
});

Expand All @@ -44,19 +76,19 @@ export const onCallbackQuery = (envSafe: EnvSafe) => async (ctx: Context) => {

if (
data === CallbackQueryType.EditFront ||
data === CallbackQueryType.EditBack
data === CallbackQueryType.EditBack ||
data === CallbackQueryType.EditExample
) {
const isFront = data === CallbackQueryType.EditFront;
const state = await userGetServerBotState(envSafe, ctx.from.id);
assert(state?.type === "deckSelected", "State is not deckSelected");
const editingField = callbackQueryEditTypeToField(data);
const editingFieldHuman = callbackQueryToHumanReadable(data);
await userSetServerBotState(envSafe, ctx.from.id, {
...state,
editingField: isFront ? "cardFront" : "cardBack",
editingField,
});
await ctx.deleteMessage();
await ctx.reply(
`Send a message with the new ${isFront ? "front" : "back"}:`,
);
await ctx.reply(`Send a message with the new ${editingFieldHuman}:`);
return;
}

Expand All @@ -75,13 +107,14 @@ export const onCallbackQuery = (envSafe: EnvSafe) => async (ctx: Context) => {
deck_id: state.deckId,
front: state.cardFront,
back: state.cardBack,
example: state.cardExample,
});

if (createCardsResult.error) {
throw new DatabaseException(createCardsResult.error);
}

await ctx.reply('Card has been created');
await ctx.reply("Card has been created");
await ctx.deleteMessage();
await userSetServerBotState(envSafe, ctx.from.id, null);
return;
Expand Down
16 changes: 14 additions & 2 deletions functions/server-bot/send-card-create-confirm-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ import {
import { CallbackQueryType } from "./callback-query-type.ts";
import { escapeMarkdown } from "./escape-markdown.ts";

const renderFieldValue = (value: string | null) => {
if (!value) {
return "_None_";
}

return escapeMarkdown(value);
};

export const sendCardCreateConfirmMessage = async (
envSafe: EnvSafe,
ctx: Context,
Expand All @@ -21,14 +29,17 @@ export const sendCardCreateConfirmMessage = async (
cardBack: state.cardBack,
cardFront: state.cardFront,
deckId: state.deckId,
cardExample: state.cardExample,
});

await ctx.deleteMessage();

await ctx.reply(
`Confirm card creation:\n\n*Front:*\n${escapeMarkdown(
`Confirm card creation:\n\n*Front:* ${renderFieldValue(
state.cardFront,
)}\n\n*Back:*\n${escapeMarkdown(state.cardBack)}`,
)}\n\n*Back:* ${renderFieldValue(
state.cardBack,
)}\n\n*Example:* ${renderFieldValue(state.cardExample)}`,
{
parse_mode: "MarkdownV2",
reply_markup: InlineKeyboard.from([
Expand All @@ -41,6 +52,7 @@ export const sendCardCreateConfirmMessage = async (
[
InlineKeyboard.text(`✏️ Edit front`, CallbackQueryType.EditFront),
InlineKeyboard.text(`✏️ Edit back`, CallbackQueryType.EditBack),
InlineKeyboard.text(`✏️ Edit example`, CallbackQueryType.EditExample),
],
[InlineKeyboard.text(`❌ Cancel`, CallbackQueryType.Cancel)],
]),
Expand Down