Categories
Code

Post an Update to Twitter with Google Apps Script

You can use Google Apps Script to post status updates (tweets) to Twitter. This example generates an OAuth 1.0a HMAC-SHA1 signature that is converted to base64 and is passed to the Twitter API via an HTTP POST request. You can use it to send tweets from Google Addons, Google Sheets and standalone web apps.


/* 
* Post to Twitter from Google Apps Script 
* Code by @rcknr
*/

function postTweet(message) {

  var method = "POST";
  var baseUrl = "https://api.twitter.com/1.1/statuses/update.json";
  var props = PropertiesService.getScriptProperties();

  var oauthParameters = {
    oauth_consumer_key: props.getProperty('CONSUMER_KEY'),
    oauth_token: props.getProperty('ACCESS_TOKEN'),
    oauth_timestamp: (Math.floor((new Date()).getTime() / 1000)).toString(),
    oauth_signature_method: "HMAC-SHA1",
    oauth_version: "1.0"
  };

  oauthParameters.oauth_nonce = oauthParameters.oauth_timestamp + Math.floor(Math.random() * 100000000);

  var payload = {
    status: message
  };

  var queryKeys = Object.keys(oauthParameters).concat(Object.keys(payload)).sort();

  var baseString = queryKeys.reduce(function(acc, key, idx) {
    if (idx) acc += encodeURIComponent("&");
    if (oauthParameters.hasOwnProperty(key))
      acc += encode(key + "=" + oauthParameters[key]);
    else if (payload.hasOwnProperty(key))
      acc += encode(key + "=" + encode(payload[key]));
    return acc;
  }, method.toUpperCase() + '&' + encode(baseUrl) + '&');

  oauthParameters.oauth_signature = Utilities.base64Encode(
    Utilities.computeHmacSignature(
      Utilities.MacAlgorithm.HMAC_SHA_1,
      baseString,
      props.getProperty('CONSUMER_SECRET') + '&' + props.getProperty('ACCESS_SECRET')
    )
  );

  var options = {
    method: method,
    headers: {
      authorization: "OAuth " + Object.keys(oauthParameters).sort().reduce(function(acc, key) {
        acc.push(key + '="' + encode(oauthParameters[key]) + '"');
        return acc;
      }, []).join(', ')
    },
    payload: Object.keys(payload).reduce(function(acc, key) {
      acc.push(key + '=' + encode(payload[key]));
      return acc;
    }, []).join('&'),
    muteHttpExceptions: true
  }

  var response = UrlFetchApp.fetch(baseUrl, options);
  var responseHeader = response.getHeaders();
  var responseText = response.getContentText();
  Logger.log(responseText);
}

function encode(string) {
  return encodeURIComponent(string)
    .replace('!', '%21')
    .replace('*', '%2A')
    .replace('(', '%28')
    .replace(')', '%29')
    .replace("'", '%27');
} 
Categories
Code

Upload and Post Images to Twitter with Google Script

There are two ways to post tweets that contain images. You can either upload the picture(s) to an image hosting service and then paste the image URL into the tweet. The other option is that you natively upload the image into Twitter.

Here’s a sample snippet that shows how you can use Google Apps Script to upload and post images to Twitter with the new Twitter API. You can either pull an image from the web or you can use the DriveApp service to pull an image from your Google Drive.

To get started, you need to create a new Twitter app and generate the Consumer API keys. You’ll also need to include the Twitter Library in your Apps Script project (key MKvHYYdYA4G5JJHj7hxIcoh8V4oX7X1M_)

function sendTweetwithImage() {
  
  var twitterKeys= {
    TWITTER_CONSUMER_KEY: "aa",
    TWITTER_CONSUMER_SECRET: "bb",
    TWITTER_ACCESS_TOKEN: "cc",
    TWITTER_ACCESS_SECRET: "cc"    
  };
  
  var props = PropertiesService.getUserProperties();
  
  props.setProperties(twitterKeys);
  
  var twit = new Twitter.OAuth(props);
  
  if ( twit.hasAccess() ) {
    
    try {
      
      // DriveApp.getFileById(id).getBlob()
      
      var imageUrl  = "http://img.labnol.org/di/M1.jpg";    
      var imageBlob = twit.grabImage(imageUrl, "image/jpeg");
      var uploadImg = twit.uploadMedia(imageBlob);
      
      if (uploadImg) {
        
        var status = "Hello @labnol";
        
        var response = twit.sendTweet(status, {
          media_ids: uploadImg.media_id_string      
        });
        
        if (response) {
          
          Logger.log("Tweet Sent " + response.id_str);
          
        } else {
          
          // Tweet could not be sent
          // Go to View -> Logs to see the error message
          
        }
        
      }
    } catch (f) {
      Logger.log(f.toString());
    }
    
  }  
}
Categories
Code

Use the Twitter Search API without the OAuth Library

Google doesn’t recommend using script libraries inside add-ons based Apps script projects as they tend to impact performance. This snippet shows how to use the Twitter Search API inside Google Apps Script without including the OAuth library.

Create a new Twitter app, get the Consumer Key and Secret and you will be able to perform most Twitter API functions from within Google Apps Script.

function testTwitterConnection() {

  var twitterKeys = {
    TWITTER_CONSUMER_KEY: "iqoWfLEG1Q4eMGptxiEzb83Da",
    TWITTER_CONSUMER_SECRET: "g6EJijC9Nsrc2D6WazXjF353FNATZzCvtCoigtBoUMfCQeW0L"
  };

  setupTwitter(twitterKeys);
  searchTwitter('ctrlq');
  
}

