The Code
This code doesn't fully implement all of the functions you'll find in the metaWeblog API. Instead, it implements two methods: getUsersBlogs and newPost. These two methods are the bare minimum needed to interface with other systems and add new weblog posts.
As you'd expect, getUsersBlogs returns a list of weblogs that a particular user can post to at a weblog service. Because Yahoo! 360 users are limited to one blog per Yahoo! ID, this function simply logs in to Yahoo! and fetches the name of the user's Yahoo! 360 blog. The newPost function also logs in to Yahoo!, changes the incoming text of a post if necessary, and adds the text as a new post to the Yahoo! 360 weblog.
Save the following code to a file called Y360_api.pl:
#!/usr/bin/perl
# Y360_api.pl
# Implements a minimalist metaWeblog API for Yahoo! 360 blogs.
# You can read more about the metaWeblog API here:
# http://www.xmlrpc.com/metaWeblogApi
#
# Usage: send metaWeblog API requests for methods:
#
# getUsersBlogs
# Returns the name and URL of a Yahoo! 360
# blog for the given user.
# newPost
# Adds a post with the incoming text to
# a Yahoo! 360 blog for the given user.
use strict;
use XMLRPC::Transport::HTTP;
XMLRPC::Transport::HTTP::CGI
-> dispatch_to('metaWeblog')
-> handle
;
package metaWeblog;
use WWW::Yahoo::Login qw( login logout );
use WWW::Mechanize;
use Image::Size 'html_imgsize';
use LWP::Simple;
my $mech = WWW::Mechanize->new(autocheck => 1);
sub getUsersBlogs {
my($app, $msg, $user, $pass) = @_;
# Set some defaults
my $blog_url = "http://blog.360.yahoo.com/blog/";
my $blog_name = "My Yahoo! 360 Blog";
# Log into Yahoo! 360
my $mech = WWW::Mechanize->new();
my $login = login(
mech => $mech,
uri => 'http://blog.360.yahoo.com/blog/',
user => $user,
pass => $pass,
);
# Get weblog URL and title
if ($login) {
my $html = $mech->response()->content( );
if ($html =~ m!<h2>(.*?)</h2>!mgis) {
$blog_name = $1;
}
if ($html =~ m!<li><a href="(.*?)">View Blog</a></li>!mgis) {
$blog_url = $1;
}
}
# Send the response
my @res;
push @res, { url => SOAP::Data->type(string => $blog_url),
blogid => SOAP::Data->type(string => "1"),
blogName => SOAP::Data->type(string=> $blog_name) };
\@res;
}
sub newPost {
shift if UNIVERSAL::isa($_[0] => __PACKAGE__);
my($blog_id, $user, $pass, $item, $publish) = @_;
# Log into Yahoo! 360
my $mech = WWW::Mechanize->new();
my $login = login(
mech => $mech,
uri => 'http://blog.360.yahoo.com/blog/compose.html',
user => $user,
pass => $pass,
);
# Add width/height to image tags (for Flickr posts)
if ($item->{description} =~ m!(.*?<img src="(.*?)" .*?)( )(/>.*)!mgis) {
my $file = get($2);
my $size = html_imgsize(\$file);
$item->{description} = "$1 $size $4";
}
# Write post description to a file
open(FILE, ">> post.txt") or die("Couldn't open post.txt\n");
print FILE $item->{description} . "\n\n";
# Remove initial div tag from del.icio.us posts
$item->{description} =~ s!<div class="delicious-link">(.*?)</div>
!$1!gis;
# Strip line breaks
$item->{description} =~ s!\n!!gis;
# If login succeeded, add post and send a successful
# response with the generic 1000 as the post ID
if ($login && $item->Add an API to Your Yahoo! 360 Blog) {
my $form = $mech->form_name("blog_compose");
$mech->field("title", $item->Add an API to Your Yahoo! 360 Blog);
$mech->field("contents", $item->{description});
$mech->click("post");
SOAP::Data->type(string => "1000");
} else {
return error $WWW::Yahoo::Login::ERROR;
}
}
This script is built specifically to work with the API-related services at Flickr and del.icio.us—a bookmark manager available at http://del.icio.us. The newPost subroutine reformats incoming text based on the text that these services provide. For example, Flickr doesn't provide height and width attributes for image tags in the HTML it produces, and Yahoo! 360 requires those attributes in weblog posts. So this script uses the Image::Size module to add those attributes to the text.