Jun
29

Permanent Facebook Sessions and Posting as a Page

For a current project, we are integrating a site with Facebook Connect and linking users of our T1EOS (our Content Management System) to their accounts. When administrators create content, the CMS publishes the article to their brand page directly from the CMS behind the scenes. This was a bit tricky to figure out how to accomplish (wasn't sure it was possible at first) given that the Facebook API had pretty much completely changed from the last time I used it; Facebook now uses OAuth 2.0 for authentication and authorization. So this article then will be an overview of how to get a permanent session (or access_token as it's called on Facebook) that will allow you to post to your fan page as the page (and not your user account).

To start, you must be an adminstrator of the page you want to post as. We're going to essentially be posting from the Application to the Page, but to post from a Facebook Application, you must give the application permission to post to your wall and also permission for offline access. In our case, offline access allows the CMS to process and post content even when I am not logged in. Once you've give permission for the application to post for you, it should be able to post to any pages you are a full administrator of. When you do it like this the post will appear as written if by the page, not your user account.

Luckily the client I am working for was gracious enough to mark me an administrator of their page, but I first tested with Typeoneerror's Fan Page. Go to your own fan page and note the ID in the url for later (hint: it comes after ?id=).

Next, you need to create a Facebook Application. If you haven't yet, you'll need to install the Facebook Developer application. Create an application and give it a name. Note your API Key, Application ID, and Application Secret. The only other thing you should need to change is your Connect URL and Base Domain. Let's just say for example's sake that we'll use http://mydomain.dev/ and mydomain.dev respectively.

Next, you need to authorize your application with some extended permissions. This is quite simple, just point a browser to the following URL, replacing {CLIENT_ID} with your Application ID and {YOUR_DOMAIN} with your Connect URL (note that your URL must have a trailing slash or it may error):

https://graph.facebook.com/oauth/authorize?client_id={CLIENT_ID}&scope=offline_access,publish_stream,create_event,rsvp_event,sms,manage_pages&redirect_uri={YOUR_DOMAIN}

Note the scope parameter. Here we are sending the extended permissions the app wants. If this is your first time authenticating, you'll see a nicely designed window explaining what the app is requesting access to. For our purposes, all we need is offline_access and publish_stream. Offline access will give us a permanent access key, allowing us to make calls to the API without being logged in or authenticated. Publish stream allows the app to, well, publish to your streams.

After you authenticate, you'll be redirected back to YOUR_DOMAIN but now you'll see a query param added to the URL which will look something like:

http://mydomain.dev/?code=1234567890abcdef.

The actual code will be much longer ;) Note it down for later. This is our authentication code that will allow us to get a permanent key. This is not the permanent key quite yet. So how do we get the permanent key? Request one from the access_token service:

https://graph.facebook.com/oauth/access_token?client_id={CLIENT_ID}&redirect_uri={YOU_DOMAIN}&client_secret={APPLICATION_SECRET}&code={YOUR_CODE}

Fire off a cURL request to the above URL, replacing {CLIENT_ID} with your Application ID, {YOUR_DOMAIN} with your Connect URL (make sure it has a trailing slash), {APPLICATION_SECRET} with your Application's Secret Key and {YOUR_CODE} with the code from the previous step. The result should be simply a piece of text that looks like this:

access_token=1234567890abcdef.

Your permanent session access token! Hooray. So let's use it. I'm using the Zend Framework so you'll see some logging includes in this code. You can ignore them. Please read the comments as I noted some tutorial notes in there. Here's the PHP snippet I wrote to post to my Page's wall from an external website. With luck, change the settings noted below and a post will appear on your page's wall too!

require_once "../library/Typeoneerror/Facebook/Library/facebook.php";
require_once "../library/Zend/Debug.php";

// need to turn these options off otherwise
// you will get errors from the API
Facebook::$CURL_OPTS[CURLOPT_SSL_VERIFYHOST] = 0;
Facebook::$CURL_OPTS[CURLOPT_SSL_VERIFYPEER] = 0;

// Replace with your page's ID
$pageId = "YOUR_PAGE_ID";
// Replace with your permanent session key from the last step
$permSess = "YOUR_PERMANENT_ACCESS_KEY";

// create the Facebook API
$facebook = new Facebook(array(
"appId" => "YOUR_APPLICATION_ID",
"secret" => "YOUR_APPLICATION_SECRET",
"cookie" => true,
));

// should log out your page's info.
// simply makes a call to the Graph API
// you don't need a session for this.
$page = $facebook->api("/{$pageId}");
Zend_Debug::dump($page);

// publish to the page
// you do need a session for this.
$rest = $facebook->api(array(
"uid" => $pageId,
"method" => "stream.publish",
"access_token" => $permSess,
"message" => "This is a test. Experimentation with OAuth and permanent sessions on Facebook.",
));

