bots/telegram.ts (view raw)
1import { Telegram, getUpdates } from "@gramio/wrappergram";
2import { findStopByName } from "@api/locationInformationRequest.ts";
3import { InlineKeyboard } from "@gramio/keyboards";
4import { getNextDepartures } from "@api/stopEvent.ts";
5import logger from "@lib/logger.ts";
6import * as kvdb from "../lib/kvdb.ts";
7
8const telegram = new Telegram(Deno.env.get("TELEGRAM_TOKEN") as string);
9
10const formatContent = (content?: string) =>
11 content
12 ?.replaceAll("-", "\\-")
13 .replaceAll(".", "\\.")
14 .replaceAll("(", "\\(")
15 .replaceAll(")", "\\)");
16
17const sendMessage = async (message: any) => {
18 const response = await telegram.api.sendMessage(message);
19 console.log(response);
20};
21
22for await (const update of getUpdates(telegram)) {
23 console.log(update);
24
25 // On new message
26 if (update.message) {
27 if (!update.message?.from) {
28 console.error("No 'from' in message");
29 continue;
30 }
31
32 logger.info(
33 `New message from ${update.message.from.username}: ${update.message.text}`
34 );
35
36 telegram.api.setMyCommands({
37 commands: [
38 { command: "aide", description: "Explique comment utiliser le bot" },
39 {
40 command: "favoris",
41 description: "Affiche la liste de vos arrêts favoris",
42 },
43 ],
44 });
45
46 if (update.message.text === "/aide" || update.message.text === "/start") {
47 sendMessage({
48 chat_id: update.message.from.id,
49 text: `Hey ! Je suis un bot qui te permet d'obtenir rapidement des informations sur les transports en commun dans toute la Suisse.
50Entre le nom d'un arrêt et laisse-toi guider !
51
52Ce bot est en cours de développement actif. Les fonctionnalités sont pour le moment limitées.
53
54/aide - Affiche ce message
55/favoris - Affiche vos favoris`,
56 });
57 } else if (update.message.text === "/favoris") {
58 const userId = `telegram:${update.message.from.id}`;
59 const favorites = kvdb.getUserFavorites(userId);
60
61 let inlineKeyboard = new InlineKeyboard();
62 for await (const favorite of favorites)
63 inlineKeyboard = inlineKeyboard
64 .text(favorite.value.name, {
65 cmd: "nextDepartures",
66 stopRef: favorite.value.stopRef,
67 })
68 .row();
69
70 await sendMessage({
71 chat_id: update.message.from.id,
72 text: "Voici vos favoris",
73 reply_markup: inlineKeyboard,
74 });
75 } else {
76 const stopLists = await findStopByName(update.message.text);
77 kvdb.saveStops(stopLists);
78 let keyboard = new InlineKeyboard();
79 for (const stop of stopLists)
80 keyboard = keyboard
81 .text(stop.name, { cmd: "nextDepartures", stopRef: stop.stopRef })
82 .row();
83
84 await sendMessage({
85 chat_id: update.message.from.id,
86 text: "Quel arrêt correspond ?",
87 reply_markup: keyboard,
88 });
89 }
90 }
91
92 // On keyboard event (callback query)
93 else if (update.callback_query) {
94 const userId = `telegram:${update.callback_query.from.id}`;
95 const payload = JSON.parse(update.callback_query.data);
96
97 logger.info(
98 `New request from ${update.callback_query.from.username}: ${update.callback_query.data}`
99 );
100
101 if (payload?.cmd === "nextDepartures") {
102 const nextDepartures = await getNextDepartures(payload.stopRef);
103 const stop = await kvdb.getStopByRef(payload.stopRef);
104 const text = formatContent(`Prochains départs depuis *${
105 stop.value?.name || "n.c."
106 }*:\n
107${nextDepartures
108 .map(
109 item =>
110 `*${item.serviceName}* ${item.serviceTypeIcon} *${item.departure}* _${item.departureIn} min_ \n${item.to}\n`
111 )
112 .join("\n")}`);
113
114 let keyboard = new InlineKeyboard().text("Rafraîchir", {
115 cmd: "nextDepartures",
116 stopRef: payload.stopRef,
117 });
118 const existingFavorite = await kvdb.getUserFavorite(
119 userId,
120 payload.stopRef
121 );
122 if (!existingFavorite?.value)
123 keyboard = keyboard.text("Enregistrer comme favoris", {
124 cmd: "saveFavorite",
125 stopRef: payload.stopRef,
126 });
127 await sendMessage({
128 chat_id: update.callback_query.from.id,
129 parse_mode: "MarkdownV2",
130 text,
131 reply_markup: keyboard,
132 });
133 } else if (payload?.cmd === "saveFavorite") {
134 const stop = await kvdb.getStopByRef(payload.stopRef);
135 if (stop?.value) await kvdb.saveUserFavorite(userId, stop.value);
136 await sendMessage({
137 chat_id: update.callback_query.from.id,
138 parse_mode: "MarkdownV2",
139 text: `L'arrêt *${formatContent(
140 stop.value?.name
141 )}* a été enregistré dans vos /favoris`,
142 });
143 }
144 }
145}