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

add support for issue comments #2

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 80 additions & 40 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,106 @@ const app = express();

const port: number = parseInt(process.env.PORT ?? '3000');

const embedFooter = {
text: `Linear App`,
icon_url:
"https://pbs.twimg.com/profile_images/1121592030449168385/MF6whgy1_400x400.png",
};

app.use(express.json());

app.post<Request['params'], unknown, IncomingLinearWebhookPayload>('/linear/:webhookTarget', async (req, res) => {
const payload = req.body;

const webhookTarget = req.params.webhookTarget;
const target = process.env[`WEBHOOK_${webhookTarget.toUpperCase()}`];

console.log("Received webhook event for target", webhookTarget);
if (target === undefined) {
console.log("Invalid target: Webhook env not set");
return res.status(400).send({status: 400, message: "Unknown webhook target."});
}

if (payload.action === 'create' && payload.type === 'Issue') {
const result = await newIssue(payload, webhookTarget);
if (!result)
{
console.log("Invalid target: Webhook env not set");
res.status(400).send({status: 400, message: "Unknown webhook target."})
return;
}
console.log("debug result", result);
console.log("Received webhook event for target", webhookTarget);

if (payload.action === 'create') {
if (payload.type === 'Issue')
await newIssue(payload, target);
else if (payload.type === 'Comment')
await newComment(payload, target);
}

res.sendStatus(200);
});

app.listen(port, () => console.log(`Webhook consumer listening on port ${port}!`));

function newIssue(payload: IncomingLinearWebhookPayload, webhookTarget: string) {
const target = process.env[`WEBHOOK_${webhookTarget.toUpperCase()}`];

console.log("Sending webhook to target", target);

if (target === undefined) return false;

return fetch(target, {
function newComment(payload: IncomingLinearWebhookPayload, webhookTarget: string) {
console.log("Sending comment webhook to target", webhookTarget);
return fetch(webhookTarget, {
method: "POST",
headers: {
"content-type": "application/json"
"content-type": "application/json",
},
body: JSON.stringify({
embeds: [
{
color: 0x4752b2,
color: 0x73ff73,
author: {
name: `Issue Created [${getId(payload.url)}]`,
name: `Comment Created [${getCommentId(payload.url)}]`,
},
title: payload.data.title,
title: `Comment by ${payload.data.user!.name}`,
url: payload.url,
timestamp: new Date(),
fields: [
{
name: 'Priority',
value: getPriorityValue(payload.data.priority ?? 0),
inline: true,
name: "Content",
value: payload.data.body,
},
{
name: 'Points',
value: payload.data.estimate,
inline: true,
},
{
name: 'Labels',
value: prettifyLabels(payload.data.labels!),
inline: false,
},
name: "Issue",
value: payload.data.issue!.title
}
],
timestamp: new Date(),
footer: {
text: `Linear App`,
icon_url: 'https://pbs.twimg.com/profile_images/1121592030449168385/MF6whgy1_400x400.png',
footer: embedFooter,
},
],
}),
});
}

function newIssue(payload: IncomingLinearWebhookPayload, webhookTarget: string) {
console.log("Sending issue webhook to target", webhookTarget);
let fields = [
{
name: "Priority",
value: getPriorityValue(payload.data.priority ?? 0),
inline: true,
}
];

if (payload.data.labels)
fields.push({
name: "Labels",
value: prettifyLabels(payload.data.labels),
inline: false,
});

return fetch(webhookTarget, {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({
embeds: [
{
color: 0x4752b2,
author: {
name: `Issue Created [${getIssueId(payload.url)}]`,
},
title: payload.data.title,
url: payload.url,
fields: fields,
timestamp: new Date(),
footer: embedFooter,
},
],
}),
Expand Down Expand Up @@ -105,10 +137,18 @@ function getPriorityValue(priority: NonNullable<IncomingLinearWebhookPayload['da
* Get the task ID from url
* @param link task url
*/
function getId(link: string) {
function getIssueId(link: string) {
return link.split('/')[5];
}

/**
* Get the comment ID from url
* @param link comment url
*/
function getCommentId(link: string) {
return link.split('#')[1];
}

/**
* Formats and prettifies label(s)
* @param labels connected labels
Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ export interface IncomingLinearWebhookPayload {
export interface Data {
id: string;
title?: string;
issue?: {
id: string;
title: string;
};
user?: {
id: string;
name: string;
};
subscriberIds?: string[];
previousIdentifiers?: any[];
createdAt: string;
Expand Down