How to make batch request using fb_graph? - ruby-on-rails

when a user login using facebook then i need collect all the movies list liked by the user and his/her friends.
user = FbGraph::User.fetch('me', :access_token => "access_token")
userFrnd = user.friends
movies=[]
userFrnd.each do | uf |
frnd = FbGraph::User.fetch(uf.raw_attributes['id'], :access_token => "access_token")
movies << frnd.movies
end
final_movie_list = movies.flatten.uniq_by {|track| track.raw_attributes["id"]}
this is my fb_graph function and it's working fine.but i need to make it as batch request since the i have 360 friend it take 360 request to process the above function correctly.but help me out to optimize this and reduce the time it takes to calculate this function.
I came to know that batch request may help me but,i don't know how to do that in fb_graph.
Please help me

I'm using FbGraph from ( github.com/nov/fb_graph ) Version: 2.7.8 and I'm able to make a batch request for 100 users, at a time and get following information about them by default.
I'm not using any access token. So you might be able to get more information including movies.
id
name
first_name
last_name
link
username
gender
locale
Here's the demonstration code where ids is an array of Facebook User Ids:
r = FbGraph::User.fetch("?ids=#{ids.join(",")}")
r.raw_attributes #information about the users hashed by their id (String)

Related

Get list of user id's from a users Twitter followers using Tweepy

I have written the following code to get a list of all the Twitter followers a username has but I would like to just get the user_id instead as this allows me to do a lot more within the rate limit for the API. How do I change this code to just print the user_ids?
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(key, secret)
api = tweepy.API(auth)
screen_name = "twitterusername"
friends = api.friends_ids(screen_name)
print(screen_name + " is following :")
for friend in friends:
print(api.get_user(friend).screen_name)
I have all of the correct authorisation keys and tokens.
The User object has an id field
print(screen_name + " is following :")
for friend in friends:
print(api.get_user(friend).id)
If you are interested in the IDs only of the users be aware that api.friends_ids returns already a list of IDs
friends = api.friends_ids('screen_name')
logging.info(friends)
# output: [324343434, 134343234567,...]

Direct link to Twitter retweet

I am working on a Twitter app and I want to find a way to link directly to a retweet.
For example. If user A makes a tweet, and user B retweets it, I want a URL that will take us to user B's profile where the retweet is displayed. What is that unique URL?
I recently needed to get a link to an arbitrary retweet that was too old for the search feature to work.
Here's what I did:
Open the Network Monitor
Visit the timeline of the retweeter
Scroll until you find the retweet
Look at the Network Monitor, open the latest request to the endpoint /UserTweets
Either
go to the "Response" tab and sift through its JSON manually to get the id_str to craft the URL:
or, paste the following into the Console, then right-click on the response, “Copy…Response”, and return to the console to press Enter:
UserTweets = JSON.parse(prompt("Paste the copied Response data:"));
// get the output from that endpoint,
UserTweets
// dig through the packaging,
['data']['user']['result']['timeline_v2']['timeline']['instructions']
// filter out "pinned tweets" metadata,
.filter(cmd => cmd['type'] == "TimelineAddEntries")
// de-batch,
.flatmap(cmd => cmd['entries'])
// filter out "cursor" metadata,
.filter(entry => entry['content']['entryType'] == "TimelineTimelineItem" )
// then dig through a bunch more layers of packaging,
.map(entry => entry['content']['itemContent']['tweet_results']['result'])
// munge the tweets into a more-usable format,
.map(tweet => ({user: tweet['core']['user_results']['legacy'], tweet: tweet['legacy']}))
// filter out non-retweets,
.filter(({tweet}) => tweet['retweeted_status_result'])
// extract just the RT text and URL of the retweet itself,
.map(({user, tweet}) => ({url: `https://twitter.com/${encodeURIComponent(user['screen_name'])}/status/${encodeURIComponent(tweet['id_str'])}`, text: tweet['full_text']}))
// print results.
.forEach(({url, text}) => console.log(url, text))
…et voilà:
https://twitter.com/ThePSF/status/1398372497741946884
Internally, all Retweets are simply special Tweets. This means each Retweet also has an ID (which is stored on id and id_str at the root of the Tweet object). For proof, here's a Retweet from the Twitter Retweets account.
If you're using Tweet Streams (e.g. statuses/filter), you'll be able to pick up this ID from the returned Tweet object of the retweet. From the ID, you can just build a normal Twitter link with https://twitter.com/<username>/status/<retweet id>. Assuming your Retweet object is named retweet, the correct link would be (in JavaScript) `https://twitter.com/${retweet.user.screen_name}/status/${retweet.id_str}`.
If the Retweet is fairly recent, you can do a status search (search/tweets) on the user's profile (i.e. you have to set the q parameter to from:<username>) to find the Retweet. You'll most likely have to cross check the ID of the Tweet you want and the ID of the Retweet you're looking for to be sure, though.
If you're trying to get the Retweet ID of an old Tweet, however, you might have to use Twitter's Premium APIs, which are paid.
JamesTheAwesomeDude's answer worked for me with some light modifications for the new twitter API:
UserTweets = { /*PASTE HERE*/ }
// .timeline changed to .timeline_v2
UserTweets.data.user.result.timeline_v2.timeline.instructions
.filter(cmd => cmd['type'] == "TimelineAddEntries")
.map(cmd => cmd['entries']).flat()
.filter(entry => entry['content']['entryType'] == "TimelineTimelineItem" )
.map(entry => entry['content']['itemContent']['tweet_results']['result'])
// .user changed to .user_results.result
.map(tweet => [tweet['core']['user_results']['result']['legacy'], tweet['legacy']])
.filter(([user, tweet]) => tweet['retweeted_status_result'])
.map(([user, tweet]) => [`https://twitter.com/${user['screen_name']}/status/${tweet['id_str']}`, tweet['full_text']])
.forEach(([url, rt_text]) => console.log(url, rt_text))

