Google Street View Image API

One of the many cool APIs available through Google Maps is the Street View Image API. This gives you full access to the images taken by the Google vans that photograph streets.

The API is dead simple in the basic form, just a URL:

http://maps.googleapis.com/maps/api/streetview?size=WIDTHxHEIGHT&location=LOCATION&sensor=false

(The required “sensor” param tells Google if you are getting the location from a GPS device or similar – probably a privacy thing.)

The images are not necessarily spectacular brochure shots:

http://maps.googleapis.com/maps/api/streetview?size=400x400&location=Parliament+Square,+London&sensor=false

Unspectacular Street View of Parliament Square, London

but it is a useful API for any app that is displaying places that a user might not have been to before. It can both give them an idea of it’s the kind of place they are looking for and help them find it. Here’s an example, a local keycutters:

http://maps.googleapis.com/maps/api/streetview?size=400x400&location=Timpson,+Victoria+Station,+London&sensor=false

Street View of Timpson key cutters at Victoria Station, London

CoffeeScript Web App Framework

I’ve been working on a CoffeeScript web app in RailwayJS which is a rails-alike framework for nodejs built on top of Express.

One cool thing about RailwayJS is that you can write most of your code (not views?) in CoffeeScript instead of JavaScript. The generators, etc. will do the right thing if you give them the --coffee switch.

RailwayJS also has ORM with MongoDB and localization baked in.

#!/usr/bin/env coffee

app = module.exports = require('railway').createServer()

if not module.parent
  port = process.env.PORT or 3000
  app.listen port
  console.log "Railway server listening on port %d within %s environment", port, app.settings.env

App Screen Shot

History (Again)

[bakert@fenchurch ~]$ history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
24899 git
9575 vi
7366 cd
3929 ls
2517 php
2162 mate
2125 rsync
2022 cat
1950 ssh
1938 make

Compare to four years ago. New: git, php, mate, rsync, cat, make. Climbers: ls. Same: cd, ssh. Fallers: vi. Old: u, ruby, svn, td, mysql, gd.

Newlines at the end of files

For

Against

  • git considers a trailing newline a whitespace error.
  • Trailing whitespace is easily lost when, for example, exchanging patches via email.
  • A newline after a closing “?>” in PHP can cause problems with header() (although closing tags are no longer required in PHP).
  • It uses one more byte.

You Know You Are Trying to Do Too Much in a Bash One-Liner When …

find ~/bazel/src/main/webapp/lib -type f | grep -v "lib/deps/" | grep -v "lib/ext/" | grep -v "XG_MessageCatalog_" | xargs -I{} -L1 sh -c "echo {}; phpcs -d memory_limit=1024M -p -n -s --standard=/Users/bakert/Desktop/BazelCodingStandard {}"

Edit: Better:

#!/bin/env ruby

BAZEL_HOME = '/Users/bakert/bazel'
STANDARD_PATH = '/Users/bakert/Desktop/BazelCodingStandard'
VERBOSE = false

def main
  exclude_patterns = [ /XG_MessageCatalog_/, /\/lib\/deps\//, /\/lib\/ext\// ]
  files = Dir.glob("#{BAZEL_HOME}/src/main/webapp/**/*").reject do |f|
    exclude_patterns.any? { |p| f.match(p) } \
      || ! File.file?(f) \
      || File.extname(f) != '.php'
  end
  files.each do |f|
    puts f if VERBOSE
    print %x[phpcs -d memory_limit=1024M -n -s --standard=#{STANDARD_PATH} #{f}]
  end
end

main

Transparent Overlays in iMovie ’09

Assuming you have a PNG with transparency, and an iMovie project then, in iMovie:

  1. iMovie, Preferences
  2. Check “Show Advanced Tools”
  3. File, Project Properties, Timing
  4. Set Initial Photo Placement to “Crop”
  5. Drag the PNG with transparency to the point you want the overlay to appear in the timeline
  6. From the resulting pop-up menu choose “Overlay” (for full screen) or “Picture in Picture” (for part-of-screen)
  7. Adjust the size and duration of your overlay

node.js on ubuntu (on linode)

I got my simple movies node.js app running through Apache using mod_proxy

$ a2enmod proxy_http
$ a2enmod proxy

Configured under sites-available like so:

$ cat /etc/apache2/sites-available/movies 
<VirtualHost *:80>
    ServerName actualfqdnofhost.bluebones.net
    ServerAlias movies.bluebones.net
    ProxyPass / http://127.0.0.1:3000/
    <Proxy *>
	Allow from all
    </Proxy>
</VirtualHost>

(This assumes that your app listens on port 3000 when running.)

Then to ensure it gets restarted when the machine does I created the following file as /etc/init/movies.conf

$ cat /etc/init/movies.conf 
description "movies.bluebones.net on node.js"
author "bakert"

start on startup
stop on shutdown

script
  export MOVIES_ROOT=/srv/movies
  export EXPRESS_ROOT=$MOVIES_ROOT/src/express
  cd $EXPRESS_ROOT && exec sudo -u www-data NODE_PATH=$NODE_PATH:/opt/local/node/lib/node_modules/ EXPRESS_ENV=production /opt/local/node/bin/node $EXPRESS_ROOT/app.js 2>&1 >>$MOVIES_ROOT/logs/node.log
end script

Which also lets me stop and start my app with:

$ start movies
$ stop movies

Set up an SPF Record to (theoretically) reduce the risk of your web app’s email being marked as spam

I’m setting up email sending from my domain instead of faking gmail.com because of mail delivery issues. To make this work without just going automatically to everyone’s spam folder I have set up an SPF record. I found the documentation on the web a bit dense trying to work this out so here’s a short look at what I did.

“Show Original” in gmail used to say:

Received-SPF: neutral (google.com: 74.54.101.112 is neither permitted nor denied by domain of bakert+fantasyfootball@gmail.com) client-ip=74.54.101.112;
Authentication-Results: mx.google.com; spf=neutral (google.com: 74.54.101.112 is neither permitted nor denied by domain of bakert+fantasyfootball@gmail.com) smtp.mail=bakert+fantasyfootball@gmail.com

Now it says:

Received-SPF: pass (google.com: domain of admin+2@ff.bluebones.net designates 178.79.178.155 as permitted sender) client-ip=178.79.178.155;
Authentication-Results: mx.google.com; spf=pass (google.com: domain of admin+2@ff.bluebones.net designates 178.79.178.155 as permitted sender) smtp.mail=admin+2@ff.bluebones.net

This means Gmail is less likely to mark email sent by my web app as spam, thanks to the SPF record I have set up.

An SPF record is implemented as a DNS TXT (as opposed to A, CNAME, etc.) record with no “name” and a value something like this:

v=spf1 a mx include:_spf.google.com ~all

Let’s break that down …

v=spf1 – this indicates that the record is an SPF v1 record.

A – this indicates that any IP address in an A record for this network is allowed to send email for this domain.

MX – this indicates that any IP address in an MX record for this network is allowed to send email for this domain.

include:_spf.google.com – this indicates that _spf.google.com is allowed to send email for this domain.

~all – this indicates that _spf.google.com is allowed to send email for this domain.

All parts of the record except v=spf1 are optional and can take a prefix of -, + or ~. If there is no prefix + is assumed. + means allowed, – means not allowed and ~ means might be allowed. all is the catch-all for anything not explicitly called out by the rule.

You might be interested in a more detailed guide to SPF record syntax.