-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
99 lines (82 loc) · 3.06 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { Buffer } from 'node:buffer';
// See https://docs.github.com/en/webhooks/webhook-events-and-payloads
function buildMessage(event) {
const messageBlock = {
type: 'section',
text: { type: 'mrkdwn' },
accessory: { type: 'image' },
};
let user, type;
if (['member_added', 'member_removed'].includes(event.action)) {
user = event.membership.user;
type = `the ${event.organization.login} organisation`;
if (event.action == 'member_added') { type += ` (as ${event.membership.role})`; }
} else if (['added', 'removed'].includes(event.action)) {
user = event.member;
type = `the <${event.repository.html_url}|${event.repository.full_name}> repository`;
if (event.action == 'added') { type += ` (with ${event.changes.role_name.to} permission)`; }
}
if (user) {
messageBlock.accessory.image_url = user.avatar_url;
messageBlock.accessory.alt_text = `${user.login} on GitHub`;
messageBlock.text.text = `*<${user.html_url}|${user.login}>* `;
if (event.action.includes('added')) {
messageBlock.text.text += 'was added to ' + type;
} else if (user.login == event.sender.login) {
messageBlock.text.text += 'removed themselves from ' + type;
} else {
messageBlock.text.text += 'was removed from ' + type;
}
if (user.login != event.sender.login) {
messageBlock.text.text += ` by <${event.sender.html_url}|${event.sender.login}>`;
}
return {
text: messageBlock.text.text.replace(/<[^|]*\|([^>]*)>/g, '$1'),
blocks: [messageBlock],
};
}
}
// https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries
async function checkSignature(secret, signature, payload) {
if (!signature) { return 'Missing signature'; }
// sha256=xxx
let [alg, sig, ...extra] = signature.split('=');
if (alg != 'sha256' || !sig || extra.length) { return 'Malformed signature'; }
const encoder = new TextEncoder();
const key = await crypto.subtle.importKey('raw', encoder.encode(secret), {
name: 'HMAC',
hash: {name: 'SHA-256'},
}, false, ['verify']);
const signatureBytes = Buffer.from(sig, 'hex');
const data = encoder.encode(payload);
const verify = await crypto.subtle.verify('HMAC', key, signatureBytes, data);
if (!verify) { return 'Invalid signature'; }
}
export default {
async fetch(request, env, ctx) {
const body = await request.text();
const error = await checkSignature(
env.API_SECRET,
request.headers.get('x-hub-signature-256') || '',
body
);
if (error) { return new Response(error, {status: 401}); }
const event = JSON.parse(body);
const message = buildMessage(event);
if (message && env.SLACK_WEBHOOK) {
let response = await fetch(env.SLACK_WEBHOOK, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(message),
});
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
return new Response('KO');
},
};