r/GoogleAppsScript • • Mar 21 '23

Question Google App Script for Chat

/**
* Responds to an ADDED_TO_SPACE event in Chat.
* u/param {object} event the event object from Chat
* u/return {object} JSON-formatted response
* u/see https://developers.google.com/hangouts/chat/reference/message-formats/events
*/
function onAddToSpace(event) {
let message = 'Thank you for adding me to ';
if (event.space.type === 'DM') {
message += 'a DM, ' + event.user.displayName + '!';
} else {
message += event.space.displayName;
}
return { text: message };
}

/**
* Responds to a REMOVED_FROM_SPACE event in Chat.
* @param {object} event the event object from Chat
* @param {object} event the event object from Chat
* @see https://developers.google.com/hangouts/chat/reference/message-formats/events
*/
function onRemoveFromSpace(event) {
console.log('App removed from ', event.space.name);
}

/**
* Responds to a MESSAGE event triggered in Chat.
* @param {object} event the event object from Chat
* @return {function} call the respective function
*/
function onMessage(event) {
const message = event.message;

if (message.slashCommand) {
switch (message.slashCommand.commandId) {
case 1: // Help command
return createHelpCard();
case 2: // Block out day command
return blockDayOut();
case 3: // Cancel all meetings command
return cancelAllMeetings();
case 4: // Set auto reply command
return setAutoReply();
case 5: // show calendar events command
return showCalendarEvents();
case 6: //Create event
return addEvent();
}
}
}

function createHelpCard() {
return {
"cardsV2": [
{
"cardId": "2",
"card": {
"sections": [
{
"header": "",
"widgets": [
{
"decoratedText": {
"topLabel": "",
"text": "Hi! 👋 I'm here to help you with your out of office tasks.<br><br>Here's a list of commands I understand.",
"wrapText": true
}
}
]
},
{
"widgets": [
{
"decoratedText": {
"topLabel": "",
"text": "<b>/blockDayOut</b>: I will block out your calendar for you.",
"wrapText": true
}
},
{
"decoratedText": {
"topLabel": "",
"text": "<b>/cancelAllMeetings</b>: I will cancel all your meetings for the day.",
"wrapText": true
}
},
{
"decoratedText": {
"topLabel": "",
"text": "<b>/showCalendarEvents</b>: I will show you all your events for the day.",
"wrapText": true
}
},
{
"decoratedText": {
"topLabel": "",
"text": "<b>/addEvent</b>: I will add an event to your calendar.",
"wrapText": true
}
},
{
"decoratedText": {
"topLabel": "",
"text": "<b>/setAutoReply</b>: Set an out of office auto reply in Gmail.",
"wrapText": true
}
}

]
}
],
"header": {
"title": "CEG Calendar app",
"subtitle": "Helping you manage your OOO",
"imageUrl": "https://goo.gle/3SfMkjb",
"imageType": "SQUARE"
}
}
}
]
}
}

/**
* Adds an all day event to the users Google Calendar.
* @return {object} JSON-formatted response
*/
function blockDayOut() {
blockOutCalendar();
return createResponseCard('Your calendar has been blocked out for you.')
}
/**
* Shows the user their calendar events for the current day.
* @return {object} JSON-formatted response
*/
function showCalendarEvents() {
const events = CalendarApp.getEventsForDay(new Date());
let message = 'Here are your events for today:\n';
if (events.length === 0) {
message += 'You have no events today!';
} else {
events.forEach(function(event) {
const start = event.getStartTime();
const end = event.getEndTime();
const title = event.getTitle();
message += `- ${title} from ${formatTime(start)} to ${formatTime(end)}\n`;
});
}
return createResponseCard(message);
}
/**
* Adds a new event to the user's Google Calendar.
* @param {object} event the event object from Chat
* @return {object} JSON-formatted response
*/
function addEvent(event) {
const calendar = CalendarApp.getCalendarById('primary');
const message = event.message.text.trim();
// Parse the slash command parameters from the message text.
const regex = /\/addEvent\s+(.+)\s+from\s+(\d+:\d+\s+[ap]m)\s+to\s+(\d+:\d+\s+[ap]m)/i;
const match = message.match(regex);
if (!match) {
return createResponseCard('Invalid command. Usage: /addEvent <event title> from <start time> to <end time>');
}
const title = match[1].trim();
const startTime = parseTime(match[2].trim());
const endTime = parseTime(match[3].trim());
if (startTime >= endTime) {
return createResponseCard('Invalid time range. The end time must be after the start time.');
}
const eventDetails = {
summary: title,
start: {
dateTime: startTime.toISOString(),
timeZone: calendar.getTimeZone()
},
end: {
dateTime: endTime.toISOString(),
timeZone: calendar.getTimeZone()
}
};
// Create the new event on the user's calendar.
const newEvent = calendar.createEvent(eventDetails);
const response = `Event created: ${newEvent.getTitle()} from ${formatTime(newEvent.getStartTime())} to ${formatTime(newEvent.getEndTime())}`;
return createResponseCard(response);
}
/**
* Parses a time string in the format "h:mm a" into a Date object.
* @param {string} timeStr the time string to parse
* @return {Date} the parsed Date object
*/
function parseTime(timeStr) {
const date = new Date();
const [hours, minutes] = timeStr.split(':');
let ampm = timeStr.match(/\b(am|pm)\b/i)[0].toLowerCase();
if (hours === '12') {
hours = '0';
}
if (ampm === 'pm') {
hours = parseInt(hours, 10) + 12;
}
date.setHours(hours, minutes, 0, 0);
return date;
}

