Category Archives: How To

A Free Phone Screen/Interview App With Twilio

I have thoroughly enjoyed working with Twilio for the last 6 months or so on an open-source project that will soon be released (can’t wait!). Now that my part in that project has wrapped up, I’ve got some extra time to play around with my own projects and look for my next job. Over on the Twilio support forums, someone recently requested help, and it caught my eye:

I have to conduct a lot of phone interviews every year for my company with fairly standard questions. Would there be a way to use Twilio to manage this in an automated fashion? I don’t want to spend the time actually conducting the interviews but would rather listen to them when I have a chance. [...]
During the call, I would like to have the user enter the # sign or something when they have finished answering the question, to prompt the next question. This way, I could have my 10 standard questions recorded in Mp3, and then have the whole process managed through Twilio ideally where i enter the interviewee’s phone number and a time for the call ideally.

Someone posted a link there that lead me to this service: VoiceScreener which starts at $169/month. Yikes! Twilio, on the other hand, is 3¢/minute and $5/month/phone number. I got to thinking: this is incredibly easy to set up with Twilio’s API; why not just whip it up? So I did.

Here’s a demo where you can try a sample phone interview and here’s where you can download the code. To install and customize it, just follow these directions:

  1. Unzip the file to a directory on a web server that runs PHP 5
  2. Edit the file inc/config.php with your own Twilio authentication credentials and the email address that will receive reports.
  3. I have included my sample MP3 files in the files directory, but you should replace them with your own. The file names should be self explanatory: intro.mp3, thanks.mp3, conclusion.mp3, and question_XX.mp3, where XX is a two-digit number.

As it is written now, this works without any database at all because we can use Twilio’s REST API to query the call details and list of associated recordings. This project is more of a starter and proof of concept, although for simple interview scenarios it would work just fine. Other possible upgrades (some requiring a database) could be:

  • Account for unanswered questions in the report
  • Allow interviewers to hang up in the middle of the interview and call back later to pick up where they left off
  • Allow the interviewer to review their answer and re-record
  • Allow for question branching, where the user enters a touch-tone response for yes/no on some answers and is asked only relevant questions from then on
  • Set up multiple types of interviews
  • Show the text of the question in the interviewer’s web browser  while they are listening to it on the phone using AJAX
  • Make the interview conclusion a menu, as in: “To hear more about the company, press 1. To hear more about this position, press 2…”

If you are interested in having me work on this for you, please contact me and I’d be happy to help you out. If you have any suggestions or improvements, please send them my way too.

Deleting Duplicate Records in MySQL

I am writing this post to remind myself of a cool trick that I rediscovered today. When you are scrubbing a database table, there is the common problem of removing duplicate data. In my case, I had a table of ZIP codes, city names, and state codes, along with the latitude and longitude values. The problem was that there were a few thousand records where the lat/lon data was slightly off leading to multiple duplicate zip code rows with slightly different data. I have seen solutions for other databases that require a temporary ID field and self joins. It turns out that for MySQL the solution is much simpler. If you use the ALTER IGNORE TABLE command to add a unique index, then your duplicate rows will be silently deleted. Here was the command I used:
ALTER IGNORE TABLE `zip_codes`
ADD UNIQUE INDEX dupes (`region_code`, `city`, `zipcode`);

Finally, just drop the temporary index and you’re done. Here’s the official word from the manual:

IGNORE is a MySQL extension to standard SQL. It controls how ALTER TABLE works if there are duplicates on unique keys in the new table or if warnings occur when strict mode is enabled. If IGNORE is not specified, the copy is aborted and rolled back if duplicate-key errors occur. If IGNORE is specified, only the first row is used of rows with duplicates on a unique key, The other conflicting rows are deleted. Incorrect values are truncated to the closest matching acceptable value.

Tools of My Trade

I am a former Windows-only developer happily using my iMac and running OS X all the time, rarely booting into Windows anymore. Here is a list of software and services that I use to do my day-to-day development, besides Mail.app and Terminal.app which seem too obvious to include:

  • Komodo Edit 5.0: Good cross-platform IDE, was using Aptana Studio and Eclipse too
  • Smultron: quick plain text editor
  • Cyberduck: FTP and then some
  • 1Password: $ manage all the passwords to all the sites
  • Pixelmator: $ great Mac-only image editor
  • MacPorts: for everything not already in OS X
  • MAMP, which includes Apache, MySQL, and phpMyAdmin
  • Firefox + Firebug + YSlow: for web debugging. All other surfing through Safari
  • Skype: video conferencing
  • Chicken of the VNC: VNC client
  • Snapz Pro X: $ screencasts and screenshots
  • iWork: $ Pages and Numbers work great – who needs MS Office?
  • VMWare Fusion: $ emulator for booting into Windows occasionally
  • MediaTemple.com: $ hosting
  • Unfuddle.com: Subversion hosting and issue tracking for my own projects
  • WordPress: you are here

$ = commercial software/service that I paid for

How ThisLineIsSecure.com was built

Here is a quick rundown of how my recently launched site ThisLineIsSecure.com was built. First of all, it would not have been possible without the Twilio API. Besides that:

I need to tally up my expenses, but besides my time I’m probably out less than $200 for this whole thing so far. Unbelievable. I think that the Kohana project, Nuvio, the WordPress Audio Player, and Cyberduck each deserve at least a $20 donation, which will be forthcoming.

Sharepoint Locked for Editing

