#!/usr/bin/env ruby

# TypePad converter for typo by Justin Johnson <justinj@justinj.org>
#
# No need to make a backup of the original blog, since you'll just be
# importing from the TypePad export.
#
# Even so, this script is still PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.

require File.dirname(__FILE__) + '/../../config/environment'
require 'optparse'

class TypePadMigrate
  attr_accessor :options

  def initialize
    self.options = {}
    self.parse_options
    self.convert_entries
  end

  def convert_entries
    entries = File.read(self.options[:file]).split('--------')
    puts "Converting #{entries.length} entries..."

    entries.each do |e|

      article_pattern1 = /AUTHOR:\s*([^\n]*)\n
                          TITLE:\s*([^\n]*)\n
                          STATUS:\s*([^\n]*)\n
                          ALLOW\sCOMMENTS:\s*([^\n]*)\n
                          CONVERT\sBREAKS:\s*([^\n]*)\n
                          ALLOW\sPINGS:\s*([^\n]*)\n
                         /mx
      article_cat_pattern = /CATEGORY:\s*([^\n]*)\n/mx
      article_pattern2 = /DATE:\s*([^\n]*)\n
                          -----\n
                          BODY:\s*(.*?)\n
                          -----\n
                          EXTENDED\sBODY:\s*(.*?)\n
                          -----\n
                          EXCERPT:\s*(.*?)\n
                          -----\n
                          KEYWORDS:\s*([^\n]*)\n
                          -----
                         /mx
      comment_pattern = /COMMENT:\n
                         AUTHOR:\s*([^\n]*)\n
                         EMAIL:\s*([^\n]*)\n
                         IP:\s*([^\n]*)\n
                         URL:\s*([^\n]*)\n
                         DATE:\s*([^\n]*)\n
                         (.*?)\n
                         -----
                        /mx
      comments = []
      categories = []
      article_attributes = {}
    
      if e =~ /#{article_pattern1}/
        article_attributes[:author] = $1
        article_attributes[:title] = $2
        article_attributes[:published] = 1
        article_attributes[:allow_comments] = $4
        article_attributes[:allow_pings] = $6
        e.sub!(/#{article_pattern1}/, '')
      end
    
      while e =~ /#{article_cat_pattern}/
        categories << $1
        e.sub!(/#{article_cat_pattern}/, '')
      end
    
      if e =~ /#{article_pattern2}/
        article_attributes[:published_at] = $1
        article_attributes[:created_at] = $1
        article_attributes[:body] = $2
        article_attributes[:extended_html] = $3
        article_attributes[:excerpt] = $4
        article_attributes[:keywords] = $5
        e.sub!(/#{article_pattern2}/, '')
      end
    
      while e =~ /#{comment_pattern}/
        comments << {:author => $1,
                     :email => $2,
                     :ip => $3,
                     :url => $4,
                     :created_at => $5,
                     :body => $6}
        e.sub!(/#{comment_pattern}/, '')
      end

      article_attributes[:blog_name] = self.options[:blogname]
    
      if article_attributes.has_key?(:author)
        puts "Converting '#{article_attributes[:title]}'"
        a = Content.create(article_attributes)

        categories.each do |cat|
          Category.create(:name => cat) unless Category.find_by_name(cat)
        end
        categories.each do |c|
          a.categories.push_with_attributes(Category.find_by_name(c), :is_primary => 0)
        end
        comments.each do |c|
          puts "Adding comment by #{c[:author]}"
          a.comments << Comment.create(c)
        end
      end
    
    end
  end

  def parse_options
    OptionParser.new do |opt|
      opt.banner = 'Usage: typepad.rb [options]'

      opt.on('-f', '--file FILE', 'Path to TypePad export file.') do |f|
        self.options[:file] = f
      end

      opt.on('-b', '--blogname BLOGNAME', 'Name of blog defined in Typo.') do |b|
        self.options[:blogname] = b
      end

      opt.on_tail('-h', '--help', 'Show this message.') do
        puts opt
        exit
      end

      opt.parse!(ARGV)
    end

    unless self.options.include?(:file) and self.options.include?(:blogname)
      puts 'See typepad.rb --help for help.'
      exit
    end
  end
end

TypePadMigrate.new