function setupTwitter(twitterKeys) {

  // URL encode the consumer key and the consumer secret according to RFC 1738
  var encodedConsumerKey = encodeURIComponent(twitterKeys.TWITTER_CONSUMER_KEY);
  var encodedConsumerSecret = encodeURIComponent(twitterKeys.TWITTER_CONSUMER_SECRET);

  // Concatenate the encoded consumer key, a colon character “:”, and the encoded consumer secret into a single string.
  // Base64 encode the string from the previous step.
  var base64EncodedBearerToken = Utilities.base64Encode(encodedConsumerKey + ":" + encodedConsumerSecret);

  // Step 2: Obtain a bearer token

  // The request must be a HTTP POST request.
  // The request must include an Authorization header with the value of Basic .
  // The request must include a Content-Type header with the value of application/x-www-form-urlencoded;charset=UTF-8.
  // The body of the request must be grant_type=client_credentials.

  var bearer_url = 'https://api.twitter.com/oauth2/token';
  var options = {
    "method": "POST",
    "headers": {
      "Authorization": "Basic " + base64EncodedBearerToken,
      "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
    },
    "payload": {
      "grant_type": "client_credentials"
    }
  };

  var response = UrlFetchApp.fetch(bearer_url, options);
  var data = JSON.parse(response.getContentText());

  // Store the Access Token
  if (data.access_token) {
    PropertiesService.getScriptProperties()
      .setProperty("TWITTER_ACCESS_TOKEN", data.access_token);
  }

  return data.access_token;
}


function searchTwitter(query) {

  var access_token = PropertiesService.getScriptProperties().getProperty("TWITTER_ACCESS_TOKEN");

  if (access_token === null) {
    Logger.log("Run Twitter setup again");
    return;
  }

  var base_url = 'https://api.twitter.com/1.1/search/tweets.json';
  var search_url = base_url + '?q=' + encodeURIComponent(query);

  var options = {
    "method": "GET",
    "headers": {
      "Authorization": "Bearer " + access_token,
      "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
      "Accept-Encoding": "gzip"
    },
    "followRedirects": true,
    "muteHttpExceptions": true
  };

  var response = UrlFetchApp.fetch(search_url, options);
  var data = JSON.parse(response.getContentText());
  var tweets = data.statuses;

  // Output the tweets in the log
  // They can also be saved in a Google Spreadsheet

  for (var t = 0; t < tweets.length; t++) {
    Logger.log("%s wrote: %s", tweets[t].user.name, tweets[t].text);
  }

}
Categories
Code

How to Send Tweets with Google Scripts and Twitter API

This example shows how you can setup your own Twitter Client using Google Apps Script and publish tweets programmatically from inside a Google Document, a spreadsheet or even a web app.

To get started, go to apps.twitter.com and create a new Twitter application. Switch to Keys and Access Tokens tab and generate your Access Token and Secret. This will help you send tweets from your Twitter account without manual authorization. Next in the Apps Script project, include the Twitter library (key: MKvHYYdYA4G5JJHj7hxIcoh8V4oX7X1M_) with the identifier set to Twitter.

function sendTweet(status) {
  
  status = status || "I found this snippet on @labnol's ctrlq.org";
  
  var twitterKeys= {
    TWITTER_CONSUMER_KEY: "<>",
    TWITTER_CONSUMER_SECRET: "<>",
    TWITTER_ACCESS_TOKEN: "<>",
    TWITTER_ACCESS_SECRET: "<>"    
  };
  
  var props = PropertiesService.getScriptProperties();
  
  props.setProperties(twitterKeys);
  
  var service = new Twitter.OAuth(props);
  
  if ( service.hasAccess() ) {
    
    var response = twit.sendTweet(status);
    
    if (response) {
      
      Logger.log("Tweet ID " + response.id_str);
      
    } else {
      
      // Tweet could not be sent
      // Go to View -> Logs to see the error message
      
    }
  }  
}
Categories
Code

Twitter Bot for Auto-Favoriting and Retweeting Tweets

The Twitter bot, written with Google Apps Script, will auto-favorite and retweet tweets every few minutes. Do include the Twitter API library in your Google Scripts project as discussed in the previous tutorial on creating Twitter bots.


// Written by Amit Agarwal @labnol on 31/07/2015

// Fill the Twitter Keys and then choose Run -> Start Bot

TWITTER_CONSUMER_KEY    = "123";
TWITTER_CONSUMER_SECRET = "123";
TWITTER_ACCESS_TOKEN    = "123";
TWITTER_ACCESS_SECRET   = "123";
TWITTER_SEARCH_PHRASE   = "filter:links labnol.org";

function Start_Bot() {
  
  var props = PropertiesService.getScriptProperties();
  
  props.setProperties({
    TWITTER_CONSUMER_KEY: TWITTER_CONSUMER_KEY,
    TWITTER_CONSUMER_SECRET: TWITTER_CONSUMER_SECRET,
    TWITTER_ACCESS_TOKEN: TWITTER_ACCESS_TOKEN,
    TWITTER_ACCESS_SECRET: TWITTER_ACCESS_SECRET,
    SINCE_TWITTER_ID: 0
  });
  
  var twit = new Twitter.OAuth(props);
  
  // Test Twitter authorization
  
  if (!twit.favorite("628053456071192576")) {
    throw new Error("Please check your Twitter access tokens");
    return;
  }
  
  ScriptApp.newTrigger("labnol_twitterBot")
  .timeBased()
  .everyMinutes(10)
  .create();
  
}

function labnol_twitterBot() {
  
  try {
    
    var props = PropertiesService.getScriptProperties(),
        twit = new Twitter.OAuth(props);
    
    if (twit.hasAccess()) {
      
      var tweets = twit.fetchTweets(
        TWITTER_SEARCH_PHRASE, function(tweet) {
          // Skip tweets that contain sensitive content
          if (!tweet.possibly_sensitive) {
            return tweet.id_str;
          }
        }, {
          multi: true,
          lang: "en", // Process only English tweets
          count: 5,   // Process 5 tweets in a batch
          since_id: props.getProperty("SINCE_TWITTER_ID")
        });
      
      if (tweets) {
        
        props.setProperty("SINCE_TWITTER_ID", tweets[0]);
        
        for (var i = tweets.length - 1; i >= 0; i--) {
          
          twit.retweet(tweets[i]);
          twit.favorite(tweets[i]);
          
          /* Wait between 10 seconds and 1 minute */
          Utilities.sleep(Math.floor(Math.random()*50000) + 10000);
          
        }
      }
    }
    
  } catch (f) {
    Logger.log("Error: " + f.toString());
  }
  
}

