Facebook Graph API get page post's attachments - json

I am trying to get the url of an image attachment published by a facebook page. The goal is to embed that image in a webpage in order for the website to always display the last image attachment published by the page. I own both website and FB page.
I have yet not grasped all the details on handling Facebook Graph API, but here is what I did so far:
1) in FB developers website, I have created an application, getting its App ID and secret;
2) I used that information to get an access token (just pasted in my browser the following code:
https://graph.facebook.com/oauth/access_token?client_id={my-client-id}&client_secret={my-client-secret}&grant_type=client_credentials
3) in my website, I have loaded Facebook JS SDK after the body tag; and got also my Facebook page ID from Facebook Page administration;
4) now the real question begins: how can I query Facebook to get the information that I need – the source url of the last published image?
The best result I have gotten so far was by making a getJSON call with the help of jQuery:
var fbfeed = $j.getJSON('https://graph.facebook.com/{my-page-id}/feed?access_token={my-token}&fields=attachments&limit=1');
This will get and store a JSON array in the fbfeed variable (please correct me if I'm wrong). One of the keys of that array is called "src" which contains the source url of the attachment – the information I need to embed that picture in my website;
I have the following problems / concerns:
- I have not found the way to retrieve the value of the "url" key – how can I do that? How can I parse the fbfeed variable and extract the value of the "url" key?
– I have concerns with my usage of the access token:
is it problematic to expose the access token in this way, by using it in a jQuery function? Is it a security risk? If so, can I "mimic" this request but using a server side language such as PHP?
Will this access token expire (i.e. will I need to repeat step 2 from time to time?). So, imagining that I can get this to work, will I need from time to time to "refresh" the access token?
Thanks for your help.

I have managed to get the information I needed using server-side code, although it may not be the most "clean solution": it will iterate through the last 5 posts of my page until it finds an image and a post url:
<?php
$url = 'https://graph.facebook.com/{page-id}/feed?access_token={access-token}&fields=attachments,link&limit=5';
$json = file_get_contents($url);
$json_data = json_decode($json, true);
for($count = 0; $count < 5; $count++) {
$imagesource = $json_data['data'][$count]['attachments']['data'][0]['media']['image']['src']; // gets the image url
$postlink = $json_data['data'][$count]['link']; // gets the post url
if (isset($imagesource) && isset($postlink)) {
// do stuff with the image and post url
break;
};
};
// then I can do other stuff as fallback if the image url and post url are not found

Related

Permanent links to thumbnails in Google Drive API

I'm using Google Drive API (PHP) to upload some photos to my Drive. When a file is uploaded, a Google_DriveFile object is returned in the response to confirm the successful transfer. It includes a field called thumbnailLink, accessible through the getThumbnailLink getter. Its content may look like this:
https://lh4.googleusercontent.com/dqVdU195R4_0ZtWxsJlhW1Fr2K30xa2hH3V1KV4UrTBl9QkhOSR0ZqN9HoB-TjEQv8SIJw=s220
Until today, I was sure that the link doesn't change by itself over time. However, when I tried to display a thumbnail of a photo I have on my Drive, using a cached address I keep in my local database, I got a 403 error - you can see it under the mentioned link. I asked the API for the current link to the thumbnail and it's now completely different.
It happened to me only once but for multiple files, i.e. all the files I had on my Drive suddenly got new thumbnail links.
Is there a way to quickly retrieve a thumbnail of a document (preferably, a photo) by some constant value or to be sure that it won't change? The perfect solution would be to access the thumbnail under a link that includes the document's id instead of some hash that may change.
Try this:
https://drive.google.com/thumbnail?authuser=0&sz=w320&id=[fileid]
Where:
sz is a size, where you may use as w (width), as h (height)
fileid is a file id. You may find it in "share" menu by right click in Google Drive UI.
I have gone through the API Documentation as they have provided:
Important: Thumbnails are invalidated each time the content of the file changes. When supplying thumbnails, it is important to upload new thumbnails each time the content is modified.
According to the information it means that a new Thumbnail is only generated only when the contents of the file are modifided. But in your case it is really weired thing and the contents are not changed but the thumbnail are Changed. As from documentation there is no batch process thing avaiable but another way around is available i.e. Web Hook
According to the Documentation there is web hook available i.e. Files:Watch process through which one can track the changes are made to file. Thus, it means every time contents are changed then hook would run and you can change the cache of the image thumbnail.
HTTP request can be sent to request the watching the files changing
POST https://www.googleapis.com/drive/v2/files/fileId/watch
Here fileID means the ID provided after loading the file.
In the request body, supply data with the following structure:
id ==> string (A UUID or similar unique string that identifies
this channel.)
token# ==> string (An arbitrary string delivered to the target address with
each notification delivered over this channel).
expiration# => long (Date and time of notification channel expiration,
expressed as a Unix timestamp, in milliseconds.)
type ==> string (The type of delivery mechanism used for this channel.
The only option is web_hook.)
address => string (The address where notifications are delivered
for this channel.)
# Optional.
If the contents get changed then new Thumbnail is generated and hook will notify you address and through your address you can fetch new information.
Here is another solution. Let's say we store only GDrive ID of the images or PDFs (google generate thumbs for many file types).
we can send request to gDrive to get valid thumbnail since looks like thumbs will expire even if there is no changes to the file.
In this case each thumbnail inside Angular component. If you use something else you can create array of links and iterate through it to create proper thumb links.
Here is the code:
const thumb = () => {
if (this.item.DriveId) {
this.getThumb(this.item.DriveId, this.authToken)
.then(response => {
console.log(`response from service ${response}`);
// Set thumbnail width size to 300px or any other width if needed
this.item.externalThumbnailId = response.slice(0, -3) + 300;
})
//here we can handle cases when API limit exceeded 10 req in a sec
.catch(e => {
if(e.data.error.message == 'User Rate Limit Exceeded'){
console.log('Failed to load thumb. trying one more time');
setTimeout(thumb, 1000);
} else {
console.log(e);
}
});
}
};
//call this function on component load.
thumb();
Another solution will be to write some backend script that updates thumbs in DB records.

