Skip to content

Commit 28581b4

Browse files
feat: Store source of contact
1 parent 485c06e commit 28581b4

File tree

7 files changed

+282
-303
lines changed

7 files changed

+282
-303
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import { Client, isFullPage } from "@notionhq/client";
2+
import { notifyContactCreated } from "./slack";
3+
4+
const { NOTION_TOKEN, MENTION_EMAILS, MENTION_IDS } = process.env;
5+
6+
const notion = new Client({ auth: NOTION_TOKEN });
7+
8+
const mentionPerson = ({ id }: { id: string }) => [
9+
{
10+
mention: {
11+
user: {
12+
id,
13+
},
14+
},
15+
plain_text: "",
16+
href: null,
17+
},
18+
{
19+
text: {
20+
content: " ",
21+
},
22+
},
23+
];
24+
25+
const getMentions = () => {
26+
if (MENTION_EMAILS && MENTION_IDS) {
27+
const emails = MENTION_EMAILS.split(",");
28+
const ids = MENTION_IDS.split(",");
29+
30+
if (emails.length && ids.length) {
31+
return ids.map((id, i) => ({
32+
id,
33+
}));
34+
}
35+
}
36+
return [];
37+
};
38+
39+
const mentionPeople = () => {
40+
return getMentions().flatMap(mentionPerson);
41+
};
42+
43+
const createContactObject = (
44+
id: string,
45+
email: string,
46+
name: string,
47+
content: string,
48+
databaseID: string,
49+
source: string,
50+
) => ({
51+
parent: {
52+
database_id: databaseID,
53+
},
54+
properties: {
55+
id: {
56+
title: [
57+
{
58+
text: {
59+
content: id,
60+
},
61+
},
62+
],
63+
},
64+
email: {
65+
email,
66+
},
67+
name: {
68+
rich_text: [
69+
{
70+
text: {
71+
content: name,
72+
},
73+
},
74+
],
75+
},
76+
date: {
77+
date: {
78+
start: new Date().toISOString(),
79+
},
80+
},
81+
source: {
82+
rich_text: [
83+
{
84+
text: {
85+
content: source,
86+
},
87+
},
88+
],
89+
},
90+
},
91+
children: [
92+
{
93+
paragraph: {
94+
rich_text: [
95+
{
96+
text: {
97+
content,
98+
},
99+
},
100+
],
101+
},
102+
},
103+
{
104+
paragraph: {
105+
rich_text: mentionPeople(),
106+
},
107+
},
108+
],
109+
});
110+
111+
const createContact = async (
112+
id: string,
113+
email: string,
114+
name: string,
115+
content: string,
116+
databaseID: string,
117+
source: string,
118+
) => {
119+
const response = await notion.pages.create(
120+
createContactObject(id, email, name, content, databaseID, source),
121+
);
122+
123+
if (response.id && isFullPage(response)) {
124+
return {
125+
id: response.id,
126+
url: response.url,
127+
};
128+
}
129+
throw {
130+
body: {
131+
message: "Failed to create notion page",
132+
},
133+
};
134+
};
135+
136+
export const processContact = async (event: {
137+
id: string;
138+
email: string;
139+
name: string;
140+
message: string;
141+
databaseID: string;
142+
source: string;
143+
}) => {
144+
const { id, email, name, message, databaseID, source } = event;
145+
146+
if (!id || !email || !name || !databaseID) {
147+
console.log({ event });
148+
throw {
149+
body: {
150+
message: "Missing data in process contact event",
151+
},
152+
};
153+
}
154+
155+
const { id: notionPageID, url } = await createContact(
156+
`Message from ${name} (${id})`,
157+
email,
158+
name,
159+
message,
160+
databaseID,
161+
source,
162+
);
163+
164+
await notifyContactCreated(name, email, url);
165+
return notionPageID;
166+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
const { SLACK_CHANNEL, SLACK_BOT_TOKEN, IS_OFFLINE } = process.env;
2+
3+
export const createPayload = (name: string, email: string, url: string) => ({
4+
channel: SLACK_CHANNEL,
5+
blocks: [
6+
{
7+
type: "header",
8+
text: {
9+
type: "plain_text",
10+
text: "We have 1 new message(s).",
11+
emoji: true,
12+
},
13+
},
14+
{
15+
type: "section",
16+
text: {
17+
type: "mrkdwn",
18+
text: `We got a new message from _${name}_ (_${email}_).`,
19+
},
20+
},
21+
{
22+
type: "divider",
23+
},
24+
{
25+
type: "section",
26+
text: {
27+
type: "mrkdwn",
28+
text: " ",
29+
},
30+
accessory: {
31+
type: "button",
32+
text: {
33+
type: "plain_text",
34+
text: "Show me the message",
35+
emoji: true,
36+
},
37+
value: "new_message_click",
38+
url,
39+
action_id: "button-action",
40+
},
41+
},
42+
],
43+
});
44+
45+
export const notifyContactCreated = async (
46+
name: string,
47+
email: string,
48+
url: string,
49+
) => {
50+
const payload = createPayload(name, email, url);
51+
const payloadStringify = JSON.stringify(payload);
52+
53+
if (IS_OFFLINE) {
54+
console.log(payload);
55+
} else {
56+
const result = await fetch("https://slack.com/api/chat.postMessage", {
57+
method: "POST",
58+
body: payloadStringify,
59+
headers: {
60+
"Content-Type": "application/json; charset=utf-8",
61+
"Content-Length": payloadStringify.length.toString(),
62+
Authorization: `Bearer ${SLACK_BOT_TOKEN}`,
63+
Accept: "application/json",
64+
},
65+
});
66+
if (result.status !== 200) {
67+
throw {
68+
body: "Could not send notification message to Slack",
69+
statusCode: result.status,
70+
};
71+
}
72+
}
73+
};

0 commit comments

Comments
 (0)