<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title>jonmagic.com ...nuf said</title>
  
  <link href="http://theprogrammingbutler.com/blog/" />
  <id>http://theprogrammingbutler.com/blog/</id>
  <updated>2013-05-15T14:20:35-04:00</updated>
 
  
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/jonmagic" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="jonmagic" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
      <title>Business With Pleasure</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2013/05/15/business-with-pleasure/" />
      <id>http://theprogrammingbutler.com/blog/archives/2013/05/15/business-with-pleasure/</id>
      <updated>2013-05-15T14:20:35-04:00</updated>
      <published>2013-05-15T13:00:00-04:00</published>
      
      <summary type="html">Hi, my name is Jon. I'm an addict. It does not matter what it is if it makes me feel good I do more of it.</summary>
      <content type="html">Hi, my name is Jon. I'm an addict. It does not matter what it is if it makes me feel good I do more of it.&lt;h3&gt;But I Love It So Much!&lt;/h3&gt;
&lt;p&gt;I love my job, or more specifically, I love the work I get to do every day. Combine my love for work with my addiction problem and I end up working too much and spending too little time with my wife, or reading a book, or taking a walk.&lt;/p&gt;
&lt;p&gt;When things are going well at work I have a sense of accomplishment, which feels good, and &lt;a href="http://www.youtube.com/watch?v=48-tcRiBNj4"&gt;I want more&lt;/a&gt;. How do you get more of something? You just keep doing the same thing over and over again that got you that good feeling right?&lt;/p&gt;
&lt;h3&gt;Being Honest With Myself&lt;/h3&gt;
&lt;p&gt;Right now I have no problem identifying that my line of thinking, doing more of something will result in more pleasure, is wrong. When I am in a destructive cycle I am completely blind to this fact.&lt;/p&gt;
&lt;p&gt;A destructive cycle is wanting one thing too much and being blind to the costs of achieving it. We also call this being obsessed with something. Ultimately these destructive cycles lead to some sort of meltdown for me when &lt;a href="http://en.wikipedia.org/wiki/Diminishing_returns"&gt;increased input does not lead to an equal increase in output&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During a cycle I can&amp;#8217;t stop thinking about whatever I&amp;#8217;m obsessing about; I bring it to the dinner table, I bring it on a date, I go to bed with it. This damages my marriage and my mental health.&lt;/p&gt;
&lt;p&gt;Thankfully I am getting better at recognizing and breaking these cycles. I can&amp;#8217;t take the credit though, my wife usually notices and starts to warn me early on. Learning to listen to her concerns is something I need to get better at. My last obsession lasted about ten days before she got through to me and I recognized the error of my ways. That was yesterday.&lt;/p&gt;
&lt;h3&gt;Shortening the Cycle&lt;/h3&gt;
&lt;p&gt;There are a few things I am going to try to shorten this cycle. The first is obvious, listen to my wife. But what if you don&amp;#8217;t live with someone?&lt;/p&gt;
&lt;p&gt;Recognize the signs. If I am spending less time doing things that relax me, like reading, walking with my dogs, or doing chores around the house, these are pretty good signs I&amp;#8217;m not balancing work and life very well.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m trying out a checklist of sorts. It is just a long list of non-work things that I can do each day. I made this list by observing what has been healthy for me in the past. I&amp;#8217;m not going to check off everything on the list each day, but doing three or four a day is a good sign, and doing one or none is probably a bad sign.&lt;/p&gt;
&lt;p&gt;Make yourself accountable to your peers. If you know your signs ask a coworker and friend to watch out for them. Most of the time someone other than yourself will recognize the signs much sooner than you will. There is a caveat, if you are going to make yourself accountable you have to be willing to listen when they warn you.&lt;/p&gt;
&lt;p&gt;Getting it right feels great too. Excuse me while I add blogging to my list of non-work things to do.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>Focus</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2012/09/07/focus/" />
      <id>http://theprogrammingbutler.com/blog/archives/2012/09/07/focus/</id>
      <updated>2012-09-07T16:32:38-04:00</updated>
      <published>2012-09-07T15:00:00-04:00</published>
      
      <summary type="html">We just finished shipping a six month long milestone on one of our support tools at &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt;. One lesson I learned along the way was focus.</summary>
      <content type="html">We just finished shipping a six month long milestone on one of our support tools at &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt;. One lesson I learned along the way was focus.&lt;h3&gt;Make a Commitment&lt;/h3&gt;
&lt;p&gt;When I first heard about this project, the tool that handles all incoming support requests at GitHub, I was immediately intrigued and volunteered myself to help. Sitting down with the person who had developed the tool to that point and the support team, we came up with a few core things that had to happen, plus a lot of higher level todos.&lt;/p&gt;
&lt;p&gt;At the time, our support tool was just a front-end to a popular customer care service called &lt;a href="http://tenderapp.com"&gt;Tender&lt;/a&gt;, that was actually built by a couple GitHub employees in their previous lives. The service had done its job for a long time, but it was clear that our needs were changing, and that we couldn&amp;#8217;t rely on a third party service to meet them.&lt;/p&gt;
&lt;p&gt;So, I made the commitment to help achieve this goal and get our support system running on its own as a full fledged application inside of GitHub. I am not actually sure if I would have made this commitment if I had read through the codebase and understood what a long road it would be. Thankfully, in my gung-ho sorta way I just signed up on the spot.&lt;/p&gt;
&lt;h3&gt;Frame All Questions &amp;amp; Answers&lt;/h3&gt;
&lt;p&gt;Having made the commitment, I dove into the project head first. I quickly became the primary developer on the project, with people coming in from other teams to help for a few weeks before returning to their other work (thankfully &lt;a href="http://twitter.com/spicycode"&gt;@spicycode&lt;/a&gt; joined later as a full time member of the team). Along the way I learned that being the primary person responsible also meant that people came to me with their needs and wants.&lt;/p&gt;
&lt;p&gt;Initially, being a people pleaser, I did everything in my power to fulfill their wishes and desires or promised to work on what they needed later. Quickly this became unsustainable and I became frustrated with my inability to fulfill those requests.&lt;/p&gt;
&lt;p&gt;Then I learned the right way to answer questions when asked. I had to frame every question, every want, every wish, in the context of my original commitment. Would satisfying their need further our core goals, and did I have the resources necessary to accomplish it?&lt;/p&gt;
&lt;h3&gt;Learn To Say No&lt;/h3&gt;
&lt;p&gt;Most of the time during the last six months that answer ended up being &lt;b&gt;no&lt;/b&gt;. This was especially tough for me, I hate saying no, but I had to learn how to do it or risk losing my sanity and disappoint a lot of people.&lt;/p&gt;
&lt;p&gt;Thankfully in many cases I didn&amp;#8217;t have to say a flat no &amp;#8211; instead, we would channel the energy and idea into a feature request that we could talk about more down the road. All of these feature requests were recorded in GitHub Issues and revisited over the following months, taking new shapes, and in some cases being made obsolete by better and newer ideas.&lt;/p&gt;
&lt;p&gt;Along the way, we implemented just enough to keep our support team happy, with all of their hair intact. Mostly, we focused on our core goals.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Last night at midnight we flipped the switch to route all support requests thru our new backend. We still use Tender in a limited capacity for old discussions that are still open, but as time passes those will be archived and eventually we will be able to remove Tender completely as a dependency.&lt;/p&gt;
&lt;p&gt;In six months, we laid a solid foundation for the future of support at GitHub by staying focused.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>HUBOT img me woman laughing alone with salad</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2012/05/19/hubot-img-me-woman-laughing-alone-with-salad/" />
      <id>http://theprogrammingbutler.com/blog/archives/2012/05/19/hubot-img-me-woman-laughing-alone-with-salad/</id>
      <updated>2012-05-19T19:30:21-04:00</updated>
      <published>2012-05-19T19:25:00-04:00</published>
      
      <summary type="html">In the past month I've had the opportunity to present this talk twice, first in London England and then in Verona Italy.</summary>
      <content type="html">In the past month I've had the opportunity to present this talk twice, first in London England and then in Verona Italy.&lt;p&gt;Before joining GitHub I met &lt;a href="http://zachholman.com/"&gt;Zach Holman&lt;/a&gt; from GitHub at a conference in Colorado and heard about &lt;a href="http://hubot.github.com"&gt;Hubot&lt;/a&gt;. As soon as Hubot was released as open source we started using him at Ordered List and I blogged a simple &lt;a href="http://theprogrammingbutler.com/blog/archives/2011/10/28/hubot-scripts-explained/"&gt;script writing tutorial&lt;/a&gt; which is still my most popular blog post day to day.&lt;/p&gt;
&lt;p&gt;After joining GitHub I got up the nerve to write and submit a talk proposal and low and behold two out of three of the conferences I submitted to accepted my talk. I gave this presentation first in London at &lt;a href="http://devslovebacon.com/"&gt;DevsLoveBacon&lt;/a&gt; and you can find the &lt;a href="http://devslovebacon.com/speakers/jonathan-hoyt"&gt;video of my talk&lt;/a&gt; on their site. A few weeks later I traveled to &lt;a href="http://2012.jsday.it/"&gt;jsDay in Verona Italy&lt;/a&gt; and presented a second time!&lt;/p&gt;
&lt;p&gt;Here are the slides from my presentation.&lt;/p&gt;
&lt;script async class="speakerdeck-embed" data-id="4f8b4288d80cdf001f000cb1" data-ratio="1.3333333333333333" src="//speakerdeck.com/assets/embed.js"&gt; &lt;/script&gt;&lt;p&gt;If you have any feedback on how I can make the talk better or any questions about Hubot please send it via &lt;a href="http://twitter.com/jonmagic"&gt;Twitter @jonmagic&lt;/a&gt;.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>My Trip to Verona</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2012/05/19/my-trip-to-verona/" />
      <id>http://theprogrammingbutler.com/blog/archives/2012/05/19/my-trip-to-verona/</id>
      <updated>2012-05-20T12:15:53-04:00</updated>
      <published>2012-05-19T19:00:00-04:00</published>
      
      <summary type="html">As my plane broke through the clouds, descending into Verona, my eyes were met with seemingly endless farm land, a patchwork quilt, broken up by small patches of trees and wandering erratic roads.</summary>
      <content type="html">As my plane broke through the clouds, descending into Verona, my eyes were met with seemingly endless farm land, a patchwork quilt, broken up by small patches of trees and wandering erratic roads.&lt;h3&gt;Day 1&lt;/h3&gt;