// Email: amit@labnol.org
// Premium Support: http://ctrlq.org

Categories
Code

Search Twitter with Google Apps Script

The Twitter Search Archiver uses the OAuth1 library for Google Apps Script to talk to the Twitter Search API. You need to include the OAuth1 library in your Google Script project, create a Callback URL and then call the authorization URL in a separate browser tab to authorize the Twitter service.

However, if you are only going to make read-only requests to Twitter – like fetching user timelines for Twitter RSS feeds or performing searches – you can do without the library as well. You won’t be able to post tweets or DMs though.

Twitter supports application-only authentication giving apps the ability to issue authenticated requests on behalf of the application itself without authenticating the specific user.

First create a new Twitter app and make a note of the Twitter consumer key and consumer secret. The Callback URL can be left blank since it is not required.


/* Based on thinkAmi-sandbox/GAS-TwitterOAuth2-sample */

function Twitter() {
  
  // Encode consumer key and secret
  var tokenUrl = "https://api.twitter.com/oauth2/token";
  var tokenCredential = Utilities.base64EncodeWebSafe(
    TWITTER_CONSUMER_KEY + ":" + TWITTER_CONSUMER_SECRET);
  
  //  Obtain a bearer token with HTTP POST request
  var tokenOptions = {
    headers : {
      Authorization: "Basic " + tokenCredential,
      "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" 
    },
    method: "post",
    payload: "grant_type=client_credentials"
  };
  
  var responseToken = UrlFetchApp.fetch(tokenUrl, tokenOptions);
  var parsedToken = JSON.parse(responseToken);
  var token = parsedToken.access_token;
  
  // Authenticate Twitter API requests with the bearer token
  var apiUrl = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=labnol";
  var apiOptions = {
    headers : {
      Authorization: 'Bearer ' + token
    },
    "method" : "get"
  };
  
  var responseApi = UrlFetchApp.fetch(apiUrl, apiOptions);
  
  var result = "";
  
  if (responseApi.getResponseCode() == 200) {
    
    // Parse the JSON encoded Twitter API response
    var tweets = JSON.parse(responseApi.getContentText());
    
    if (tweets) {
      
      for (var i = 0; i < tweets.length; i++) {
        var tweet = tweets[i].text;
        var date = new Date(tweets[i].created_at);
        result += "[" + date.toUTCString() + "]" + tweet + " / ";
      }
    }
  }
  
  Logger.log(result);
  
}
Categories
Code

How to Make a Twitter Bot with Google Scripts

You can easily write a Twitter bot with the help of Google Apps Script. It fetches tweets addressed (@mentions) to the bot through the Twitter API, computes the answer with Wolfraph Alpha and replies with a tweet. The steps are:

  • Create a Twitter App at apps.twitter.com (screenshot) and note the Twitter Consumers Keys and Access Tokens
  • Go to developer.wolfram.com, create an account screenshot and then choose “Get an App ID” to create your new app. We will need this App ID in the Google Script. Your free Wolfram Alpha App can only be used for a non-commercial purpose.
  • Edit the values of TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET, TWITTER_HANDLE (your Twitter account) and WOLFRAM_API_ID
  • Go to Run -> Start to initialize the Twitter bot. Say yes if the script requires you to authorize access to certain Google services.

The code is ready to though you’ll need to create a Wolfram App and also include the Twitter library in your Google Scripts project (key is MKvHYYdYA4G5JJHj7hxIcoh8V4oX7X1M_) with the identifier set to Twitter.


/* Twitter Bot written by Amit Agarwal */

function Start() {

  var props = PropertiesService.getScriptProperties();

  props.setProperties({
    TWITTER_CONSUMER_KEY: TWITTER_CONSUMER_KEY,
    TWITTER_CONSUMER_SECRET: TWITTER_CONSUMER_SECRET,
    TWITTER_ACCESS_TOKEN: TWITTER_ACCESS_TOKEN,
    TWITTER_ACCESS_SECRET: TWITTER_ACCESS_SECRET,
    MAX_TWITTER_ID: 0
  });

  // Delete exiting triggers, if any

  var triggers = ScriptApp.getProjectTriggers();

  for (var i = 0; i < triggers.length; i++) {
    ScriptApp.deleteTrigger(triggers[i]);
  }

  // Setup a time-based trigger for the Bot to fetch and process incoming Tweets 
  // every minute. If your Google Script is running out of quota, change the
  // time to 5 or 10 minutes though the bot won't offer real-time answers then.

  ScriptApp.newTrigger("labnol_twitterBot")
    .timeBased()
    .everyMinutes(1)
    .create();

}

/* For help, email amit@labnol.org or visit http://ctrlq.org */

function labnol_twitterBot() {

  try {

    var props = PropertiesService.getScriptProperties(),
      twit = new Twitter.OAuth(props);

    // Are the Twitter access tokens are valid?
    if (twit.hasAccess()) {

      var tweets = twit.fetchTweets("to:" + TWITTER_HANDLE,
        function(tweet) {
          // Ignore tweets that are sensitive (NSFW content)
          if (!tweet.possibly_sensitive) {
            var question = tweet.text.toLowerCase().replace("@" + TWITTER_HANDLE, "").trim(),
              answer = askWolframAlpha_(question);
            if (answer) {
              return {
                answer: "@" + tweet.user.screen_name + " " + answer,
                id_str: tweet.id_str
              };
            }
          }
        }, {
          multi: true,
          lang: "en",  // Fetch only English tweets
          count: 5,    // Process 5 tweets in a batch
          since_id: props.getProperty("MAX_TWITTER_ID")
        });

      if (tweets.length) {

       // The MAX_TWITTER_ID property store the ID of the last tweet answered by the bot
        props.setProperty("MAX_TWITTER_ID", tweets[0].id_str);

        // Process the tweets in FIFO order
        for (var i = tweets.length - 1; i >= 0; i--) {

          // The bot replies with an answer
          twit.sendTweet(tweets[i].answer, {
            in_reply_to_status_id: tweets[i].id_str
          });

          // Wait a second to avoid hitting the rate limits
          Utilities.sleep(1000);
        }
      }
    }

  } catch (f) {
    // You can also use MailApp to get email notifications of errors.
    Logger.log("Error: " + f.toString());
  }

}

