Skip to content

Commit 4709e65

Browse files
PierrickVouletpierrick
andauthored
feat: add attendance chat app (#386)
Co-authored-by: pierrick <[email protected]>
1 parent 8cb3feb commit 4709e65

File tree

11 files changed

+579
-0
lines changed

11 files changed

+579
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Attendance Chat App
2+
3+
This code sample shows how to build a Google Chat app using Google
4+
Apps Script. The Chat app responds to messages in a space or direct message (DM) and
5+
allows the user to set a vacation responder in Gmail or add an all-day event to
6+
their Calendar from Google Chat.
7+
8+
## Usage
9+
10+
You can follow [this codelab](https://developers.google.com/codelabs/chat-apps-script)
11+
to build and test this Chat app.
12+
13+
To use this Chat app, you must enable the Hangouts Chat API in the
14+
[Google API Console](https://console.developers.google.com/). After enabling
15+
the API, configuring the Chat app, and publishing it, you must add the Chat app to a space
16+
or DM to begin a conversation.
17+
18+
For more information about how to publish a Chat app, see
19+
[Publishing Google Chat apps](https://developers.google.com/workspace/chat/apps-publish).
20+
21+
## Disclaimer
22+
23+
This is not an official product.
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/**
2+
* Responds to an ADDED_TO_SPACE event in Google Chat.
3+
* @param {object} event the event object from Google Chat
4+
* @return {object} JSON-formatted response
5+
* @see https://developers.google.com/workspace/chat/receive-respond-interactions
6+
*/
7+
function onAddToSpace(event) {
8+
console.info(event);
9+
let message = "Thank you for adding me to ";
10+
if (event.space.type === "DM") {
11+
message += `a DM, ${event.user.displayName}!`;
12+
} else {
13+
message += event.space.displayName;
14+
}
15+
return { text: message };
16+
}
17+
18+
/**
19+
* Responds to a REMOVED_FROM_SPACE event in Google Chat.
20+
* @param {object} event the event object from Google Chat
21+
* @see https://developers.google.com/workspace/chat/receive-respond-interactions
22+
*/
23+
function onRemoveFromSpace(event) {
24+
console.info(event);
25+
console.log("Chat app removed from ", event.space.name);
26+
}
27+
28+
const DEFAULT_IMAGE_URL = "https://goo.gl/bMqzYS";
29+
const HEADER = {
30+
header: {
31+
title: "Attendance Chat app",
32+
subtitle: "Log your vacation time",
33+
imageUrl: DEFAULT_IMAGE_URL,
34+
},
35+
};
36+
37+
/**
38+
* Creates a card-formatted response.
39+
* @param {object} widgets the UI components to send
40+
* @return {object} JSON-formatted response
41+
*/
42+
function createCardResponse(widgets) {
43+
return {
44+
cards: [
45+
HEADER,
46+
{
47+
sections: [
48+
{
49+
widgets: widgets,
50+
},
51+
],
52+
},
53+
],
54+
};
55+
}
56+
57+
const REASON = {
58+
SICK: "Out sick",
59+
OTHER: "Out of office",
60+
};
61+
/**
62+
* Responds to a MESSAGE event triggered in Google Chat.
63+
* @param {object} event the event object from Google Chat
64+
* @return {object} JSON-formatted response
65+
*/
66+
function onMessage(event) {
67+
console.info(event);
68+
let reason = REASON.OTHER;
69+
const name = event.user.displayName;
70+
const userMessage = event.message.text;
71+
72+
// If the user said that they were 'sick', adjust the image in the
73+
// header sent in response.
74+
if (userMessage.indexOf("sick") > -1) {
75+
// Hospital material icon
76+
HEADER.header.imageUrl = "https://goo.gl/mnZ37b";
77+
reason = REASON.SICK;
78+
} else if (userMessage.indexOf("vacation") > -1) {
79+
// Spa material icon
80+
HEADER.header.imageUrl = "https://goo.gl/EbgHuc";
81+
}
82+
83+
const widgets = [
84+
{
85+
textParagraph: {
86+
text: `Hello, ${name}.<br/>Are you taking time off today?`,
87+
},
88+
},
89+
{
90+
buttons: [
91+
{
92+
textButton: {
93+
text: "Set vacation in Gmail",
94+
onClick: {
95+
action: {
96+
actionMethodName: "turnOnAutoResponder",
97+
parameters: [
98+
{
99+
key: "reason",
100+
value: reason,
101+
},
102+
],
103+
},
104+
},
105+
},
106+
},
107+
{
108+
textButton: {
109+
text: "Block out day in Calendar",
110+
onClick: {
111+
action: {
112+
actionMethodName: "blockOutCalendar",
113+
parameters: [
114+
{
115+
key: "reason",
116+
value: reason,
117+
},
118+
],
119+
},
120+
},
121+
},
122+
},
123+
],
124+
},
125+
];
126+
return createCardResponse(widgets);
127+
}
128+
129+
/**
130+
* Responds to a CARD_CLICKED event triggered in Google Chat.
131+
* @param {object} event the event object from Google Chat
132+
* @return {object} JSON-formatted response
133+
* @see https://developers.google.com/workspace/chat/receive-respond-interactions
134+
*/
135+
function onCardClick(event) {
136+
console.info(event);
137+
let message = "";
138+
const reason = event.action.parameters[0].value;
139+
if (event.action.actionMethodName === "turnOnAutoResponder") {
140+
turnOnAutoResponder(reason);
141+
message = "Turned on vacation settings.";
142+
} else if (event.action.actionMethodName === "blockOutCalendar") {
143+
blockOutCalendar(reason);
144+
message = "Blocked out your calendar for the day.";
145+
} else {
146+
message = "I'm sorry; I'm not sure which button you clicked.";
147+
}
148+
return { text: message };
149+
}
150+
151+
const ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
152+
/**
153+
* Turns on the user's vacation response for today in Gmail.
154+
* @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER
155+
*/
156+
function turnOnAutoResponder(reason) {
157+
const currentTime = new Date().getTime();
158+
Gmail.Users.Settings.updateVacation(
159+
{
160+
enableAutoReply: true,
161+
responseSubject: reason,
162+
responseBodyHtml:
163+
"I'm out of the office today; will be back on the next business day.<br><br><i>Created by Attendance Chat app!</i>",
164+
restrictToContacts: true,
165+
restrictToDomain: true,
166+
startTime: currentTime,
167+
endTime: currentTime + ONE_DAY_MILLIS,
168+
},
169+
"me",
170+
);
171+
}
172+
173+
/**
174+
* Places an all-day meeting on the user's Calendar.
175+
* @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER
176+
*/
177+
function blockOutCalendar(reason) {
178+
CalendarApp.createAllDayEvent(
179+
reason,
180+
new Date(),
181+
new Date(Date.now() + ONE_DAY_MILLIS),
182+
);
183+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"timeZone": "America/Los_Angeles",
3+
"dependencies": {
4+
"enabledAdvancedServices": [
5+
{
6+
"userSymbol": "Gmail",
7+
"serviceId": "gmail",
8+
"version": "v1"
9+
}
10+
]
11+
},
12+
"chat": {}
13+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Responds to an ADDED_TO_SPACE event
3+
* in Google Chat.
4+
*
5+
* @param event the event object from Google Chat
6+
* @return JSON-formatted response
7+
*/
8+
function onAddToSpace(event) {
9+
console.info(event);
10+
11+
let message = "";
12+
13+
if (event.space.type === "DM") {
14+
message = `Thank you for adding me to a DM, ${event.user.displayName}!`;
15+
} else {
16+
message = `Thank you for adding me to ${event.space.displayName}`;
17+
}
18+
19+
return { text: message };
20+
}
21+
22+
/**
23+
* Responds to a REMOVED_FROM_SPACE event
24+
* in Google Chat.
25+
*
26+
* @param event the event object from Google Chat
27+
*/
28+
function onRemoveFromSpace(event) {
29+
console.info(event);
30+
console.info("Chat app removed from ", event.space.name);
31+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"timeZone": "America/Los_Angeles",
3+
"dependencies": {},
4+
"chat": {}
5+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Responds to an ADDED_TO_SPACE event
3+
* in Google Chat.
4+
*
5+
* @param event the event object from Google Chat
6+
* @return JSON-formatted response
7+
*/
8+
function onAddToSpace(event) {
9+
console.info(event);
10+
11+
let message = "";
12+
13+
if (event.space.type === "DM") {
14+
message = `Thank you for adding me to a DM, ${event.user.displayName}!`;
15+
} else {
16+
message = `Thank you for adding me to ${event.space.displayName}`;
17+
}
18+
19+
return { text: message };
20+
}
21+
22+
/**
23+
* Responds to a REMOVED_FROM_SPACE event
24+
* in Google Chat.
25+
*
26+
* @param event the event object from Google Chat
27+
*/
28+
function onRemoveFromSpace(event) {
29+
console.info(event);
30+
console.info("Chat app removed from ", event.space.name);
31+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"timeZone": "America/Los_Angeles",
3+
"dependencies": {},
4+
"chat": {}
5+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Responds to an ADDED_TO_SPACE event
3+
* in Google Chat.
4+
*
5+
* @param event the event object from Google Chat
6+
* @return JSON-formatted response
7+
*/
8+
function onAddToSpace(event) {
9+
console.info(event);
10+
11+
let message = "";
12+
13+
if (event.space.type === "DM") {
14+
message = `Thank you for adding me to a DM, ${event.user.displayName}!`;
15+
} else {
16+
message = `Thank you for adding me to ${event.space.displayName}`;
17+
}
18+
19+
return { text: message };
20+
}
21+
22+
/**
23+
* Responds to a REMOVED_FROM_SPACE event
24+
* in Google Chat.
25+
*
26+
* @param event the event object from Google Chat
27+
*/
28+
function onRemoveFromSpace(event) {
29+
console.info(event);
30+
console.info("Chat app removed from ", event.space.name);
31+
}
32+
33+
/**
34+
* Creates a card-formatted response.
35+
*
36+
* @param widgets the UI components to send
37+
* @return JSON-formatted response
38+
*/
39+
function createCardResponse(widgets) {
40+
return {
41+
cards: [
42+
header,
43+
{
44+
sections: [
45+
{
46+
widgets: widgets,
47+
},
48+
],
49+
},
50+
],
51+
};
52+
}
53+
54+
/**
55+
* Responds to a MESSAGE event triggered in Google Chat.
56+
*
57+
* @param event the event object from Google Chat
58+
* @return JSON-formatted response
59+
*/
60+
function onMessage(event) {
61+
const userMessage = event.message.text;
62+
63+
const widgets = [
64+
{
65+
textParagraph: {
66+
text: `You said: ${userMessage}`,
67+
},
68+
},
69+
];
70+
71+
return createCardResponse(widgets);
72+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"timeZone": "America/Los_Angeles",
3+
"dependencies": {},
4+
"chat": {}
5+
}

0 commit comments

Comments
 (0)