/birdhouse

BirdHouse is a Titanium Developer plugin for authenticating and sending API calls to Twitter. (Currently tested on Linux and Mac Titanium Mobile 1.6.1 with Android 1.6, 2.2, and iPhone 4.3.)

Primary LanguageJavaScript

==============
BirdHouse v0.5
==============

Installation & Implementation
=============================

1. Twitter Application Settings
-------------------------------

First of all, make sure that you have registered an application with Twitter at http://dev.twitter.com and that the application's type is "Browser" (not "Client"). Also, you will need to set a callback url that has no redirects on that page--if the url redirects the OAuth sequence will not work.

Also, if you would like tweeps who use your application to be able to update their status (i.e. send tweets) then be sure to set "Default access type" to "Read & Write" in the application settings.

2. Get Dependencies
-------------------

Go to: http://oauth.googlecode.com/svn/code/javascript/

    a. oauth.js
    b. sha1.js

3. Include and Initialize BirdHouse Class
-----------------------------------------

Ti.include('birdhouse.js');

var BH = new BirdHouse({
    consumer_key: "yourappsconsumerkey",
    consumer_secret: "yourappsconsumersecretwhichislonger",
    callback_url: "http://yourappsEXACTcallbackurl.com" // only necessary for overridding
});

4. Authorize or Make an API Call
--------------------------------

At this point you can call six different functions:

    - authorize: this initiates the authorization sequence, storing credentials in the app's directory in a file called 'twitter.config', returns void
    - deauthorize: deletes the 'twitter.config' so the app no longer has the access tokens
    - authorized: returns bool whether or not the user is authorized
    - get_tweets: returns the last 20 tweets as an object (not as a string)
    - tweet: opens a tweet dialog box with the given text, sends the tweet upon hitting the "tweet" button, and returns the response from twitter, which will be the tweet itself, as an object (not as a string)
    - api: sends an api call to the given url by the given method with the given parameters which should be in url form, i.e. "count=20&since_id=13343859", and then returns the evaluated response; the responses are evaluated by:

        return eval('('+XHR.responseText+')');

With any call, if the user is not authorized it will initiate the authorization process, thus, there is no need to initiated the authorization process before hand unless, for some reason, you wanted to get it out of the way. So, for example, to get the latest tweets,

    var tweets = BH.get_tweets();

Note that with most of these functions you can send a callback function. Because the XHR requests will be completed AFTER the functions have already sent a return value, in order to tell whether or not an API request was made successfully, you will need to use a callback, such as:

    BH.get_tweets(function(e){
        if (e===false) {
            // it failed
        } else {
            // it worked
        }
    });

How BirdHouse Authorizes with Twitter
=====================================

This script does not use the OOB (Out-Of-Band) method, the one where it gets the pin. It actually does something pretty slick. After getting the request tokens, it opens a WebView that sends the user to the authorization page on Twitter's site, and listens for when the page has redirected to a page with the 'oauth_verifier' in the url, which the page will be the app's callback url (or the callback url override if specified).

Note 1: As a quick note here, if the app's callback url immediately redirects to another page, the listener won't pick up that the url has changed until it finally hits the resultant page, and the 'oauth_verifier' token will be lost. So make sure whatever page the callback goes to does not have redirects set.

Note 2: A few if statements had to be made on the event that someone clicks "denY" or "sign up for an account". In both cases, the window immediately closes. It would be very expensive in terms of time to figure out what URL's are used when making an account and upon success redirect back to the allow screen, so this option is killed.

So, once the redirected to the callback url it extracts the oauth_verifier variable from the url and stores it. Then, that token, combined with the request token, is exchanged for access tokens which are then stored and can be re-used over and over. Finally, if we are authorized and a callback function is set then call it. So, the general process looks like:

1. Get the Request Token

    a. Make API request
    b. Store the request token and token secret in cfg

2. Get the Request Verifier

    a. Open up a webview to Twitter's site with the request token
    b. If 'account' or 'suspended' are in the URL, the user has
       clicked 'sign up', so kill the process
    c. Else if 'Redirect' is not in the HTML title of the page,
       we know the user has clicked 'deny', so kill the process
    d. Else, we know the user clicked 'allow', so begin listening
       for the keys in the URL
    e. When webview has redirected to the Twitter app's callback,
       grab the request verifier from the URL
    f. Store the verifier in cfg
    g. Close the webview

3. Get the Access Token

    a. Make API request
    b. Store the request token and token secret in cfg
    c. Save the cfg in twitter.config file

4. Callback

    If a callback function is set, call it and send whether or not we are
    authorized.

Debugging
=========

Check out the "debug" branch for a version of BirdHouse that has a ton of debug outputs so you can see better what is going on. Please report on GitHub any issues or suggestions!

    http://github.com/jpurcell/birdhouse/issues

Also, check out the Wiki for FAQ and additional info.

    http://github.com/jpurcell/birdhouse/wiki

To Do
=====

1. More testing with other API calls
2. Add as much customization as possible
3. Better documentation and code comments
4. Make a test app.js

Known Issues
============

There are no known issues at this time.

Credits
=======

This code came from a lot of debugging, implementing some of my own ideas, and I must give credit to the people I got a lot of the code from:

    - Netflix for the oauth.js, 
    - Paul Johnston and crew for sha1.js,
    - The oauth developers who made the examples here:
        http://oauth.googlecode.com/svn/code/javascript/
    - David Riccitelli for his script that is awesome, but doesn't work on Android,
        http://code.google.com/p/oauth-adapter/
    - Ketan Majmudar for modifying the oauth-adapter for Android,
        https://github.com/stereoket/oauth-adapter
    - Mike, my colleague at iEntry who initiated the BirdHouse project in PHP.