// Get a Wordnik API key: http://developer.wordnik.com/ var WORDNIK_API_KEY = "XXXX"; // Get a Twitter app key: https://apps.twitter.com/ var TWITTER_CONSUMER_KEY = "XXXX"; var TWITTER_CONSUMER_SECRET = "XXXX"; function Start() { // Delete exiting triggers, if any var triggers = ScriptApp.getProjectTriggers(); for (var i = 0; i < triggers.length; i++) { ScriptApp.deleteTrigger(triggers[i]); } // Setup trigger to post a Tweet every hour. ScriptApp.newTrigger("UberBut") .timeBased() .everyHours(1) .create(); } // From https://github.com/googlesamples/apps-script-oauth1 function GetTwitterService() { // Create a new service with the given name. The name will be used when // persisting the authorized token, so ensure it is unique within the // scope of the property store. return OAuth1.createService('twitter') // Set the endpoint URLs. .setAccessTokenUrl('https://api.twitter.com/oauth/access_token') .setRequestTokenUrl('https://api.twitter.com/oauth/request_token') .setAuthorizationUrl('https://api.twitter.com/oauth/authorize') // Set the consumer key and secret. .setConsumerKey(TWITTER_CONSUMER_KEY) .setConsumerSecret(TWITTER_CONSUMER_SECRET) // Set the name of the callback function in the script referenced // above that should be invoked to complete the OAuth flow. .setCallbackFunction('AuthCallback') // Set the property store where authorized tokens should be persisted. .setPropertyStore(PropertiesService.getScriptProperties()); } function TwitterFetch(url) { var twit = GetTwitterService(); if (!twit.hasAccess()) { var authorization_url = twitterService.authorize(); Logger.log("No Twitter access -- go to " + authorization_url + " to authorize"); return; } return twit.fetch(url); } function TwitterPost(url, payload) { var twit = GetTwitterService(); if (!twit.hasAccess()) { var authorization_url = twitterService.authorize(); Logger.log("No Twitter access -- go to " + authorization_url + " to authorize"); return; } return twit.fetch(url, { "method" : "post", "payload" : payload }); } function AuthCallback(request) { var twit = GetTwitterService(); if (twit.handleCallback(request)) { Logger.log('Success!'); } else { Logger.log('Denied.'); } } // Makes an HTTP request to the Wordnik API for a random word, given the part of speech // Modified from: https://gist.github.com/scazon/a427f58974b6e7c80827 function RandomWord(part_of_speech){ var content = UrlFetchApp.fetch( "http://api.wordnik.com/v4/words.json/randomWord?includePartOfSpeech=" + part_of_speech + "&minCorpusCount=8000&maxCorpusCount=-1&minDictionaryCount=8&" + "maxDictionaryCount=-1&minLength=4&maxLength=-1&api_key=" + WORDNIK_API_KEY); var word = JSON.parse(content)["word"]; //Logger.log("Got random word: " + word); return word; } function WordIsPartOfSpeech(word, part_of_speech){ var content = UrlFetchApp.fetch( "http://api.wordnik.com/v4/word.json/" + word + "/definitions?limit=1&partOfSpeech=" + part_of_speech + "&api_key=" + WORDNIK_API_KEY); var defs = JSON.parse(content); return defs.length; } // For pluralizing: https://code.google.com/p/inflection-js/ function Pluralize(noun) { return noun.pluralize(); } function StandaloneTweet() { var text = ""; while (text == "") { var noun = RandomWord("noun"); text = Pluralize(noun); if (text == noun) { text = ""; } } // An adjective 50% of the time if (Math.random() < 0.5) { var adjective = RandomWord("adjective"); if (adjective != "") { text = adjective + " " + text; } } return "Like Uber, but for " + text + "."; } function ReplyTweet() { var props = PropertiesService.getScriptProperties(); var max_id = props.getProperty("MAX_TWITTER_ID"); if (max_id && max_id > 0) { max_id = "&since_id=" + max_id; } else { max_id = ""; } var url = "https://api.twitter.com/1.1/search/tweets.json?q=" + encodeURIComponent("-from:uberbut @uberbut") + "&count=50" + max_id; Logger.log(url); response = TwitterFetch(url); if (response.getResponseCode() !== 200) { Logger.log("Got response code: " + response.getResponseCode()); return StandaloneTweet(); } data = JSON.parse(response.getContentText()); if (!data) { Logger.log("Can't parse json from '" + data + "'"); return StandaloneTweet(); } var tweets = data.statuses; for (var t in tweets.reverse()) { tweet = tweets[t] props.setProperty("MAX_TWITTER_ID", tweet.id_str); if (!tweet.possibly_sensitive && !tweet.retweeted_status) { // For each word, in reverse order, try to find a noun. var words = tweet.text.split(" ").reverse().filter(function(w) { // If the word has any non-alphabetic characters or is less than 6 letters long, skip it. return (w.length >= 6 && w.match('^[a-zA-Z]*$')); }); for (var w = 0; w < words.length; w++) { word = words[w]; if (WordIsPartOfSpeech(word, "noun")) { var choice = Pluralize(word); // Check to see if the previous word is an adjective. if ((w < words.length - 1) && WordIsPartOfSpeech(words[w+1], "adjective")) { choice = words[w+1] + " " + choice; } // Done! var url = 'https://twitter.com/' + tweet.user.screen_name + '/status/' + tweet.id_str; var text = "Like Uber, but for " + choice + ".\n" + url; Logger.log(text); return text; } } } } return StandaloneTweet(); } function UberBut() { try { var text = ReplyTweet(); Logger.log("Tweeting: '" + text + "'"); // Post to twitter: TwitterPost("https://api.twitter.com/1.1/statuses/update.json", {'status': text}) } catch (f) { Logger.log("Error: " + f); } }