feat: support multiple URL unfurls at a time

This commit is contained in:
Samuel Attard 2021-04-06 19:34:38 -07:00
Родитель 5c4c2bc4b9
Коммит 1a6ee47e15
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 191FEF027779CC6C
4 изменённых файлов: 124 добавлений и 146 удалений

Просмотреть файл

@ -1,12 +1,7 @@
import { WebClient } from '@slack/web-api';
import { MessageAttachment } from '@slack/bolt';
import fetch from 'node-fetch';
export async function handleChromiumReviewUnfurl(
url: string,
message_ts: string,
channel: string,
client: WebClient,
) {
export async function handleChromiumReviewUnfurl(url: string): Promise<MessageAttachment | null> {
const match = /^https:\/\/chromium-review\.googlesource\.com\/c\/([a-z0-9]+)\/([a-z0-9]+)\/\+\/([0-9]+)/g.exec(
url,
);
@ -29,39 +24,29 @@ export async function handleChromiumReviewUnfurl(
? message.substr(subject.length + 1).trim()
: message;
const unfurl = await client.chat.unfurl({
channel,
ts: message_ts,
unfurls: {
[url]: {
color: '#4D394B',
author_name: owner.name,
author_icon:
owner.avatars && owner.avatars.length
? owner.avatars[owner.avatars.length - 1].url
: ':void',
author_link: `https://chromium-review.googlesource.com/q/author:${encodeURIComponent(
owner.email,
)}`,
fallback: `[${niceRepo}] #${cl} ${subject}`,
title: `#${cl} ${subject}`,
title_link: url,
footer_icon: 'https://chromium-review.googlesource.com/favicon.ico',
text: messageWithoutSubject,
footer: `<https://source.chromium.org/chromium/${niceRepo}|${niceRepo}>`,
ts: `${new Date(date).getTime()}`,
// TODO: Labels? CQ status?
// fields: [{
return {
color: '#4D394B',
author_name: owner.name,
author_icon:
owner.avatars && owner.avatars.length
? owner.avatars[owner.avatars.length - 1].url
: ':void',
author_link: `https://chromium-review.googlesource.com/q/author:${encodeURIComponent(
owner.email,
)}`,
fallback: `[${niceRepo}] #${cl} ${subject}`,
title: `#${cl} ${subject}`,
title_link: url,
footer_icon: 'https://chromium-review.googlesource.com/favicon.ico',
text: messageWithoutSubject,
footer: `<https://source.chromium.org/chromium/${niceRepo}|${niceRepo}>`,
ts: `${new Date(date).getTime()}`,
// TODO: Labels? CQ status?
// fields: [{
// }]
},
},
});
if (unfurl.status !== 200 || !unfurl.ok) {
console.error('Failed to unfurl', unfurl);
}
return true;
// }]
};
}
return false;
return null;
}

Просмотреть файл

@ -1,4 +1,4 @@
import { WebClient } from '@slack/web-api';
import { MessageAttachment } from '@slack/bolt';
import fetch from 'node-fetch';
import { Policy, ConstantBackoff } from 'cockatiel';
@ -83,14 +83,9 @@ const notNull = <T>(arr: (T | null)[]) => {
return arr.filter(Boolean) as T[];
};
export async function handleChromiumBugUnfurl(
url: string,
message_ts: string,
channel: string,
client: WebClient,
) {
export async function handleChromiumBugUnfurl(url: string): Promise<MessageAttachment | null> {
const bugIdentifier = parseBugIdentifier(url);
if (!bugIdentifier) return false;
if (!bugIdentifier) return null;
const headers = await getMonorailHeaders();
const monorailQuery = JSON.stringify({
@ -109,73 +104,62 @@ export async function handleChromiumBugUnfurl(
headers,
body: monorailQuery,
});
if ((await response).status !== 200) return false;
if ((await commentResponse).status !== 200) return false;
if ((await response).status !== 200) return null;
if ((await commentResponse).status !== 200) return null;
const { issue }: { issue: MonorailIssue } = JSON.parse((await (await response).text()).slice(4));
const { comments }: { comments: MonorailComments } = JSON.parse(
(await (await commentResponse).text()).slice(4),
);
const unfurl = await client.chat.unfurl({
channel,
ts: message_ts,
unfurls: {
[url]: {
color: issue.statusRef.meansOpen ? '#36B37E' : '#FF5630',
author_name: issue.reporterRef.displayName,
// author_icon: owner.avatars && owner.avatars.length ? owner.avatars[owner.avatars.length - 1].url : ':void',
author_link: `https://bugs.chromium.org/u/${issue.reporterRef.userId}/`,
fallback: `[${issue.projectName}] #${issue.localId} ${issue.summary}`,
title: `#${issue.localId} ${issue.summary}`,
title_link: url,
footer_icon: 'https://bugs.chromium.org/static/images/monorail.ico',
text: comments[0].content,
footer: `<https://bugs.chromium.org/p/${issue.projectName}|crbug/${issue.projectName}>`,
ts: `${issue.openedTimestamp * 1000}`,
fields: notNull([
issue.componentRefs && issue.componentRefs.length
? {
title: 'Components',
value: issue.componentRefs
.map(
(ref) =>
`• <https://bugs.chromium.org/p/${
issue.projectName
}/issues/list?q=component%3A${encodeURIComponent(
ref.path,
)}|\`${ref.path.replace(/>/g, '→')}\`>`,
)
.join('\n'),
short: true,
}
: null,
issue.labelRefs && issue.labelRefs.length
? {
title: 'Labels',
value: issue.labelRefs
.map(
(ref) =>
`• <https://bugs.chromium.org/p/${
issue.projectName
}/issues/list?q=label%3A${encodeURIComponent(ref.label)}|\`${ref.label}\`>`,
)
.join('\n'),
short: true,
}
: null,
{
title: 'Comments',
value: `${comments.length}`,
return {
color: issue.statusRef.meansOpen ? '#36B37E' : '#FF5630',
author_name: issue.reporterRef.displayName,
author_link: `https://bugs.chromium.org/u/${issue.reporterRef.userId}/`,
fallback: `[${issue.projectName}] #${issue.localId} ${issue.summary}`,
title: `#${issue.localId} ${issue.summary}`,
title_link: url,
footer_icon: 'https://bugs.chromium.org/static/images/monorail.ico',
text: comments[0].content,
footer: `<https://bugs.chromium.org/p/${issue.projectName}|crbug/${issue.projectName}>`,
ts: `${issue.openedTimestamp * 1000}`,
fields: notNull([
issue.componentRefs && issue.componentRefs.length
? {
title: 'Components',
value: issue.componentRefs
.map(
(ref) =>
`• <https://bugs.chromium.org/p/${
issue.projectName
}/issues/list?q=component%3A${encodeURIComponent(ref.path)}|\`${ref.path.replace(
/>/g,
'→',
)}\`>`,
)
.join('\n'),
short: true,
},
]),
}
: null,
issue.labelRefs && issue.labelRefs.length
? {
title: 'Labels',
value: issue.labelRefs
.map(
(ref) =>
`• <https://bugs.chromium.org/p/${
issue.projectName
}/issues/list?q=label%3A${encodeURIComponent(ref.label)}|\`${ref.label}\`>`,
)
.join('\n'),
short: true,
}
: null,
{
title: 'Comments',
value: `${comments.length}`,
short: true,
},
},
});
if (unfurl.status !== 200 || !unfurl.ok) {
console.error('Failed to unfurl', unfurl);
}
return true;
]),
};
}

Просмотреть файл

@ -1,4 +1,4 @@
import { WebClient } from '@slack/web-api';
import { MessageAttachment } from '@slack/bolt';
import fetch from 'node-fetch';
type GrimoireMeta = {
@ -117,19 +117,14 @@ function removeOverIndent(contents: string): string {
return lines.map((l) => l.slice(minIndent)).join('\n');
}
export async function handleChromiumSourceUnfurl(
url: string,
message_ts: string,
channel: string,
client: WebClient,
) {
export async function handleChromiumSourceUnfurl(url: string): Promise<MessageAttachment | null> {
const parsed = new URL(url);
if (parsed.hostname !== 'source.chromium.org') return false;
if (parsed.hostname !== 'source.chromium.org') return null;
const match = /^https:\/\/source\.chromium\.org\/([a-z0-9]+)\/([a-z0-9]+)\/([a-z0-9]+)\/\+\/([a-z0-9]+):([^;]+)(?:;l=([0-9]+(?:-[0-9]+)?))?/.exec(
url,
);
if (!match) return false;
if (!match) return null;
const [, parent, project, projectKey, branch, fileName, lineRange] = match;
@ -148,25 +143,14 @@ export async function handleChromiumSourceUnfurl(
}
}
const unfurl = await client.chat.unfurl({
channel,
ts: message_ts,
unfurls: {
[url]: {
color: '#00B8D9',
fallback: `[${project}/${projectKey}] ${fileName}`,
title: fileName,
title_link: url,
footer_icon: 'https://www.gstatic.com/devopsconsole/images/oss/favicons/oss-96x96.png',
text: `\`\`\`\n${maybeTruncate(contents)}\n\`\`\``,
footer: `<https://source.chromium.org/${parent}/${project}/${projectKey}/+/${branch}|${project}/${projectKey}>`,
mrkdwn_in: ['text'],
},
},
});
if (unfurl.status !== 200 || !unfurl.ok) {
console.error('Failed to unfurl', unfurl);
}
return true;
return {
color: '#00B8D9',
fallback: `[${project}/${projectKey}] ${fileName}`,
title: fileName,
title_link: url,
footer_icon: 'https://www.gstatic.com/devopsconsole/images/oss/favicons/oss-96x96.png',
text: `\`\`\`\n${maybeTruncate(contents)}\n\`\`\``,
footer: `<https://source.chromium.org/${parent}/${project}/${projectKey}/+/${branch}|${project}/${projectKey}>`,
mrkdwn_in: ['text'],
};
}

Просмотреть файл

@ -1,13 +1,15 @@
import { App } from '@slack/bolt';
import { App, MessageAttachment } from '@slack/bolt';
import { handleChromiumReviewUnfurl } from './chromium-review';
import { handleChromiumBugUnfurl } from './crbug';
import { handleChromiumSourceUnfurl } from './crsource';
const app = new App({
token: process.env.SLACK_TOKEN,
authorize: async () => ({
botToken: process.env.SLACK_TOKEN,
botId: process.env.SLACK_BOT_ID,
}),
signingSecret: process.env.SLACK_SIGNING_SECRET,
botId: process.env.SLACK_BOT_ID,
});
app.event('link_shared', async ({ client, body }) => {
@ -16,13 +18,36 @@ app.event('link_shared', async ({ client, body }) => {
// Do not unfurl if there are more than three links, we're nice like that
if (links.length > 3) return;
for (const { url } of links) {
if (await handleChromiumReviewUnfurl(url, message_ts, channel, client)) return;
if (await handleChromiumBugUnfurl(url, message_ts, channel, client)) return;
if (await handleChromiumSourceUnfurl(url, message_ts, channel, client)) return;
const linkUnfurls: Record<string, MessageAttachment> = {};
// Unfurl all the links at the same time
await Promise.all(
links.map(async ({ url }) => {
const unfurls = await Promise.all([
handleChromiumReviewUnfurl(url),
handleChromiumBugUnfurl(url),
handleChromiumSourceUnfurl(url),
]);
const validUnfurls = unfurls.filter((unfurl) => !!unfurl) as MessageAttachment[];
if (validUnfurls.length > 1) {
console.error('More than one unfurler responded to a given URL', { url });
} else if (validUnfurls.length === 1) {
linkUnfurls[url] = validUnfurls[0];
}
}),
);
const unfurl = await client.chat.unfurl({
channel,
ts: message_ts,
unfurls: linkUnfurls,
});
if (!unfurl.ok) {
console.error('Failed to unfurl', { unfurl, linkUnfurls });
}
});
app.start(process.env.PORT ? parseInt(process.env.PORT, 10) : 8080).then(() => {
app.start(process.env.PORT ? parseInt(process.env.PORT, 10) : 8080).then((server) => {
console.log('Chromium Unfurler listening...');
});