How To Target Photo(s) For a Page Using Graph API? - facebook-graph-api

I need help understanding whether or not this is the intended behavior or if it's something that is not supported. What I want to do is upload a photo to a Facebook page post that is targeted to a specific country.
The steps I take are:
1) Upload the photo to a public album (e.g. Timeline Photos)
2) Retrieve the uploaded photo id from the album
3) Create an attachment to the post with the photo id from step #2
The problem is that I'm now uploading a photo to a public album that is not targeted to a specific country. What I would like to do is to have BOTH the photo(s) and page contents be restricted by targeting. I see a picture parameter in the api, but I believe this is just for setting the page's profile picture.
Any ideas on how this may be accomplished or whether or not this is even possible? Any code examples would also be welcomed.

After playing around with this more I found that I had to set the 'source' parameter to point to a file in my local file system (pointing to a remote file did not work). Not sure if the latter may be accomplished. Also, you have to make a call to setFileUploadSupport with true.
Pseudo code via PHP:
//Create a temporary file somewhere
$contents = ...
$tmpfname = tempnam(sys_get_temp_dir(), $prefix);
$handle = fopen($tmpfname, "w");
fwrite($handle, $contents);
fclose($handle);
//Add to params
$params['source'] = '#' . $tmpfname
$fb = FB_sdk::instance(true);
$fb->setFileUploadSupport(true);
$fb->api('[url to page]/photos', 'POST', $params);

Related

How to get Zomato restaurant ID using restaurant link?

