Created
December 1, 2015 15:25
-
-
Save jptrsn/e5a61108c8e9789ee5c1 to your computer and use it in GitHub Desktop.
This file contains 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
/** | |
// Twitter Translator for the GEG Montreal | |
// Written by James Petersen, some time during 2014. | |
// | |
// Website: http://www.opensourceteacher.ca | |
// | |
// Code built on top of the | |
// T W I T T E R A R C H I V E R | |
// - - - - - - - - - - - - - - - | |
// | |
// Originally written by Amit Agarwal www.ctrlq.org | |
// Tutorial : http://www.labnol.org/?p=6505 | |
// YouTube : https://www.youtube.com/watch?v=sjRTSkBHnyo | |
// | |
// Please note that changes to oAuthConfig mean that this code will break | |
// in the very near future if it hasn't already. | |
// | |
*/ | |
var CONSUMER_KEY = "_________________________"; | |
var CONSUMER_SECRET = "____________________________________________________"; | |
var LANG_API_KEY = "______________________" | |
function onOpen(e) { | |
var ss = SpreadsheetApp.getActiveSpreadsheet(); | |
var menuEntries = []; | |
menuEntries.push({name: 'Check for new Tweets', functionName: 'saveTweets'}); | |
menuEntries.push({name: 'Authorize', functionName: 'authorizeTwitter_'}); | |
menuEntries.push({name: 'Reset', functionName: 'Initialize'}); | |
menuEntries.push({name: 'Stop checking automatically', functionName: 'Stop'}); | |
ss.addMenu('Twitter', menuEntries ); | |
} | |
function encodeString (q) { | |
var str = q.replace(/\(/g,'{') | |
.replace(/\)/g,'}') | |
.replace(/\[/g,'{') | |
.replace(/\]/g,'}') | |
.replace(/\!/g, '|') | |
.replace(/\*/g, 'x') | |
.replace(/\'/g, ''); | |
return encodeURIComponent(str); | |
} | |
function oAuth_() { | |
var oauthConfig = UrlFetchApp.addOAuthService("twitter"); | |
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token"); | |
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token"); | |
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize"); | |
oauthConfig.setConsumerKey(CONSUMER_KEY); | |
oauthConfig.setConsumerSecret(CONSUMER_SECRET); | |
} | |
function logTweet_(sheet, tweet) { | |
var log = []; | |
var data = []; | |
log.push(new Date(tweet.created_at)); | |
log.push(tweet.user.screen_name); | |
data[0] = tweet.user.screen_name; | |
log.push(tweet.user.followers_count); | |
log.push(tweet.user.friends_count); | |
log.push(tweet.retweet_count); | |
log.push(tweet.favorite_count); | |
data[1] = tweet.text.replace(/\r\n|\n|\r/g, " ").replace("<", "<").replace(">", ">"); | |
log.push(data[1]); | |
data[2] = detectLang(data[1]); | |
data[3] = (tweet.id_str); | |
sheet.insertRowBefore(3).getRange(3,1, 1, sheet.getLastColumn()).setValues([log]); | |
return data; | |
} | |
function detectLang(text) { | |
var api = "http://ws.detectlanguage.com/0.2/detect?"; | |
api += "key=" + LANG_API_KEY; | |
api += "&q=" + encodeString(text); | |
var parsed = JSON.parse(UrlFetchApp.fetch(api).getContentText()); | |
var language = parsed.data.detections[0].language; | |
Logger.log(language); | |
return language; | |
} | |
function parseTweet(tweet) { | |
var startId = tweet.indexOf('@'); | |
var endId = tweet.indexOf(' ',startId); | |
if (startId > 0) { | |
tweet = tweet.substring(endId+1, tweet.length); | |
} | |
return tweet; | |
} | |
function translate(data) { | |
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1]; | |
var user = data[0]; | |
var origData = extractTags(data[1]); | |
var origText = origData[0]; | |
var origLang = data[2]; | |
var destLang; | |
if (origLang == 'en') { destLang = 'fr';} else { destLang = 'en';} | |
var translation = LanguageApp.translate(origText, origLang, destLang) + origData[1] + origData[2]; | |
var inReplyTo = data[3]; | |
var values = [[ origLang, | |
destLang, | |
translation, | |
user, | |
inReplyTo | |
]]; | |
var newRow = sheet2.insertRowBefore(2).getRange(2,1,1,5); | |
newRow.setValues(values); | |
var newTweet = [translation, user, inReplyTo]; | |
if (user != 'GEGMontreal') { | |
postTweet(newTweet); | |
} | |
} | |
function retrieveTweet() { | |
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1]; | |
var cell = sheet2.getRange(2,5).getValue(); | |
Browser.msgBox(cell); | |
} | |
function encodeString(q) { | |
var str = encodeURIComponent(q); | |
str = str.replace(/\'/g, "%27") | |
.replace(/\)/g,"%29") | |
.replace(/\[/g,"%5B") | |
.replace(/\]/g,"%5D") | |
.replace(/\!/g,"%21") | |
.replace(/\*/g,"%2A") | |
.replace(/\(/g,"%28"); | |
return str; | |
} | |
function authorize() { | |
authorizeTwitter_(); | |
} | |
function authorizeTwitter_() { | |
var authorized = PropertiesService.getScriptProperties().getProperty('authStatus'); | |
try { | |
var api = "https://api.twitter.com/1.1/application/rate_limit_status.json"; | |
var options = { | |
"method": "GET", | |
"oAuthServiceName":"twitter", | |
"oAuthUseToken":"always" | |
}; | |
oAuth_(); | |
var result = UrlFetchApp.fetch(api, options); | |
if ( result.getResponseCode() === 200 ) | |
PropertiesService.getScriptProperties().setProperty('authStatus',true); | |
return true; | |
} catch (e) { | |
writeError('error in authorizeTwitter'); | |
writeError(e); | |
Logger.log(e.toString()); | |
} | |
PropertiesService.getScriptProperties().setProperty('authStatus', false); | |
return false; | |
} | |
/* | |
function postTweet(tweet) { | |
//tweet = "Special (characters) aren't making me happy"; | |
try { | |
var payload = "status=" + encodeString(tweet); | |
var options = { | |
"method": "POST", | |
"oAuthServiceName": "twitter", | |
"oAuthUseToken": "always", | |
"escaping": false, | |
"payload": payload | |
}; | |
authorizeTwitter_(); | |
var url = "https://api.twitter.com/1.1/statuses/update.json"; | |
Logger.log('begin post'); | |
var request = UrlFetchApp.fetch(url, options); | |
Logger.log('post complete'); | |
} catch (e) { | |
writeError('Error in Post Tweet'); | |
writeError(e); | |
return; | |
} | |
return request.getResponseCode(); | |
} | |
*/ | |
function Initialize() { | |
try { | |
var tweet_text, sinceID, maxID, api, sheet, search; | |
var options, result, json, tweets, tweet, sender; | |
Stop(); | |
if ( authorizeTwitter_() ) { | |
sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; | |
search = sheet.getName(); | |
options = { | |
"method": "get", | |
"oAuthServiceName":"twitter", | |
"oAuthUseToken":"always" | |
}; | |
api = "https://api.twitter.com/1.1/search/tweets.json?count=50&include_entities=false"; | |
api += "&result_type=recent&q=" + encodeString_(search); | |
result = UrlFetchApp.fetch(api, options); | |
if (result.getResponseCode() == 200) { | |
json = Utilities.jsonParse(result.getContentText()); | |
if (json) { | |
tweets = json.statuses; | |
doProperty_("SINCEID", tweets[0].id_str); | |
doProperty_("MAXID", tweets[tweets.length-1].id_str); | |
for (var i=tweets.length-1; i>=0; i--) { | |
logTweet_(sheet, tweets[i]); | |
} | |
} | |
} | |
ScriptApp.newTrigger("saveTweets") | |
.timeBased().everyMinutes(1).create(); | |
} | |
} catch (e) { | |
writeError('error in intialize'); | |
writeError(e); | |
Logger.log(e.toString()); | |
} | |
} | |
function Clear() { | |
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; | |
sheet.getRange("A3:G" + (sheet.getLastRow() > 3 ? sheet.getLastRow() : "3")).clear(); | |
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1]; | |
sheet2.getRange(2,1,sheet2.getLastRow(),sheet2.getLastColumn()).clear(); | |
Stop(); | |
} | |
function postTweet(newTweet) { | |
//writeError(newTweet); | |
try { | |
var textAndTags = extractTags(newTweet[0]); | |
var status = ('TR: @' + newTweet[1] + ' ' + textAndTags[0]).substring(0,140 - (textAndTags[1].length + textAndTags[2].length)); | |
status += textAndTags[1] + textAndTags[2]; | |
var inReplyTo = newTweet[2]; | |
status = encodeString(status); | |
var payload = "status=" + status + "&in_reply_to_status_id=" + inReplyTo; | |
var options = { | |
"method": "POST", | |
"oAuthServiceName": "twitter", | |
"oAuthUseToken": "always", | |
"escaping": false, | |
"payload": payload, | |
"muteHttpExceptions": true, | |
}; | |
authorizeTwitter_(); | |
var url = "https://api.twitter.com/1.1/statuses/update.json"; | |
Logger.log('begin post'); | |
var request = UrlFetchApp.fetch(url, options); | |
Logger.log('post complete'); | |
} catch (e) { | |
writeError('Error in Post Tweet'); | |
writeError(e); | |
} | |
} | |
function saveTweets() { | |
var tweet_text, sinceID, maxID, api, sheet, search; | |
var options, result, json, tweets, tweet, sender; | |
try { | |
sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; | |
search = sheet.getName(); | |
sinceID = doProperty_("SINCEID"); | |
options = { | |
"method": "get", | |
"oAuthServiceName":"twitter", | |
"oAuthUseToken":"always" | |
}; | |
authorizeTwitter_() | |
api = "https://api.twitter.com/1.1/search/tweets.json?count=50&include_entities=false"; | |
api += "&result_type=recent&q=" + encodeString(search) + "&since_id=" + sinceID; | |
result = UrlFetchApp.fetch(api, options); | |
Logger.log(result.getResponseCode()); | |
if (result.getResponseCode() === 200) { | |
json = JSON.parse(result.getContentText()); | |
if (json) { | |
tweets = json.statuses; | |
if (tweets.length) { | |
doProperty_("SINCEID", tweets[0].id_str); | |
} | |
for (var i=tweets.length-1; i>=0; i--) { | |
var user = logTweet_(sheet, tweets[i]); | |
var text = tweets[i].text; | |
var lang = detectLang(text); | |
translate(user); | |
} | |
} | |
} else { | |
if (result.getResponseCode() === 503 || result.getResponseCode() === 504) { | |
Utilities.sleep(2000); | |
result = UrlFetchApp.fetch(api, options); | |
} | |
} | |
} | |
catch (e) { | |
writeError('error in saveTweets'); | |
writeError(e); | |
Logger.log(e.toString()); | |
} | |
} | |
function writeError(e) { | |
var sheet3 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[2]; | |
var range = sheet3.getRange(2,1,sheet3.getLastRow(),sheet3.getLastColumn()); | |
range.setBackgroundRGB(200,200,200); | |
var row = sheet3.insertRowAfter(1); | |
var now = new Date(); | |
sheet3.getRange(2,1).setValue(now); | |
if (e != null) { | |
sheet3.getRange(2,2).setValue(e.toString()); | |
} | |
} | |
function doProperty_(key, value) { | |
var properties = PropertiesService.getScriptProperties(); | |
if (value) { | |
properties.setProperty(key, value); | |
} else { | |
return properties.getProperty(key) || ""; | |
} | |
} | |
function Stop() { | |
var triggers = ScriptApp.getScriptTriggers(); | |
for(var i=0; i < triggers.length; i++) { | |
ScriptApp.deleteTrigger(triggers[i]); | |
} | |
doProperty_("SINCEID", ""); | |
doProperty_("MAXID", ""); | |
} | |
function extractTags(text) { | |
//text = "This is a test tweet with a @user"; | |
var hashtags = []; | |
var hashString = ''; | |
var users = []; | |
var userString = ''; | |
var words = text.split(' '); | |
var newText = ''; | |
for (var i in words) { | |
if (words[i][0] == '#') { | |
hashtags.push(words[i]); | |
} | |
if (words[i][0] == '@' || words[i][1] == '@') { | |
users.push(words[i]); | |
} | |
if (words[i][0] != '#' && words[i][0] != '@') { | |
newText += words[i] + ' '; | |
} | |
} | |
if (hashtags.length > 0) { | |
hashString += ' '; | |
for (i in hashtags) { | |
hashString += hashtags[i]; | |
if (hashtags.length > 1 && i != hashtags.length - 1) { | |
hashString += ' '; | |
} | |
} | |
} | |
if (users.length > 0) { | |
userString += ' '; | |
for (i in users) { | |
userString += users[i]; | |
if (users.length > 1 && i != users.length - 1) { | |
userString += ' '; | |
} | |
} | |
} | |
var values = [newText, hashString, userString]; | |
return values; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment