#!/usr/bin/perl # # post2blog - a tool to post a new entry to Movable Type with attachments # # Copyright (C) 2003 - 2006 Jiro Motonaga # All rights reserved. # This is free software with NO WARRANTY. # # You can redistribute it and/or modify it under the terms of # the GNU General Public License version 2. # BEGIN { my $MT_DIR = '/Library/WebServer/Documents/mt/'; push @INC, $MT_DIR . 'extlib'; push @INC, $MT_DIR . 'lib'; } use strict; my $url = 'http://www.your-site.com/movabletype/mt-xmlrpc.cgi'; # CGIPath + 'mt-xmlrpc.cgi' my $blog_id = 2; my $username = 'Melody'; my $password = 'Nelson'; my $category_id = 1; my @categories = (2, 3, 4); my $parse_path = '/Users/Shared/post2blog'; my $ffmpeg = '/usr/local/bin/ffmpeg'; my ($maxx, $maxy) = (320, 320); use MIME::Parser; #use Data::Dumper; use File::Basename; use Jcode; use Image::Size; use XMLRPC::Lite; use MT::Sanitize; my $j = new Jcode; #open(OUT, ">$parse_path/mtmail"); my $str=''; while() { $str = $str.$_; #print OUT $_; } #close(OUT); my $parser = new MIME::Parser; $parser->output_under($parse_path); $parser->filer->ignore_filename(1); my $entity = $parser->parse_data($str); my $head = $entity->head; my $sub = $head->get('Subject'); $sub = MT::Sanitize->sanitize($sub); my $message_id = $head->get('Message-ID'); my $cnttype = $entity->mime_type; $sub = $j->set($sub)->mime_decode->utf8; $sub =~ s/[\r\n]//g; $sub =~ s/ +$//g; $sub = 'Untitled' unless ($sub); $message_id =~ s/[<>]//g; $message_id =~ s/\@.*//g; $message_id =~ s/[\r\n]//g; my @entities = decode_mime($entity); my $rpc = XMLRPC::Lite->new; $rpc->proxy($url); my $cont; foreach my $entity (@entities) { if (ref $entity) { my ($file, $filename) = @{ $entity }; $filename = MT::Sanitize->sanitize($filename); my $tag = upload($rpc, $file, $filename); $cont .= $tag; } else { open(CONT, $entity) or die "can't open text file '$entity': $!"; my $tmp; while () { s/\r\n/\n/g; s/\r/\n/g; $tmp .= $_; } close(CONT); $tmp = $j->set($tmp)->utf8; $cont .= MT::Sanitize->sanitize($tmp); } } my @conts = split(/\n\n\n/, $cont); my $description = shift(@conts); my $text_more = join("\n\n\n", @conts); my $title = $sub; my $ret = $rpc->call('metaWeblog.newPost', $blog_id, $username, $password, { 'title' => $title, 'description' => $description, 'mt_text_more' => $text_more }, 0, ); my $post_id; if (defined ($ret)) { $post_id = $ret->result(); } else { die 'metaWeblog.newPost failed'; } if ($category_id) { my $cats = [{ 'categoryId' => $category_id, 'isPrimary' => 1, }]; foreach my $cat_id (@categories) { push @$cats, { 'categoryId' => $cat_id }; } $ret = $rpc->call('mt.setPostCategories', $post_id, $username, $password, $cats, ); die 'mt.setPostCategories failed' unless (defined ($ret)); } $ret = $rpc->call('metaWeblog.editPost', $post_id, $username, $password, { 'title' => $title, 'description' => $description, 'mt_text_more' => $text_more }, 1 ); die 'metaWeblog.editPost failed' unless (defined ($ret)); #print Dumper $ret->result; #print Dumper $ret->fault; #$parser->filer->purge; sub decode_mime { my $entity = shift; my (@entities, @ent, $cnttype, $cntpath, $cntname); my $partnum = $entity->parts; if ($entity->is_multipart) { # multi parts for (my $pn = 0; $pn < $partnum; $pn++) { my $part = $entity->parts($pn); if ($part->is_multipart) { @ent = decode_mime($part); push(@entities, @ent); } else { $cnttype = $part->mime_type; $cntpath = $part->bodyhandle->path; $cntname = $part->head->mime_attr('content-type.name') || $part->head->mime_attr('content-disposition.filename'); $cntname = $j->set($cntname)->mime_decode->utf8; @ent = arrange_parts($cnttype, $cntpath, $cntname); push(@entities, @ent); } } } else { # single part $cnttype = $entity->mime_type; $cntpath = $entity->bodyhandle->path; $cntname = $entity->head->mime_attr('content-type.name') || $entity->head->mime_attr('content-disposition.filename'); $cntname = $j->set($cntname)->mime_decode->utf8; @ent = arrange_parts($cnttype, $cntpath, $cntname); push(@entities, @ent); } return @entities; } sub arrange_parts { my ($cnttype, $cntpath, $cntname) = @_; my @entity; if ($cnttype =~ /^text\/plain$/i) { # plain text push(@entity, $cntpath); } else { # attachment unless ($cnttype eq 'application/applefile') { unless ($cntname) { my ($filename, $filepath, $suffix) = fileparse($cntpath, '\..+'); $cnttype =~ s/\//-/; $cntname = "${message_id}_${filename}_$cnttype$suffix"; } my $orgsuffix = ($cntname =~ /.+(\..+)/) ? $1 : ''; if ($orgsuffix =~ /^\.(amc|3gp)$/ && -x $ffmpeg) { my ($movthumbpath, $movthumbname) = movie2thumb($cntpath); push(@entity, [ $movthumbpath, $movthumbname ]); } push(@entity, [ $cntpath, $cntname ]); } } return @entity; } sub movie2thumb { my $movie = shift; my ($filename, $filepath, $suffix) = fileparse($movie, '\.(amc|3gp)'); my $jpg = $filepath.$filename.'%d.jpg'; my $jpg1 = $filename.'1.jpg'; system("$ffmpeg -f m4v -i $movie -f jpeg -t 0.01 $jpg"); return ($filepath.$jpg1, $jpg1); } sub upload { my ($rpc, $file, $filename) = @_; my $tag; open(BIN, $file) or die "can't open attached file '$file': $!"; my $bindata; while () { $bindata .= $_; } close(BIN); my $ret = $rpc->call('metaWeblog.newMediaObject', $blog_id, $username, $password, { 'bits' => $bindata, 'name' => $filename }, 1 ); if (defined ($ret) && $ret->result) { my $returl = $ret->result->{url}; if ($returl =~ /\.(jpe?g|gif|png)$/i) { my ($imgx, $imgy) = imgsize($file); if ($imgx > $maxx) { $imgy = sprintf("%d", $imgy * ($maxx / $imgx)); $imgx = $maxx; } $tag = "\"$filename\"
"; } else { $tag = "$filename
"; } } else { die "metaWeblog.newMediaObject '$file ($filename)' failed"; } return $tag; }