While I was working on a document through our new Sharepoint team site at GWC, Word crashed due to some permission changes. After trying unsuccessfully to open it again many times, I came across this MS support article:

You receive a “(Filename) is locked for editing by ‘another user’” message when you try to modify a document in Windows SharePoint Services even though you are the user who previously opened the document

CAUSE

When a document is opened by a client program, Windows SharePoint Services puts a write lock on the document on the server. The write lock times out after 10 minutes. Users cannot modify the document during the time when the document is locked.

In a scenario where the program that opens the document unexpectedly quits or crashes and you try to open the document again before the write lock times out, the message that you receive says that the document is locked by another user. This behavior occurs even though you are user who previously opened the document.

WORKAROUND

To work around this behavior, wait 10 minutes before you click Edit in ProgramName to open the document again. (dismayed emphasis mine)

God Bless Microsoft, and bless their arbitrary 10-minute timeout that protects me from myself. I have six minutes and counting. (Hums impatiently to self)

Forcing Logout in Forms Authentication

Here’s a simple fix to a common ASP.NET development problem. The only code you really need to put on a log out page is “FormsAuthentication.SignOut()”. However, any controls or code that change based on authentication (such as the LoginView control or the LoginStatus control) will not reflect that the user is logged out until the following web page. This is bad for usability because you may be presenting links that are technically un-clickable. I’ve seen forum posts that advocate redirecting to another page, but there’s a simpler fix:

Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
	FormsAuthentication.SignOut()
	Context.User = Nothing
End Sub

Setting the Context.User to nothing does the trick.

Directory synchronization batch file

Batch IconToday I ran into a problem that required two directories to be synchronized. This is more than just copying all of the files from one directory to another, which XCOPY does very well. I had to ensure that there were no orphaned files in the destination that were not already in the source. The closest thing XCOPY comes to this is to copy only files that already exist in the destination. This can be a problem when deploying ASP.NET projects over and over, because “XCOPY deployment” does not account for deleted or renamed files.

There are many shareware GUI programs that can synchronize two directories like I wanted, but that seemed like overkill. I basically wanted a Windows version of rsync that would work out of the box (if you know of one, please share in the comments). I had already fired up the old source control editor and was about to code up a quick console program to do this when I realized that the same thing could be accomplished with a recursive batch file. Ten minutes later, I had this little script: Read more »

I like my Blackjack

Samsung BlackjackI got a new phone a few weeks ago: the Samsung Blackjack, otherwise known as the SGH-i607. It works great with Skweezer, and since it’s a Windows Mobile device, I’ve also gotten a chance to see it in action with the Yahoo! Go and Live applications, both of which have their pluses (Flickr/Maps & Directions respectively) and minuses. Overall I’m very pleased with the new phone though.

One thing that has been a little odd has been the fact that sometimes my network connection has trouble restarting. After the phone has been idle for a while, and more often when I’ve traveled (perhaps switching cell towers?) my phone’s browser would be unable to make any connections. Navigating to new pages would show “Connecting” in the status bar for a few minutes before returning an error. Network-enabled applications such as Yahoo! Go would also stop working, showing time-out errors or “unable to refresh” messages. I called up Cingular AT&T tech support and they told me it was probably a coverage problem: they claimed you need at least four bars to browse the web, whereas you can send SMS and talk with fewer bars of course. That is only half the story, as this problem sometimes crops up even with great signal. Fortunately, I finally found the cause and solution. Read more »

Fix for SOAP reflection error in VS 2005 web projects

VS 2005Today we found a fix for a strange error experienced while deploying a web project built in Visual Studio 2005 that has a web reference (SOAP), specifically to the Microsoft Live search service. We were using a web deploy project, and although everything compiled all right and ran well on the local development server, on pre-deployment testing the following error stack would be raised: Read more »

How to make your EDGE connection 4.7 times faster

I just saw Jeff Atwood’s entry from last week on why you don’t want an iPhone, and his well-reasoned advice boils down to this: EDGE is painfully slow compared to 3G, and you should wait until they iron out the bugs in v2.0. For these reasons, even the Apple faithful are sitting v1.0 out. Sprint is obviously thrilled right now.

As far as I can figure, the difference between EDGE and 3G networks like EVDO is presently 4-5x, accounting for the recent boost. There is a free and easy way to get 4-5x faster downloads on any network, even EDGE: Skweezer. Because content is pre-compressed on our servers before it even starts down the thin invisible tube to your phone, there’s less overall data transmitted, which translates into a faster browsing experience. It is the equivalent of turning your 200 kbit connection into a 1 mbit connection. Basic web surfing will be loads faster with Skweezer than without.

You still don’t believe me? It’s been a while since we did a site comparison, so I ran a few sites through Firebug this evening (July 3, 2007) to compare their total original page weight with the Skweezed versions, with images on and off. Unfortunately the figures aren’t as dramatic as they once were because server-side content compression (gzip and deflate) is more commonplace now, and that used to be an easy win for us. Nevertheless, Skweezer still always brought the page weight down, as follows:

Page size comparison

The worst value in each column is in red, and the best value is green. The fastest way to browse is without images, but that’s only useful if you’re just information hunting. Even with images on, the median speedup for browsing sites through Skweezer was 4.7 x, if we assume that the network is the main bottleneck. If you want to run your own tests, be aware that IE reports uncompressed page size in the page properties dialog, while Firefox reports the number of bytes received for the main HTML document, reflecting compression. The best way to compare total page weight accurately is to use a tool like Firebug or a proxy like Fiddler2.