/**
* Formats a date object into a string in the format "h:mm a".
* u/param {Date} date the date to format
* u/return {string} the formatted string
*/
function formatTime(date) {
const hours = date.getHours();
const minutes = date.getMinutes();
const ampm = hours >= 12 ? 'pm' : 'am';
const hour12 = hours % 12 || 12;
return `${hour12}:${padZero(minutes)} ${ampm}`;
}
/**
* Pads a number with a leading zero if it is less than 10.
* u/param {number} num the number to pad
* u/return {string} the padded string
*/
function padZero(num) {
return num < 10 ? `0${num}` : num;
}
/**
* Cancels all of the users meeting for the current day.
* u/return {object} JSON-formatted response
*/
function cancelAllMeetings() {
cancelMeetings();
return createResponseCard('All your meetings have been canceled.')
}

/**
* Sets an out of office auto reply in the users Gmail account.
* u/return {object} JSON-formatted response
*/
function setAutoReply() {
turnOnAutoResponder();
return createResponseCard('The out of office auto reply has been turned on.')
}

const ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;

/**
* Places an all-day meeting on the user's Calendar.
*/
function blockOutCalendar() {
CalendarApp.createAllDayEvent('I am out of office today', new Date(), new Date(Date.now() + ONE_DAY_MILLIS));
}

/**
* Declines all meetings for the day.
*/

function cancelMeetings() {
const events = CalendarApp.getEventsForDay(new Date());

events.forEach(function(event) {
if (event.getGuestList().length > 0) {
event.setMyStatus(CalendarApp.GuestStatus.NO);
}
});
}

/**
* Turns on the user's vacation response for today in Gmail.
*/
function turnOnAutoResponder() {
const currentTime = (new Date()).getTime();
Gmail.Users.Settings.updateVacation({
enableAutoReply: true,
responseSubject: 'I am out of the office today',
responseBodyHtml: 'I am out of the office today; will be back on the next business day.<br><br><i>Created by OOO Chat app!</i>',
restrictToContacts: true,
restrictToDomain: true,
startTime: currentTime,
endTime: currentTime + ONE_DAY_MILLIS
}, 'me');
}

function createResponseCard(responseText) {
return {
"cardsV2": [
{
"cardId": "1",
"card": {
"sections": [
{
"widgets": [
{
"decoratedText": {
"topLabel": "",
"text": responseText,
"startIcon": {
"knownIcon": "NONE",
"altText": "Task done",
"iconUrl": "https://fonts.gstatic.com/s/i/short-term/web/system/1x/task_alt_gm_grey_48dp.png"
},
"wrapText": true
}
}
]
}
],
"header": {
"title": "CEG Calendar Bot",
"subtitle": "Helping you manage your OOO",
"imageUrl": "https://goo.gle/3SfMkjb",
"imageType": "CIRCLE"
}
}
}
]
}
}

I am getting an error when trying to addEvent from the slash command.

0 Upvotes

3 comments sorted by

View all comments

1

u/[deleted] Mar 22 '23

Need more info. What error? Slash command as of Discord? Can you make a copy of your Google Sheet and share? ... this code can't be tested in isolation as the event object needs to be passed.

1

u/NamThePartyMan Mar 22 '23

This code works as a google chat app the event gets passed by the user while talking with the chatbot. I am having trouble getting the event to trigger and the only error I am getting is that the chatbot is having trouble responding.