Archive for the ‘twitter’ Category
CWOB without tweets
February 7th, 2010 at 8:49 am
Looking through my RSS reader this morning, I noticed that Andy Ihnatko has installed a WordPress plugin that collects and summarizes his Twitter stream from the previous day and publishes it as a blog post on the Celestial Waste of Bandwidth.1 Since I
- subscribe to his RSS feed
- follow him on Twitter, and
- don’t feel the need to read everything twice,
I’ve used Yahoo! Pipes to create a customized feed that filters out the Twitter summary posts.

The URL for the feed is at this link.
Regular readers of this blog may be arching their eyebrows. Didn’t Dr. Drang inflict exactly the same sort of redundancies on us last year? Yes, I did, and I’m sorry for it. In my defense, I’ll point out that I
- linked to Pattrick Mosby’s Pipes filter, which filtered out the posts with my tweets;
- later provided my own Pipes filters that did the same thing; and
- eventually dropped the Twitter posts entirely.
I wouldn’t be surprised to see Andy go through the same steps.
Update 2/17/10
I think Andy has turned off the daily Twitter update, but a few days ago a weekly Twitter summary showed up in my RSS reader. I’ve reworked the above-linked Yahoo! Pipes filter to get rid of those, too. The screen shot shows the current filter.
-
Ah, I remember when it was just a Colossal Waste of Bandwidth. ↩
Dr. Twoot and Twitter’s new retweeting
November 19th, 2009 at 11:51 pm
Last night, I finally got in on the beta group for Twitter’s new retweeting system, just one day before it went live for everyone. I do and do for you, Twitter, and this is the thanks I get? Wait’ll you have to work with a web service.
I discussed the new retweeting a couple of months ago when it came out in its first incarnation and then, a week later, when it was considerably revised. Dr. Twoot, my jQuery/Fluid-based Twitter client1, works with the new API, and I thought it worth spending a little time describing it and explaining the design choices I made.
(Lots of people don’t like the new retweeting, and I can understand why—unlike the old handcrafted retweets, the new ones don’t give you flexibility to include your own comment. But I also understand why Twitter did what it did. If you’ve ever looked through the Trending Topics, you’ll see that there’s a lot of retweeting out there, and the great majority of users just do plain retweets. The new API gives them a simple, one-click method to do what they want. Yes, these are the kind of people who keep re-re-re-forwarding emails, but Twitter needs to keep them happy if it wants to maintain its huge user numbers. The new retweeting is here to stay, and it’s time to adapt to it.)
Let me start by saying that it’s never been my intention to make Dr. Twoot a full-featured Twitter client; it’s just for reading the people I follow and writing my own tweets. This covers at least 95% of my Twitter use. For everything else—following, unfollowing, reporting spam, etc.—I use the twitter.com page. Also, I have all links open in the default browser (Safari for me) to keep Dr. Twoot focused on tweets.
With that in mind, I wanted to change Dr. Twoot to handle four aspects of the new retweeting:
- Displaying the retweets of the people I follow.
- Creating my own retweets.
- Displaying retweets of my posts.
- Displaying my retweets.
I agree with the Twitter people that the preferred way to display the retweets of others is to show the original message with a small annotation of who retweeted it. Dr. Twoot has been doing that for a couple of months, and I’ve been happy with it, so no new code was needed.

Creating my own retweets using the new API was a simple matter of recoding the retweet button (♺) to make the new statuses/retweet call. I had already written this code back in September when the new API was announced; I just had it commented out. Last night, when the feature became available to me, I uncommented those lines and it worked the first time I tested it—a happy result due more to the simplicity of the call than to my programming skills.
The code for displaying retweets of my posts was the easiest to write, because I decided that feature didn’t belong in Dr. Twoot. My tweets already appear when I post them; I don’t need to see them again. If I really need to see who, if anyone, is retweeting me, I can go to twitter.com.
By the same logic, I didn’t want Dr. Twoot to display my own retweets. They’d be nothing more than a repetition of a message already displayed. But I did want some way showing in the original message that I had retweeted it. Here’s what I came up with:

