Last active
June 17, 2018 14:23
-
-
Save kshwetabh/feff379200c61151c369 to your computer and use it in GitHub Desktop.
Xoom Exchange Rate Trend - Draws a graph indicating the exchange rate trend of Xoom.com Online Money Transfer Website.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Services combined together: | |
* ~Yahoo Pipes~, Gmail, Google App Script, GDrive, Google Charts | |
* | |
* This is a Google App Script Web App that draws a Column Graph highlighting the current and historical exchange rate trend of | |
* Xoom Money Transfer. Created this simple app to keep an eye on the $ to Rupee up/down trend. | |
* Has a related excel sheet also. | |
* | |
* Output (snapshot): https://plus.google.com/photos/108969069990423509081/albums/6115274347350257297?authkey=CKOFv9-t77O4kAE | |
* | |
* How to (re)use this script: | |
* - Go to Google Drive (https:\\drive.google.com) | |
* - Create a new Spreadsheet | |
* - Go to Tools -> Script Editor menu | |
* - Copy and paste this entire script in the script file (eg. in Code.gs file) | |
* | |
* One time Configuration: | |
* - You need to replace the dummy SPREADSHEETID with your newly created SpreadSheetID | |
* Run getId() method in Google App Script and check logs to get the SpreadSheetID | |
* - You will need to grant permission to Google Drive (for spreadsheet update), external requests (to use ~yahoo pipes URL~ Google Apps Script) and Gmail (to pull old historical XOOM data from gmail). | |
* | |
* Optionally configure the trigger in the App script to run the updateDailyXchangeDataToSpreadsheet() method everyday (for eg at 4-5 PM everyday) | |
* | |
* You can specify the number of days of data you want to see in the chart by passing p=value as query param in the Web App link | |
* https://script.google.com/macros/s/AKfycbwUeHXu5p4WkHZg4oKsHx6BlN8OIHHIu2xxxx-xxxxx-xxxxx/dev?p=25 | |
* | |
*/ | |
/** | |
Has a related excel sheet also. | |
*/ | |
var DEFAULTNOOFDAYS = 25, //if no parameter specified in WebApp URL | |
QUERIEDNOOFDAYS = 0, | |
SPREADSHEETID = 'YOUR_SPREADSHEET_ID_GOES_HERE'; | |
/* | |
* Fetch daily xoom rates and update in a spreadsheet. Use web service to then respond back a Column Chart to highlight the trend. | |
*/ | |
function updateDailyXchangeDataToSpreadsheet() { | |
var sheet = SpreadsheetApp.getActiveSheet(), | |
lastRow = sheet.getLastRow(); //need to append data at the end | |
var rate = getDailyXchangeRateFromXoom(), | |
date = new Date(); | |
sheet.getRange(lastRow+1,1).setValue(Utilities.formatDate(date, "GMT", "MM/dd/yyyy")); | |
sheet.getRange(lastRow+1,2).setValue(rate); | |
} | |
/* | |
* Fetch today's exchange rate from Xoom's website | |
*/ | |
function getDailyXchangeRateFromXoom() { | |
var html = UrlFetchApp.fetch('https://www.xoom.com/india/fees-fx').getContentText(); | |
var doc = XmlService.parse(html); | |
var html = doc.getRootElement(); | |
var menu = getElementsByClassName(html, 'cp-grn-highlight')[0]; //Exchange rate usually in the first child | |
var output = XmlService.getPrettyFormat().format(menu); | |
return menu.getText().replace('1 USD = ', '').replace(' INR', '').trim().substring(0,5); | |
} | |
/* | |
* Locates an HTML Dom element by ClassName | |
*/ | |
function getElementsByClassName(element, classToFind) { | |
var data = []; | |
var descendants = element.getDescendants(); | |
descendants.push(element); | |
for(i in descendants) { | |
var elt = descendants[i].asElement(); | |
if(elt != null) { | |
var classes = elt.getAttribute('class'); | |
if(classes != null) { | |
classes = classes.getValue(); | |
if(classes == classToFind) data.push(elt); | |
else { | |
classes = classes.split(' '); | |
for(j in classes) { | |
if(classes[j] == classToFind) { | |
data.push(elt); | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
return data; | |
} | |
/** | |
* To access the spreadsheet data from a web app you must create/save the sspreadsheet id. | |
* This method must be run manually once by the user for the webapp to get data from the spreadsheet properly | |
*/ | |
function getId() { | |
var ui = SpreadsheetApp.getUi(), | |
id = SpreadsheetApp.getActiveSpreadsheet().getId(); | |
Logger.log(id); | |
SpreadsheetApp.getUi().alert(id); | |
} | |
function getXchangeDataFromSpreadSheet(noOfDays) { | |
var sheet = SpreadsheetApp.openById(SPREADSHEETID), | |
data = sheet.getDataRange().getValues().reverse(), | |
arrExchngRates = []; | |
//code here looks weird. Little explanation is needed | |
//if noOfDays passed in query parameter is valid and less than no of records in spreadsheet, use it, | |
//otherwise use the DEFAULTNOOFDAYS | |
if (noOfDays === null || noOfDays === '' || noOfDays < 1 ) { | |
noOfDays = DEFAULTNOOFDAYS; //if noofdays invalid in query string, set it to default value | |
} | |
var len = noOfDays > data.length ? DEFAULTNOOFDAYS : noOfDays; //noOfDays > DEFAULTNOOFDAYS > data.length | |
QUERIEDNOOFDAYS = len; //to be displayed on chart title | |
for (var i = 0; i < len; i++) { | |
arrExchngRates.push([getDateMonth(data[i][0]), data[i][1]]); | |
} | |
return arrExchngRates; | |
} | |
/** | |
* Respond back with the chart when the WebApp URL is invoked | |
*/ | |
function doGet(e) { | |
//if URL has today parameter, return today's rate instead of graph | |
if (e.parameters["today"]) { | |
return ContentService.createTextOutput(JSON.stringify({rate:getDailyXchangeRateFromXoom()})).setMimeType(ContentService.MimeType.JSON); | |
} | |
var noOfDays = e.parameters["p"]; | |
Logger.log(noOfDays); //input param from query string p=20 | |
var dataTable = Charts.newDataTable() | |
.addColumn(Charts.ColumnType.STRING, "Dates") | |
.addColumn(Charts.ColumnType.NUMBER, "Rates"); | |
var arrExchngRates = getXchangeDataFromSpreadSheet(noOfDays).reverse(); | |
//Logger.log(arrExchngRates); | |
for (var i = 0; i < arrExchngRates.length; i++) { | |
dataTable.addRow(arrExchngRates[i]); | |
} | |
dataTable.build(); | |
var textStyleBuilder = Charts.newTextStyle().setFontSize(10), | |
style = textStyleBuilder.build(); | |
// Build the chart. | |
var chart = Charts.newColumnChart() | |
.setDataTable(dataTable) | |
.setColors(["rgb(66, 133, 244)"]) | |
.setDimensions(950, 400) | |
.setXAxisTitle("Date") | |
.setYAxisTitle("Rupees") | |
.setTitle("Xoom Exchange Rate Trend ("+QUERIEDNOOFDAYS+" Days)") | |
.setLegendTextStyle(style) | |
.setXAxisTextStyle(style) | |
.build(); | |
// Add our chart to the UI and return it so that we can publish | |
// this UI as a service and access it via a URL. | |
var ui = UiApp.createApplication(); | |
ui.add(chart); | |
return ui; | |
} | |
function getDateMonth(dateString) { | |
var dateArray = dateString.split("/"); | |
var year = dateArray[2]; | |
var day = dateArray[1]; | |
var month = dateArray[0]; | |
return day + "/" + month; | |
} | |
/** | |
* Run this method once to pull all historical Xoom Rates from your Gmail Inbox into the spreadsheet | |
*/ | |
function updateOldXchangeDataToSpreadsheet() { | |
var sheet = SpreadsheetApp.getActiveSheet(), | |
lastRow = sheet.getLastRow(); | |
// Which Gmail Label should be searched? you can specify Inbox, Sent, etc. | |
// Not mandatory, but specifying a subset (like search only within xoom filter) makes the response faster | |
var label = 'xoom'; //This is a label defined in Gmail to filter all mails with subject 'Today at Xoom' | |
// Retrieve all threads of the specified label | |
var threads = GmailApp.search("in:" + label); | |
threads = threads.reverse(); | |
for (var i = 0; i < threads.length; i++) { | |
var messages = threads[i].getMessages(); | |
for (var m = 0; m < messages.length; m++) { | |
var msg = messages[m], | |
xchngRate = msg.getSubject().substring(9,14); //Subject is in format: "Rupee at 61.30 Today at Xoom" | |
sheet.getRange(lastRow+1+i,1).setValue(msg.getDate()); | |
sheet.getRange(lastRow+1+i,2).setValue(xchngRate); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Under function getDailyXchangeRateFromXoom()
while html parsing at below line of code
var doc = XmlService.parse(html);
I am getting error "The entity name must immediately follow the '&' in the entity reference."
Looks like below fetch call is getting incomplete html
var html = UrlFetchApp.fetch('https://www.xoom.com/india/fees-fx').getContentText();
Below is the html