{"id":442,"date":"2009-01-11T21:00:11","date_gmt":"2009-01-11T21:00:11","guid":{"rendered":"http:\/\/dalelane.co.uk\/blog\/?p=442"},"modified":"2009-01-11T21:00:11","modified_gmt":"2009-01-11T21:00:11","slug":"revisiting-my-twitter-glossary","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=442","title":{"rendered":"Revisiting my Twitter Glossary"},"content":{"rendered":"<p>Have you ever read someone&#8217;s tweet and not known what they are on about?<\/p>\n<p>At IBM HackDay 5, I played around with an idea for a Twitter hack &#8211; a Twitter Glossary that would let users define terms they regularly use in tweets. The idea was that followers would see the definitions appearing as tooltips over those words when they appear in tweets. <\/p>\n<p><img decoding=\"async\" src=\"http:\/\/dalelane.co.uk\/blog\/post-images\/090111-twitter.gif\" alt=\"screenshot of the firefox extension\"\/><\/p>\n<p>I described <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=259\">the idea in more detail here<\/a>. It&#8217;s now <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=442#tryit\">available for anyone to try<\/a>.<\/p>\n<p><!--more--><strong>The original hack<\/strong><\/p>\n<p>In the tradition of hackdays, I had a day to knock something together. At work, we have an internal service which lets you deploy a <a href=\"http:\/\/en.wikipedia.org\/wiki\/LAMP_(software_bundle)\" target=\"_blank\">LAMP stack<\/a> on request &#8211; ideal for developers wanting somewhere to try out web apps. I used MySQL to store the definitions, PHP to handle translating terms into definitions, and <a href=\"http:\/\/www.greasespot.net\/\" target=\"_blank\">Greasemonkey<\/a> to modify the twitter.com homepage, adding definitions as tooltips.<\/p>\n<p>This meant the app was only available on the IBM intranet, but it was enough to show that the idea could work.<\/p>\n<p>After <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=259\">blogging about it<\/a> at the time, a few people asked if I&#8217;d make it available outside of IBM. But I couldn&#8217;t afford to pay for hosting it (I only have a single MySQL database where this blog is hosted, and didn&#8217;t fancy adding to the wordpress database). <\/p>\n<p><img decoding=\"async\" src=\"http:\/\/dalelane.co.uk\/blog\/post-images\/090111-twitter3.gif\" alt=\"screenshot of the firefox extension\"\/><\/p>\n<p><strong>Porting the app to Google App Engine<\/strong><\/p>\n<p>Fast-forward a year, and I was asked again. The difference now is <a href=\"http:\/\/code.google.com\/appengine\/\" target=\"_blank\">Google App Engine<\/a>. This wasn&#8217;t an option when I wrote the original hack, but now free hosting for scalable web apps is possible.<\/p>\n<p>So on Friday night, I thought I&#8217;d try and port the original hack to run on GAE. <\/p>\n<p>It needed a little work:<\/p>\n<ul>\n<li>the PHP web service needed porting to Python<\/li>\n<li>the PHP website where users add their own definitions was ported to Python\/Django<\/li>\n<li>the MySQL database where definitions are stored needed porting to Google&#8217;s BigTable<\/li>\n<\/ul>\n<p>I also <a target=\"_blank\" href=\"http:\/\/arantius.com\/misc\/greasemonkey\/script-compiler\">compiled my original Greasemonkey script<\/a> into a stand-alone Firefox extension, so non-Greasemonkey users could give it a try.<\/p>\n<p>It was surprisingly easy &#8211; I had it all <a href=\"http:\/\/twitter.com\/dalelane\/status\/1108012329\">up and running in an evening<\/a>, and still found time for quite a bit of <a href=\"http:\/\/www.callofduty.com\/profile\/3605410\/stats\/\" target=\"_blank\">Call of Duty 5<\/a> \ud83d\ude42<\/p>\n<p>There was one thing that needed changing though&#8230;<\/p>\n<p><strong>Security &#8211; proving who you are on twitter<\/strong><\/p>\n<p>The original hack let anyone add definitions for any twitter user. The other nice thing of hosting it within the IBM intranet is that I could trust users a little more. While testers will do what they can to give it a kick, ultimately I didn&#8217;t worry too much about malicious users.<\/p>\n<p>Moving the hack to the big bad Internet meant I needed to worry a little more about authentication &#8211; in particular, people adding definitions to other twitter users&#8217; glossaries. <\/p>\n<p>The <a href=\"http:\/\/apiwiki.twitter.com\/\" target=\"_blank\">twitter API<\/a> doesn&#8217;t have a nice way of doing this without asking for someone&#8217;s twitter password. Given the recent <a href=\"http:\/\/bokardo.com\/archives\/the-curious-case-of-twply-and-twitter\/\" target=\"_blank\">uproar about Twply<\/a>, that probably wouldn&#8217;t have been the best idea. \ud83d\ude42<\/p>\n<p>I threw together a workaround &#8211; when you sign-up the site selects a random word and asks you to tweet that in an @reply to <a href=\"http:\/\/twitter.com\/twitglossary\" target=\"_blank\">twitglossary<\/a>. As long as your tweets are unprotected, the site can verify that you really sent the tweet and so you are who you say you are. <\/p>\n<p>By adding &#8220;<code>login: required<\/code>&#8221; to the <a target=\"_blank\" href=\"http:\/\/code.google.com\/appengine\/docs\/configuringanapp.html#Requiring_Login_or_Administrator_Status\">site&#8217;s manifest<\/a>, I make the Google App Engine platform require users to login with a Google user account. This means I can cache someone&#8217;s twitter ID, without needing people to go through the @reply process every time they want to use the site. As users only enter their password on a google.com webpage (which passes the auth token) my code never sees people&#8217;s passwords. <\/p>\n<p><strong><a name=\"tryit\">Ready to try<\/a><\/strong><\/p>\n<p>It&#8217;s live now, so please give it a try.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/dalelane.co.uk\/blog\/post-images\/090111-twitter2.gif\" alt=\"screenshot of the link added to twitter.com\" vspace=5 hspace=10 align=\"right\"\/>Install the <a href=\"http:\/\/twitterglossary.appspot.com\/static\/twitterglossary.xpi\">Twitter Glossary Firefox plugin<\/a>, then visit <a href=\"http:\/\/twitter.com\" target=\"_blank\">http:\/\/twitter.com<\/a> to see twitter with definitions added. (<em>You don&#8217;t need to signup or authenticate anything to do this &#8211; authentication is only needed to modify a user&#8217;s Twitter glossary<\/em>).<\/p>\n<p>You should also see that the right column has a new &#8220;Twitter Glossary&#8221; item with a link to a page where you can add your own twitter definitions.<\/p>\n<p>Clicking on this takes you to <a href=\"http:\/\/twitterglossary.appspot.com\/\">the Twitter Glossary page<\/a> where (once you&#8217;ve authenticated) you will be able to add definitions for your own tweets.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Have you ever read someone&#8217;s tweet and not known what they are on about? At IBM HackDay 5, I played around with an idea for a Twitter hack &#8211; a Twitter Glossary that would let users define terms they regularly use in tweets. The idea was that followers would see the definitions appearing as tooltips [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[151],"class_list":["post-442","post","type-post","status-publish","format-standard","hentry","category-code","tag-twitter"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/442","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=442"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/442\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=442"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=442"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=442"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}