Work the Shell - Our Twitter Autoresponder Goes Live!

 in
Some final fixes to the Twitterbot script we developed last month.
What's Really Wrong?

The problem isn't that the data is being eaten, it's that the awk script is pairing the name information with the wrong tweet. Let's re-examine the awk script:

awk '{ if (NR % 4 == 0) {
           printf ("name=%s; ", $0)
       }
       else if (NR % 4 == 1) {
           printf ("id=%s; ",$0)
       }
       else if (NR % 4 == 2) {
           print "msg=\"" $0 "\""
       }
     }'

NR%4=0 is correctly tagged as the name, NR%4=1 as the message ID, NR%4=2 as the msg, and NR%4=3 is skipped. (It's the Twitter user ID, not the tweet ID. It might be useful in a different context, but not for what we're doing.)

The problem is subtle, but it becomes obvious when you compare what the parser is generating against the actual tweets in the Twitter stream. We saw the first two like this:

id=7395681235; msg="African or European?"
name=jeffrey; id=7395672894; msg="North Hall IStage"

But in fact, the tweet “African or European?” was sent by jeffrey, and the “North Hall IStage” was sent by the user identified in the subsequent line of parsed and formatted data.

Conclusion? We're splitting the data lines in the wrong place. Instead of adding the carriage return after NR%4==2 (it's subtle, we use print instead of printf), we actually should be adding it after the match for NR%4==0, like this:

awk '{ if (NR % 4 == 0) {
           printf ("name=%s;\n", $0)
     } else if (NR % 4 == 1) {
           printf ("id=%s; ",$0)
     } else if (NR % 4 == 2) {
           printf ("msg=\"%s\"; ", $0) }
     }'

Now, let's try that statement again:

id=7395681235; msg="African or European?"; name=jeffrey;
id=7395672894; msg="North Hall IStage"; name=sideline;

Ah, that's the ticket!

Fixed It, Now Let's Clean Everything Up

With the problem solved, I'll remove the added debug statements and unleash the listener beast:

got name = jeffrey, id = 7395681235, and msg = African or European?
got name = sideline, id = 7395672894, and msg = North Hall IStage
got name = Genuine, id = 7395669466, and msg = ummmmm I know

Perfect. Bug debugged!

Now when we run the script, it correctly sees only the new tweets since it was last run, and it responds only to those it understands:

Twitter user @Larkin asked for the time
@Larkin the time on our server is LOCALTIME
Twitter user @jennyj asked for the time
@jennyj the time on our server is LOCALTIME

Run the script again, and it sees only what's newer yet:

Twitter user @NoA asked for directions in tweet 7396527668
@NoA directions to our office are here: SOMEADDRESS

Perfect! Now, a tiny tweak. As we've debugged things, I have set the variable tweet to /bin/echo, so as not to flood my followers with unnecessary messages. Change it back to the tweet.sh script (as developed in an earlier series of columns), and the script actually responds with tweets.

The first run looks like this:

$ sh tweet-listen.sh
Twitter user @mosa asked for directions in tweet 7396566048
(sent tweet @mosa directions to our office are here: SOMEADDRESS)
Twitter user @xwatch asked for the time
(sent tweet @xwatch the time on our server is TIME)
Twitter user @NoA asked for directions in tweet 7396527668
(sent tweet @NoA directions to our office are here: SOMEADDRESS)

To ensure that it won't answer more than once to a tweet query, I'll run the script again:

$ sh tweet-listen.sh
$

That's it! Now one tiny additional task is left, to add it to crontab so that it'll be an active listener, which is done by having it run every two minutes with the line:

*/2 * * * *  bash $SCRIPTS/davesbot/tweet-listen.sh

That's all there is to it. Congratulations, we've just built a fully featured Twitterbot.

If you'd like to test it, it has its own account on Twitter, @davesbot. Start by sending a 2–3 word message, and it'll tell you what it can do. Grab the final source code from the LinuxJournal.com site at ftp.linuxjournal.com/pub/lj/listings/issue192/10711.tgz.

Dave Taylor has been hacking shell scripts for a really long time. He's the author of the popular Wicked Cool Shell Scripts and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.

______________________

Dave Taylor has been hacking shell scripts for over thirty years. Really. He's the author of the popular "Wicked Cool Shell Scripts" and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState