New Years Resolutioning
January 15, 2012

For the first time probably ever I’ve decided to create some New Year’s Resolutions. While it’s pretty abnormal for me to make commitments that I know I’ll have a hard time upholding, I decided that doing something was better than nothing. Most of the things that I’m trying to improve about myself come from 2 root causes: poor scheduling and distraction. Since changing the essence of my being is pretty much impossible I thought I’d try hitting a couple things that are the main contributors to the problem. Without further adieu, let’s get into it:

The Internet

The cause of all of my problems.

The internet simultaneously makes the day bearable while being a horrible timesink. I think I’ve narrowed down the cause of wasting time: checking feeds/whatever repeatedly. This includes Facebook, reddit, Shacknews, Ars, MacRumors, etc. Knowing that there is some sort of dialogue going on that I could participate in causes me to compulsively reload these pages to see what new stuff has come up. What was my solution to this? Remove it entirely and replace it with something that I don’t have to check every 2 seconds. I first added all the sites that I normally goto to my /etc/hosts:

Goodbye, sweet internet.

This is all great but sometimes I do need to take a break and do something else – programming works that way. Of course, I needed to figure out how to do this without compulsively checking the internet. Thankfully this is a solved problem: RSS Readers! Google Reader is a popular webapp, I can find feeds that I like and subscribe! Sounds perfect, right?

Wrong. Google Reader is pretty awful to use as a webapp (like pretty much any other Google webservice). A little app called Reeder came to save the day though:

Reeder is amazing

Reeder helps me distill all the content into things that are interesting and relevant to me into one quickly browsable list. As soon as I am done thumbing through it all gets marked as read (or starred for later) and I can go about my business! It takes an order of magnitude less time for me to go through everything which means I spend more time working. Productivity is way up over the last few weeks!

Everything Else

The more difficult part of this whole New Year’s Resolution thing is making a few efforts to get into some semblance of a routine. It’s early in the year so I’m just trying to do some small things first:

  • Tidy up the website and make posts more often. So far, so good - I’ve added an RSS generator to my nanoc workflow and it seems to be working pretty great! Subscribe! And this post itself marks 2 posts in one month. Huzzah!
  • Train more for the races I have this year. I joined New York Road Runners and am on my way to completing the 9 races that I need to do the New York City Marathon. There’s a long way to go, but I think I’ll make it.
  • Try to focus on leaving work at a reasonable time so I can relax a bit at home and go to sleep (also at a reasonable time)
  • Get SCUBA certified (finally) and go on a cool trip!

I’m looking forward to a good year and doing a retrospective sometime a year from now. Wish me luck!

Fixing Share With JungleDisk
January 05, 2012

I was having some issues sharing files on JD using the built-in Finder option:

This little button causes a nice silent exception

So I took matters into my own hands and discovered that all that does is run an Automator Workflow that posts to a local url. I whipped up a quick ruby script to allow me to continue sharing files:

#!/usr/bin/ruby

require 'base64'
require 'uri'

if ARGV.length == 0 then
  puts 'usage: share_with_jungle_disk.rb [file list]'
end

ARGV.each() do |arg|
  #expand
  full_path = File.expand_path(full_path)
  if File.exist?(full_path) == false then
    puts "Error: #{full_path} does not exist!"
    exit(1)
  end

  #encode to pass to jungledisk
  pathout = Base64.encode64(full_path)
  url = "http://localhost:2667/~publish?paths=" + URI.escape(pathout)
  
  puts url
  system("open #{url}")
end

Now I just run it from my terminal and all is right in the world. I also will look into why the workflow doesn’t work (it’s a quite simple workflow) but no time for that now! Hope this helps someone out there!

Steve Jobs
October 15, 2011

Despite the fact Steve was an egomanical jerk, he was a man who influenced the direction of technology for years to come. He shaped the professional life of myself and tons of others out there, he had the foresight to really drive development of forward thinking products at Apple. There is no doubt that we have all suffered a great loss.

This has been somewhat done to death so I’ll keep it short – I just want to drop a few links that I think are particularly interesting about Steve:

I also want to mention that folklore.org is a great place to read stories about the early development of the Mac. There’s some good ones in there.

I guess most of all: Thanks, Steve.

Using RMagick (or getting a weather radar image without downloading a subpar weather app)
July 23, 2011

Whew, it’s been a while.

A few months ago I ran into an issue with how I got the weather on my iPhone. The TWC application was crashing all the time and not giving me good information and someone had recommended that I try Shine. It’s a really great app but it doesn’t provide that one important thing - the radar. Sometimes you’re out and about and you just need to know if it’s going to rain soon, and a 20% chance of rain wasn’t going to do it.

So I did a bit of digging and decided to make my own radar image generator, basically by scraping weather.gov. Here’s the page I worked off of. I wrote code to parse out and composite the image into one solid jpg on my server.

Here’s the code:

require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'RMagick'

def retrieve_image(url)
  data = open(url).read
  data
end

def composite(img, dest_image_data)
  if dest_image_data.nil? then
    return img
  end

  begin
    tmp_img = Magick::Image.from_blob(dest_image_data).first
    if img == nil then
      img = tmp_img
    else
      img = img.composite(tmp_img, Magick::CenterGravity, Magick::OverCompositeOp)
    end
  rescue
    puts "error, could not composite radar image"
    exit(0)
  end
  img
end

radar_id = ARGV[0]
if radar_id.nil? || radar_id.length != 3 then
  puts "usage: radar "
  exit
end

html = Nokogiri::HTML(open("http://radar.weather.gov/radar.php?rid=#{radar_id}"))

#get map
map_graphics = html.xpath("//div[@id='bkgrnd']//img")

img = nil
map_graphics.each() do |graphic|
  #src
  url = graphic['src']
  #check for nothing
  if url[0..1] != '#' then
    #get it
    data = retrieve_image("http://radar.weather.gov/#{url}")
    img = composite(img, data)
  end
end

#get radar
radar_img = retrieve_image("http://radar.weather.gov/RadarImg/N0R/#{radar_id}_N0R_0.gif")
img = composite(img, radar_img)
radar_legend = retrieve_image("http://radar.weather.gov/Legend/N0R/#{radar_id}_N0R_Legend_0.gif")
img = composite(img, radar_legend)

img.write('./result.jpg')  { self.quality = 85 }

The script creates this image. I have it run as a cron job and host a page for my iPhone to hit here: http://www.elrepositorio.com/radar/ of which looks really good on my phone. I found that this was the best way for me to get the information I needed without using a crappy weather app!

Dynamic DNS on Linode
May 07, 2011

I’ve recently moved my hosting over to Linode due to Slicehost shutting down. I’ll make a post related to moving everything over shortly.

One thing I did use at Slicehost was their API to set my home computer as a subdomain – basically like dyndns. It was pretty great – I had a cron job on my home machine that would update the DNS manager to tell it to hit my DHCP’d Time Warner IP. Thankfully Linode has the same capability and a ruby gem that works!

Here’s the code:

require 'rubygems'
require 'linode'
require 'net/http'
require 'ipaddress'

API_KEY = 'secretkey' #your API key
DOMAIN = 183775 #your domain
RESOURCE = 1268908 #the resource id for domain on linode

ip = Net::HTTP.get('www.elrepositorio.com', '/ipcheck/ipcheck.php')
if( ! IPAddress.valid? ip ) then
  puts "ip not valid!"
  exit
end

er = Linode.new( :api_key => API_KEY )
if !er then
  puts 'no connection' 
  exit 
end

er.domain.resource.list(:DomainId => DOMAIN).each() do |resource|
  if resource.resourceid == RESOURCE then
    if resource.target != ip then
      puts "updating ip to #{ip}"
      er.domain.resource.update(:DomainId => DOMAIN, :ResourceId => RESOURCE, :Name => 'home', :Target => ip)
    else
      puts 'no need to update!'
    end
  end
end

This code will update the record to your current IP. You may notice a PHP file - ipcheck.php in the script. It is literally just one line:

echo $_SERVER['REMOTE_ADDR']

This will just output the caller’s IP so that we can update the DNS record. But how do I get the resource domain ids you ask? This quick script will print out all the ids for each domain on your system:

require 'rubygems'
require 'linode'

API_KEY = 'secretkey'

er = Linode.new( :api_key => API_KEY )
if !er then
  puts 'no connection' 
  exit 
end

er.domain.list.each() do |domain|
  puts "Domain: #{domain.domain}"
  puts "ID: #{domain.domainid}"
  er.domain.resource.list(:DomainId => domain.domainid).each() do |resource|
    puts "  Name: #{resource.name}"
    puts "  Target: #{resource.target}"
    puts "  ID: #{resource.resourceid}"
    puts "  ---------"
  end
  puts "\n"
end

Should be nice and easy to figure out what record you need to update! Remember that you have to enter a new record into the DNS manager first – we could have done creating a new record in the script but it was unnecessary for my purposes. Then just save your script and add it to your crontab!

Archive
  • Specifying Coordinates for Selection in Acorn -
  • Enabling Break on Exception in XCode4 -
  • Changing Quality Level in Screen Sharing (OSX 10.6) -
  • Link Dump: 04/20/11 -
  • Portal 2 Release Tracker -
  • A Few Git Tips -
  • Garbage Collection in Interpreted Languages or Why You Should Care -
  • Link Dump: 04/11/2011 -
  • Syntax Highlighting -
  • Connecting to a VPN Using the Commandline in OSX -
  • Ruby CoreLibs Documentation -
  • New stuff! Ruby, nanoc, and more! -
  • iPhone Dev Tip #3: Using New Symbols While Preserving Backwards Compatibility -
  • Last.FM is back up and running! -
  • iPhone Dev Tip #2: Static Libraries and Categories -
  • Hello Youtubes -
  • Gallery -
  • WordPress 3.0.1, nginx, FastCGI, Gallery3, and JungleDisk -
  • A Simple Code Sample -
  • Moving a Time Machine Drive -
  • Things are busy. -
  • iPhone Dev Tip #1: Taking a Screenshot -
  • Bloggin' Stuff -
  • I am posting something! -
  • I'm in Europe! -
  • Slow going... -
  • New Logo! -
  • Back to work! -
  • NSXMLParser, initWithContentsOfURL:, OSX 10.4 and 5 and you -
  • Growing Pains -
  • New Host! -
  • Video Game Music -- Yes, I'm lame -