<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>Terence Eden has a Blog &#187; dabr</title> <atom:link href="http://shkspr.mobi/blog/index.php/tag/dabr/feed/" rel="self" type="application/rss+xml" /><link>http://shkspr.mobi/blog</link> <description>Mobiles, Shakespeare, Politics, Usability.</description> <lastBuildDate>Mon, 06 Feb 2012 16:31:09 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>Dabr Helps Ai Weiwei!</title><link>http://shkspr.mobi/blog/index.php/2011/06/dabr-helps-ai-weiwei/</link> <comments>http://shkspr.mobi/blog/index.php/2011/06/dabr-helps-ai-weiwei/#comments</comments> <pubDate>Thu, 23 Jun 2011 09:38:02 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[/etc/]]></category> <category><![CDATA[ai weiwei]]></category> <category><![CDATA[china]]></category> <category><![CDATA[dabr]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=4212</guid> <description><![CDATA[I&#8217;ve written before about Dabr, the Twitter client I code for. Dabr helps people around the world and is used by some of Twitter&#8217;s most influential users. Today, I am pleased to announce that Chinese artist, political prisoner, and sower of porcelain sunflower seed, Ai Weiwei uses dabr! On last night&#8217;s Newsnight, as part of <a
href='http://shkspr.mobi/blog/index.php/2011/06/dabr-helps-ai-weiwei/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>I&#8217;ve written before about <a
href="http://code.google.com/p/dabr/">Dabr</a>, the Twitter client I code for.  Dabr helps people around the world and is used by some of <a
href="http://shkspr.mobi/blog/index.php/2011/03/dabr-dabr-everywhere/">Twitter&#8217;s most influential users</a>.</p><p>Today, I am pleased to announce that Chinese artist, political prisoner, and sower of porcelain sunflower seed, <strong><a
href="http://en.wikipedia.org/wiki/Ai_Weiwei">Ai Weiwei</a> uses dabr!</strong></p><p>On <a
href="http://www.bbc.co.uk/iplayer/episode/b0125h2m/Newsnight_22_06_2011/">last night&#8217;s Newsnight</a>, as part of a package on Ai Weiwei&#8217;s release, they showed him using Twitter.  Here&#8217;s a screenshot.<br
/><div
id="attachment_4213" class="wp-caption aligncenter" style="width: 310px"><a
href="http://shkspr.mobi/blog/wp-content/uploads/2011/06/ai-weiwei-dabr-screenshot-large.jpg"><img
src="http://shkspr.mobi/blog/wp-content/uploads/2011/06/ai-weiwei-dabr-screenshot-large-300x180.jpg" alt="ai weiwei dabr screenshot large" title="ai weiwei dabr screenshot large" width="300" height="180" class="size-medium wp-image-4213" /></a><p
class="wp-caption-text">Click for larger image</p></div><br
/> That&#8217;s Dabr! I&#8217;d recognise the orange colour scheme anywhere!  It looks like he&#8217;s using one of the many hundreds of installs of Dabr &#8211; this one looks like it has been localised to Chinese.</p><p>One interesting thing, none of the user&#8217;s avatars appear.  That&#8217;s because, at a guess, the images are retrieved from Twitter&#8217;s servers which are blocked by the <a
href="http://en.wikipedia.org/wiki/Golden_Shield_Project">Great Firewall of China</a>.</p><p>Indeed, if we zoom in on the text we can see the letters &#8220;GFW&#8221;.<br
/> <img
src="http://shkspr.mobi/blog/wp-content/uploads/2011/06/ai-weiwei-dabr-GFW.jpg" alt="ai weiwei dabr GFW" title="ai weiwei dabr GFW" width="271" height="153" class="aligncenter size-full wp-image-4214" /><br
/> My Mandarin is too rusty to translate the rest &#8211; can anyone else help?</p><p>So, looks like my next addition to Dabr will be to use an image proxy to ensure avatar images make it through China&#8217;s firewall!</p><p>Thanks to <a
href="http://twitter.com/Kristiansblog " class="broken_link">Kristian Carter</a> for alerting me.<br
/> <style type='text/css'>#bbpBox_83659275024601088 a { text-decoration:none; color:#0084B4; }#bbpBox_83659275024601088 a:hover { text-decoration:underline; }</style><div
id='bbpBox_83659275024601088' class='bbpBox' style='padding:20px; margin:5px 0; background-color:#C0DEED; background-image:url(http://a0.twimg.com/images/themes/theme1/bg.png); background-repeat:no-repeat'><div
style='background:#fff; padding:10px; margin:0; min-height:48px; color:#333333; -moz-border-radius:5px; -webkit-border-radius:5px;'><span
style='width:100%; font-size:18px; line-height:22px;'>Ai Weiwei uses @<a
href="http://twitter.com/intent/user?screen_name=dabr" class="twitter-action">dabr</a>! <a
href="http://twitter.com/search?q=%23Newsnight" title="#Newsnight">#Newsnight</a></span><div
class='bbp-actions' style='font-size:12px; width:100%; padding:5px 0; margin:0 0 10px 0; border-bottom:1px solid #e6e6e6;'><img
align='middle' src='http://shkspr.mobi/blog/wp-content/plugins/twitter-blackbird-pie//images/bird.png' /><a
title='tweeted on 22/06/2011 22:15' href='http://twitter.com/#!/Kristiansblog/status/83659275024601088' target='_blank'>22/06/2011 22:15</a> via <a
href="http://blackberry.com/twitter" rel="nofollow" target="blank">Twitter for BlackBerry®</a><a
href='https://twitter.com/intent/tweet?in_reply_to=83659275024601088&related=https://twitter.com/edent' class='bbp-action bbp-reply-action' title='Reply'><span><em
style='margin-left: 1em;'></em><strong>Reply</strong></span></a><a
href='https://twitter.com/intent/retweet?tweet_id=83659275024601088&related=https://twitter.com/edent' class='bbp-action bbp-retweet-action' title='Retweet'><span><em
style='margin-left: 1em;'></em><strong>Retweet</strong></span></a><a
href='https://twitter.com/intent/favorite?tweet_id=83659275024601088&related=https://twitter.com/edent' class='bbp-action bbp-favorite-action' title='Favorite'><span><em
style='margin-left: 1em;'></em><strong>Favorite</strong></span></a></div><div
style='float:left; padding:0; margin:0'><a
href='http://twitter.com/intent/user?screen_name=Kristiansblog'><img
style='width:48px; height:48px; padding-right:7px; border:none; background:none; margin:0' src='http://a0.twimg.com/profile_images/1365639000/IMG00805-20110514-2236__1__normal.jpg' /></a></div><div
style='float:left; padding:0; margin:0'><a
style='font-weight:bold' href='http://twitter.com/intent/user?screen_name=Kristiansblog'>@Kristiansblog</a><div
style='margin:0; padding-top:2px'>Kristian Carter</div></div><div
style='clear:both'></div></div></div></p><p>Awesome!</p><p><span
style="text-align:center; display: block;"><a
href="http://shkspr.mobi/blog/index.php/2011/06/dabr-helps-ai-weiwei/"><img
src="http://img.youtube.com/vi/AFdciadSMbk/2.jpg" alt="" /></a></span></p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=4212&amp;md5=73f34f7da225089ff0fc2830b991e61e" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2011/06/dabr-helps-ai-weiwei/feed/</wfw:commentRss> <slash:comments>2</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=4212&amp;md5=73f34f7da225089ff0fc2830b991e61e" type="text/html" /> </item> <item><title>Displaying Twitter Photos via Entities</title><link>http://shkspr.mobi/blog/index.php/2011/06/displaying-twitter-photos-via-entities/</link> <comments>http://shkspr.mobi/blog/index.php/2011/06/displaying-twitter-photos-via-entities/#comments</comments> <pubDate>Fri, 03 Jun 2011 15:43:19 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[api]]></category> <category><![CDATA[code]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[howto]]></category> <category><![CDATA[php]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=4150</guid> <description><![CDATA[Twitter has announced that it will soon open up a native photo sharing service. Rather than using an external service like Embed.ly to retrieve thumbnails, all the data is embedded within Twitter Entities. So, if you request a status using &#8220;include_entities=true&#8220;, you will be able to grab the image and display the thumbnail using the <a
href='http://shkspr.mobi/blog/index.php/2011/06/displaying-twitter-photos-via-entities/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>Twitter has announced that it will soon open up a <a
href="http://groups.google.com/group/twitter-development-talk/browse_thread/thread/99b451ce5d8259ce#">native photo sharing service</a>.</p><p>Rather than using an external service like Embed.ly to retrieve thumbnails, all the data is embedded within <a
href="http://dev.twitter.com/pages/tweet_entities">Twitter Entities</a>.</p><p>So, if you request a status using &#8220;<em>include_entities=true</em>&#8220;, you will be able to grab the image and display the thumbnail using the following code.</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1"><span
class="kw2">function</span> twitter_get_media<span
class="br0">&#40;</span><span
class="re1">$status</span><span
class="br0">&#41;</span> <span
class="br0">&#123;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp;<span
class="kw1">if</span><span
class="br0">&#40;</span><span
class="re1">$status</span><span
class="sy0">-&gt;</span><span
class="me1">entities</span><span
class="sy0">-&gt;</span><span
class="me1">media</span><span
class="br0">&#41;</span> <span
class="br0">&#123;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="re1">$url</span> <span
class="sy0">=</span> <span
class="re1">$status</span><span
class="sy0">-&gt;</span><span
class="me1">entities</span><span
class="sy0">-&gt;</span><span
class="me1">media</span><span
class="br0">&#91;</span><span
class="nu0">0</span><span
class="br0">&#93;</span><span
class="sy0">-&gt;</span><span
class="me1">media_url_https</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="re1">$width</span> <span
class="sy0">=</span> <span
class="re1">$status</span><span
class="sy0">-&gt;</span><span
class="me1">entities</span><span
class="sy0">-&gt;</span><span
class="me1">media</span><span
class="br0">&#91;</span><span
class="nu0">0</span><span
class="br0">&#93;</span><span
class="sy0">-&gt;</span><span
class="me1">sizes</span><span
class="sy0">-&gt;</span><span
class="me1">thumb</span><span
class="sy0">-&gt;</span><span
class="me1">w</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="re1">$height</span> <span
class="sy0">=</span> <span
class="re1">$status</span><span
class="sy0">-&gt;</span><span
class="me1">entities</span><span
class="sy0">-&gt;</span><span
class="me1">media</span><span
class="br0">&#91;</span><span
class="nu0">0</span><span
class="br0">&#93;</span><span
class="sy0">-&gt;</span><span
class="me1">sizes</span><span
class="sy0">-&gt;</span><span
class="me1">thumb</span><span
class="sy0">-&gt;</span><span
class="me1">h</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="re1">$media_html</span> <span
class="sy0">=</span> <span
class="st0">&quot;&lt;a href=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$url</span> <span
class="sy0">.</span> <span
class="st0">&quot;<span
class="es0">\&quot;</span> target=&#39;_blank&#39;&gt;&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="re1">$media_html</span> <span
class="sy0">.=</span> &nbsp;<span
class="st0">&quot;&lt;img src=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$url</span> <span
class="sy0">.</span> <span
class="st0">&quot;:thumb<span
class="es0">\&quot;</span> width=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$width</span> <span
class="sy0">.</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span
class="st0">&quot;<span
class="es0">\&quot;</span> height=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$height</span> <span
class="sy0">.</span> <span
class="st0">&quot;<span
class="es0">\&quot;</span> /&gt;&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="re1">$media_html</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;/a&gt;&lt;br /&gt;&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="kw1">return</span> <span
class="re1">$media_html</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp;<span
class="br0">&#125;</span> &nbsp; &nbsp; &nbsp; &nbsp;</div></li><li
class="li1"><div
class="de1"><span
class="br0">&#125;</span></div></li></ol></div><p>So, a tweet like this:<br
/> <style type='text/css'>#bbpBox_76360760606986241 a { text-decoration:none; color:#038543; }#bbpBox_76360760606986241 a:hover { text-decoration:underline; }</style><div
id='bbpBox_76360760606986241' class='bbpBox' style='padding:20px; margin:5px 0; background-color:#ACDED6; background-image:url(http://a1.twimg.com/images/themes/theme18/bg.gif); background-repeat:no-repeat'><div
style='background:#fff; padding:10px; margin:0; min-height:48px; color:#333333; -moz-border-radius:5px; -webkit-border-radius:5px;'><span
style='width:100%; font-size:18px; line-height:22px;'><a
href="http://twitter.com/search?q=%23Photos" title="#Photos">#Photos</a> on Twitter: taking flight <a
href="http://t.co/qbJx26r" rel="nofollow">http://t.co/qbJx26r</a></span><div
class='bbp-actions' style='font-size:12px; width:100%; padding:5px 0; margin:0 0 10px 0; border-bottom:1px solid #e6e6e6;'><img
align='middle' src='http://shkspr.mobi/blog/wp-content/plugins/twitter-blackbird-pie//images/bird.png' /><a
title='tweeted on 02/06/2011 18:53' href='http://twitter.com/#!/twitter/status/76360760606986241' target='_blank'>02/06/2011 18:53</a> via web<a
href='https://twitter.com/intent/tweet?in_reply_to=76360760606986241&related=https://twitter.com/edent' class='bbp-action bbp-reply-action' title='Reply'><span><em
style='margin-left: 1em;'></em><strong>Reply</strong></span></a><a
href='https://twitter.com/intent/retweet?tweet_id=76360760606986241&related=https://twitter.com/edent' class='bbp-action bbp-retweet-action' title='Retweet'><span><em
style='margin-left: 1em;'></em><strong>Retweet</strong></span></a><a
href='https://twitter.com/intent/favorite?tweet_id=76360760606986241&related=https://twitter.com/edent' class='bbp-action bbp-favorite-action' title='Favorite'><span><em
style='margin-left: 1em;'></em><strong>Favorite</strong></span></a></div><div
style='float:left; padding:0; margin:0'><a
href='http://twitter.com/intent/user?screen_name=twitter'><img
style='width:48px; height:48px; padding-right:7px; border:none; background:none; margin:0' src='http://a0.twimg.com/profile_images/1124040897/at-twitter_normal.png' /></a></div><div
style='float:left; padding:0; margin:0'><a
style='font-weight:bold' href='http://twitter.com/intent/user?screen_name=twitter'>@twitter</a><div
style='margin:0; padding-top:2px'>Twitter</div></div><div
style='clear:both'></div></div></div><br
/> Will render like this (in Dabr):<br
/> <img
src="http://shkspr.mobi/blog/wp-content/uploads/2011/06/Twitter-Dabr-Images.jpg" alt="Twitter Dabr Images" title="Twitter Dabr Images" width="317" height="528" class="aligncenter size-full wp-image-4154" /></p><h2>Notes</h2><p>This is very rough and ready proof of concept code.  Beware of the following:</p><ul><li>This will only take the first image from the tweet.</li><li>Only images are supported &#8211; I&#8217;m not sure how their proposed video sharing will work.</li><li>There&#8217;s no error checking.</li><li>In the above code, the https URL is used &#8211; if you want a non-SSL link, you&#8217;ll need to remove the &#8220;_https&#8221;</li></ul><p>Enjoy!</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=4150&amp;md5=3e6ea664f76da8468cb1d87dd54edddd" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2011/06/displaying-twitter-photos-via-entities/feed/</wfw:commentRss> <slash:comments>3</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=4150&amp;md5=3e6ea664f76da8468cb1d87dd54edddd" type="text/html" /> </item> <item><title>Dabr, Dabr, Everywhere&#8230;</title><link>http://shkspr.mobi/blog/index.php/2011/03/dabr-dabr-everywhere/</link> <comments>http://shkspr.mobi/blog/index.php/2011/03/dabr-dabr-everywhere/#comments</comments> <pubDate>Fri, 25 Mar 2011 11:30:35 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=3763</guid> <description><![CDATA[I contribute code to Dabr &#8211; a mobile twitter client. It&#8217;s a great project to keep my hand in the world of PHP, APIs, SVN, and all the other tools that are essential to the modern online world. Dabr&#8217;s strength for developers is two-fold Dead easy to install. Unzip the files, fill in your API <a
href='http://shkspr.mobi/blog/index.php/2011/03/dabr-dabr-everywhere/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>I contribute code to<a
href="http://code.google.com/p/dabr/"> Dabr &#8211; a mobile twitter client</a>.  It&#8217;s a great project to keep my hand in the world of PHP, APIs, SVN, and all the other tools that are essential to the modern online world.</p><p>Dabr&#8217;s strength for developers is two-fold</p><ol><li>Dead easy to install.  Unzip the files, fill in your API key(s), upload, done.</li><li>It&#8217;s under an incredibly permissive Open Source <a
href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>. Essentially anyone can do anything with the code and they don&#8217;t need to ask permission, nor contribute anything back to the code base.</li></ol><p>It&#8217;s a really popular tool.  Although it&#8217;s hard to count how many users are on the main Dabr server &#8211; not to mention all the clones &#8211; it&#8217;s obvious that many people find it an indispensable way to access Twitter.</p><p>According to the New York Times, <a
href="http://6thfloor.blogs.nytimes.com/2011/03/24/a-better-way-to-measure-twitter-influence/">Rafinha Bastos is the most influential person on Twitter</a>.  Guess what client he uses?<br
/> <img
src="https://shkspr.mobi/blog/wp-content/uploads/2011/03/rafinhabastos-uses-Dabr.jpg" alt="rafinhabastos uses Dabr" title="rafinhabastos uses Dabr" width="345" height="769" class="aligncenter size-full wp-image-3772" /><br
/> <span
id="more-3763"></span><br
/> So, with a kick-arse product and no silly &#8220;Intellectual Property&#8221; restrictions, we have let a thousand flowers bloom. There are clients deployed all over the world.  Including on my secure server &#8211; <a
href="https://shkspr.mobi/dabr/">SSL Dabr</a>.  And here&#8217;s one more&#8230;</p><h2>Welcome UberSocial!</h2><p>The most recent flower is <a
href="http://www.ubersocial.com/">UberSocial</a>. As well as having the most popular BlackBerry Twitter client, and an iPhone client &#8211; they&#8217;ve now beta-launched a <a
href="http://m.ubersocial.com/">mobile web client</a> &#8211; based on Dabr!</p><p><img
class="alignleft size-full wp-image-3764" title="munch_2011_03_24_153355" src="https://shkspr.mobi/blog/wp-content/uploads/2011/03/munch_2011_03_24_153355.jpg" alt="UberSocial Dabr" width="252" height="336" /><img
class="alignright size-full wp-image-3765" title="munch_2011_03_24_153106" src="https://shkspr.mobi/blog/wp-content/uploads/2011/03/munch_2011_03_24_153106.jpg" alt="UberSocial Dabr" width="252" height="336" /></p><div
style="clear: both"> It looks like UberSocial are running a slightly out of date version of the code &#8211; but I&#8217;m sure they&#8217;ll be up to the latest version shortly.</div><p>I&#8217;m really excited to see Dabr spreading far and wide.  The intention &#8211; for me &#8211; has never been to make pots of money from it.  The adverts on <a
href="https://shkspr.mobi/dabr/">SSL Dabr</a> just about cover the hosting costs.</p><p>What I like seeing is my code being used far and wide &#8211; and helping people.  I know it&#8217;s corny, but seeing my code being used by Twitter users in Egypt during the uprising was overwhelming.  In a tiny, almost insignificant way, I helped.</p><p>I don&#8217;t think my coding is good enough to get something into a really important project &#8211; like <a
href="http://www.kernel.org/">the Linux Kernel</a>, or <a
href="http://spaceflight.nasa.gov/station/index.html">the International Space Station</a> &#8211; but seeing millions of users is personally edifying.</p><p>So, long live Open Source and long live Dabr!</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=3763&amp;md5=a6a1f23d03ea9dbcd1146658c9243d99" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2011/03/dabr-dabr-everywhere/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=3763&amp;md5=a6a1f23d03ea9dbcd1146658c9243d99" type="text/html" /> </item> <item><title>Getting Images from a Foursquare Checkin</title><link>http://shkspr.mobi/blog/index.php/2011/03/getting-images-from-a-foursquare-checkin/</link> <comments>http://shkspr.mobi/blog/index.php/2011/03/getting-images-from-a-foursquare-checkin/#comments</comments> <pubDate>Tue, 15 Mar 2011 12:35:22 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[/etc/]]></category> <category><![CDATA[4SQ]]></category> <category><![CDATA[api]]></category> <category><![CDATA[bit.ly]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[FOURSQUARE]]></category> <category><![CDATA[programming]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=3749</guid> <description><![CDATA[&#8220;Oi!&#8221; shouted Whatleydude, &#8220;Get Dabr to show images from foursquare checkins!&#8221; &#8220;Righty-ho sir!&#8221; I said. I started coding furiously. Of course, things are never quite as simple as I first thought&#8230;. So, how do we go from http://4sq.com/fgIWov to ? 1 Expand the URL Get your Bit.ly API Key. http://api.bitly.com/v3/expand ?shortUrl=http://4sq.com/fgIWov &#038;login=YOUR_BIT_LY_USERNAME &#038;apiKey=YOUR_BIT_LY_API_KEY &#038;format=txt You <a
href='http://shkspr.mobi/blog/index.php/2011/03/getting-images-from-a-foursquare-checkin/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>&#8220;Oi!&#8221; shouted <a
href="http://whatleydude.com/">Whatleydude</a>, &#8220;Get Dabr to show images from foursquare checkins!&#8221;<br
/> &#8220;Righty-ho sir!&#8221; I said.  I started coding furiously.  Of course, things are never quite as simple as I first thought&#8230;.</p><p>So, how do we go from <a
href="http://4sq.com/fgIWov">http://4sq.com/fgIWov</a><br
/> to<br
/> <img
src="http://playfoursquare.s3.amazonaws.com/derived_pix/NYI1TUY5OOMV53BB4QGK2JUBDYTR20QA13W4VTHM1U4XSAPB_300x300.jpg" alt="James' Foursquare Checkin Image" />?</p><h2>1 Expand the URL</h2><p>Get your <a
href="http://bit.ly/a/your_api_key/">Bit.ly API Key</a>.</p><pre>