function askWolframAlpha_(q, app) {

  try {

    var api = "http://api.wolframalpha.com/v2/query?podindex=2&format=plaintext&appid=" 
                   + WOLFRAM_APP_ID + "&input=" + encodeURIComponent(q);
    var response = UrlFetchApp.fetch(api, {
      muteHttpException: true
    });

    // Parse the XML response
    if (response.getResponseCode() == 200) {
      var document = XmlService.parse(response.getContentText());
      var root = document.getRootElement();
      if (root.getAttribute("success").getValue() === "true") {
        return root.getChild("pod").getChild("subpod").getChild("plaintext").getText();
      }
    }
  } catch (f) {}
  return false;
}

Categories
Code

Export Tweets from Twitter with Google Apps Script

The Twitter Archiver app will archive tweets for any hashtag to a Google Spreadsheet using the Twitter API and Google Apps Script.

You can set a time-based trigger to run downloadTweets() every 5 minutes or even 1 minute for #hashtags that are extremely popular and generate thousands of tweets. The code has been updated to using the OAuth1 library instead of the OAuthConfig service which has since been deprecated.


function downloadTweets(searchTerm) {

    var twitterService = getTwitterService_();

    var props = PropertiesService.getUserProperties();
    var sinceID = props.getProperty("SINCEID") || "";

    var api = "https://api.twitter.com/1.1/search/tweets.json?count=100&include_entities=false";
    api += "&result_type=recent&q=" + encodeString_(searchTerm) + "&since_id=" + sinceID;

    var result = twitterService.fetch(api);

    if (result.getResponseCode() == 200) {

        var json = JSON.parse(result.getContentText());

        var tweets = json.statuses;

        // SINCEID will store the ID of the last processed tweet

        for (var i = tweets.length - 1; i >= 0; i--) {
            logTweet_(tweets[i]);
            if (i == 0) {
                props.setProperty("SINCEID", tweets[0].id_str);
            }
        }
    }
}

/* Add the tweet details into the sheet */
function logTweet_(tweet) {

    var log = [];

    log.push(new Date(tweet.created_at));
    log.push('=HYPERLINK("https://twitter.com/' + tweet.user.screen_name + '/status/' + tweet.id_str + '","' + tweet.user.name + '")');
    log.push(tweet.user.followers_count);
    log.push(tweet.user.friends_count);
    log.push(tweet.retweet_count);
    log.push(tweet.favorite_count);
    log.push(tweet.text.replace(/\n|\r/g, " "));

    SpreadsheetApp.getActiveSheet().appendRow(log)
}


function getTwitterService_() {

    var props = PropertiesService.getUserProperties();

    return OAuth1.createService('twitter')
        .setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
        .setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
        .setAuthorizationUrl('https://api.twitter.com/oauth/authorize')
        .setConsumerKey(props.getProperty("consumer_key"))
        .setConsumerSecret(props.getProperty("consumer_secret"))
        .setProjectKey(ScriptApp.getProjectKey())
        .setCallbackFunction('twitter')
        .setPropertyStore(props);

}