Tweepy user_search api is very slow

After two days of unsuccessful attempt to use twitter gem I have decided to use tweepy of python for a task. (My original attempt was with ruby and I posted the question here)
My task is to collect all those actresses who have a verified account on twitter. I have taken the list of actresses from wikipedia.
Everything looks fine till now. I have started hitting twitter REST api with each name and I check whether it is a verified account or not.
The only problem I have is that the response is very slow. It takes about 12-15 seconds for every request. Am I doing something wrong here or is it how it is suppose to be.
Below is my code in its entirety :
import tweepy
consumer_key = 'xxx'
consumer_secret = 'xxx'
access_token_key = 'xx-xx'
access_token_secret = 'xxx'
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token_key, access_token_secret)
api = tweepy.API(auth)
actresses = []
f = open('final','r')
for line in f:
actresses.append(line)
f.close()
print actresses
for actress in actresses:
print actress
users = api.search_users(actress)
for u in users:
if u.verified == True and u.name == actress:
print u.name + " === https://twitter.com/" + u.screen_name
Also is there any better way to extract the verified actresses using that list?
Unfortunately, there is no faster way to do it, given that you only know the actresses' full names, and not their screen names. Each request will take a long time, as Twitter needs to return the results of users matching the query (there may be quite a few). Each one needs to be loaded and examined, which can take a while, depending on how many results were returned.

Koala - get number of likes for a post

I'm facing an issue using Koala 1.7.0rc1 and the new Facebook graph api. I'm trying to retrieve number of likes for a post using this request [object_id]/likes?summary=1. This query works in Facebook Graph Explorer but I cannot access 'summary' using Koala :
likes = graph.get_object("5718732097_10151698726822098", summary: 1){|data| data['likes']}
# OR
likes = graph.get_object("5718732097_10151698726822098/likes?summary=1")
You should do:
graph.get_object(your_post_id, :fields => "likes.summary(true)")
The api documentation that Facebook gave is kind of misleading here:
https://developers.facebook.com/docs/reference/api/post/
It says summary = 1 which should be summary = true in rails
You'll need to get the summary data from the raw response in Koala, like so:
likes = graph.get_object("5718732097_10151698726822098/likes?summary=1").
raw_response["summary"]["total_count"]

Replies to a particular tweet, Twitter API

