Using the facebook batch api to post the same photo to multiple facebook pages - facebook

So here is what I'm trying to do. I'm trying to use the facebook batch api to post a single photo to multiple facebook pages at the same time. I first put everything into an array (fb_batch) then encode it using JSON. This method works just fine for posting messages and links. In the example below the #pages array is an array of facebook pages that contains the facebook page information including a valid access token. I know the access token is valid because elsewhere in the program I can post an individual photo using this same access token.
fb_batch = []
top_access_token = nil
#pages.each do |page|
top_access_token = page.access_token if top_access_token.nil?
if image.nil?
fb_batch << {method: 'POST', relative_url: 'me/feed?access_token=' + page.access_token, body: body}
else
fb_batch << {method: 'POST', relative_url: 'me/photos?access_token=' + page.access_token, body: body, attached_files: 'file1'}
end
end
c = Curl::Easy.new('https://graph.facebook.com')
c.multipart_form_post = true
c.verbose = true
post_data = [Curl::PostField.content('access_token', top_access_token), Curl::PostField.content('batch', fb_batch.to_json)]
post_data << Curl::PostField.file('file1', image.image.current_path) if !image.nil?
c.http_post(post_data)
Notice how I only add the file if there is an image. So this same code works for when I'm posting messages or links to multiple accounts.
The error comes when I post an image to multiple accounts. It will apply the image to the first account an the fb_batch array, but all the other accounts have an error. Do I have to attach the image separately for each account I wish to post the photo to each image having a different attached_file name? To me this means that the request would be huge since I would potentially have to attach the same image 50 times if I was posting to 50 accounts.
Here is the response I get from facebook:
[{"code":200,"headers":[{"name":"Access-Control-Allow-Origin","value":"*"},{"name":"Cache-Control","value":"private, no-cache, no-store, must-revalidate"},{"name":"Connection","value":"close"},{"name":"Content-Type","value":"text/javascript; charset=UTF-8"},{"name":"Expires","value":"Sat, 01 Jan 2000 00:00:00 GMT"},{"name":"Pragma","value":"no-cache"}],"body":"{\"id\":\"416193168426655\",\"post_id\":\"159594100753231_416193185093320\"}"},{"code":400,"headers":[{"name":"Access-Control-Allow-Origin","value":"*"},{"name":"Cache-Control","value":"no-store"},{"name":"Connection","value":"close"},{"name":"Content-Type","value":"text/javascript; charset=UTF-8"},{"name":"Expires","value":"Sat, 01 Jan 2000 00:00:00 GMT"},{"name":"Pragma","value":"no-cache"},{"name":"WWW-Authenticate","value":"OAuth \"Facebook Platform\" \"invalid_request\" \"(#1) An unknown error occurred\""}],"body":"{\"error\":{\"message\":\"(#1) An unknown error occurred\",\"type\":\"OAuthException\",\"code\":1}}"}]
Sorry it is messy. You can see that the first code is 200 which posts the image successfully and returns the image ID. The second code is a 400 saying An unknown error occurred. I assume this means that it couldn't find the image or something of that sort. If I switch the two accounts around in the array then it will post successfully to the other account and will fail on the account that just succeeded.
Thanks for reading all the way to the end! Here is your pot of gold...

My answer somewhat skates around debugging your problem and offers a possible alternative. Back last year, Facebook launched the ability to upload photos by supplying a source URL instead of having to supply multipart data. Therefore, I recommend the following workaround:
Upload the image you want to use to somewhere outside of the Facebook CDN (there can be issues using CDN media to upload to Facebook)
Grab the URL of said image
Instead of making the call you are currently, simplify it to PAGEID/photos?access_token=PAGETOKEN&url=URLOFPHOTO
This will post the photo directly to the Page's Timeline. Batching that call should not make any difference. Hope this helps!

Related

Facebook Graph API only returning 15 photos with no pagination options

I'm trying to download all of the photos that I've been tagged in from facebook.
https://graph.facebook.com/me/photos?access_token=blah
Returns a data[] with 15 pictures and a paging object:
'paging':
{
'cursors':
{
'after': 'afterHash',
'before': 'beforeHash'
}
}
I expected to see next and previous urls in paging to get at more photos.
Calling: https://graph.facebook.com/me/photos?access_token=blah&type=tagged&after=afterHash returns an empty data[]
Adding &limit=14 to the request returns 14 pictures and the next url that I would expect. Getting that next url only returns 1 picture though, for a total of 15 again.
Further details on the pictures being returned by the api call:
Created Times range from 2013-08-25 to 2015-10-10
5 photos uploaded by friends and tagged, 10 uploaded by myself.
When I look at "/Photos/Photos of You" from my profile page I see many more pictures than are being returned by the API (50+ for 2015, hundreds in years before that). The 15 that are being returned are a mixture of pictures that I have uploaded and those uploaded by friends who then tagged me.
By default reading from the photos edge includes all photos a person has been tagged in.
Required Permission : user_photos
Referance: https://developers.facebook.com/docs/graph-api/reference/user/photos
You can make following API Call. Because no one tagged in 999,999,999,999,999 Photos.
https://graph.facebook.com/me/photos?fields=images{source}&limit=999999999999999&access_token=xxxxx
You can retrieve all photos which was allowed on Timeline. You can see those from here:
https://www.facebook.com/your_username_or_id/photos_of
Here is the sample php code which will get source for all photos using curl:
<?php
$curl = curl_init();
curl_setopt_array($curl,array(
CURLOPT_RETURNTRANSFER =>1,
CURLOPT_URL => 'https://graph.facebook.com/me/photos?fields=images{source}&limit=999999999999999&access_token=xxxxx',
CURLOPT_SSL_VERIFYPEER => false
));
$array = json_decode(curl_exec($curl),true);
curl_close($curl);
for( $i = 0; $i<count($array['data']);$i++)
{
echo $array['data'][$i]['images'][0]['source']."</br>";
}
?>
First of all was your access token requested with the user_photos permission?
Also, as taken from https://developers.facebook.com/docs/graph-api/reference/photo:
A user access token may read a photo that user is tagged in if they
have granted the user_photos or user_posts permission. However, in
some cases the photo's owner's privacy settings may not allow your
application to access it.
Most likely though, you need to ask for all albums (via https://graph.facebook.com/me/albums?access_token=blah) and then in turn ask each of these for all the photos. The 15 photos you are retrieving are the photos from the first ever album created as mentioned in Get all photos of a page using Facebook API
Try it out here: https://developers.facebook.com/tools/explorer/?method=GET&path=me%2Falbums&version=v2.5

FB API returning blank for /statuses while result is in /feed

I'm trying to get all the data the logged-in user / one of his friends posted on FB.
I'm currently doing three different calls to:
/<username I want data for>/links
/<username I want data for>/photos/uploaded
/<username I want data for>/statuses
This works just fine for many users. However, some users are returning an empty result ({
"data": [
]
}). When trying to debug I'm noticing that a call to /username/feed is returning results which some of them are links / photos / statuses.
How can this be? Am I calling the wrong endpoints?
This is the relevant API page FB User Object
you are getting data for your account. Please try to reproduce the same on different browser.
(check the same thing on IE)

Get user profile picture by Id

I'm now working on a web application which is mostly based of facebook graph api.
I hold some data about users - actually , the possible public data available - such as name and id.
I also know that a profile picture is a part of the public data, and I wondered how I'll be able to get a direct link to a profile picture of a user only by using their id?
http://graph.facebook.com/" + facebookId + "/picture?type=square
For instance:
http://graph.facebook.com/67563683055/picture?type=square
There are also more sizes besides "square". See the docs.
Update September 2020
As Facebook have updated their docs this method is not working anymore without a token. You need to append some kind of access_token. You can find further information and how to do it correctly in the fb docs to the graph api of user picture
Requirements Change
This endpoint supports App-Scoped User IDs (ASID), User IDs (UID), and Page-Scoped User IDs (PSID). Currently you can query ASIDs and UIDs with no requirements. However, beginning October 24, 2020, an access token will be required for all UID-based queries. If you query a UID and thus must include a token:
use a User access token for Facebook Login authenticated requests
use a Page access token for page-scoped requests
use an App access token for server-side requests
use a Client access token for mobile or web client-side requests
Quote of fb docs
You can use following urls to obtain different sizes of profile images.
Please make sure to add Facebook id to url.
Large size photo
https://graph.facebook.com/{facebookId}/picture?type=large
Medium size photo
https://graph.facebook.com/{facebookId}/picture?type=normal
Small size photo
https://graph.facebook.com/{facebookId}/picture?type=small
Square photo
https://graph.facebook.com/{facebookId}/picture?type=square
To get largest size of the image
https://graph.facebook.com/{userID}?fields=picture.width(720).height(720)
or anything else you need as size. Based on experience, type=large is not the largest result you can obtain.
From the Graph API documentation.
/OBJECT_ID/picture returns a redirect to the object's picture (in this case the users)
/OBJECT_ID/?fields=picture returns the picture's URL
Examples:
<img src="https://graph.facebook.com/4/picture"/> uses a HTTP 301 redirect to Zuck's profile picture
https://graph.facebook.com/4?fields=picture returns the URL itself
This will be helpful link:
http://graph.facebook.com/893914824028397/picture?type=large&redirect=true&width=500&height=500
You can set height and width as you needed
893914824028397 is facebookid
UPDATE September 2020
Facebook has new requirements change: an access token will be required for all UID-based queries
So you have to add your app access token to the url:
https://graph.facebook.com/{profile_id}/picture?type=large&access_token={app_access_token}
To get your app_access_token use the following url:
https://graph.facebook.com/oauth/access_token?client_id={your-app-id}&client_secret={your-app-secret}&grant_type=client_credentials
You find your-app-id and your-app-secret in the Basic Settings of your Facebook app in Facebook developers
https://www.avatars.io/
It's an API that returns the profile image when given a username for a variety of social networks including Twitter, Facebook, Instagram, and gravatar. It has libraries for iOS, Android, Ruby, Node, PHP, Python, and JavaScript.
you can get it with using this url : you will get the picture HD (max size)
https://graph.facebook.com/{userID}?fields=picture.width(720).height(720)&redirect=false
don't forget redirect=false or it will return an error
Use url as:https://graph.facebook.com/user_id/picture?type=square in src of img tag.
type may be small,large.
You can use AngularJs for this, Its two -way data binding feature will get solution with minimum effort and less code.
<div>
<input type="text" name="" ng-model="fbid"><br/>
<img src="https://graph.facebook.com/{{fbid}}/picture?type=normal">
</div>
I hope this answers your query.Note: You can use other library as well.
Through the Javascript SDK (v2.12 - April, 2017) you can get the details of the picture request this way:
FB.api("/" + uid + "/picture?redirect=0", function (response) {
console.log(response);
// prints the following:
//data: {
// height: 50
// is_silhouette: false
// url: "https://lookaside.facebook.com/platform/profilepic/?asid=…&height=50&width=50&ext=…&hash…"
// width: 50
//}
if (response && !response.error) {
// change the src attribute of img elements
[...document.getElementsByClassName('fb-user-img')].forEach(
i => i.src = response.data.url
);
// OR redirect to the URL above
location.assign(response.data.url);
}
});
For getting the JSON response the parameter redirect with 0 (zero) as value is important since the request redirects to the image by default. You may still add other parameters in the same URL. Examples:
"/" + uid + "/picture?redirect=0&width=100&height=100": a 100x100 image will be returned;
"/" + uid + "/picture?redirect=0&type=large": a 200x200 image is returned. Other possible type values include: small, normal, album, and square.
As per the current latest Facebook API version 3.2, For users you can use this generic method for getting profile picture is https://graph.facebook.com/v3.2/{user-id}/picture?type=square you can visit documentation for user picture here.
The possible values for type parameter in URL can be small, normal, album, large, square
For Groups and Pages, the profile picture is not available directly. You have to get them using access token. For Groups you have to use User Access Token and for Pages you can use both User Access Token and Page Access Token.
You can get Group's or Page's Profile Picture using the generic URL: https://graph.facebook.com/v3.2/{user-id}/picture?access_token={access-token}&type=square
I hope this is helpful for people who are looking for Page or Group Profile picture.
Simply Follow as below URL
https://graph.facebook.com/facebook_user_id/picture?type=square
type may be normal,small,medium,large. Or square (f you want to get square picture, the square size is limited to 50x50).
today I found a problem, the profile images was returning the default profile picture because a new requirement from Facebook to all the UID based queries, so just add &access_token=[apptoken] to the url, you can obtain your app token from here
You can use the following endpoint to get the image.jfif instead of jpg:
https://graph.facebook.com/v3.2/{user-id}/picture
Note that you won't be able to see the image, only download it.
Update July 2021
On top of answer by #EddyG, turned out that if you still not able to fetch the profile picture with app access token, the FB account must "allow" the FB app first then you should be able to fetch the profile picture with FB app access token.

cannot get image info using https://graph.facebook.com/<photo_id>

The API always return false, without any detailed information.
Then same even when using the photo IDs of my own photos.
However, the photo ID listed in the API document (the Coca Cola one) works without problems...
Your call to FB is correct i.e.
https://graph.facebook.com/PHOTO_ID + accesstoken
will return a JSON response with info about your image and urls to download the image in different sizes.
Most likely reason for your problem is you haven't requested the "user_photos" permission from the app user.

How to share Amazon authenticated URL when posting to the wall using Facebook Graph API?

I am trying to create a Facebook wall post using Facebook Graph API. The payload is:
{ :message => 'I just uploaded image',
:picture => 'http://s3.amazonaws.com/picyou-andrey-development/images/GejoFV/GejoFV.png?AWSAccessKeyId=AKIAI6ANFCV7RKOBGGBA&Signature=U0Bd2bMQ3Pai%2BAblVOimSOVcbzk%3D&Expires=1308771841',
:link => 'http://google.com',
:name => 'Test Post' }
The post is created properly but the problem in picture which does not displays at all.
When I was using public Amazon S3 URLs like http://s3.amazonaws.com/picyou-andrey-development/images/GejoFV/GejoFV.png picture was displayed correctly.
Any chance to use dynamic URLs as a 'picture' param with Facebook?
Thanks in advance.
Update:
Found a guy on the Facebook developer forum with exactly the same problem:
http://forum.developers.facebook.net/viewtopic.php?pid=302856
Could it be that the signature part of the url has some chararcters in it that have special meaning in urls - %2B (+) and %3D (=)?
I have run into a problem with these urls in some video players and solved it by making sure that the url doesn't have any of those characters. You can do this by generating the url in a loop and adding a second onto the expiry time everytime to ensure the signature changes. Repeat until the signature is 'valid'
psuedocode:
loop
expiry = expiry + 1 second
create url with expiry
until url is valid
In my experience it only takes an iteration or two for the url to be valid.