// should log an ID of a created wall post
Zend_Debug::dump($rest);

Did you like this article? Maybe you'll like our company page:

May
16

Install and Deploy Django with MAMP using mod_wsgi

Getting Apache ready for serving Python applications seems to really be a headache. mod_python seems relatively easy, but the preferred mod_wsgi seems to give everyone headaches. I wanted to serve my python applications using MAMP since it's part of my daily workflow. I found a decent solution that is working really well for me with MAMP on OSX (Leopard). You may want to check out my previous post on installing and managing a basic OSX Django Stack before reading this one.

Installing WSGI

To install WSGI, you need to compile it against the version of Apache you'll be using it with. MAMP's current packaged version of Apache is 2.0.63, which is not super new, but will do. If you're like me and you just installed the MAMP binary instead of downloading the source code...well, then you don't have the Apache source code for 2.0.63, do you? So, let's get it!

I had already installed Macports in my previous adventure with Django installs. I decided to see what was available Apache-wise, and lo-and-behold:

$ port search "apache"
apache20 @2.0.63 (www)
    The extremely popular second version of the Apache http server

The exact same version that MAMP is packaged with! Awesome! Let's install it...

$ port install apache20

That'll install Apache in /opt/local/apache20 (or wherever Macports is installing stuff on your machine). Next you'll need to grab the mod_wsgi source from author Graham Dumpleton (thanks, Graham!). Unpack that tar.gz file and fire up terminal and cd into that folder. First read this code section:

mod_wsgi-3.2 $ ./configure

checking for apxs2... no
checking for apxs... /usr/sbin/apxs
checking Apache version... 2.2.14
checking for python... /Library/Frameworks/Python.framework/Versions/2.6/bin/python
configure: creating ./config.status
config.status: creating Makefile

So our basic configure checks for apxs (apache extension tool) and finds the default OSX install – which for me is currently 2.2.14; too new for MAMP. So go ahead and add the --with-apxs flag to the configure and point to wherever Macports installed your apache20:

mod_wsgi-3.2 $ ./configure --with-apxs=/opt/local/apache20/bin/apxs
checking Apache version... 2.0.63
checking for python... /Library/Frameworks/Python.framework/Versions/2.6/bin/python
configure: creating ./config.status
config.status: creating Makefile

Ok, so the Apache version looks right this time. Let's make and install that guy:

$ make
$ sudo make install
chmod 755 /opt/local/apache20/modules/mod_wsgi.so

Cool, so looks like it copied the compiled wsgi module into our apache20 installation. Now we just need to copy it to /Applications/MAMP/Library/modules (your MAMP modules folder).

Fire up MAMP Pro and go to File > Edit Template > Apache httpd.conf. Add the following after the other LoadModule directives:

LoadModule wsgi_module modules/mod_wsgi.so

Ok, that's the install. Stop and start MAMP services and you've got WSGI ready to serve python apps. Next step is to configure a Django site to be served.

Using WSGI

To start, I've commited my "learning" code to github, so you can check out how I'm learning how to set up and use Django on my machine. I'll be referencing these files throughout so grab them if you want them. I'm also assuming you've created a basic Django project and an application. My learning code uses the same code from the introduction tutorial on the djangoproject.com site. My sample code is in a directory called "project" and I have an application called "polls."

First thing you want to do is create a named host like you always do with MAMP. Switch to the hosts panel and hit the "+" button. I called this one "django.dev". In the General settings, point the document root to your project's root; in my case it points to /Library/WebServer/Documents/Django/project.

Now in your django project, create a folder called "apache" and create two files there.

/project/
    /apache/
        apache_django_wsgi.conf
        django.wsgi
    settings.py
    polls
    ...

See the two files and folder stucture on github here. django.wsgi is your primary wsgi application. This is mounted as the root of your website:

import os, sys

# path to parent folder of project
sys.path.append('/Library/Webserver/Documents/Django')
# path to your settings module
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'

# create a wsgi "application"
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

You can see my setup here. apache_django_wsgi.conf is the httpd.conf file for your VirtualHost:

Alias /static /Library/Webserver/Documents/Django/project/static

<Directory /Library/Webserver/Documents/Django/project/media>
Order deny,allow
Allow from all
</Directory>

WSGIScriptAlias / /Library/Webserver/Documents/Django/project/apache/django.wsgi

