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

Change parse mode #16

Merged
merged 9 commits into from Apr 10, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Expand Up @@ -13,7 +13,7 @@ COLUMN_NODE_ID_PR=
NOTIFIER_URL=

# List of people to tag in the «Pull Requests» message
MENTION = "ilyamore88 fabled228 Xemka kebyo GeekaN2 ranemihir Robonetphy neSpecc nikmel2803 talyguryn gohabereg khaydarov f0m41h4u7 SunnyCapt dependabot"
MENTION = "ilyamore88 fabled228 Xemka kebyo GeekaN2 ranemihir Robonetphy neSpecc nikmel2803 n0str talyguryn gohabereg khaydarov f0m41h4u7 SunnyCapt dependabot"

# List of people to tag in the «Meeting Message» message
MEETING_MENTION = "specc guryn khaydarovm nikmel2803 xemk4 gohabereg ilyamore88 GeekaN augustovich n0str f0m41h4u7 polina_shneider oybekmuslimov"
Expand Down
7 changes: 5 additions & 2 deletions package.json
Expand Up @@ -5,6 +5,7 @@
"license": "MIT",
"scripts": {
"start": "node src/index.js",
"start:dev": "nodemon src/index.js",
"lint": "eslint -c .eslintrc.json src/ --ext .js",
"lint:errors": "eslint -c .eslintrc.json src/ --ext .js --quiet",
"lint:fix": "eslint -c .eslintrc.json src/ --ext .js --fix",
Expand All @@ -14,10 +15,12 @@
"@octokit/core": "^3.1.2",
"axios": "^0.19.2",
"cron": "^1.8.2",
"dotenv": "^8.2.0"
"dotenv": "^8.2.0",
"parse-github-url": "^1.0.2"
},
"devDependencies": {
"eslint": "^7.12.1",
"eslint-config-codex": "^1.6.0"
"eslint-config-codex": "^1.6.0",
"nodemon": "^2.0.7"
}
}
106 changes: 72 additions & 34 deletions src/index.js
@@ -1,5 +1,6 @@
require('dotenv').config();
const { Octokit } = require('@octokit/core');
const parseGithubUrl = require('parse-github-url');
const axios = require('axios').default;
const CronJob = require('cron').CronJob;

Expand All @@ -9,6 +10,8 @@ const COLUMN_NODE_ID_PR = process.env.COLUMN_NODE_ID_PR;
const NOTIFIER_URL = process.env.NOTIFIER_URL;
const MENTION = process.env.MENTION;
const MEETING_MENTION = process.env.MEETING_MENTION;
const PARSE_MODE = 'HTML';

/**
* The default cron expression described as:
* At minute 0 past hour 9 and 18 on every day-of-week from Monday through Friday.
Expand All @@ -35,16 +38,15 @@ const PR_QUERY = require('./queries/pr');
* Sends POST request to telegram bot
*
* @param {string} message - telegram message
* @param {boolean} markdown - telegram message include markdown or not.
* @returns {Promise} - returns a promise to catch error.
*/
async function notify(message, markdown) {
const botMessage = 'message=' + encodeURIComponent(message) + (markdown ? '&parse_mode=Markdown' : '');
async function notify(message) {
const messageData = `parse_mode=${PARSE_MODE}&disable_web_page_preview=True&message=${encodeURIComponent(message)}`;

return axios({
method: 'POST',
url: NOTIFIER_URL,
data: botMessage,
data: messageData,
});
}

Expand Down Expand Up @@ -83,25 +85,57 @@ function replaceGithubLink(message, markdownLink) {
);
}

/**
* Escape chars in raw string which should not be processed as marked text
*
* List of chars to be transcoded
* https://core.telegram.org/bots/api#html-style
*
* @param {string} message - string to be processed
* @returns {string}
*/
function escapeChars(message) {
message = message.replace(/</g, '&lt;');
message = message.replace(/>/g, '&gt;');
message = message.replace(/&/g, '&amp;');
Comment on lines +98 to +100
Copy link
Member

@robonetphy robonetphy Apr 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@talyguryn I change this because replaceAll throwing me an error

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it work correctly for multiple entities?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup


return message;
}

/**
* Parse github link via jonschlinkert/parse-github-url module
*
* https://github.com/jonschlinkert/parse-github-url
*
* @param {string} url - any github link (to pr or issue for example)
* @returns {string} - HTML marked link to repo
*/
function createTaskBadge(url) {
const repoInfo = parseGithubUrl(url);

return `<a href="https://github.com/${repoInfo.repo}"><b>${repoInfo.name}</b></a>`;
}