Is there a way in the Twitter API to get the replies to a particular tweet? Thanks
Here is the procedure to get the replies for a tweets
when you fetch the tweet store the tweetId ie., id_str
using twitter search api do the following query
[q="to:$tweeterusername", sinceId = $tweetId]
Loop all the results , the results matching the in_reply_to_status_id_str to $tweetid is the replies for the post.
From what I understand, there's not a way to do that directly (at least not now). Seems like something that should be added. They recently added some 'retweet' capabilities, seem logical to add this as well.
Here's one possible way to do this, first sample tweet data (from status/show):
<status>
<created_at>Tue Apr 07 22:52:51 +0000 2009</created_at>
<id>1472669360</id>
<text>At least I can get your humor through tweets. RT #abdur: I don't mean this in a bad way, but genetically speaking your a cul-de-sac.</text>
<source>TweetDeck</source>
<truncated>false</truncated>
<in_reply_to_status_id></in_reply_to_status_id>
<in_reply_to_user_id></in_reply_to_user_id>
<favorited>false</favorited>
<in_reply_to_screen_name></in_reply_to_screen_name>
<user>
<id>1401881</id>
...
From status/show you can find the user's id. Then statuses/mentions_timeline will return a list of status for a user. Just parse that return looking for a in_reply_to_status_id matching the original tweet's id.
The Twitter API v2 supports this now using a conversation_id field. You can read more in the docs.
First, request the conversation_id field of the tweet.
https://api.twitter.com/2/tweets?ids=1225917697675886593&tweet.fields=conversation_id
Second, then search tweets using the conversation_id as the query.
https://api.twitter.com/2/tweets/search/recent?query=conversation_id:1225912275971657728
This is a minimal example, so you should add other fields as you need to the URL.
Twitter has an undocumented api called related_results. It will give you replies for the specified tweet id. Not sure how reliable it is as its experimental, however this is the same api call that is called on twitter web.
Use at your own risk. :)
https://api.twitter.com/1/related_results/show/172019363942117377.json?include_entities=1
For more info, check out this discussion on dev.twitter:
https://dev.twitter.com/discussions/293
Here is my solution. It utilizes Abraham's Twitter Oauth PHP library: https://github.com/abraham/twitteroauth
It requires you to know the Twitter user's screen_name attribute as well as the id_str attribute of the tweet in question. This way, you can get an arbitrary conversation feed from any arbitrary user's tweet:
*UPDATE: Refreshed code to reflect object access vs array access:
function get_conversation($id_str, $screen_name, $return_type = 'json', $count = 100, $result_type = 'mixed', $include_entities = true) {
$params = array(
'q' => 'to:' . $screen_name, // no need to urlencode this!
'count' => $count,
'result_type' => $result_type,
'include_entities' => $include_entities,
'since_id' => $id_str
);
$feed = $connection->get('search/tweets', $params);
$comments = array();
for ($index = 0; $index < count($feed->statuses); $index++) {
if ($feed->statuses[$index]->in_reply_to_status_id_str == $id_str) {
array_push($comments, $feed->statuses[$index]);
}
}
switch ($return_type) {
case 'array':
return $comments;
break;
case 'json':
default:
return json_encode($comments);
break;
}
}
Here I am sharing simple R code to fetch reply of specific tweet
userName = "SrBachchan"
##fetch tweets from #userName timeline
tweets = userTimeline(userName,n = 1)
## converting tweets list to DataFrame
tweets <- twListToDF(tweets)
## building queryString to fetch retweets
queryString = paste0("to:",userName)
## retrieving tweet ID for which reply is to be fetched
Id = tweets[1,"id"]
## fetching all the reply to userName
rply = searchTwitter(queryString, sinceID = Id)
rply = twListToDF(rply)
## eliminate all the reply other then reply to required tweet Id
rply = rply[!rply$replyToSID > Id,]
rply = rply[!rply$replyToSID < Id,]
rply = rply[complete.cases(rply[,"replyToSID"]),]
## now rply DataFrame contains all the required replies.
You can use twarc package in python to collect all the replies to a tweet.
twarc replies 824077910927691778 > replies.jsonl
Also, it is possible to collect all the reply chains (replies to the replies) to a tweet using command below:
twarc replies 824077910927691778 --recursive
Not in an easy pragmatic way. There is an feature request in for it:
http://code.google.com/p/twitter-api/issues/detail?id=142
There are a couple of third-party websites that provide APIs but they often miss statuses.
I've implemented this in the following way:
1) statuses/update returns id of the last status (if include_entities is true)
2) Then you can request statuses/mentions and filter the result by in_reply_to_status_id. The latter should be equal to the particular id from step 1
As states satheesh it works great. Here is REST API code what I used
ini_set('display_errors', 1);
require_once('TwitterAPIExchange.php');
/** Set access tokens here - see: https://dev.twitter.com/apps/ **/
$settings = array(
'oauth_access_token' => "xxxx",
'oauth_access_token_secret' => "xxxx",
'consumer_key' => "xxxx",
'consumer_secret' => "xxxx"
);
// Your specific requirements
$url = 'https://api.twitter.com/1.1/search/tweets.json';
$requestMethod = 'GET';
$getfield = '?q=to:screen_name&sinceId=twitter_id';
// Perform the request
$twitter = new TwitterAPIExchange($settings);
$b = $twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest();
$arr = json_decode($b,TRUE);
echo "Replies <pre>";
print_r($arr);
die;
I came across the same issue a few months ago at work, as I was previously using their related_tweets endpoint in REST V1.
So I had to create a workaround, which I have documented here:
http://adriancrepaz.com/twitter_conversations_api Mirror - Github fork
This class should do exactly what you want.
It scrapes the HTML of the mobile site, and parses a conversation. I've used it for a while and it seems very reliable.
To fetch a conversation...
Request
<?php
require_once 'acTwitterConversation.php';
$twitter = new acTwitterConversation;
$conversation = $twitter->fetchConversion(324215761998594048);
print_r($conversation);
?>
Response
Array
(
[error] => false
[tweets] => Array
(
[0] => Array
(
[id] => 324214451756728320
[state] => before
[username] => facebook
[name] => Facebook
[content] => Facebook for iOS v6.0 ? Now with chat heads and stickers in private messages, and a more beautiful News Feed on iPad itunes.apple.com/us/app/faceboo?
[date] => 16 Apr
[images] => Array
(
[thumbnail] => https://pbs.twimg.com/profile_images/3513354941/24aaffa670e634a7da9a087bfa83abe6_normal.png
[large] => https://pbs.twimg.com/profile_images/3513354941/24aaffa670e634a7da9a087bfa83abe6.png
)
)
[1] => Array
(
[id] => 324214861728989184
[state] => before
[username] => michaelschultz
[name] => Michael Schultz
[content] => #facebook good April Fools joke Facebook?.chat hasn?t changed. No new features.
[date] => 16 Apr
[images] => Array
(
[thumbnail] => https://pbs.twimg.com/profile_images/414193649073668096/dbIUerA8_normal.jpeg
[large] => https://pbs.twimg.com/profile_images/414193649073668096/dbIUerA8.jpeg
)
)
....
)
)
since statuses/mentions_timeline will return the 20 most recent mention this won't be that efficient to call, and it has limitations like 75 requests per window (15min) , insted of this we can use user_timeline
the best way: 1. get the screen_name or user_id parameters From status/show.
2. now use user_timeline
GET https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=screen_name&count=count
(screen_name== name which we got From status/show)
(count== 1 to max 200)
count: Specifies the number of Tweets to try and retrieve, up to a maximum of 200 per distinct request.
from the result Just parse that return looking for an in_reply_to_status_id matching the original tweet's id.
Obviously, it's not ideal, but it will work.
If you need all replies related to one user for ANY DATE RANGE, and you only need to do it once (like for downloading your stuff), it is doable.
Make a Twitter development application
Apply for elevated credentials. You will instantly get them after filling out the forms. At least I did on two separate accounts today.
Your development account now has access to the v1.1 API search in the "Sandbox" tier. You get 50 requests against the tweets/search/fullarchive endpoint maxing out at 5000 returned tweets.
Make an environment for your development application.
Make a script to query https://api.twitter.com/1.1/tweets/search/fullarchive/<env name>.json where <env name> is the name of your environment. Make your query to:your_twitter_username and fromDate when you created your account, toDate today.
Iterate over the results
This will not get your replies recursively

Resources