&lt;p&gt;We landed at the small airport and for the first time in a decade I felt like a foreigner. I was in Verona for &lt;a href="http://2012.jsday.it/"&gt;jsDay&lt;/a&gt;, having been given the opportunity to speak.&lt;/p&gt;
&lt;p&gt;After exchanging dollars for euros I hailed a cab. My driver must have been training for the grand prix as we zigzagged and raced around cars at 140km/h. The exhilarating ride ended at the hotel and my original notion that Verona was mostly flat was thoroughly dispelled.&lt;/p&gt;
&lt;p&gt;Soon I met with my &lt;a href="http://github.com/bkeepers"&gt;coworker&lt;/a&gt; and his wife who were in Verona on holiday and we jumped on a bus for &lt;a href="http://en.wikipedia.org/wiki/Lake_Garda"&gt;Lago di Garda&lt;/a&gt;. We spent the afternoon catching up, enjoying the scenery, and eating the local fare.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb904efdabe9d338d001a1d/blog_post/40affccc9e9211e1abb01231382049c1_7.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Jet lag began to sneak up on me as the sun moved into the western sky. We returned to the hotel and began making dinner plans, but before we could execute I ran into other speakers from the conference.&lt;/p&gt;
&lt;p&gt;Introductions were made, plans were changed, and the &lt;a href="http://en.wikipedia.org/wiki/Spritz_(alcoholic_beverage)"&gt;spritz&lt;/a&gt; began to flow. At a local Pizzeria, one among hundreds in a several kilometer area apparently, we feasted on thin crust delicacies.&lt;/p&gt;
&lt;p&gt;We talked into the night, closing the pizzeria and then the hotel bar. A &lt;a href="http://twitter.com/shvi"&gt;rag&lt;/a&gt; &lt;a href="http://twitter.com/seldaek"&gt;tag&lt;/a&gt; group of &lt;a href="https://twitter.com/maboa"&gt;many&lt;/a&gt; &lt;a href="http://twitter.com/couac"&gt;nationalities&lt;/a&gt;, daring each other to try the &lt;a href="http://en.wikipedia.org/wiki/Grappa"&gt;grappa&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb908ffdabe9d338d004be3/blog_post/pizzeria.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Finally around 3am I collapsed into bed, exhausted from the last 37 hours of travel and new culture acclimation.&lt;/p&gt;
&lt;h3&gt;Day 2&lt;/h3&gt;
&lt;p&gt;The conference began with a &lt;a href="http://twitter.com/#!/jsconfit/status/202676559918804993/photo/1"&gt;spritz&lt;/a&gt;. The talks were great and it was refreshing to catch up on the world of Javascript since I&amp;#8217;ve been so deep in Ruby for the past six months. Twice I had to retire to my room to lay down for a bit, jet lagged and exhausted.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90587dabe9d2ebc02573e/blog_post/atanqebcmaaji5w.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Lunch was catered by the conference center and I mostly feasted on salad, cuts of meat and cheese, carrots, and cooked greens. Red wine was served and rivaled anything I&amp;#8217;ve had back home.&lt;/p&gt;
&lt;p&gt;At this point I must have been meeting new people at a rate of six or more per hour. English truly is the international language, at least in the programming community.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90a92dabe9d172100ef64/blog_post/10df970aa28e11e180c9123138016265_7.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;In the evening they took all of the speakers to the tallest tower in Verona, where I scaled 368 steps and then faced one of my worst fears, heights. It is so strange that I have no problem getting in an aluminum tube that hurtles around the world many thousands of feet above the ground without a second thought, but looking down from a twenty story tower makes me weak in the knees.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90aacdabe9d2ebc0282ae/blog_post/3915c5d2a28e11e1989612313815112c_7.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;After descending we walked across the piazza and sat down at the finest restaurant in Verona. The first glass was filled with Prosecco and I began meeting everyone around the table. Two Californians, a few from Italy, a couple from Germany, and the GitHub delegation.&lt;/p&gt;
&lt;p&gt;We all enjoyed conversing, the three course meal and dessert, and of course more red wine. The meal was good but I felt like it was not much different in style or quality from what my wife and I cook at home. The dessert on the other hand, a cream with nuggets of pure chocolate heaven, was fantastic.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90acadabe9d2ebc0286fe/blog_post/6307482aa28e11e19e4a12313813ffc0_7.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;After dinner we were bussed back to the hotel and a large number of us headed back to the pizzeria from the pervious night to join the conference attendees. I met more people, sampled the local beer, and once again we closed the place.&lt;/p&gt;
&lt;p&gt;Once back to the hotel I settled in at a table in the bar with a Norwegian living in Italy and a &lt;a href="http://twitter.com/seldaek"&gt;Belgian&lt;/a&gt; living in Switzerland. We talked into the wee hours of the morning over a couple of beers, discussing everything from nationalized healthcare to the perfect bolognese recipe.&lt;/p&gt;
&lt;p&gt;I finally climbed the four flights of steps to my room around 4am and kissed the mattress.&lt;/p&gt;
&lt;h3&gt;Day 3&lt;/h3&gt;
&lt;p&gt;Going to bed so late prevented me from waking up in time to see Douglas Crockford talk in the morning, which was definitely a disappointment. I did make it to a few talks however and it was interesting to see what libraries and tools people were using around the world.&lt;/p&gt;
&lt;p&gt;Right before my talk I took a power nap and awoke with an idea for how to engage my audience a bit more.&lt;/p&gt;
&lt;p&gt;Before leaving my room I grabbed some &lt;a href="http://en.wikipedia.org/wiki/Mostarda"&gt;mostarda&lt;/a&gt; I had purchased and on the way to the conference rooms I ordered a spritz from the bar.&lt;/p&gt;
&lt;p&gt;As I began my talk about &lt;a href="http://theprogrammingbutler.com/blog/archives/2012/05/19/hubot-img-me-woman-laughing-alone-with-salad/"&gt;Hubot the robot butler&lt;/a&gt; I walked out into the audience and asked whether they liked it when someone did something nice for them. They didn&amp;#8217;t answer immediately so I singled out one young lady and asked her if she would like the mostarda or the spritz. She said either so I gave her the spritz and then held up the mostarda and asked who wanted it. A gentleman in the back said sure and I passed it to him and then headed to the front to start my talk. I had broken the ice, demonstrated a servants heart (a butlers heart!), and calmed myself down in the process by having some one on one interaction with the audience.&lt;/p&gt;
&lt;p&gt;It felt like the rest of my talk went really well, my energy level was high, I didn&amp;#8217;t stumble, and I actually hit my allotted time perfectly! There were even a few questions and light applause. But later I noticed there was only one tweet and no one really came up to ask me more about Hubot, so I&amp;#8217;m wondering if either I spoke too quickly and was hard to understand or if my audience just didn&amp;#8217;t really need their own robot butler.&lt;/p&gt;
&lt;p&gt;After the talk the usual wave of relief washed over me mixing with the waning adrenaline. Now it was time to prepare for hosting a GitHub drinkup!&lt;/p&gt;
&lt;p&gt;I found a group to have dinner with and we began our trek across the city. We sat down to a nice meal and the conversation was relaxed. Then I left them a bit early to ensure our venue was ready for the drinkup.&lt;/p&gt;
&lt;p&gt;Arriving at the &lt;a href="http://www.kbh.it/"&gt;Kulmbacher Bier-Haus&lt;/a&gt; I found my coworker and his wife already there. I went inside and made friends with Tony the bartender, an energetic young fellow with blond hair. The entire staff were dressed up in cheesy Bavarian garb that put a smile on your face.&lt;/p&gt;
&lt;p&gt;As the designated hour approached people started arriving and we took our place in the back of the restaurant. My coworker and I took turns greeting each new group that wandered in, asking them what they were working on, what they were excited about in their careers, and answering any questions they had for us. One question was oft repeated: &amp;#8220;how do I sell my boss or clients on using git.&amp;#8221; I honestly struggled to come up with anything they hadn&amp;#8217;t already tried. Definitely something I need to study more and work on, as I haven&amp;#8217;t ever had to sell git to a boss or client, I just started using it and didn&amp;#8217;t give them a choice. Unfortunately that doesn&amp;#8217;t work for everyone.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90c61dabe9d2a9100706f/blog_post/img_1570.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;After the successful drinkup a small group of us migrated to a quiet watering hole down the road, continuing unfinished conversations over a grappa.&lt;/p&gt;
&lt;p&gt;The bar closed and we walked back to the hotel, me in the lead, arriving back at nearly 4am. With jsDay over I rested my head on the pillow and had my first good long night of sleep since arriving.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90b88dabe9d5a2803cab5/blog_post/img_1587.jpg" alt="" /&gt;&lt;/p&gt;
&lt;h3&gt;Day 4&lt;/h3&gt;
&lt;p&gt;As my eyes opened I realized it was nearly lunchtime, so I jumped up, dressed, and grabbed my Kindle. Leaving the hotel I found myself heading back to the trusty Pizzeria San Marco. I ordered wine and a pizza with prosciutto, fungi (mushrooms), and mozzarella. I spent my lunch reading &lt;a href="http://objectsonrails.com/"&gt;Objects on Rails&lt;/a&gt; and thinking.&lt;/p&gt;
&lt;p&gt;When I was done a nap seemed in order so I returned to the hotel and layed down for a few more hours. Waking up for the second time that day I wasn&amp;#8217;t sure what to do so I loaded my messenger bag with laptop and Kindle and headed towards the city center. It was a fascinating hike with beautiful sites and delicious smells, set to a soundtrack from my iPhone. I started with &lt;a href="http://www.rdio.com/artist/Danger_Mouse/album/Rome/"&gt;Rome&lt;/a&gt; and then moved on to &lt;a href="http://www.rdio.com/artist/Django_Reinhardt/album/Sultan_Of_Swing/"&gt;The Sulton of Swing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90cd7dabe9d2ebc029f10/blog_post/81a36576a13411e1be6a12313820455d_7.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;While crossing over the Ponte Pietra bridge into the touristy center I saw many people with Gelato so I tracked down the source and bought a small cup of Strachiatella, then found a bench overlooking the river and took my time enjoying the purchase. Around dinner time I found a touristy place and had a somewhat awful meal (never go touristy!).&lt;/p&gt;
&lt;p&gt;Dinner complete I trekked back to the hotel and found a table in the bar to sit, read, and relax at. I enjoyed my last glass of wine in Italy (for this trip at least) and read &lt;a href="http://practicingruby.com/"&gt;Practicing Ruby&lt;/a&gt; articles and watched &lt;a href="http://destroyallsoftware.com/"&gt;Destroy All Software&lt;/a&gt; videos. Completely exhausted from socializing I avoided the party that night and retired to my room early.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4fb90cfbdabe9d2a91007371/blog_post/dece0b44a11f11e1989612313815112c_7.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;After a few short hours of sleep I rose, packed, and grabbed a much more relaxed cab ride to the airport.&lt;/p&gt;
&lt;p&gt;As my plane rose into the sky I said &amp;#8220;Ciao Verona&amp;#8221; and began writing my tale.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>Speaker Deck Goes Full-screen</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2012/04/04/speaker-deck-goes-full-screen/" />
      <id>http://theprogrammingbutler.com/blog/archives/2012/04/04/speaker-deck-goes-full-screen/</id>
      <updated>2012-04-04T12:09:34-04:00</updated>
      <published>2012-04-04T11:50:00-04:00</published>
      
      <summary type="html">I'm really excited to let you know that we've added full-screen support to presentations on &lt;a href="http://speakerdeck.com"&gt;Speaker Deck&lt;/a&gt;. This feature has been percolating for awhile, going thru several iterations before we found a solution that we really liked.</summary>
      <content type="html">I'm really excited to let you know that we've added full-screen support to presentations on &lt;a href="http://speakerdeck.com"&gt;Speaker Deck&lt;/a&gt;. This feature has been percolating for awhile, going thru several iterations before we found a solution that we really liked.&lt;p&gt;&lt;img src="/assets/4f7c6724dabe9d6fbb008830/fullscreen_arrows.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;We are using the &lt;a href="https://developer.mozilla.org/en/DOM/Using_full-screen_mode"&gt;new full-screen API&amp;#8217;s&lt;/a&gt; available in Webkit based browsers and Firefox. There were a few obstacles we had to overcome, mostly just learning how the API&amp;#8217;s actually worked, specifically how to make an element inside an iFrame go fullscreen (make sure to add the allow flags to your iframe tag).&lt;/p&gt;
