-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCode.js
151 lines (137 loc) · 5.42 KB
/
Code.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
* Builds email with training information and sends it
*
* Explanation
* This code sets up a Google Sheet that contains a training schedule, then
* uses Apps Script to send email reminders to the user about upcoming workouts.
* The code defines constants for the sheet name, header row and column names,
* and email settings. It then creates a Spreadsheet class that represents the
* training schedule, with methods for getting the email date and email content.
* Finally, it creates an EmailSender class that sends the email using a template
* file and the MailApp service. The main() function brings everything together
* by creating instances of the Spreadsheet and EmailSender classes and sending
* the email if email reminders are turned on and there is an upcoming workout
* scheduled.
*
* This code needs a Google Spreadsheet and an email.html template.
* Get the Google Spreadsheet here: https://docs.google.com/spreadsheets/d/1OrGPV743KBXale8ZKQXNKI8ubKRcnBoipjITNq0zHm4/edit?usp=sharing
*
* Developed by Juan Lazarde. 2023
*/
// Sets sheet name
const SHEET_NAME = "Training Schedule";
// Sets header-row and column names and index numbers
const HEADER_ROW = 3;
const COLUMNS = {
date: 0,
week: 1,
dte: 2,
workout: 3,
exercise: 4,
link: 5,
};
// Sets email to be sent and number of days from today to send it
const EMAIL_ON = true;
const DAYS_AHEAD_TO_SEND = 0; // Same day is 0
// Represents spreadsheet and contains functions to build the email's body
class Spreadsheet {
// Creates an instance of Spreadsheet and instance variables inside it
constructor() {
this.ss = SpreadsheetApp.getActiveSpreadsheet();
this.sheet = this.ss.getSheetByName(SHEET_NAME);
this.range = this.sheet.getDataRange();
this.rows = this.range.getDisplayValues();
this.lastRow = this.range.getLastRow();
this.dataRow = HEADER_ROW + 1;
this.timeZone = this.ss.getSpreadsheetTimeZone();
this.emailDate = this.getEmailDate(this.timeZone);
}
/**
* Returns formatted date to send email in corresponding to the timeZone as a string
* @param {string} timeZone - Your timezone
* @returns {string} The formatted date to send the email
*/
getEmailDate(timeZone) {
let date = new Date();
date.setDate(date.getDate() + DAYS_AHEAD_TO_SEND);
return Utilities.formatDate(date, timeZone, "EEE, MMM d, yyyy");
}
/**
* Returns content of the email
* @returns {object} The content of the email as an object or null
*/
getEmailContent() {
// Iterates through rows (dates) to find a match and pull data
for (let i = this.dataRow; i < this.lastRow; i++) {
let row = this.rows[i];
// Finds values from current date
if (row[COLUMNS.date] === this.emailDate) {
// Returns an array if "|" character is present in the exercise string
const getExercise = (x) => (x.indexOf("|") > -1 ? x.split(" | ") : x);
// Returns 'Rest day' if workouts are empty
const getWorkout = (x) => (x.trim() ? x : "Rest day");
const plan = this.ss
.getRangeByName("PlanSelected")
.getValues()
.toString();
return {
date: row[COLUMNS.date],
week: row[COLUMNS.week],
dte: row[COLUMNS.dte],
workout: getWorkout(row[COLUMNS.workout]),
exercises: getExercise(row[COLUMNS.exercise]),
link: row[COLUMNS.link],
plan,
sheetUrl: this.ss.getUrl(),
};
}
}
return null;
}
}
// Represents an email sender and contains functions to assemble email from template and send it
class EmailSender {
// Creates an instance of EmailSender with constants declared
constructor() {
this.recipient = Session.getActiveUser().getEmail();
this.EMAIL_TEMPLATE_FILE = "email";
}
/**
* Sends an email
* @param {string} subject - The subject of the email
* @param {object} content - The content of the email as an object
*/
send(subject, content) {
let template = HtmlService.createTemplateFromFile(this.EMAIL_TEMPLATE_FILE);
template.content = content;
const msg = template.evaluate();
MailApp.sendEmail(this.recipient, subject, msg.getContent(), {
htmlBody: msg.getContent(),
});
}
}
/**
* The main function of the script, which orchestrates the sending of email
* reminders for upcoming workouts. It creates instances of the Spreadsheet
* and EmailSender classes, and uses them to retrieve the email content and
* send the email if email reminders are turned on and there is an upcoming
* workout scheduled for the current day. If there are no upcoming workouts
* scheduled for the current day, or if email reminders are turned off, no
* email is sent.
*
* @returns {void} - This function does not return a value.
*/
function main() {
const spreadsheet = new Spreadsheet();
const emailContent = spreadsheet.getEmailContent();
if (EMAIL_ON && emailContent) {
const emailSender = new EmailSender();
const subject = `Training reminder: ${emailContent.workout}`;
emailSender.send(subject, emailContent);
}
}
// Samples: https://github.com/googleworkspace/apps-script-sample
// References: https://developers.google.com/apps-script/reference/
// Style: https://developer.mozilla.org/en-US/docs/MDN/Writing_guidelines/Writing_style_guide/Code_style_guide/JavaScript
// Date notations: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
// Google Style: https://google.github.io/styleguide/jsguide.html