Sunday, June 5, 2011

Using google-voice-dialout.agi With Asterisk, Sipgate And Google Voice


Paul Marks has a neat Python AGI script for Asterisk - google-voice-dialout.agi - that will login to your Google Voice account and place a call for you. This script is intended to allow you to place free outgoing calls from your home SIP phone (like a Cisco 7960 which is what I've got set up right now) using Google Voice and Gizmo5. Mario has a bunch of blog posts explaining different ways of doing this including a simpler setup with Google Talk, using the Jabber/Jingle support in Asterisk 1.8. His dial-plan also includes bridging of your outbound call and Google Voice callback so you needn't answer the call back from Google Voice.

Gizmo5 has since been acquired by Google and isn't accepting new sign-ups any more so if you didn't get an account earlier or need a second account to support a roommate or spouse's Google Voice number, you're out of luck there. However, there are other services available and I came across Sipgate in this Lifehacker post.

Sipgate has a help article that explains how to set up Asterisk to work with their service. Now, to make outgoing calls, I copied the basic dial plan for Asterisk from Mario's post with one little change to the Google Voice dialout script - change the value of phoneType to 2 instead of 7. From what I can tell 2 is for regular numbers, 7 is for Gizmo5 numbers and 9 is for Google Talk.

Credit: Recycle icon from Obsidian Dawn

Sunday, February 27, 2011

Color Clock - Representing Time As A Hexadecimal Color Value

I came across a post in my Facebook feed today that linked to The Colour Clock by Jack Hughes. It's a pretty neat idea - the current time is translated into a hexadecimal color value and applied to the background of the page. So as the time changes, the background color of the page changes as well.

The only thing is, it's in Flash so if you're on an iOS device, you won't be able to see it. Or if you'd like to pull it up on your web-enabled TV or other device that doesn't have Flash. So I spent my Sunday afternoon porting it over to JavaScript and this is what I have: http://colorclock.nogoodatcoding.com. Can you spot the original?



Will the real Color Clock please stand up?
It's the one on the left.
  

I've tried to stay true to the original but among other things, my colors are just a little off, most likely because I'm calculating them differently. You can find project details on my site.

 Cross-posted from The No Good Blog
 

Saturday, February 19, 2011

JDOM - getChild() Or getChildText() Returns null

If you're using JDOM for parsing XML in Java and you run into the problem that Element#getChild(String) and Element#getChildText(String) just keep returning null, here's a list of reasons why that might be happening:
  1. The node really doesn't exist!
  2. The node is in a different namespace and you need to use the version of the method that also accepts the namespace: Element#getChild(String, Namespace) or Element#getChildText(String, Namespace).
  3. Most importantly, remember that these methods return only immediate descendents of a node! So if you're looking to get a node nested at the nth level, you will need to walk the tree to its parent and only then can you call #getChild() and actually get the child!

Saturday, February 12, 2011

Facebook created_time format in JSON response

I was trying to get relative times for Facebook posts for fbbash, using the time returned in JSON objects using the Facebook JavaScript SDK. The created_time looks something like 2011-02-12T11:58:46+0000

The part before the 'T' is the date in a 'YYYY-MM-DD' format. And after is the time in 'HH:MM:SS'. As far as I can tell, the trailing '+0000' is the timezone offset but I've only ever seen that value so I've made the assumption that you're getting times that are GMT more or less (or UTC if you want to get technical).

I found this script on Stack Overflow by no, that converts this timestamp into a relative time string such as '5 min ago'. Unfortunately, despite what the comments on the script say, simply calling
fuzzyFacebookTime('2011-02-12T11:58:46+0000'); //doesn't work!
doesn't return the right value - instead, it gives back 'NaN years ago'.

The easy fix to this problem is to change the timestamp you're passing to the function to the form YYYY/MM/DDTHH:MM:SS+ZZZZ i.e. change the hyphens (-) to slashes (/). That seems to work and you should get the correct string. So you can make the call
fuzzyFacebookTime('2011-02-12T11:58:46+0000'.replace(/-/g,'/'));

Here's the script:
var fuzzyFacebookTime = (function(){

  fuzzyTime.defaultOptions={
    // time display options
    relativeTime : 48,
    // language options
    monthNames : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    amPm : ['AM', 'PM'],
    ordinalSuffix : function(n) {return ['th','st','nd','rd'][n<4 || (n>20 && n % 10<4) ? n % 10 : 0]}
  }

  function fuzzyTime (timeValue, options) {

    var options=options||fuzzyTime.defaultOptions, 
        date=parseDate(timeValue),
        delta=parseInt(((new Date()).getTime()-date.getTime())/1000),
        relative=options.relativeTime,
        cutoff=+relative===relative ? relative*60*60 : Infinity;

    if (relative===false || delta>cutoff)
      return formatTime(date, options)+' '+formatDate(date, options);

    if (delta<60) return 'less than a minute ago';
    var minutes=parseInt(delta/60 +0.5);
    if (minutes <= 1) return 'about a minute ago';
    var hours=parseInt(minutes/60 +0.5);
    if (hours<1) return minutes+' minutes ago';
    if (hours==1) return 'about an hour ago';
    var days=parseInt(hours/24 +0.5);
    if (days<1) return hours+' hours ago';
    if (days==1) return formatTime(date, options)+' yesterday';
    var weeks=parseInt(days/7 +0.5);
    if (weeks<2) return formatTime(date, options)+' '+days+' days ago';
    var months=parseInt(weeks/4.34812141 +0.5);
    if (months<2) return weeks+' weeks ago';
    var years=parseInt(months/12 +0.5);
    if (years<2) return months+' months ago';
    return years+' years ago';
  }

  function parseDate (str) {
    var v=str.replace(/[T\+]/g,' ').split(' ');
    return new Date(Date.parse(v[0] + " " + v[1] + " UTC"));
  }

  function formatTime (date, options) {
    var h=date.getHours(), m=''+date.getMinutes(), am=options.amPm;
    return (h>12 ? h-12 : h)+':'+(m.length==1 ? '0' : '' )+m+' '+(h<12 ? am[0] : am[1]);
  }

  function formatDate (date, options) {
    var mon=options.monthNames[date.getMonth()],
        day=date.getDate(),
        year=date.getFullYear(),
        thisyear=(new Date()).getFullYear(),
        suf=options.ordinalSuffix(day);

    return mon+' '+day+suf+(thisyear!=year ? ', '+year : '');
  }

  return fuzzyTime;

}());
Image Credit: ThinkDiff.net

 UPDATE [1235 20 Feb 2011]: Added an image and fixed some formatting