--- twitter.module.orig	2009-02-04 14:28:00.000000000 -0600
+++ twitter.module	2009-02-04 20:27:00.000000000 -0600
@@ -70,7 +70,7 @@ function twitter_form_alter(&$form, $for
     );
     $form['twitter'] += $twitter_form;
     $form['twitter']['status']['#default_value'] = variable_get('twitter_default_format', 'New post: !title !tinyurl');
-    $form['twitter']['status']['#description'] = t('The given text will be posted to twitter.com. You can use !url, !url-alias, !tinyurl, !title and !user as replacement text.');
+    $form['twitter']['status']['#description'] = t('The given text will be posted to twitter.com. You can use !title, !user, !tinyurl, !url-alias, and !url as replacement text. Note that only one URL replacement will be honored.');
   }
 }
 
@@ -87,12 +87,109 @@ function twitter_nodeapi(&$node, $op, $a
     case 'update':
       if (!empty($node->status) && !empty($node->twitter) && !empty($node->twitter['post'])) {
         $twitter_accounts = twitter_get_user_accounts($node->uid, TRUE);
-        $replacements = array('!title' => $node->title,
-                              '!url' => url('node/'. $node->nid, array('absolute' => TRUE, 'alias' => TRUE)),
-                              '!url-alias' => url('node/'. $node->nid, array('absolute' => TRUE)),
-                              '!tinyurl' => _twitter_tinyurl(url('node/'. $node->nid, array('absolute' => TRUE))),
-                              '!user' => $node->name);
-        $status = strtr($node->twitter['status'], $replacements);
+
+        $format_string = $node->twitter['status'];
+        $format_string_length = strlen($format_string);
+
+        // Creating empty values for the URL replacements ensures they're removed when the tweet is built.
+        $replacements = array(
+          '!tinyurl' => '',
+          '!url-alias' => '',
+          '!url' => '',
+        );
+        $replacements_length = 0;
+
+        $title_length = 0;
+        $nontitle_length = 0;
+
+        // Check if !title string exists before creating a replacement
+        if (strpos($format_string, '!title') !== FALSE) {
+          drupal_set_message('"!title" found!');
+          $replacements_length += 6; // Length of literal "!title"
+          $replacements['!title'] = $node->title;
+          $title_length += strlen($replacements['!title']);
+        }
+
+        // Check if !user string exists before creating a replacement
+        if (strpos($format_string, '!user') !== FALSE) {
+          drupal_set_message('"!user" found!');
+          $replacements_length += 5; // Length of literal "!user"
+          $replacements['!user'] = $node->name;
+          $nontitle_length += strlen($replacements['!user']);
+        }
+
+        // Note that the URL replacements below are mutually exclusive.
+        // This is necessary to prevent false positives when looking for "!url" (it's found in "!url-alias").
+
+        // Check if !tinyurl string exists before creating a replacement
+        // Avoids unnecessary calls to _twitter_tinyurl() each time a node is published regardless of whether !tinyrul exists
+        if (strpos($format_string, '!tinyurl') !== FALSE) {
+          drupal_set_message('"!tinyurl" found!');
+          $replacements_length += 8; // Length of literal "!tinyurl"
+          $replacements['!tinyurl'] = _twitter_tinyurl(url('node/'. $node->nid, array('absolute' => TRUE)));
+          $nontitle_length += strlen($replacements['!tinyurl']);
+        }
+
+        // Check if !url-alias string exists before creating a replacement
+        else if (strpos($format_string, '!url-alias') !== FALSE) {
+          drupal_set_message('"!url-alias" found!');
+          $replacements_length += 9; // Length of literal "!url-alias"
+          $url = url('node/'. $node->nid, array('absolute' => TRUE));
+
+          // URLs longer than 30 chars get tinyurl'd by Twitter
+          if (strlen($url) > 30) {
+            $url = _twitter_tinyurl($url);
+          }
+
+          $replacements['!url-alias'] = $url;
+          $nontitle_length += strlen($url);
+        }
+
+        // Check if !url string exists before creating a replacement
+        else if (strpos($format_string, '!url') !== FALSE) {
+          drupal_set_message('"!url" found!');
+          $replacements_length += 4; // Length of literal "!url"
+          $url = url('node/'. $node->nid, array('absolute' => TRUE, 'alias' => TRUE));
+
+          // URLs longer than 30 chars get tinyurl'd by Twitter
+          if (strlen($url) > 30) {
+            $url = _twitter_tinyurl($url);
+          }
+
+          $replacements['!url'] = $url;
+          $nontitle_length += strlen($url);
+        }
+
+        $status = strtr($format_string, $replacements);
+        $status_length = strlen($status);
+
+        // Only 140 chars are allowed. If we've passed that threshold, we need to modify the tweet.
+        // However, we must have a title present. It's the only string we're able to truncate!
+        // Tweets > 140 chars with no post title are a lost cause. We let Twitter sort it out.
+        if (($status_length > 140) && ($title_length > 0)) {
+          drupal_set_message('Tweet is too long. We will truncate the title.');
+
+          // We need to find out how many characters are left for the title.
+          // First, figure out how much non-replacement text ("New post:" and whitespace) is in the string.
+          // Second, add that length to the running total of nontitle characters.
+          $nontitle_length += $format_string_length - $replacements_length;
+
+          // We need to make sure that all the nontitle text ("New post:", whitespace, user, url) are <= 130 chars.
+          // 130 chars is somewhat arbitrary. This allows seven characters from the title and three periods for an ellipsis.
+          // If we don't have 10 chars of wiggle room, we remove the title entirely.
+          if ($nontitle_length <= 130) {
+            // We use 137 here to allow three periods for an ellipsis.
+            $truncated_title_length = 137 - $nontitle_length;
+            $replacements['!title'] = substr($replacements['!title'], 0, $truncated_title_length) .'...';
+          }
+          else {
+            $replacements['!title'] = '';
+          }
+
+          // Rebuild the tweet with the truncated (or empty) title
+          $status = strtr($format_string, $replacements);
+        }
+
         $pass = $twitter_accounts[$node->twitter['account']]['password'];
         twitter_set_status($node->twitter['account'], $pass, $status);
         drupal_set_message(t('Successfully posted to Twitter'));
