diff --git a/README.md b/README.md index 0c5f47e..b759a7d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # community-map-google-scripts -Script to support Google spreadsheets that use community-generated information to map important points, such as https://github.com/jdalt/twin-cities-aid-distribution-locations/. +Scripts to support Google spreadsheets that use community-generated information to map important points, such as https://github.com/jdalt/twin-cities-aid-distribution-locations/. -Script currently has two functions: +`script.gs` currently has two functions: - Inserts a timestamp in a desired column when specific columns of your spreadsheet are edited - Inserts a latitude and longitude in desired columns when an address column in your spreadsheet is updated. + +`receiveMessages.gs`: +- Script to receive text messages from Twilio number into a Google Sheet + +`sendMessages.gs`: +- Idea for how to send text responses to individual phone numbers +- Idea for how to send text reminders to multiple phone numbers \ No newline at end of file diff --git a/receiveMessages.gs b/receiveMessages.gs new file mode 100644 index 0000000..c22146d --- /dev/null +++ b/receiveMessages.gs @@ -0,0 +1,75 @@ +function getMediaAssets(messageSid, accountSid, options) { + var reqUrl = "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages/" + messageSid + "/Media.json"; + var response = UrlFetchApp.fetch(reqUrl,options); + var dataAll = JSON.parse(response.getContentText()); + Logger.log("Media List: \n"); + Logger.log(dataAll.media_list); + var assets = dataAll.media_list; + var mediaLinks = []; + for (var k = 0; k < assets.length; k++) { + mediaLinks.push("https://api.twilio.com" + assets[k].uri.slice(0, assets[k].uri.length - 5)); + } + Logger.log("\n Media links: \n" + mediaLinks) + return mediaLinks; +} + +function myFunction() { + const ACCOUNT_SID = "XXXXXXXXXXXXXXXX"; + const ACCOUNT_TOKEN = "XXXXXXXXXXXXXXXX"; + const toPhoneNumber = "+1XXXXXXXXXX"; + const numberToRetrieve = 200; + const hoursOffset = 0; + + var options = { + "method" : "get" + }; + options.headers = { + "Authorization" : "Basic " + Utilities.base64Encode(ACCOUNT_SID + ":" + ACCOUNT_TOKEN) + }; + var url="https://api.twilio.com/2010-04-01/Accounts/" + ACCOUNT_SID + "/Messages.json?To=" + toPhoneNumber + "&PageSize=" + numberToRetrieve; + var response = UrlFetchApp.fetch(url,options); + // ------------------------------------------- + // Parse the JSON data and put it into the spreadsheet's active page. + // Documentation: https://www.twilio.com/docs/api/rest/response + var theSheet = SpreadsheetApp.getActive().getSheetByName('Receive'); + var theRow = 3; + var startColumn = 2; + var dataAll = JSON.parse(response.getContentText()); + for (i = 0; i < dataAll.messages.length; i++) { + theColumn = startColumn; + // ------------------------------------- + // Date and Time + rowDate = dataAll.messages[i].date_sent; + var theDate = new Date (rowDate); + if(isNaN(theDate.valueOf())) { + theDate = 'Not a valid date-time'; + theColumn++; + theColumn++; + } + else { + theDate.setHours(theDate.getHours()+hoursOffset); + theSheet.getRange(theRow, theColumn).setValue(theDate); + theColumn++; + theSheet.getRange(theRow, theColumn).setValue(theDate); + theColumn++; + } + // ------------------------------------- + theSheet.getRange(theRow, theColumn).setValue(dataAll.messages[i].to); + theColumn++; + theSheet.getRange(theRow, theColumn).setValue(dataAll.messages[i].from); + theColumn++; + theSheet.getRange(theRow, theColumn).setValue(dataAll.messages[i].body); + theColumn++; + /** Check for media assets */ + if (dataAll.messages[i].num_media > 0) { + Logger.log("message with media assets: \n\n") + Logger.log(dataAll.messages[i]) + var mediaLinks = getMediaAssets(dataAll.messages[i].sid, ACCOUNT_SID, options); + for (let j = 0; j < mediaLinks.length; j++) { + theSheet.getRange(theRow, theColumn).setValue(mediaLinks[j]); + theColumn++; + } + } + theRow++; + } +} \ No newline at end of file diff --git a/script.js b/script.gs similarity index 100% rename from script.js rename to script.gs diff --git a/sendMessages.gs b/sendMessages.gs new file mode 100644 index 0000000..3a573e0 --- /dev/null +++ b/sendMessages.gs @@ -0,0 +1,90 @@ +function sendSms(to, body) { + const ACCOUNT_SID = "XXXXXXXXXXXXXXXX"; + const ACCOUNT_TOKEN = "XXXXXXXXXXXXXXXX"; + const fromPhoneNumber = "+1XXXXXXXXXX"; + + var messages_url = "https://api.twilio.com/2010-04-01/Accounts/" + ACCOUNT_SID + "/Messages.json"; + + var payload = { + "To": to, + "Body" : body, + "From" : fromPhoneNumber + }; + + var options = { + "method" : "post", + "payload" : payload + }; + + options.headers = { + "Authorization" : "Basic " + Utilities.base64Encode(ACCOUNT_SID +":"+ ACCOUNT_TOKEN) + }; + + UrlFetchApp.fetch(messages_url, options); + } + + /* + Spreadsheet setup idea: + Phone Number | Message Body | Status | + xxx-xxx-xxxx | msg here | sent (or error) | + */ + function sendResponses() { + var sheet = SpreadsheetApp.getActive().getSheetByName('SendResponses'); + var startRow = 2; // start after column title row + var numRows = sheet.getLastRow() - 1; // subtract column title row from total row count + var dataRange = sheet.getRange(startRow, 1, numRows, 3) // row, column, numRows, numColumns + var data = dataRange.getValues(); + + for (i in data) { + var row = data[i]; + var msgSentStatus = row[2] + if (msgSentStatus == "sent") { + continue; // skip sending this message. It was already sent + } else { + try { + response_data = sendSms(row[0], row[1]); + status = "sent"; + } catch(err) { + Logger.log(err); + status = "error"; + } + sheet.getRange(startRow + Number(i), 3).setValue(status); + } + } + } + + function flatten(nestedArr){ + return [].concat.apply([], nestedArr); + } + + /* + Spreadsheet setup idea: + Send to | Reminder info | Status | + xxx-xxx-xxxx | msg to send | sent (or error) | + xxx-xxx-xxxx | ------------------------------------------- + xxx-xxx-xxxx | ------------------------------------------- + ... | ------------------------------------------- + */ + + function sendReminders() { + var sheet = SpreadsheetApp.getActive().getSheetByName('SendReminders'); + var reminderMessage = sheet.getRange("B2").getValue(); // get the current reminder message to be sent + + var numbersCol = sheet.getRange("A2:A").getValues(); + numbersCol = numbersCol.filter(String); + var lenNums = numbersCol.length; // get length of a + var sendToNumbers = flatten(sheet.getRange("A2:A" + (lenNums + 1)).getValues()); // arr of all #s to send reminder to + + for (i in sendToNumbers) { + try { + response_data = sendSms(sendToNumbers[i], reminderMessage); + status = "sent" + } catch(err) { + Logger.log(err); + status = "error"; + } + } + // @todo: some way to denote whether the reminder was sent or errored when trying to send to + // each number in the list. @todo: move current message down to previous message category in + // spreadsheet + } \ No newline at end of file