3

As the title suggests, my goal here is to be able to send a tweet from a script.gs. The tweet would be posted to my feed, ideally without me having to visit the Twitter website.

I wrote two main functions to attempt this:

script.gs

//post tweet
function oAuth() {
  var CONSUMER_KEY = "**********************";
  var CONSUMER_SECRET = "*************************************************";
  ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", CONSUMER_KEY);
  ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", CONSUMER_SECRET);
  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"));
  var options = {muteHttpExceptions: true,oAuthServiceName:'twitter',oAuthUseToken:'always'}
  var url = "https://api.twitter.com/1.1/statuses/user_timeline.json";
  var response = UrlFetchApp.fetch(url, options).getContentText();
  Logger.log(response);
}
function postTweet() {
  oAuth();
  Logger.log('oAuth complete');
  var status = "Tweet";
  var Roptions = {
    method: "post",
    oAuthServiceName: "twitter",
    oAuthUseToken: "always",
    status: status
  };
  var url = "https://api.twitter.com/1.1/statuses/update.json";
  Logger.log('begin post');
  var request = UrlFetchApp.fetch(url, Roptions); //the trouble line. Execution stops.
  Logger.log('post complete');
}

After about a day of relentless hacking, I was able to get the first function, oAuth() to work. That logs, well, my user data. However, for the life of me, I cannot figure out what is holding up request. I do get this error: Request failed for returned code 403. Truncated server response: {"errors":[{"message":"SSL is required","code":92}]}. Googling this didn't turn up much. I'm guessing that the issue is somewhere in Roptions. Any help would be appreciated, and I can try to provide further clarification if needed.

J148
  • 576
  • 1
  • 4
  • 17
  • SSL is synonymous with HTTPS. Your `url` variable uses HTTP and not HTTPS. I'd try that as the simplest first step. `var url = "https://api.twitter.etc` – Alan Wells Aug 30 '14 at 02:44
  • The Twitter API Documentation uses HTTPS. [Tweet API](https://dev.twitter.com/docs/api/1.1/post/statuses/update) – Alan Wells Aug 30 '14 at 03:03
  • *facepalm* for missing the https. However, I now get the error `Request failed for returned code 403. Truncated server response: {"errors":[{"code":170,"message":"Missing required parameter: status."}]}`. But I have `status` in `Roptions`?? – J148 Aug 30 '14 at 04:46

2 Answers2

6

Eureka! Here's the solution. The irony is that I had had something like this before, but had dismissed it. Turns out https was my biggest problem. I'll feast on humble pie tonight.

script to send tweet

//post tweet
function oAuth() {
  var CONSUMER_KEY = "*************************";
  var CONSUMER_SECRET = "**************************************************";
  ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", CONSUMER_KEY);
  ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", CONSUMER_SECRET);
  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/authenticate");
  oauthConfig.setConsumerKey(ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
  oauthConfig.setConsumerSecret(ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
  var options = {muteHttpExceptions: true,oAuthServiceName:'twitter',oAuthUseToken:'always'}
  var url = "https://api.twitter.com/1.1/statuses/user_timeline.json";
  var response = UrlFetchApp.fetch(url, options).getContentText();
  Logger.log(response);
}
function postTweet() {
  oAuth();
  Logger.log('oAuth complete');
  var status='Test tweet';
  var options = {
    "method": "post",
    "oAuthServiceName": "twitter",
    "oAuthUseToken": "always",
    "payload":{"status":status}
  };
  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');
}

When you register your Twitter app, you have to check the option Allow this application to be used to Sign in with Twitter. This prevents continual Authorize popups. Also, the tweet text CANNOT contain single quotes (').

J148
  • 576
  • 1
  • 4
  • 17
1

@J148, oauthConfig depricated and you can't use it anymore;

Now for twitter you have to use OAuth1 for Apps Script. Migration docs: https://developers.google.com/apps-script/migration/oauth-config?utm_campaign=oauth-appsscript-315&utm_source=gadbc&utm_medium=blog

Sample: https://github.com/googlesamples/apps-script-oauth1/blob/master/samples/Twitter.gs

To make sample working you have to:

  • Add "OAuth1 for Apps Script library" to your script project
  • Declare some stub "Callback URL" in the twitter app's settings
Kirill Vashilo
  • 1,559
  • 1
  • 18
  • 27