GoTwitr - Twitter Automation Site Built with Drupal
Whether it's for pleasure or business, or both, Twitter automation is a must for anyone who wants to use Twitter effectively. GoTwitr is a new site whose primary goal is to make it easy for people to grow and manage their Twitter communities.
It’s also a tool to help new Twitter users get started quickly and easily. GoTwitr’s unique invitation model makes it extremely easy for any Twitter user to get his friends and family connected to Twitter. GoTwitr uses a unique new concept to deliver quality followers, and promote you to other twitter users that share common interests and passions.
GoTwitr was built in Drupal 6. Drupal’s external site integration tools made it easy to bypass the normal Drupal registration and login and use the “Login with Twitter” service.
GoTwitr Technology
GoTwitr uses Twitter’s Oauth API, which means the Drupal registration is 100% automated. This is a first for Twitter Automation sites. Using this technology lets you experience all the advanced automation tools without sharing your Twitter username and password with the site (which can be risky).
For the actual Twitter integration, we tested several Drupal Twitter modules, but ended up using Jaisen Mathai’s excellent EpiTwitter and EpiOauth php library. It uses CURL to make calls to Twitter asynchronously, so it was blazingly fast, and very easy to turn into a Drupal custom module.
Why No Drupal Registration or Login Form?
Since GoTwitr is only useful for working with your Twitter account, we decided to fully automate the Drupal login and registration process by using data from Twitter. This means you can register or sign into the GoTwitr website with a single click. To accommodate this process, the following three functions were used.
First, a call is made to twitter_sign_in() which loads our Twitter API keys and sends them to Twitter. The bulk of the work is done in twitter_validate() which is called by Twitter during the Oauth validation. The call to getAccessToken() returns an individual's security tokens from Twitter, and a single call to get_accountVerify_credentials() not only validates you on Twitter, but it returns the complete Twitter user record in the $response variable. Now, with your Twitter UID we can use user_external_load($token->user_id) to see if you are a current Drupal registered user. If you are a current user, you are immediately logged into the site using user_external_login($account), however if this is your first visit a call is made to new_gotw_account() where a Drupal registration is performed on your behalf using the data Twitter sent us in the $response variable.
No Long Registration Form to Fill Out! Yeah!
<span style="color: #000000"><span style="color: #0000BB"><?php<br> <br> </span><span style="color: #007700">function </span><span style="color: #0000BB">twitter_sign_in</span><span style="color: #007700">() {<br> global </span><span style="color: #0000BB">$user</span><span style="color: #007700">;<br> if (</span><span style="color: #0000BB">$user</span><span style="color: #007700">-></span><span style="color: #0000BB">uid</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">drupal_goto</span><span style="color: #007700">(</span><span style="color: #DD0000">"home"</span><span style="color: #007700">) ;<br> } else {<br> </span><span style="color: #0000BB">$consumer_key </span><span style="color: #007700">= </span><span style="color: #0000BB">variable_get</span><span style="color: #007700">(</span><span style="color: #DD0000">'twitter_consumer_key'</span><span style="color: #007700">, </span><span style="color: #DD0000">''</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$consumer_secret </span><span style="color: #007700">= </span><span style="color: #0000BB">variable_get</span><span style="color: #007700">(</span><span style="color: #DD0000">'twitter_consumer_secret'</span><span style="color: #007700">, </span><span style="color: #DD0000">''</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$twitterObj </span><span style="color: #007700">= new </span><span style="color: #0000BB">EpiTwitter</span><span style="color: #007700">(</span><span style="color: #0000BB">$consumer_key</span><span style="color: #007700">, </span><span style="color: #0000BB">$consumer_secret</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">drupal_goto</span><span style="color: #007700">(</span><span style="color: #0000BB">$twitterObj</span><span style="color: #007700">-></span><span style="color: #0000BB">getAuthenticateUrl</span><span style="color: #007700">()) ; <br> }<br> }<br> <br> function </span><span style="color: #0000BB">twitter_validate</span><span style="color: #007700">() {<br> global </span><span style="color: #0000BB">$user</span><span style="color: #007700">;<br> <br> </span><span style="color: #0000BB">$consumer_key </span><span style="color: #007700">= </span><span style="color: #0000BB">variable_get</span><span style="color: #007700">(</span><span style="color: #DD0000">'twitter_consumer_key'</span><span style="color: #007700">, </span><span style="color: #DD0000">''</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$consumer_secret </span><span style="color: #007700">= </span><span style="color: #0000BB">variable_get</span><span style="color: #007700">(</span><span style="color: #DD0000">'twitter_consumer_secret'</span><span style="color: #007700">, </span><span style="color: #DD0000">''</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$twitterObj </span><span style="color: #007700">= new </span><span style="color: #0000BB">EpiTwitter</span><span style="color: #007700">(</span><span style="color: #0000BB">$consumer_key</span><span style="color: #007700">, </span><span style="color: #0000BB">$consumer_secret</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$twitterObj</span><span style="color: #007700">-></span><span style="color: #0000BB">setToken</span><span style="color: #007700">(</span><span style="color: #0000BB">$_GET</span><span style="color: #007700">[</span><span style="color: #DD0000">'oauth_token'</span><span style="color: #007700">]);<br> </span><span style="color: #0000BB">$token </span><span style="color: #007700">= </span><span style="color: #0000BB">$twitterObj</span><span style="color: #007700">-></span><span style="color: #0000BB">getAccessToken</span><span style="color: #007700">();<br> </span><span style="color: #0000BB">$twitterObj</span><span style="color: #007700">-></span><span style="color: #0000BB">setToken</span><span style="color: #007700">(</span><span style="color: #0000BB">$token</span><span style="color: #007700">-></span><span style="color: #0000BB">oauth_token</span><span style="color: #007700">, </span><span style="color: #0000BB">$token</span><span style="color: #007700">-></span><span style="color: #0000BB">oauth_token_secret</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$response </span><span style="color: #007700">= </span><span style="color: #0000BB">$twitterObj</span><span style="color: #007700">-></span><span style="color: #0000BB">get_accountVerify_credentials</span><span style="color: #007700">();<br> try {<br> </span><span style="color: #0000BB">$account </span><span style="color: #007700">= </span><span style="color: #0000BB">user_external_load</span><span style="color: #007700">(</span><span style="color: #0000BB">$token</span><span style="color: #007700">-></span><span style="color: #0000BB">user_id</span><span style="color: #007700">);<br> if (isset(</span><span style="color: #0000BB">$account</span><span style="color: #007700">-></span><span style="color: #0000BB">uid</span><span style="color: #007700">)) { </span><span style="color: #FF8000">// current user<br> </span><span style="color: #0000BB">user_external_login</span><span style="color: #007700">(</span><span style="color: #0000BB">$account</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">update_gotw_account</span><span style="color: #007700">(</span><span style="color: #0000BB">$response</span><span style="color: #007700">, </span><span style="color: #0000BB">$token</span><span style="color: #007700">);<br> } else { </span><span style="color: #FF8000">// new gotwitr user<br> </span><span style="color: #0000BB">new_gotw_account</span><span style="color: #007700">(</span><span style="color: #0000BB">$response</span><span style="color: #007700">, </span><span style="color: #0000BB">$token</span><span style="color: #007700">); <br> }<br> } catch (</span><span style="color: #0000BB">EpiException $e</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">drupal_set_message</span><span style="color: #007700">(</span><span style="color: #DD0000">"Twitter has an error - please try again: " </span><span style="color: #007700">. </span><span style="color: #0000BB">$e</span><span style="color: #007700">-></span><span style="color: #0000BB">getMessage</span><span style="color: #007700">());<br> </span><span style="color: #0000BB">twitter_log_error</span><span style="color: #007700">(</span><span style="color: #0000BB">$user</span><span style="color: #007700">-></span><span style="color: #0000BB">uid</span><span style="color: #007700">, </span><span style="color: #DD0000">'TwitterValidate'</span><span style="color: #007700">, </span><span style="color: #0000BB">$e</span><span style="color: #007700">); <br> }<br> </span><span style="color: #0000BB">drupal_goto</span><span style="color: #007700">(</span><span style="color: #DD0000">"homepage"</span><span style="color: #007700">);<br> }<br> <br> function </span><span style="color: #0000BB">new_gotw_account</span><span style="color: #007700">(</span><span style="color: #0000BB">$response</span><span style="color: #007700">, </span><span style="color: #0000BB">$token</span><span style="color: #007700">) {<br> <br> global </span><span style="color: #0000BB">$user</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$edit </span><span style="color: #007700">= array(<br> </span><span style="color: #DD0000">'name' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$response</span><span style="color: #007700">[</span><span style="color: #DD0000">'screen_name'</span><span style="color: #007700">],<br> </span><span style="color: #DD0000">'pass' </span><span style="color: #007700">=> </span><span style="color: #0000BB">user_password</span><span style="color: #007700">(),<br> </span><span style="color: #DD0000">'init' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$response</span><span style="color: #007700">[</span><span style="color: #DD0000">'screen_name'</span><span style="color: #007700">],<br> </span><span style="color: #DD0000">'status' </span><span style="color: #007700">=> </span><span style="color: #0000BB">1</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">"authname_twitter" </span><span style="color: #007700">=> </span><span style="color: #0000BB">$token</span><span style="color: #007700">-></span><span style="color: #0000BB">user_id</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'access' </span><span style="color: #007700">=> </span><span style="color: #0000BB">time</span><span style="color: #007700">(),<br> );<br> </span><span style="color: #0000BB">$account </span><span style="color: #007700">= </span><span style="color: #0000BB">user_save</span><span style="color: #007700">(</span><span style="color: #DD0000">''</span><span style="color: #007700">, </span><span style="color: #0000BB">$edit</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$user </span><span style="color: #007700">= </span><span style="color: #0000BB">$account</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">insert_gotw_account</span><span style="color: #007700">(</span><span style="color: #0000BB">$response</span><span style="color: #007700">, </span><span style="color: #0000BB">$token</span><span style="color: #007700">);<br> }<br></span><span style="color: #0000BB">?></span></span>
Search Engine Optimization
Drupal is also very SEO friendly. To take advantage of Drupal’s SEO features, we integrated the XML Sitemap, Global Redirect, Pathauto, Page Title, and Sitemap modules. We also used the excellent Google Analytics and Google Adsense module to take advantage of Google’s services.
The Need for Speed
Everything related to Twitter eats bandwidth, so we knew site optimization would be important. To keep overhead as low as possible, we used only the Drupal libraries that were absolutely necessary. Next we installed APC so our php would execute faster. Memcached was installed next, and we used the excellent Memcache module to integrate Memcached with Drupal. APC + Memcached = approximately 300% increase in speed.
Drupal may be Fast, but Twitter can be slow
We set a goal to have all pages load in less than a second. But no matter how much caching or query optimization we do, when we use the Twitter API to send a lot of data back and forth between Twitter, it can take some time. For example, our "Smart Follow" routine finds all users that are following you that you are not following back. This is done by first retrieving a list of all Friend and Follower ID from Twitter. We then use array_diff() to find the Twitter IDs that are followers and not friends. The first 30 of these users are then individually retrieved from Twitter for your review.
If you have several thousand friends and followers, then this process can take SEVERAL seconds. We needed an easy way to tell the user that we were busy talking to Twitter. We found a very simple way to do this with the Forms API and a single line of Javascript.
Take a look at the form definition below. First, the submit button has '#attributes' => array('onclick' => "standby();" which tells it to run the standby() js function. Secondly, we have a hidden markup field at the bottom of the form. This contains a big red message that says we are talking to Twitter. This is displayed when the button is pressed, and lets the user know we are busy. The new page loads when the function is complete, which clears the message. Simple, but effective.
<span style="color: #000000"><span style="color: #0000BB"><?php<br> </span><span style="color: #007700">function </span><span style="color: #0000BB">smart_follow_start_form</span><span style="color: #007700">(</span><span style="color: #0000BB">$form_state</span><span style="color: #007700">) {<br> <br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'markup'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'markup'</span><span style="color: #007700">,<br></span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'</p><br><h2>Smart Follow</h2><br>Smart Follow is a powerful feature that will analyze all your <br>Twitter Followers and notify you of the ones which you are not following. This function makes numerous Twitter API calls, and may take a few moments to run.<br>'</span><span style="color: #007700">,<br> );<br> <br> <br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'submit'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Run Smart Follow'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#attributes' </span><span style="color: #007700">=> array(</span><span style="color: #DD0000">'onclick' </span><span style="color: #007700">=> </span><span style="color: #DD0000">"standby();"</span><span style="color: #007700">),<br> );<br> <br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'cancel'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'submit'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Cancel'</span><span style="color: #007700">,<br> );<br> <br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'standby'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'markup'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'<br><br><span id="stand_by" style="visibility: hidden;" ><font size=4 <br>color=red>Depending on Twitter, this may take a few moments, please stand by.</font></span>'</span><span style="color: #007700">, <br> );<br> return </span><span style="color: #0000BB">$form</span><span style="color: #007700">;<br> <br>}<br><br></span><span style="color: #FF8000">// This function is Javascript and is placed in an external js file<br></span><span style="color: #007700">function </span><span style="color: #0000BB">standby</span><span style="color: #007700">() {<br> $(</span><span style="color: #DD0000">'#stand_by'</span><span style="color: #007700">).</span><span style="color: #0000BB">css</span><span style="color: #007700">(</span><span style="color: #DD0000">'visibility'</span><span style="color: #007700">, </span><span style="color: #DD0000">'visible'</span><span style="color: #007700">);<br>}<br></span><span style="color: #0000BB">?></span></span>
GoTwitr AHAH!
There are many places on GoTwitr we found that the AHAH capabilities of Drupal 6 added great usability. For example, when you want to send a tweet, it is customary to have the Tweet include a shortened URL. We did not want to reload an entire page to alter one field, so we created an AHAH call to do the URL shortening. When we were initially programming the AHAH code, we found several AHAH examples, but most were very complex. Since this was a pretty simple example of using AHAH, we thought we'd include it for your review.
First, in the form definition for tweet_form, you will see that we have added the AHAH attribute to the submit button. We tell it to call shorten_url_callback() when the button is pressed, and replace the short_text wrapper in the HTML. Next, look at the form field definition for 'tweet'. You'll notice that it's a textarea to hold the text of the tweet, but you also see a #prefix and #suffix which are the wrappers for the AHAH call.
When the user presses the shorten_url button, the shorten_url_callback() is called. This reads the URL from $form_state and calls the URL shortening function. The shortened URL is then appended to the value in the Tweet textarea. Finally, the callback replaces the entire textarea (remember the short_text wrapper) with the modified textarea. Now the shortened URL is appended to the end of their tweet, all done with AHAH without submitting the form.
<span style="color: #000000"><span style="color: #0000BB"><?php<br> <br></span><span style="color: #007700">function </span><span style="color: #0000BB">tweet_form</span><span style="color: #007700">(</span><span style="color: #0000BB">$form_state</span><span style="color: #007700">) {<br> <br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'tweet'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'textarea'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Message'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#attributes' </span><span style="color: #007700">=> array(</span><span style="color: #DD0000">'onkeyup' </span><span style="color: #007700">=> </span><span style="color: #DD0000">"CheckFieldLength(tweet, 'remaining', 140);"</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'onkeydown' </span><span style="color: #007700">=> </span><span style="color: #DD0000">"CheckFieldLength(tweet, 'remaining', 140);"</span><span style="color: #007700">, <br> </span><span style="color: #DD0000">'onmouseout' </span><span style="color: #007700">=> </span><span style="color: #DD0000">"CheckFieldLength(tweet, 'remaining', 140);"</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#prefix' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'<div id=short_text>'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#rows' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'3'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#cols' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'20'</span><span style="color: #007700">, <br> </span><span style="color: #DD0000">'#suffix' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'</div>'</span><span style="color: #007700">,<br> );<br><br></span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'url'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'textfield'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'URL'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#size' </span><span style="color: #007700">=> </span><span style="color: #0000BB">30</span><span style="color: #007700">,<br> );<br> <br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'submit'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Send Tweet'</span><span style="color: #007700">,<br> );<br> <br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'shorten'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'submit'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Shorten Url'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#suffix' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'<font size=4 color=#000000> <span align=right id="remaining">140</span></font><hr>'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#ahah' </span><span style="color: #007700">=> array(<br> </span><span style="color: #DD0000">'path' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'shorten_url_callback'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'wrapper' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'short_text'</span><span style="color: #007700">,<br> ),<br> );<br> <br> return </span><span style="color: #0000BB">$form</span><span style="color: #007700">;<br>}<br><br><br>function </span><span style="color: #0000BB">shorten_url_callback</span><span style="color: #007700">() {<br> <br> </span><span style="color: #0000BB">$form_state </span><span style="color: #007700">= array(</span><span style="color: #DD0000">'storage' </span><span style="color: #007700">=> </span><span style="color: #0000BB">NULL</span><span style="color: #007700">, </span><span style="color: #DD0000">'submitted' </span><span style="color: #007700">=> </span><span style="color: #0000BB">FALSE</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$form_build_id </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'form_build_id'</span><span style="color: #007700">];<br> </span><span style="color: #0000BB">$form </span><span style="color: #007700">= </span><span style="color: #0000BB">form_get_cache</span><span style="color: #007700">(</span><span style="color: #0000BB">$form_build_id</span><span style="color: #007700">, </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$args </span><span style="color: #007700">= </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'#parameters'</span><span style="color: #007700">];<br> </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">[</span><span style="color: #DD0000">'rebuild'</span><span style="color: #007700">] = </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$form_id </span><span style="color: #007700">= </span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$args</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">[</span><span style="color: #DD0000">'post'</span><span style="color: #007700">] = </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'#post'</span><span style="color: #007700">] = </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'#programmed'</span><span style="color: #007700">] = </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'#redirect'</span><span style="color: #007700">] = </span><span style="color: #0000BB">FALSE</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">drupal_process_form</span><span style="color: #007700">(</span><span style="color: #0000BB">$form_id</span><span style="color: #007700">, </span><span style="color: #0000BB">$form</span><span style="color: #007700">, </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$short </span><span style="color: #007700">= </span><span style="color: #0000BB">shorten_url</span><span style="color: #007700">(</span><span style="color: #0000BB">$form_state</span><span style="color: #007700">[</span><span style="color: #0000BB">values</span><span style="color: #007700">][</span><span style="color: #0000BB">url</span><span style="color: #007700">]);<br> </span><span style="color: #0000BB">$myvalue </span><span style="color: #007700">= </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">[</span><span style="color: #0000BB">values</span><span style="color: #007700">][</span><span style="color: #0000BB">tweet</span><span style="color: #007700">] . </span><span style="color: #DD0000">' ' </span><span style="color: #007700">. </span><span style="color: #0000BB">$short</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$form </span><span style="color: #007700">= </span><span style="color: #0000BB">drupal_rebuild_form</span><span style="color: #007700">(</span><span style="color: #0000BB">$form_id</span><span style="color: #007700">, </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">, </span><span style="color: #0000BB">$args</span><span style="color: #007700">, </span><span style="color: #0000BB">$form_build_id</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$output </span><span style="color: #007700">= </span><span style="color: #DD0000">'<DIV id=short_text><DIV id=edit-tweet-wrapper class=form-item><br><DIV class=resizable-textarea jQuery1251689638328="null"><SPAN jQuery1251689638328="17"><TEXTAREA <br>id=edit-tweet class="form-textarea resizable textarea-processed" rows=3 cols=25 name=tweet>'</span><span style="color: #007700">. <br></span><span style="color: #0000BB">$myvalue</span><span style="color: #007700">.</span><span style="color: #DD0000">'</TEXTAREA><br><DIV style="MARGIN-RIGHT: -6px" class=grippie jQuery1251689638328="18"></DIV></SPAN></DIV> </DIV></DIV>'</span><span style="color: #007700">;<br> print </span><span style="color: #0000BB">drupal_json</span><span style="color: #007700">(array(</span><span style="color: #DD0000">'status' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">, </span><span style="color: #DD0000">'data' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$output</span><span style="color: #007700">));<br> exit();<br>}<br></span><span style="color: #0000BB">?></span></span>
Drupal Keystroke Counter
With Tweets being limited to 140 characters, we thought it was important to put a Keystroke counter on the Tweet field in the above form. This was easy to accomplish once we found the right Javascript. You may have noticed the extra #attributes added to the textarea above. This calls the CheckFieldLength js code when you type a keystroke into the textarea. Now, look at the definition for the shorten_url button above. You'll see a #suffix that adds a span tag called "remaining". The CheckFieldLength function below, counts the characters remaining, and replaces the text in the span tag.
<span style="color: #000000"><span style="color: #0000BB"><?php<br> <br><br></span><span style="color: #FF8000">// fieldname, remainingname, maxchars<br></span><span style="color: #007700">function </span><span style="color: #0000BB">CheckFieldLength</span><span style="color: #007700">(</span><span style="color: #0000BB">fn</span><span style="color: #007700">,</span><span style="color: #0000BB">rn</span><span style="color: #007700">,</span><span style="color: #0000BB">mc</span><span style="color: #007700">) {<br> var </span><span style="color: #0000BB">len </span><span style="color: #007700">= </span><span style="color: #0000BB">fn</span><span style="color: #007700">.</span><span style="color: #0000BB">value</span><span style="color: #007700">.</span><span style="color: #0000BB">length</span><span style="color: #007700">;<br> if (</span><span style="color: #0000BB">len </span><span style="color: #007700">> </span><span style="color: #0000BB">mc</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">fn</span><span style="color: #007700">.</span><span style="color: #0000BB">value </span><span style="color: #007700">= </span><span style="color: #0000BB">fn</span><span style="color: #007700">.</span><span style="color: #0000BB">value</span><span style="color: #007700">.</span><span style="color: #0000BB">substring</span><span style="color: #007700">(</span><span style="color: #0000BB">0</span><span style="color: #007700">,</span><span style="color: #0000BB">mc</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">len </span><span style="color: #007700">= </span><span style="color: #0000BB">mc</span><span style="color: #007700">;<br> }<br> </span><span style="color: #0000BB">document</span><span style="color: #007700">.</span><span style="color: #0000BB">getElementById</span><span style="color: #007700">(</span><span style="color: #0000BB">rn</span><span style="color: #007700">).</span><span style="color: #0000BB">innerHTML </span><span style="color: #007700">= </span><span style="color: #0000BB">mc </span><span style="color: #007700">- </span><span style="color: #0000BB">len</span><span style="color: #007700">;<br>}<br></span><span style="color: #0000BB">?></span></span>
So What's Unique about GoTwitr?
- GoTwitr lets you preview everyone you follow or unfollow. Other Twitter automation tools bulk follow people. This unique feature ensures that you get a chance to decide if you want to follow or not. MUCH better than a blind follow based on ANY search result.
- GoTwitr delivers people to your website. Every invitation accepted will take your recipient to YOUR website, blog, profile, or any other URL.
- 100% Oauth - You don't have to give away your Twitter password to use all the features of our service. This also provide you with easy sign in and registration.
- Attract Followers by Invitation, not by bulk following. GoTwitr is the first Twitter application designed to build your community by sending out beautiful HTML invitations to your prospects. You can email, post on a website or blog, or even send invitations to existing Twitter users.
- Promote your friends. Add your favorite friends to a group, and attach them to your invitations. This way, not only can your invitee follow you, they can also follow all your friends. Establishing an initial Twitter community has never been easier.
- Plus so much more.....
If you've never heard of Twitter until now then you've been missing out on the newest craze in social networking. It’s time to get started. Go to www.gotwitr.com and have fun.
Happy Tweeting, and GO TWITTER!
GoTwitr.com - Visit GoTwitr Today!
Drupal version: Drupal 6.x