/* Properly encode the Twitter search query */
function encodeString_(q) {
    var str = encodeURIComponent(q);
    str = str.replace(/!/g, '%21');
    str = str.replace(/\*/g, '%2A');
    str = str.replace(/\(/g, '%28');
    str = str.replace(/\)/g, '%29');
    str = str.replace(/'/g, '%27');
    return str;
}

Categories
Code

Get your Twitter Followers with Google Script

The Google Script fetches your Twitter followers and appends the list to a Google Spreadsheet. It fetch the Twitter avatar and add it to the cell using Image formula. This method was used to determine the Egg followers for any Twitter user.

function getTwitterFollowers() {
  
  var api = "https://api.twitter.com/1.1/followers/list.json?count=200";
  
  var oAuth = UrlFetchApp.addOAuthService("labnol");
  
  oAuth.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
  oAuth.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
  oAuth.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
  oAuth.setConsumerKey("CONSUMER_KEY");
  oAuth.setConsumerSecret("CONSUMER_SECRET"); 
  
  var result = UrlFetchApp.fetch ( api, {
    "method": "get",
    "oAuthServiceName":"labnol",
    "oAuthUseToken":"always"
  } );   
  
  if (result.getResponseCode() == 200) {
    
    if ( var json = JSON.parse(result.getContentText()) ) {
      
      var ss = SpreadsheetApp.getActive().getActiveSheet();
      
      for (var u in json.users) {
        
        var user = json.users[u];
        
        ss.appendRow([
          '=image("' + user.profile_image_url + '", 4, 50, 50)' : "",
          '=hyperlink("http://twitter.com/' + user.screen_name + '","' + user.name + '")',
          user.status ? user.status.created_at : "never",    
          user.created_at,    
          user.statuses_count,
          user.followers_count,
          user.friends_count,
          user.url.replace(/https?:\/\/(www.)?/, "").replace(/\/$/, "") : "",
          user.location,
          user.description.replace(/\n|\r/g, " ") 
        ]);
        
      } 
    } 
  }
}
Categories
Code

Twitter API – Error Messages

If your app is posting to Twitter using using the API v1.1, it should be able to handle the following errors:

1. This request looks like it might be automated. To protect our users from spam and other malicious activity, we can’t complete this action right now. Please try again later.

2. One or more of the uploaded media is too large.

3. User is over daily status update limit.

4. Invalid or Expired Token.

5. You cannot send messages to users who are not following you.

6. Your account is suspended and is not permitted to access this feature.

For #2, you are probably attaching an image that is beyond the permitted size. In the case of #4, probably the user has been inactive for long and the session has expired. For #1, they are probably posting tweets too soon.

Categories
Code

Embed a Tweet with JavaScript Programmatically

You can embed any tweet on your website easily using the embed code from the Twitter website but a downside is you do not have any control over the embedded IFRAME widget. You can neither customize the style of elements nor can you hide elements (like the Follow button) that you do not want in the embedded tweet.

As an alternative, you can use JavaScript to embed tweets programmatically and here you will be able to decide how the elements are styled and which elements are displayed or stay hidden.

To get started, paste this snippet anywhere in your HTML web page and change the tweetID. You can cards option in the createTweet() method to “visible” and then the photos and cards in the tweet would be auto-expanded.






Categories
Code

Scrape Twitter Data with JavaScript

You can use YQL and JavaScript to quickly scrape tweets from Twitter search results on the client side. The tweets are returned as JSON that can be easily parsed using regular expressions.

The advantage with this approach is that it requires no OAuth (authorization) and even old tweets can be returned when the search request is combined with the since: and until: search operators.

YQL allows 2000 requests / per hour / per IP so you are also unlikely to hit the usage limit.



function fetchTweets(q) {

  var yql  = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%3D%22";
  var base = "https://twitter.com/i/search/timeline?f=realtime&src=typd&include_entities=0&q=";

  // Test the URL in YQL console to make sure it works
  var url  = yql + base + encodeURIComponent(q) + "%22&format=json";

   // Make synchronous AJAX request to yql
  var tweets = jQuery.ajax({type: "GET", url: url, dataType: 'json', async: false }).responseText;

  // Parse the JSON response
  var data = JSON.parse(tweets);

  // Return the HTML search results
  return data.query.results.json.items_html;
  
}

Categories
Code

Save Twitter Emails in a Google Sheet

This Google Script will save the email addresses and usernames from Twitter’s Lead Generation Cards into a Google Sheet. You publish this Google Script as a web app, the Twitter card makes a POST HTTP request and the payload is parsed and saved in the Google Sheet.

We are using the HYPERLINK() method so the Twitter user name automatically points to the profile page on the Twitter website.


function doPost(e) {
  
  if (typeof e !== 'undefined') {
    
    try {
      
      var params = e.parameter;
      
      var formula = '=hyperlink("https://twitter.com/' + params.screen_name + '", "@' + params.screen_name + '")';
            
      var date = Utilities.formatDate(new Date(), "GMT", "MM-dd-yyyy HH:mm:ss")
            
      var id = "sheetID";
      
      SpreadsheetApp.openById(id).appendRow([date, params.name, params.email, formula]);
      
      return ContentService.createTextOutput("Data added");  
      
    } catch (e) {
      
      return ContentService.createTextOutput(e.toString());  
      
    }
    
  }
  
}
Categories
Code

Delete Old Tweets Automatically with Google Scripts

The Google Script will read your Twitter timeline and auto-delete tweets that are older than ‘n’ days excepts the ones that are retweets or favorited.

You can run this function Delete_Old_Tweets manually in the Google Apps Script editor or setup a time-based trigger to keep your Twitter profile void of any old tweets. The author of the script is unknown.

function Delete_Old_Tweets() {

  oAuth();
  var destroy_count = 0;
  var tweets = fetchTweets(0);
  var stoptweets = 0;
  var run_time = new Date();
  var tweet_date = new Date();
  var tweet_age = 0;
  
  while (tweets.length>1) {
    max_id = tweets[tweets.length-1].id_str
    for (var i=tweets.length-1; i>=0; i--) {
      tweet_date = new Date(tweets[i].created_at);
      
      //age of the tweet in days
      tweet_age = (run_time-tweet_date)/1000/60/60/24 + "  " + tweet_date;
      
      /////////////ALTER CRITERIA HERE TO TWEAK WHAT GETS DELETED
      if (tweet_age >> 2 && ((tweets[i].retweeted_status != undefined) || (tweets[i].retweet_count == 0 && tweets[i].favorited == false)))
      {
        destroyTweet(tweets[i].id_str);
        destroy_count+=1;
      }
    }
    tweets = fetchTweets(max_id+1);
    Logger.log(destroy_count);
    
  }
}


function fetchTweets(max_id) {
  
  /////////////////////////SET YOU TWITTER SCREENNAME HERE
  var twitter_handle = "TWITTER SCREENNAME";
  
  var search = "https://api.twitter.com/1.1/statuses/user_timeline.json"; 
  search = search + "?include_entities=true&include_rts=true&screen_name=" + twitter_handle + "&count=200";    
  if (max_id>0) {
    search = search + "&since_id=" + max_id;
  }  
  
  var options =
      {
        "method": "get",
        "oAuthServiceName":"twitter",
        "oAuthUseToken":"always"
      };
  
  try {
    var result = UrlFetchApp.fetch(search, options);    
  }
  catch(e) {
    Logger.log(e.toString());
  }
  
  if (result.getResponseCode() === 200) {
    
    var data = JSON.parse(result.getContentText());
    
    if (data) {
      Logger.log("Fetched " + data.length + " tweets.");
      return data;    
    }
    
  }
  
}

function destroyTweet(tweet_id) {
  
  var options =
      {
        "method": "POST",
        "oAuthServiceName":"twitter",
        "oAuthUseToken":"always"    
      };
  
  var destroy = "https://api.twitter.com/1.1/statuses/destroy/" + tweet_id + ".json";
  
  try {
    var result = UrlFetchApp.fetch(destroy, options); 
  }  
  catch (e) {
    Logger.log(e.toString());
  }   
}


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");
  
  //////////////////////////SET YOUR TWITTER API KEY AND SECRET HERE
  oauthConfig.setConsumerKey("TWITTER API KEY");
  oauthConfig.setConsumerSecret("TWITTER API SECRET");
  
}
Categories
Code

