Skip to content

Commit 2f44804

Browse files
committed
initial commit
0 parents  commit 2f44804

File tree

8 files changed

+142
-0
lines changed

8 files changed

+142
-0
lines changed

.eslintrc.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
env: {
3+
browser: true,
4+
commonjs: true,
5+
es2021: true,
6+
},
7+
extends: [
8+
'airbnb-base',
9+
],
10+
parserOptions: {
11+
ecmaVersion: 12,
12+
},
13+
rules: {
14+
'linebreak-style': 0
15+
},
16+
};

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.env
3+
package-lock.json

index.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* eslint-disable no-console */
2+
/* eslint-disable no-unused-vars */
3+
/* eslint-disable no-param-reassign */
4+
const querify = require('querystring').stringify;
5+
const onFinished = require('on-finished');
6+
const template = require('./src/templates/default');
7+
const sendMessage = require('./src/sendMessage');
8+
const { printWarning } = require('./src/utils/print');
9+
10+
/**
11+
* @param options Middleware's options
12+
* @param options.botToken Bot's token, sent by BotFather
13+
* @param options.chatId ChatID of a Telegram chat to send notifications to
14+
*/
15+
const telegramMiddleware = (options) => (req, res, next) => {
16+
if (!options) options = {};
17+
const { botToken } = options;
18+
const { chatId } = options;
19+
20+
if (!botToken) printWarning('botToken not provided, errors get ignored');
21+
if (!chatId) printWarning('chatId not provided, errors get ignored');
22+
23+
if (botToken && chatId) {
24+
onFinished(res, (err, _) => {
25+
if (err || res.statusCode >= 400) {
26+
const text = template(req, res, options);
27+
28+
let query = {
29+
text,
30+
chat_id: chatId,
31+
parse_mode: 'Markdown',
32+
};
33+
34+
// If statusCode is less than 500, then this error is not critical, we disable notification
35+
if (res.statusCode < 500) query.disable_notification = true;
36+
37+
query = querify(query);
38+
39+
try {
40+
sendMessage(botToken, query);
41+
} catch (e) {
42+
console.log(e);
43+
next(e);
44+
}
45+
}
46+
});
47+
}
48+
next();
49+
};
50+
51+
module.exports = telegramMiddleware;

package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "express-notify-telegram",
3+
"version": "1.0.0",
4+
"description": "A simple Express middleware to notify errors into Telegram",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [
10+
"telegram",
11+
"express",
12+
"errors"
13+
],
14+
"author": "Azamat Abdullaev",
15+
"license": "MIT",
16+
"devDependencies": {
17+
"eslint": "^7.11.0",
18+
"eslint-config-airbnb-base": "^14.2.0",
19+
"eslint-plugin-import": "^2.22.1"
20+
},
21+
"dependencies": {
22+
"on-finished": "^2.3.0"
23+
}
24+
}

src/sendMessage.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const https = require('https');
2+
3+
const sendMessage = (botToken, query) => {
4+
const API = `https://api.telegram.org/bot${botToken}/sendMessage?${query}`;
5+
https.get(API);
6+
};
7+
8+
module.exports = sendMessage;

src/templates/default.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const escape = require('../utils/escaper');
2+
3+
module.exports = (req, res, options) => {
4+
const notificationTitle = res.statusCode < 500 ? '⚠️⚠️⚠️ SERVER WARNING ⚠️⚠️⚠️' : '⛔️⛔️⛔️ SERVER ERROR ⛔️⛔️⛔️';
5+
const endpoint = `\`${req.method}\` ${`${req.protocol}://${req.get('host')}${req.originalUrl}`}`;
6+
const appName = options.appName || process.env.APP_NAME || 'Unknown application';
7+
8+
const message = `
9+
*${notificationTitle}*
10+
11+
*🔺 APPLICATION:* ${escape(appName)}
12+
13+
*🔺 ENDPOINT:* ${endpoint}
14+
*🔺 STATUS_CODE:* ${res.statusCode}
15+
16+
*🔺 ERROR_MESSAGE:* ${escape(req.errorMessage || 'Unknown')}
17+
18+
*🔺 IP_ADDRESS:* ${escape(req.ip)}
19+
20+
*🔺REQUEST_BODY:* \`\`\`${JSON.stringify(req.body || {}, null, 2)}\`\`\`
21+
`;
22+
return message;
23+
};

src/utils/escaper.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable no-useless-escape */
2+
module.exports = (string) => (
3+
typeof string === 'string'
4+
? string
5+
.replace(/[\*]/g, '\\*')
6+
.replace(/[_]/g, '\\_')
7+
.replace(/[\[]/g, '\\[')
8+
.replace(/[`]/g, '\\`')
9+
: string);

src/utils/print.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* eslint-disable no-console */
2+
3+
const printWarning = (text) => console.warn(
4+
'\x1b[33m', 'express-notify-telegram ==>',
5+
'\x1b[0m', text,
6+
);
7+
8+
module.exports = { printWarning };

0 commit comments

Comments
 (0)