New Perl that I learned
Today, I'll try to explain the new concepts first and then show the code.
- "$0": This is dollar-zero. It is a special Perl variable to indicate the name of the file containing the perl script being executed
- The x operator repeats a string pattern.
print "*" x 10; and print "**********"; are equivalent - defined will return false if a variable is undef and true if it has a value.
- @ARGV is a reserved Perl array that contains the list of arguments passed on the command line.
Help if (@ARGV == 0); will call the Help subroutine if the list of arguments is empty, i.e. if you just type "perl twit.pl" at the command line.
Note that checking @ARGV must be performed before the call to GetOptions which will empty the argument list. - You can tell the GetOption procedure to directly call a subroutine when a specific argument is passed at the command line. See for example "version" => \&Version. When -v or --version is added after the script name, you will see the version number of the script and exit the program.
To use version 0.2.0, you have to add -t (for twitter), -i (for identica) or -a (for both, also works if you choose -t -i) to the command line.
It is getting a bit long to post the whole script on this blog. You can still find the latest version to download here.
#!/usr/bin/perl
use 5.10.0; # To be able to use "say" function
use strict; # Pragma to add restrictions to Perl rules
use warnings; # Pragma to add warnings at compile and run-time
use Getopt::Long; # To parse the command line
use Net::Twitter; # API to twitter.com and identi.ca
my $PROG_NAME = $0; # $0 contains the name of the file containing the Perl script being executed
my $VERSION = "v0.2.0";
my $VersionDate = "February 21st 2009";
# ------------------------------------------------------------------------------
# Name : Help
# Comment : displays list of available options
# Input : no argument to command line or "-h" or "--help"
# Output : help screen and exit program
# ------------------------------------------------------------------------------
sub Help {
print "
Usage:
perl $PROG_NAME [-options]
Options:
-a, --all : send message to all supported macroblogging sites
-f, --file : file containing the login information for each site
-h, --help : this help screen
-i, --identica : send message to identi.ca
-s, --status : status (message) to send
-t, --twitter : send message to twitter.com
-v, --version : displays version information
$PROG_NAME help
";
print "-" x (length ($PROG_NAME) + 5);
print "
$PROG_NAME sends a status update to either twitter.com or identi.ca (or both) from the command line.
If -t is specified (for example), it will send the update to twitter.com.
If -a is passed, then your status on both twitter and identica will be updated.
Format of login files
---------------------
$PROG_NAME will first try to find \"twit.txt\" located in the current directory.
You can also use the --file option to tell $PROG_NAME where to find your login information.
- Lines starting with '#' are comments and will be ignored by the script
- The last line starting with \"Twitter\" will be parsed for username and password.
Each of these fields must be separated by a semi-column ':'
- Same thing with \"Identica\"
Examples:
---------
- perl twit.pl -s \"Using Padre on Linux\" -f \"~/secretstuff/mytwitterpassword.txt\" -a
Updates both twitter and identica status with login info from specified file
- perl twit.pl -s \"This is Vistaaaaaa\" -i
Updates identica status only
$PROG_NAME uses the following modules:
- Getopt::Long
- Net::Twitter
";
exit;
} # End of Help
# ------------------------------------------------------------------------------
# Name : version
# Comment : displays script's version number
# Input : --
# Output : version number screen and exit program
# ------------------------------------------------------------------------------
sub Version {
print "
$PROG_NAME version: $VERSION
Date : $VersionDate
Author: dlp
Get the latest version from here:
http://sites.google.com/site/damienlearnsperl/DLP-scripts
";
exit;
} # end of Version
# ------------------------------------------------------------------------------
# Name : CreateObject
# Comment : Creates and returns an instance of the Net::Twitter class
# Input : - Input string with value
# "twitter" -> twitter.com instance
# "identica" -> identi.ca instance
# all other values return an error
# - Hash with "UserName" and "Password"
# Output : Object newly created or 0 if error
# ------------------------------------------------------------------------------
sub CreateObject {
my $SiteInstance = 0;
my $NameString = shift;
my %Login = @_;
$NameString =~ tr/A-Z/a-z/;
if ($NameString eq "twitter") {
$SiteInstance = Net::Twitter->new(username => $Login{"UserName"}, password => $Login{"Password"});
}
elsif ($NameString eq "identica") {
$SiteInstance = Net::Twitter->new(identica => 1, username => $Login{"UserName"}, password => $Login{"Password"});
}
return $SiteInstance;
} # End of CreateObject
# ------------------------------------------------------------------------------
# Name : SendUpdate
# Comment : Sends update to Twitter object
# Input : - Net::Twitter object
# - message string
# Output : string "OK" if successful update, string "FAIL" otherwise
# ------------------------------------------------------------------------------
sub SendUpdate {
my $Site = shift;
my $Message = shift;
my $SiteName = ($Site->{identica})?"identi.ca":"twitter.com";
#There's a hard limit on the size of twits for both twitter and identica
if (!defined $Message) {
return "$SiteName update: FAILED (no message)";
}
if (length $Message > 140) {
return "$SiteName update: FAILED (message over 140 characters)";
}
if ($Site->update($Message)) {
return "$SiteName update: OK";
}
else {
return "$SiteName update: FAIL";
}
} #End of SendUpdate
# ------------------------------------------------------------------------------
# Name : SendMessage
# Comment : Sends message to chosen macroblogging site
# Input : $_[0] = Input string with value
# "twitter" -> twitter.com instance
# "identica" -> identi.ca instance
# $_[1] = Message string to be sent
# $_[2] = Hash with "UserName" and "Password" elements
# Output : Return string: "Error" if couldn't create object or string from SendUpdate
# ------------------------------------------------------------------------------
sub SendMessage {
my $ReturnString;
my $Instance;
my ($SiteName, $Message, %Login) = @_;
$Instance = CreateObject($SiteName, %Login);
if ($Instance) {
$ReturnString = SendUpdate($Instance, $Message);
}
else {
$ReturnString = "Error with $SiteName creation process";
}
return $ReturnString;
} #End of SendMessage
# ------------------------------------------------------------------------------
# Main
# ------------------------------------------------------------------------------
my $Status;
my $PasswordFile;
my %TwitLogin;
my %IdenticaLogin;
my $TwitterUse; # 1-> send to twitter, 0 -> do not send
my $IdenticaUse; # 1-> send to identica, 0 -> do not send
Help if (@ARGV == 0);
#Parse command line arguments
GetOptions ("all" => sub {$TwitterUse = 1; $IdenticaUse = 1},
"status=s" => \$Status,
"file=s" => \$PasswordFile,
"help" => \&Help,
"identica" => \$IdenticaUse,
"twitter" => \$TwitterUse,
"version" => \&Version);
# Read Password file passed as argument or twit.txt by default
$PasswordFile = "twit.txt" unless ($PasswordFile);
open(LOGINFILE, $PasswordFile) or die "Cannot open \"$PasswordFile\" file: $!\n";
while () {
my $line = $_;
my $PlaceHolder;
chomp $line; # Remove trailing newline character
next if ($line =~ m/^#/); # Ignore lines starting with '#'
if ($line =~ m/^twitter/i) { # /^ indicates the beginning of the line
($PlaceHolder, $TwitLogin{"UserName"}, $TwitLogin{"Password"}) = split (/:/, $line);
}
if ($line =~ m/^identica/i) { # /i to ignore alphabetic case
($PlaceHolder, $IdenticaLogin{"UserName"}, $IdenticaLogin{"Password"}) = split (/:/, $line);
}
}
close (LOGINFILE);
say SendMessage("Twitter", $Status, %TwitLogin) if ($TwitterUse);
say SendMessage("Identica", $Status, %IdenticaLogin) if ($IdenticaUse);
Help if (!defined ($TwitterUse) && !defined ($IdenticaUse));
__END__
To do:
- Use POD format for comments
- Simple GUI interface (1 text box + 1 check box for each Twitter and Identi.ca + 1 "Send" button)
- Create executable file for standalone use without need of a Perl interpreter
History:
...
v0.2.0 (2009/02/21): Added --twitter (-t) and --identica (-i) command line options to select site for updates
Added --help (-h) and --version (-v) command line options
Added undefined argument check for $Message in SendUpdate().
There are better ways to include help and comments in code. I will talk about POD soon.
Larry Wall quote of the day:
"We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise."
Possible next posts:
- Perl template - Part II: Adding Help and Version procedures
- Perl help resources
- Improving on twit.pl: Graphical User interface
- POD
- Install Google Analytics on your Blogger blog and stats for DLP
Some new Perl culture for you to learn: subroutine names that are AllSquishedTogether() are frowned upon. The convention is names_like_this() - lowercase, with underscores separating words.
ReplyDeleteThanks for the comment!
ReplyDeleteI replied to you there:
http://damienlearnsperl.blogspot.com/2009/03/perl-naming-convention-for-subroutine.html