A Facebook App

cakeexoticInternet and Web Development

Dec 13, 2013 (3 years and 8 months ago)

53 views

A Facebook App
In 10 Minutes or Less
Disclaimers
Facebook Sucks
Its pointless.
Its slow.
It doesn’t work half the time.
Unfortunately you have to have it because
everybody is on it.
The Graph API Sucks
Terribly incomplete documentation.
Duplicate APIs.
Link, Post, and Status all do the same thing.
Multiple things called “Link”
Inconsistent returns.
JSON, URL encoded strings, true/false
Facebook::Graph
What?
A perl wrapper for the Facebook Graph API.
About 40% complete, but still very functional.
Features
Query Facebook Data
(both privileged and public
data)
Publish to wall
Publish comments
Like posts
Publish events
RSVP to events
Publish Notes
Publish Links
Authenticate against
Facebook
Request privileges
Convert old school sessions
Why?
WWW::Facebook::API is no longer maintained
and is hard to figure out.
Facebook says Graph is the direction they’re
going forward.
Share what I’ve learned so others don’t have to
figure it out.
Or Less?
10 Minutes
I’m timing you. Go!
Assumptions
You already have a Facebook account.
You have a server available on the internet.
You have a modern Perl installed on the server.
You have Dancer (the web app framework)
installed on the server.
You can point a domain the server.
Minute 1
Install the Developers Application
http://apps.facebook.com/developer
Create Your App
Minute 2
Create a canvas URL
Update your Connect URL
# config.yml
facebook:
postback: "
http://www.yourapplication.com/facebook/postback/
"
app_id: "XXXXXXXXXXXXXXXX"
secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
Minute 3
Create a config file with your app settings.
# app.pl
use Dancer;
get '/' => sub {
return ‘hello world’;
};
dance;
Minute 4
Create a basic Dancer ‘Hello World’ app.
use Dancer;
use Facebook::Graph;
get '/' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
redirect $fb
->authorize
->uri_as_string;
};
dance;
Minute 5
Ask for authorization from the Facebook user.
use Dancer;
use Facebook::Graph;
get '/' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
redirect $fb
->authorize
->uri_as_string;
};
get '/facebook/postback/' => sub {
my $params = request->params;
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->request_access_token($params->{code});
};
dance;
Minute 6
Accept the postback from Facebook.
use Dancer;
use Facebook::Graph;
get '/' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
redirect $fb
->authorize
->uri_as_string;
};
get '/facebook/postback/' => sub {
my $params = request->params;
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->request_access_token($params->{code});
return $fb->fetch(‘me’)->{name};
};
dance;
Minute 7
Display who’s logged in.
use Dancer;
use Facebook::Graph;
get '/' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
redirect $fb
->authorize
->uri_as_string;
};
get '/facebook/postback/' => sub {
my $params = request->params;
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->request_access_token($params->{code});
return $fb->fetch(‘me’)->{name};
};
dance;
The Complete Program
Minute 8
Start it
perl app.pl
Try it:
http://apps.facebook.com/madmongers
http://facebook.madmongers.org
/
Minute 9 & 10
You’re done!
Have a cup of coffee while
you wait for the clock to run
out.
More
Interesting
Little
Do
Let’s
Something
A
Set Up Sessions and Templates
# config.yml
port: 80
session: "YAML"
session_dir: "/tmp/dancer-sessions"
template: template_toolkit
engines:
template_toolkit:
start_tag: '[%'
stop_tag: '%]'
facebook:
postback: "
http://www.yourapplication.com/facebook/postback/
"
app_id: "XXXXXXXXXXXXXXXX"
secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
YAML Sessions are
good enough for
development.
Let’s use Template Toolkit
since that’s what most people
are familiar with.
Store Access Token In A Session
get '/facebook/postback/' => sub {
my $params = request->params;
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->request_access_token($params->{code});
session access_token => $fb->access_token;
redirect '/';
};
Shove it in a session
for use on subsequent
requests.
Redirect the user back to our home
page. (We’ll come back to this.)
We get the access token
here.
All Non FB Pages Force Login
before sub {
if (request->path_info !~ m{^/facebook}) {
if (session->{access_token} eq '') {
request->path_info('/facebook/login')
}
}
};
Look for path.
Look for existing access
token.
If not, make ‘em log in.
But wait! We don’t have
that page!
Give Ourselves A Home Page
get '/facebook/login' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
redirect $fb
->authorize
->uri_as_string;
};
get '/' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->access_token(session->{access_token});
my $user = $fb->fetch(‘me’);
template 'home.tt', { name => $user->{name}}
};
Have to rename our
existing home page.
Make a new home
page.
Good thing we have
that access token.
Let’s welcome the
user with a template
saying “Welcome,
Name.”
Let’s Look Up Our Friends
get '/friends' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->access_token(session->{access_token});
my $friends = $fb->fetch('me/friends')->{data};
template 'friends.tt', { friends => $friends};
};
Wow, it’s easy to get
our friends!
Unfortunately
Facebook::Graph
doesn’t turn this into a
nice object for us yet.
Formatting goes in a
template.
Let’s Request More Privileges
get '/facebook/login' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
redirect $fb
->authorize
->extend_permissions(
qw(offline_access publish_stream create_event rsvp_event)
)
->uri_as_string;
};
We just have to ask.
Let’s us do stuff when
the user’s not even
logged in.
Publish posts, links, etc.
Create Facebook
events.
RSVP “maybe”,
“attending”, and
“declined “ to events.
Next time the user logs in to
our app, Facebook will ask if
it’s ok for us to have these privs.
Import An RSS Feed
get '/rss-importer' => sub {
template 'rss-importer.tt';
};
Why? Cuz someone
suggested I show how
to do it.
Set up a page that has a
form for submitting a
feed URI.
Import An RSS Feed
post '/rss-importer' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->access_token(session->{access_token});
my $feed = XML::FeedPP->new(request->params->{rss_uri});
foreach my $item ($feed->get_item) {
$fb->add_post
->set_message('Created by RSS Feed Importer')
->set_link_uri($item->link)
->set_link_name($item->title)
->set_link_description($item->description)
->publish;
}
template 'rss-importer-post.tt';
};
Same URI, but
accepting a POST
this time.
Pass the feed URI into
XML::FeedPP.
For each item in the
feed post a message to
the user’s wall.
When we call ‘publish’
it makes the call to
Facebook.
It also returns a post id
if we wanted to use it
for something.
Import An iCal Feed
get '/ical-importer' => sub {
template 'ical-importer.tt';
};
Why? Cuz someone
suggested I show how
to do it.
Set up a page that has a
form for submitting a
feed URI.
Import An iCal Feed
post '/ical-importer' => sub {
my $fb = Facebook::Graph->new( config->{facebook} );
$fb->access_token(session->{access_token});
my $ical = LWP::UserAgent->new
->get(request->params->{ical_uri})
->content;
my $calendar = Data::ICal->new( data => $ical );
foreach my $entry (@{$calendar->entries}) {
$fb->add_event
->set_name($entry->properties->{summary}[0]->value)
->set_location($entry->properties->{location}[0]->value)
->set_description($entry->properties->{description}[0]->value)
->set_start_time(DateTime::Format::ICal->parse_datetime($entry->properties->{dtstart}[0]->value))
->set_end_time(DateTime::Format::ICal->parse_datetime($entry->properties->{dtend}[0]->value))
->publish;
}
template 'ical-importer-post.tt';
};
Download the iCal
feed.
Convert the feed into
some “usable” data.
Create FB events for
each item in the feed.
Data::ICal returns iCal date
format, so we have to convert
that into a DateTime object.
Facebook::Graph
All the code displayed in this
presentation is available as Recipe 2
in the Facebook::Graph Cookbook.
DEMO