http://api.bitly.com/v3/expand

   ?shortUrl=http://4sq.com/fgIWov
   &#038;login=YOUR_BIT_LY_USERNAME
   &#038;apiKey=YOUR_BIT_LY_API_KEY
   &#038;format=txt
</pre><p>You can, if you prefer, get the info back in JSON or XML. See the <a
href="http://code.google.com/p/bitly-api/wiki/ApiDocumentation#/v3/expand">Bit.ly API Expand Documentation</a>.</p><h2>2 The Foursquare URL</h2><p>Bit.ly gives us the URL which includes a checkin ID and a signature.</p><pre>

http://foursquare.com/edent/checkin/4d7e5b4f9df3f04d7400c394

   ?s=afH3jJg3L9HpLqVIwiqp-YpNL5k
</pre><h2>3 The Foursquare API Call</h2><p>From this, we construct an API call to Foursquare.  It looks like this</p><pre>

https://api.foursquare.com/v2/checkins/4d7e5b4f9df3f04d7400c394

   ?signature=afH3jJg3L9HpLqVIwiqp-YpNL5k
   &#038;oauth_token=YOUR_FOURSQUARE_OAUTH_TOKEN
</pre><p><strong>NOTE</strong> the Foursquare URL says <em>?s=</em> whereas the API call requires <em>?signature=</em><br
/> That caused me more frustration than it should&#8230;</p><p>Getting your OAuth token is a little cumbersome &#8211; follow the steps at the <a
href="http://developer.foursquare.com/docs/oauth.html">Foursquare Developers site</a>.</p><h2>4 The JSON Response</h2><p>I&#8217;ll cut the cruft out of here, so you only see what you need to display images.<br
/> The response gives us the link to the full sized image &#8211; as well as several different sizes should you wish to display thumbnails.</p><div
class="geshi no json"><ol><li
class="li1"><div
class="de1">{</div></li><li
class="li1"><div
class="de1">&nbsp; &quot;meta&quot;:{</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp;&quot;code&quot;:200</div></li><li
class="li1"><div
class="de1">&nbsp; },</div></li><li
class="li1"><div
class="de1">&nbsp; &quot;response&quot;:{</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp;&quot;checkin&quot;:{</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; },</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp;&#8230;</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp;&quot;photos&quot;:{</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &quot;count&quot;:1,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &quot;items&quot;:[</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;id&quot;:&quot;4d7e5b4f9df3f04d7400c394&quot;,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;createdAt&quot;:1300184596,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;url&quot;:&quot;http://playfoursquare.s3.amazonaws.com/pix/A.jpg&quot;,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;sizes&quot;:{</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;count&quot;:4,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;items&quot;:[</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;url&quot;:&quot;http://playfoursquare.s3.amazonaws.com/pix/B.jpg&quot;,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;width&quot;:720,&quot;height&quot;:540</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;url&quot;:&quot;http://playfoursquare.s3.amazonaws.com/derived_pix/C.jpg&quot;,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;width&quot;:300,&quot;height&quot;:300</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;url&quot;:&quot;http://playfoursquare.s3.amazonaws.com/derived_pix/D.jpg&quot;,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;width&quot;:100,&quot;height&quot;:100</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;url&quot;:&quot;http://playfoursquare.s3.amazonaws.com/derived_pix/E.jpg&quot;,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;width&quot;:36,</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;height&quot;:36</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;]</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },</div></li></ol></div><h2>5 Gotchas</h2><p>Again, nothing in life is easy.  Not all foursquare checkins have an image associated with them.  In which case, we can do one of three things.</p><ol><li>Display no image</li><li>Display the user&#8217;s avatar &#8211; if it&#8217;s public</li><li>Display an image of the venue &#8211; or one of the icons associated with it.</li></ol><h2>6 Embed.ly</h2><p>Dabr uses the <a
href="http://embed.ly/">awesome Embedly service</a>.  Rather than having hundreds of different regular expressions and API calls to get embedded images, Embed.ly gives us a single end point to call.<br
/> So, rather than rewrite huge chunks of Dabr&#8217;s code, I&#8217;ve submitted this to the clever-clogs behind Embed.ly &#8211; that way, everyone can benefit.</p><p>Any questions, comments, or clarifications &#8211; please let me know in the comments box.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=3749&amp;md5=8814e78d3d7a091ede6c32915214bf4e" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2011/03/getting-images-from-a-foursquare-checkin/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=3749&amp;md5=8814e78d3d7a091ede6c32915214bf4e" type="text/html" /> </item> <item><title>Twitter API &#8211; pagination and IDs</title><link>http://shkspr.mobi/blog/index.php/2010/06/twitter-api-pagination-and-ids/</link> <comments>http://shkspr.mobi/blog/index.php/2010/06/twitter-api-pagination-and-ids/#comments</comments> <pubDate>Sun, 27 Jun 2010 07:54:36 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[/etc/]]></category> <category><![CDATA[api]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=2121</guid> <description><![CDATA[Looking for some Twitter API help.  Bit of a geeky post, this&#8230; Pagination is the act of splitting data into logical  pages. Suppose I had a list of item, numbered 0 &#8211; 99.  If I want 20 items per page, it&#8217;s trivial to see that pagination looks like: p1 = 0-19 p2 = 20-40 p3 <a
href='http://shkspr.mobi/blog/index.php/2010/06/twitter-api-pagination-and-ids/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>Looking for some Twitter API help.  Bit of a geeky post, this&#8230;</p><p>Pagination is the act of splitting data into logical  pages. Suppose I had a list of item, numbered 0 &#8211; 99.  If I want 20 items per page, it&#8217;s trivial to see that pagination looks like:</p><pre>p1 = 0-19
p2 = 20-40
p3 = 41-61
p4 = 62-82
p5 = 83-99
</pre><p>If I wanted to start at, say, page 55 &#8211; pagination would look like:</p><pre>p1 = 55-75
p2 = 76-96
p3 = 97-99</pre><p>Easy, right?  So why am I telling you this?</p><h2>Twitter Timeline</h2><p>Imagine that those items are Twitter Status ID.  Each one represents a tweet in your timeline.</p><p>Twitter will allow us to &#8220;page&#8221; back and forth through our timeline. If we say status ID 80 is the most recent post in our timeline, and we want to see 20 tweets at a time, pagination would look like this.</p><pre>p1 = 80-60
p2 = 60-40
... etc.</pre><p>Normally, that would be fine.</p><p>The only issue is that friends are posting <em>all the time</em>.  Imagine we start with tweets 80-60.  We go to page 2, but in the meantime, 5 new tweets have been made.</p><pre>p1 = 80-60
p2 = 65-45</pre><p>The user sees 5 tweets she has already read.  Not desirable.</p><p>If 20 tweets had been made before clicking on the &#8220;next&#8221; button, this is what happens.</p><pre>p1 = 80-60
p2 = 80-60</pre><h2>Max_ID To The Rescue (AKA, the easy bit)</h2><p>Luckily, Twitter allows us to use a max_id parameter in our API calls.  This says &#8220;Get the tweets <strong>older</strong> than this number.&#8221;</p><pre>http://api.twitter.com/1/statuses/home_timeline.json?max_id=123465789</pre><p>So, using max_id we can ensure that the user never has to read the same tweet twice.  Instead of dumbly using pages, we call the specific tweets we want.</p><pre><span style="text-decoration: line-through;">p1</span> max_id=80 = 80-60</pre><pre><span style="text-decoration: line-through;">p2</span> max_id=60 = 60-40</pre><p>Easy!  We just use the oldest tweet on the page as the max_id parameter when we call the next page.</p><h2>Looking To The Future (AKA, where it all goes horribly wrong)</h2><p>So far, we&#8217;ve looked at stepping back in time.  Seeing older tweets.  Suppose we want to see newer tweets?</p><p>Twitter provides us with a since_id parameter for API calls.  This says &#8220;Get the tweets <strong>newer</strong> than this number.&#8221;</p><p>Unfortunately, it doesn&#8217;t work.  Well, it <em>works</em> but not the way I expected it to!</p><p>Suppose our user is deep down in her tweets, this is how I would expect since_id to work</p><pre>max_id=60  = 60-40</pre><pre> (So, let's show any more recent tweets)</pre><pre>since_id=60 = 80-60</pre><p>We see the 20 tweets that occured <em>since</em> the since_id.  Right?  Wrong!  This is what happens?</p><pre>max_id=60  = 60-40</pre><pre>(So, let's show any more recent tweets)</pre><pre>since_id=60 = 100-80</pre><p><strong>What?</strong></p><h2>An Explanation</h2><p>The since_id retrieves tweets <em>starting with the most recent</em>.  It stops when it reaches the since_id.</p><p>I don&#8217;t know the max_id that I&#8217;m looking for, so I can&#8217;t call that.</p><p>I could call the most recent 200 tweets and look for the 20 I need.  That&#8217;s wasteful in terms of bandwidth and processing &#8211; there&#8217;s also no guarantee that the since_id will be in there.</p><p>So, I have a problem.  The &#8220;Older&#8221; link in my Twitter application will work.  The &#8220;Newer&#8221; links won&#8217;t.</p><p>Any suggestions?</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=2121&amp;md5=93574a165e925710efeff37e057cc2ac" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/06/twitter-api-pagination-and-ids/feed/</wfw:commentRss> <slash:comments>8</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=2121&amp;md5=93574a165e925710efeff37e057cc2ac" type="text/html" /> </item> <item><title>HOWTO: Twitpic and OAuth</title><link>http://shkspr.mobi/blog/index.php/2010/05/howto-twitpic-and-oauth/</link> <comments>http://shkspr.mobi/blog/index.php/2010/05/howto-twitpic-and-oauth/#comments</comments> <pubDate>Mon, 31 May 2010 17:07:29 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[/etc/]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[howto]]></category> <category><![CDATA[oauth]]></category> <category><![CDATA[php]]></category> <category><![CDATA[twitpic]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=2084</guid> <description><![CDATA[I am no longer confused! Here is a quick tutorial in how to post images to Twitpic and Twitter when using OAuth. I&#8217;m indebted to Steve Corona of Twitpic, for his help with this. You can see the full code on Dabr&#8217;s Google Code page. First of all, you&#8217;ll need to have enabled OAuth for <a
href='http://shkspr.mobi/blog/index.php/2010/05/howto-twitpic-and-oauth/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>I am no longer <a
href="http://shkspr.mobi/blog/index.php/2010/05/twitpic-oauth-im-stuck">confused</a>!  Here is a quick tutorial in how to post images to Twitpic and Twitter when using OAuth.  I&#8217;m indebted to <a
href="http://twitter.com/stevencorona">Steve Corona of Twitpic</a>, for his help with this.</p><p>You can see the full code on <a
href="http://code.google.com/p/dabr/source/detail?r=318">Dabr&#8217;s Google Code page</a>.</p><p>First of all, you&#8217;ll need to have enabled OAuth for your Twitter client.  I use Abraham&#8217;s excellent <a
href="http://github.com/abraham/twitteroauth/tree/master/twitteroauth/">OAuth libraries for PHP</a>.</p><p>This tutorial assumes you already have OAuth working.  I&#8217;ll attempt to explain what I&#8217;m doing as I go along &#8211; but the code should be pretty readable.</p><p>Start by reading the <a
href="http://dev.twitpic.com/docs/2/upload/">Twitpic API documentation</a>.  You will also need to <a
href="http://dev.twitpic.com/apps/new">register for an API key</a> &#8211; this only takes a few seconds.</p><p>We start by setting CURL&#8217;s headers to those required by Twitpic</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1"><span
class="co1">//Has the user submitted an image and message?</span></div></li><li
class="li1"><div
class="de1"><span
class="kw1">if</span> <span
class="br0">&#40;</span><span
class="re1">$_POST</span><span
class="br0">&#91;</span><span
class="st0">&#39;message&#39;</span><span
class="br0">&#93;</span><span
class="br0">&#41;</span></div></li><li
class="li1"><div
class="de1"><span
class="br0">&#123;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$twitpicURL</span> <span
class="sy0">=</span> <span
class="st0">&#39;http://api.twitpic.com/2/upload.json&#39;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//Set the initial headers</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span> <span
class="sy0">=</span> <span
class="kw3">array</span><span
class="br0">&#40;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span
class="st0">&#39;X-Auth-Service-Provider: https://api.twitter.com/1/account/verify_credentials.json&#39;</span><span
class="sy0">,</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span
class="st0">&#39;X-Verify-Credentials-Authorization: OAuth realm=&quot;http://api.twitter.com/&quot;&#39;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="br0">&#41;</span><span
class="sy0">;</span></div></li></ol></div><p>Next, we create the OAuth credentials that we need.  Essentially, we&#8217;re signing a URL request. We then pass that on to Twitpic and they verify it with Twitter.  We <em>never</em> pass our OAUTH_CONSUMER_SECRET &#8211; so Twitpic can&#8217;t impersonate us.</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//Using Abraham&#39;s OAuth library</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="kw1">require_once</span><span
class="br0">&#40;</span><span
class="st0">&#39;OAuth.php&#39;</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">// instantiating OAuth customer </span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$consumer</span> <span
class="sy0">=</span> <span
class="kw2">new</span> OAuthConsumer<span
class="br0">&#40;</span>OAUTH_CONSUMER_KEY<span
class="sy0">,</span> OAUTH_CONSUMER_SECRET<span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">// instantiating signer</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$sha1_method</span> <span
class="sy0">=</span> <span
class="kw2">new</span> OAuthSignatureMethod_HMAC_SHA1<span
class="br0">&#40;</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">// user&#39;s token</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="kw3">list</span><span
class="br0">&#40;</span><span
class="re1">$oauth_token</span><span
class="sy0">,</span> <span
class="re1">$oauth_token_secret</span><span
class="br0">&#41;</span> <span
class="sy0">=</span> <span
class="kw3">explode</span><span
class="br0">&#40;</span><span
class="st0">&#39;|&#39;</span><span
class="sy0">,</span> <span
class="re1">$GLOBALS</span><span
class="br0">&#91;</span><span
class="st0">&#39;user&#39;</span><span
class="br0">&#93;</span><span
class="br0">&#91;</span><span
class="st0">&#39;password&#39;</span><span
class="br0">&#93;</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$token</span> <span
class="sy0">=</span> <span
class="kw2">new</span> OAuthConsumer<span
class="br0">&#40;</span><span
class="re1">$oauth_token</span><span
class="sy0">,</span> <span
class="re1">$oauth_token_secret</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">// Generate all the OAuth parameters needed</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$signingURL</span> <span
class="sy0">=</span> <span
class="st0">&#39;https://api.twitter.com/1/account/verify_credentials.json&#39;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$request</span> <span
class="sy0">=</span> OAuthRequest<span
class="sy0">::</span><span
class="me2">from_consumer_and_token</span><span
class="br0">&#40;</span><span
class="re1">$consumer</span><span
class="sy0">,</span> <span
class="re1">$token</span><span
class="sy0">,</span> <span
class="st0">&#39;GET&#39;</span><span
class="sy0">,</span> <span
class="re1">$signingURL</span><span
class="sy0">,</span> <span
class="kw3">array</span><span
class="br0">&#40;</span><span
class="br0">&#41;</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">sign_request</span><span
class="br0">&#40;</span><span
class="re1">$sha1_method</span><span
class="sy0">,</span> <span
class="re1">$consumer</span><span
class="sy0">,</span> <span
class="re1">$token</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li></ol></div><p>We add these generated credentials into the header.</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span><span
class="br0">&#91;</span><span
class="nu0">1</span><span
class="br0">&#93;</span> <span
class="sy0">.=</span> <span
class="st0">&quot;, oauth_consumer_key=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">get_parameter</span><span
class="br0">&#40;</span><span
class="st0">&#39;oauth_consumer_key&#39;</span><span
class="br0">&#41;</span> <span
class="sy0">.</span><span
class="st0">&quot;<span
class="es0">\&quot;</span>&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span><span
class="br0">&#91;</span><span
class="nu0">1</span><span
class="br0">&#93;</span> <span
class="sy0">.=</span> <span
class="st0">&quot;, oauth_signature_method=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">get_parameter</span><span
class="br0">&#40;</span><span
class="st0">&#39;oauth_signature_method&#39;</span><span
class="br0">&#41;</span> <span
class="sy0">.</span><span
class="st0">&quot;<span
class="es0">\&quot;</span>&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span><span
class="br0">&#91;</span><span
class="nu0">1</span><span
class="br0">&#93;</span> <span
class="sy0">.=</span> <span
class="st0">&quot;, oauth_token=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">get_parameter</span><span
class="br0">&#40;</span><span
class="st0">&#39;oauth_token&#39;</span><span
class="br0">&#41;</span> <span
class="sy0">.</span><span
class="st0">&quot;<span
class="es0">\&quot;</span>&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span><span
class="br0">&#91;</span><span
class="nu0">1</span><span
class="br0">&#93;</span> <span
class="sy0">.=</span> <span
class="st0">&quot;, oauth_timestamp=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">get_parameter</span><span
class="br0">&#40;</span><span
class="st0">&#39;oauth_timestamp&#39;</span><span
class="br0">&#41;</span> <span
class="sy0">.</span><span
class="st0">&quot;<span
class="es0">\&quot;</span>&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span><span
class="br0">&#91;</span><span
class="nu0">1</span><span
class="br0">&#93;</span> <span
class="sy0">.=</span> <span
class="st0">&quot;, oauth_nonce=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">get_parameter</span><span
class="br0">&#40;</span><span
class="st0">&#39;oauth_nonce&#39;</span><span
class="br0">&#41;</span> <span
class="sy0">.</span><span
class="st0">&quot;<span
class="es0">\&quot;</span>&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span><span
class="br0">&#91;</span><span
class="nu0">1</span><span
class="br0">&#93;</span> <span
class="sy0">.=</span> <span
class="st0">&quot;, oauth_version=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">get_parameter</span><span
class="br0">&#40;</span><span
class="st0">&#39;oauth_version&#39;</span><span
class="br0">&#41;</span> <span
class="sy0">.</span><span
class="st0">&quot;<span
class="es0">\&quot;</span>&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$header</span><span
class="br0">&#91;</span><span
class="nu0">1</span><span
class="br0">&#93;</span> <span
class="sy0">.=</span> <span
class="st0">&quot;, oauth_signature=<span
class="es0">\&quot;</span>&quot;</span> <span
class="sy0">.</span> <span
class="kw3">urlencode</span><span
class="br0">&#40;</span><span
class="re1">$request</span><span
class="sy0">-&gt;</span><span
class="me1">get_parameter</span><span
class="br0">&#40;</span><span
class="st0">&#39;oauth_signature&#39;</span><span
class="br0">&#41;</span><span
class="br0">&#41;</span> <span
class="sy0">.</span><span
class="st0">&quot;<span
class="es0">\&quot;</span>&quot;</span><span
class="sy0">;</span></div></li></ol></div><p>Add everything into CURL</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//open connection</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$ch</span> <span
class="sy0">=</span> curl_init<span
class="br0">&#40;</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//Set paramaters</span></div></li><li
class="li1"><div
class="de1">&nbsp;curl_setopt<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="sy0">,</span> CURLOPT_HTTPHEADER<span
class="sy0">,</span> <span
class="re1">$header</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;curl_setopt<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="sy0">,</span> CURLOPT_RETURNTRANSFER<span
class="sy0">,</span> <span
class="kw2">TRUE</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;curl_setopt<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="sy0">,</span> CURLOPT_SSL_VERIFYPEER<span
class="sy0">,</span> <span
class="nu0">0</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//set the url, number of POST vars, POST data</span></div></li><li
class="li1"><div
class="de1">&nbsp;curl_setopt<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="sy0">,</span>CURLOPT_URL<span
class="sy0">,</span><span
class="re1">$twitpicURL</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li></ol></div><p>The data we send to Twitpic (message text, image and key) have to go via POST.</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//TwitPic requires the data to be sent as POST</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$media_data</span> <span
class="sy0">=</span> <span
class="kw3">array</span><span
class="br0">&#40;</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span
class="st0">&#39;media&#39;</span> <span
class="sy0">=&gt;</span> <span
class="st0">&#39;@&#39;</span><span
class="sy0">.</span><span
class="re1">$_FILES</span><span
class="br0">&#91;</span><span
class="st0">&#39;media&#39;</span><span
class="br0">&#93;</span><span
class="br0">&#91;</span><span
class="st0">&#39;tmp_name&#39;</span><span
class="br0">&#93;</span><span
class="sy0">,</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span
class="st0">&#39;message&#39;</span> <span
class="sy0">=&gt;</span> <span
class="st0">&#39; &#39;</span> <span
class="sy0">.</span> <span
class="kw3">stripslashes</span><span
class="br0">&#40;</span><span
class="re1">$_POST</span><span
class="br0">&#91;</span><span
class="st0">&#39;message&#39;</span><span
class="br0">&#93;</span><span
class="br0">&#41;</span><span
class="sy0">,</span> <span
class="co1">//A space is needed because twitpic b0rks if first char is an @</span></div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span
class="st0">&#39;key&#39;</span><span
class="sy0">=&gt;</span>TWITPIC_API_KEY</div></li><li
class="li1"><div
class="de1">&nbsp; &nbsp; &nbsp; <span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;curl_setopt<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="sy0">,</span> CURLOPT_POST<span
class="sy0">,</span> <span
class="kw2">true</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;curl_setopt<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="sy0">,</span>CURLOPT_POSTFIELDS<span
class="sy0">,</span><span
class="re1">$media_data</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li></ol></div><p>All done, we now send the data to Twitpic.</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//execute post</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$result</span> <span
class="sy0">=</span> curl_exec<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="re1">$response_info</span><span
class="sy0">=</span>curl_getinfo<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="co1">//close connection</span></div></li><li
class="li1"><div
class="de1">&nbsp;curl_close<span
class="br0">&#40;</span><span
class="re1">$ch</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li></ol></div><p>If this has worked, Twitpic will pass back the URL of the image we posted.  We then need to post the entire message to Twitter ourselves (Twitpic can&#8217;t do it for us).</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp;<span
class="kw1">if</span> <span
class="br0">&#40;</span><span
class="re1">$response_info</span><span
class="br0">&#91;</span><span
class="st0">&#39;http_code&#39;</span><span
class="br0">&#93;</span> <span
class="sy0">==</span> <span
class="nu0">200</span><span
class="br0">&#41;</span> <span
class="co1">//Success</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="br0">&#123;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="co1">//Decode the response</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$json</span> <span
class="sy0">=</span> json_decode<span
class="br0">&#40;</span><span
class="re1">$result</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$id</span> <span
class="sy0">=</span> <span
class="re1">$json</span><span
class="sy0">-&gt;</span><span
class="me1">id</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$twitpicURL</span> <span
class="sy0">=</span> <span
class="re1">$json</span><span
class="sy0">-&gt;</span><span
class="me1">url</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$text</span> <span
class="sy0">=</span> <span
class="re1">$json</span><span
class="sy0">-&gt;</span><span
class="me1">text</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$message</span> <span
class="sy0">=</span> <span
class="kw3">trim</span><span
class="br0">&#40;</span><span
class="re1">$text</span><span
class="br0">&#41;</span> <span
class="sy0">.</span> <span
class="st0">&quot; &quot;</span> <span
class="sy0">.</span> <span
class="re1">$twitpicURL</span><span
class="sy0">;</span></div></li></ol></div><p>This next part is specific to Dabr &#8211; your client may post things differently.</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp; <span
class="co1">//Send the user&#39;s message to twitter</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$request</span> <span
class="sy0">=</span> API_URL<span
class="sy0">.</span><span
class="st0">&#39;statuses/update.json&#39;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$post_data</span> <span
class="sy0">=</span> <span
class="kw3">array</span><span
class="br0">&#40;</span><span
class="st0">&#39;source&#39;</span> <span
class="sy0">=&gt;</span> <span
class="st0">&#39;dabr&#39;</span><span
class="sy0">,</span> <span
class="st0">&#39;status&#39;</span> <span
class="sy0">=&gt;</span> <span
class="re1">$message</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$status</span> <span
class="sy0">=</span> twitter_process<span
class="br0">&#40;</span><span
class="re1">$request</span><span
class="sy0">,</span> <span
class="re1">$post_data</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;</div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="co1">//Back to the timeline</span></div></li><li
class="li1"><div
class="de1">&nbsp; twitter_refresh<span
class="br0">&#40;</span><span
class="st0">&quot;twitpic/confirm/$id&quot;</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="br0">&#125;</span></div></li></ol></div><p>If it didn&#8217;t work, Twitpic will tell us why.</p><div
class="geshi no php"><ol><li
class="li1"><div
class="de1">&nbsp;<span
class="kw1">else</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="br0">&#123;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">=</span> <span
class="st0">&quot;&lt;p&gt;Twitpic upload failed. No idea why!&lt;/p&gt;&quot;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$json</span> <span
class="sy0">=</span> json_decode<span
class="br0">&#40;</span><span
class="re1">$result</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;br / /&gt;&lt;b&gt;message&lt;/b&gt; &quot;</span> <span
class="sy0">.</span> <span
class="kw3">urlencode</span><span
class="br0">&#40;</span><span
class="re1">$_POST</span><span
class="br0">&#91;</span><span
class="st0">&#39;message&#39;</span><span
class="br0">&#93;</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;br / /&gt;&lt;b&gt;json&lt;/b&gt; &quot;</span> <span
class="sy0">.</span> <span
class="kw3">print_r</span><span
class="br0">&#40;</span><span
class="re1">$json</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;br / /&gt;&lt;b&gt;Response&lt;/b&gt; &quot;</span> <span
class="sy0">.</span> <span
class="kw3">print_r</span><span
class="br0">&#40;</span><span
class="re1">$response_info</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;br / /&gt;&lt;b&gt;header&lt;/b&gt; &quot;</span> <span
class="sy0">.</span> <span
class="kw3">print_r</span><span
class="br0">&#40;</span><span
class="re1">$header</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;br / /&gt;&lt;b&gt;media_data&lt;/b&gt; &quot;</span> <span
class="sy0">.</span> <span
class="kw3">print_r</span><span
class="br0">&#40;</span><span
class="re1">$media_data</span><span
class="br0">&#41;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;br /&gt;&lt;b&gt;URL was&lt;/b&gt; &quot;</span> <span
class="sy0">.</span> <span
class="re1">$twitpicURL</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp; <span
class="re1">$content</span> <span
class="sy0">.=</span> <span
class="st0">&quot;&lt;br /&gt;&lt;b&gt;File uploaded was&lt;/b&gt; &quot;</span> <span
class="sy0">.</span> <span
class="re1">$_FILES</span><span
class="br0">&#91;</span><span
class="st0">&#39;media&#39;</span><span
class="br0">&#93;</span><span
class="br0">&#91;</span><span
class="st0">&#39;tmp_name&#39;</span><span
class="br0">&#93;</span><span
class="sy0">;</span></div></li><li
class="li1"><div
class="de1">&nbsp;<span
class="br0">&#125;</span></div></li><li
class="li1"><div
class="de1"><span
class="br0">&#125;</span></div></li></ol></div><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=2084&amp;md5=71593e8ec741c57504029f65f36a4261" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/05/howto-twitpic-and-oauth/feed/</wfw:commentRss> <slash:comments>25</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=2084&amp;md5=71593e8ec741c57504029f65f36a4261" type="text/html" /> </item> <item><title>Bugs in Twitter Text Libraries</title><link>http://shkspr.mobi/blog/index.php/2010/03/bugs-in-twitter-text-libraries/</link> <comments>http://shkspr.mobi/blog/index.php/2010/03/bugs-in-twitter-text-libraries/#comments</comments> <pubDate>Wed, 31 Mar 2010 10:27:50 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[/etc/]]></category> <category><![CDATA[mobile]]></category> <category><![CDATA[usability]]></category> <category><![CDATA[bugs]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[parse]]></category> <category><![CDATA[regex]]></category> <category><![CDATA[twitter]]></category> <category><![CDATA[urls]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1924</guid> <description><![CDATA[The Twitter Engineering Team have a set of text processing classes which are meant to simplify and standardise the recognition of URLs, screen names, and hashtags. Dabr makes use of them to keep in conformance with Twitter&#8217;s style. One of the advantages of the text processing is that it will recognise that www.example.com is a <a
href='http://shkspr.mobi/blog/index.php/2010/03/bugs-in-twitter-text-libraries/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>The <a
href="http://engineering.twitter.com/2010/02/introducing-open-source-twitter-text.html">Twitter Engineering Team have a set of text processing classes</a> which are meant to simplify and standardise the recognition of URLs, screen names, and hashtags.  Dabr makes use of them to keep in conformance with Twitter&#8217;s style.</p><p>One of the advantages of the text processing is that it will recognise that www.example.com is a URL and automatically create a hyperlink. Considering that dropping the &#8220;http://&#8221; represents 5% saving on Twitter&#8217;s 140 character limit for messages, this is great.</p><p>So, I was mightily surprised to get <a
href="http://twitter.com/schmmuck/status/11352406573">this bug report</a> from user &#8220;schmmuck&#8221;</p><div
id="attachment_1927" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-1927" title="Dabr rendering error" src="http://shkspr.mobi/blog/wp-content/uploads/2010/03/Capture8_19_22.jpg" alt="Dabr rendering error" width="480" height="320" /><p
class="wp-caption-text">Dabr rendering error</p></div><p>How very odd&#8230;  This is how it looks on <a
href="http://m.twitter.com/">m.twitter.com</a>.</p><div
id="attachment_1926" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-1926" title="m.twitter rendering error" src="http://shkspr.mobi/blog/wp-content/uploads/2010/03/Capture8_20_48.jpg" alt="m.twitter rendering error" width="480" height="320" /><p
class="wp-caption-text">m.twitter rendering error</p></div><p>Twitter also use <a
href="http://mobile.twitter.com/">mobile.twitter.com</a> for smartphones.  Here&#8217;s how that site renders the text.</p><div
id="attachment_1925" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-1925" title="mobile.twitter rendering error" src="http://shkspr.mobi/blog/wp-content/uploads/2010/03/Capture8_21_54.jpg" alt="mobile.twitter rendering error" width="480" height="320" /><p
class="wp-caption-text">mobile.twitter rendering error</p></div><p>Finally, let&#8217;s take a look at the &#8220;canonical&#8221; rendering at Twitter.com</p><div
id="attachment_1928" class="wp-caption aligncenter" style="width: 410px"><img
class="size-full wp-image-1928" title="Twitter rendering error" src="http://shkspr.mobi/blog/wp-content/uploads/2010/03/Twitter-rendering-error.jpg" alt="Twitter rendering error" width="400" height="213" /><p
class="wp-caption-text">Twitter rendering error</p></div><h2>The Problem(s)</h2><p>The first issue is inconsistency.  Twitter ought to be using the same regex for each of its sites.  It doesn&#8217;t.  This means that different developers will get divergent experiences.  This leads to confusion, which leads to fear, which, as we all know, leads to anger&#8230;. and so forth.</p><p>Secondly, and more importantly, parsing is <em>hard</em>.  There are so many edge cases that errors inevitably creep in.  My post about hashtags explains the problems in defining what <em>should</em> be recognised.</p><p>So, based on what we&#8217;ve seen, should Twitter recognise any of the following as URLs?</p><p>news.bbc.co.uk &#8211; no www there.</p><p>invalid.name &#8211; a silly URL, but a valid one.</p><p>खोज.com &#8211; International domains contain more than just ASCII</p><p>All the above are valid &#8211; yet they&#8217;re not recognised by Twitter.</p><h2>A (Simple) Solution?</h2><p>There is a <a
href="http://www.iana.org/domains/root/db/">canonical list of TLDs</a> which is also available as a <a
href="http://data.iana.org/TLD/tlds-alpha-by-domain.txt">plain text list</a>.</p><p>Any string containing a &#8220;.&#8221; followed by a valid TLD, then followed by a space or &#8220;/&#8221; should be treated as a URL.</p><p>Your thoughts?</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1924&amp;md5=f23a393180b7edf5f5386e927c745cec" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/03/bugs-in-twitter-text-libraries/feed/</wfw:commentRss> <slash:comments>6</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1924&amp;md5=f23a393180b7edf5f5386e927c745cec" type="text/html" /> </item> <item><title>Dabr &#8211; Reply to all and Geotagging</title><link>http://shkspr.mobi/blog/index.php/2010/03/dabr-reply-to-all-and-geotagging/</link> <comments>http://shkspr.mobi/blog/index.php/2010/03/dabr-reply-to-all-and-geotagging/#comments</comments> <pubDate>Wed, 24 Mar 2010 11:36:39 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[geotagging]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1881</guid> <description><![CDATA[People have been very excited to see some new functionality in Dabr &#8211; the mobile Twitter client I develop for. But what is it and how does it work? Reply to All The @@ symbol allows you to reply to all the people mentioned within the tweet. It only shows up on tweets which mention <a
href='http://shkspr.mobi/blog/index.php/2010/03/dabr-reply-to-all-and-geotagging/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>People have been very excited to see some new functionality in <a
href="http://m.dabr.co.uk/">Dabr</a> &#8211; the mobile Twitter client I develop for.  But what is it and how does it work?</p><div
id="attachment_1882" class="wp-caption aligncenter" style="width: 456px"><img
class="size-full wp-image-1882" title="@@ and geotag" src="http://shkspr.mobi/blog/wp-content/uploads/2010/03/@@-and-geotag.png" alt="@@ and geotag" width="446" height="60" /><p
class="wp-caption-text">@@ and geotag</p></div><h2>Reply to All</h2><p>The <strong>@@</strong> symbol allows you to reply to all the people mentioned within the tweet.<br
/> It only shows up on tweets which mention other users &#8211; so you should only ever see it when it can be used.</p><p>Hitting <strong>@@</strong> on the above tweet will pre-populate the text box with &#8220;@topgold @whatleydude @dabr&#8221;.</p><p>It should remove any duplicates and should also remove your username.</p><h2>Geotagging</h2><p>Twitter recently allowed the geotagging of tweets.  This allows you to set the longitude and latitude of where you are when you wrote your message.<br
/> Clicking on the green globe (it just looks like a dot at that size!) takes you to a mobile mapping service.</p><div
id="attachment_1884" class="wp-caption aligncenter" style="width: 330px"><img
class="size-full wp-image-1884" title="Google Maps Mobile" src="http://shkspr.mobi/blog/wp-content/uploads/2010/03/snap20100324_110828.png" alt="Google Maps Mobile" width="320" height="480" /><p
class="wp-caption-text">Google Maps Mobile</p></div><p>It only shows up on tweets which are geotagged &#8211; so you should only ever see it when it can be used.</p><h2>How Does It Work?</h2><p>You can see <a
href="http://code.google.com/p/dabr/source/list">all the code in the SVN</a>, but here&#8217;s a quick rundown.</p><p>Geotagging is very simple.  Statuses now have a &lt;geo&gt; field.  If this is populated, it will contain a longitude and latitude.</p><p>﻿We can take those values and pass them to Google Maps Mobile (or your favourite mobile mapping service).<br
/> <code>if ($geo !== null)<br
/> {<br
/> &nbsp;&nbsp;&nbsp;$latlong = $geo->coordinates;<br
/> &nbsp;&nbsp;&nbsp;$lat = $latlong[0];<br
/> &nbsp;&nbsp;&nbsp;$long = $latlong[1];<br
/> &nbsp;&nbsp;&nbsp;$actions[] = theme('action_icon', "http://maps.google.co.uk/m?q={$lat},{$long}", 'images/map.png', 'MAP');<br
/> }</code></p><p>Reply to all is a little more involved.<br
/> Twitter provide an <a
href="http://engineering.twitter.com/2010/02/introducing-open-source-twitter-text.html">excellent set of Text Libraries</a>.  These provide officially sanctioned regular expressions to help your project find URLs, hashtags and usernames.</p><p>Using the <a
href="http://github.com/mzsanford/twitter-text-php/blob/master/src/Twitter/Extractor.php">Twitter Text Extractor class</a> we can determine how many usernames are mentioned in a tweet.  Any duplicates are removed &#8211; as is the user&#8217;s username.</p><p>Any questions &#8211; just ask!</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1881&amp;md5=dbf9f757fc788e0c1e2191cde3940932" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/03/dabr-reply-to-all-and-geotagging/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1881&amp;md5=dbf9f757fc788e0c1e2191cde3940932" type="text/html" /> </item> <item><title>Hashtags and Implicit Knowledge</title><link>http://shkspr.mobi/blog/index.php/2010/02/hashtags-and-implicit-knowledge/</link> <comments>http://shkspr.mobi/blog/index.php/2010/02/hashtags-and-implicit-knowledge/#comments</comments> <pubDate>Wed, 24 Feb 2010 16:58:27 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[usability]]></category> <category><![CDATA[api]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[documentation]]></category> <category><![CDATA[hashtags]]></category> <category><![CDATA[tags]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1706</guid> <description><![CDATA[What is &#8220;Implicit Knowledge&#8221;? Essentially it&#8217;s stuff that everyone knows, but no one has written down. Usually it&#8217;s something that people have worked out through their own experiences. This sort of knowledge is common in life &#8211; but is fatal in computing and design. Take the following tweet I received. The complaint was that #tfm&#38;a <a
href='http://shkspr.mobi/blog/index.php/2010/02/hashtags-and-implicit-knowledge/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>What is &#8220;Implicit Knowledge&#8221;?  Essentially it&#8217;s stuff that everyone knows, but no one has written down.  Usually it&#8217;s something that people have worked out through their own experiences.</p><p>This sort of knowledge is common in life &#8211; but is fatal in computing and design.  Take the following tweet I received.</p><div
class="quotedtweet" id="tw9582463562" style="background-color:#eef;padding:5px;margin-bottom:5px"><div
class="tw_user-info" style="padding:10px 10px 5px 0;float:left;text-align:center;width:100px;"><div
class="tw_thumb"> <a
href="http://twitter.com/Mawkins" title="Mark Hawkins" class="quoting_pic" rel="external"><img
src="http://img.tweetimag.es/i/Mawkins_n" alt="Mawkins" /></a></div><div
class="tw_screen-name"> <em><a
href="http://twitter.com/Mawkins" title="Twitter page : Mark Hawkins" rel="external">Mawkins</a></em></div><div
class="tw_full-name"> <strong>(Mark Hawkins)</strong></div></div><div
class="tw_content" style="float: left; width: 500px; font: 20pt Georgia, Verdana, sans-serif; font-style: normal;"><div
class="tw_entry-content"> <a
href="http://www.twitter.com/edent" rel="external">@edent</a> <a
href="http://www.twitter.com/dabr" rel="external">@dabr</a> you folks aware ampersands / &amp;s don't seem to work as part of hashtag links?</div></div><div
style="clear: both; text-align: left;font-style:italic;margin-left:110px"><p
class="tw_meta tw_entry-meta" style="margin: 0;padding-top:5px"> <small> <span>On <a
href="http://twitter.com/Mawkins/status/9582463562" rel="external">24-2-2010 16:27:19</a></span> <span>from <a
href="http://www.tweetdeck.com" rel="nofollow">TweetDeck</a></span> <span> in reply to <a
href="http://twitter.com/edent/status/9581804744" rel="external">Terence Eden</a></span> </small></p></div></div><p>The complaint was that #tfm&amp;a should be rendered as <span
style="text-decoration: underline;">#tfm&amp;a</span> not <span
style="text-decoration: underline;">#tfm</span>&amp;a.</p><h2>Everyone knows that&#8217;s how hashtags work!</h2><p>On Twitter&#8217;s website, find the page which discusses hashtag syntax.  Find where they explain how they should be styled.</p><p><strong>You can&#8217;t.</strong></p><p>And thus implicit knowledge is born.  Dabr only looks at letters and numbers in a hashtag.  It assumes that any other character is the end of the tag.</p><div
id="attachment_1708" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-1708" title="Dabr's Hashtag" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Capture16_35_30.jpg" alt="Dabr's Hashtag" width="480" height="320" /><p
class="wp-caption-text">Dabr&#39;s Hashtag</p></div><p>Without official guidance &#8211; implicit knowledge develops.</p><h2>Has Dabr Got It Wrong?</h2><p>No.  I don&#8217;t think so.  Take a look at how Twitter on the web renders hashtags&#8230;</p><div
id="attachment_1710" class="wp-caption aligncenter" style="width: 392px"><img
class="size-full wp-image-1710" title="Twitter's Web Site" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Twitters-Web-Site.png" alt="Twitter's Web Site" width="382" height="312" /><p
class="wp-caption-text">Twitter&#39;s Web Site</p></div><p>&#8230;and on the mobile.</p><div
id="attachment_1707" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-1707" title="Twitter Mobile" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Capture16_34_33.jpg" alt="Twitter Mobile" width="480" height="320" /><p
class="wp-caption-text">Twitter Mobile</p></div><h2>So Where Does Render The Full Tag?</h2><p>Several applications don&#8217;t render tags in the same way as Twitter.  Take a look at SocialScope</p><div
id="attachment_1709" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-1709" title="SocialScope Hashtags" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Capture16_34_56.jpg" alt="SocialScope Hashtags" width="480" height="320" /><p
class="wp-caption-text">SocialScope Hashtags</p></div><div
id="attachment_1727" class="wp-caption aligncenter" style="width: 330px"><img
src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/jsfe.jpg" alt="Tweetie2" title="Tweetie2" width="320" height="480" class="size-full wp-image-1727" /><p
class="wp-caption-text">Tweetie2</p></div><p>I&#8217;ll upload more screenshots if I find examples of &#8220;badly behaved&#8221; hashtags.  Please let me know if you find any.</p><h2>What Does Twitter Say?</h2><p>Twitter has one page devoted to hashtags.  It is a <a
href="http://help.twitter.com/forums/10711/entries/49309-what-are-hashtags-the-symbol">support page for hashtags</a>.  This explains to people what hashtags are.  There&#8217;s no detail on valid characters, maximum length, or any of the things which might be useful for a developer or designer.</p><h3>Edit 2010-02-25</h3><p>David Dorward has <a
href="http://twitter.com/dorward/status/9584777039">pointed out that there is an official resource</a>. On the Twitter Engineering blog &#8211; which isn&#8217;t linked to from the developer site &#8211; there is a <a
href="http://engineering.twitter.com/2010/02/introducing-open-source-twitter-text.html">page discussing hashtags and how to validate them</a>.  You&#8217;ll notice that they are rather circumspect on what should constitute a hashtag.</p><h2>Conclusion</h2><p>Standards and guidelines allow developers to create compatible applications.</p><p>Without explicit recommendations, developers will diverge as widely as possible.  Twitter &#8211; and everyone with an interest in compatibility and usability &#8211; needs to ensure that the knowledge they impart is <em>explicit</em>.</p><p>Letting people make it up as they go along leads to confusion.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1706&amp;md5=3da27a57f5bf04e91e228cb51e8ce6b3" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/02/hashtags-and-implicit-knowledge/feed/</wfw:commentRss> <slash:comments>5</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1706&amp;md5=3da27a57f5bf04e91e228cb51e8ce6b3" type="text/html" /> </item> <item><title>Don&#8217;t Let Users Do Things They Can&#8217;t Do</title><link>http://shkspr.mobi/blog/index.php/2010/02/dont-let-users-do-things-they-cant-do/</link> <comments>http://shkspr.mobi/blog/index.php/2010/02/dont-let-users-do-things-they-cant-do/#comments</comments> <pubDate>Mon, 22 Feb 2010 15:05:42 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[usability]]></category> <category><![CDATA[api]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1682</guid> <description><![CDATA[There are many &#8220;rules&#8221; when it comes to User Interface / User Experience design.  One that I try to stick to is &#8220;Don&#8217;t let users do things they can&#8217;t do.&#8221; It&#8217;s one of my gripes with Linux.  If you&#8217;re editing a configuration file, you are relying on yourself to sanity check your input &#8211; often <a
href='http://shkspr.mobi/blog/index.php/2010/02/dont-let-users-do-things-they-cant-do/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>There are many &#8220;rules&#8221; when it comes to User Interface / User Experience design.  One that I try to stick to is &#8220;Don&#8217;t let users do things they can&#8217;t do.&#8221;</p><p>It&#8217;s one of my gripes with Linux.  If you&#8217;re editing a configuration file, you are relying on yourself to sanity check your input &#8211; often without knowing what the limits are.</p><p>Take these two different examples.</p><p>In a text file, we might have:</p><blockquote><pre>#Maximum Widgets to fidget
maxW_to-F = 0
</pre></blockquote><p>Whereas a GUI would show</p><p>How many Widgets do you want to fidget?<br
/> <select><option>1</option><option>2</option><option>3</option><option>5</option> </select><p>Even if you don&#8217;t know the rules behind Widget fidgetting (must be a prime number lower than 7), the GUI won&#8217;t let you choose a value that you can&#8217;t select.  The GUI doesn&#8217;t prevent you setting an innapropriate value &#8211; just an illegal one. Your config file, however, could be set to any crazy value that a user type &#8211; often resulting in &#8220;unpredictable&#8221; results.</p><blockquote><pre>#Maximum Widgets to fidget
maxW_to-F = seventeen
</pre></blockquote><p>It&#8217;s with this in mind that I&#8217;ve made the following <a
href="http://code.google.com/p/dabr/source/detail?r=279">change to Dabr</a> &#8211; the mobile Twitter client.</p><h2>To Auth or Not To Auth? That Is The Question</h2><p>Twitter&#8217;s API has bug / peculiarity (<a
href="http://groups.google.com/group/twitter-development-talk/browse_thread/thread/318a5e820ee73765#">reported to their discussion board</a>) which causes Dabr to log a user out.  Let me explain the steps</p><ul><li>User 1 (@private) has set her tweets to &#8220;protected&#8221;.</li><li>This means no one can see @private&#8217;s tweet unless she allows them.</li><li>@private has not allowed User 2 (@edent) to view her tweets.  She is protect from his view.</li><li>@edent clicks to view @private&#8217;s profile.</li><li>@edent can see that @private has 42 friends, 17 followers and 3 favourites.</li></ul><p>So far, this is the same behaviour on Twitter&#8217;s website as it is through their API.  Here&#8217;s the difference</p><h3>Web</h3><ul><li>@edent tries to see @private&#8217;s followers and can see their names, profile pictures etc.</li><li>@edent can also see @private&#8217;s friends</li><li>@edent <strong>cannot</strong> see @private&#8217;s favourites (or even how many favourites she has)</li></ul><h3>API</h3><ul><li>@edent tries to see @private&#8217;s followers, friends or favourites</li><li>Because @edent isn&#8217;t allowed to see @private&#8217;s info, the API returns <a
href="http://apiwiki.twitter.com/HTTP-Response-Codes-and-Errors">401 Authorisation Required</a>.</li></ul><p>This is where things get tricky. Dabr sees the 401 and concludes that the user has invalid credentials.  It then, as a security measure, clears the user&#8217;s cookie and logs them out.</p><p>This may be a little harsh, but <a
href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error">HTTP 401 essentially says that the authorisation has failed</a>.</p><h2>Fixing It</h2><p>There are 3 ways that this could be fixed</p><ol><li>Twitter could rationalise the API to allow access to the same content that a web user gets.</li><li>Twitter could return a different status code.</li><li>Dabr needs fixing.</li></ol><p>So, how do we get Dabr not to log out when it receives a 401 <em>only</em> under these specific circumstances?</p><p><a
href="http://code.google.com/p/dabr/source/browse/trunk/common/twitter.php?r=274#293">Looking at the code</a>, we can see that Dabr simply sees the HTTP response code.  To fix it we&#8217;ll need to pass extra parameters, check where the code was called from, investigate all the edge cases, add more logic to the system, futz around breaking things, etc&#8230; etc&#8230;</p><p>What a pain in the&#8230;</p><h2>Or</h2><p><em>Don&#8217;t let users do things they </em>can&#8217;t<em> do.</em></p><p>If a user can&#8217;t see the information &#8211; why do we even let them <em>try</em> to see the information?  Why can&#8217;t we just get rid of the link?</p><p>This is what a user currently sees:</p><div
id="attachment_1688" class="wp-caption aligncenter" style="width: 364px"><img
class="size-full wp-image-1688" title="Old Style" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Old-Style.png" alt="Old Style" width="354" height="73" /><p
class="wp-caption-text">Old Style</p></div><p>We&#8217;ve established that they can&#8217;t view followers, friends and favourites.  So we can get rid of those links (but not the information).</p><div
id="attachment_1687" class="wp-caption aligncenter" style="width: 364px"><img
class="size-full wp-image-1687" title="New Style" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/New-Style.png" alt="New Style" width="354" height="73" /><p
class="wp-caption-text">New Style</p></div><p>(Incidentally, I&#8217;ve changed the order of the links.  I&#8217;ve tried to group together similar items.  Followers, friends, favourites and lists go together. Then DM. Finally, follow, block, report spam.)</p><p>Now a user cannot click through to an unwanted error message.</p><h2>Or</h2><p>There is another way round this.  With &#8220;Direct Messages&#8221; we could do the same thing &#8211; simply remove the link if you&#8217;re not able to send that user a DM.</p><p>Instead, we&#8217;ve taken the approach of displaying a suitable error message.</p><div
id="attachment_1689" class="wp-caption aligncenter" style="width: 455px"><img
class="size-full wp-image-1689" title="Direct Message Warning" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Direct-Message-Warning.png" alt="Direct Message Warning" width="445" height="194" /><p
class="wp-caption-text">Direct Message Warning</p></div><p>The advantage of this is that the user gets an explanation as to <em>why</em> they are unable to complete an action.</p><h2>Your Thought?</h2><p>Which do you prefer? Being unable to click on a link (with no explanation) or clicking on a link only to be given a warning message?</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1682&amp;md5=b886ba243cc96e8f8af7c6865be81c44" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/02/dont-let-users-do-things-they-cant-do/feed/</wfw:commentRss> <slash:comments>3</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1682&amp;md5=b886ba243cc96e8f8af7c6865be81c44" type="text/html" /> </item> <item><title>Twitter and Linebreaks</title><link>http://shkspr.mobi/blog/index.php/2010/02/twitter-and-linebreaks/</link> <comments>http://shkspr.mobi/blog/index.php/2010/02/twitter-and-linebreaks/#comments</comments> <pubDate>Wed, 17 Feb 2010 11:45:21 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[aral]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[feathers]]></category> <category><![CDATA[html]]></category> <category><![CDATA[php]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1642</guid> <description><![CDATA[As any student of computer science knows, line breaks are confusing. There are styles of line breaks unique to Unix, Mac and Windows &#8211; so what should a web renderer do when faced with a newline command? In HTML, it&#8217;s simple, they should be ignored. But what when it is user generated text, not HTML? <a
href='http://shkspr.mobi/blog/index.php/2010/02/twitter-and-linebreaks/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>As any student of computer science knows, <a
href="http://en.wikipedia.org/wiki/Newline">line breaks are confusing</a>. There are styles of line breaks unique to Unix, Mac and Windows &#8211; so what should a web renderer do when faced with a newline command?  In HTML, it&#8217;s simple, they should be ignored.  But what when it is user generated text, not HTML?</p><p>This was a problem I faced when trying to get Dabr to render the <a
href="http://en.wikipedia.org/wiki/ASCII_art">ASCII* art</a> produced by <a
href="http://aralbalkan.com/">Aral Balkan</a>&#8216;s <a
href="http://feathersapp.com/">Feathers App</a>.  Feathers uses line breaks to achieve images like&#8230;</p><pre>〰❀❃ Introducing ❃❀〰
My new iPhone app,
░░░▒█ Feathers █▒░░░
</pre><p>What&#8217;s confusing to me, as a developer is the inconsistent way Twitter handles line breaks.  For example&#8230;</p><p>Twitter&#8217;s website ignores line breaks.</p><div
id="attachment_1643" class="wp-caption aligncenter" style="width: 410px"><img
class="size-full wp-image-1643" title="Desktop Spacing" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Desktop-Spacing.png" alt="Desktop Spacing" width="400" height="178" /><p
class="wp-caption-text">Desktop Spacing</p></div><p>Twitter Mobile, however, does line breaking correctly.</p><div
id="attachment_1644" class="wp-caption aligncenter" style="width: 330px"><img
class="size-full wp-image-1644" title="Android Spacing" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Android-Spacing.png" alt="Android Spacing" width="320" height="480" /><p
class="wp-caption-text">Android Spacing</p></div><p>Twitter has no style guide for rendering and &#8211; if it did &#8211; appears to render inconsistently.  So, what&#8217;s the correct thing to do?</p><p>In my opinion, <strong>respect the user</strong>. If a user has indicted that they want something, it is a developer&#8217;s role to implement it (unless it causes severe problems for the system).</p><h2>How to achieve it?</h2><p>You could use all sorts of complex regular expressions to get line breaks and convert them.<br
/> Thankfully, PHP has this function built in with <a
href="http://uk.php.net/manual/en/function.nl2br.php">nl2br()</a> which will give you (X)HTML line breaks wherever a break occurs in the text.</p><h3>Footnote</h3><p>*Technically, Unicode Art. But that doesn&#8217;t have the same ring to it.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1642&amp;md5=0d3aa180d4ac52bae4d97a8b448c8fc3" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/02/twitter-and-linebreaks/feed/</wfw:commentRss> <slash:comments>6</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1642&amp;md5=0d3aa180d4ac52bae4d97a8b448c8fc3" type="text/html" /> </item> <item><title>Twitter&#8217;s new OAuth Problem</title><link>http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-problem/</link> <comments>http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-problem/#comments</comments> <pubDate>Fri, 12 Feb 2010 12:10:07 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[politics]]></category> <category><![CDATA[usability]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[oauth]]></category> <category><![CDATA[security]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1627</guid> <description><![CDATA[Twitter have announced that all third party site will have to use OAuth.  You will no longer be able to just type in your username and password to get access to Twitter via your favourite web client. Usually, I would be a big fan of this move &#8211; especially if it forces password anti-pattern sites <a
href='http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-problem/'>[...]</a>]]></description> <content:encoded><![CDATA[<p><a
href="http://groups.google.com/group/twitter-api-announce/browse_thread/thread/c2c4963061422f28?hl=en&amp;pli=1">Twitter have announced that all third party site will have to use OAuth</a>.  You will no longer be able to just type in your username and password to get access to Twitter via your favourite web client.</p><p>Usually, I would be a big fan of this move &#8211; especially if it forces <a
href="http://adactio.com/journal/1357">password anti-pattern</a> sites like <a
href="http://getsatisfaction.com/twitpic/topics/when_will_twitpic_implement_oauth">TwitPic to implement the new, secure standard</a>.</p><p>This means that you won&#8217;t be able to log in to a third party site by giving them your username and  password.  You will have to use OAuth to securely validate with the main Twitter site.</p><p>But &#8211; as ever &#8211; there&#8217;s a dark side to OAuth.</p><h2>Repressive Regimes</h2><p>One of the joys of Twitter is that its clients are decentralised from the main site.</p><p>This means that if Twitter is blocked in your country, you can use a third party client (like <a
href="http://dabr.co.uk/">Dabr</a>) to access it.</p><blockquote><pre>Twitter User -&gt; Dabr -&gt; Twitter API -&gt; Dabr -&gt; User</pre></blockquote><p>If Dabr became sufficiently popular to be blocked by an oppressive regime, you can switch to any one of the thousands of Twitter web clients.</p><p>OAuth <strong>forces </strong>you to the main Twitter site.  While you may visit Dabr to start with, you would be redirected to Twitter to complete OAuth.  If Twitter is blocked, you can&#8217;t connect.</p><h3>At a stroke, Twitter has shut itself off to anyone in a repressive country.</h3><p><a
href="http://groups.google.com/group/twitter-development-talk/browse_thread/thread/39b8b326d8b679c6">This has been picked up by some concerned users</a>.</p><h2>A (Hacky) Way Around It</h2><p>There&#8217;s really only one way around this problem.  The third party web client has to act as a man-in-the-middle.  There&#8217;s a patch for Dabr &#8211; developed by <a
href="http://code.google.com/u/cnyegle/" class="broken_link">cnyegle</a> &#8211; which will ask for a username and password, then proxy it to Twitter, get the OAuth token and tweet on behalf of the user.</p><p>From the user&#8217;s point of view, they are still giving the (potentially untrusted) site the username and password.</p><h2>Challenge Response</h2><p>This could be solved by implemented a challenge / response system.</p><ol><li>Alice visits the Dabr website.</li><li>Dabr asks Alice for her username (and <em>only</em> her username)</li><li>Dabr asks Twitter for the challenge associated with Alice&#8217;s username.</li><li>Twitter checks that Dabr is an authorised website (i.e. has signed up for OAuth).</li><li>Twitter returns the response:  A secret phrase which Alice has previously chosen.</li><li>Dabr displays this phrase to Alice.</li><li>Alice knows that Twitter trusts Dabr</li><li>Dabr asks Twitter for the password challenge.</li><li>Twitter returns that it requires the 3rd, 5th and last character from Alice&#8217;s password (the characters requested change randomly).</li><li>Dabr asks Alice for <em>only</em> those characters.</li><li>If Alice provides the correct characters, an OAuth token is granted to Dabr to tweet on behalf of Alice.</li></ol><p>This has the advantage of proving that Dabr is trusted (by displaying Alice&#8217;s pre-defined secret phrase) and mitigating the risk that Dabr is untrusted (by only revealing part of the password).</p><h2>Conclusion</h2><p>This is a very new area, and I&#8217;ve not had a chance to read through all of the proposals.  Nevertheless, it remains a fundamental problem that, if you can&#8217;t access a site, you need to delegate your trust to someone else.</p><p>I&#8217;m not a security expert &#8211; so I would appreciate someone pointing out the flaws in my reasoning.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1627&amp;md5=3e2818252192289b33db318f3f3a2b2f" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-problem/feed/</wfw:commentRss> <slash:comments>4</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1627&amp;md5=3e2818252192289b33db318f3f3a2b2f" type="text/html" /> </item> <item><title>Twitter OAuth &#8211; Mobile Failures</title><link>http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-mobile-failures/</link> <comments>http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-mobile-failures/#comments</comments> <pubDate>Sun, 07 Feb 2010 15:06:26 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[usability]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[oauth]]></category> <category><![CDATA[security]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1606</guid> <description><![CDATA[I&#8217;m a big fan of OAuth &#8211; despite some claims to the contrary. It&#8217;s an excellent way of teaching people not to stick their username and password into any old site which asks for it. Which is why I&#8217;m so incredibly disappointed in Twitter&#8217;s implementation of mobile OAuth. For a service which started out operating <a
href='http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-mobile-failures/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>I&#8217;m a big fan of OAuth &#8211; <a
href="http://www.theregister.co.uk/2009/11/04/oauth_dark_side/">despite some claims to the contrary</a>.  It&#8217;s an excellent way of teaching people not to stick their username and password into any old site which asks for it.  Which is why I&#8217;m so incredibly disappointed in Twitter&#8217;s implementation of mobile OAuth.</p><p>For a service which started out operating by SMS, Twitter takes a surprisingly unenlightened view of mobile.  It&#8217;s main mobile service &#8211; <a
href="http://m.twitter.com/">http://m.twitter.com/</a> &#8211; is almost completely devoid of useful features.  That&#8217;s one of the main impetuses behind the development of <a
href="http://dabr.co.uk/">Dabr</a>.  Their latest mobile site &#8211; <a
href="http://mobile.twitter.com/">http://mobile.twitter.com/</a> &#8211; is really only suitable for the tiny minority of people who have smartphones.</p><p>So, understandably, many people use 3rd party sites like Dabr.  They are now faced with a dilemma &#8211; give an untrusted site their username and password or try to use OAuth on the mobile.</p><p>A few weeks ago came the <a
href="http://groups.google.com/group/twitter-development-talk/browse_thread/thread/084f57349587b3d2/">announcement that OAuth was finally ready for mobile</a>&#8230; Was it? No.  Once again a &#8220;mobile friendly&#8221; site designed with masses of JavaScript and guaranteed not to work with the majority of phones on the market.</p><p>Here&#8217;s how mobile OAuth looks on a variety of popular mobile phones.</p><h2>BlackBerry</h2><div
id="attachment_1607" class="wp-caption aligncenter" style="width: 480px"><img
class="size-full wp-image-1607" title="BlackBerry Twitter OAuth" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/BlackBerry-Twitter-OAuth.png" alt="BlackBerry Twitter OAuth" width="470" height="695" /><p
class="wp-caption-text">BlackBerry Twitter OAuth</p></div><p>While this looks pretty enough, it doesn&#8217;t work.  The buttons <em>aren&#8217;t clickable</em>.  I&#8217;ve tried with and without JavaScript.  No matter where I click, nothing happens.</p><h2>Android</h2><p>The Android&#8217;s User-Agent isn&#8217;t detected by Twitter as being a mobile phone.  While it&#8217;s true that the browser is very capable &#8211; the OAuth screen is a lot more usable when it&#8217;s in mobile mode.</p><div
id="attachment_1610" class="wp-caption aligncenter" style="width: 330px"><img
class="size-full wp-image-1610" title="Android Twitter OAuth" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/android2.png" alt="Android Twitter OAuth" width="320" height="480" /><p
class="wp-caption-text">Android Twitter OAuth</p></div><p>So, it works, but it doesn&#8217;t look nice.</p><h2>N95</h2><p>The N95 makes a good test phone because it&#8217;s popular.  Probably more popular than the iPhone.</p><div
id="attachment_1612" class="wp-caption aligncenter" style="width: 250px"><img
class="size-full wp-image-1612" title="N95 Twitter OAuth" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Screenshot0106.png" alt="N95 Twitter OAuth" width="240" height="320" /><p
class="wp-caption-text">N95 Twitter OAuth</p></div><div
id="attachment_1613" class="wp-caption aligncenter" style="width: 250px"><img
class="size-full wp-image-1613" title="N95 Twitter OAuth" src="http://shkspr.mobi/blog/wp-content/uploads/2010/02/Screenshot0108.png" alt="N95 Twitter OAuth" width="240" height="320" /><p
class="wp-caption-text">N95 Twitter OAuth</p></div><p>It&#8217;s not pretty &#8211; but at least it works.</p><h2>Others</h2><p>The Sharp GX-10 is my default test phone.  One of the first phones with a colour HTML browser.  If your site can work on this phone, it will work on any phone.  There are no screenshot capabilities for this phone &#8211; but rest assured, it does not work.</p><p>The three phones I&#8217;ve demo&#8217;d above are very popular modern phones &#8211; AKA the minority.  If they don&#8217;t work well, what chance for the people using older phones?</p><p>Useless!  How hard can it be?  All it needs is a username field, a password field and a button.  That&#8217;s just about the most basic page imaginable.  It should be child&#8217;s play to make it work on mobile.</p><p>This was <a
href="http://code.google.com/p/twitter-api/issues/detail?id=395">first raised in March 2009 on Twitter&#8217;s issues list</a>. It&#8217;s currently the <em>most popular</em> bug.</p><p>So, we&#8217;re stuck in a dire situation.  Third-Party mobile sites get access to Twitter users&#8217; passwords because Twitter are unable or unwilling to develop a <em>simple</em> OAuth form.  It would be fascinating to know how many of Twitter&#8217;s security breaches are down to corrupt or insecure 3rd party sites which leak passwords.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1606&amp;md5=de898d729cb42f915edb82f089063071" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/02/twitter-oauth-mobile-failures/feed/</wfw:commentRss> <slash:comments>4</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1606&amp;md5=de898d729cb42f915edb82f089063071" type="text/html" /> </item> <item><title>Dabr Widget for 360 H1</title><link>http://shkspr.mobi/blog/index.php/2010/01/dabr-widget-for-360-h1/</link> <comments>http://shkspr.mobi/blog/index.php/2010/01/dabr-widget-for-360-h1/#comments</comments> <pubDate>Thu, 21 Jan 2010 11:30:38 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[360]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[jil]]></category> <category><![CDATA[limo]]></category> <category><![CDATA[twitter]]></category> <category><![CDATA[vodafone]]></category> <category><![CDATA[widgets]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1557</guid> <description><![CDATA[I&#8217;ve written a very basic JIL widget to launch dabr.  You can grab it from http://shkspr.mobi/Dabr.wgt I&#8217;ve tested this to work on the Vodafone 360 H1 &#8211; but it should work with any JIL handset. Because it isn&#8217;t certified, you may need to dial *#35767# to remove the H1&#8242;s security check. The code is very <a
href='http://shkspr.mobi/blog/index.php/2010/01/dabr-widget-for-360-h1/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>I&#8217;ve written a very basic JIL widget to launch <a
href="http://m.dabr.co.uk/">dabr</a>.  You can grab it from <a
href="http://shkspr.mobi/Dabr.wgt" class="broken_link">http://shkspr.mobi/Dabr.wgt</a></p><p><a
href="http://shkspr.mobi/blog/wp-content/uploads/2010/01/Dabr-on-360.jpg"><img
class="aligncenter size-full wp-image-1559" title="Dabr on 360" src="http://shkspr.mobi/blog/wp-content/uploads/2010/01/Dabr-on-360.jpg" alt="" width="400" height="315" /></a></p><p>I&#8217;ve tested this to work on the Vodafone 360 H1 &#8211; but it should work with any <a
href="http://www.jil.org/">JIL</a> handset.</p><p>Because it isn&#8217;t certified, you may need to dial</p><pre>*#35767#</pre><p>to remove the <a
href="http://www.jil.org/jil-forums/posts/list/176.page#525">H1&#8242;s security check</a>.</p><p>The code is very simple.  The JIL SDK allows you to call specific phone application &#8211; in this case, all I&#8217;ve done is invoked the browser.</p><pre>&lt;body&gt;
   &lt;script type="text/javascript"&gt;
      Widget.openURL("http://m.dabr.co.uk/");
   &lt;/script&gt;
   &lt;div&gt;
      Launching Dabr!
   &lt;/div&gt;
&lt;/body&gt;</pre><p>One thing to note, if you&#8217;re deploying the widgets from your website, ensure you have set the MIME type to &#8220;application/widget&#8221; &#8211; as per the <a
href="http://www.w3.org/TR/widgets/#media-type-registration-for-applicationw">W3C standards</a> &#8211; otherwise many devices won&#8217;t recognise it as a valid widget.</p><p>If you&#8217;re interest in developing for this platform, there&#8217;s a <a
href="http://widget.developer.vodafone.com/en/" class="broken_link">€1,000,000 bounty up for grabs</a>.  There&#8217;s also a <a
href="http://jil.vodafone.com/app_planet/" class="broken_link">Dev Camp at Mobile World Congress</a> this year.</p><p>I work for Vodafone &#8211; this is my personal blog, I don&#8217;t to speak for them.  All opinions, claims and mistakes are my own.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1557&amp;md5=50fd357feb69187aafe89fbea5478d3d" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2010/01/dabr-widget-for-360-h1/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1557&amp;md5=50fd357feb69187aafe89fbea5478d3d" type="text/html" /> </item> <item><title>Integrating AudioBoo and Phreadz with Dabr</title><link>http://shkspr.mobi/blog/index.php/2009/12/integrating-audioboo-phreadz-dabr/</link> <comments>http://shkspr.mobi/blog/index.php/2009/12/integrating-audioboo-phreadz-dabr/#comments</comments> <pubDate>Wed, 30 Dec 2009 14:33:58 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[api]]></category> <category><![CDATA[audioboo]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[phreadz]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1492</guid> <description><![CDATA[A quick explanation of how I integrated AudioBoo and Phreadz with Dabr. I&#8217;m a big fan of AudioBoo &#8211; for those who don&#8217;t know it,  AudioBoo allows you to record some audio on your phone and then publish it to the web.  It&#8217;s like instant podcasting.  Originally only for the iPhone, AudioBoo now works on <a
href='http://shkspr.mobi/blog/index.php/2009/12/integrating-audioboo-phreadz-dabr/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>A quick explanation of how I integrated AudioBoo and Phreadz with Dabr.</p><p>I&#8217;m a big fan of <a
href="http://audioboo.fm/">AudioBoo</a> &#8211; for those who don&#8217;t know it,  AudioBoo allows you to record some audio on your phone and then publish it to the web.  It&#8217;s like instant podcasting.  Originally only for the iPhone, AudioBoo now works on Android and there&#8217;s an S60 version comeing out &#8220;soon&#8221;.</p><p>I&#8217;m very proud to announce that as of <a
href="http://code.google.com/p/dabr/source/detail?r=260">r260</a> &#8211; Dabr now support AudioBoo!</p><p>It all started with a tweet from David Carrington (creator of Dabr) asking how one would go about linking directly to a tweeted &#8216;boo.</p><p>So &#8211; how do I turn a tweeted &#8216;boo like <a
href="http://boo.fm/b73803">http://boo.fm/b73803</a> to the associated MP3 of <a
href="http://audioboo.fm/boos/73803-rockbandboo.mp3">http://audioboo.fm/boos/73803-rockbandboo.mp3</a> ?</p><h2>Bring Me The API!</h2><p>An API is a way for two computers to talk to each other.  The client (dabr) asks the server (AudioBoo) a question.  The server replies with some data and the client then does something with it.</p><p><a
href="http://code.google.com/p/audioboo-api/">AudioBoo&#8217;s API</a> is a &#8220;work in progress&#8221; &#8211; that&#8217;s the polite term for &#8220;not quite finished&#8221;.<br
/> There are various APIs to get information about a &#8216;boo.  However, it&#8217;s not particularly intuitive.  For example, if I use /audio_clips/</p><p>http://api.audioboo.fm/audio_clips/b73803.mp3</p><p>I get an error.<br
/> I have to drop the b to get</p><p>http://api.audioboo.fm/audio_clips/73803.mp3</p><p><a
href="http://groups.google.com/group/audioboo-api-discuss/browse_thread/thread/2c9a8d5694c0c8cd">I asked on the AudioBoo forums</a> if there was a better way but I didn&#8217;t get a quick response &#8211; so I turned to twitter.  One of the top AudioBoo bods, Mark Rock, is an active twitterer (seriously &#8211; isn&#8217;t there a better word than that?)</p><div
class="quotedtweet" id="tw6891551616" style="background-color:#eef;padding:5px;margin-bottom:5px"><div
class="tw_user-info" style="padding:10px 10px 5px 0;float:left;text-align:center;width:100px;"><div
class="tw_thumb"> <a
href="http://twitter.com/markrock" title="Mark Rock" class="quoting_pic" rel="external"><img
src="http://img.tweetimag.es/i/markrock_n" alt="markrock" /></a></div><div
class="tw_screen-name"> <em><a
href="http://twitter.com/markrock" title="Twitter page : Mark Rock" rel="external">markrock</a></em></div><div
class="tw_full-name"> <strong>(Mark Rock)</strong></div></div><div
class="tw_content" style="float: left; width: 500px; font: 20pt Georgia, Verdana, sans-serif; font-style: normal;"><div
class="tw_entry-content"> <a
href="http://www.twitter.com/davidcarrington" rel="external">@davidcarrington</a> <a
href="http://www.twitter.com/edent" rel="external">@edent</a> just updated server so this works - <a
href="http://boo.fm/b1234.mp3" rel="external">http://boo.fm/b1234.mp3</a></div></div><div
style="clear: both; text-align: left;font-style:italic;margin-left:110px"><p
class="tw_meta tw_entry-meta" style="margin: 0;padding-top:5px"> <small> <span>On <a
href="http://twitter.com/markrock/status/6891551616" rel="external">21-12-2009 12:12:59</a></span> <span>from <a
href="http://www.tweetdeck.com/" rel="nofollow">TweetDeck</a></span> <span> in reply to David Carrington</span> </small></p></div></div><p>So, now I can link http://boo.fm/b73803 to http://boo.fm/b73803.mp3 &#8211; simple.  Here&#8217;s what it looks like in the browser.</p><div
id="attachment_1497" class="wp-caption aligncenter" style="width: 309px"><img
src="http://shkspr.mobi/blog/wp-content/uploads/2009/12/Screenshot-shkspr.mobi-Search-Mozilla-Firefox-e1262183483383.png" alt="AudioBoo" title="AudioBoo" width="299" height="296" class="size-full wp-image-1497" /><p
class="wp-caption-text">AudioBoo</p></div><h2>Phreadz</h2><p><a
href="http://Phreadz.com" class="broken_link">Phreadz</a> is a service which allows you to post VITAL &#8211; Video Images Text Audio Links &#8211; it&#8217;s a fantastic service, so when Kosso (its founder) asked me to integrate it into Dabr, I was keen to take on the challenge.</p><p>The code was quite simple and can be seen in <a
href="http://code.google.com/p/dabr/source/detail?r=261">r261</a>.  But there was one small complication &#8211; image sizes.</p><p>The thumbnail images from Phreadz aren&#8217;t always suitable for mobiles.  If images are too large, it will slow download speeds and potentially cost people money.</p><p>So, I used <a
href="http://tinysrc.mobi/">tinysrc.mobi</a>. Tinysrc is a very simple API which will resize any image to a mobile friendly format.  It detects the phone&#8217;s user-agent string and creates a suitable sized image.</p><p>Here&#8217;s what it looks like.</p><div
id="attachment_1498" class="wp-caption aligncenter" style="width: 410px"><img
class="size-full wp-image-1498" title="Phreadz" src="http://shkspr.mobi/blog/wp-content/uploads/2009/12/vodaclone_1261744837_400.jpg" alt="Phreadz" width="400" height="955" /><p
class="wp-caption-text">Phreadz</p></div><h2>Conclusions</h2><p>I&#8217;ve used 4 separate APIs here &#8211; twitter, AudioBoo, Phreadz, tinysrc &#8211; the joy of Web 2.0 is that all those disparate services can combine to create something new and magical.</p><p>API designers often need to think about how their products will be used &#8220;in the wild&#8221;.  It&#8217;s very easy to create something that works very well for your requirements &#8211; but much harder to think about what others will need.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1492&amp;md5=8e778ce9a6fe1d7f41b75d382bab7480" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2009/12/integrating-audioboo-phreadz-dabr/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <enclosure
url="http://boo.fm/b73803.mp3" length="479360" type="audio/mpeg" /> <enclosure
url="http://api.audioboo.fm/audio_clips/73803.mp3" length="479360" type="audio/mpeg" /> <enclosure
url="http://audioboo.fm/boos/73803-rockbandboo.mp3" length="479360" type="audio/mpeg" /> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1492&amp;md5=8e778ce9a6fe1d7f41b75d382bab7480" type="text/html" /> </item> <item><title>Seesmic Twitter Client for BlackBerry</title><link>http://shkspr.mobi/blog/index.php/2009/11/seesmic-twitter-client-for-blackberry/</link> <comments>http://shkspr.mobi/blog/index.php/2009/11/seesmic-twitter-client-for-blackberry/#comments</comments> <pubDate>Sun, 22 Nov 2009 07:00:04 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[usability]]></category> <category><![CDATA[blackberry]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[nablopomo]]></category> <category><![CDATA[twitter]]></category> <category><![CDATA[ubertwitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=1232</guid> <description><![CDATA[Seesmic, a service I&#8217;ve not tried before, have released a Twitter client for the BlackBerry. Is it any good? How does it compare with the features of Dabr or the usability of UberTwitter? Find out! Getting the client was fairly simple, but could be better. Simply visiting http://seesmic.com was enough to bring up a mobile <a
href='http://shkspr.mobi/blog/index.php/2009/11/seesmic-twitter-client-for-blackberry/'>[...]</a>]]></description> <content:encoded><![CDATA[<p><a
href="http://seesmic.com/">Seesmic</a>, a service I&#8217;ve not tried before, have released a Twitter client for the BlackBerry.  Is it any good? How does it compare with the features of <a
href="http://m.dabr.co.uk/">Dabr</a> or the usability of <a
href="http://www.ubertwitter.com/">UberTwitter</a>? Find out!</p><p>Getting the client was fairly simple, but could be better.  Simply visiting <a
href="http://seesmic.com">http://seesmic.com</a> was enough to bring up a mobile friendly page with download instructions.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_25_27.jpg"><img
class="aligncenter size-full wp-image-1233" title="Capture9_25_27" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_25_27.jpg" alt="Capture9_25_27" width="480" height="320" /></a><br
/> However, scrolling down presented this mess.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_25_41.jpg"><img
class="aligncenter size-full wp-image-1234" title="Capture9_25_41" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_25_41.jpg" alt="Capture9_25_41" width="480" height="320" /></a><br
/> You simply can&#8217;t rely on users to know what make, model or firmware version they have.  Use the user-agent string to do as much of the hard work as possible.  If a user tries to install an incompatible version, it won&#8217;t work and they&#8217;ll blame you.</p><p>The download itself is a sprightly 172KB and installs very quickly &#8211; it also doesn&#8217;t require a reboot.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_26_9.jpg"><img
class="aligncenter size-full wp-image-1235" title="Capture9_26_9" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_26_9.jpg" alt="Capture9_26_9" width="480" height="320" /></a><br
/> Once you&#8217;ve signed in, the main interface is very simple.  UberTwitter, for example, presents the user with complex set-up options on the first run.  Seesmic gets straight to the action.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_27_55.jpg"><img
class="aligncenter size-full wp-image-1236" title="Capture9_27_55" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_27_55.jpg" alt="Capture9_27_55" width="480" height="320" /></a><br
/> Seesmic is entirely menu driven &#8211; there are no shortcut keys.  UberTwitter allows me to hit R for reply &#8211; on Seesmic, I have to delve into the menus.  Luckily, they&#8217;re short and have obvious names.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_28_1.jpg"><img
class="aligncenter size-full wp-image-1237" title="Capture9_28_1" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_28_1.jpg" alt="Capture9_28_1" width="480" height="320" /></a><br
/> Reading a tweet gives the usual option, hashtags and @s are hyperlinked &#8211; as are web addresses.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_29_20.jpg"><img
class="aligncenter size-full wp-image-1238" title="Capture9_29_20" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_29_20.jpg" alt="Capture9_29_20" width="480" height="320" /></a><br
/> On usability flaw, the cursor is at the top of the screen.  A user has to scroll through the &#8220;Web&#8221; hyperlink before getting to the links within the tweet.</p><p>Again, because there are no keyboard shortcuts, everything has to go through the menu.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_29_46.jpg"><img
class="aligncenter size-full wp-image-1240" title="Capture9_29_46" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_29_46.jpg" alt="Capture9_29_46" width="480" height="320" /></a><br
/> Searching is problematic.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_31_8.jpg"><img
class="aligncenter size-full wp-image-1241" title="Capture9_31_8" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_31_8.jpg" alt="Capture9_31_8" width="480" height="320" /></a><br
/> Pressing enter doesn&#8217;t start a search, it inserts a new line.<br
/> The search button isn&#8217;t the first thing you get to when you scroll down.<br
/> While the results are standard, this odd error message kept popping up.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_31_27.jpg"><img
class="aligncenter size-full wp-image-1242" title="Capture9_31_27" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_31_27.jpg" alt="Capture9_31_27" width="480" height="320" /></a><br
/> I encountered this error several times.</p><p>Writing new tweet has some great usability touches &#8211; and some real clunkers.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_42_13.jpg"><img
class="aligncenter size-full wp-image-1245" title="Capture9_42_13" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_42_13.jpg" alt="Capture9_42_13" width="480" height="320" /></a><br
/> The closer a user gets to filling the 140 characters, the more red the screen turns.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_42_35.jpg"><img
class="aligncenter size-full wp-image-1246" title="Capture9_42_35" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_42_35.jpg" alt="Capture9_42_35" width="480" height="320" /></a><a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_47_4.jpg"><img
class="aligncenter size-full wp-image-1252" title="Capture9_47_4" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_47_4.jpg" alt="Capture9_47_4" width="480" height="320" /></a><br
/> URLs can be automatically shortened and images can be added.  This shows one of the great usability failures of Seesmic.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_38_58.jpg"><img
class="aligncenter size-full wp-image-1243" title="Capture9_38_58" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_38_58.jpg" alt="Capture9_38_58" width="480" height="320" /></a><br
/> Rather than use the BlackBerry&#8217;s file select utility, it uses its own &#8211; and it&#8217;s dreadful.  Ugly looking, no ability to search, slow, no preview.  Overall, a real let-down.</p><p>I don&#8217;t know why companies often insist on creating their own versions of well established system functions.  Especially when they add nothing and remove plenty.</p><p>Sending a tweet was continually problematic for me.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_43_55.jpg"><img
class="aligncenter size-full wp-image-1250" title="Capture9_43_55" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_43_55.jpg" alt="Capture9_43_55" width="480" height="320" /></a><br
/> Although it eventually relented.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_44_18.jpg"><img
class="aligncenter size-full wp-image-1251" title="Capture9_44_18" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_44_18.jpg" alt="Capture9_44_18" width="480" height="320" /></a><br
/> Seesmic also makes great use of notifies, showing you on your home screen how many unread tweets you have.<br
/> <a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_40_42.jpg"><img
class="aligncenter size-full wp-image-1244" title="Capture9_40_42" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_40_42.jpg" alt="Capture9_40_42" width="480" height="320" /></a><br
/> Overall, Seesmic isn&#8217;t a bad client.  There are a few rough-around-the-edges bugs and the file selection is atrocious but other than that, it works.  Power users like me will miss the shortcut keys of UberTwitter, and UT&#8217;s system-wide integration (uploading photos, capturing hashtags in emails etc.).  It lacks other features such as in-line photos, ability to see followers and friends, it also has no way of marking a tweet as a favourite or seeing favourites.</p><p>One feature it does have &#8211; a first in mobile twitter clients &#8211; is the ability to view lists.  You can&#8217;t add, edit or create &#8211; but you can see the lists you have created or are following.</p><p><a
href="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_32_49.jpg"><img
class="aligncenter size-full wp-image-1266" title="Capture9_32_49" src="http://shkspr.mobi/blog/wp-content/uploads/2009/11/Capture9_32_49.jpg" alt="Capture9_32_49" width="480" height="320" /></a></p><h2>Conclusion</h2><p>Seesmic works well enough as a basic twitter client for BlackBerry &#8211; but there&#8217;s nothing exciting about it.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1232&amp;md5=af5d1db65822ba52cc4cb37b09ea3864" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2009/11/seesmic-twitter-client-for-blackberry/feed/</wfw:commentRss> <slash:comments>2</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=1232&amp;md5=af5d1db65822ba52cc4cb37b09ea3864" type="text/html" /> </item> <item><title>Embedding Mobile YouTube in Dabr / Twitter</title><link>http://shkspr.mobi/blog/index.php/2009/09/embedding-mobile-youtube-in-dabr-twitter/</link> <comments>http://shkspr.mobi/blog/index.php/2009/09/embedding-mobile-youtube-in-dabr-twitter/#comments</comments> <pubDate>Sun, 27 Sep 2009 10:15:14 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[php]]></category> <category><![CDATA[twitter]]></category> <category><![CDATA[youtube]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=554</guid> <description><![CDATA[I&#8217;ve decided to add a preview of YouTube videos into Dabr, the mobile Twitter service. The code is fairly simple &#8211; although I still suck at regular expressions. if (preg_match_all('#youtube\.com\/watch\?v=([_-\d\w]+)#', $tmp, $matches, PREG_PATTERN_ORDER) &#62; 0) { foreach ($matches[1] as $match) { $images[] = theme('external_link', "http://m.youtube.com/watch?v={$match}", "&#60;img src='http://i.ytimg.com/vi/{$match}/1.jpg' class='twitpic' /&#62;"); } } Here&#8217;s how it looks.  <a
href='http://shkspr.mobi/blog/index.php/2009/09/embedding-mobile-youtube-in-dabr-twitter/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>I&#8217;ve decided to add a preview of <a
href="http://www.youtube.com/">YouTube</a> videos into <a
href="http://m.dabr.co.uk/">Dabr</a>, the mobile <a
href="http://twitter.com">Twitter</a> service.</p><p>The <a
href="http://code.google.com/p/dabr/source/detail?r=192">code is fairly simple</a> &#8211; although I still suck at regular expressions.</p><pre> if (preg_match_all('#youtube\.com\/watch\?v=([_-\d\w]+)#', $tmp, $matches, PREG_PATTERN_ORDER) &gt; 0)
 {
  foreach ($matches[1] as $match)
  {
  $images[] = theme('external_link', "http://m.youtube.com/watch?v={$match}", "&lt;img src='http://i.ytimg.com/vi/{$match}/1.jpg' class='twitpic' /&gt;");
  }
 }</pre><p>Here&#8217;s how it looks.  A user writes a tweet which contains a YouTube URL</p><div
id="attachment_555" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-555" title="Capture7_55_25" src="http://shkspr.mobi/blog/wp-content/uploads/2009/09/Capture7_55_25.jpg" alt="A thumbnail embedded in a tweet" width="480" height="320" /><p
class="wp-caption-text">A thumbnail embedded in a tweet</p></div><p>The thumbnail is displayed and hyperlinked to the <a
href="http://m.youtube.com/">mobile version of YouTube</a></p><div
id="attachment_556" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-556" title="Capture7_55_41" src="http://shkspr.mobi/blog/wp-content/uploads/2009/09/Capture7_55_41.jpg" alt="Pointing to Mobile YouTube" width="480" height="320" /><p
class="wp-caption-text">Pointing to Mobile YouTube</p></div><p>When clicked on, the user is taken straight to the video&#8217;s page.</p><div
id="attachment_557" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-557" title="Capture8_35_37" src="http://shkspr.mobi/blog/wp-content/uploads/2009/09/Capture8_35_37.jpg" alt="The Destination" width="480" height="320" /><p
class="wp-caption-text">The Destination</p></div><p>There were three main issues with this code</p><ol><li>How do we extract the video&#8217;s ID from the URL? YouTube video IDs contain alphanumeric character and the &#8211; and _ characters. They can also have other parameters passed.  There can also be text <em>after</em> the URL.  The regular expression above takes care of them.</li><li>How do we get the thumbnail?  Previously, I had been using the image URL given in the m.YouTube page &#8211; something like http://i.ytimg.com/vi/plvE4882B7Y/default.jpg?w=80&amp;h=60 &#8211; however those URLs now need signing. So, using the <a
href="http://code.google.com/apis/youtube/2.0/reference.html">YouTube API</a>, I took a look at the Video Information XML file &#8211; http://gdata.youtube.com/feeds/api/videos/plvE4882B7Y &#8211; it showed that all videos have a full sized thumbnail &#8211; http://i.ytimg.com/vi/plvE4882B7Y/0.jpg and a mobile friendly thumbnail &#8211; http://i.ytimg.com/vi/plvE4882B7Y/1.jpg</li><li>How do we link to the mobile version of YouTube?  There are two ways to do this &#8211; either allow YouTube to detect the User-Agent and redirect based on that, or simply point to the mobile version.  While a regular YouTube link looks like http://<strong>www</strong>.youtube.com/watch?v=plvE4882B7Y the mobile one simply substitutes www for m : http://<strong>m</strong>.youtube.com/watch?v=plvE4882B7Y</li></ol><p>TODO</p><p>For phones which support playing YouTube videos inline (Android, some Nokias etc) I may actually embed the video, rather than just link to it.  I may also detect Desktop Browsers and send them to the regular version of YouTube.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=554&amp;md5=de8ddff81648a904b8bc7dc699b96693" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2009/09/embedding-mobile-youtube-in-dabr-twitter/feed/</wfw:commentRss> <slash:comments>3</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=554&amp;md5=de8ddff81648a904b8bc7dc699b96693" type="text/html" /> </item> <item><title>Expanding URLs in Dabr / Twitter</title><link>http://shkspr.mobi/blog/index.php/2009/09/expanding-urls-in-dabr-twitter/</link> <comments>http://shkspr.mobi/blog/index.php/2009/09/expanding-urls-in-dabr-twitter/#comments</comments> <pubDate>Tue, 08 Sep 2009 11:46:55 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[/etc/]]></category> <category><![CDATA[bit.ly]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[longurlplease]]></category> <category><![CDATA[twitter]]></category> <category><![CDATA[url]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/?p=461</guid> <description><![CDATA[I hate shortened URLs with a passion.  It makes it hard to see what a link is and whether I&#8217;ve visited it before.  If they fail &#8211; like tr.im threatened to do &#8211; you lose your links with no way to see where they once went. So, hurrah for LongURLPlease &#8211; a service which takes <a
href='http://shkspr.mobi/blog/index.php/2009/09/expanding-urls-in-dabr-twitter/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>I hate shortened URLs with a passion.  It makes it hard to see what a link is and whether I&#8217;ve visited it before.  If they fail &#8211; <a
href="http://blog.tr.im/post/159369789/tr-im-r-i-p" class="broken_link">like tr.im threatened to do</a> &#8211; you lose your links with no way to see where they once went.</p><p>So, hurrah for <a
href="http://www.longurlplease.com/">LongURLPlease</a> &#8211; a service which takes those horrid little links and turns them in to full sized URLs.</p><p>Here&#8217;s the basic code in PHP to use the service.</p><blockquote><p>[php]<br
/> function long_url($shortURL)<br
/> {<br
/> //Use the LongURLPlease API<br
/> $url = &quot;http://www.longurlplease.com/api/v1.1?q=&quot; . $shortURL;</p><p> //Set up CURL<br
/> $curl_handle=curl_init();<br
/> curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);<br
/> curl_setopt($curl_handle,CURLOPT_URL,$url);</p><p> //Get the JSON response<br
/> $url_json = curl_exec($curl_handle);</p><p> //Close the connection<br
/> curl_close($curl_handle);</p><p> //Decode the JSON<br
/> $url_array = json_decode($url_json,true);</p><p> //Get the Long URL out of the array<br
/> $url_long = $url_array[&quot;$shortURL&quot;];</p><p> if ($url_long == null) //The service couldn&#8217;t find a long URL<br
/> {<br
/> return $shortURL;<br
/> }</p><p> return $url_long;<br
/> }<br
/> [/php]</p></blockquote><p>So, how should this be displayed to the user in Dabr?</p><p>There are three possibilities.</p><h2>Display</h2><p>[html]&lt;a href=&quot;short.url/foo&quot;&gt;VeryVeryLong.Url/Bar&lt;/a&gt;[/html]</p><p>This keeps the redirect, but it displays the full URL for the user.</p><h3>Pros.</h3><ul><li>Get to see what the content is.</li><li>Allows the short URL service to record hits etc.</li></ul><h3>Cons.</h3><ul><li>Won&#8217;t highlight if you&#8217;ve already visited it.</li><li>May cause problems if the VeryLong.Url is too long for the screen.</li></ul><h2>All Change</h2><p>[html]&lt;a href=&quot;VeryVeryLong.Url/Bar&quot;&gt;VeryVeryLong.Url/Bar&lt;/a&gt;[/html]<br
/> This completely replaces the short URL.</p><h3>Pros.</h3><ul><li>Hurrah! No more silly URLs.</li><li>Will highlight if you&#8217;ve already visited it.</li><li>You can seen what you&#8217;re about to click on.</li></ul><h3>Cons.</h3><ul><li>Breaks any statistics management the short URL service was performing (is this a con? Surely the receiving website should be recording such details?)</li><li>May cause problems if the VeryLong.Url is too long for the screen.</li></ul><h2>Background</h2><p>[html]&lt;a href=&quot;VeryVeryLong.Url/Bar&quot;&gt;short.url/foo&lt;/a&gt;[/html]</p><h3>Pros.</h3><ul><li>Will highlight if you&#8217;ve already visited it.</li><li>You can seen what you&#8217;re about to click on if you hover over the URL.</li><li>Won&#8217;t cause problems if the URL is too long for the screen.</li></ul><h3>Cons.</h3><ul><li>Breaks any statistics management the short URL service was performing (is this a con? Surely the receiving website should be recording such details?)</li><li>User can&#8217;t immediately see what they&#8217;re about to click on.</li></ul><h2>Conclusions</h2><p>I prefer replacing the URL completely.  I see no value in the various short URL services.  The stats that they gather don&#8217;t seem any better that those your webserver can provide.</p><p>However, long URLs can be messy &#8211; especially on small screened devices.</p><div
id="attachment_467" class="wp-caption aligncenter" style="width: 490px"><img
class="size-full wp-image-467" title="Capture12_17_3" src="http://shkspr.mobi/blog/wp-content/uploads/2009/09/Capture12_17_3.jpg" alt="Long URLs on a BlackBerry" width="480" height="320" /><p
class="wp-caption-text">Long URLs on a BlackBerry</p></div><p>So, which do you prefer?</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=461&amp;md5=ec4ef192b610d654c8962242a6329db2" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2009/09/expanding-urls-in-dabr-twitter/feed/</wfw:commentRss> <slash:comments>7</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=461&amp;md5=ec4ef192b610d654c8962242a6329db2" type="text/html" /> </item> <item><title>Twestival &#8211; The Good, The Bad and The Ugly</title><link>http://shkspr.mobi/blog/index.php/2009/02/twestival-the-good-the-bad-and-the-ugly/</link> <comments>http://shkspr.mobi/blog/index.php/2009/02/twestival-the-good-the-bad-and-the-ugly/#comments</comments> <pubDate>Sun, 15 Feb 2009 08:43:00 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[/etc/]]></category> <category><![CDATA[#awesome09]]></category> <category><![CDATA[bbc]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[LDNtwestival]]></category> <category><![CDATA[twestival]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/index.php/2009/02/twestival-the-good-the-bad-and-the-ugly/</guid> <description><![CDATA[Woooo! Twestival! YAYAYAYAY! Errr&#8230; Well, no. Not really. After the success of last year&#8217;s London Twestival, I thought this one would be even better. Looks like I was wrong. Let&#8217;s start with&#8230; The GoodOnce again, it&#8217;s impossible to feel anything other that gratitude and humbleness in the face of the sheer amount of effort, determination <a
href='http://shkspr.mobi/blog/index.php/2009/02/twestival-the-good-the-bad-and-the-ugly/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>Woooo! <a
href="http://twestival.com/">Twestival</a>! YAYAYAYAY! Errr&#8230; Well, no. Not really.  After the success of last year&#8217;s London Twestival, I thought <a
href="http://london.twestival.com/">this one</a> would be even better. Looks like I was wrong.  Let&#8217;s start with&#8230;</p><p><span
style="font-weight: bold;">The Good</span><br
/>Once again, it&#8217;s impossible to feel anything other that gratitude and humbleness in the face of the sheer amount of effort, determination and self-sacrifice that goes in to making a &#8220;happening&#8221; on this scale.  Kudos to <a
href="http://amandarose.com/">Amanda</a>, <a
href="http://www.puddingrelations.com/">Ben</a> and everyone else who worked so hard.</p><p>Getting people all over the world to raise (hopefully) a million bucks for <a
href="http://www.charitywater.org/twestival/">Charity : Water</a> certainly goes on my <a
href="http://www.tarekesber.com/?p=257">#Awesome09</a> list.</p><p>As always &#8211; it&#8217;s the people you meet which make the evening.  It&#8217;s bizarre trying to recognise someone from a 48*48 pixel avatar &#8211; this often means spending a large portion of the time staring at random strangers&#8217; chests trying to read a name-badge.</p><p>There&#8217;s a myth that in some languages the word &#8220;stranger&#8221; translates into &#8220;Friend I&#8217;ve Not Yet Met&#8221; &#8211; so it is with twitter.  I was surrounded with people who I felt I knew intimately, yet I&#8217;d never so much as shaken their hand before tonight.</p><p>The net result of all this was that everyone was <span
style="font-style: italic;">so friendly</span>. Any other venue in London, if you accidentally spilled someone&#8217;s drink you&#8217;d get stabbed.  Here, you were more likely to get a hug.</p><p>Which was nice.</p><p><span
style="font-weight: bold;">The Bad</span><br
/>I&#8217;m obviously a grumpy old man &#8211; but here&#8217;s my run down of what people could do to improve the next London Twestival.<ol><li>I appreciate that there&#8217;s a paucity of cheap / free venues in London on a Thursday night.  But if you&#8217;re going to pick one a mile away from the tube, in some grim back street, it might be an idea to put up a few signs directing people &#8211; or even a few volunteers.</li><li>The queuing system sucked.  I don&#8217;t know what the hold up was at the front, but it took us around 45 minutes to get in.  That certainly put a dampener on my evening.</li><li>You can&#8217;t control the weather &#8211; but you can plan for it. <a
href="http://www.flickr.com/photos/webwandering/3275721712/in/set-72157613726776968/"> If you can see that there&#8217;s a long queue of people standing about in the snow</a> &#8211; go out and explain to them what&#8217;s going on.  People are happier when they know <span
style="font-style: italic;">why</span> there&#8217;s a delay and what&#8217;s being done about it.</li><li>If there&#8217;s a long queue of bored and hungry people, bring out some food or (non-alcoholic) drink.  I saw lots of organisers wandering past the queue with crates of food.  They didn&#8217;t even throw so much as a bag of Doritos our way.</li><li>Twitter is a meritocracy.  If you&#8217;re the organiser and you spot one of your mates &#8211; <a
href="http://twitter.com/willhowells/statuses/1203825964">or a BBC journalist</a> &#8211; in the queue, <span
style="font-style: italic;">don&#8217;t let them jump the queue!</span> It&#8217;s the sort of thing which builds resentment.</li><li>Actually check the tickets.  By the time I arrived at the front, the notion of a ticketing system had all but been abandoned.  There were funky <a
href="http://2d-code.co.uk/melbourne-twestival-ticket-2009/">2D Barcodes</a> on there which should have speeded up the check-in process.</li><li>Either pre-print name-badges in big letters, or make sure you have enough thick black markers on the front desk.  Loads of people had been reduced to writing their badges in biro. This made it really hard to read who someone was.</li><li>Have more than 2 people on the coat check.  I&#8217;m here to part and meet people, not join another queue just to hand over a coat (see point 12)</li><li>Keep food, drink and raffles in a fixed location.  I saw lots of people chasing after the last reported sighting of the raffle tickets and the burgers. If people can&#8217;t find you, they can&#8217;t give you their money.</li><li>The food.  What a farce.  Despite being given a ticket for food, I couldn&#8217;t find anywhere to spend it &#8211; nor could anyone else.  There was a chap wandering around giving burgers away &#8211; but he didn&#8217;t know where the rest of the food was, or if there was anything vegetarian available.  I subsided on a few dropped Liquorish Allsorts. Rubbish.</li><li>The raffle. Grrr. Possibly the most annoying thing about the night.</li><ul><li>Hard to find raffle tickets</li><li>No validation on the tickets (I saw people dropping <span
style="font-style: italic;">both</span> halves of their ticket in and only keeping one stub from the several they purchased.)</li><li>Filling in the tickets took an age.  Not sure how this could be improved &#8211; certainly give the raffle sellers more pens so that multiple people can fill in tickets at the same time.</li><li>Timing was bad. The<a
href="http://london.twestival.com/raffle/"> website said you had to stick around to claim your prize</a>. A bit unfair given that our names and phone numbers were on there.</li><li>Lousy rules &#8211; <a
href="http://london.twestival.com/raffle/">the website said you had to stick around until &#8220;halfway&#8221; through the evening&#8221; for the draw</a>. I&#8217;m obviously an old man because I don&#8217;t consider after 2300 to be halfway through the evening.  We don&#8217;t all work in PR &#8211; taking Friday as a hangover day isn&#8217;t always an option.</li><li>To make matters worst, the first few prizes were announced &#8211; then the raffle was seemingly abandoned! I got bored at this point and left.</li><li>I should point out that I&#8217;m probably just<a
href="http://twitter.com/edent/statuses/1204426015"> bitter that I didn&#8217;t win the Lego Death Star</a>&#8230;</li></ul><p><li>Coat check. When you have &#8220;tired and emotional&#8221; party goers who just want to catch the last train back home &#8211; put more than two people on the coat check.  Make sure that the coats are in some sort of order so your coat can be found.</li><li>The final testament as to why I&#8217;m an old man. The music.  Don&#8217;t get me wrong, I loved the music, but the point of twitter is that it&#8217;s a conversation. It&#8217;s rather hard to have a conversation when the music drowns out everything.</li></ol><p><span
style="font-weight: bold;">The Ugly<br
/></span><span>It </span><span>would</span><span> appear that I am genetically unable to be photographed in a flattering light.</p><p><a
onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/webwandering/3275698960/"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 334px; height: 500px;" src="http://farm4.static.flickr.com/3497/3275698960_fee06159e6.jpg?v=0" alt="" border="0" /></a> Photo by <a
href="http://www.webwandering.com/">Webwandering</a>.</p><p><a
onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/anniemole/3275508007/"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 500px; height: 331px;" src="http://farm4.static.flickr.com/3378/3275508007_bfb3d19337.jpg?v=0" alt="" border="0" /></a>Photo by <a
href="http://london-underground.blogspot.com/2009/02/twestival-2009.html">Annie Mole</a>.</p><p><a
onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/anniemole/3275508335/"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 500px; height: 323px;" src="http://farm4.static.flickr.com/3496/3275508335_73e81386ea.jpg?v=0" alt="" border="0" /></a></span><span>Photo by <a
href="http://london-underground.blogspot.com/2009/02/twestival-2009.html">Annie Mole</a>.</span><br
/><span><br
/>Although it was very nice of <a
href="http://twitter.com/LJRich">LJRich</a> to <a
href="http://news.bbc.co.uk/1/hi/technology/7888740.stm">interv<br
/> iew me for the BBC</a>!<br
/><img
src="http://shkspr.mobi/blog/uploaded_images/lj1-788959.png" alt="" border="0" /><img
src="http://shkspr.mobi/blog/uploaded_images/lj2-754816.png" alt="" border="0" /><img
src="http://shkspr.mobi/blog/uploaded_images/lj3-752354.png" alt="" border="0" /></p><p>Amazing to see nearly everyone in that video using the fantastic <a
href="http://m.dabr.co.uk/">Dabr</a> for tweeting from their phones..</p><p><span
style="font-weight: bold;">So&#8230;</span><br
/>I hope I haven&#8217;t upset anyone with this post. I am genuinely in awe of the organisers for getting a global event of the ground and raising a whole heap for charity. I just wish that a bit more logistical effort had gone in to the London Twestival.</p><p>TTFN.</span><span
style="font-weight: bold;"><br
/></span></p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=28&amp;md5=2328016afd7fefd463b477ef280cdc7c" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2009/02/twestival-the-good-the-bad-and-the-ugly/feed/</wfw:commentRss> <slash:comments>2</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=28&amp;md5=2328016afd7fefd463b477ef280cdc7c" type="text/html" /> </item> <item><title>Mobile Twitter on the Blackberry</title><link>http://shkspr.mobi/blog/index.php/2008/10/mobile-twitter-on-the-blackberry/</link> <comments>http://shkspr.mobi/blog/index.php/2008/10/mobile-twitter-on-the-blackberry/#comments</comments> <pubDate>Mon, 06 Oct 2008 09:45:00 +0000</pubDate> <dc:creator>Terence Eden</dc:creator> <category><![CDATA[mobile]]></category> <category><![CDATA[usability]]></category> <category><![CDATA[blackberry]]></category> <category><![CDATA[dabr]]></category> <category><![CDATA[slandr]]></category> <category><![CDATA[twitstat]]></category> <category><![CDATA[twitter]]></category><guid
isPermaLink="false">http://shkspr.mobi/blog/index.php/2008/10/mobile-twitter-on-the-blackberry/</guid> <description><![CDATA[Twitter == Addictive. CrackBerry == Addictive. Twitter + BlackBerry == toxic levels of addictivenessicity. This is a quick review of some of the mobile Twitter interfaces and how well they work on the BlackBerry. I&#8217;m just looking at mobile web interfaces (for now). Mobile Twitter First off &#8211; the official mobile Twitter interface &#8211; http://m.twitter.com <a
href='http://shkspr.mobi/blog/index.php/2008/10/mobile-twitter-on-the-blackberry/'>[...]</a>]]></description> <content:encoded><![CDATA[<p>Twitter == Addictive. CrackBerry == Addictive. Twitter + BlackBerry == toxic levels of addictivenessicity.</p><p>This is a quick review of some of the mobile Twitter interfaces and how well they work on the BlackBerry.  I&#8217;m just looking at mobile web interfaces (for now).</p><h2>Mobile Twitter</h2><p>First off &#8211; the official mobile Twitter interface &#8211; <a
href="http://m.twitter.com/">http://m.twitter.com</a></p><p><a
href="http://shkspr.mobi/blog/uploaded_images/twit-766453.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twit-766451.png" border="0" alt="" /></a><br
/> It&#8217;s fairly plain and uninteresting.  At the bottom of the screen, we see a few options.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/m.twit.bottom-766456.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/m.twit.bottom-766455.png" border="0" alt="" /></a></p><p>You can even perform basic follow / unfollow activity.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/m.twit.follow-783836.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/m.twit.follow-783831.png" border="0" alt="" /></a></p><p>At first glance, it seems ok.  Most of the basic functionality is there.  If all you want to do is read your stream and post &#8211; it&#8217;s fine.</p><p>But! Thanks to the Twitter API, there are a plethora of different interfaces.</p><h2>Slandr</h2><p>Let&#8217;s look at <a
href="http://m.slandr.net/">Slandr</a>.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/m.slandr.top-746990.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/m.slandr.top-746988.png" border="0" alt="" /></a><br
/> Wow! Straight away we can see the difference.  Avatars are displayed &#8211; as are adverts &#8211; and there&#8217;s a whole heap of extra functionality.  Those icons beside a person&#8217;s name are &#8220;reply&#8221;, &#8220;Direct Message&#8221;, &#8220;Favourite&#8221; and &#8220;Retweet&#8221;.  It really saves the wear and tear on the thumbs to have quick access to those functions.<br
/> There&#8217;s even more at the bottom.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/m.slandr.bottom-777086.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/m.slandr.bottom-777084.png" border="0" alt="" /></a></p><p>Conspicuous by its absence on the official interface is &#8220;Replies&#8221;.  Slandr quickly gives you access to any messages you&#8217;ve been sent &#8211; either directly or in your friend stream.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/m.slandr.replies-777089.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/m.slandr.replies-777088.png" border="0" alt="" /></a></p><p>There&#8217;s also a wicked search page.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/m.slandr.search-708347.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/m.slandr.search-708345.png" border="0" alt="" /></a><a
href="http://shkspr.mobi/blog/uploaded_images/m.slandr.smc-708352.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/m.slandr.smc-708350.png" border="0" alt="" /></a></p><p>The only problem with it, is that you cannot bookmark your searches.  So, if you&#8217;re following a particular subject of hashtag, you&#8217;re out of luck.  You&#8217;ll also notice that hashtags aren&#8217;t clickable.</p><h2>Twitstat Mobile</h2><p><a
href="http://www.twitstat.com/">Twitstat</a> is a great site for gathering stats about your twittering. <a
href="http://www.twitstat.com/m/index.php">Their mobile interface</a> is also pretty good.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/twitstat-792324.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twitstat-792323.png" border="0" alt="" /></a><br
/> It&#8217;s clean and well spaced.  Although you may see fewer tweets at once, it&#8217;s much easier to read than other interfaces.</p><p>The little icons allow you to favourite, reply and &#8211; oddly &#8211; &#8220;LOL&#8221; someone. Disappointingly, they rely on JavaScript.  I keep JS switched off on my BlackBerry for performance reasons.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/twitstat.js-753276.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twitstat.js-753274.png" border="0" alt="" /></a></p><p>On to the features that make Twitstat stand out.<br
/> Reply highlighting.  When scrolling through a load of tweets, it&#8217;s easy to miss ones directed at you.  Twitstat helpfully colours the tweets to make them stand out.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/twitstat.highlight-729359.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twitstat.highlight-729356.png" border="0" alt="" /></a></p><p>The &#8220;ego&#8221; link will return all the tweets that feature your name.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/twitstat.ego-706804.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twitstat.ego-706800.png" border="0" alt="" /></a></p><p>Hashtags are clickable <strong>and</strong> can be bookmarked.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/twitstat.hash-729354.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twitstat.hash-729351.png" border="0" alt="" /></a></p><p>Anyone who follows twitstat, will have generated for them some details about their tweeting.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/twitstat.stat-769840.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twitstat.stat-769838.png" border="0" alt="" /></a><br
/> I post a lot about beer&#8230;</p><p>Not only will Twitstat expand some links run through URL shortening services, it will also place flickr pictures in-line.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/twitstat.flickr-706810.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/twitstat.flickr-706807.png" border="0" alt="" /></a><br
/> This is probably the most useful aspect. It&#8217;s so annoying to have to click through to find out what someone thinks is cool.  Much better to see the full URL so that I can determine if it&#8217;s a link I want to visit, if I&#8217;ve seen it before or<br
/> if it&#8217;s BlackBerry friendly.</p><h2>Dabr</h2><p>Finally, on to <a
href="http://dabr.co.uk/">dabr</a>.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/dabr-730143.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/dabr-730141.png" border="0" alt="" /></a><br
/> Lots of options &#8211; but the screen is quite cluttered.  Again, it has the ability to reply, DM, favourite and retweet.</p><p>The basic search functionality is good.  It allows bookmarking.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/dabr.search-755249.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/dabr.search-755247.png" border="0" alt="" /></a><br
/> Hashtags are also clickable.</p><p>Profile pages allow you to see followers, which is a nice touch.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/dabr.profile-755246.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/dabr.profile-755244.png" border="0" alt="" /></a></p><p>It does have a couple of bugs.  The input field isn&#8217;t limited to 140 characters. This means you don&#8217;t get notified if your tweet is too long.  It also claims to do reply colouring &#8211; but I can&#8217;t see any colouring in the BlackBerry browser.<br
/> <a
href="http://shkspr.mobi/blog/uploaded_images/dabr.bugs-730139.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img
style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://shkspr.mobi/blog/uploaded_images/dabr.bugs-730137.png" border="0" alt="" /></a></p><h2>Conclusion</h2><p>All of the alternatives are better than the standard m.twitter.com interface.  I find myself using Twitstat for reading and searching &#8211; but as it doesn&#8217;t allow me to follow new users, I flick back to Slandr quite a bit.  Twitstat has cooler features, but Slandr is more useable.  Dabr is fine &#8211; but it doesn&#8217;t have anything to make it stand out from the others.</p><h2>Geek Stuff</h2><p>These device used was a BlackBerry 8800, running firmware 4.5.0.37. The screenshots were taken using <a
href="http://www.blackberryfreaks.com/JL_Cmder.html">JL_Cmder</a>.</p><p><a
href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=36&amp;md5=eb6024ed84be09e439a6dbe361e69cbb" title="Flattr" target="_blank"><img
src="http://shkspr.mobi/blog/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded> <wfw:commentRss>http://shkspr.mobi/blog/index.php/2008/10/mobile-twitter-on-the-blackberry/feed/</wfw:commentRss> <slash:comments>3</slash:comments> <atom:link rel="payment" href="http://shkspr.mobi/blog/?flattrss_redirect&amp;id=36&amp;md5=eb6024ed84be09e439a6dbe361e69cbb" type="text/html" /> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced (Requested URI is rejected)

Served from: www.shkspr.mobi @ 2012-02-08 06:39:48 -->
