all repos — kokyo @ 96b7285acbac64583de6ddb0612a88f3d65dd885

Chatbot and CLI tool for Swiss public transports

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}