ブログにXML-RPC APIで、複数のファイルをアップロードするRubyスクリプト

Movable TypeやTypePadなどのブログに、コマンドラインからファイルをアップロードするRubyスクリプトを作ってみた。XML-RPC APIを利用するので、他にも対応しているブログソフト、サービスであれば問題なくつかえるはずです。

一つのファイルをアップロードする場合。

% ruby upload.rb sample.jpeg 

ディレクトリ内のファイルを、まとめてアップしたい場合。

% ruby upload.rb ディレクトリ名
FirefoxScreenSnapz005.jpg

FTPなどでファイルを直接アップしてしまうと、ブログソフトのファイルマネージャーから見れないので、API経由でアップした方が、後々ファイルを使いやすいですね。ソースコードは以下。

upload.rb

注意 : Ruby の最新バージョンでは先頭の require 'rubygems' を削除する必要があるとのこです。(コメント教えていただきました)

# TypePadやMovable Typeなどにに複数のファイルをアップロードするXML-RPCクライアント
# 利用方法: ディレクトリ名を指定した場合は、その中のファイルをすべてアップします
# % ruby upload.rb ファイル名あるいはディレクトリ名

require 'rubygems'
require "xmlrpc/client"

class TypePadUploader

  def initialize()
    
    # XMLRPC のエンドポイント
    # Movable Type "http:/ブログのスクリプトURL/mt-xmlrpc.cgi"
    # TypePad.jp "https://www.typepad.jp/t/api"
    # ココログ・フリー "https://app.f.cocolog-nifty.com/t/api"
    # ココログ・フリー以外 "https://app.cocolog-nifty.com/t/api"
    # ブログ人 "https://app.blog.ocn.ne.jp/t/api"
    
    uri = "https://www.typepad.jp/t/api" # 上記のエンドポイントURLを指定
    
    @username = "自分のログイン名" # ログインのユーザ名
    @password = "自分のパスワード" # ログインパスワード, MTの場合は、ウェブサービスパスワード
    @blogid = "ブログID" # ブログID 例 https://www.typepad.jp/t/app/weblog/manage?blog_id=120316の場合は "120316"
    @upload_dir = "uploaded" # ファイルをアップする先のディレクトリ
    client = XMLRPC::Client.new2( uri )
    @metaWeblog = client.proxy("metaWeblog")

  end

  # 接続テスト
  def connect()

    begin
      appkey = "ignored" # ignored
      result = metaWeblog.getUsersBlogs appkey, @username, @password
      p result
    rescue XMLRPC::FaultException => e
      puts "fault #{e.faultCode}: #{e.faultString}"
    end
  end
  
  # 新しい記事を投稿
  def post(title, description, categories)

    today = Time.now
    dateCreated = XMLRPC::DateTime.new(today.year, today.month,today.day, today.hour, today.min,today.sec ) # 日時
    publish = true # falseにするとドラフトに保存,公開されない

    begin
      result = @metaWeblog.newPost @blogid, @username, @password, {
        'title'=>title, 'description'=>description, 
        'dateCreated'=>dateCreated, 'categories'=>categories}, publish
      p result
    rescue XMLRPC::FaultException => e
      puts "fault #{e.faultCode}: #{e.faultString}"
    end    
    
  end

  # アップロードするファイルを探す
  def find_file(path)
    
    file_path = Dir.getwd + "/"  + path
    puts ("Searching : " + file_path)
    
    if File.exist?(file_path) then
      
      if File.directory?(file_path) then
        target = "#{file_path}/*.{jpeg,jpg,gif,png,txt,html}"
        targets = Dir.glob(  target, File::FNM_CASEFOLD)
        targets.each do |file|
          puts( "Found : " + file)
          self.upload(file)
        end
      else
        puts( "Found : " + file_path)
        self.upload(file_path)
      end # File.directory?
    else
      puts "File Not Found : " + file_path
    end # File.exist?

  end

  # XMLRPCでファイルをアップロード
  def upload(file_path)
    
    if File.file?(file_path) then
      file_name = File.basename(file_path)
      
      file = File.open(file_path,"rb").readlines.join('')
      base64 = XMLRPC::Base64.new(file)
      file_hash = {:name => @upload_dir + "/" + file_name, :bits => base64}
      
      begin
        result = @metaWeblog.newMediaObject @blogid, @username, @password, file_hash
        p result
      rescue XMLRPC::FaultException => e
        puts "fault #{e.faultCode}: #{e.faultString}"
      end   
    
    else
      puts "#{file_path} is not a file"
    end
  
  end
end

uploader = TypePadUploader.new()
uploader.find_file(ARGV[0])
こちらの記事を参考にさせていただきました。