Serotonin Storm

source>fixtures>blog.json
1
[{"pk": 1, "model": "blog.category", "fields": {"slug": "django", "title": "Django"}}, {"pk": 5, "model": "blog.category", "fields": {"slug": "google", "title": "Google"}}, {"pk": 4, "model": "blog.category", "fields": {"slug": "photography", "title": "Photography"}}, {"pk": 2, "model": "blog.category", "fields": {"slug": "python", "title": "Python"}}, {"pk": 3, "model": "blog.category", "fields": {"slug": "web", "title": "Web"}}, {"pk": 4, "model": "blog.post", "fields": {"body": "This is the story of implementing Google Voice functionality in Python\r\n\r\nLet me start this off by saying that there is no official API for Google Voice. Voice was a product developed by GrandCentral and then subsequently bought out by Google. The tricky part about this transfer was the terms of service which Google has adapted and modified. In Google's ToS (which they inherited from GrandCentral) they outline the service for personal, non-commercial use only.\r\n\r\n`GRANT OF RIGHTS TO USE SERVICES. Effective upon acceptance of this Agreement, Google Voice hereby grants to Subscriber a personal, nonexclusive, nontransferable, revocable license to access and use the Services (as defined below), for Subscriber's non-commercial use.`\r\n\r\nThis probably means that Google is not going to get around to making an API anytime soon. Not feeling like waiting around for Google, it was time to hack at it. \r\n\r\nThe interesting thing about Voice is that it uses a very particular API for its web interface, but Google has yet to publish documentation anywhere for it. The web app just makes a series of authenticated HTTPS requests to the Voice server, which allows it to place calls, send sms messages, and *most* of the communication is done with xml. I say most because the standard data format is wrapped in an ugly XML envelope. Here is what a typical response looks like\r\n\r\n    :::xml\r\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n    <response>\r\n      <json><![CDATA[{\"messages\":{\"3b8d9d77...]]></json>\r\n      <html><![CDATA[\r\n        <div id=\"3b8d9d77...\"\r\n             class=\"goog-flat-button gc-message gc-message-read\">\r\n        <div class=\"gc-message-bg\">\r\n        ...      \r\n        ]]></html>\r\n    </response>\r\n\r\nNotice that there are both JSON and HTML payloads contained inside the XML envelope, which have to be parsed separately. Parsing the JSON in Python2.5 is easy with [simplejson](http://code.google.com/p/simplejson/) and natively in Python>=2.6 with the [json](http://docs.python.org/library/json.html) module. The data contained in that section has only a portion of the interesting data, which makes full data retrieval a royal pain in the ass. The rest of the good stuff is stored awkwardly in the HTML payload, and contains such niceties as sms message text, voicemail/call transcription, and caller thumbnails. \r\n\r\nEven without the commercial issues, there is an interesting social networking application that would allow you to broadcast a quick call/message to a local group of friends, like \"hey! let's get together\".  The API would be useful even for interesting non-commercial social networking use. Hopefully in the future, regardless of API, there will be a whole generation of apps that will find a way to use this functionality. To that effect, [PyGoogleVoice](http://code.google.com/p/pygooglevoice/) has appeared on the scene. It currently allows you to place calls, send sms, download voicemails/recorded messages, and search the various folders of your Google Voice Accounts. Here is some example usage\r\n\r\n\r\n    :::python\r\n    from googlevoice import Voice\r\n    voice = Voice()\r\n    voice.login('myusername@gmail.com','mypassword')\r\n    voice.call('18004664411', '14075551234')\r\n\r\nAnd it can be extended to other platforms as well. Someone has already found a way to have the service [interact with Asterisk to create a really sweet PBX setup.](http://nerdvittles.com/?p=635) \r\n\r\nThe lack of a solidified API from Google means that they are free to change things around at will. \r\n", "status": 2, "allow_comments": 1, "author": null, "tease": "The emerging concept of a Google Voice API", "modified": "2009-09-16 10:24:01", "publish": "2009-09-16 10:24:00", "created": "2009-08-11 23:48:39", "categories": [5, 2, 3], "title": "Hacking Away at Voices in The Ether", "slug": "hacking-away-at-voice", "tags": ""}}, {"pk": 3, "model": "blog.post", "fields": {"body": "I love the site [Digital Blasphemy](http://digitalblasphemy.com) and the photos they produce. The best feature of their site is their [free gallery](http://digitalblasphemy.com/freegallery.shtml) section which provides a lot of their premium content for free. They rotate this collection often, so there are always new impressive images. On the site they are nice, but I wanted all of them on my desktop without paying for their service.\r\n\r\n<p>The solution I came up with is this python script that follows. It grabs all the images from their free gallery and downloads them into your Pictures folder.</p>\r\n\r\n    :::python\r\n    #!/usr/bin/env python\r\n\r\n    from urllib import urlopen, urlretrieve\r\n    from os import path\r\n    \r\n    site = 'http://digitalblasphemy.com'\r\n    ddir = path.expanduser('~/Pictures/')\r\n    find = lambda s,p: s.find(p) > -1\r\n    width = '1280'\r\n    \r\n    for l in urlopen('%s/freegallery.shtml' % site).readlines():\r\n        if find(l, 'w=%s' % width):\r\n            for u in ['%s/fshow%s' % (site, x.split('\">')[0]) \\\r\n             for x in l.split('fshow') if find(x, 'w=%s' % width)]:\r\n                for xl in urlopen(u).readlines():\r\n                    if find(xl, 'width=\"%s\"' % width):\r\n                        p = xl.strip().split('src=\"')[1].split('\"')[0]\r\n                        fn = path.join(ddir, path.basename(p))\r\n                        if not path.isfile(fn): urlretrieve(site+p, fn)\r\n\r\n<p>Short, sweet, and completely unintelligible. Just be glad it works. Also for those of you playing along at home, that runs in O(N<sup>4</sup>), which his absolutely horrendous, but performance was not a huge concern since it takes about all of 3 seconds to fetch every image. And the results speak for themselves</p>\r\n\r\n<center>\r\n<img src=\"http://serotoninstorm.com/media/static/img/blasphemy.png\"/>\r\n</center>\r\n\r\n\r\n\r\nI personally put this script into a cron job and run it every so often. It dumps the images into my Pictures folder, which I set my desktop background to randomly rotate through. They do not update their free gallery very often, but its a nice surprise to see an awesome backround appear out of no where.", "status": 2, "allow_comments": 1, "author": null, "tease": "Capturing Digital Blasphemy's free gallery", "modified": "2009-09-03 20:56:20", "publish": "2009-08-11 15:23:34", "created": "2009-08-11 15:24:23", "categories": [4, 2, 3], "title": "Digital Blasphemy - Blasphemy", "slug": "blasphemy", "tags": ""}}, {"pk": 1, "model": "blog.post", "fields": {"body": "<p>\r\nWelcome to django-mingus, the Django powered blog engine.\r\n</p>", "status": 2, "allow_comments": 1, "author": null, "tease": "Hey there world.", "modified": "2009-07-01 23:22:04", "publish": "2009-07-01 23:19:39", "created": "2009-07-01 23:20:29", "categories": [1], "title": "Welcome", "slug": "welcome", "tags": "blog, mingus"}}]