Make a Twitter Auto Reply Bot 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;
}
Amit Agarwal

Amit Agarwal

Google Developer Expert, Google Cloud Champion

Amit Agarwal is a Google Developer Expert in Google Workspace and Google Apps Script. He holds an engineering degree in Computer Science (I.I.T.) and is the first professional blogger in India.

Amit has developed several popular Google add-ons including Mail Merge for Gmail and Document Studio. Read more on Lifehacker and YourStory

Awards & Titles

Digital Inspiration has won several awards since it's launch in 2004.

Google Developer Expert

Google Developer Expert

Google awarded us the Google Developer Expert award recogizing our work in Google Workspace.

ProductHunt Golden Kitty

ProductHunt Golden Kitty

Our Gmail tool won the Lifehack of the Year award at ProductHunt Golden Kitty Awards in 2017.

Microsoft MVP Alumni

Microsoft MVP Alumni

Microsoft awarded us the Most Valuable Professional (MVP) title for 5 years in a row.

Google Cloud Champion

Google Cloud Champion

Google awarded us the Champion Innovator title recognizing our technical skill and expertise.

Email Newsletter

Sign up for our email newsletter to stay up to date.

We will never send any spam emails. Promise.