Needs cleanup, but this at least runs on AppEngine