From: Tim Pope Date: Mon, 9 Aug 2004 06:44:45 +0000 (+0000) Subject: Added blogcl X-Git-Url: http://git.tpope.net/?p=tpope-extra.git;a=commitdiff_plain;h=56b1d1bb70f458ac15e64e5b3ca3a0b8f147b98f Added blogcl --- diff --git a/perl/blogcl b/perl/blogcl new file mode 100755 index 0000000..71403b8 --- /dev/null +++ b/perl/blogcl @@ -0,0 +1,291 @@ +#!/usr/bin/perl +# $Id$ +# -*- perl -*- vim: ft=perl sw=4 sts=4 + +use strict; +use Net::MovableType; +use Getopt::Long; +use File::Temp (); +use Term::Complete; +use vars qw(%opts $mt); + +if (-r $ENV{HOME} . "/.blogclrc") { + open CONFIG, $ENV{HOME} . "/.blogclrc"; + while() { + s/\#.*//; + next unless m/^([^=]*)=(.*)/; + $opts{$1}=$2; + } + close CONFIG; +} + +Getopt::Long::Configure ("bundling", "auto_help"); +die "Invalid arguments\n" unless +GetOptions (\%opts, 'username|l=s', 'password|p=s', 'url|u=s', 'blogid|b=i', 'title|t=s', 'category|c=s', 'file|f=s'); + +if ($ARGV[0] eq "help") { + Getopt::Long::HelpMessage(); + exit(0); +} + +sub init_mt { + die "No url given.\n" unless(defined("$url")); + die "No username given.\n" unless(defined("$username")); + die "No passowrd given.\n" unless(defined("$password")); + $mt = new Net::MovableType($opts{'url'}) || die "$!"; + $mt->username($opts{'username'}); + $mt->password($opts{'password'}); + my $blogid = $opts{'blogid'} || $mt->resolveBlogId($opts{'username'}); + unless($blogid) { + my $userblogs=$mt->getUsersBlogs(); + if($userblogs && $userblogs->[0]->{blogid}) { + $blogid=$userblogs->[0]->{'blogid'}; + } else { + warn "Blog ID unknown.\n"; + } + } + $mt->blogId($blogid); +} + +sub print_recent { + my $entries = $mt->getRecentPosts(shift || 10); + while ( my $entry = shift @$entries ) { + printf("[%02d] - %s\n", + $entry->{postid}, $entry->{title} ); + } +# postid userid content title description dateCreated +} + +sub print_categories { + print join("\n",map {$_->{categoryName}} @{$mt->getCategoryList()}), "\n"; +} + +sub show_post { + my $postid=shift; + my $post = $mt->getPost($postid) or die "$!"; + my $categories = $mt->getPostCategories($postid) or die "$!"; + if(defined($opts{file})) { + if($opts{file} eq "-") { + print STDOUT $post->{description}, "\n"; + } else { + open FH, ">".$opts{file} or die "$!"; + print $opts{file}, "\n"; + print FH $post->{description}, "\n"; + close FH; + } + } else { + printf("Title: %s (%d)\n", $post->{title}, $post->{postid}); + if(@$categories>1) { + print "Categories:"; + } elsif (@$categories==1) { + print "Category:"; + } + foreach(@$categories) { + print " ", $_->{'categoryName'}; + } + print "\n" if(@$categories); + print "Body:\n"; + print $post->{description}, "\n"; + } +} + +sub edit_string { + my $string = shift; + if(defined($opts{file})) { + open FILE, $opts{file} or die "$!"; + chop($string = join("", )); + close FILE; + return $string; + } + my $editor = $ENV{VISUAL} || $ENV{EDITOR}; + $editor ||= "/usr/bin/sensible-editor" if (-x "/usr/bin/sensible-editor"); + $editor ||= "/bin/vi" if (-x "/bin/vi"); + $editor ||= "/usr/bin/nano" if (-x "/usr/bin/nano"); + my $tmp = new File::Temp(SUFFIX => '.html'); + print $tmp $string, "\n"; + close $tmp; + my $mtime = (stat($tmp->filename))[9]; + system(split (/ /, $editor), $tmp->filename); + if($mtime == (stat($tmp->filename))[9]) { + return undef; + } else { + open $tmp; + chop($string = join("", <$tmp>)); + close $tmp; + return $string; + } +} + +sub new_post { + my $title = $opts{title} || Complete('Title: '); + my $category = $opts{category} || Complete('Categories: ', map {$_->{categoryName}} @{$mt->getCategoryList()}); + die "No title given.\n" unless($title); + my $description = edit_string(""); + if(defined($description)) { + my $postid = $mt->newPost({ 'title' => $title, 'description' => $description }); + $mt->setPostCategories($postid, $category ? [split(/[, ]+/, $category)] : $category) || warn "$!" + if(defined($category)); + $mt->publishPost($postid); + } else { + die "No change. Aborting.\n"; + } +} + +sub edit_post { + my $postid=shift; + my $post = $mt->getPost($postid); + my $categories = $mt->getPostCategories($postid); + my $title = $opts{title} || Complete('Title: ', $post->{title}) || $post->{title}; + my $description = edit_string($post->{description}); + if(defined($description)) { + $mt->editPost($postid, { 'title' => $title, 'description' => $description }); + $mt->setPostCategories($postid, $opts{category} ? [split(/[, ]/, $opts{category})] : $opts{category}) || warn "$!" + if(defined($opts{'category'})); + $mt->publishPost($postid); + } else { + die "No change. Aborting.\n"; + } +} + + +if ($ARGV[0] eq "help") { + Getopt::Long::HelpMessage(); +} elsif ($ARGV[0] eq "categories") { + init_mt(); + print_categories(); +} elsif ($ARGV[0] eq "list" && $ARGV[1] =~ /^\d*$/) { + init_mt(); + print_recent($ARGV[1]); +} elsif ($ARGV[0] eq "new") { + init_mt(); + new_post(); +} elsif ($ARGV[0] eq "edit" && $ARGV[1] =~ /^\d+$/) { + init_mt(); + edit_post($ARGV[1]) +} elsif ($ARGV[0] eq "show" && $ARGV[1] =~ /^\d+$/) { + init_mt(); + show_post($ARGV[1]) +} else { + Getopt::Long::HelpMessage(); + exit(1); +} +__END__ +=head1 NAME + +blogcl - Blog from the command-line + +=head1 SYNOPSIS + +B S<[ B<--title>|B<-t> "Title" ]> S<[ B<--category>|B<-c> category[,...] ]> S<[ B<--file>|B<-f> F ]> S<[ B<--username>|B<-l> username ]> S<[ B<--password>|B<-p> password ]> S<[ B<--url>|B<-u> url ]> S<[ B<--blogid>|B<-b> blogid ]> { B | B postid | B postid | B [count] | B } + +=head1 DESCRIPTION + +This is a simple script used to blog from the command-line. It was designed +for use with Drupal, but may work with any blog featuring a Movable Type +compatible interface. + +One of the commands below must be present. + +=over 4 + +=item B + +Creates a new blog entry. + +=item B + +Edit an existing blog entry. An existing postid must be specified. To find a +post's postid, use B. + +=item B + +Shows the contents of the post specified by the postid given on the +command-line. + +=item B + +List recents posts and their postids. An optional integer specifies the number +of posts to list. + +=item B + +Gives categories that are valid parameters to the B<--category> option. + +=item B + +Show usage information. + +=back + +=head1 OPTIONS + +=over 4 + +=item B<-b>, B<--blogid> + +Specify a blog ID. Defaults to the first blog found. + +=item B<-c>, B<--category> + +Specify a category for a new or existing entry. For multiple categories, +seperate them with a comma. Ignored except when used with either B or +B. + +=item B<-f>, B<--file> + +When used with B or B, specifies a file from which to read the +post's body. When used with B, specifies a file to which to write the +post's body. + +=item B<-l>, B<--username> + +Specify a username. + +=item B<-p>, B<--password> + +Specify a password. + +=item B<-t>, B<--title> + +Specify a title for a new or existing entry. Ignored except when used with +either B or B. + +=item B<-u>, B<--url> + +Specify the URL of the XMLRPC interface. + +=back + +=head1 FILES + +=over 4 + +=item F<~/.blogclrc> + +Contains options of format parameter=value. Only the long form of +options may be used. Omit leading hyphens. + +=back + +=head1 SEE ALSO + +L + +=head1 BUGS + +Error checking is minimal. + +=head1 COPYRIGHT + +Copyright by Tim Pope. All rights reserved. + +This library is a free software; you may redistribute it and/or modify it under +the same terms as perl itself. + +=head1 AUTHORS + +Tim Pope, Eperl@relongto.usE. + +L + +=cut