- Calendar -

March 2010
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

- Archive -

- Browse By Random Tag -

- Most Commented -

- Random Favourites -

- Blogs I Like -

- Email Viruses Received -

- My Geek Code -

-BEGIN GEEK CODE BLOCK-
Version: 3.12
GIT d-- s: a- C++ UL++ P+++ L+++ E--- W+++ N+ o-- K- w--- O- M-- V- PS+++ PE-- Y++ PGP t++ 5+++ X R tv b+ DI+ D++ G e h r+ y+
--END GEEK CODE BLOCK--
Get The Encoder
Get The Decoder

- My Blog Code -

-BEGIN BLOG CODE BLOCK-
B6 d+ t++ k+ s++ u-- f i++ o+ x+ e l c-- --END BLOG CODE BLOCK--
Blog Code Encoder
Blog Code Decoder

- The Internet is Cool -

- Nifty Blog Toys -

RSS Feed

- Content License -

Blog

Unrepresented

So that word is floating around again "Prorogue". For those of you who missed it, I'm sorry to be the one to break it to you, but we've all been without representation in the federal government now for almost a month now. Stephen Harper, our Prime Minister decided to shut down parliament back in December and won't be affording us representation until some time in March.

That's three months paid vacation for a parliament that sat for only 49days last year. Three months without the business of government being done, without your voice being heard in the House. Sure Harper still gets to be the boss and represent Canada abroad and at the Olympics, and no, our soldiers in Afghanistan don't get to take a break. Addressing our commitments on climate change won't happen by the Copenhagen deadline, and we're all still paying taxes for the privilege of living in a democracy.

People have staged (successful) revolutions for less.

In Canada though, where we once saw only apathy, there appears to be some exciting movement among the grass roots. Hundreds of thousands of people have joined a Facebook group denouncing Harper's Conservatives for this move and the numbers keep growing. Support for the Conservatives has begun to dwindle as well and now there are rallies planned around the world in condemnation of this prorogue.

Here's a list of what proroguing means to Canada:

  1. Committees investigating accusations of torture of Afghan detainees stop working.
  2. Questions about Canada's inaction at the Copenhagen climate-change summit are silenced. Opportunities to move forward with Canada’s plan for sustainable development are stalled for over a month.
  3. Discussions and decisions about the pension crisis affecting Canada’s seniors stops.
  4. All 37 bills being debated in Parliament are thrown in the trash. Discussion on bills starts from scratch in March, wasting months of hard work by all parties. These bills included new crime legislation, and limits on credit card insurance rates, etc.
  5. Your MP cannot raise your concerns in Ottawa
  6. Harper will still appoint Conservative senators, giving him control of the Senate.

Frankly, it's actions like these that make it hard for me to claim that I live in a democracy. Instead, it might be more accurate to say that we've become a cyclical banana republic. As for what the other parties are saying...

  • The Liberals have flat-out said that they're going back to work with or without the Conservatives on January 25th, the original date that Parliament would have reconvened.
  • The NDP have similarly said that they will be "on Parliament Hill" on the 25th, though I'm unsure as to what that means exactly.
  • The Bloc Québécois have condemned the prorogation but as far as I can tell, have not said anything about showing up to work.
  • The Greens, not in possession of a seat (yet) also condemned the Harper move and will be out at the rallies tomorrow across the country as well.

So what can you do? Some suggestions:

  • Tell your friends and family about this. A lot of people still don't know that they're paying taxes to a non-existent government and the Conservatives are counting on an ignorant public to keep them in power. Don't let them have it.
  • Join in on one of the rallies this Saturday, January 23rd. They're happening all over the world in Vancouver, Toronto, New York, Amsterdam and even Costa Rica. Details are on noprorogue.ca. Vancouver's rally starts at 1pm at the VAG, while Toronto's starts at 1pm at Dundas Square.
  • Call your MP. If (s)he's a Conservative, tell them to get back to work. If they aren't, tell them to consider all alternatives for bringing democracy back to our government. The Coalition is still an option, if only the opposition parties can learn to get along.