When I retweet a message, its retweet button turns red. In this way, it acts just like the favorite button (★). Implementing this turned out to be more complicated than it should have been; it’s an area where the API could use some improvement.
Here’s the problem. When I call statuses/home_timeline, it returns this for the message I’ve retweeted (I’ll be showing the XML form even though Dr. Twoot uses JSON; the data are the same for both):
1: <status>
2: <created_at>Thu Nov 19 21:28:09 +0000 2009</created_at>
3: <id>5869348957</id>
4: <text>Majority of Republicans think Obama really lost in 2008. Even greater majority thinks Bush really won in 2000, 2004.</text>
5: <source>web</source>
6: <truncated>false</truncated>
7: <in_reply_to_status_id></in_reply_to_status_id>
8: <in_reply_to_user_id></in_reply_to_user_id>
9: <favorited>false</favorited>
10: <in_reply_to_screen_name></in_reply_to_screen_name>
11: <user>
12: <id>79797834</id>
13: <name>Roger Ebert</name>
14: <screen_name>ebertchicago</screen_name>
15: <location>Chicago</location>
16: <description>Thinker, writer and blogger, shallow and profound, correct and mistaken; film critic, Chicago Sun-Times. </description>
17: <profile_image_url>http://a3.twimg.com/profile_images/452601677/DSC_2648_2_2_normal.jpg</profile_image_url>
18: <url>http://rogerebert.suntimes.com/</url>
19: <protected>false</protected>
20: <followers_count>20079</followers_count>
21: <profile_background_color>000000</profile_background_color>
22: <profile_text_color>000000</profile_text_color>
23: <profile_link_color>454545</profile_link_color>
24: <profile_sidebar_fill_color>cfcfcf</profile_sidebar_fill_color>
25: <profile_sidebar_border_color>cfcfcf</profile_sidebar_border_color>
26: <friends_count>21</friends_count>
27: <created_at>Sun Oct 04 18:33:10 +0000 2009</created_at>
28: <favourites_count>7</favourites_count>
29: <utc_offset>-21600</utc_offset>
30: <time_zone>Central Time (US & Canada)</time_zone>
31: <profile_background_image_url>http://a3.twimg.com/profile_background_images/46080801/thirdman.jpg</profile_background_image_url>
32: <profile_background_tile>false</profile_background_tile>
33: <statuses_count>816</statuses_count>
34: <notifications>false</notifications>
35: <geo_enabled>false</geo_enabled>
36: <verified>false</verified>
37: <following>true</following>
38: </user>
39: <geo/>
40: </status>
As you can see, there’s no tag that shows I’ve retweeted this message. This is, I think, a significant and inexplicable omission. Retweeting could and should be flagged just like favoriting is (see Line 9 for the favorited flag).
To figure out whether I’ve retweeted a message, Dr. Twoot has to:
- Make a
statuses/retweets_by_mecall to get my retweets. - Go through that list and pluck out the original message IDs, putting them in an array.
- Check whether the ID of each message in the
home_timelineis in that array.
The extra call is both annoying and, given Twitter’s notorious relationship with the fail whale, potentially time-consuming. Fortunately, the comparison of the message against the array of IDs is made simple by jQuery’s inArray() function.
The updated Dr. Twoot can be found at its GitHub repository, where you can see the details of of the retweeting code in its main JavaScript file, twoot.js.
What I like about Tweetie 2
October 10th, 2009 at 10:25 pm
If you’re a Twitter and iPhone user, you surely know that the new version of the popular Twitter client, Tweetie 2, appeared in the App Store yesterday. I don’t claim to be familiar yet with all its new features, but I have found a few new things that are delightful.
First, the cut/copy/paste system now works as it should. In Tweetie 1, when looking at a posted tweet, you could select a word or the entire tweet, but nothing in between—the selection handles could not be moved. Now you can move the selection handles wherever you want, just like every other app that supports cut/copy/paste. Strictly speaking, I don’t consider this feature delightful, I consider it minimally competent and something that Tweetie 1 should have been updated to correct. But still, it’s very nice to be able to copy just what I want from a tweet.
Next is the ability to review the original tweet as you reply to it. This is a feature that Twitterrific had some time ago and was perhaps the only advantage Twitterrific had over Tweetie. Tweetie’s implementation is especially clever. To see the original tweet, put your finger in the editing area and drag down; the original tweet will appear just above your reply. When you lift your finger, the editing area will spring back up to where it was.

