forked from bernot-dev/starrez-google-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstarrez.js
281 lines (240 loc) · 7.82 KB
/
starrez.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/* global getRoomLocationTable */
/* exported
formatSheet
findRoomLocation
getRoomLocationRegExp
getStarRezReport
query
queryArray
validDate
*/
/**
* Call API
* @param {object} params Parameters for request
* @return {object} Object returned by API call
*/
function callApi(path, params) {
// Ensure credentials are set
var credentials = PropertiesService
.getUserProperties()
.getProperty("STARREZ_CREDENTIALS");
if (credentials === null) {
throw new Error("StarRez credentials could not be found. Please run setup function.");
}
if (params === undefined) {
throw new Error("params must be defined");
} else if (typeof params === "object") {
// Verify or fill in Headers
if (params.headers === undefined) {
params.headers = {
"Accept": "application/json",
"Authorization": credentials
};
} else if (typeof params.headers === "object") {
if (params.headers.Accept === undefined) {
params.headers.Accept = "application/json";
}
if (params.headers.Authorization === undefined) {
params.headers.Authorization = credentials;
}
} else {
throw new Error("params must be an object");
}
// Set contentType to application/json
if (params.contentType === undefined) {
params.contentType = "application/json";
}
// Set request method to POST
params.method = "post";
// Return error response instead of throwing error
params.muteHttpExceptions = true;
// Verify Content-Type
if (params.contentType === undefined) {
throw new Error("contentType must be defined");
} else if (typeof params.contentType !== "string") {
throw new Error("contentType must be a string");
}
} else {
throw new Error("params must be an object");
}
var endpoint = PropertiesService
.getScriptProperties()
.getProperty("STARREZ_API_ENDPOINT");
if (endpoint === null) {
throw new Error("StarRez API Endpoint could not be found. Please run setup function.");
}
if (path === undefined) {
throw new Error("Path of request must be defined");
} else if (typeof path !== "string") {
throw new Error("Invalid path specified");
}
var resp = UrlFetchApp.fetch(endpoint + path, params);
if (resp.getResponseCode() === 200) {
return JSON.parse(resp.getContentText());
}
try {
var [error] = JSON.parse(resp.getContentText());
if (error.description === "Error rendering report: There aren't any records to display") {
return null;
}
} catch (unableToParseJsonFromResponse) {
throw new Error(resp.getContentText() + " May be invalid request.");
}
return undefined;
}
/**
* Convert an array of objects (as returned by StarRez) to a 2D array
* @param {object[]} Array of results from StarRez query/report
* @return {string[][]} 2D array of strings
*/
function objectArrayTo2dArray(resultObjectArray) {
if (resultObjectArray === undefined || resultObjectArray === null) {
return resultObjectArray;
} else if (typeof resultObjectArray === "object" && resultObjectArray instanceof Array && typeof resultObjectArray[0] === "object") {
var array2d = resultObjectArray.map(function mapObjectToArray(row) {
var array = [];
for (var value in row) {
if (typeof value === "string") {
array.push(row[value]);
}
}
return array;
});
var keys = Object.keys(resultObjectArray[0])
.map(function underscoreToSpace(str) {
return str.replace(/_/g, " ");
});
array2d.unshift(keys);
return array2d;
}
throw new Error("resultObjectArray must be an array of objects");
}
/**
* Execute a StarQL query against the database
* @param {string}
* @return [Sheet]{@link https://developers.google.com/apps-script/reference/spreadsheet/sheet}
*/
function query(queryString) {
var params = {};
/**
* If requestBody parameter exists, change method to POST and set requestBody
* as payload.
*/
if (typeof queryString === "string") {
params.contentType = "text/plain";
params.method = "post";
params.payload = queryString;
} else {
throw new Error("Invalid query string.");
}
return callApi("/services/query", params);
}
/**
* Run a StarQL query that returns a 2D array of strings
* @param {object} options
* @return {string[][]} 2D array of strings with results
*/
function queryArray(queryString) {
var resultObjectArray = query(queryString);
return objectArrayTo2dArray(resultObjectArray);
}
/**
* Retrieve report from StarRez using getreport API as a 2D array of strings
* @param {object} options The Description, WebDescription, or Building Code
* (CustomString1) of a RoomLocation
* @return {string[][]}
*/
function getStarRezReport(options) {
// Ensure Report ID is set
if (options.reportId === undefined) {
throw new Error("StarRez \"reportId\" is required, but was not defined.");
}
// Assemble path
var path = "/services/getreport/" + options.reportId;
// Set request parameters for web request
var params = {};
/**
* If requestBody parameter exists, change method to POST and set requestBody
* as payload.
*/
if (options.requestBody !== undefined) {
params.contentType = "application/json";
params.payload = JSON.stringify(options.requestBody);
}
var report = callApi(path, params);
return objectArrayTo2dArray(report);
}
/**
* Validate that a string representing a date can be parsed into a valid date
* @param {string} date Date to be tested
*/
function validDate(date) {
if (Object.prototype.toString.call(date) === "[object Date]") {
if (isNaN(date.valueOf())) {
return false;
}
return true;
}
return false;
}
/**
* @typedef RoomLocation
* @type {object}
* @property {number} RoomLocationID
* @property {string} Building_Code
* @property {string} Description
* @property {string} WebDescription
*/
/**
* Retrieve cached RoomLocation objects in StarRez
* @return {object} An object representing the RoomLocation table in StarRez
*/
function getRoomLocationTable() {
var cache = CacheService.getScriptCache();
// Maximum of 6 hours = 21600 seconds
var CACHE_TIME = 21600;
var roomLocationTableQuery = "SELECT RoomLocationID, [Building Code], Description, WebDescription FROM RoomLocation WHERE RecordTypeEnum=0";
// Cache.remove("RoomLocationTable");
var roomLocationTable = cache.get("RoomLocationTable");
if (roomLocationTable === null) {
Logger.log("Fetching Room Location table");
roomLocationTable = query(roomLocationTableQuery);
cache.put(
"RoomLocationTable",
JSON.stringify(roomLocationTable),
CACHE_TIME
);
} else {
Logger.log("Using cached Room Location table\n");
}
return JSON.parse(roomLocationTable);
}
/**
* Get an cached instance of RegExp that will match any Room Location based on
* any of several values
* @param {string} buildingString The Description, WebDescription, or Building
* Code (CustomString1) of a RoomLocation
* @return {RoomLocation}
*/
function getRoomLocationRegExp() {
var cache = CacheService.getScriptCache();
// Maximum of 6 hours = 21600 seconds
var CACHE_TIME = 21600;
var roomLocationRegExp = cache.get("RoomLocationRegExp");
if (roomLocationRegExp === null) {
Logger.log("Generating Room Location RegExp");
var roomLocationTable = getRoomLocationTable();
var matches = [];
roomLocationTable.forEach(function pushPotentialMatches(roomLocation) {
matches.push(roomLocation.WebDescription);
matches.push(roomLocation.Description);
matches.push(roomLocation.Building_Code);
});
roomLocationRegExp = "(?:\\b)(" + matches.join("|") + ")(?:\\b)";
cache.put("RoomLocationRegExp", roomLocationRegExp, CACHE_TIME);
} else {
Logger.log("Using cached Room Location RegExp");
return new RegExp(roomLocationRegExp, "gi");
}
return new RegExp(roomLocationRegExp, "gi");
}