I'll be at the event in Vancouver, so if you care to come along, let me know and we can meet up :-)

It's a Wonderful Life

A lot of people have read this thinking that it was an exercise in self-loathing or a cry for help of sorts. Nothing could be further from the truth. It was purely an existential question based in the thinking that at the core, humanity hasn't changed that much through the course of our history. New titles, different roles is all. Anyway, thanks for the support everyone, but I'm fine, honest :-)

You know how in that movie, George Bailey finds out just what the world would be like if he'd never existed? The moral of the story is supposed to be how significant your own minor contributions have been to the tapestry of your life, but I was just thinking...

In the grand scheme of things, the unremarkable of us (that is to say, pretty much everyone but a remarkable few) don't really have lasting effects on the world as a whole. Rather, our greatest effects, if we have any at all, are usually on those we care about, those to whom we are closest.

Given this reality, is this idea that we are somehow integral to "the world" in our own small way, really just a egocentric fantasy? How different would the world really be if one of us never existed? Wouldn't it be more honest to say that the tiny part of the world about which we care the most would be different? Isn't it a bit presumptuous to think that every one of us is integral to the balance of society?

Humanity hasn't changed much in the last few thousand years. Sometimes, I wonder if any of us really matter at all.

Facebook Page Syncronisation

This is going to be a rather technical post, coupled with a smattering of rants about Facebook so those of you uninterested in such things might just wanna skip this one.

As part of my work on my new company, I'm building a syncroniser for status updates between Twitter, Facebook, and our site. Eventually, it'll probably include additional services like Flickr, but for now, I'm just focusing on these two external systems.

A Special Case

Reading this far, you might think that this isn't really all that difficult for either Twitter or Facebook. After all, both have rather well-documented and heavily used APIs for pushing and pulling data to and from a user's stream, so why bother writing about it? Well for those with my special requirements, I found that Facebook has constructed a tiny, private hell, one in which I was trapped for four days over the Christmas break. In an effort to save others from this pain, I'm posting my experiences here. If you have questions regarding this setup, or feel that I've missed something, feel free to comment here and I'll see what I can do for you.

So, lets start with my special requirements. The first stumbler was the fact that my project is using Python, something not officially supported by Facebook. Instead, they've left the job to the community which has produced two separate libraries with different interfaces and feature sets.

Second, I wasn't trying to syncronise the user streams. Instead, I needed push/pull rights for the stream on a Facebook Page, like those created for companies, politicians, famous people, or products. Facebook claims full support for this, but in reality it's quite obvious that these features have been crowbared into the overall design, leaving gaping holes in the integration path.

What Not to Do

  • Don't expect Facebook to do the right/smart thing. Everything in Facebookland can be done in one of 3 or 4 ways and none of them do exactly what you want. You must accept this.
  • Don't try to hack Facebook into submission. It doesn't work. Facebook isn't doing that thing that makes sense because they forgot or didn't care to do it in the first place. Accept it and deal. If you try to compose elaborate tricks to force Facebook's hand, you'll only burn 8 hours, forget to eat or sleep in the process and it still won't work.

What to Do

Step 1: Your basic Facebook App

If you don't know how to create and setup a basic canvas page in Django, this post is not for you. Go read up on that and come back when you're ready.

You need a simple app so for starters get yourself a standard "Hello World" canvas page that requires a login. You can probably do this in minifb, but PyFacebook makes this easy since it comes with handy Django method decorators:

# views.py
from django.http import HttpResponse, HttpResponseRedirect
import facebook

@facebook.djangofb.require_login()
def fbCanvas(request):
    return HttpResponse("Hello World")
Step 2: Ask the User to Grant Permissions

This will force the user to add your application before proceeding, which is all fine and good but that doesn't give you access to much of anything you want, so we'll change the view to use a template that asks the user to click on a link to continue:

# views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
import facebook

@facebook.djangofb.require_login()
def fbCanvas(request):
    return render_to_response(
        "social/canvas.fbml",
        {},
        context_instance=RequestContext(request)
    )

