├── README.md ├── exmples ├── cron.gs └── hello.gs └── parse.gs /README.md: -------------------------------------------------------------------------------- 1 | Helps your Spreadsheets interact with Parse.com. 2 | 3 | ## Quickstart 4 | 5 | The Google Apps Script gallery is being finnicky, so for now, this is the easiest way to get started: 6 | 7 | 1. Copy `parse.gs`. 8 | 2. Create a new Google Spreadsheet. 9 | 3. Create a new sheet and make sure it is first sheet (closes to left side of the screen). 10 | 4. Enter your Parse Application ID in Cell B:1 and your Parse REST API Key in Cell B:2. 11 | 5. Tools -> Script Editor 12 | 6. Paste 13 | 7. See `examples.gs` or below: 14 | 15 | ```javascript 16 | parseInsert("GameScore",{ 17 | "score" : 1000, 18 | "playerName" : "Sean Plott" 19 | }); 20 | 21 | results = parseQuery("GameScore", { 22 | 'playerName' : 'Sean Plott' 23 | }); 24 | 25 | var objectId = results[0].objectId; 26 | parseUpdate("GameScore", objectId, { 27 | "playerName" : "Sean Plott III" 28 | }); 29 | 30 | parseFindOrCreateByAttribute("GameScore",{ 31 | "playerName" : "Sean Plott" 32 | }); 33 | ``` 34 | 35 | ## Cron 36 | 37 | Here's a neat trick to run cron tasks for free: 38 | 39 | 1. Open the Google Apps Script editor. 40 | 2. Define function that you want to run in the cron task. 41 | 3. Resources -> Current Script Triggers 42 | 4. Select the function from step two, and customize to your needs. 43 | 44 | ### Cron example 45 | 46 | Let's say you're running a script that will tally the score for a multiplayer game. You have a class called `Game` with the boolean field `scored`, the integer fields `homeScore` and `awayScore`, and a string field `winner`. 47 | 48 | Let's load some sample data: 49 | 50 | ```javascript 51 | function setupData() { 52 | parseInsert("Game", { 53 | "scored" : true, 54 | "homeScore" : 55, 55 | "awayScore" : 44, 56 | "winner" : "home" 57 | }); 58 | parseInsert("Game", { 59 | "scored" : false, 60 | "homeScore" : 99, 61 | "awayScore" : 59 62 | }); 63 | parseInsert("Game", { 64 | "scored" : false, 65 | "homeScore" : 46, 66 | "awayScore" : 12, 67 | }); 68 | parseInsert("Game", { 69 | "scored" : false, 70 | "homeScore" : 66, 71 | "awayScore" : 100, 72 | }); 73 | } 74 | ``` 75 | 76 | And here's the scoring script: 77 | 78 | ```javascript 79 | function scoreGames() { 80 | var games = parseQuery("Game", { 81 | "scored" : false 82 | }); 83 | for (var i = 0; i < games.length; i++) { 84 | var objectId = games[i].objectId; 85 | var winner; 86 | if (games[i].homeScore > games[i].awayScore) { // home team wins 87 | winner = "home"; 88 | } else if (games[i].homeScore < games[i].awayScore) { //away team wins 89 | winner = "away"; 90 | } else { // tie 91 | winner = "tie"; 92 | } 93 | parseUpdate("Game", objectId, { 94 | "scored" : true, 95 | "winner" : winner 96 | }); 97 | } 98 | } 99 | ``` 100 | 101 | So to get this script to run every minute, just click "Resources" -> "Current Script Triggers", then select "scoreGames()" from the function list and set it to run every minute. -------------------------------------------------------------------------------- /exmples/cron.gs: -------------------------------------------------------------------------------- 1 | function setupData() { 2 | parseInsert("Game", { 3 | "scored" : true, 4 | "homeScore" : 55, 5 | "awayScore" : 44, 6 | "winner" : "home" 7 | }); 8 | parseInsert("Game", { 9 | "scored" : false, 10 | "homeScore" : 99, 11 | "awayScore" : 59 12 | }); 13 | parseInsert("Game", { 14 | "scored" : false, 15 | "homeScore" : 46, 16 | "awayScore" : 12, 17 | }); 18 | parseInsert("Game", { 19 | "scored" : false, 20 | "homeScore" : 66, 21 | "awayScore" : 100, 22 | }); 23 | } 24 | 25 | function scoreGames() { 26 | var games = parseQuery("Game", { 27 | "scored" : false 28 | }); 29 | for (var i = 0; i < games.length; i++) { 30 | var objectId = games[i].objectId; 31 | var winner; 32 | if (games[i].homeScore > games[i].awayScore) { // home team wins 33 | winner = "home"; 34 | } else if (games[i].homeScore < games[i].awayScore) { //away team wins 35 | winner = "away"; 36 | } else { // tie 37 | winner = "tie"; 38 | } 39 | parseUpdate("Game", objectId, { 40 | "scored" : true, 41 | "winner" : winner 42 | }); 43 | } 44 | } -------------------------------------------------------------------------------- /exmples/hello.gs: -------------------------------------------------------------------------------- 1 | function postToParse() { 2 | parseInsert("GameScore",{ 3 | "score" : 1000, 4 | "playerName" : "Sean Plott" 5 | }); 6 | }; 7 | 8 | function queryParse() { 9 | var results = parseQuery("GameScore", { 10 | 'playerName' : 'Sean Plott' 11 | }); 12 | 13 | Logger.log(results[0].playerName); 14 | } 15 | 16 | function updateParse() { 17 | var results = parseQuery("GameScore", { 18 | 'playerName' : 'Sean Plott' 19 | }); 20 | 21 | var objectId = results[0].objectId; 22 | parseUpdate("GameScore", objectId, { 23 | "playerName" : "Sean Plott III" 24 | }); 25 | } 26 | 27 | /** 28 | * Adds a custom menu to the active spreadsheet, containing a single menu item 29 | * for invoking the readRows() function specified above. 30 | * The onOpen() function, when defined, is automatically invoked whenever the 31 | * spreadsheet is opened. 32 | * For more information on using the Spreadsheet API, see 33 | * https://developers.google.com/apps-script/service_spreadsheet 34 | */ 35 | function onOpen() { 36 | var sheet = SpreadsheetApp.getActiveSpreadsheet(); 37 | var entries = [{ 38 | name : "Read Data", 39 | functionName : "readRows" 40 | }]; 41 | sheet.addMenu("Script Center Menu", entries); 42 | }; 43 | -------------------------------------------------------------------------------- /parse.gs: -------------------------------------------------------------------------------- 1 | // Returns an object with the given attribute key/value pair 2 | // If the object exists with that attribute, it merely finds and returns it. 3 | // If the object does not exist, it creates and returns it. 4 | // Example: 5 | // obj = parseFindOrCreateByAttribute("GameScore", { 6 | // "playerName" : "Sean Plott" 7 | // }); 8 | // If multiple results are returned from the parseQuery, an array of the results is returned here. 9 | // If one result is returned from the parseQuery, just that result is returned here. 10 | function parseFindOrCreateByAttribute(className, attributeNameAndValue) { 11 | var obj = parseQuery(className, attributeNameAndValue); 12 | var result; 13 | if (obj == false) { 14 | result = parseInsert(className, attributeNameAndValue); 15 | } 16 | else { 17 | if (obj.length > 1) { result = obj; } 18 | else { result = obj[0]; } 19 | } 20 | 21 | return result; 22 | } 23 | 24 | // Query Parse to get results from server 25 | // Example: 26 | // var results = parseQuery("GameScore", { 27 | // "playerName" : "Sean Plott" 28 | // }); 29 | // results[0].playerName #=> Sean Plott 30 | function parseQuery(className, params) { 31 | var encoded_params = encodeURIComponent(Utilities.jsonStringify(params)); 32 | var url = "https://api.parse.com/1/classes/" + className + "?where=" + encoded_params; 33 | var options = { 34 | "method" : "get", 35 | "headers" : makeHeaders(), 36 | }; 37 | 38 | var resp = UrlFetchApp.fetch(url, options); 39 | var result; 40 | if (resp.getResponseCode() != 200) { 41 | Logger.log(resp.getContentText()); 42 | result = false; 43 | } else { 44 | result = Utilities.jsonParse(resp.getContentText())["results"]; 45 | } 46 | 47 | return result; 48 | } 49 | 50 | // Update an existing Parse object 51 | // Example: 52 | // parseUpdate("GameScore", "6K0FnTtGZC", { 53 | // "playerName" : "Sean Plott Jr." 54 | //}); 55 | function parseUpdate(className, objectId, params) { 56 | var url = "https://api.parse.com/1/classes/" + className + "/" + objectId; 57 | var payload = Utilities.jsonStringify(params); 58 | var options = { 59 | "method" : "put", 60 | "payload" : payload, 61 | "headers" : makeHeaders(), 62 | "contentType" : "application/json" 63 | }; 64 | 65 | var resp = UrlFetchApp.fetch(url, options); 66 | var result; 67 | if (resp.getResponseCode() != 200) { 68 | Logger.log(resp.getContentText()); 69 | result = false; 70 | } else { 71 | result = Utilities.jsonParse(resp.getContentText()); 72 | } 73 | 74 | return result; 75 | } 76 | 77 | // Sent POST request to insert into the database 78 | // Example: 79 | // parseInsert("GameScore", { 80 | // "playerName" : "Sean Plott", 81 | // "score" : "1337" 82 | // }); 83 | function parseInsert(className, params) { 84 | var url = "https://api.parse.com/1/classes/" + className; 85 | var payload = Utilities.jsonStringify(params); 86 | var options = { 87 | "method" : "post", 88 | "payload" : payload, 89 | "headers" : makeHeaders(), 90 | "contentType" : "application/json" 91 | }; 92 | 93 | var resp = UrlFetchApp.fetch(url, options); 94 | var result; 95 | if (resp.getResponseCode() != 200) { 96 | Logger.log(resp.getContentText()); 97 | result = false; 98 | } else { 99 | result = Utilities.jsonParse(resp.getContentText()); 100 | } 101 | 102 | return result; 103 | } 104 | 105 | 106 | // Looks for the first Sheet in a Speadsheet 107 | // and gets the first two rows of the 2nd column 108 | function getAPIKeys() { 109 | var ss = SpreadsheetApp.getActiveSpreadsheet(); 110 | SpreadsheetApp.setActiveSheet(ss.getSheets()[0]); 111 | var sheet = SpreadsheetApp.getActiveSheet(); 112 | var rows = getRows(sheet); 113 | keys = { 114 | "application_id" : rows[0][1], 115 | "rest_api_key" : rows[1][1] 116 | }; 117 | 118 | return keys; 119 | } 120 | 121 | // calls getAPIKeys() and assembles into HTTP headers 122 | function makeHeaders() { 123 | var keys = getAPIKeys(); 124 | var headers = { 125 | "X-Parse-Application-Id": keys["application_id"], 126 | "X-Parse-REST-API-Key": keys["rest_api_key"] 127 | }; 128 | 129 | return headers; 130 | } --------------------------------------------------------------------------------