You’ve probably noticed that refreshing is done the same way. In the timeline view, drag down to see the refresh arrow and release to have Tweetie look for updates.

This feature works well with Tweetie’s new ability to maintain your old view between launches. In Tweetie 1, each launch of the app started with a blank screen as Tweetie polled Twitter for the 20 most recent updates of your friends. Tweetie 2 starts with what your were looking at the last time you were running it. If there are new updates or @mentions or direct messages, a little blue dot appears by the appropriate icon in the bottom toolbar.

It looks like searching has been improved, but since I almost never search (as a former educator, I find reading the tweets of the Average Twitterer really depressing) I’m not qualified to pass judgement.
I miss the chat-like balloons of Tweetie 1, but I suspect I’m one of the few who does.
The last thing I want to mention is the scrolling. Tweetie 1 was famous for its fast, smooth scrolling, and I was worried that Tweetie 2’s new features would weigh it down and make its interface a bit clunkier. No need to have worried. The scrolling is as fast and as smooth as ever, making Tweetie 2 a pleasure to use.
Twitter changes the retweet API
September 30th, 2009 at 10:17 pm
…and ruined the changes I made last week to Dr. Twoot. This little bomb dropped a few hours ago. The changes don’t appear to be in the calls your program makes, but are in the organization of the data that are returned. In a nutshell, the positions of the original tweet and the retweet have been reversed in the hierarchy.
Originally, a retweet would return something like this (in XML format):
<status>
<created_at>Fri Jun 19 22:36:52 +0000 2009</created_at>
<id>2245071380</id>
<text>Last night I dreamt that I was watching a film about someone who gradually realized they were retweeting their own death.</text>
…[snip]…
<user>
<id>25753325</id>
<name>Prabhakar Ragde</name>
<screen_name>plragde</screen_name>
…[snip]…
</user>
<retweet_details>
<retweet_id>2245122541</retweet_id>
<retweeted_at>Fri Jun 19 22:41:13 +0000 2009</retweeted_at>
<retweeting_user>
<id>3191321</id>
<name>Marcel Molina</name>
<screen_name>noradio</screen_name>
…[snip]…
</retweeting_user>
</retweet_details>
</status>
Note that the original tweet, the one with the smaller id, and its author are at the root level of the status and the retweet is buried one level deeper. Now see an example of what that’s been changed to:
<status>
<created_at>Thu Sep 24 19:41:53 +0000 2009</created_at>
<id>4349744308</id>
<text>RT @Schwarzenegger: About to go on right now to talk about AB32 and climate change. Watch at http://tweetcast.in</text>
…[snip]…
<retweeted_status>
<created_at>Thu Sep 24 19:03:30 +0000 2009</created_at>
<id>4348912569</id>
<text>About to go on right now to talk about AB32 and climate change. Watch at http://tweetcast.in</text>
…[snip]…
<user>
<id>12044602</id>
<name>Gov. Schwarzenegger</name>
<screen_name>Schwarzenegger</screen_name>
…[snip]…
</user>
</retweeted_status>
<user>
<id>44940026</id>
<name>Anita Doller</name>
<screen_name>testiverse</screen_name>
…[snip]…
</user>
</status>
The retweet and retweeter are now at the root level and the original is one level deeper.
This is a significant change. It’s not that it’s much harder to program for the new return values—it isn’t—but those of us who were anticipating the first hierarchy (which is what the API docs are still showing as I write this) will find our earlier work at odds with the new system.
I’ve created a new branch of Dr. Twoot, called retweet, to handle this latest change. I haven’t tested it fully, and probably can’t until the new retweeting goes live, but I doubt it has too many bugs. It’s working fine with the current home_timeline, anyway.
Regarding a somewhat more popular Twitter client, Loren Brichter announced this morning that the final build of Tweetie 2 was submitted to the App Store yesterday. I hope the Twitter folks gave him a heads-up about this change. If not, I bet we’ll be seeing 2.1 (but not paying for it) close on 2’s heels.
Tweetie 2
September 28th, 2009 at 11:00 pm
Earlier today Loren Brichter announced the imminent release of Tweetie 2 for the iPhone. Tweetie is the Twitter client that sort of set the standard back when it was first released. The new version will be a substantial revision; Brichter plans to release it as a separate app, not as an update to the existing Tweetie. Current Tweetie users who want Version 2 will have to pay the same $2.99 as first-time buyers.
This is, as far as I know, something new on the iPhone. Certainly every upgrade I’ve gotten so far has been free. I don’t believe the App Store even has a mechanism for non-free upgrades, which I guess is why Brichter chose to treat Tweetie 2 as an entirely new app. (There’s in-app purchasing, but as I understand it, that’s intended more for additional content, not for version upgrades.)
Which raises the issue of discounts for owners of earlier versions. Certainly most Tweetie users will be happy to pay the $3 for the many new features Brichter describes. But I wonder what will happen when developers of more expensive apps want to do a paid upgrade. OmniFocus is $20. When it goes to version 2, will its current users have to pay that much a second time? And what about those new turn-by-turn navigation apps? They’re priced like desktop applications: $50–100. Updated maps can be handled through in-app purchasing, but what will happen when the app itself is given a significant upgrade? Maybe there is some sort of provision for discounts on upgrades, but I haven’t heard of it.
I’m one of the current Tweetie owners that will not hesitate to put up another $3 for Tweetie 2. I will say, though, that I’m a bit disappointed that Tweetie 1 was abandoned before it was made fully compliant with the iPhone 3 copy-and-paste system. You can copy an entire tweet, and you can copy a single word, but you can’t move the selection handles to copy anything in between. Would have been nice if a small slice of Brichter’s time over the past few months had been devoted to fixing that bug.
Dr. Twoot and the new retweeting
September 22nd, 2009 at 10:03 pm
This morning a weird tweet showed up in Dr. Twoot.1 It was from Clint Ecker (@clint) from Ars Technica. It’s not that the topic of the tweet was weird; nor, as far as I know, is Clint Ecker. What was weird was that I don’t follow Clint Ecker, and yet there was his tweet, appearing in my stream as if I were.
A short while later, John Gruber (@gruber) mentioned that he was a beta user of Twitter’s new-style retweets, currently being tested by some of the Twitterati. The Ecker tweet was a Gruber retweet. This not only explained the weird tweet, it suggested that the new retweeting system is getting close.
If you go to the Twitter API page, you’ll see several methods marked [COMING SOON] that are all related to the new-style retweets. When the new system comes out of beta, retweeting will be a formally supported Twitter feature with its own set of data; it won’t be an ad hoc format with everyone choosing his or her own style.
In anticipation of the new retweeting, I’ve made some changes to Dr. Twoot, all of which are available at its GitHub repository. Some of the changes are usable today, some won’t be usable until the new system goes live.
First, I changed from the soon-to-be-deprecated friends_timeline method to the new home_timeline method. I think these two methods return identical results right now, but that won’t be true in the future. (The API docs on home_timeline say that friends_timeline won’t have the new retweets, but that certainly isn’t the case now. This morning Dr. Twoot was still using friends_timeline, but it picked up the new-style retweet from Gruber.) Although home_timeline is marked [COMING SOON] in the API docs, it’s working now.
Second, I changed the way new-style retweets are displayed, adding the name of the retweeter to the end. This may break if more than one of the people I follow retweets the same message, but it’s working so far.

