Yak Shaving

just me

Archive for January, 2009

bit.ly Competition Entry

without comments

Below is the raw code to make a Google App Engine application with the really basic bit.ly api. Theres currently no error checking etc.

If you just want the functionality use the BitLy class in your App Engine code. Currently is just returns simple for you to use. So for example with shorten to access the the hash you would use: json['results'][urlentered]['hash']. Replace the url entered with the url you supplied.

Any questions please email ch at chrishannam dot co dot uk

import cgi

from django.utils import simplejson

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from google.appengine.api import urlfetch

class Index(webapp.RequestHandler):
	def get(self):

		EXPAND = "expand"
		SHORTEN = "shorten"
		INFO = "info"
		STATS = "stats"
		ERRORS = "errors"

		bitly = BitLy('your_login','your_apikey')

		self.response.out.write('')
		self.response.out.write(bitly.expand('31IqMl'))
		self.response.out.write(bitly.shorten('http://www.chrishannam.co.uk'))
		self.response.out.write(bitly.info('31IqMl'))
		self.response.out.write(bitly.stats('http://bit.ly/31IqMl'))
		self.response.out.write(bitly.errors())
		self.response.out.write('')

class BitLy():
	def __init__(self, login, apikey):
		self.login = login
		self.apikey = apikey

	def expand(self,param):
		request = "http://api.bit.ly/expand?version=2.0.1&shortUrl=http://bit.ly/"
		request += param
		request += "&login=" + self.login + "&apiKey=" +self.apikey

		result = urlfetch.fetch(request)
		json = simplejson.loads(result.content)
		return json

	def shorten(self,param):
		url = "http://" + param
		request = "http://api.bit.ly/shorten?version=2.0.1&longUrl="
		request += url
		request += "&login=" + self.login + "&apiKey=" +self.apikey

		result = urlfetch.fetch(request)
		json = simplejson.loads(result.content)
		return json

	def info(self,param):
		request = "http://api.bit.ly/info?version=2.0.1&hash="
		request += param
		request += "&login=" + self.login + "&apiKey=" +self.apikey

		result = urlfetch.fetch(request)
		json = simplejson.loads(result.content)
		return json

	def stats(self,param):
		request = "http://api.bit.ly/stats?version=2.0.1&shortUrl="
		request += param
		request += "&login=" + self.login + "&apiKey=" +self.apikey

		result = urlfetch.fetch(request)
		json = simplejson.loads(result.content)
		return json

	def errors(self):
		request += "http://api.bit.ly/errors?version=2.0.1&login=" + self.login + "&apiKey=" +self.apikey

		result = urlfetch.fetch(request)
		json = simplejson.loads(result.content)
		return json

application = webapp.WSGIApplication(
                                     [('/', Index)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

Written by channam

January 23rd, 2009 at 12:35 am

Posted in App Engine, bit.ly

Excellent Cartoon

without comments

Written by channam

January 12th, 2009 at 9:17 pm

Posted in social media

New Development Approach

without comments

Currently watching a TV programme about swarms. There was a fantastic part where wildebeest cross a river. Using a form of collective intelligence they all cross as the same place. However, they struggle to get up the side of the river bank. The force of more wildebeest arriving forces the ones in front to find a way up the side of the bank. The brute force and sheer number of the heard eventually find a way up the side.

This approach made me think that’s its not unlike some code development. Enough people trying enough different ideas until eventually success is found and the idea spread among the developers.

Written by channam

January 12th, 2009 at 9:03 pm

Posted in Uncategorized

iPlayer has Linux Application Finally

without comments

iPlayer has finally released a download client. Its an Adobe Air app instead of Kontiki based client and it rocks.

Good work all involved.

Now if I could just wire up the app to dbus…

Written by channam

January 11th, 2009 at 3:46 pm

Posted in Uncategorized

Woe is pylast.py

without comments

Well it tested OK my local machine but deploying it to Google created some issues. In short its just CPU hungry:

01-04 03:39PM 50.602

This request used a high amount of CPU, and was roughly 2.1 times over the average request CPU limit. High CPU requests have a small quota, and if you exceed this quota, your app will be temporarily disabled.

I removed some of the xml processing as by default it gets everything you might need. This sped it up slightly but still the fatal 500 error appeared.

Well for once it appears I was right to reinvent the wheel.

Written by channam

January 5th, 2009 at 12:54 am

Posted in App Engine, code

Making pylast.py play with Google App Engine

without comments

I have been playing with Google App Engine and last.fm’s api for a while now. I made the standard mistake of not checking if anyone else had written a library in Python to do the hard work for me. So, after a little googling I found pyLast which is a great piece of work by Amr Hassan. After a little playing I found that it didn’t play well with App Engine. This was down to the it not using urlfetch, which is no big surprise as thats a feature unique to App Engine. I also noticed it was missing the ability to fetch the date and start time of an event.

So below is a patch to App Engine up the code and fetch the date/time of an event. There is a slight oddity I have yet to figure out, the time gets appended to the date. I cant see any sane reason why currently.

Be warned this breaks the module for standard Python use unless you are have google.appengine.api kicking around in your module path.

If you wish to try out my App Engine app its over at Cassandra. Just enter the name of the artist to find out where they are playing displayed on Google Maps. Its very much an ongoing project…

diff pylast.py pylast.py.orig
37d36
< from google.appengine.api import urlfetch
286,287c285,292
< 			request = 'http://' + API_SERVER + API_SUBDIR + '?method=' + '&'.join(data)
< 			response = urlfetch.fetch(request)
---
> 			conn = httplib.HTTPConnection(API_SERVER)
> 			headers = {
> 				"Content-type": "application/x-www-form-urlencoded",
> 				'Accept-Charset': 'utf-8',
> 				'User-Agent': __name__ + '/' + __version__
> 				}
> 			conn.request('POST', API_SUBDIR, '&'.join(data), headers)
> 			response = conn.getresponse()
292c297
< 		doc = minidom.parseString(response.content)
---
> 		doc = minidom.parse(response)
404a410
>
1391,1392d1396
< 		data['date'] = self._extract(doc, 'startDate')
< 		data['time'] = self._extract(doc, 'startTime')
1482,1497c1486
<
< 	def getStartDate(self):
< 		"""Returns the start date of the event """
<
< 		return self._getCachedInfo('date')
<
< 	def getStartTime(self):
< 		"""Returns the start time of the event """
<
< 		return self._getCachedInfo('time')
<
< 	def getReviewCount(self):
< 		"""Returns the number of available reviews for this event. """
<
< 		return self._getCachedInfo('reviews')
<
---
>

Written by channam

January 5th, 2009 at 12:20 am

Posted in App Engine, code