Sie sind auf Seite 1von 6

2/1/12

Hands-on experience with Opa

Making friends Introduction

with

Facebook:

Lots of announcements lately, but not many tutorials; time to change it. Hopefully by now you know how easy it is to create web apps in Opa (if you don't and/or are new around here I suggest you explore the history of this blog that has a number of tutorials, also for beginners), but as we all know web apps hardly ever live in isolation. More often than not they interact with other services and platforms. Today I present you with the first article in the series `Making friends with Facebook', that will explore how to interact with Facebook from Opa apps. Ready? You better
Summary You will learn: How to use Opa's Facebook API to connect with user's Facebook account. How to write a simple Opa app that will show given user's name and thumbnails of her friends (both data obtained from Facebook).

Setting up a Facebook app


To get started we need to create our app's profile on https://developers.facebook.com. You'll see the following status bar. Facebook. To do that go to

Go the Apps (highlighted in the above screenshot) and choose Create New App.

That will open a dialog with basic info about the new application. For now just put OpaIntro1 as App display name (we'd prefer something like HelloFacebook, but using Facebook trademarks in app names is prohibited) and agree to the Facebook Platform Policies (preferably, after reading ;).

le:///Users/henri/Downloads/facebook-01/Facebook tutorial 01.html

2/7

2 / 1 2 H a n d s o n e x p r i e n c w i t h O p a
Then (possibly after answering a Captcha) you will be presented with the following settings screen.

Firstly note on the top of the screen the App ID and App Secret (they're blurred in the screenshot as the secret should not be shared with anyone) we will need those values in a minute. Then in the Select how your app integrates with Facebook section (bottom of the screen; note that we cut out the Basic info and Cloud services sections of the settings in the screenshot) select the Website mark, put the URL at which your application will be hosted it's important to get that right as the Facebook login will only redirect to this site's URL and click Save changes. Ok, we're all set on the Facebook side; now let's do some Opa coding!

l e : / U s e r / h e n r i / D o w n l o a d s / f a c e b o k 0 1 / F a c e b o k t u o r i a l0 1 . h t m l
Writing the Opa application

The goal of the app is simple: allow users to login via Facebook and upon connection greet them with their

3 / 7

2 / 1 2 H a n d s o n e x p r i e n c w i t h O p a
name and a quick info on the number of friends they have. Since we will be using Facebook API, including authentication and Facebook Graph to have some basic info about the logged-in user let's start with some imports.
import stdlib.apis.{facebook, facebook.auth, facebook.graph}

Then we need to fill in some basic info about the application; we'll put this inside a module.
module OpaIntro1 { config = { app_id: "xxxxxxxxxxxxxxx" , api_key: "xxxxxxxxxxxxxxx" , app_secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } }}

Of course the x's need to be replaced with the real data here app_id and app_key are the same (there used to be a distinction) and correspond to App ID in the Facebook settings screen, whereas app_secret is the value of App secret. Now we initialize the authentication module with this configuration, make an abbreviation for the Facebook Graph module and define the redirect URL this is where Facebook will redirect after authenticating the user.
FBA = FbAuth(OpaIntro1.config) FBG = FbGraph redirect = "http://facebook-01.tutorials.opalang.org/connect"

Now, we have to handle two pages: the login screen that will show the Facebook connect button and the main screen that is visible after login. Let's start with the main page.
function main() { login_url = FBA.user_login_url([], redirect) <a href="{login_url}"><img src="resources/fb_connect.png" /></a> }

The user_login_url function of the authentication module of the Opa Facebook API gives us the URL to redirect to in order to invoke authentication. The first argument is the list of permissions that we require for now, we keep it empty. Then we just create a regular link to that address and put a nice image for it. And that's it.

l e : / U s e r / h e n r i / D o w n l o a d s / f a c e b o k 0 1 / F a c e b o k t u o r i a l0 1 . h t m l
Now let's take a look at the dispatcher of our application:

dispatcher = parser | "/connect?" data=(.*) -> connect(Text.to_string(data)) |> page

4 / 7

2 / 1 2

| .* -> main() |> page

H a n d s o n e x p e r in c e w i t h O p a

The /connect page is where we are redirected upon completing authentication (see the redirect variable before); it will have an extra parameter after the question mark, which is the Facebook authentication token that we will use for all functionality requiring Facebook login (in our app: to get some data about the logged-in user). Any other URL in our sample app is handled with the welcome screen that we created above. The page function is just a simple wrapper to create an HTML-page resource (we skip it here but we encourage curious readers to consult the complete listing at the end of the article). Finally the connect function that takes as an argument the part of the URL after the question mark. First we need to extract a token from this string with
FBA.get_token_raw(data, redirect)

which optionally returns a token that we can subsequently use to get some user data. For that we will use the Facebook Graph API, which one can explore at: https://developers.facebook.com/tools/explorer. Two functions that are used for this are:
FBG.Read.object(id, options) FBG.Read.connection(id, connection, token, paging)

For instance reading object "me" (try https://graph.facebook.com/me in the Facebook API explorer) will give basic information about the logged-in user (we will extract name from there), whereas reading connection "friends" of object "me" (try https://graph.facebook.com/me/friends) will give the list of user's friends. The returned data is in JSON format, so we have to do a bit of processing to extract the data we need. See function get_name in the complete listing below for details on how to get logged-in user's name. Similarly consult get_friends_ids to see how to obtain ids of given user's friends, which then is used in the main_msg function where we get a thumbnail of user with given id using the FBG.Read.picture_url function. Ideally, the API should be extended with more high level functions that would provide a nice mapping from the JSON Facebook API to a type-safe world of Opa (essentially doing what we did in those functions but for all possible objects/connections). This can be done of course (volunteers?) but is a bit complicated by the fact that the shape of the information for different queries depends on application permissions. So, let us present our first Facebook app in Opa. The complete listing & a link to the running version of the application below.
import stdlib.apis.{facebook, facebook.auth, facebook.graph} import stdlib.{themes.bootstrap, widgets.bootstrap} config = OpaIntro1.config redirect = "http://facebook-01.tutorials.opalang.org/connect"

l e : / U s e r s / h e n r i / D o w n l o a d s / f a c e b o k 0 1 / F a c e b o k t u o r i a l0 1 . h t m l

5 / 7

2 / 1 2
FBA = FbAuth(config) FBG = FbGraph

H a n d s o n e x p e r in c e w i t h O p a

function main() { login_url = FBA.user_login_url([], redirect) <a href="{login_url}"><img src="resources/fb_connect.png" /></a> } function show_box(t, title, description) { WBootstrap.Message.make( { alert: ~{ title, description } , closable: false }, t ) } function get_name(token) { opts = { FBG.Read.default_object with token:token.token } match (FBG.Read.object("me", opts)) { case {~object}: match (List.assoc("name", object.data)) { case {some: {String: v}}: some(v) default: none } default: none } } function get_friends_ids(token) { opts = FBG.default_paging match (FBG.Read.connection("me", "friends", token.token, opts)) { case {success: c}: some(List.map(function (friend) { friend.id }, c.data)) default: none } } function main_msg(friends) { function friend_img(id) { { href: none , onclick: ignore , content: <img src={FBG.Read.picture_url(id, {square})} /> } } <> <h4>Your friends:</> {WBootstrap.Media.grid(List.map(friend_img, friends))} </> } function connect(data) { match (FBA.get_token_raw(data, redirect)) { case {~token}: match (get_name(token)) { case {some: name}: match (get_friends_ids(token)) { case {some: friends}: show_box({success}, "Hello, {name}!", main_msg(friends)) default: show_box({error}, "Error getting your friends list", <></>) } default: show_box({error}, "Error getting your name", <></>) } case ~{error}: show_box({error}, error.error, <>{error.error_description}</>) } } function page(body) { Resource.html("Facebook connect tutorial", WBootstrap.Layout.fixed( <> <h1>Facebook connect tutorial</> {body} </> ) ) }

l e : / U s e r s / h e n r i / D o w n l o a d s / f a c e b o k 0 1 / F a c e b o k t u o r i a l0 1 . h t m l

6 / 7

2 / 1 2

dispatcher = parser | "/connect?" data=(.*) -> connect(Text.to_string(data)) |> page | .* -> main() |> page Server.start(Server.http, [ { resources: @static_resource_directory("resources") } , { custom: dispatcher } ] )

H a n d s o n e x p e r in c e w i t h O p a
See Run

Later we will continue this series of tutorials with examples of some more advanced interactions with the Facebook platform. I'm not sure yet what it will involve so requests and good ideas are welcome just drop a comment!

l e : / U s e r s / h e n r i / D o w n l o a d s / f a c e b o k 0 1 / F a c e b o k t u o r i a l0 1 . h t m l

7 /

Das könnte Ihnen auch gefallen