You can see that mine defines an alias that points to a static folder (where I'll serve my js, css, images from for now) and a WSGIScriptAlias which is the full path to my .wsgi application.

Now back in MAMP, go to the advanced settings of your virtual host and in the "Customized virtual host general settings" add:

Include /Library/Webserver/Documents/Django/project/apache/apache_django_wsgi.conf

This would be the full path to your .conf file in your project. Again, restart MAMP's services. So now when you hit django.dev, the application defined in your .wsgi will be served. django.dev/static/ will be avaiable for you to add static content like js, css, etc. The end.

May
14

Django "Stack" Install with ActivePython on Win/Mac

A current project involves Django, PostgreSQL, and git; three softwares I was pretty much unfamiliar with as a LAMP developer. After some poking around and initial love affair with Python and the idea of Django...well, Django is super-sweet on *nix OSs like Ubuntu, but not so fun to install and use on Windows and the "unix-like" Darwin-based Mac OS. So here's the start of my install guide for Windows. It can easily be applied to Mac since ActivePython is available for Mac as well.

So, the requirements: Python is easy to install; Django is easy to install; MySQL is generally pretty easy to install; the adapters that allow Python to talk to MySQL? Not so much. And what if you want to manage all those python modules you install? Or have virtual environments that match your target deployment environment? Enter ActivePython. ActivePython is essentially a distribution of Python and a number of other programs for managing python and python modules/package. I highly recommend you start with that:

Install ActivePython: http://www.activestate.com/activepython/

I just installed to C:\Python (/Python on Mac).

Now, the creators of the code I'm working with for this project use an application called "pip" (bundled with ActivePython) that allows you to install a list of dependancies from a standard requirements file. You can "install" packages, svn repositories, git repositories, and more. This is easily one of the coolest ways to distribute code I've ever seen. I fully expect this to be a standard development method in the next few years. Anyway, to import these files into pip require require you to have a command line version of git and subversion, so:

Install Git for windows

Options for the install:
- Install git as cmd line tool (not in bash shell)
- Checkout as-is, commit as Unix-style endings

Install Git for OSX

Install Subversion Command line client (CollabNet Subversion Command-Line Client v1.6.11 (for Windows))

On OSX you should have svn already and you shouldn't need to worry too much about line endings. Feel free to upgrade to the latest and greatest.

Now we have what we need to get going: from ActivePython; virtualenv, pip, and pypm; svn; and git.

Make sure you can run both. Open up a cmd prompt or Terminal on OSX:

$ git --version
git version 1.7.0.2.mysysgit.0

$ svn --version
svn, version 1.6.11

Ok, we're good to go. Switch to your drive root or wherever you want to create your virtual environments:

$ mkdir virtualenvs
$ cd virtualenvs

# create a virtual enviroment called "myenv"
$ virtualenv myenv

# OR, if you want the env to not inherit your globally installed python site packages
# which you probably want since installing mysql and postgre plugins in a virtual
# environment is tough since you have to compile them
$ virtualenv --no-site-packages myenv

# activate the environment (windows):
$ myenv\Scripts\activate.bat
(myenv)D:\virtualenvs>

# activate the environment (mac):
# note that scripts are created in "bin" instead of "Scripts"
$ source myenv/bin/activate
(myenv)virtualenvs $

Now running pip will use the pip created when the virtual environment was created, installing packages only in that working environment. So you can have different environments with different packages installed.

Let's install Django as a test first.

# latest
(myenv)virtualenvs $ pip install Django

# or install a specific version
(myenv)virtualenvs $ pip install Django==1.1
Downloading/unpacking Django==1.1
  Downloading Django-1.1.tar.gz (5.6Mb): 5.6Mb downloaded
  Running setup.py egg_info for package Django
Installing collected packages: Django
  Running setup.py install for Django
Successfully installed Django

Next step in my install process was getting the codebase from the client. They used github for version control (replacing client name with dummy copy):

# clone the git repository
(myenv)virtualenvs $ cd D:\Projects\Client\
(myenv)virtualenvs $ git clone git@github.com:client/repository.git

The client's repo had a requirments formatted file that I can then use to install with pip.

# back in our virtual environment, now install the requirements
# the -E flag tells pip which environment to install to.
(myenv)virtualenvs $ pip install -E myenv -r D:\Projects\Client\repository\requirements.txt

This is neat because pip's requirements format allows svn, git, and pypm (pythom package manager) hints in this file. It'll automatically pull in the dependancies using the method specified. Here's an example:

Django==1.1
-e svn+http://django-mptt.googlecode.com/svn/trunk@121#egg=django_mptt-0.3_pre-py2.5-dev
django-flatcontent==0.1.2
-e git://github.com/bartTC/django-frontendadmin.git@53d8ed1fdcd1ef466fb9c8b38ccb2abb77978b1e#egg=django_frontendadmin-0.5-py2.6-dev
django-markitup==0.5.2
django-haystack==1.0.1-final
Whoosh==0.3.9
textile

So we're installing Django 1.1, copying down an svn repo from googlecode, cloning a git repo from github and installing a number of python mods using PyPm. Pretty badass for one command!

If we were on unix or mac (with xcode installed) we could also use pip to compile the mysqldb module, but we have some binary install options on windows. This will install it for all python environments. Not sure how to use this to install to a specific virtual environment: Download MySQL-python-1.2.2.win32-py2.6.exe (1,022.8 KiB). Run the installer and select your ActivePython install when prompted. To test if it works, open cmd prompt and type

$ python
>>> import MySQLdb 

If there's no errors; hey, it worked. On MacOS, it's not quite as fun. I used Macports to download the MySQL5 headers, then I did the following:

# only download the package
(myenv)virtualenvs $ pip install --no-install MySQL-python

Then open the downloaded package and edit site.cfg and uncomment line 13 and add the path to your mysql_config (for me this ended up pointing to the bin folder and mysql_config I downloaded with Macports). After than you can run:

python setup.py build
python setup.py install

There's also a Windows port of the psycopg2 module (PostgreSQL for Python). We happen to be using this for the client project. You'll need to install Postgre 8.x first. Then install this guy. Not going to go into Postgre installation and whatnot since I only know a bit of the basics myself. It was enough to get my Django project up and running:

cd /Projects/Client/repository/web
python manage.py syncdb
pyhton manage.py runserver

Command line is fun. Now, getting WSGI to work with MAMP will be the real challenge.

Apr
22

An HTML5/CSS3 Checklist; A wakeup call; A rambling

Here's a nicely designed support list for css3 and html5. Want to make an application with Canvas? Guess what, no IE users will be able to use it until IE9. So Flash does seem to be quite relevant to the consumer at this time: http://www.findmebyip.com/litmus

Then again, from what I've seen from the browsers that do have a wide array of support for HTML5 (namely, Webkit-based Safari and Chrome, Firefox), Flash as a platform is very much in trouble. The Flash IDE is still a great tool for design and content creation, but in my opinion Adobe is way behind the times with the CS5 release. Developing a game using the engine below would obviously be a lot more work than creating a game using an IDE, but you can see the potential if a company (maybe a certain fruit-based company, maybe Adobe finally releases a version of their software where all the feature additions aren't design-based?) were to make a new IDE that made it easy to create HTML/Canvas-based content: http://www.kesiev.com/akihabara/

