Expriencing issues while handling webhooks requests from and to Telegram

My Glitch project, handsome-sheet is experiencing problems with handling requests from the Telegram API because I am using Express to host documentation files while using webhooks to pull and push requests to Telegram API servers. How should I fix this?

Source code

The source code is copied from the server.js file in the root directory. I removed the comments to take less reading time. Check the original file at https://glitch.com/edit/#!/handsome-sheet?path=server.js:1:0 if you want to review them.

var fs = require("fs");
const express = require("express");
const app = express();
const TelegramBot = require("node-telegram-bot-api");
const bodyParser = require("body-parser");

const { QueueManager } = require("node-telegram-operation-manager");

const token = process.env.TGBOT_TOKEN;

const url = process.env.APP_URL || process.env.NOW_URL;

const port = process.env.PORT || 443;

const GLITCH_PROJECT_SLUG = process.env.PROJECT_DOMAIN

const bot = new TelegramBot(token);

bot.setWebHook(`${url}/webhook/tgbot-${token}`);

app.use(bodyParser.json());

app.post(`/webhook/tgbot-${token}`, (req, res) => {
  bot.processUpdate(req.body);
  res.sendStatus(200);
});

app.use(express.static("public"));

function getFilesInDirectory(dir) {
  return [].concat(
    ...fs.readdirSync(dir).map(name => {
      const path = dir + "/" + name;
      const stats = fs.statSync(path);
      if (stats.isDirectory()) {
        return getFilesInDirectory(path);
      } else if (stats.isFile()) {
        return [path];
      }
      return [];
    })
  );
}

app.get("/docs", function(request, response) {
  const files = {};
  getFilesInDirectory("docs")
    .sort()
    .forEach(path => {
      const fileName = path.replace(/docs\/(.*)\.md/, "$1"); //trim off "docs/" and ".md"
      files[fileName] = fs.readFileSync(path, "utf8");
    });
  response.send(files);
});

// http://expressjs.com/en/starter/basic-routing.html
app.get("/", function(request, response) {
  response.sendFile(__dirname + "/views/index.html");
});

app.get("/offline", function(request, response) {
  response.sendFile(__dirname + "/views/offline.html");
});

app.get("/manifest.json", function(request, response) {
  response.sendFile(__dirname + "/views/manifest.json");
});

app.use(function (req, res, next) {
  res.status(404).send("Sorry can't find that!")
  res.sendFile(__dirname + "/views/404.html")
})

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

app.listen(port, () => {
  console.log(`Express server is listening on ${port}`);
});

//

// Matches "/echo [whatever]"
bot.onText(/\/start/, (msg) => {
  const chatId = msg.chat.id;

  bot.sendMessage(chatId, "Welcome to **Recap Time** bot\!", {parse_mode: "MarkdownV2", "reply_markup": {
    "keyboard": [["Explore", "My Account"],   ["About bot"], ["Send feedback"]]
    }});
});

// Remove the code below for local deployments and deployments outside Glitch.com
// It's better to get your own copy of this project.
process.on("SIGTERM", function() {
  console.log("SIGTERM received, sending SOS to Resurrect...");
  require("https").get(
    "https://resurrect.glitch.me/" +
       GLITCH_PROJECT_SLUG +
      "/optional/path/here",
    process.exit
  );
});

Error Log

Error: Can't set headers after they are sent.
    at SendStream.headersAlreadySent (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/send/0.17.1/node_modules/send/index.js:390:13)
    at SendStream.send (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/send/0.17.1/node_modules/send/index.js:617:10)
    at onstat (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/send/0.17.1/node_modules/send/index.js:729:10)
    at FSReqCallback.oncomplete (fs.js:167:5)

Your issue is with this block of code I believe:

app.use(function (req, res, next) {
  res.status(404).send("Sorry can't find that!")
  res.sendFile(__dirname + "/views/404.html")
})

You try to send a file after you already sent Sorry can't find that!. You can either send the file or send the text. Here’s the fixed up one bellow

Send the text

app.use(function (req, res, next) {
  res.status(404).send("Sorry can't find that!")
})

Send the file

app.use(function (req, res, next) {
  res.status(404).sendFile(__dirname + "/views/404.html")
})
2 Likes

Thank you. I will be updating the code…

EDIT: I am experiencing issues while using MarkdwonV2. The error said that…

Unhandled rejection Error: ETELEGRAM: 400 Bad Request: can't parse entities: Character '!' is reserved and must be escaped with the preceding '\'
    at /rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/node-telegram-bot-api/0.30.0/node_modules/node-telegram-bot-api/src/telegram.js:280:15
    at tryCatcher (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/promise.js:547:31)
    at Promise._settlePromise (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/promise.js:604:18)
    at Promise._settlePromise0 (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/promise.js:649:10)
    at Promise._settlePromises (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/promise.js:729:18)
    at _drainQueueStep (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/async.js:93:12)
    at _drainQueue (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/async.js:86:9)
    at Async._drainQueues (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/async.js:102:5)
    at Immediate.Async.drainQueues [as _onImmediate] (/rbd/pnpm-volume/d4aca002-e4f5-48b9-b6c6-e4dbb591af21/node_modules/.registry.npmjs.org/bluebird/3.7.2/node_modules/bluebird/js/release/async.js:15:14)
    at processImmediate (internal/timers.js:439:21)

…and below is my code for /start command which…

bot.onText(/\/start/, (msg) => {
  // 'msg' is the received Message from Telegram
  // 'match' is the result of executing the regexp above on the text content
  // of the message

  const chatId = msg.chat.id;

  // send back the matched "whatever" to the chat
  bot.sendMessage(chatId, "Welcome to **Recap Time** bot\!" + "\n\n" + "\* Explore the bot", {parse_mode: "MarkdownV2", "reply_markup": {
    "keyboard": [["Explore", "My Account"],   ["About bot"], ["Send feedback"]]
    }});
});

How should I escape ! and others as described by the documentation, under MarkdownV2 style?

Does \\! work?

20chars20chars

2 Likes