I want to get details of a restaurant in Zomato. I have it's link as the input (https://www.zomato.com/mumbai/fantasy-the-cake-shop-kalyan?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1). By browsing the documentation of Zomato APIs, I didn't found a way to get it.
I tried searching for the restaurant using search API but it returns many results.
Any help will be appreciated
It's a two-step process:
Find out restaurant's city id, in your case, Mumbai's city id through the /cities API. It's a simple query search.
Use the city id from the above API call in the /search API, like, https://developers.zomato.com/api/v2.1/search?entity_type=city&entity_id=3&q=fantasy%20the%20cake%20shop%20kalyan
This would give all the basic information about a restaurant.
View the page's source and search for window.RES_ID
I had the same issue as you described. This Zomato's API approach is at least odd. It's almost immposible to GET any information about restaurant if you don't know res_id in advance and that's not possible to parse since Zomato will deny access.
This worked for me:
Obtain user-key from Zomato API Credentials (https://developers.zomato.com/api)
Search restaurant url via API (https://developers.zomato.com/api/v2.1/search?entity_id=84&entity_type=city&q=RESTAURANT_URL&category=7%2C9). The more specific you will be, the better results you'll get (This url is specified by city to Prague (ID = 84) and categories Daily menus (ID = 7) and Lunch (ID = 9). If there is possibility do specify city, category or cuisine, it helps, but should't be necessary. Don't forget to define GET method in headers.
Loop or filter through json results and search for the wanted url. You might need to use method valueOf() to search for the same url. Be careful, you might need to add "?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1" at the end of your wanted url so it has the same format. Check that through Zomato API Documentation page.
for (i in body.restaurants) {
var url_wanted = restaurant_url + '?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1'
var url_in_json = body.restaurants[i].restaurant.url;
if (url_wanted.valueOf() == url_in_json.valueOf()) {
var restaurant_id = body.restaurants[i].restaurant.id;
}
console.log('Voala! We have res_id:' + restaurant_id);
}
There you have it. It could be easier though.
Hope it helps!
once you have the url of the rseraunt's page you can simply look for a javascript object attribute named "window.RES_ID" and further use it in the api call.

Generating image url using carrierwave in rails

This is somewhat related my question about joins here. By default when I use listing.image.name in my search results view, it does a full query to find the image for every listing in my results array. It even does an extra query just to check if the listing has any images. So to avoid this, I'm adding the following to my Thinking Sphinx query:
#ts_params[:sql][:joins] = "INNER JOIN listing_images ON listing_images.listing_id = listings.id AND listing_images.position = 0"
#ts_params[:sql][:select] = "listings.*, listing_images.image as image_name, listing_images.id as image_id"
This works, however I'm not sure how to generate the full image_url using carrierwave. Previously, where it was doing an extra query per result, I was using listing.image.image_url(:sizename). So, I can find the image name and ID from my join as above, but how to I convert this to a full image url via carrierwave? Is there a built-in method to retrieve the url, that doesn't require an 'image' object?
I tried listing.image_id.image_url(:sizename) but it gave an undefined method error as expected.
From carrierwave's perspective, the answer is obvious:
user.avatar.url
user.avatar.thumbnail.url
Here, user is an instance of a model, and avatar is the field on the model with mount_uploader called on it. In your case this would be something like:
listing_image.image_name.url
listing_image.image_name.thumbnail.url
That probably doesn't work, though, because it looks like you may be loading your listing_image fields into the Listing instead of through includes (or the dreaded N+1 non-eager loads). You may need to resolve your other stackoverflow question before this one will be possible.
Edit:
Per our discussion on your other issue, once you've got a has_one :main_image for just the one ListingImage you want, you're going to use something like #listing.main_image.image_name.url and, if you have a version named "thumbnail", #listing.main_image.image_name.thumbnail.url.
I had the similar issue when I was fetching image using query and wanted to build image url using db field instead of issuing full sql query for each image.
I found out that with couple of field fetched from related image table we can build image which will not run any sql for image if we have three fields id, updated_at and image_name this field should be from the table where image is being saved. It could be from the main table where image is saved as separate column or completely separate table use to specially for image here is a sample code
It can be in your helper or in decorator as per your choice
def logo_url(id, updated_at, name)
return if id.blank? || updated_at.blank? || name.blank?
Company.new(id: id, updated_at: updated_at, logo: name).logo
end
and in view you can call this helper method as
<%= logo_url(company.id, company.updated_at, company.logo).url %>
This way you can have your image with url without executing sql query on each image.

Manage multiple uploads with Flask session

I have a following situation. I created a simple backend in Flask that handles file uploads. With files received, Flask does something (uploads them), and returns the data to the caller. There are two scenarios with the app, to upload one image and multiple images. When uploading one image, I can simply get the response and voila, I'm all set.
However, I am stuck on handling multiple file uploads. I can use the same handler for the actual file upload, but the issue is that all of those files need to be stored into a list or something, then processed, and after doing that, a single link (album) containing all those images, needs to be delivered.
Here is my upload handling code:
#app.route('/uploadv3', methods=['POST'])
def upload():
if request.method == 'POST':
data_file = request.files["file"]
file_name = data_file.filename
path_to_save_to = os.path.join(app.config['UPLOAD_FOLDER'], file_name)
data_file.save(path_to_save_to)
file_url = upload_image_to_image_host(path_to_save_to)
return file_url
I was experimenting with session in flask, but I dont know can I create a list of items under one key, like session['links'], and then get all those, and clear it after doing the work. Or is there some other simpler solution?
I assume that I could probably do this via key for each image, like session["link1"], and so on, but that would impose a limit on the images (depending on how much of those I create), would make the code very ugly, make the iteration over each in order to generate a list that is passed to an album building method problematic, and session clearing would be tedious.
Some code that I wrote for getting the actual link at the end and clearing the session follows (this assume that session['link'] has a list of urls, which I can't really achieve with my knowledge of session management in Flask:
def create_album(images):
session.pop('link', None)
new_album = im.create_album(images)
return new_album.link
#app.route('/get_album_link')
def get_album_link():
return create_album(session['link'])
Thanks in advance for your time!
You can assign anything to a session including individual value or list/dictionary etc. If you know the links, you can store them in the session as follows:
session['links'] = ['link1','link2'...and so on]
This way, you have a list of all the links. You can now access a link by:
if 'links' in session:
for link in session['links']:
print link
Once you are done with them, you can clear the session as:
if 'links' in session:
del session['links']
To clarify what I have done to make this work. At the end, it appeared that the uploading images and adding them to the album anonymously had to be done "reversely", so not adding images to an album object, but uploading an image object to an album id.
I made a method that gets the album link and puts it in the session:
#app.route('/get_album_link')
def get_album_link():
im = pyimgur.Imgur(CLIENT_ID)
new_album = im.create_album()
session.clear()
session['album'] = new_album.deletehash
session['album_link'] = new_album.link
return new_album.link
Later on, when handling uploads, I just add the image to the album and voila, all set :)
uploaded_image = im.upload_image(path_of_saved_image, album=session['album'])
file_url = uploaded_image.link
return file_url
One caveat is that the image should be added to the "deleteahash" value passed as the album value, not the album ID (which is covered by the imgur api documentation).

Graph API: Can I make multi-calls at a same time?

In fact, I want to get the cover photo for each user's albums.
So, first I get the albums data:
$albums = $GLOBALS["facebook"]->api("/me/albums",'GET');
Then I retrieve the cover_photo id and ask API to get details about this photo (such as the source)
foreach($albums as $album) {
$data = $GLOBALS["facebook"]->api("/". $album["cover_photo"], 'GET');
}
But this make a lot of calls to the API (one per album) and it's seems that she doesn't like.. Because my application return a timeout error.
Is there another way to do what I want?
Thanks.
You can always use the Batch API, or just use FQL. Something like the below would retrieve the src of all the album covers of the current user:
SELECT src
FROM photo
WHERE pid IN (
SELECT cover_pid
FROM album
WHERE owner = me()
)
You can try it here. Obviously you can choose any field to retrieve from the photo table.

Amazon Product Advertising API: Get Average Customer Rating

When using Amazon's web service to get any product's information, is there a direct way to get the Average Customer Rating (1-5 stars)? Here are the parameters I'm using:
Service=AWSECommerceService
Version=2011-08-01
Operation=ItemSearch
SearchIndex=Books
Title=A Game of Thrones
ResponseGroup=Large
I would expect it to have a customer rating of 4.5 and total reviews of 2177. But instead I get the following in the response.
<CustomerReviews><IFrameURL>http://www.amazon.com/reviews/iframe?...</IFrameURL></CustomerReviews>
Is there a way to get the overall customer rating, besides for reading the <IFrameURL/> value, making another HTTP request for that page of reviews, and then screen scraping the HTML? That approach is fragile since Amazon could easily change the reviews page structure which would bust my application.
You can scrape from here. Just replace the asin with what you need.
http://www.amazon.com/gp/customer-reviews/widgets/average-customer-review/popover/ref=dpx_acr_pop_?contextId=dpx&asin=B000P0ZSHK
As far as i know, Amazon changed it's API so its not possible anymore to get the reviewrank information. If you check this Link the note sais:
As of November 8, 2010, only the iframe URL is returned in the request
content.
However, testing with the params you used to get the Iframe it seems that now even the Iframe dosn't work anymore. Thus, even in the latest API Reference in the chapter "Motivating Customers to Buy" the part "reviews" is compleatly missing.
However: Since i'm also very interested if its still possible somehow to get the reviewrank information - maybe even not using amazon API but a competitors API to get review rank informations - i'll set up a bounty if anybody can provide something helpful on that. Bounty will be set in this topic in two days.
You can grab the iframe review url and then use css to position it so only the star rating shows. It's not ideal since you're not getting raw data, but it's an easy way to add the rating to your page.
Sample of this in action - http://spamtech.co.uk/positioning-content-inside-an-iframe/
Here is a VBS script that would scrape the rating. Paste the code below to a text file, rename it to Test.vbs and double click to run on Windows.
sAsin = InputBox("What is your ASIN?", "Amazon Standard Identification Number (ASIN)", "B000P0ZSHK")
if sAsin <> "" Then
sHtml = SendData("http://www.amazon.com/gp/customer-reviews/widgets/average-customer-review/popover/ref=dpx_acr_pop_?contextId=dpx&asin=" & sAsin)
sRating = ExtractHtml(sHtml, "<span class=""a-size-base a-color-secondary"">(.*?)<\/span>")
sReviews = ExtractHtml(sHtml, "<a class=""a-size-small a-link-emphasis"".*?>.*?See all(.*?)<\/a>")
MsgBox sRating & vbCrLf & sReviews
End If
Function ExtractHtml(sHtml,sPattern)
Set oRegExp = New RegExp
oRegExp.Pattern = sPattern
oRegExp.IgnoreCase = True
Set oMatch = oRegExp.Execute(sHtml)
If oMatch.Count = 1 Then
ExtractHtml = Trim(oMatch.Item(0).SubMatches(0))
End If
End Function
Function SendData(sUrl)
Dim oHttp 'As XMLHTTP30
Set oHttp = CreateObject("Msxml2.XMLHTTP")
oHttp.open "GET", sUrl, False
oHttp.send
SendData = Replace(oHttp.responseText,vbLf,"")
End Function
Amazon has completely removed support for accessing rating/review information from their API. The docs mention a Response Element in the form of customer rating, but that doesn't work either.
Google shopping using Viewpoints for some reviews and other sources
This is not possible from PAPI. You either need to scrape it by yourself, or you can use other free/cheaper third-party alternatives for that.
We use the amazon-price API from RapidAPI for this, it supports price/rating/review count fetching for up to 1000 products in a single request.