&lt;p&gt;In the process we learned a ton of great stuff that will let us do some pretty cool things in the future. The way we designed full-screen will let us use higher resolution slides in the future as well (you know, in case we decide to start encoding them at the resolution of that new device Apple just released).&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a presentation I did awhile back, check it out in full-screen!&lt;/p&gt;
&lt;script async class="speakerdeck-embed" data-id="4de44aa05753083b8d000002" data-ratio="1.3333333333333333" src="//speakerdeck.com/assets/embed.js"&gt; &lt;/script&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>Scriptular</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2012/03/05/scriptular/" />
      <id>http://theprogrammingbutler.com/blog/archives/2012/03/05/scriptular/</id>
      <updated>2012-03-05T12:25:26-05:00</updated>
      <published>2012-03-05T02:55:00-05:00</published>
      
      <summary type="html">Ever since &lt;a href="http://hubot.github.com"&gt;Hubot&lt;/a&gt; was released I've been regular expressing myself. Here is a tool I built to make testing regular expressions in javascript easier.</summary>
      <content type="html">Ever since &lt;a href="http://hubot.github.com"&gt;Hubot&lt;/a&gt; was released I've been regular expressing myself. Here is a tool I built to make testing regular expressions in javascript easier.&lt;p&gt;&lt;a href="http://rubular.com"&gt;Rubular&lt;/a&gt; was my go to for testing regex in the past, but its targeted at Ruby so I went in search of a nice editor for javascript regular expressions. Unfortunately my search yielded no results. Fortunately I had the tools and experience to build one!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://scriptular.com"&gt;Scriptular&lt;/a&gt; is the fruits of my labor. I modeled Scriptular after Rubular with one major difference. It doesn&amp;#8217;t have a backend service, everything runs in the browser.&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/4f528c42dabe9d7056022d3b/blog_post/screen_shot_20120303_at_1.24.57_pm.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;I am really excited about Scriptular, I think it will be useful for developers everywhere. With its current implementation you can test how a regex reacts in any browser by loading Scriptular in that browser and testing the regex. In the future I would also like to have a backend service for testing server side javascript implementations like V8.&lt;/p&gt;
&lt;p&gt;So go &lt;a href="http://scriptular.com"&gt;kick the tires&lt;/a&gt;, give it a &lt;a href="http://scriptular.com"&gt;spin around the block&lt;/a&gt;, and let me know what you think. If you would like to help on the project please &lt;a href="http://github.com/jonmagic/scriptular"&gt;check it out on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Update: Thanks to &lt;a href="http://opensoul.org"&gt;@bkeepers&lt;/a&gt; for contributing the design.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>New Tabs and Cucumber</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2012/02/07/new-tabs-and-cucumber/" />
      <id>http://theprogrammingbutler.com/blog/archives/2012/02/07/new-tabs-and-cucumber/</id>
      <updated>2012-02-07T13:37:28-05:00</updated>
      <published>2012-02-07T13:00:00-05:00</published>
      
      <summary type="html">While working on an internal app at &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; I had to write a &lt;a href="http://cukes.info/"&gt;cucumber&lt;/a&gt; scenario that ran expectations against a new tab that was opened. Here is how I did it.</summary>
      <content type="html">While working on an internal app at &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; I had to write a &lt;a href="http://cukes.info/"&gt;cucumber&lt;/a&gt; scenario that ran expectations against a new tab that was opened. Here is how I did it.&lt;h3&gt;The Code&lt;/h3&gt;
&lt;p&gt;Searching around the internet, I finally found a tip on &lt;a href="http://stackoverflow.com/questions/3104348/ruby-on-rails-cucumber-how-do-i-follow-a-link-that-opens-a-new-window"&gt;StackOverflow&lt;/a&gt; that got me moving in the right direction. In this context tabs are referred to as windows.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This code grabs the browser object and calls switch_to window on it and passes in the last opened window.&lt;/p&gt;
&lt;p&gt;Now all we need to do is wrap this in a step so we can use it in our scenarios.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;When&lt;/span&gt; &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;^I access the new tab$&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;
  page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;The Caveat&lt;/h3&gt;
&lt;p&gt;This will only work if you are using &lt;a href="http://seleniumhq.org/docs/"&gt;selenium-webdriver&lt;/a&gt;. It will &lt;a href="https://github.com/thoughtbot/capybara-webkit/issues/47"&gt;not work with capybara-webkit&lt;/a&gt; unfortunately. So I switched to selenium, but I told it to use chrome instead of the default firefox and it still works great!&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Capybara&lt;/span&gt;.javascript_driver = &lt;span class="sy"&gt;:selenium&lt;/span&gt;
&lt;span class="co"&gt;Capybara&lt;/span&gt;.register_driver &lt;span class="sy"&gt;:selenium&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt; |app|
  &lt;span class="co"&gt;Capybara&lt;/span&gt;::&lt;span class="co"&gt;Selenium&lt;/span&gt;::&lt;span class="co"&gt;Driver&lt;/span&gt;.new(app, &lt;span class="sy"&gt;:browser&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:chrome&lt;/span&gt;)
