Posting a Custom Story to Facebook Open Graph - facebook-graph-api

I'm trying to post a custom story to a proof of concept Facebook app, consisting of an object type "badge" and an action type "earn." When I "get code" for this in the Facebook Open Graph Types interface, the Graph Explorer example successfully posts the story to my timeline. However, the one parameter ("badge") is a URL reference to OG samples.
How can I post something directly, not as a reference to OG samples?
Using the C# SDK, I'm currently trying this:
var client = new FacebookClient();
client.AccessToken = tokenResult.access_token;
dynamic parameters = new ExpandoObject();
parameters.badge = #"
{
""app_id"" : [my app ID],
""title"" : ""Widget Badge"",
""image"" : ""[a public image URL]"",
""url"" : ""[a public website URL]"",
""type"" : ""[my custom namespace]:badge""
}
";
var result = client.Post("/me/[my custom namespace]:earn", parameters);
However, the exception I'm getting back from Facebook is:
"[the above JSON]" is an invalid value for property "badge" with type "Reference"
Following some code snippets I've found online, I tried changing the property "badge" above to a generic "post" (I would guess relying on the "type" value to know what it's posting), but then the error says that I'm missing the required parameter "badge."
I haven't found anything which tells me what a "Reference" type is in this case, though I could just be overlooking something. In the original example it was a URL to OG Samples, but I would assume we can post custom things and not just samples. Do I need to host some sort of "sample" page of my own with the values in meta tags like OG Samples, or can I just specify the values directly in the post somehow?

To post actions with an object, you need to provide the url of this object.
But in the case where you don't have this url on your own app (you app doesn't have a webpage for each object), then you can create objects hosted directly by facebook, and the url will use the generated id of this object.
To do that, you need to use the Object API : https://developers.facebook.com/docs/opengraph/using-object-api/
Providing the json data, it will create the object in facebook opengraph, returning its id (so you have the url) and then you'll be able to post your action

Related

Identify Facebook object type from user notification

I'm reading the user/notifications facebook stream (https://developers.facebook.com/docs/graph-api/reference/v2.4/notification/).
As part of the result i'm getting an Object.
"The object (this can be a post, a photo, a comment, etc.) that was the subject of the notification."
Is there a way to identify if the object is post or comment or like etc'?
Thanks,
fredy
You can retrieve the type of a Facebook Object if you using something Facebook call "Introspection" by adding metadata argument to your request:
GET http://graph.facebook.com/object_id?metadata=1
The resulting JSON will include a metadata property that lists all the supported edges for the given node and a type field
Find more on : https://developers.facebook.com/docs/graph-api/using-graph-api/v2.4 under the section Introspection.

What is the correct way to get fb_ref in an open graph action?

According to the documentation, if you call an open graph action publish with the optional "ref" parameter filled in (let's say, ref: foo), Facebook will return that value to you in the fb_ref URL parameter that Facebook sends your clickers too (let's say, myObject?fb_ref=foo).
However, Facebook is NOT doing this. I haven't seen any yield from including the ref parameter in my action publishes, even on a production, non-sandbox app.
From my experimenting, the only way to get fb_ref into my URL is to include fb_ref in the URL parameters for the object the user is acting upon (rather than by including parameter in the API call), and have the page include that fb_ref in the og:url. However, I'm guessing that this will result in Facebook treating every different fb_ref as a different objects. This is obviously not desirable.
So, no matter what I do, I can't get Facebook to provide a link to anything other than what the og:url in my object specifies and what Facebook generates, such as fb_source.
Does anybody know what I'm doing wrong?

Post an Object to Facebook Graph API Explorer