/**
* parse the response of GraphQL query for pull request.
*
* @param {object} content - response of GraphQL API.
* @returns {string} - parsed message.
*/
function pullRequestParser(content) {
let parsedTask = `[${content.title.replace(/[[\]']+/g, '')}](${content.url}) @${content.author.login}`;

content.reviewRequests.nodes.forEach((node) => {
if (node.requestedReviewer.login) {
parsedTask += `@${node.requestedReviewer.login}`;
}
});
content.assignees.nodes.forEach((node) => {
if (node.login) {
parsedTask += `@${node.login}`;
}
});
const parsedTask = `${createTaskBadge(content.url)}: <a href="${content.url}">${escapeChars(content.title)}</a> @${content.author.login}`;

// content.reviewRequests.nodes.forEach((node) => {
// if (node.requestedReviewer.login) {
// parsedTask += `@${node.requestedReviewer.login}`;
// }
// });
//
// content.assignees.nodes.forEach((node) => {
// if (node.login) {
// parsedTask += `@${node.login}`;
// }
// });
Comment on lines +131 to +141
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we removed the requested reviewer and assignees

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can discuss it too. i think it is now necessary to duplicate link to pr. u can see repo name and request name and if it is project which u working for u should check it


return parsedTask;
}
Expand All @@ -113,7 +147,7 @@ function pullRequestParser(content) {
* @returns {string} - parsed message.
*/
function issuesParser(content) {
let parsedTask = `[${content.title.replace(/[[\]']+/g, '')}](${content.url})`;
let parsedTask = `${createTaskBadge(content.url)}: <a href="${content.url}">${escapeChars(content.title)}</a>`;

content.assignees.nodes.forEach((node) => {
parsedTask += `@${node.login} `;
Expand Down Expand Up @@ -180,12 +214,12 @@ async function parseQuery(members, response) {
await response.map(async (items) => {
if (items.state === 'NOTE_ONLY') {
for (let i = 0; i < members.length; i++) {
if (items.note.includes(`@${members[i].name}`)) {
if (items.note.includes(`@${members[i].name}`) || items.note.includes(`@${members[i].name.toLowerCase()}`)) {
const parsable = checkForParsableGithubLink(items.note);

return parsable[0]
? await parseGithubLink(items.note, parsable)
: items.note;
: escapeChars(items.note);
}
}
const parsable = checkForParsableGithubLink(items.note);
Expand All @@ -209,15 +243,17 @@ async function parseQuery(members, response) {
let cardDataWithoutMembers = [ ...parsedCardData ];

for (let i = 0; i < members.length; i++) {
cardDataWithoutMembers = cardDataWithoutMembers.map((x) =>
x.replace(new RegExp(`@${members[i].name}`, 'g'), '')
);
cardDataWithoutMembers = cardDataWithoutMembers.map((x) => {
const data = x.replace(new RegExp(`@${members[i].name}`, 'g'), '');

return data.replace(new RegExp(`@${members[i].name.toLowerCase()}`, 'g'), '');
});
}
cardDataWithoutMembers = cardDataWithoutMembers.map((x) => x.replace(/^\s+|\s+$/g, ''));

parsedCardData.forEach((items, index) => {
for (let i = 0; i < members.length; i++) {
if (items.includes(`@${members[i].name}`)) {
if (items.includes(`@${members[i].name}`) || items.includes(`@${members[i].name.toLowerCase()}`)) {
members[i].tasks.push(cardDataWithoutMembers[index]);
}
}
Expand Down Expand Up @@ -275,13 +311,18 @@ async function notifyMessage(title, columnID) {
);

parsedData.forEach((items) => {
dataToSend += `@${items.name}`;
dataToSend += '\n';
/** Skip person with no tasks */
if (!items.tasks.length) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@talyguryn, Peter told me earlier to remove this, So we can identify a person without a task.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm. well then we can mark these people other way. maybe put them at the end of the message and mark as "no task" or any other way.

i did this because i see big message which has only 50% useful information. let's discuss a better design format.


dataToSend += `<b>${items.name}</b>\n`;

items.tasks.forEach((data) => {
dataToSend += `${data} \n`;
dataToSend += `${data}\n`;
});
dataToSend += '\n\n';

dataToSend += '\n';
});

return dataToSend;
Expand All @@ -293,8 +334,7 @@ async function notifyMessage(title, columnID) {
* @returns {string} -parsed messages
*/
function parseMeetingMessage(mentionList) {
let message = `☝️
Join the meeting in Discord!\n`;
let message = `☝️ Join the meeting in Discord!\n\n`;

mentionList.split(' ').forEach((items) => {
message += `@${items} `;
Expand All @@ -310,8 +350,8 @@ async function main() {
const toDoJob = new CronJob(
TO_DO_TIME,
async () => {
notify(await notifyMessage("📌 Sprint's backlog", COLUMN_NODE_ID_TO_DO), true)
.then(() => console.log('PR Job Completed.'))
notify(await notifyMessage("📌 Sprint's backlog", COLUMN_NODE_ID_TO_DO))
.then(() => console.log('Tasks Job Completed.'))
.catch(console.error);
},
null,
Expand All @@ -322,9 +362,7 @@ async function main() {
const prJob = new CronJob(
PR_TIME,
async () => {
notify(
await notifyMessage('🚜 Pull requests for review', COLUMN_NODE_ID_PR, true)
)
notify(await notifyMessage('👀 Pull requests for review', COLUMN_NODE_ID_PR))
.then(() => console.log('PR Job Completed.'))
.catch(console.error);
},
Expand Down