#---------------------------------------------------------------------
# Backup or Restore the content of a blog to/from YAML whose host server
# supports the MetaWebLog API. (Currently supports typo|wordpress|blogger)
#
# Sample command lines (program prompts for blog password)
#  ruby backup_blog.rb username improvingwetware.com backup.yaml 25 typo backup
#  ruby backup_blog.rb username improvingwetware.com backup.yaml num_posts typo restore
# (the num_posts argument is unused on restore)
#
# Note: typo has bug whereby it ignores createdDate when creating URL, but does show 
# correctly posted x days ago. Clicking on the link on the home page fails
# but it generates feed OK... puzzling... not fixed yet.
#
# Copyright (C) 2007 Derek Mahar & Pete McBreen 
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#---------------------------------------------------------------------
require "rubygems"

blog_protocol = { 	"typo" => "/backend/xmlrpc" ,
					"wordpress" => "/xmlrpc.php" ,
					"blogger" => "/api/RPC2" }

if ARGV.length != 6
  	puts "Usage: backup_blog username hostname backup_filename num_posts blog_software backup|restore"
  	puts ARGV
  	exit
else
  	if ARGV[5] != "backup" and ARGV[5] != "restore" then
  		puts "last argument must be backup or restore"
  		exit
  	end
  	if !blog_protocol.include?(ARGV[4]) then
  		puts "only the following blog_software providers are supported"
  		blog_protocol.each{|k,v| puts k}
  		exit
  	end
end
# Create an XMLRPC client for blog.
require "xmlrpc/client"
require "yaml"

# Set command line arguments into variables for readability 
username = ARGV[0]
blog_host = ARGV[1]
backup_filename = ARGV[2]
post_count = ARGV[3].to_i
blog_path = blog_protocol.fetch(ARGV[4])
backup = true
if ARGV[5] == "restore" then backup = false end 

print "Please enter your #{ARGV[4]} password for #{username} on #{blog_host} :"
password = $stdin.gets.chomp

blog_client = XMLRPC::Client.new(blog_host, blog_path)

# Retrieve first blog properties from blog server.

application_key = 1 # may need to be different, works OK for typo and wordpress
blogs = blog_client.call(
	"blogger.getUsersBlogs",
  	application_key,
  	username,
  	password)

blog_id = blogs[0].fetch("blogid")

if backup then 
	# Retrieve most recent entries from source blog 
	source_posts = blog_client.call(
  		"metaWeblog.getRecentPosts",
  		blog_id,
  		username,
  		password,
  		post_count)
  		puts "backup"
	f = File.new(backup_filename, "w")
	f.puts source_posts.to_yaml
	f.close
	puts "Backed up #{source_posts.length} posts for #{blog_host} to #{backup_filename} in YAML format" 
else
	# Restore from the YAML file and upload entries
	source_posts = YAML.load_file( backup_filename )
	puts "Restoring #{source_posts.length} posts from from #{backup_filename}" 
	source_posts.each {|content|
		retries = 3
		while (retries > 0) 
			begin
        		blog_client.call(
        			'metaWeblog.newPost', 
        			blog_id, 
        			username, 
        			password, 
        			content, 
        			true)
      			retries = 0
      			puts "posted #{content['title']} #{content['dateCreated'].to_date}"
      		rescue Timeout::Error
		    	puts "Retrying #{content['title']}, retry #{retries}"
        		retries =- 1
      		end
    	end
	}
	puts "Restored #{source_posts.length} posts to #{blog_host} from #{backup_filename}" 
end