Trying to figure out the correct Json string to pass to my OpenGraph app. I'm using the Gigya Java SDK, but decided to eliminate some of the extra layers in testing the string.
So I'm first of all looking at the Graph API Explorer.
My POST field name is "Recipe" and the value is
{"title":"one-handed fried pies","description":"ye olde Description goeth here.","image":"http://www.recipe.com/images/one-handed-fried-pies-R094255-ss.jpg","url":"http://www.recipe.com/one-handed-fried-pies/"}
This maps exactly to the fields of the Recipe object.
However, no matter how I format the JSON, I get this exception
{
"error": {
"message": "(#3503) \"{\"title\":\"one-handed fried pies\",\"description\":\"ye olde Description goeth here.\",\"image\":\"http://www.recipe.com/images/one-handed-fried-pies-R094255-ss.jpg\",\"url\":\"http://www.recipe.com/one-handed-fried-pies/\"}\" is an invalid value for property \"recipe\" with type \"Reference\"",
"type": "OAuthException",
"code": 3503
}
}
Any thoughts?
By hacking thru, got it to work this way.
Most important... the URL as above must point to a page that has valid og: tags for the app. (You can look at the source of this page for the structure http://www.csmonitor.com/Science)
In the Graph Api Explorer,Select your Application in the top left.
Click get Access token.
Select POST.
Click on Add a field
Type the name of the object. In my case "recipe".
Type the url. In my case, I set up a live test page and deployed it.
click submit and wait for an id.
{
"id": "290473937742173"
}

Cookie to log in with Jsoup?

For a project I'm trying to get data from a website only acessible when you're logged in from the site Goodreads.com. I'm new to Jsoup, since I'm using it only for this particular project. Getting the relevant data from the website is not a problem, but I can't seem to get to the particular page I need. The page I'm trying to acces is viewable only when logged in, when not logged in it rederects to the log-in page.
I've looked through the answers here, but the answers given so far have not helped.
What I have now:
String url = "http://www.goodreads.com/friend/user/7493379-judith";
Connection.Response res = Jsoup.connect("http://www.goodreads.com/user/sign_in")
.data("email", "MYEMAIL", "user_password", "MYPASSWORD")
.method(Connection.Method.POST)
.execute();
Document doc2 = res.parse();
String sessionId = res.cookie("_session_id");
Document doc = Jsoup.connect(url)
.cookie("_session_id", sessionId)
.get();
I got this far with help of the answers here, but it doesn't work, I'm still only getting the data from the log-in page it rederects to.
I have several questions:
Most importantly of course; How can I make it work?
The given answers here heve used method.(Method.POST) instead of method.(Connection.Method.POST) . When I use the first one however, I get an error that Method cannot be resolved. Anyone know why this is?
The examples I've seen have used "username" and "password" in .data() . What exactly do these refer to? I've now used the name of the input box. Is it the name, the type, the id, what exactly? Since Goodreads does not refer to the log in as the username, but as the e-mail, I assume I have to change them. (username & password doesn't work either)
Examples also use http://example.com/login.php as example url. Goodreads doesn't have a /login.php page though. Am I correct to assume I have to use the url with the log-in screen?
_session_id is the name of the relevant cookie on Goodreads.
I'd be very grateful if anyone can point me in the right direction!
See carefully what data is posted on login:
user[email]:email#email
remember_me:on
user[password]:plain_pasword
n:667387
So your post must execute exact same keys.
2.Make sure, you make right import: import org.jsoup.Connection.Method;
but Connection.Method.POST is still good.
3.See p1
4.Yes, you are correct
5.what is the question?
Goodreads requires two things when logging in: first, that you have a session ID stored in a cookie, and second, that you have a random generated number. You can get these when first visiting the login page without logging in: it will set a cookie with a session ID, and the form will contain a hidden input form (i.e. ) with the name "n" and value a number. Save these and pass them along as respectively a cookie and a form value when logging in.
Some remarks about the way I found this out:
The first thing you need to realise is that you're trying to recreate the exact same requests your browser does with Jsoup. So, in order to check whether what you have right now will work, you can try to recreate the exact same situation with your browser.
To recreate your code, I went to the login page, then I deleted all my Goodreads cookies (as you don't send along any cookies when you send the login request as well), and attempted to sign in with only passing the username and password form values. It gave an error that my session had timd out. When I first loaded the login page and then deleted all cookies except the session ID and did not remove the "n" form value, I could log in successfully. Therefore, you want to make a general GET request to the sign in page first, retrieve the session ID cookie you get there and the hidden form value, and pass it along with the POST request.
It could be that the API changed or that there just are several ways. Using Connection.Method.POST will do fine, in any case.
Yes, they refer to the names of the input boxes. This should be id, however, since name was used in the past and not all versions of all browsers supported passing the ids as data, most websites are just adding both. Either should be fine.
If you look at the source code of the sign in form, you can see that the "method" attribute of the form element is indeed the sign in page itself, so that's where it sends the request to.
PS. As a general tip, you can use the Firefox extension "Tamper Data" to remove form data or even cookies (though there are easier extensions for that).
You can log in with this code:
public static void main(String[] args) throws Exception {
Connection.Response execute = Jsoup
.connect("https://www.goodreads.com/")
.method(Connection.Method.GET).execute();
Element sign_in = execute.parse().getElementById("sign_in");
String authenticityToken = sign_in.select("input[name=authenticity_token]").first().val();
String n = sign_in.select("input[name=n]").first().val();
Document document = Jsoup.connect("https://www.goodreads.com/user/sign_in")
.data("cookieexists", "✓")
.data("authenticity_token", authenticityToken)
.data("user[email]", "user#email.com")
.data("user[password]", "password")
.data("remember_me", "on")
.data("n", n)
.cookies(execute.cookies())
.post();
}

REST service returning "useful" information for demos

I am looking for a REST service that I could use in demo code. I'd like the service:
To take at least one parameter (as a request parameter, or XML POSTed as the body of the HTTP request).
To return the result as XML (not JSON).
To be accessible anonymously (I'll call the service in sample code, so I don't want to put my key in the code, or request users to get a key).
When the Twitter API supported XML (not just JSON), I was typically using their search API. But really anything mainstream enough, easy enough to understand will do (information about zip code, weather for a city…).
If you are using .Net, why don't you just create a tiny MVC application that has a controller that exposes a method that returns some sort of formatted XML? That way you can run the whole thing locally.
EDIT:
You know, I think you can use Google Maps API without a key. I created a test project a couple of days ago. Here is a .Net code snippet (only included so that you can see how I am calling the service):
private static string GetString(Uri requestUri)
{
var output = string.Empty;
var response = WebRequest.Create(requestUri).GetResponse();
var stream = response.GetResponseStream();
if (stream != null)
{
using (var reader = new StreamReader(stream))
{
output = reader.ReadToEnd();
reader.Close();
}
}
response.Close();
return output;
}
I pass in a uri with a url:
https://maps.googleapis.com/maps/api/directions/xml?mode=walking&origin={0},{1}&destination={2},{3}&sensor=false
Where {0},{1} are the first lat/long, and {2},{3} are the second. I am not attaching a key to this and it worked for testing. My method returns a string that later I handle like so:
var response = XDocument.Parse(GetString(request));
which gives me back xml. Again, I still recommend just creating your own web app and then deploying it somewhere publicly accessible (either in a LAN or on the web), but if you just need a web service to return XML you can use that.
The Yahoo! Weather API can be used for this. It takes a location as a request parameter and returns the weather forecast for that location as XML. It also returns weather information as HTML, which you could display as-is to the user. You can see an example of this below. Also make sure that you respect the term of use described at the bottom of the Weather API documentation page.