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.
- #!/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 (<loginfile>) {
- 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().
- </loginfile>
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