&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;The Finale&lt;/h3&gt;
&lt;p&gt;Now its time to see the step in action. Notice I had to tag the feature with @javascript so that it uses the selenium webdriver.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="iv"&gt;@javascript&lt;/span&gt;
&lt;span class="co"&gt;Feature&lt;/span&gt;: &lt;span class="co"&gt;Open&lt;/span&gt; a discussion

  &lt;span class="co"&gt;Scenario&lt;/span&gt;: staff opens a discussion with the mouse
    &lt;span class="co"&gt;Given&lt;/span&gt; the following users exist:
      | username  | email                |
      | test-user | integration&lt;span class="iv"&gt;@test&lt;/span&gt;.com |
    &lt;span class="co"&gt;And&lt;/span&gt; &lt;span class="co"&gt;I&lt;/span&gt; am on the triage page
    &lt;span class="co"&gt;When&lt;/span&gt; &lt;span class="co"&gt;I&lt;/span&gt; follow &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Can't get git running on my mac&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="co"&gt;And&lt;/span&gt; &lt;span class="co"&gt;I&lt;/span&gt; access the new tab
    &lt;span class="co"&gt;Then&lt;/span&gt; &lt;span class="co"&gt;I&lt;/span&gt; should be on the discussion page &lt;span class="r"&gt;for&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;5786909&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="co"&gt;And&lt;/span&gt; &lt;span class="co"&gt;I&lt;/span&gt; should see &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Can't get git running on my mac&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The link that I follow opens the new page in a new tab, I select the new tab, then run my expectations against it.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>Being acquired doesn't have to suck</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2012/01/08/being-acquired-doesnt-have-to-suck/" />
      <id>http://theprogrammingbutler.com/blog/archives/2012/01/08/being-acquired-doesnt-have-to-suck/</id>
      <updated>2012-01-08T17:36:54-05:00</updated>
      <published>2012-01-08T12:00:00-05:00</published>
      
      <summary type="html">It has been a month since &lt;a href="https://github.com/blog/993-ordered-list-is-a-githubber"&gt;Ordered List was acquired by GitHub&lt;/a&gt; and our team of 5 joined their team of 50, and it hasn’t sucked at all. Here are some observations on how to remove the suck from acquisitions.</summary>
      <content type="html">It has been a month since &lt;a href="https://github.com/blog/993-ordered-list-is-a-githubber"&gt;Ordered List was acquired by GitHub&lt;/a&gt; and our team of 5 joined their team of 50, and it hasn’t sucked at all. Here are some observations on how to remove the suck from acquisitions.&lt;h3&gt;The Suck&lt;/h3&gt;
&lt;p&gt;My general attitude towards acquisitions the past few years has been fairly negative. I&amp;#8217;ve seen too many people and products we love be acquired and the people only stick around until their stock vests and the products are shut down or perverted into something hideous.&lt;/p&gt;
&lt;p&gt;With all that negative sentiment you would think I would have fought for Ordered List to remain independent, but I assure you everyone on our team was not only on board with the acquisition but also excited about the opportunity.&lt;/p&gt;
&lt;p&gt;The number one problem after an acquisition are differences in culture. From how the individuals and teams work, to how they interact, how they are led, and how they are motivated.&lt;/p&gt;
&lt;p&gt;We would not have even considered joining GitHub if there were large differences in culture and any company looking at an acquisition should make sure this is the first thing they research and consider.&lt;/p&gt;
&lt;h3&gt;The Reality&lt;/h3&gt;
&lt;p&gt;Both sides in this acquisition did their homework and didn&amp;#8217;t just jump in without lots of serious consideration. Putting in this work ahead of time has made the actual integration of our teams virtually frictionless.&lt;/p&gt;
&lt;p&gt;My day to day work has not changed and yours shouldn&amp;#8217;t have to either. This is definitely something to think about before an acquisition. Do they know what you do best and will they give you the opportunity to continue doing it? Thankfully I&amp;#8217;m still working on the products I love and now I have a pool of talent and knowledge 10x greater than before to draw from.&lt;/p&gt;
&lt;p&gt;There is definitely more to keep track of since there are more people, more products, and just more going on in general, but the time I spend on that is a lot less than the time I used to spend on client work to make sure my salary got paid. Acquisitions can and should give you more opportunities to concentrate on what you are passionate about.&lt;/p&gt;
&lt;p&gt;Yes, its only been a month, how can I be sure this acquisition won&amp;#8217;t suck? I feel like I&amp;#8217;ve been working with these people for a long time, and in a way I have. I have been hanging out with them at conferences, working on open source code with them, and having conversations with them on Twitter for much longer than I&amp;#8217;ve been their coworker.&lt;/p&gt;
&lt;p&gt;In the tech industry we have and should take advantage of those opportunities. We can follow and get to know people through their code (a great way to use &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;!) as well as on social networks and at conferences. Do your best to know the people you are getting into bed with.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;My attitude towards acquisitions has definitely changed, but only because it&amp;#8217;s clearer to me what works and what doesn&amp;#8217;t.&lt;/p&gt;
&lt;p&gt;Avoid merging teams with drastically different cultures, understand the strengths and weaknesses of the teams on both sides and be committed to letting them do what they do best, and know the actual people you will share the future with.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>Assimilating Contributed Code</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2011/12/30/assimilating-contributed-code/" />
      <id>http://theprogrammingbutler.com/blog/archives/2011/12/30/assimilating-contributed-code/</id>
      <updated>2011-12-30T12:59:59-05:00</updated>
      <published>2011-12-30T10:55:00-05:00</published>
      
      <summary type="html">This year I authored several RubyGems and just this week finally learned how to work with a contributor.</summary>
      <content type="html">This year I authored several RubyGems and just this week finally learned how to work with a contributor.&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; &lt;a href="http://twitter.com/bryckbost"&gt;@bryckbost&lt;/a&gt; points out that the &lt;a href="https://github.com/defunkt/github-gem"&gt;github-gem&lt;/a&gt; does exactly what I wanted to do. See the &lt;strong&gt;Fetching and Evaluating Downstream Changes&lt;/strong&gt; section of the &lt;span class="caps"&gt;README&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Of course &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; has the great &lt;strong&gt;Merge pull request&lt;/strong&gt; option when an auto-merge is possible, and I use that quite often, but the workflow on &lt;span class="caps"&gt;OSS&lt;/span&gt; projects sometimes requires you to run the tests locally and make any modifications before merging it.&lt;/p&gt;
&lt;p&gt;A quick search didn&amp;#8217;t turn up any easy to read instructions, and I&amp;#8217;m no git guru, so it took me a few minutes to figure out a simple workflow.&lt;/p&gt;
&lt;p&gt;Here is how I checked out, tested, modified, and merged a &lt;a href="https://github.com/jonmagic/ghee/pull/1"&gt;massive pull request&lt;/a&gt; for &lt;a href="http://github.com/jonmagic/ghee"&gt;Ghee&lt;/a&gt; from &lt;a href="https://github.com/rauhryan"&gt;Ryan Rauh&lt;/a&gt; this week.&lt;/p&gt;
&lt;h3&gt;1. Clone my repo and create a feature branch&lt;/h3&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;git clone git@github.com:jonmagic/ghee.git
cd ghee
git checkout -b repos_support master&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This creates a new branch called repos_support, based off of master, and checks it out.&lt;/p&gt;
&lt;h3&gt;2. Pull contributors code into your local branch&lt;/h3&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;git pull https://github.com/rauhryan/ghee.git repos_support&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This pulls the repos_support branch from the remote repo and merges it into the branch you have checked out (which we also called repos_support).&lt;/p&gt;
&lt;h3&gt;3. Run tests, make modifications, commit changes&lt;/h3&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;bundle exec rake
touch OHNOES.txt
git add OHNOES.txt
git commit -m &amp;quot;Added OHNOES&amp;quot;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;4. Checkout master, merge feature branch, push&lt;/h3&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;git checkout master
git merge repos_support
git push&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;This workflow follows the &lt;a href="http://en.wikipedia.org/wiki/KISS_principle"&gt;kiss principle&lt;/a&gt;, so it worked quite well for me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please give me feedback&lt;/strong&gt;. I would love to hear about how other people accomplish this task, so I encourage you to leave links/tips/tricks in the comments below.&lt;/p&gt;
&lt;p&gt;Also be sure to checkout &lt;a href="https://github.com/jonmagic/ghee/compare/71fe16a34aad6edf9d17379e7f3dd413e6855e21...2065149ff01be1770d3d51bdb8b9272ebb972e4d"&gt;Ryan&amp;#8217;s awesome work&lt;/a&gt; on &lt;a href="http://github.com/jonmagic/ghee"&gt;Ghee&lt;/a&gt;, a simple ruby client for the &lt;a href="http://developer.github.com/v3/"&gt;GitHub &lt;span class="caps"&gt;API&lt;/span&gt; V3&lt;/a&gt;.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>Twelve (gauge)</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2011/12/09/twelve-gauge/" />
      <id>http://theprogrammingbutler.com/blog/archives/2011/12/09/twelve-gauge/</id>
      <updated>2011-12-09T18:27:05-05:00</updated>
      <published>2011-12-09T18:00:00-05:00</published>
      
      <summary type="html">Today I hacked together an easy to use gem for accessing the &lt;a href="http://get.gaug.es"&gt;Gauges&lt;/a&gt; API.</summary>
      <content type="html">Today I hacked together an easy to use gem for accessing the &lt;a href="http://get.gaug.es"&gt;Gauges&lt;/a&gt; API.&lt;p&gt;When I started this morning 12-gauge was the first thing I thought, so I called the gem Twelve (silly I know).&lt;/p&gt;