Send Tweets from Google Sheets

It is possible to send bulk tweets from Google Spreadsheet using Google Scripts. To get started, you need to include the OAuth1 libarary in your project, create a new Twitter app on apps.twitter.com and pass the Consumer Keys and API Secret to the Google Script project.

function sendTweet(user, tweet, tweet_type) {

    var twitterService = getTwitterService_();

    // If the Google Apps user has authorized the Twitter service
    if (twitterService.hasAccess()) {

        // Remove @ from the Twitter user name, if found
        var twitterUser = user.trim().replace(/^\@/, "");

        var api = "https://api.twitter.com/1.1/";

        // Send a public @tweet or direct message (DM)
        if (tweet_type === "DM") {
            api += "direct_messages/new.json?screen_name=" + twitterUser + "&text=" + encodeString_(tweet);
        } else if (tweet_type === "TWEET") {
            tweet = "@" + twitterUser + " " + tweet;
            api = "statuses/update.json?status=" + encodeString_(tweet);
        }

        var response = twitterService.fetch(api, {
            method: "POST",
            muteHttpExceptions: true
        });
        if (response.getResponseCode() === 200) {
            Logger.log("Tweet sent");
        } else {
            Logger.log("ERROR: " + JSON.parse(response.getContentText()).errors[0].message);
        }
    }
}