Since I decided to prefix the retweeter’s name with “via,” I changed the Twitter client prefix from “via” to “from.”
Finally, I added lines to Dr. Twoot’s retweet function that will (I hope) follow the new API. Since this feature isn’t available to everyone yet, I have these lines commented out and haven’t been able to test them. When Twitter flips the switch on retweeting, I’ll comment out the current retweeting code, uncomment the new lines, and make sure things work the way they should.
-
You know Dr. Twoot, right? The JavaScript-based Twitter client that’s sweeping the nation? The one I’ve blogged about many, many times because I wrote it? (OK, rewrote it.) Yeah, that Dr. Twoot. ↩
Updated Twitter posting and an apology
September 12th, 2009 at 8:43 am
Let’s start with the apology. Earlier this week, RSS subscribers got repeated notices of the daily roundup of my Twitter updates. These posts are generated automatically overnight; because of a screwup on my part, two posts were being made each day and the feeds followed suit. I’m sorry about that. It took me a couple of days to figure out what was wrong, but it seems to be fixed now.
The screwup came as I was trying to make the twitterpost script more robust. When it’s working, twitterpost
- Connects to Twitter and collects my recent tweets.
- Sorts through them and retains only those that were written the previous day.
- Puts them in chronological order.
- Generates and uploads a post to the blog.
I have a launchd process set up to run twitterpost in the middle of the night to automatically generate a blog post of my deathless thoughts. But it had stopped working well.
You may recall that at the beginning of the month Twitter was quite unreliable—more so than usual. For several days in a row, twitterpost had been unable to connect when it ran, so it would just fail, and there’d be no automatic posting for that day. I’d have to run the script by hand when Twitter was responsive. To fix this problem, I rewrote twitterpost to check whether the connection was successful and try again several minutes later if it wasn’t. Here’s the new source code:
1: #!/usr/bin/python
2:
3: import twitter
4: from datetime import datetime, timedelta
5: from time import sleep
6: import pytz
7: import wordpresslib
8: import sys
9: import re
10:
11: # Parameters.
12: tname = 'drdrang' # the Twitter username
13: chrono = True # should tweets be in chronological order?
14: replies = False # should Replies be included in the post?
15: burl = 'http://www.leancrew.com/all-this/xmlrpc.php' # the blog xmlrpc URL
16: bid = 0 # the blog id
17: bname = 'drdrang' # the blog username
18: bpword = 'seekret' # not the real blog password
19: bcat = 'personal' # the blog category
20: tz = pytz.timezone('US/Central') # the blog timezone
21: utc = pytz.timezone('UTC')
22:
23: # Get the starting and ending times for the range of tweets we want to collect.
24: # Since this is supposed to collect "yesterday's" tweets, we need to go back
25: # to 12:00 am of the previous day. For example, if today is Thursday, we want
26: # to start at the midnight that divides Tuesday and Wednesday. All of this is
27: # in local time.
28: yesterday = datetime.now(tz) - timedelta(days=1)
29: starttime = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
30: endtime = starttime + timedelta(days=1)
31:
32: # Create a regular expression object for detecting URLs in the body of a tweet.
33: # Adapted from
34: # http://immike.net/blog/2007/04/06/5-regular-expressions-every-web-programmer-should-know/
35: url = re.compile(r'''(https?://[-\w]+(\.\w[-\w]*)+(/[^.!,?;"'<>()\[\]\{\}\s\x7F-\xFF]*([.!,?]+[^.!,?;"'<>()\[\]\{\}\s\x7F-\xFF]+)*)?)''', re.I)
36:
37: # A regular expression object for initial hash marks (#). These must
38: # be escaped so Markdown doesn't interpret them as a heading.
39: hashmark = re.compile(r'^#', re.M)
40:
41: ##### Twitter interaction #####
42:
43: # Get all the available tweets from the given user. If Twitter is unresponsive,
44: # wait a while and try again. If it's still unreponsive after several tries,
45: # just give up.
46: api = twitter.Api()
47: tries = 9
48: trial = 0
49: while trial < tries:
50: trial += 1
51: try:
52: statuses = api.GetUserTimeline(user=tname)
53: except:
54: print "Can't connect to Twitter on try %d..." % trial
55: sleep(15*60)
56: continue
57: break
58: if trial >= tries:
59: print 0
60: sys.exit()
61:
62: # Tweets are in reverse chronological order by default.
63: if chrono:
64: statuses.reverse()
65:
66: # Collect every tweet and its timestamp in the desired time range into a list.
67: # The Twitter API returns a tweet's posting time as a string like
68: # "Sun Oct 19 20:14:40 +0000 2008." Convert that string into a timezone-aware
69: # datetime object, then convert it to local time. Filter according to the
70: # start and end times.
71: tweets = []
72: for s in statuses:
73: posted_text = s.GetCreatedAt()
74: posted_utc = datetime.strptime(posted_text, '%a %b %d %H:%M:%S +0000 %Y').replace(tzinfo=utc)
75: posted_local = posted_utc.astimezone(tz)
76: if (posted_local >= starttime) and (posted_local < endtime):
77: timestamp = posted_local.strftime('%I:%M %p').lower()
78: # Add or escape Markdown syntax.
79: body = url.sub(r'<\1>', s.GetText()) # URLs
80: body = hashmark.sub(r'\#', body) # initial hashmarks
81: body = body.replace('\n', ' \n') # embedded newlines
82: if replies or body[0] != '@':
83: if timestamp[0] == '0':
84: timestamp = timestamp[1:]
85: tweet = '[**%s**](http://twitter.com/%s/statuses/%s) \n%s\n' % (timestamp, tname, s.GetId(), body)
86: tweets.append(tweet)
87:
88: # Obviously, we can quit if there were no tweets.
89: if len(tweets) == 0:
90: print 0
91: sys.exit()
92:
93: # A line for the end directing readers to the post with this program.
94: lastline = """
95:
96: *This post was generated automatically using the script described [here](http://www.leancrew.com/all-this/2009/07/updated-twitter-to-blog-script/).*
97: """
98:
99: # Uncomment the following 2 lines to see the output w/o making a blog post.
100: # print '\n'.join(tweets) + lastline
101: # sys.exit()
102:
103: ##### Blog interaction #####
104:
105: # Connect to the blog.
106: blog = wordpresslib.WordPressClient(burl, bname, bpword)
107: blog.selectBlog(bid)
108:
109: # Create the info we're going to post.
110: post = wordpresslib.WordPressPost()
111: post.title = 'Tweets for %s' % yesterday.strftime('%B %e, %Y')
112: post.description = '\n'.join(tweets) + lastline
113: post.categories = (blog.getCategoryIdFromName(bcat),)
114:
115: # And post it.
116: newpost = blog.newPost(post, True)
117: print newpost
The new stuff is in Lines 43-60. The connection to Twitter is now in the body of a loop. If the connection fails, the connection attempt is repeated 15 minutes later, for a maximum of 9 attempts over a two-hour period. If the connection succeeds, the process breaks out of the loop and continues on to create the post.
I tested the new twitterpost by running it with my network cable initially disconnected (Twitter wouldn’t oblige me by being down during testing). After a few loops, I’d reconnect the cable and the rest of the script would execute. It seemed to be working perfectly, so I was surprised to find the repeated posts the next day.
My first thought was that some mistake in the loop was making the script stutter. But it wouldn’t stutter when I tested it, and the connection to the blog wasn’t even in the loop. Eventually I learned that I had somehow created a second launchd process; the posts were repeated because twitterpost was being run twice each night. Killing the second launchd process eliminated the repeated post.
Update 9/15/09
Hey, it works! Last night, the script couldn’t connect to Twitter for an hour. I have it set to start at 1:15 am, but last night’s post is timestamped 2:15 am. Launching Console to look at the system log, I found this:
Sep 15 02:15:05 drang com.leancrew.twitterpost[45665]: Can't connect to Twitter on try 1...
Sep 15 02:15:05 drang com.leancrew.twitterpost[45665]: Can't connect to Twitter on try 2...
Sep 15 02:15:05 drang com.leancrew.twitterpost[45665]: Can't connect to Twitter on try 3...
Sep 15 02:15:05 drang com.leancrew.twitterpost[45665]: Can't connect to Twitter on try 4...
Sep 15 02:15:05 drang com.leancrew.twitterpost[45665]: 998
Four failures and then a success. I know the timestamps make it look like all the attempts were made at 2:15, but that’s because the script doesn’t flush its output as it runs; all the output hits the system log when script finishes. I saw the same thing when I was testing the script with the network cable disconnected.
I did my best to simulate a failed connection in my testing, and I thought it would work, but it’s still nice to see it doing what it’s supposed to in a real world situation.
Because I felt bad about sending out repeated feeds, and because I began to question the value of these automatic tweet posts, I decided to create new feeds that excluded the Twitter posts. Patrick Mosby had already done this through Yahoo! Pipes, and my first thought was to just link to his feed. But I didn’t want to be dependent on his maintaining that feed, so I just copied his work on my own Yahoo! account.