Note what I mentioned above, that we're asking the user to click on a link rather than issuing a redirect. I fought with Facebook for a good few hours to get this to happen all without user-input and it worked... sometimes. My advice is to just go with the user-clickable link. That way seems fool-proof (so far).

Here's our template:

<!-- canvas.fbml -->
<fb:header>
    <p>To enable the syncronisation, you'll need to grant us permission to read/write to your Facebook stream.  To do that, just <a href="http://www.facebook.com/connect/prompt_permissions.php?api_key=de33669a10a4219daecf0436ce829a2e&v=1.0&next=http://apps.facebook.com/myappname/granted/%3fxxRESULTTOKENxx&display=popup&ext_perm=read_stream,publish_stream,offline_access&enable_profile_selector=1">click here</a>.
</fb:header>

See that big URL? It's option #5 (of 6) for granting extended permissions to a Facebook App for a user. It's the easiest to use and hasn't broken for me yet (Numbers 1, 2, 3 and 4 all regularly complained about silly things like not having the app instaled when this was not the case, but your milage may vary). Basically, the user will be directed to a page asking her to grant read_stream, publish_stream, and offline_access to your app on whichever pages or users she selects from the list of pages she administers. Details for modifying this URL can be found in the Facebook Developer Wiki.

Step 3: Understanding Facebook's Hackery

So you see how in the previous section, adding enable_profile_selector=1 to the URL will tell Facebook to ask the user to specify which pages to which she'd like to grant these shiny new permissions? Well that's nifty and all, but they don't tell you which pages the user selected.

When the permission questions are finished, Facebook does a POST to the URL specified in next=. The post will include a bunch of cool stuff, including the all important infinite session key and the user id doing all of this, but it doesn't tell you anything about the choices made. You don't even know what page ids were in the list, let alone which ones were selected to have what permissions. Nice job there Facebook.

Step 4: The Workaround

My workaround for this isn't pretty, and worse, depends on a reasonably intelligent end-user (not always a healthy assumption), but after four days cursing Facebook for their API crowbarring, I could come up with nothing better. Basically, when the user returns to us from the permissioning steps, we capture that infinite session id, do a lookup for a complete list of pages our user maintains and then bounce them out of Facebook back to our site to complete the process by asking them to tell us what they just told Facebook. I'll start with the page defined in next=:

# views.py
@facebook.djangofb.require_login()
def fbGranted(request):

    from cPickle import dumps as pickle
    from urllib  import quote as encode

    from myproject.myapp.models import FbGetPageLookup

    return render_to_response(
        "social/granted.fbml",
        {
            "redirect": "http://mysite.com/social/facebook/link/?session=%s&pages=%s" % (
                request.POST.get("fb_sig_session_key"),
                encode(pickle(FbGetPageLookup(request.facebook, request.POST["fb_sig_user"])))
            )
        },
        context_instance=RequestContext(request)
    )
# models.py
def FbGetPageLookup(fb, uid):
    return fb.fql.query("""
        SELECT
            page_id,
            name
        FROM
            page
        WHERE
            page_id IN (
                SELECT
                    page_id
                FROM
                    page_admin
                WHERE
                    uid = %s
            )
    """ % uid)

The above code will fetch a list of page ids from Facebok using FQL, and coupling it with the shiny new infinite session key, bounce the user out of Facebook and back to your site where you'll use that info to re-ask the user about which page(s) you want them to link to Facebook.

Step 5: Capture That page_id

How you capture and store the page id is up to you. For me, I had to create a list of organisations we're storing locally and let the user compare that list of organisations to the list of Facebook Pages and make the links appropriately. Your process will probably be different. Regardless of how you do it, just make sure that for every page you wish to syncronise with Facebook, you have a session_key and page_id.

Step 6: Push & Pull

Because connectivity with Facebook (and Twitter) is notonoriously flakey, I don't recommend doing your syncronisation in real-time unless your use-case demands it. Instead, run the code via cron, or better yet as a daemon operating on a queue depending on the amount of data you're playing with. However you do it, the calls are the same:

import facebook

# Setup your connection
fb = facebook.Facebook(settings.FACEBOOK_API_KEY, settings.FACEBOOK_SECRET_KEY)
infinitesessionkey = "your infinite session key from facebook"
pageid             = "the page id the user picked"

# To push to Facebook:
fb(
    method="stream_publish",
    args={
        "session_key": infinitesessionkey,
        "message":     message,
        "target_id":   "NULL",
        "uid":         pageid
    }
)

# To pull from Facebook:
fb(
    method="stream_get",
    args={
        "session_key": infinitesessionkey,
        "source_ids": pageid
    }
)["posts"]

Conclusion

And that's it. It looks pretty complicated, and... well it is. For the most part, Facebook's documentation is pretty thorough, it's just that certain features like this page_id thing appear to have fallen off their radar. I'm sure that they'll change it in a few months though, which will make my brain hurt again :-(

Abstract Sequential

I was up late last night. Very late. So late that it had stopped being late and moved well into being mid-morning before I finally passed out. I should probably look into that, but it was fun ;-)

So what was I doing until 1030 on New Years Day? Blogging and writing code of course. My previous post was only the first of two, the second of which is really long and all about my Facebook/Python/Django experiences. It's not finished/polished yet though, so I haven't published it yet.

In addition to those two posts though, I was also inspired by this post on Stephanie's blog about thinking styles to write a Javascript-managed quiz based word-for-word on the pen and paper quiz she pointed to there. For the most part, it was just an exercise for me in how to improve my Jquery-foo, but the subject of the test is fun and interesting too. I'm apparently an "Abstract Sequential" thinker which means that I like things done one way: the right way, and I'm not very good on picking up non-verbal cues. I ranked rather high in both "Abstract Random" and "Concrete Random" too though.

Anyway, if you're so inclined, I've posted the test here. Take it, and let me know what you are!

The Once and Future Me (MMX)

I noticed a number of people posting on Twitter today with the tag #10yearsago and it got me thinking of my actions over this past decade. I started asking questions like what was life like for me back in 2000? What's changed in the world, and what's changed in me over the course of these ten years? More than anything, my father's voice keeps coming up, telling me how life moves so fast. "Blink", he says, "and you're ten years older", and he's exactly right.

Ten years ago, I was still living with my parents in Langley. I claimed to be an environmentalist, while driving 33km to and from work every day and was dying to get the hell out of this province and into the world. My understanding of who I was, and what I wanted was still quite fragile, but at least I was beginning to comprehend that knowing these things was important.

Since then, I've run away from this place and seen the world -- admittedly only few pieces of it, but more than many people around here bother to see in a lifetime. I've lived in the biggest city in Canada, embraced volunteerism and politics and furthered my understanding of the answers to those two important questions.

To be honest, it's hard not to look back on the last ten years of my life and not be pleased with my experiences. I've made a good many mistakes (even made the same ones more than once), but on the whole, I think that I've done good for this world and been true to myself and those I care about. I've learnt more about who I am and what I want than I thought possible, and have no doubt that there's still a great deal more to take in. If my next ten years are as rich as the last, I will be a lucky man.

My concern however is rooted in my father's voice. Indeed, this time has passed quite quickly: I remember having lunch with my father days after 9/11 like it was yesterday, and some days it feels like I'd only recently abandoned Vancouver for a bigger, better life in Toronto... How did I do all of that in just ten years? How much time is left?

There is a life that I want out there, a person I want to be -- is there time remaining to become that man, to build the life I want? Is it folly to try to do both at the same time, or even to convince myself that that life can be achieved? And what if the needs of the various parts of that life are in conflict? When 2020 rings in, and I am 40 years old, will I be able to look back on these next ten years as favourably as those that just passed?

It's a hell of a thing to ask so much of a mere passage of time, but this is who I want to be and what I want out of this life. It may not happen. It may all go sideways. But the path will be mine.

pit-faulty