Create POST Request in air /as3 for youtube direct upload

I'm developing a simple youtube app in adobe air, so far I could get the approval window in youtube and getting the token for uploading. However I'm stuck in the part where you send the data on POST with all the information (https://developers.google.com/youtube/2.0/developers_guide_protocol_direct_uploading)
I already loaded my video data as a bytearray, what I need is to create the whole POST request containing all the information as it shows in the link. (the xml atom feed, the bytearray data, etc.) I have all the information needed, I just need to structure the POST request.
How to do that in as3/air? Do I create all the information as URLVariables? which ones are headers and which ones arent? How do you add the --< boundary_string> to the POST? How do you add the bytearra to the POST? All help is highly appreciated.
Thanks!
I have always done something like this when sending POST variables:
<fx:Declarations>
<s:HTTPService id="loginServ" resultFormat="text" result="onResult(event)" method="POST" url="http://www.myurl.com/login.php"/>
</fx:Declarations>
Then you would have two functions, one for sending the request and one for handling the result you get back:
private function login():void{
//Make a new Object to hold all of your POST variables
var reqInfo:Object = new Object();
//Then set the properties of that Object to be each POST variable
reqInfo.username = "admin";
reqInfo.password = "password";
//Finally, send the request with the Object as the parameter
loginServ.send(reqInfo);
}
private function onResult(e:ResultEvent):void {
trace("Result:" + e.result);
}

Need help parsing through a page & getting all comments found into an Array using a RegEx pattern in Google Apps Script?

My problem lies in 2 parts however I'm hoping solving 1 will fix the other. I've been trying to parse through a page and get all the comments found within a forum thread.
The comments are found using a RegEx pattern and the idea is that whatever lies in the comment will be read into an array until there aren't any more comments left. Each comment div follows this format
<div id="post_message_480683" style="margin-right:2px;"> something </div>
I'm trying to locate up to "post_message_[some number]" since each number seems to be generated randomly and then get whatever is between that particular div. My 1st problem is my RegEx just doesn't seem to be working I've tried a few but none yielded any results (except for when I insert the post message no. in manually), Here's the code so far:
function GetPosts() {
var posts = new Array(60);
var url = "http://forums.blackmesasource.com/showthread.php?p=480683";
var geturl = UrlFetchApp.fetch(url).getContentText().toString();
var post_match = geturl.match(/<div id="post_message_(.+)" style="margin-right:2px;">(\w.+)<\/div>/m);
Logger.log(post_match);
}
Edit: I initially tried getting this info via GAS's Xml.Parse() class but after grabbing the URL I just didn't know what to do since suffixing
.getElement().getElement('div') (I also tried .getElements('div') and other variations with 'body' & 'html')
would cause an error. Here is the last code attempt I tried before trying the RegEx route:
function TestArea() {
var url = "http://forums.blackmesasource.com/showthread.php?p=480683";
var geturl = UrlFetchApp.fetch(url).getContentText().toString();
//after this point things stop making sense
var parseurl = Xml.parse(geturl, true);
Logger.log(geturl);
//None of this makes sense because I don't know HOW!
//The idea: Store each cleaned up Message Div in an Array called posts
//(usually it's no more than 50 per page)
//use a for loop to write each message into a row in GoogleSpreasheet
for (var i = 0; i <= parseurl - 1; i++) {
var display = parseurl[i];
Logger.log(parseurl); }
}
Thanks for reading!
In general like the comment points out - be aware of parsing HTML with RegEx.
In my past personal experience, I've used Yahoo's YQL platform to run the HTML through and using XPath on their service. Seems to work decently well for simple reliable markup. You can then turn that into a JSON or XML REST service that you can grab via UrlFetch and work on that simplified response. No endorsement here, but this might be easier than to bring down the full raw HTML into Google Apps Script. See below for the YQL Console. I also don't know what their quotas are - you should review that.
Of course, the best course is to convince the site owner to provide an RSS feed or an API.

Post an object of type Reference

I have had this problem for some time now and I have seen others have it as well. It has to deal with posting your custom objects that you create in Open Graph to post with your application. I am having this problem primarily on all platforms, but right now let's say I am using Android. If someone has accomplished this in C# or on IOS or even in PHP please post your answer.
An Example:
I have an object that posts a meal to Facebook. Let's say its properties are the following.
mealName = "Lunch"
mealType = "Vegetarian"
mealLocation = "Somewheresville, OH"
Now I have another object in my Open Graph and it is called DailyFood. It has properties such as the following.
day = "12/01/2012"
meal = "MyCustomMeal" // This references a meal object
Now when I go to post that I try to do the following in Java.
//Build Meal
JSONObject mealData = new JSONObject();
mealData.put("mealName", "Lunch");
mealData.put("mealType", "Vegetarian");
mealData.put("mealLocation", "Somewheresville, OH");
Bundle params = new Bundle();
params.putString("day", "12/01/2012");
params.putString("meal", mealData.ToString());
AsyncFacebookRunner request = new AsyncFacebookRunner(facebook);
This is where I generate the following error code.
{"error":
{"message":"(#3503) is an invalid value for property
\"meal\" with type \"Reference\"","type":"OAuthException","code":3503}}
Now I know that it says OAuthException but I am able to post feeds to Facebook with this app just fine. If anyone else has experienced this error on any platform and has found a solution please post it here.
Thanks!
So the answer to this question is that you actually need a website available for your app to be able to reference what its posting to Facebook. In the docs, I at least, wasn't able to find out where this was noted.
according to this official video you must have the web application to post the action using open graph,no matter in which platform we are working android,ios etc
as it fetches the meta tags and properties from the web url only which works as refrence.

Posting image to Facebook album with AS3 API

I'm having trouble with posting an image from my canvas application to the user's albums. According to the Facebook docs:
In order to publish a photo to a user’s album, you must have the publish_stream permission. With that granted, you can upload a photo by issuing an HTTP POST request with the photo content and an optional description to one these to Graph API connections:
https://graph.facebook.com/USER_ID/photos - The photo will be published to an album created for your app. We automatically create an album for your app if it does not already exist. All photos uploaded this way will then be added to this same album.
https://graph.facebook.com/ALBUM_ID/photos - The photo will be published to a specific, existing photo album, represented by the ALBUM_ID.
So, going by point one, if I upload an image like this...
Facebook.api("me/photos",imagePostCallback,{message:"",image:myImageBitmap,fileName:''},URLRequestMethod.POST);
...then I can expect it to place my image in an album named for my app, which it will create if necessary?
Not so.
What actually happens when the album doesn't exist is that the uploaded image is pushed into any other handy albums that exist, which are usually for (and created by) other applications. This is a bit of a pain.
So far I've tried the following:
Disabling sandbox mode. I had thought that the app might be unable to create new albums because it was in sandbox mode, however disabling sandbox mode made no difference and I can create albums directly with it enabled.
Checking for the existence of my album and creating it if necessary. I can check for my album and create it if it does not exist, but I cannot then upload an image because the POST call to Facebook.api to upload the image will fail if it is not called as a direct result of a user interaction.
And so now I'm a bit stumped. Obviously I can't have the possibility of my app posting images to a competitors album, but at the moment the only alternative I can see will involve effectively making the user submit their image twice if an album has to be created. Any ideas?
I'm guessing you need the access_token in your params :) When posting something on a user's facebook, you always need this one (not always necessary when getting information). The way to get the accesstoken is shown below :)
public function post():void
{
var _params:Object = new Object();
_params.access_token = Facebook.getSession().accessToken;
_params.message = "";
_params.image = myImageBitmap;
_params.fileName = "";
Facebook.api("me/photos", imagePostCallback, _params, URLRequestMethod.POST);
}
also make sure that you have the right permissions when asking for permissions with your app.
EDIT
Ok, so I've missed your edit a bit there ;) it should be possible to create your own album. Take a look at this php-code for graph api. The code should also be able to be parsed to AS3.
http://developers.facebook.com/blog/post/498/
EDIT2
ok, i've done some more digging (seemed interesting to know). This should actually work when using graph api.
FB.api('/me/albums', albumCreateCallback, {name: 'name of the album', message: 'description of the album'}, URLRequestMethod.POST);
When you then call for another api call to upload your image in the albumCreateCallback, it should work and upload your image (according to what i've found).