So now there are four feeds: an RSS 2.0 feed with every post, an Atom feed with every post, an RSS 2.0 feed without the Twitter posts, and an Atom feed without the Twitter posts.

I’ve never understood the niceties of RSS 2.0 v. Atom, but since WordPress and Yahoo! Pipes make it easy to provide both, that’s what I’ll do.
A personal update to Dr. Twoot
August 23rd, 2009 at 3:49 pm
Last night I pushed an update to the Dr. Twoot GitHub repository. As written, it’s of no practical use to anyone else, but it’s been very helpful to me. And the thought behind it may give you some ideas for your own work.
To review, Dr. Twoot is my JavaScript/JQuery/Fluid Twitter client, a heavily modified version of Peter Krantz’s Twoot with the features I find most useful for day-to-day Twittering. I use twitter.com for infrequent actions like following, unfollowing, and searching but Dr. Twoot for all my reading and writing.
A few months ago, I added Twitter-based commenting to the blog. Clicking the Comment via Twitter link at the bottom of a post will take you to twitter.com and enter something like “@drdrang #770∀ ” to the tweet field. The hashtag identifies the number of the post being commented on, and the ∀ at the end of the hashtag is the mathematical symbol meaning “for all,” which is reasonably close to the name of this blog and should distinguish its comments from other numeric hashtags.
This commenting system—the idea for which I stole from Dan Sandler—has worked well for a low-traffic site like mine, but I often found myself wanting to refer back to the original post before responding to a comment. The easiest way to do that would be to turn the hashtag into a link so it could be clicked on. That’s the change I added last night. Here’s what it looks like:

Clicking the #919∀ will open in my default browser the post @wilshipley is commenting on. A small improvement, but one that will save me more time than it took to implement.
Since this is not a feature anyone else would have a direct use for, I added a global ALL_THIS flag near the top of the code in twoot.js. Comment hashtags are converted to links only if that flag is set to true. The link is created in the htmlify function of twoot.js:
1: function htmlify(body, allThisLinks) {
2: // handle links
3: body = body.replace(/((https?|ftp):\/\/[^ \n]+[^ \n.,;:?!&'"’”)}\]])/g, '<a href="$1">$1</a>');
4: // handle Twitter names
5: body = body.replace(/[\@]+([A-Za-z0-9-_]+)/g, '<a href="http://twitter.com/$1">@$1</a>');
6: // turn newlines into breaks
7: body = body.replace(/\n/g, '<br />');
8: // handle references to And now it's all this
9: if (allThisLinks){
10: body = body.replace(/#(\d+)∀/, '<a href="http://www.leancrew.com/all-this/?p=$1">#$1∀</a>');
11: }
12: return body;
13: }
The value of ALL_THIS is passed as the second argument to htmlify when it’s called.
Twitpocalypse Now
June 13th, 2009 at 10:50 am
So the Twitpocalypse claimed two prominent Twitter clients, Twitterrific (the iPhone version) and Tweetie (not sure which version—maybe both). Hard to believe that professional programmers were caught by something that was both obvious and well-publicized.

A little background: Twitter assigns each tweet a unique ID number. The ID is just a counter that increments by one with each tweet that gets posted. Yesterday, the total count of tweets posted since Twitter began passed 2,147,483,647, which is the largest number that can be represented by a signed 32-bit integer. A signed 32-bit integer can handle values from (–231) through (231 – 1)—that’s 232 values in all. So if a Twitter client uses signed 32-bit integer variables to store IDs, all hell will break loose when an ID greater than 2,147,483,647 appears. That’s the Twitpocalypse.
Twitter began warning developers about the coming Twitpocalypse months ago. One simple fix would be to switch from signed 32-bit integers to unsigned 32-bit integers. That would stave off the Twitpocalypse until IDs reach 4,294,967,295 (232 – 1), and is the solution implicit in this patch.
You might well ask why a programmer would use a signed variable to hold a value that would never be negative. Laziness and habit would be my guess. Still, with months of warning, you’d think that any decent programmer would be able to search his or her code for variables declared as signed instead of unsigned.
I’m sure both Craig Hockenberry (Twitterrific) and Loren Brichter (Tweetie) did that search, but obviously they didn’t do it well enough. Last night, Twitterrific for the iPhone began issuing an error message every time it tried to retrieve new messages from the server.

Twitterrific thus became unusable, and I switched to Tweetie. This morning, Brichter apologized for searches being hosed by the Twitpocalypse. Since I almost never search Twitter, my use of Tweetie was unaffected.
What about Dr. Twoot? Because it’s written in JavaScript and treats status IDs as strings, Dr. Twoot made it through the Twitpocalypse seemingly unscathed. Score one for the amateur programmers.
Zits doesn’t get Twitter
June 2nd, 2009 at 10:40 pm
I generally enjoy Zits. It’s a one-joke strip—sort of like the Lockhorns—but it does its one joke well. What makes it work for me is the way it understands both sides of the parent/teen relationship and doesn’t always make one side the butt of the jokes.
But today’s strip just wrong.

First, what kind of Twitter client is Jeremy using? Instead of a picture, there’s a violet square next to each of his mother’s tweets. In my morning newspaper—which does not have the benefit of color—the squares are white, making the whole thing look like an undone to-do list. I’m not looking for absolute fidelity here, and I understand that space is limited. But wouldn’t the entries have looked more Twitter-like had each tweet been accompanied by a little sketch of Connie Duncan? I don’t think this is asking too much. Artist Jim Borgman’s been drawing her for a dozen years; surely he could evoke the “essence of Connie” in just a few pen strokes.
Next, there’s the final tweet, which is directed at Jeremy. It’s inconceivable to anyone who actually uses Twitter that that entry doesn’t start with @.
Finally, there’s the punch line, which is what really makes the strip wrong. Jeremy is 15 or 16 years old. He is not going to be teaching his mother to use Twitter, even by mistake, because teenagers don’t use Twitter.
Teens use Facebook. Teens use text messaging. In fact, as I was reading the strip, I assumed Connie was texting Jeremy. A punch line in which Jeremy regrets teaching his mom how to text would have rung true. I know lots of middle-aged women—and even a couple of middle-aged men—who have learned how to text in order to communicate with their teenaged children. It’s not unusual for the kids to see this as an invasion into an otherwise parent-free area of their lives.
But Twitter’s been in all the papers and has been associated with “young people,” and writer Jerry Scott apparently felt compelled to incorporate it. So we end up with a strip that’s as clueless and out of touch as if it had been done by Mort Walker.