&lt;p&gt;I had fun figuring out the &lt;span class="caps"&gt;API&lt;/span&gt; (with a little help from &lt;a href="http://twitter.com/bkeepers"&gt;Brandon&lt;/a&gt;) and then writing the gem using some of the proxy object and method missing stuff I was learning a few weeks ago.&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;gem install twelve&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;Usage&lt;/h3&gt;
&lt;p&gt;Get the client ready:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;access_token = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;abcd1234&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
bfg = &lt;span class="co"&gt;Twelve&lt;/span&gt;.new(access_token)&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Request your Gauges info:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;bfg.me&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For me I got this back:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;{&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Jonathan Hoyt&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;urls&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;{&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;https://secure.gaug.es/me&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;gauges&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;https://secure.gaug.es/gauges&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;clients&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;https://secure.gaug.es/clients&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Hoyt&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;first_name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Jonathan&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;jonmagic@gmail.com&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Next try these:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;bfg.clients
bfg.gauges&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;More Documentation and Examples&lt;/h3&gt;
&lt;p&gt;Its a full-fledged client, so you can create, update, and delete gauges as well as see all the different types of information available on a gauge. See the docs on &lt;a href="https://github.com/jonmagic/twelve"&gt;GitHub&lt;/a&gt;!&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>GitHubber</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2011/12/05/githubber/" />
      <id>http://theprogrammingbutler.com/blog/archives/2011/12/05/githubber/</id>
      <updated>2011-12-05T13:04:23-05:00</updated>
      <published>2011-12-05T12:00:00-05:00</published>
      
      <summary type="html">Today the whole crew from Ordered List joins GitHub!
</summary>
      <content type="html">Today the whole crew from Ordered List joins GitHub!
&lt;p&gt;&lt;img src="/assets/4edcfe61dabe9d380e00519c/20111205n75qfwihebs5pj53aucy71qxui.png" class="plain" /&gt;&lt;/p&gt;
&lt;h3&gt;Ordered List&lt;/h3&gt;
&lt;p&gt;Last year was a &lt;a href="/blog/archives/2010/11/18/hey-mom-i-got-a-job/"&gt;big year for myself&lt;/a&gt; and &lt;a href="http://orderedlist.com"&gt;Ordered List&lt;/a&gt;. &lt;a href="https://twitter.com/orderedlist"&gt;Steve&lt;/a&gt; and &lt;a href="https://twitter.com/jnunemaker"&gt;John&lt;/a&gt; launched &lt;a href="http://get.harmonyapp.com"&gt;Harmony&lt;/a&gt; in August, I started hanging out with them on a regular basis and &lt;a href="/blog/archives/2011/10/03/the-history-of-speaker-deck/"&gt;began work&lt;/a&gt; on &lt;a href="http://speakerdeck.com"&gt;Speaker Deck&lt;/a&gt;, and the end of the year saw &lt;a href="http://opensoul.org"&gt;Brandon Keepers&lt;/a&gt; and I leaving our &lt;a href="http://collectiveidea.com"&gt;own&lt;/a&gt; &lt;a href="http://sabretechllc.com"&gt;businesses&lt;/a&gt; to make OL &lt;a href="http://orderedlist.com/blog/articles/four/"&gt;four strong&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This year was even bigger, launching &lt;a href="http://get.gaug.es"&gt;Gauges&lt;/a&gt; and &lt;a href="/blog/archives/2011/10/10/launching-speaker-deck/"&gt;Speaker Deck&lt;/a&gt;, adding &lt;a href="http://orderedlist.com/blog/articles/welcome-matt-graham/"&gt;Matt Graham&lt;/a&gt; to the team, and beginning the journey of learning &lt;a href="/blog/archives/2011/03/02/new-guy-blues/"&gt;how&lt;/a&gt; to &lt;a href="/blog/archives/2011/03/03/share-the-dream/"&gt;work&lt;/a&gt; as a &lt;a href="/blog/archives/2011/11/29/how-we-work/"&gt;cohesive unit&lt;/a&gt;. While we learned each others strengths and weaknesses I began my own &lt;a href="/blog/archives/2011/10/20/mentors/"&gt;journey&lt;/a&gt; of becoming a full-time programmer that could not only contribute to the growth of our company, but also lead in certain circumstances.&lt;/p&gt;
&lt;p&gt;We all dreamed of taking over the world, and we knew we could do it together. We also know it takes time to build something great and that as time goes on new opportunities present themselves. Every once in awhile those opportunities get you even more excited than the dream you are currently living. One year (minus a day) after I joined Ordered List our entire team has accepted the opportunity to join &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;GitHub&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/about#company_description"&gt;This company&lt;/a&gt; and the &lt;a href="https://github.com/about#the_team"&gt;team behind it&lt;/a&gt; has been near and dear to our hearts for years. I had the chance to meet and hang out with a &lt;a href="http://zachholman.com/"&gt;few&lt;/a&gt; &lt;a href="http://timclem.wordpress.com/"&gt;GitHubbers&lt;/a&gt; &lt;a href="http://twitter.com/mtodd"&gt;over&lt;/a&gt; the last year and have really come to appreciate them as &lt;a href="http://twitter.com/mtodd"&gt;programmers&lt;/a&gt;, &lt;a href="http://tom.preston-werner.com/2011/03/29/ten-lessons-from-githubs-first-year.html"&gt;professionals&lt;/a&gt;, &lt;a href="http://zachholman.com/posts/customer-support-doesnt-have-to-suck/"&gt;writers&lt;/a&gt;, and people. When they started &lt;a href="http://speakerdeck.com/u/holman/p/how-github-uses-github-to-build-github"&gt;talking&lt;/a&gt; &lt;a href="http://speakerdeck.com/u/schacon/p/robots-beer-and-maslow"&gt;about&lt;/a&gt; their &lt;a href="http://speakerdeck.com/u/mojombo/p/optimizing-for-happiness"&gt;culture&lt;/a&gt; at conferences I marveled even more, excited about how they were &lt;a href="http://speakerdeck.com/u/schacon/p/robots-beer-and-maslow?slide=79"&gt;changing the rules&lt;/a&gt;, hiring &lt;a href="http://www.google.com/search?client=safari&amp;amp;rls=en&amp;amp;q=site:github.com/blog+is+a+GitHubber&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8"&gt;tons of awesome people&lt;/a&gt;, and just &lt;a href="https://github.com/blog/936-one-million"&gt;kicking-butt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When the opportunity to join GitHub materialized it sparked an epic discussion about the possibilities. It made sense in so many ways, but whenever you entertain the chance to change course you can&amp;#8217;t help but wonder how far you can get on your current trajectory. There were a lot of factors to consider and in the end Steve and John decided that our personal and collective futures with GitHub seemed greater.&lt;/p&gt;
&lt;p&gt;Over the past few weeks the details were hammered out and during that time we&amp;#8217;ve each had a chance to reset our dreams for the future, while trying to &lt;a href="http://twitter.com/michigangraham/status/142695650084139008"&gt;keep&lt;/a&gt; &lt;a href="http://twitter.com/holman/status/142696256022659072"&gt;the&lt;/a&gt; &lt;a href="http://twitter.com/michigangraham/status/143443710292672512"&gt;whole&lt;/a&gt; &lt;a href="http://twitter.com/holman/status/143444127403618304"&gt;thing&lt;/a&gt; a secret.&lt;/p&gt;
&lt;h3&gt;The Future&lt;/h3&gt;
&lt;p&gt;Right now I have no idea what the future holds, except that it is going to be great. I am most excited about the journey, learning new things, powering thru the hard times, accelerating during the good times, and building something that we can all be proud of.&lt;/p&gt;
&lt;p&gt;Thanks again to everyone involved in making this a reality. Watch out world.&lt;/p&gt;
&lt;h3&gt;Links&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="https://github.com/blog/993-ordered-list-is-a-githubber"&gt;Ordered List is a GitHubber&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="https://github.com/blog/996-jonathan-hoyt-is-a-githubber"&gt;Jonathan Hoyt is a GitHubber&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>How We Work</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2011/11/29/how-we-work/" />
      <id>http://theprogrammingbutler.com/blog/archives/2011/11/29/how-we-work/</id>
      <updated>2011-11-29T06:00:11-05:00</updated>
      <published>2011-11-29T06:00:00-05:00</published>
      
      <summary type="html">I've been working at Ordered List for almost a year now and wanted to share some observations on how we work.
</summary>
      <content type="html">I've been working at Ordered List for almost a year now and wanted to share some observations on how we work.
&lt;h3&gt;Ideas&lt;/h3&gt;
&lt;p&gt;We launched two products this year while continuing work on our first. The ideas for these products came from spending time together hanging out, brainstorming, drinking a few beers, and talking about services we already used that caused us great pain.&lt;/p&gt;
&lt;p&gt;The idea for Speaker Deck was born out of a frustration with other slide sharing services. Over a scotch or two Steve and John outlined what they envisioned a slide sharing service would look like, with me listening in intently.&lt;/p&gt;
&lt;p&gt;When the conversation was over I had a pretty clear idea of what the initial product could look like and quickly volunteered to start working on it. At this point Ordered List was still just Steve and John, but this conversation, and my willingness to work on the product, eventually helped with them hiring me.&lt;/p&gt;
&lt;p&gt;The ideas and visions for our products have varied greatly during our brainstorming sessions over the last year, but we always come back to the pain that inspired the product in the first place and execute on that first before moving on to some of the grander ideas we have.&lt;/p&gt;
&lt;p&gt;After a product has shipped our users feedback begins to inform our decisions moving forward. We do our best to make it easy for them to share their ideas so we can add it to our brainstorming process.&lt;/p&gt;
&lt;h3&gt;Execution&lt;/h3&gt;
&lt;p&gt;We have very few processes that help us in executing our ideas, which is great, because it makes it easy for me to share them with you now!&lt;/p&gt;
&lt;h4&gt;Building The Right Team&lt;/h4&gt;
&lt;p&gt;I think the most important process at Ordered List is how Steve and John choose the people they want to work with.&lt;/p&gt;
&lt;p&gt;They built their team with people who could work autonomously and take ownership of their products and client projects, filling in the gaps where necessary and taking leadership roles when called to. They built a team of unique individuals, each with different strengths. We have starters and we have finishers, visionaries and those not afraid to do the grunt work, those obsessed with the beauty of the code and those preoccupied with the beauty of the UI.&lt;/p&gt;
&lt;p&gt;Over the past year we have been learning each other strengths and weaknesses and how to ask for help when we know another person on the team is better suited to make a decision or offer guidance. This has not been easy, but is essential to how we execute.&lt;/p&gt;
&lt;p&gt;Whoever is the most passionate in an argument is the person that has put the most thought and research into it, so they usually win.&lt;/p&gt;
&lt;h4&gt;Minimum Process&lt;/h4&gt;
&lt;p&gt;We do not avoid processes in our work day, but we definitely do not go seeking them out. The processes we use day to day are there only because it was more painful to operate without them.&lt;/p&gt;
&lt;p&gt;We write tests first and implement second, except when we don&amp;#8217;t. We use staging servers. We make sure deploying is easy and can be done by anyone on the team. This process of well tested code and a place to easily deploy it and make sure everything works as intended removes the fear of deploying code to production and having it bring down an entire service.&lt;/p&gt;
&lt;p&gt;Using pull requests on Github has changed the way we work. Even more autonomy when implementing, but you still get asynchronous feedback once you get a feature to where you think it should be. We even switched to Github Issues for all of our products so that all of our conversations around code happen in the same place, next to the code.&lt;/p&gt;
&lt;p&gt;Probably the most important but least obvious process that has emerged as we&amp;#8217;ve coalesced as a team is how we communicate. Setting up team@orderedlist.com made starting email threads trivial, Hipchat made chatting during the day easy, and iChat or Google+ video chats kept us face to face with our two remote team members. Recently we&amp;#8217;ve been using iMessage to text back and forth like a bunch of fourteen year old girls. Seriously.&lt;/p&gt;
&lt;h4&gt;Shipping&lt;/h4&gt;
&lt;p&gt;We try not to ship a feature before it is ready, we prefer well thought out features, but some days we&amp;#8217;ll ship six, seven, eight times if we&amp;#8217;re fixing small things. There is no pressure to ship or not ship, when our intuition says its ready, it ships.&lt;/p&gt;
&lt;p&gt;Everyone on our team likes shipping things we are proud of right out the gate. This doesn&amp;#8217;t sound very agile, but since we&amp;#8217;re building products that we use ourselves, we have a pretty good sense of what to build in the first place. Yes, sometimes things change once the feature is out in the wild, but this is not a common occurrence.&lt;/p&gt;
&lt;p&gt;We take ideas, we boil them down, we build them, and then we ship them.&lt;/p&gt;
&lt;h3&gt;Celebration&lt;/h3&gt;
&lt;p&gt;There is one other process I want to mention, my favorite one. We love to celebrate. Once a feature has shipped things have come full circle, the ideas that were born over a few beers have become a reality, and now we gather again, drink a few beers to celebrate, and start brainstorming the next big idea.&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>Finish Weekend</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2011/11/12/finish-weekend/" />
      <id>http://theprogrammingbutler.com/blog/archives/2011/11/12/finish-weekend/</id>
      <updated>2011-11-12T23:08:48-05:00</updated>
      <published>2011-11-12T22:00:00-05:00</published>
      
      <summary type="html">While I initially had issues with the concept of Finish Weekend, I'm really glad I participated and believe everyone involved is better off for it.</summary>
      <content type="html">While I initially had issues with the concept of Finish Weekend, I'm really glad I participated and believe everyone involved is better off for it.&lt;h3&gt;The Who&lt;/h3&gt;
&lt;p&gt;My friends at &lt;a href="http://collectiveidea.com"&gt;Collective Idea&lt;/a&gt; have apparently been talking about doing a &lt;a href="http://finishweekend.com"&gt;Finish Weekend&lt;/a&gt; for a few years and this is the year they made it happen! They put out the word thru Twitter, friends, collegues, and a ton of people signed up and showed up!&lt;/p&gt;
&lt;p&gt;I met folks from Detroit, Chicago, South Bend, and even as far away as California! There were programmers, designers, editors, math geeks, marketers, and testers just to name a few.&lt;/p&gt;
&lt;h3&gt;The Why&lt;/h3&gt;
&lt;p&gt;Finish Weekend was born out of a personal and professional frustration with starting things and never finishing them. What if there was a weekend dedicated to taking something you&amp;#8217;ve started, never found time to finish, and actually finish it. Even better, what if there were people around to help you finish it!&lt;/p&gt;
&lt;p&gt;Many folks showed up with projects to finish, but what really surprised me were how many people showed up to help other people finish! This brings us to my issue with finish weekend.&lt;/p&gt;
&lt;h3&gt;My Issue&lt;/h3&gt;
&lt;p&gt;When first told about Finish Weekend immediately I reacted negatively because I believe we should be working hard to finish things every day. I love finishing things. Finishing projects is hard (that last 5% can be excruciating) but the joy you get from shipping feature X, or accomplishing goal Y, is greater than the joy I personally get from starting a project (as much fun as that is).&lt;/p&gt;
&lt;p&gt;When I finally got over myself and realized that Collective Idea was trying to help people learn how to finish things I signed up and made the trek to Holland Michigan. I did not regret it.&lt;/p&gt;
&lt;h3&gt;The Outcome&lt;/h3&gt;
&lt;p&gt;Today I saw a great group of people with greatly varying skillsets and backgrounds come together with one purpose, to finish things. We had people building video based web apps, crazy poetry recombinators, iPhone apps, and even a bond trader learning Python to automate a process that has taken him 1.5 hours every work evening for the last two years in Excel.&lt;/p&gt;
&lt;p&gt;I was able to teach basic programming concepts, performance measuring and optimization, even cut up a mockup into html/css, and paired with my coworker on some tech that will hopefully help power our products into the future.&lt;/p&gt;
&lt;p&gt;Collective Idea nailed it with Finish Weekend and my hope and desire is that we take the relationships and spirit of pitching in together to accomplish big and small things and carry it into the rest of our lives and not relegate it to a weekend.&lt;/p&gt;
&lt;p&gt;Of course we&amp;#8217;ll need reminded every so often. See you at the next Finish Weekend :)&lt;/p&gt;
&lt;h3&gt;Links&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;Learn more about Finish Weekend at &lt;a href="http://finishweekend.com"&gt;finishweekend.com&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Learn more about the great folks at Collective Idea at &lt;a href="http://collectiveidea.com"&gt;collectiveidea.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>hubot Scripts Explained</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2011/10/28/hubot-scripts-explained/" />
      <id>http://theprogrammingbutler.com/blog/archives/2011/10/28/hubot-scripts-explained/</id>
      <updated>2011-11-03T12:52:28-04:00</updated>
      <published>2011-10-28T16:39:00-04:00</published>
      
      <summary type="html">Ok, so now you've got your shiny new hubot up and ready to listen to your every command. But what should we tell him to do with our nonsense!</summary>
      <content type="html">Ok, so now you've got your shiny new hubot up and ready to listen to your every command. But what should we tell him to do with our nonsense!&lt;h3&gt;Basics&lt;/h3&gt;
&lt;p&gt;Scripts for &lt;a href="https://github.com/github/hubot"&gt;hubot&lt;/a&gt; are written with &lt;a href="http://jashkenas.github.com/coffee-script/"&gt;CoffeeScript&lt;/a&gt;. This is what a basic script looks like:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# hubot greeting.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# (hi|hello) - say hi to your butler&lt;/span&gt;

&lt;span class="r"&gt;module&lt;/span&gt;.exports = (robot) -&amp;gt;
  robot.respond &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;hi|hello&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;, (msg) -&amp;gt;
    msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Howdy!&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Lets break this script down. The first line is just a description of the script. The third line tells hubot what to include in the help (when you ask hubot for help).&lt;/p&gt;
&lt;p&gt;The actual code starts on the module.exports line. Every script you make will start with that line.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt;.exports = (robot) -&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The next line tells hubot to respond to hi and hello.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;robot.respond &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;hi|hello&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;, (msg) -&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It uses a &lt;a href="http://en.wikipedia.org/wiki/Regular_expression"&gt;regular expression&lt;/a&gt; to parse the text, looking for the words hi and hello. The i after the last slash tells the regular expression to not be case sensitive, so it will also match Hi and Hello.&lt;/p&gt;
&lt;p&gt;I like to use &lt;a href="http://rubular.com/"&gt;rubular&lt;/a&gt; for writing and testing regular expressions. Its quick, easy to use, and while javascript regular expressions aren&amp;#8217;t exactly like ruby regular expressions I haven&amp;#8217;t run into any inconsistencies yet.&lt;/p&gt;
&lt;p&gt;Finally we tell hubot to take the message and send a message back.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Howdy!&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;Respond vs Hear&lt;/h3&gt;
&lt;p&gt;I didn&amp;#8217;t discover this at first and thought that hubot only responded to commands directed at him, but then I discovered robot.hear! Whereas robot.respond only matches messages directed at hubot, robot.hear will run your regular expression against any chat message!&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Hubot has an attitude&lt;/span&gt;

&lt;span class="r"&gt;module&lt;/span&gt;.exports = (robot) -&amp;gt;
  robot.hear &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;tired|too hard|to hard|upset|bored&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;, (msg) -&amp;gt;
    msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Panzy&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;See what I did there :) Any time someone in our chat room says they are tired, that something is too hard, upset, or bored, hubot tells them they&amp;#8217;re a panzy. Oh yeah. This robot butler has an attitude.&lt;/p&gt;
&lt;h3&gt;Random&lt;/h3&gt;
&lt;p&gt;I saw this used first in the shipit script, which displays a random shipit squirrel for your viewing pleasure whenever someone says the words &amp;#8220;ship it&amp;#8221; in your chat room.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Rodent Motivation&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# ship it - Display a motivation squirrel&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;

squirrels = [
  &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;http://img.skitch.com/20100714-d6q52xajfh4cimxr3888yb77ru.jpg&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;https://img.skitch.com/20111026-r2wsngtu4jftwxmsytdke6arwd.png&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;http://cl.ly/1i0s1r3t2s2G3P1N3t3M/Screen_Shot_2011-10-27_at_9.36.45_AM.png&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;http://shipitsquirrel.github.com/images/squirrel.png&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
]

&lt;span class="r"&gt;module&lt;/span&gt;.exports = (robot) -&amp;gt;
  robot.hear &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;ship it&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;, (msg) -&amp;gt;
    msg.send msg.random squirrels&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Notice the array that we create with 4 different shipit squirrel images. Then notice this line:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;msg.send msg.random squirrels&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The msg object has a random method on it which we can pass an array and it will pick a random item from that array! Super handy to keep things from getting repetitive.&lt;/p&gt;
&lt;h3&gt;Reply&lt;/h3&gt;
&lt;p&gt;You can reply to a user by changing the send command to reply like this:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;msg.reply &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Why thank you sir!&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Replies will be directed at a specific user, example: &amp;#8220;@hoyt Why thank you sir!&amp;#8221;&lt;/p&gt;
&lt;h3&gt;Http&lt;/h3&gt;
&lt;p&gt;So far we&amp;#8217;ve only talked about how to make hubot listen and respond in various ways. Hubot really starts to get interesting when we empower him to go out and do our bidding in the larger world though. This is where hubot really starts to become powerful!&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Whois for gems, because gem names are like domains in the 90's&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# gem whois &amp;lt;gemname&amp;gt; - returns gem details if it exists&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;

&lt;span class="r"&gt;module&lt;/span&gt;.exports = (robot) -&amp;gt;
  robot.respond &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;gem whois (.*)&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;, (msg) -&amp;gt;
    gemname = escape(msg.match[&lt;span class="i"&gt;1&lt;/span&gt;])
    msg.http(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;http://rubygems.org/api/v1/gems/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;gemname&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.json&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
      .get() (err, res, body) -&amp;gt;
        try
          json = &lt;span class="co"&gt;JSON&lt;/span&gt;.parse(body)
          msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;   gem name: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.name&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
     owners: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.authors&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
       info: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.info&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
    version: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.version&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
  downloads: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.downloads&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
        catch error
          msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Gem not found. It will be mine. Oh yes. It will be mine. *sinister laugh*&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This script is doing quite a bit so we&amp;#8217;ll dissect it line by line.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;robot.respond &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;gem whois (.*)&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;, (msg) -&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This tells hubot to look for messages directed at him that have the words &amp;#8220;gem whois&amp;#8221; and then some string.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;gemname = escape(msg.match[&lt;span class="i"&gt;1&lt;/span&gt;])&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now I grab the gemname from the regular expression. msg.match with an integer will match the captured item from the regular expression. You use parenthesis to capture strings in regular expressions, and they get numbered left to right by however many there are. In this case its the first one, so we pass 1 to msg.match and then assign it off to our variable gemname.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;msg.http(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;http://rubygems.org/api/v1/gems/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;gemname&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.json&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Next we tell the msg.http object to use this url, with the gemname interpolated in it.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;.get() (err, res, body) -&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The .get() function kicks off the request and returns 3 objects, err, res, and body. In this case we&amp;#8217;re only interested in body.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;try
  json = &lt;span class="co"&gt;JSON&lt;/span&gt;.parse(body)
  msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;   gem name: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.name&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
    owners: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.authors&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
    info: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.info&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
    version: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.version&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="k"&gt;
    downloads: &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;json.downloads&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
catch error
  msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Gem not found. It will be mine. Oh yes. It will be mine. *sinister laugh*&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If &lt;span class="caps"&gt;JSON&lt;/span&gt;.parse is able to parse the body then it displays the gem information, if it errors we get the &amp;#8220;Gem not found&amp;#8221; message.&lt;/p&gt;
&lt;h3&gt;Advanced &lt;span class="caps"&gt;HTTP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;What if you want to hit an &lt;span class="caps"&gt;API&lt;/span&gt; that requires authentication? Here is a script that uses http basic auth when hitting the &lt;a href="http://dnsimple.com"&gt;dnsimple&lt;/a&gt; api to check domain name availability.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Domain availability via DNSimple, requires you set&lt;/span&gt;
&lt;span class="c"&gt;# DNSIMPLE_USERNAME &amp;amp; DNSIMPLE_PASSWORD environment variables&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# check domain &amp;lt;domainname&amp;gt; - returns whether a domain is available&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;

&lt;span class="r"&gt;module&lt;/span&gt;.exports = (robot) -&amp;gt;
  robot.hear &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;check domain (.*)&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="mod"&gt;i&lt;/span&gt;&lt;/span&gt;, (msg) -&amp;gt;
    domain = escape(msg.match[&lt;span class="i"&gt;1&lt;/span&gt;])
    user = process.env.&lt;span class="co"&gt;DNSIMPLE_USERNAME&lt;/span&gt;
    pass = process.env.&lt;span class="co"&gt;DNSIMPLE_PASSWORD&lt;/span&gt;
    auth = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Basic &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; + new Buffer(user + &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; + pass).toString(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;);
    msg.http(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;https://dnsimple.com/domains/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;domain&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;/check&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
      .headers(&lt;span class="co"&gt;Authorization&lt;/span&gt;: auth, &lt;span class="co"&gt;Accept&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)
      .get() (err, res, body) -&amp;gt;
        switch res.statusCode
          &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;200&lt;/span&gt;
            msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Sorry, &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;domain&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; is not available.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;404&lt;/span&gt;
            msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Cybersquat that s***!&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;401&lt;/span&gt;
            msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;You need to authenticate by setting the DNSIMPLE_USERNAME &amp;amp; DNSIMPLE_PASSWORD environment variables&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="r"&gt;else&lt;/span&gt;
            msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Unable to process your request and we're not sure why :(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;We do the same thing as the last example, grabbing the domain name that is captured by the regular expression, but then things get a bit different.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;user = process.env.&lt;span class="co"&gt;DNSIMPLE_USERNAME&lt;/span&gt;
pass = process.env.&lt;span class="co"&gt;DNSIMPLE_PASSWORD&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Here we grab some environment variables and assign them to variables. If you are &lt;a href="http://jonmagic.com/blog/archives/2011/10/28/hipchat-hubot-and-me/"&gt;deploying hubot to Heroku&lt;/a&gt; then setting environment variables is crazy easy:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;heroku config:add DNSIMPLE_USERNAME=john@doe.com DNSIMPLE_PASSWORD=4w3s0m3p4ssw0rd&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Next we have to create the auth string that we&amp;#8217;ll stuff into the authorization header.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;auth = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Basic &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; + new Buffer(user + &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; + pass).toString(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Creating that auth string is some javascript voodoo that took me awhile to figure out, finally finding an article on &lt;a href="http://stackoverflow.com/questions/3905126/how-to-use-http-client-in-node-js-if-there-are-basic-authorization"&gt;stackoverflow&lt;/a&gt; that had the magic I needed.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;msg.http(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;https://dnsimple.com/domains/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;domain&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;/check&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
  .headers(&lt;span class="co"&gt;Authorization&lt;/span&gt;: auth, &lt;span class="co"&gt;Accept&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)
  .get() (err, res, body) -&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The really interesting line in the code above is the .headers() line. We can set headers for the http request before calling .get(), allowing us to configure the Authorization and Accept headers! Now the last bit.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;switch res.statusCode
  &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;200&lt;/span&gt;
    msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Sorry, &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;domain&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; is not available.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;404&lt;/span&gt;
    msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Cybersquat that s***!&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;401&lt;/span&gt;
    msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;You need to authenticate by setting the DNSIMPLE_USERNAME &amp;amp; DNSIMPLE_PASSWORD environment variables&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="r"&gt;else&lt;/span&gt;
    msg.send &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Unable to process your request and we're not sure why :(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The response (res) object has a statusCode method on it which we can use to match http response codes. Based on the dnsimple api I was able to make a simple switch statement with the correct replies for each status code.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I hope this is helpful to some folks out there. I can&amp;#8217;t wait to see what other hubot scripts people write!&lt;/p&gt;
&lt;p&gt;Make sure to fork the &lt;a href="https://github.com/github/hubot-scripts"&gt;hubot-scripts&lt;/a&gt; repo, add your scripts, and do a pull request once you&amp;#8217;ve got them working. The gem whois and dnsimple scripts above have already been accepted into the hubot-scripts library!&lt;/p&gt;
&lt;p&gt;Enjoy :)&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
    <entry>
      <title>HipChat, hubot, and Me</title>
      <link href="http://theprogrammingbutler.com/blog/archives/2011/10/28/hipchat-hubot-and-me/" />
      <id>http://theprogrammingbutler.com/blog/archives/2011/10/28/hipchat-hubot-and-me/</id>
      <updated>2011-11-15T11:24:29-05:00</updated>
      <published>2011-10-28T14:00:00-04:00</published>
      
      <summary type="html">How you can give Siri her very own robot brother with some help from Heroku and HipChat.</summary>
      <content type="html">How you can give Siri her very own robot brother with some help from Heroku and HipChat.&lt;p&gt;Github released &lt;a href="https://github.com/github/hubot"&gt;hubot&lt;/a&gt; this week and geeks the world over have been transfixed by his awesomeness. He&amp;#8217;s the second robot butler to enter my life lately, &lt;a href="http://www.apple.com/iphone/features/siri.html"&gt;Siri&lt;/a&gt; being the first. Together these two fulfill my every wish (not quite) and are at my beck and call day and night (too true).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: for a slightly different take &lt;a href="http://martinciu.com/2011/11/deploying-hubot-to-heroku-like-a-boss.html"&gt;try these instructions by @martinciu&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;: to learn more about writing hubot scripts &lt;a href="http://jonmagic.com/blog/archives/2011/10/28/hubot-scripts-explained/"&gt;read this&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Getting Started&lt;/h3&gt;
&lt;p&gt;The first step is to head on over to the &lt;a href="https://github.com/github/hubot/downloads"&gt;hubot downloads&lt;/a&gt; to grab yourself a copy of the latest hubot tarball. Download it and then open your command line to your download folder. It looked something like this for me:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;cd Downloads
tar zxvf hubot-1.1.3.tar.gz
cd hubot&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Make sure you have node.js and npm installed. I used &lt;a href="http://mxcl.github.com/homebrew/"&gt;homebrew&lt;/a&gt; to accomplish this.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;brew install node
brew install npm&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then you can just run the hubot binary and it should install all the necessary packages and fire right up.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;bin/hubot&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you run into any issues at this point please consult the &lt;a href="https://github.com/github/hubot/issues"&gt;hubot Issues&lt;/a&gt; page on Github, because someone has probably already run into the issue.&lt;/p&gt;
&lt;h3&gt;Configuring Heroku and HipChat&lt;/h3&gt;
&lt;p&gt;First we need to initialize git for our hubot so he&amp;#8217;s actually stored in version control.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;git init .
git add .
git commit -m &amp;quot;spawning my first robot!&amp;quot;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Next we create a new instance on the &lt;a href="http://devcenter.heroku.com/articles/cedar"&gt;Heroku cedar stack&lt;/a&gt; (assuming you already are &lt;a href="http://devcenter.heroku.com/articles/quickstart"&gt;setup to use Heroku&lt;/a&gt;).&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;heroku create my_hubot_app_name --stack cedar&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then we need to setup hubot and Heroku to connect to our &lt;a href="http://hipchat.com"&gt;HipChat&lt;/a&gt; account.&lt;/p&gt;
&lt;p&gt;This requires creating the user in HipChat and then going to your account page in HipChat (https://mycompanyhere.hipchat.com/account/xmpp) to get some values that we&amp;#8217;ll need for configuring Heroku.&lt;/p&gt;
&lt;p&gt;You&amp;#8217;ll also need to go to the Group Admin in HipChat and the &lt;span class="caps"&gt;API&lt;/span&gt; tab to create an &lt;span class="caps"&gt;API&lt;/span&gt; Auth Token. Run the following commands replacing the values with the ones that match in the HipChat settings:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;heroku config:add HUBOT_HIPCHAT_JID=&amp;lt;Username&amp;gt;

heroku config:add HUBOT_HIPCHAT_NAME=&amp;lt;Room nickname&amp;gt;
# example: heroku config:add HUBOT_HIPCHAT_NAME=&amp;quot;Geoffrey Butler&amp;quot;

heroku config:add HUBOT_HIPCHAT_PASSWORD=&amp;lt;Password you created for hubots user&amp;gt;
heroku config:add HUBOT_HIPCHAT_TOKEN=&amp;lt;Token from Group Admin and API&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;We also need to add the RedisToGo addon. (Thanks to &lt;a href="http://profitably.com/"&gt;Graham Siener&lt;/a&gt; for pointing this out)&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;heroku addons:add redistogo:nano&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now that Heroku is configured we need to slightly modify our Procfile to use the right adapter and name. Mine looks like this:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;app: bin/hubot -a hipchat -n &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Geoffrey Butler&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Replace Geoffrey Butler with whatever you named the user in HipChat. This should exactly match the Room nickname we set above. Once you&amp;#8217;ve updated the Procfile and saved it we need to commit it with git.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;git add Procfile
git commit -m &amp;quot;updated Procfile to use hipchat adapter and hipchat room nickname&amp;quot;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3&gt;Deploying to Heroku&lt;/h3&gt;
&lt;p&gt;Now we should be ready to deploy.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;git push heroku master&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This step failed for me at first. I had to edit package.json and change the dependencies section to look like this:&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dependencies&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: {
  &lt;span class="ke"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;hubot&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.1.0&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="ke"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;hubot-scripts&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.1.0&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="ke"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;optparse&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.0.1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
}&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The latest version of hubot-scripts blows up on the Heroku Cedar stack unfortunately. So after this step I committed my changes one more time and deployed.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;git add package.json
git commit -m &amp;quot;changed dependencies&amp;quot;
git push heroku master&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Woot! It worked! Now that its deployed we just need to start it up.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;heroku ps:scale app=1&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Inside our HipChat rooms Geoffrey suddenly appeared and I was able to talk to him.&lt;/p&gt;
&lt;div class="multiline_code"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="iv"&gt;@geoffrey&lt;/span&gt; help
(thanks|thank you) - say thanks to your butler
&amp;lt;keyword&amp;gt; tweet - &lt;span class="co"&gt;Returns&lt;/span&gt; a link to a tweet about &amp;lt;keyword&amp;gt;
&amp;lt;user&amp;gt; is a badass guitarist - assign a role to a user
&amp;lt;user&amp;gt; is &lt;span class="r"&gt;not&lt;/span&gt; a badass guitarist - remove a role from a user
animate me &amp;lt;query&amp;gt;  - &lt;span class="co"&gt;The&lt;/span&gt; same thing as &lt;span class="sh"&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;span class="k"&gt;image me&lt;/span&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;/span&gt;, except adds a few
ascii me &amp;lt;text&amp;gt; - &lt;span class="co"&gt;Show&lt;/span&gt; text &lt;span class="r"&gt;in&lt;/span&gt; ascii art.
check domain &amp;lt;domainname&amp;gt; - returns whether a domain is available
convert me &amp;lt;expression&amp;gt; to &amp;lt;units&amp;gt; - &lt;span class="co"&gt;Convert&lt;/span&gt; expression to given units.
gem whois &amp;lt;gemname&amp;gt; - returns gem details &lt;span class="r"&gt;if&lt;/span&gt; it exists
haters - &lt;span class="co"&gt;Returns&lt;/span&gt; a random haters gonna hate url
help - &lt;span class="co"&gt;Displays&lt;/span&gt; all of the help commands that &lt;span class="co"&gt;Hubot&lt;/span&gt; knows about.
image me &amp;lt;query&amp;gt;    - &lt;span class="co"&gt;The&lt;/span&gt; &lt;span class="co"&gt;Original&lt;/span&gt;. &lt;span class="co"&gt;Queries&lt;/span&gt; &lt;span class="co"&gt;Google&lt;/span&gt; &lt;span class="co"&gt;Images&lt;/span&gt; &lt;span class="r"&gt;for&lt;/span&gt; &amp;lt;query&amp;gt; &lt;span class="r"&gt;and&lt;/span&gt;
map me &amp;lt;query&amp;gt; - &lt;span class="co"&gt;Returns&lt;/span&gt; a map view of the area returned by &lt;span class="sh"&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;`&lt;/span&gt;&lt;/span&gt;.
math me &amp;lt;expression&amp;gt; - &lt;span class="co"&gt;Calculate&lt;/span&gt; the given expression.
mustache me &amp;lt;query&amp;gt; - &lt;span class="co"&gt;Searches&lt;/span&gt; &lt;span class="co"&gt;Google&lt;/span&gt; &lt;span class="co"&gt;Images&lt;/span&gt; &lt;span class="r"&gt;for&lt;/span&gt; the specified query &lt;span class="r"&gt;and&lt;/span&gt;
mustache me &amp;lt;url&amp;gt;   - &lt;span class="co"&gt;Adds&lt;/span&gt; a mustache to the specified &lt;span class="co"&gt;URL&lt;/span&gt;.
remind me &lt;span class="r"&gt;in&lt;/span&gt; &amp;lt;time&amp;gt; to &amp;lt;action&amp;gt;    - &lt;span class="co"&gt;Set&lt;/span&gt; a reminder &lt;span class="r"&gt;in&lt;/span&gt; &amp;lt;time&amp;gt; to &lt;span class="r"&gt;do&lt;/span&gt; an &amp;lt;action&amp;gt;
ship it - &lt;span class="co"&gt;Display&lt;/span&gt; a motivation squirrel
show storage - &lt;span class="co"&gt;Display&lt;/span&gt; the contents that are persisted &lt;span class="r"&gt;in&lt;/span&gt; redis
show users - &lt;span class="co"&gt;Display&lt;/span&gt; all users that hubot knows about
translate me &amp;lt;phrase&amp;gt; - &lt;span class="co"&gt;Searches&lt;/span&gt; &lt;span class="r"&gt;for&lt;/span&gt; a translation &lt;span class="r"&gt;for&lt;/span&gt; the &amp;lt;phrase&amp;gt; &lt;span class="r"&gt;and&lt;/span&gt; &lt;span class="r"&gt;then&lt;/span&gt;
translate me from &amp;lt;source&amp;gt; into &amp;lt;target&amp;gt; &amp;lt;phrase&amp;gt; - &lt;span class="co"&gt;Translates&lt;/span&gt; &amp;lt;phrase&amp;gt; from &amp;lt;source&amp;gt; into &amp;lt;target&amp;gt;. &lt;span class="co"&gt;Both&lt;/span&gt; &amp;lt;source&amp;gt; &lt;span class="r"&gt;and&lt;/span&gt; &amp;lt;target&amp;gt; are optional
who is &amp;lt;user&amp;gt; - see what roles a user has
youtube me &amp;lt;query&amp;gt; - &lt;span class="co"&gt;Searches&lt;/span&gt; &lt;span class="co"&gt;YouTube&lt;/span&gt; &lt;span class="r"&gt;for&lt;/span&gt; the query &lt;span class="r"&gt;and&lt;/span&gt; returns the video&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Awesome! Enjoy :)&lt;/p&gt;</content>
      <author>
        <name>Jonathan Hoyt</name>
      </author>
    </entry>
  
</feed>