// Google Script has trouble sending tweets that contain !*()'
// so we replace these variable from the status text
function encodeString_(q) {
    var str = q;
    str = str.replace(/!/g, 'Ị');
    str = str.replace(/\*/g, '×');
    str = str.replace(/\(/g, '[');
    str = str.replace(/\)/g, ']');
    str = str.replace(/'/g, '’');
    return encodeURIComponent(str);
}
Categories
Code

Get Social Share Counts of a URL with Google Scripts

Would you like to know how popular is particular web page on social networks? Google Apps Script can help.

You can create a spreadsheet with a list of web page URLs and then use this getSocialCounts() function to retrieve the social sharing count of each of these URLs.

It gets shared counts for Twitter, Facebook, StumbleUpon and LinkedIn.

function testSocialShares() {
  var url = "http://www.labnol.org/";
  getSocialCounts(url);
}

/* Credit: https://gist.github.com/tomcritchlow/904203 */
function getSocialCounts(url) {
  
  var json, response;
  
  var json = UrlFetchApp.fetch("http://graph.facebook.com/"+url);
  var response = Utilities.jsonParse(json.getContentText());
  Logger.log("Facebook Likes :: " + response.likes);
  
  json = UrlFetchApp.fetch("https://graph.facebook.com/fql?q=SELECT%20share_count%20FROM%20link_stat%20WHERE%20url%20=%22" + url + "%22");
  response = Utilities.jsonParse(json.getContentText());
  Logger.log("Facebook Shares :: " + response.data[0].share_count);
  
  json = UrlFetchApp.fetch("http://urls.api.twitter.com/1/urls/count.json?url="+url);
  response = Utilities.jsonParse(json.getContentText());
  Logger.log("Twitter Shares :: " + response.count);
  
  json = UrlFetchApp.fetch("http://www.linkedin.com/countserv/count/share?format=json&url="+url);
  response = Utilities.jsonParse(json.getContentText());
  Logger.log("LinkedIn Shares :: " + response.count);
  
  json = UrlFetchApp.fetch("http://www.stumbleupon.com/services/1.01/badge.getinfo?url="+url);
  response = Utilities.jsonParse(json.getContentText());
  Logger.log("SU :: " + response.result.views);

 
}
Categories
Code

Change Twitter Profile Picture (Avatar) with Google Scripts

This Google Script updates the Twitter user’s profile image or avatar. Twitter asynchronously processes the uploaded file before updating the user’s profile image URL.

function oAuthConfig() {

  var oAuthConfig = UrlFetchApp.addOAuthService("twitter");
  oAuthConfig.setAccessTokenUrl("http://api.twitter.com/oauth/access_token");
  oAuthConfig.setRequestTokenUrl("http://api.twitter.com/oauth/request_token");
  oAuthConfig.setAuthorizationUrl("http://api.twitter.com/oauth/authorize");
 
  oAuthConfig.setConsumerKey("PUT CONSUMER KEY HERE");
  oAuthConfig.setConsumerSecret("PUT CONSUMER SECRET HERE");
}
 
function setProfileImage() {
 
  oAuthConfig();
 
  // This is a picture that will be set as Twitter avatar
  var picture = UrlFetchApp.fetch("https://twitter.com/image.png");
  var encodedImage = Utilities.base64Encode(picture.getContent());

  var options =
  {
    "method": "post",
    "oAuthServiceName" : "twitter",
    "oAuthUseToken" : "always",
    "payload": { "image" : encodedImage, "skip_status": true}
  };

  var request = UrlFetchApp.fetch("http://api.twitter.com/1.1/account/update_profile_image.json", options);
}
Categories
Code

Embed Twitter with RSS Feeds

You use widgets in Twitter for embedding Twitter timelines into your website and this Google Script will convert those widgets into RSS format. Thus you will be able to subscribe to Twitter RSS Feeds in IFTTT, Feedly, or another RSS Reader.


 

function getTweets(id) {
  
  try {
           
    var widget, json, tweets, regex, tweet, list, time, url, when, rss, heading, title, link; 
    
    title = "Twitter RSS Feed :: " + id;
    link  = "http://www.labnol.org/#" + id;       

    // This the ID of your Twitter widget       
    url   = "http://cdn.syndication.twimg.com/widgets/timelines/" + id;
    
    widget  = UrlFetchApp.fetch(url);
    json    = Utilities.jsonParse(widget);   

    // If the Twitter widget doesn't exist, do nothing    
    if ( ! json.body ) {
      return;
    }
       
    // Remove all whitespaces from the Twitter's JSON response
    tweets  = json.body.replace(/\s+/g, ' ');
    
    // Get the Feed Title and URL from the response heading (H1)
    regex = new RegExp(/]*>(.*?)<\/h1>/ig);
    
    if ((heading = regex.exec(tweets)) !== null) {
      
      regex = RegExp(/href="(.*?)"/ig);
      link = regex.exec(heading[1])[1];
      
      regex = RegExp(/title="(.*?)"/ig);
      if ((title = regex.exec(heading[1])) !== null) {
        title = title[1];
      }
    }
    
    rss  = '';
    rss += ' ' + title + '';
    rss += ' ' + link + '';
    rss += ' ';
    rss += ' ' + title + ' :: RSS Feed for Twitter widget #' + id + ' generated by Google Scripts.';
    
    regex = RegExp(/]*>(.*?)<\/ol>/ig);
    
    if ((list = regex.exec(tweets)) !== null) {
      
      // Remove all the extra classes, DIV tags, SPAN tags from the tweets.
      list = list[1].replace(/
]*>(.*?)<\/div>/gi, "") .replace(/]*>(.*?)<\/time>/gi, "") .replace(/data-tweet-id=".*?"|class=".*?"|rel=".*?"|title=".*?"|target=".*?"|data-expanded-url=".*?"|data-query-source=".*?"|dir=".*?"|data-pre-embedded=".*?"/gi, ""); regex = RegExp(/]*>(.*?)<\/li>/ig); while ((tweets = regex.exec(list)) !== null) { tweet = tweets[1].replace(/ /g, ' ').replace(/\s+/g, ' ') .replace(/<\s*(div|span|b|p)[^>]*>/gi, "") .replace(/<\s*\/\s*(div|span|b|p)[^>]*>/gi, ""); // Extract the Date and Time of the tweet time = RegExp(/<\/a>/gi); if ((time = time.exec(tweet)) !== null) { url = time[1]; when = time[2]; tweet = tweet.replace(/]*>\s*<\/a>/gi, ""); rss += ""; rss += " " + url.split("/")[3] + ": " + tweet + ""; rss += " " + when.replace('T', ' ') + ""; rss += " " + url + ""; rss += " " + url + ""; rss += " " + tweet + ""; rss += ""; } } } rss += ""; return rss; } catch (e) { Logger.log(e.toString()); } } function doGet(e) { var cache = CacheService.getPublicCache(); var id = "twitter" + e.queryString; var rss = cache.get(id); if ( ! rss ) { rss = getTweets(e.queryString); cache.put(id, rss, 120); // Expire RSS Feed in 2 minutes } // Use the HTML Service in Google Apps Script to serve Twitter RSS Feeds return ContentService.createTextOutput(rss) .setMimeType(ContentService.MimeType.RSS); }
Categories
Code

Convert Twitter JSON to RSS with Google Apps Script

This Google Script converts the JSON response from the Twitter API to standard RSS feeds. The results are cached for 60 minutes and all requests to Twitter are authenticated with OAuth, an important requirement of the Twitter API v1.1.

 

function JSONtoRSS(json, type, key) {

  oAuth();
  
  var options =
  {
    "method": "get",
    "oAuthServiceName":"twitter",
    "oAuthUseToken":"always"
  };
    
  try {

    var result = UrlFetchApp.fetch(json, options);    

    if (result.getResponseCode() === 200) {
      
      var tweets = Utilities.jsonParse(result.getContentText());
      
      if (tweets) {
                
        var len = tweets.length;
        
        var rss = "";
        
        if (len) {
          
          rss  = '';
          rss += ' Twitter ' + type + ': ' + key + '';
          rss += ' ' + htmlentities ( json ) + '';
          rss += ' ' + new Date() + '';

          for (var i=0; i";
            rss += " " + tweets[i].user.name 
                            + " (@" + sender + ")";
            rss += " " + tweets[i].created_at + "";
            rss += " " + tweets[i].id_str + "";
            rss += " https://twitter.com/" + sender 
                            + "/statuses/" + tweets[i].id_str + "";
            rss += " " + tweet + "";
            rss += "";                        
          }
          
          rss += "";
          
          return rss;          
        }        
      }      
    }    
  } catch (e) {
    Logger.log(e.toString());
  }  
}

function doGet(e) {
   
  var a = e.parameter.action;
  var q = e.parameter.q;

  var feed = "https://api.twitter.com/1.1/";  
  
  switch (a) 
  {
    case "timeline": 
      feed += "statuses/user_timeline.json?screen_name=" + q;
      break;
    case "search":
      feed += "search/tweets.json?q=" + encodeURIComponent(q);
      break;
    case "favorites":
      feed += "favorites/list.json?screen_name=" + q;
      break;
    case "list":
      var i = q.split("/");
      feed += "lists/statuses.json?slug=" + i[1] + "&owner_screen_name=" + i[0];
      break;
    default:
      feed += "statuses/user_timeline.json";
      break;      
  }
  
  var id = Utilities.base64Encode(feed);
  
  var cache = CacheService.getPublicCache();
  var rss   = cache.get(id);
  
  if ( ! rss ) {
    rss = JSONtoRSS ( feed, a, q );
    cache.put(id, rss, 3600);
  }
  
  return ContentService.createTextOutput(rss)
    .setMimeType(ContentService.MimeType.RSS);
}

 

Categories
Code

Twitter AutoResponder with Google Scripts

Use this Google Script to setup Out of Office auto-replies in Twitter. The script reads all the Twitter @mentions and sends them a tweet with a custom status message.

 

/*     O U T   O F   O F F I C E   F O R   T W I T T E R    */
/*     - - -   - -   - - - - - -   - - -   - - - - - - -    */

/*     Written by Amit Agarwal http://labnol.org?p=27911    */
/*     For help, email amit@labnol.org or tweet @labnol     */

function start() {
  
  // Please enter dates in YYYY-MM-DD HH:MM format
  
  var OUTOFOFFICE_START_DATE  = "03/11/2013 18:13"; 
  var OUTOFOFFICE_END_DATE    = "03/11/2013 19:00";
  
  // This is your Out-Of-Office reply. Keep it less than 120 characters.
  
  var OUTOFOFFICE_TEXT = "I am currently out of the office,
                              with limited access to Twitter. Thanks!";  
   
  // Get your Twitter keys from dev.twitter.com
  
  var CONSUMER_KEY     = "AAA";
  var CONSUMER_SECRET  = "BBB";

  // Change this with your Twitter handle

  var TWITTER_HANDLE   = "labnol"; 
    
  // DO NOT MODIFY ANYTHING AFTER THIS LINE
  
  storeKeys ( CONSUMER_KEY, CONSUMER_SECRET, 
                       OUTOFOFFICE_TEXT, TWITTER_HANDLE );
  
  initialize ( OUTOFOFFICE_START_DATE, OUTOFOFFICE_END_DATE );
  
  // Make sure that Twitter oAuth is working

  doTwitter();
   
}


// Delete exiting Apps Script triggers, if any

function removeTriggers() {

  var triggers = ScriptApp.getScriptTriggers();
  
  for(var i=0; i < triggers.length; i++) {
    ScriptApp.deleteTrigger(triggers[i]);
  }
  
  clearDatabase();

}

function storeKeys(key, secret, text, handle) {
  
  ScriptProperties.setProperty("TWITTER_CONSUMER_KEY",    key);
  ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", secret);
  
  ScriptProperties.setProperty("OUTOFOFFICE_TEXT", text);  
  ScriptProperties.setProperty("MAX_TWITTER_ID",   0);  
  ScriptProperties.setProperty("TWITTER_HANDLE",   handle);  

}

// Clean and Initialize the ScriptDB database

function clearDatabase() {
  
  var db = ScriptDb.getMyDb();
  while (true) {
    
    var result = db.query({}); 
    
    if (result.getSize() == 0) {
      break;
    }
    
    while (result.hasNext()) {
      db.remove(result.next());
    }
  }
}

// Setup triggers for the START and END dates

function initialize(start, end) {
  
  var startDate = new Date(start);
  var endDate   = new Date(end);
  
  removeTriggers();
      
  ScriptApp.newTrigger("autoReply")
           .timeBased()
           .at(startDate)
           .create();
  
  ScriptApp.newTrigger("removeTriggers")
           .timeBased()
           .at(endDate)
           .create();
   
} 

function autoReply() {
  
  clearDatabase();

  ScriptApp.newTrigger("outOfOffice")
           .timeBased()
           .everyMinutes(5)
           .create();

}

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(
                 ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
 oauthConfig.setConsumerSecret(
                 ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
 
}

// This function will poll twitter every 5 minutes for any @mentions

function outOfOffice() {

  oAuth();
  
  var twitter_handle = ScriptProperties.getProperty("TWITTER_HANDLE");
  
  var phrase = "to:" + twitter_handle;
  var search = "https://api.twitter.com/1.1/search/tweets.json?count=10" 
             + "&include_entities=false&result_type=recent&q="
             + encodeString(phrase) + "&since_id=" 
             + ScriptProperties.getProperty("MAX_TWITTER_ID");    

  var options =
  {
    "method": "get",
    "oAuthServiceName":"twitter",
    "oAuthUseToken":"always"
  };
  
  try {

    var result = UrlFetchApp.fetch(search, options);    

    if (result.getResponseCode() === 200) {
      
      var data = Utilities.jsonParse(result.getContentText());
      
      if (data) {
        
        var tweets = data.statuses;
        
        if (tweets.length) {
          
          var db    = ScriptDb.getMyDb();
          var reply = ScriptProperties.getProperty("OUTOFOFFICE_TEXT");
          
          for (var i=tweets.length-1; i>=0; i--) {
            
            var sender = tweets[i].user.screen_name; 
            var found = db.query({user: sender});
            
            if ( ! found.hasNext() ) {
              db.save({user:sender});
              sendTweet(sender, tweets[i].id_str, reply);
            }
          }
        }
      }
    }    
  } catch (e) {
    Logger.log(e.toString());
  }
}

// If an @mention is found, send an Out of Office tweet to that user.

function sendTweet(user, reply_id, tweet) {

  var options =
  {
    "method": "POST",
    "oAuthServiceName":"twitter",
    "oAuthUseToken":"always"    
  };
  
  var text   =  "@" + user + " " + tweet;
  text   =  encodeString(text.substr(0, 140));
  
  var status = "https://api.twitter.com/1.1/statuses/update.json"
             + "?status=" + text + "&in_reply_to_status_id=" + reply_id;
  
  try {
    var result = UrlFetchApp.fetch(status, options);
    ScriptProperties.setProperty("MAX_TWITTER_ID", reply_id);
  }  
  catch (e) {
    Logger.log(e.toString());
  }  
  
}

function doTwitter() {

  oAuth();
  
  var req = "https://api.twitter.com/1.1/application/rate_limit_status.json"; 
      
  var options =
  {
    "method": "get",
    "oAuthServiceName":"twitter",
    "oAuthUseToken":"always"
  };
  
  try {

    var result = UrlFetchApp.fetch(req, options);    
   
  } catch (e) {
    Logger.log(e.toString());
  }
}


function encodeString (q) {
   var str =  encodeURIComponent(q);
   str = str.replace(/!/g,'%21');
   str = str.replace(/\*/g,'%2A');
   str = str.replace(/\(/g,'%28');
   str = str.replace(/\)/g,'%29');
   str = str.replace(/'/g,'%27');
   return str;
}

 
Categories
Code

Parsing the Twitter Trends API

Use the following PHP code to determine all the locations (cities and countries) for which Twitter can offer local trends data

The Twitter API offers the Trends availability data in JSON format that you can parse with the json_decode function of PHP.

";
 }

 function compare_country($a, $b) {
   return strnatcmp($a['country'], $b['country']);
  }
?>