I pulled this code from this question.
Applying the author's solution, I am always given this error:
I get my key and secret from my created twitter app here:
I have the app configured to write...
What am I doing wrong?
//post tweet
function oAuth() {
var CONSUMER_KEY = "xxxx";
var CONSUMER_SECRET = "xxxxx";
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='Operational!';
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');
}
I was getting this error also, until I realized you need to specify a 'CallBack URL' in Twitter:
Specifying that as either 'https://script.google.com' or 'https://script.google.com/macros' is allowing me to Authorize. I've tested this and it's currently letting me post with the code that you've listed.
One note however if you try and post the same 'status' text twice, it will throw you the following error:
This isn't an issue as you simply change the value of the variable 'Status', but it threw me the first time.
Related
I am not a developer so I apologize in advance if my question is really basic. I've managed to successfully install this Google script Twitter API integration below and send tweets from a Google sheet (the code was offered here). I simply use =sendTweet(message) in a cell, replacing message with the cell reference of where i have the text for the tweet, for example =sendTweet(C6) and the new Tweet will contain the pre-prepared text in cell C6.
What i'm trying to do is to add to the script the option of sending a tweet in reply to another tweet. Reading on Twitter's API documentation, I understand that the in_reply_to_status_id parameter needs to pass the in_reply_to_status_id in the API call URL but that's as far as my understanding goes.
I don't know how to define this new tweet_id variable and how to get it to pass the in_reply_to_status_id=tweet_id string in the right place so it will function. The ideal would be to use the same formula but with the addition of tweet_id for the reply, as a second variable. For example =sendTweet(message, tweet_id).
Your help would be much appreciated 🙏
// User-level Twitter API request
// Requires the OAuth1 library to be pasted into the script.
// https://developers.google.com/google-ads/scripts/docs/examples/oauth10-library
var CONSUMER_KEY = '************************';
var CONSUMER_SECRET = '************************';
var ACCESS_TOKEN = '************************';
var ACCESS_SECRET = '************************';
/**
* Sends a tweet.
* #param {string} message The message to send.
* #return {?Object} The complex response object with the status of the send
* request. See https://dev.twitter.com/rest/reference/post/statuses/update
* for the structure of this object.
*/
function sendTweet(message) {
if (typeof OAuth1 === 'undefined') {
var libUrl = 'https://developers.google.com/google-ads/scripts/docs/examples/oauth10-library';
throw Error('OAuth1 library not found. Please take a copy of the OAuth1 ' +
'library from ' + libUrl + ' and append to the bottom of this script.');
}
var params = '';
var tweet = message.substring(0, 160);
var options = {method: 'POST', payload: {status: tweet}};
var authUrlFetch = OAuth1.withAccessToken(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET);
var response = authUrlFetch.fetch('https://api.twitter.com/1.1/statuses/update.json', params, options);
var responseText = response.getContentText();
return JSON.parse(responseText);
}
You should be able to
add tweet_id as an argument in your function signature
function sendTweet(message, tweet_id) { }
and then include it in the payload.
var options = {
method: 'POST',
payload: {
status: tweet,
in_reply_to_status_id: tweet_id
}
};
Full code:
// User-level Twitter API request
// Requires the OAuth1 library to be pasted into the script.
// https://developers.google.com/google-ads/scripts/docs/examples/oauth10-library
var CONSUMER_KEY = '************************';
var CONSUMER_SECRET = '************************';
var ACCESS_TOKEN = '************************';
var ACCESS_SECRET = '************************';
/**
* Sends a tweet.
* #param {string} message The message to send.
* #param {string} [tweet_id] - The ID of an existing status that
* the update is in reply to. Note: This parameter will be ignored unless
* the author of the Tweet this parameter references is mentioned within
* the status text. Therefore, you must include #username , where username
* is the author of the referenced Tweet, within the update.
* #return {?Object} The complex response object with the status of the send
* request. See https://dev.twitter.com/rest/reference/post/statuses/update
* for the structure of this object.
*/
function sendTweet(message, tweet_id) {
if (typeof OAuth1 === 'undefined') {
var libUrl = 'https://developers.google.com/google-ads/scripts/docs/examples/oauth10-library';
throw Error('OAuth1 library not found. Please take a copy of the OAuth1 ' +
'library from ' + libUrl + ' and append to the bottom of this script.');
}
var params = '';
var tweet = message.substring(0, 160);
var options = {
method: 'POST',
payload: {
status: tweet,
in_reply_to_status_id: tweet_id
}
};
var authUrlFetch = OAuth1.withAccessToken(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET);
var response = authUrlFetch.fetch('https://api.twitter.com/1.1/statuses/update.json', params, options);
var responseText = response.getContentText();
return JSON.parse(responseText);
}
Full disclaimer, I haven't setup Twitter API access for myself to verify that this works. Please let me know if you have issues.
My objective is to use the upload attachment functionality of the Gmail API. The uploaded file is to be processed within my Gmail add-on. I found the following POST request in this link.
POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=media
Here is my try so far:
function testPOST() {
Logger.log('Testing of POST in Apps script');
// var url = ScriptApp.getService().getUrl();
var url = "https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send"
Logger.log('URL:'+url);
var options =
{
"method" : "POST",
"uploadType" : "media"
};
// Trying to fetch the file
var result = UrlFetchApp.fetch(url, options);
Logger.log('Response code: ' + result.getResponseCode());
// maybe I need to use some function in 'Gmail.Users.*'
}
How can I generate Google oauth2 Access token in Erlang.
I can generate the token in NodejS i. I need it in Erlang as all my rest api code is in Erlang.
Blockquote
var {google} = require('googleapis');
var MESSAGING_SCOPE = "https://www.googleapis.com/auth/firebase.messaging";
var SCOPES = [MESSAGING_SCOPE];
var http = require('http')
function getAccessToken(){
return new Promise(function(resolve, reject){
var key = require("./ServiceAccountKey.json");
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(function(err, tokens){
if(err){
reject(err);
return;
}
resolve(tokens.access_token+" : "+tokens.expiry_date);
});
});
}
var server = http.createServer(function(req, res){
getAccessToken().then(function(access_token){
res.end(access_token);
});
});
server.listen(3000, function(){
console.log("Server started");
});
Tried to generate the Code
URL="https://accounts.google.com/o/oauth2/auth",
Scope="https://www.googleapis.com/auth/firebase.messaging",
GetURL=URL++"?client_id="++ClientId++"&redirect_uri=com.example.app:/oauth2redirect&scope="++Scope++"&response_type=code",
Response = httpc:request(URL),
Response.
Return bad Request
In your code, you're creating a URL with all required query parameters and putting it in the variable GetURL, but then you pass URL, which is just the base URL, to httpc:request. Try passing GetURL instead, and see if that gets you further:
Response = httpc:request(GetURL),
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.
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, 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
I am trying to create a FF AddOn that brings some XML data from a website. But I can't find a way to parse my RESPONSE. First I used DOMParser but I get this error:
ReferenceError: DOMParser is not defined.
Someone suggested to use XMLHttpRequest, because the parsing is done automatically but then I get this other error:
Error: An exception occurred. Traceback (most recent call last):
File
"resource://jid0-a23vmnhgidl8wlymvolsst4ca98-at-jetpack/api-utils/lib/cuddlefish.js",
line 208, in require
let module, manifest = this.manifest[base], requirer = this.modules[base]; TypeError: this.manifest is undefined
I really don't know what else to do. I must note that I am using the AddOn Builder to achieve this.
Below the code that doesn't seem to work.
Option 1:
exports.main = function() {
require("widget").Widget({
id: "widgetID1",
label: "My Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
var Request = require("request").Request;
var goblecontent = Request({
url: "http://www.myexperiment.org/search.xml?query=goble",
onComplete: function (response) {
var parser = new DOMParser();
var xml = parser.parseFromString(response.text, "application/xml");
var packs = xml.getElementsByTagName("packs");
console.log(packs);
}
});
goblecontent.get();
}
});
};
Option 2:
exports.main = function() {
require("widget").Widget({
id: "widgetID1",
label: "My Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
var request = new require("xhr").XMLHttpRequest();
request.open("GET", "http://www.myexperiment.org/search.xml?query=goble", false);
request.send(null);
if (request.status === 200) {
console.log(request.responseText);
}
}
});
};
DOMParser constructor isn't defined in the context of SDK modules. You can still get it using chrome authority however:
var {Cc, Ci} = require("chrome");
var parser = Cc["#mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
nsIDOMParser documentation.
That said, your approach with XMLHttpRequest should work as well. You used the new operator incorrectly however, the way you wrote it a new "require object" is being created. This way it should work however:
var {XMLHttpRequest} = require("xhr");
var request = new XMLHttpRequest();
Please consider using an asynchronous XMLHttpRequest object however, use request.onreadystatechange to attach your listener (the xhr module currently doesn't support other types of listeners or addEventListener).
If you use XMLHttpRequest (available via the xhr module) you can easily avoid the use of DOMParser. Bellow I provide an example supposing request is an XMLHttpRequest object which request is successfully completed:
Instead of:
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(request.responseText, "application/xml");
Use:
var xmlDoc = request.responseXML;
An then you can:
var packs = xmlDoc.getElementsByTagName("packs");
console.log(packs);
Or whatever.