I'm trying to collect tweets from Twitter API V2:
https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
The script I'm using to send the tweet value data to a Google Sheets cell is:
function TwitterTest() {
var string_Screen_name = "1310800524619386880";
var string_Consumer_key = "AAAAAAAAAAAAAAAAAAAAAAAAAA";
var string_Consumer_secret = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
var tokenUrl = "https://api.twitter.com/oauth2/token";
var tokenCredential = Utilities.base64EncodeWebSafe(string_Consumer_key + ":" + string_Consumer_secret);
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;
var apiUrl = "";
var responseApi = "";
var apiOptions = {
headers : {
Authorization: 'Bearer ' + token
},
"method" : "get"
};
var apiUrl = 'https://api.twitter.com/2/users/'+ string_Screen_name +'/tweets?expansions=attachments.poll_ids,attachments.media_keys,author_id,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id&tweet.fields=attachments,author_id,context_annotations,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang,possibly_sensitive,public_metrics,referenced_tweets,reply_settings,source,text,withheld&user.fields=created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,withheld&place.fields=contained_within,country,country_code,full_name,geo,id,name,place_type&poll.fields=duration_minutes,end_datetime,id,options,voting_status&media.fields=duration_ms,height,media_key,preview_image_url,type,url,width,public_metrics,non_public_metrics,organic_metrics,promoted_metrics';
responseApi = UrlFetchApp.fetch(apiUrl, apiOptions);
var obj_data = JSON.parse(responseApi.getContentText());
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tweets").getRange("A3").setValue(obj_data.data);
}
The result obtained:
{attachments={media_keys=[Ljava.lang.Object;#1152e2a4}, entities={urls=[Ljava.lang.Object;#1373921e}, possibly_sensitive=false, conversation_id=1402411015724175370, public_metrics={like_count=1, reply_count=0, quote_count=0, retweet_count=0}, created_at=2021-06-08T23:43:36.000Z, source=Twitter Web App, id=1402411015724175370, text=ALERT: New high roller bet posted!
A parlay bet has been placed for $5,403.62 to win $6,241.18.
To view this bet or copy it https:// t.co /lrBXjHN0At https:// t.co /nBPMsgXI2g, author_id=1310800524619386880, lang=en, reply_settings=everyone}
Specifically in urls the result is:
urls=[Ljava.lang.Object;#1373921e}
The expected result in urls would look something like (example collected from Twitter API V2 website):
In your situation, is the following modification the result you expect?
From:
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tweets").getRange("A3").setValue(obj_data.data);
To:
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tweets").getRange("A3").setValue(JSON.stringify(obj_data.data));
Related
I run script in app script to get data from gate API by GET /spot/orders and work good but, if I change status open to finished return empty.
you can see document from this URL: https://www.gate.io/docs/developers/apiv4/en/#list-orders.
this is code:
function orders() {
const key = "*****";
const secret = "*****";
const host = "https://api.gateio.ws";
const prefix = "/api/v4";
const url = "/spot/orders";
const method = "GET";
const query_param = "currency_pair=BTC_USDT&status=open";
const signature = gen_sign_(key, secret, method, prefix + url, query_param);
const headers = { "Accept": "application/json", "Content-Type": "application/json", "muteHttpExceptions": true, ...signature };
const res = UrlFetchApp.fetch(host + prefix + url + "?" + query_param , { method, headers });
console.log(res.getContentText());
}
This code is work good and give me return of my open orders.
Problem linked by this code:
const query_param = "currency_pair=BTC_USDT&status=open";
If I change status=open to status=finished.
give me return empty just []
note: I have orders buy and sell in this pair.
Instagram Graph API:
https://developers.facebook.com/docs/instagram-api/
Content Publishing:
https://developers.facebook.com/docs/instagram-api/guides/content-publishing/
My code Javascript in Google App Script:
function InstagramPost() {
const id = '123456789';
const image = 'https://www.w3schools.com/images/w3schools_green.jpg';
const text = 'Hello%20World';
const access_token = 'TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST';
const container = 'https://graph.facebook.com/v11.0/' + id + '/media?image_url=' + image + '&caption=' + text + '&access_token=' + access_token;
const response = UrlFetchApp.fetch(container);
const creation = response.getContentText();
Logger.log(creation);
}
The return in my Logger of my container to Post via Instagram API request comes as follows:
{
"data": [
{
"id": "11111111111111111"
},
{
"id": "22222222222222222"
},
{
"id": "33333333333333333"
}
],
"paging": {
"cursors": {
"before": "QWOURQWNGEWRONHWENYWPETGNWQPGNPGNWEPGNWEPGNWEPNGWPENGPWEG",
"after": "WIWEPGNEPBNWE´GNÉ´BNWE´BNWÉBWNEB´WENBNWEBWEBEWBWE"
},
"next": "https://graph.facebook.com/v11.0/11111111111111111/media?access_token=PQWNFWPQINPWNBQPWNBQPWNBPQWNVQWPNVPQWVNPQWPVNQPWNVQPWVNQPWNVPQWNVQPWNVQPWVNQASASLGÇAJKSGLJAAÇSNAÇKNSVÇLKNASBÇANSBÇAS"
}
}
To make the final call for post image it is necessary to use an creation_id=:
const sendinstagram = 'https://graph.facebook.com/v11.0/' + id + '/media_publish?creation_id=' + creation + '&access_token=' + access_token;
UrlFetchApp.fetch(sendinstagram);
If the return from the container is several id in sequence, how do I know which one to define for the call?
Note: I can't loop to try every id because Instagram has a daily limit of 25 calls and posts, so if I did that I would end up with my calls just trying to post a single image.
First, we create IG Container by hitting the endpoint.
POST https://graph.facebook.com/v11.0/{ig-user-id}/media?image_url={image-url}&caption={caption}&access_token={access-token}
Once you have the IG container ID then we again make a POST request to post the Image.
POST https://graph.facebook.com/v11.0/{ig-user-id}/media_publish?creation_id={creation-id}&access_token={access-token}
I think you have to include the version in container and sendinstagram which is v11.0 (latest as if now).
I found the correct way to publish images:
var formData = {
'image_url': image,
'caption': text,
'access_token': access_token
};
var options = {
'method' : 'post',
'payload' : formData
};
const container = 'https://graph.facebook.com/v11.0/' + instagram_business_account + '/media';
const response = UrlFetchApp.fetch(container, options);
const creation = response.getContentText();
var data = JSON.parse(creation);
var creationId = data.id
var formDataPublish = {
'creation_id': creationId,
'access_token': access_token
};
var optionsPublish = {
'method' : 'post',
'payload' : formDataPublish
};
const sendinstagram = 'https://graph.facebook.com/v11.0/' + instagram_business_account + '/media_publish';
UrlFetchApp.fetch(sendinstagram, optionsPublish);
I'm trying to import data from a server, XML format via the server API, which require's a login.
Using information on this question: Cheers MogsDad
I can successful get the external xml file and data shows in the logger.
I cannot for the life of me write any of the info or elements to my spreadsheet. In the link shared, #mogsdad has linked to a parsing XML site. Unfortunately the link is dead. The current code returns an XML file. Normally I would try to use the importxml formula but not had much luck.
Have taken out my coding attempts to parse the XML so code doesn't look awful
has anyone got any pointers on how to parse some of all of the file or know a working URL for the XML parsing doc?
Here is my code so far. Thanks in advance
function importFromXml(){
var url = 'URL HERE'; // Advance search for macs not encrypted.
var username = 'USER HERE';
var password = 'PASSWORD HERE';
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
// Getting "bad request" here - check the username & password
var result = UrlFetchApp.fetch(url, options);
var state=result.getContentText();
// You should check state.getResponseCode()
Logger.log('1: '+state);
Logger.log(parse(state));
}
function parse(txt) {
var doc = Xml.parse(txt, true);
return doc; // Return results
}
**** EDIT ****
After a bit more playing, I have some progress.
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("NoFirevault");
var range = ss.getRange(1, 1);
range.setValue(state);
I managed to write the XML contents to my sheet. Albeit in one cell. When I try to split the data into cells, using the data length and use setValues. It bums out on me, will keep on playing.
**** EDIT *****
After a bit more playing around. I can get XML data written to sheet.
There's 31 entries, with various attributes. But these all get written to a single cell per entry.
Which is an improvement on ALL 31 entries going to a single cell.
In case it helps, here is the XML layout I'm looking at.
I want the computer data, in the computers section.
function importFromJamf(){
var url = 'URL HERE'; // Advance search for macs not encrypted.
var username = 'USER HERE';
var password = 'Password';
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var result = UrlFetchApp.fetch(url, options);
var state = result.getContentText();
var document = XmlService.parse(state);
var entries = document.getRootElement().getChild('computers').getChildren(); // Working but values joined into one row
for (i=0;i<entries.length;i++){
var value = entries[i].getValue();
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getRange(i+1,1).setValue(value);
}
}
function importFromJamf(){
var url = 'url';
var username = 'user';
var password = 'pw';
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var result = UrlFetchApp.fetch(url, options);
var state = result.getContentText();
var document = XmlService.parse(state);
var array= [];
var entries = document.getRootElement().getChild('computers').getChildren('computer');
for(i = 0 ; i < entries.length ; i++){
var a = entries[i].getContent(5).getValue();
var b = entries[i].getContent(8).getValue();
var c = entries[i].getContent(9).getValue();
var d = entries[i].getContent(6).getValue();
var e = entries[i].getContent(11).getValue();
var f = entries[i].getContent(12).getValue();
var g = entries[i].getContent(10).getValue();
var data = [a,b, c,d,e, f,g];
array.push(data);
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
sheet.getRange("A2:Z").clearContent();
var range = sheet.getRange(2,1,array.length, array[0].length);
range.setValues(array);
}
Code above works for what I need, it allows me to grab the values I want into an array I can use to write to a sheet.
.getContent() helped me get the values of y columns of array each loop
But I'm sure there are better ways of going about it.
I am a newbie in coding.
I am trying to create a function in google app script that acts like a dictionary and pulls out the meaning of the word passed as the argument. Its using the API of oxford dictionaries but its not working. Its showing the error 403. "var response = UrlFetchApp.fetch(url,headers);" shows the error.
function Word_meaning(word){
var url="https://odapi.oxforddictionaries.com:443/api/v1/entries/en/" + word + "/regions=us";
var headers =
{
'Accept': 'application/json',
'app_id': 'abc',
'app_key': '123'
};
var response = UrlFetchApp.fetch(url,headers);
var data = JSON.parse(response.getContentText());
Logger.log(data);
}
A couple of things - why do you include the port number in the API call? My API endpoint for querying Oxford Dictionaries looks different. Also, there's a dash in "od-api".
https://od-api.oxforddictionaries.com/api/v1/entries/en/{word_id}/regions={region}
Testing the link in the address bar, I get the expected server response of "Authorization required" while the URL you provided doesn't seem to exist.
Anyway, the error pops up because the optional 'params' object for the UrlFetchApp.fetch(url, params) method is not constructed properly. The "headers" property must be contained within that object. Somewhat ambiguous here, but please read:
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)
I was able to get things up and running using the code below.
function getData(word, region){
var word = word || "leprechaun";
var region = region || "us";
var wordId = encodeURI(word);
var baseUrl = "https://od-api.oxforddictionaries.com/api/v1/entries/en/{word_id}/regions={region}";
var app_id = "app_id";
var app_key = "app_key";
var headers = {
"app_id": app_id,
"app_key": app_key
};
var options = {
"headers": headers,
"muteHttpExceptions": true
};
var url = baseUrl.replace("{word_id}", wordId)
.replace("{region}", region);
var res = UrlFetchApp.fetch(url, options);
var responseCode = res.getResponseCode();
if (responseCode == 200) {
var data = JSON.parse(res.getContentText());
} else {
Logger.log(res.getContentText());
}
}
{"errors":[{"code":32,"message":"Could not authenticate you."}]}
This is what I get when trying to perform a GET users/show request to Twitter. Some background:
User is authenthicated in my Android app through ParseTwitterUtils;
From Android, I call a parse.com Cloud Code function passing in the user token and token secret (looks like bad practice, but for now I'd just like to see this work);
From Cloud Code, I format the auth header using this github library. This is needed as explained here.
You can see some of my code below. Android launch code:
HashMap<String, Object> params = new HashMap<>();
params.put("twitterId", ParseTwitterUtils.getTwitter().getUserId());
params.put("authToken", ParseTwitterUtils.getTwitter().getAuthToken());
params.put("authTokenSecret", ParseTwitterUtils.getTwitter().getAuthTokenSecret());
ParseCloud.callFunctionInBackground("fetchPictureFromTwitter", params, ... );
Cloud code main function:
Parse.Cloud.define("fetchPictureFromTwitter", function(request, response) {
var twitterId = request.params.twitterId;
var authToken = request.params.authToken;
var authTokenSecret = request.params.authTokenSecret;
var url = "https://api.twitter.com/1.1/users/show.json";
Parse.Cloud.httpRequest({
url: url,
followRedirects: true,
headers: {
"Authorization": getOAuthSignature(url,authToken,authTokenSecret)
},
params: {
user_id: twitterId
}
}).then(...)
And lastly here's getOAuthSignature, the function used to sign the request (I took this from the example page in the github link):
var getOAuthSignature = function(url, authToken, authTokenSecret) {
var nonce = OAuth.nonce(32);
var ts = Math.floor(new Date().getTime() / 1000);
var timestamp = ts.toString();
var consumerKey = <MY-APP-CONSUMER-KEY>
var consumerSecret = <MY-APP-CONSUMER-SECRET>
var accessor = {
"consumerSecret": consumerSecret,
"tokenSecret": authTokenSecret
};
var params = {
"oauth_version": "1.0",
"oauth_consumer_key": consumerKey,
"oauth_token": authToken,
"oauth_timestamp": timestamp,
"oauth_nonce": nonce,
"oauth_signature_method": "HMAC-SHA1"
};
var message = {
"method": "GET",
"action": url,
"parameters": params
};
OAuth.SignatureMethod.sign(message, accessor);
var normPar = OAuth.SignatureMethod.normalizeParameters(message.parameters);
var baseString = OAuth.SignatureMethod.getBaseString(message);
var sig = OAuth.getParameter(message.parameters, "oauth_signature") + "=";
var encodedSig = OAuth.percentEncode(sig);
return 'OAuth oauth_consumer_key="'+consumerKey+'", oauth_nonce=' + nonce + ', oauth_signature=' + encodedSig + ', oauth_signature_method="HMAC-SHA1", oauth_timestamp=' + timestamp + ',oauth_token="'+authToken+'", oauth_version="1.0"'
};
What could be wrong? I've spent two days on the matter now and I don't know what to do anymore.
The issue here was that user_id="<user-id> has to be encoded in the request header as well as all the other oauth_* parameters. So I had to change this section:
var params = {
"user_id": twitterId, // <- add here
"oauth_version": "1.0",
"oauth_consumer_key": consumerKey,
"oauth_token": authToken,
"oauth_timestamp": timestamp,
"oauth_nonce": nonce,
"oauth_signature_method": "HMAC-SHA1"
};
And I'm passing the userId from the outer function, like getOAuthSignature(url,twitterId,authToken,authTokenSecret).
As for passing auth token data from device to cloud, this is probably not needed because you can find all the authentication info in the authData field of any ParseUser (as long as it is linked with twitter or Facebook).