Perhaps designers don't have much to worry about, but from a developer's perpective, this looks like something I want to learn ASAP to stay relevant. I love the Flash platform; I love Actionscript; and I'll continue to develop for and support the platform. However, it is impossible to deny forward progress and growth in technology, especially when said platform's creators aren't moving at the speed that the market demands. AIR2 and Android look like a match-made-in-heaven, but they should be available now, not as a coming-soon afterthought after the big iPhone packager push failed. I just worry that Adobe won't be able to catch up.

Anyway, the market isn't demanding Flash; they are demanding devices. I will write code with Objective-C for iPhones and Actionscript for Android. I've made my peace with Apple's Terms and Conditions. It is what it is; a business decision. I refuse to allow personal ideology to effect my options for career development. Apple'll take my money when I want to make money with their system and Adobe'll take my money when I am locked-in to developing with their tools (please don't tell me to get Gimp instead of Photoshop ;)). It's all the same to this guy.

Apr
17

Objective-C: Properties and Instance Vars Gotcha

Learned an important lesson today regarding properties and instance variables (ivars) in Objective-C today. For example, consider the following interface and implementation:

@interface MyButton : UIButton
{
    NSString *label;
}

@property (nonatomic, copy) NSString *label;

@end

@implementation MyButton

@synthesize label;

@end

Now, inside my button class if I reference label:

label = @"Click Me!";

This directly accesses the ivar (NSString *label) and not the @property. To access the property, you would use self:

self.label = @"Click Me!";

The important thing to note here is that if you access the ivar directly, you are bypassing the getters/setters created by the synthesized property. I was having issues where variables I created were not being retained, and adding "self." solved it, leading me to this realization that I wasn't actually accessing the property. My new style for reminding me when I'm accessing an ivar or property is my old tried-and-true method for differentiating private vars in Actionscript or PHP; the underscore:

@interface MyButton : UIButton
{
    NSString *_label;
}

@property (nonatomic, copy) NSString *label;

@end

@implementation MyButton

@synthesize label=_label;

@end

Check the difference above. I changed the synthesize statement to point to a differently named instance var. So when I access "self.label," it will modify _label through the getter/setter. You can also use _label inside the instance to directly access the ivar.

prev 1 2 3 4 next

Products

Goodies

T1EOS

Content Management System T1EOS: Content Management System

Our customized content management framework T1EOS manages articles, blogs, categories, events, tagging, images & galleries, a Facebook Connect integrated commenting system, and more — all out-of-the-box.

github

ASRA

A Simple Restful API

ASRA is a lightweight package that assists in the rapid development of simple APIs for exporting data for Flash, Flex or other applications.

Download

Plum Dumb

A Typeoneerror TextMate Theme Plum Dumb