#!/usr/bin/env perl

# Movable Type SQLite3 to Jeykll conversion script
# Copyright 2015 Jonathan McDowell <noodles@earth.li>
# All modifications licensed under GPLv2+
# Based on Movable Type to ikiwiki conversion script (c) Nei <anti.teamidiot.de>

#
# Takes a Movable Type SQLite3 database file and extracts each post as
# in individual file into the _posts/ directory, then commits it to git.
# Also outputs a wxr.xml file containing all comments, suitable for
# importing into disqus.
#
# Assumes its running inside a git repository and there's a _posts/
# directory that already exists. Doesn't cope with more than one MT
# blog or author.
#

use utf8;
use strict;
use warnings;
use autodie;
use DBI;
use DBD::SQLite;
use XML::Simple;

# Set this as appropriate
my $baseurl = "http://www.earth.li/~noodles/blog-new/";
my $db = "/home/noodles/blog/mt.db";
# Set to 1 to generate posts + WXR, 0 to only generate WXR
my $dogit = 1;

# Shouldn't need to alter anything below.

my $count;
$count->{posts} = $count->{comments} = 0;

my $dbh = DBI->connect("dbi:SQLite:dbname=$db", "", "");

# Hash ref to hold the comments for WXR output
my $wxr;
$wxr->{channel}->{item} = [];

my $sth = $dbh->prepare("SELECT * FROM mt_entry");
$sth->execute();

# Walk through each post
while (my $entry = $sth->fetchrow_hashref) {
    my $format = $entry->{entry_convert_breaks};

    my @tags = ();
    my $sth2 = $dbh->prepare("SELECT tag_name FROM mt_tag WHERE mt_tag.tag_id IN (SELECT objecttag_tag_id FROM mt_objecttag WHERE objecttag_blog_id = ? AND objecttag_object_id = ?)");
    $sth2->execute($entry->{entry_blog_id}, $entry->{entry_id});
    while (my $tag = $sth2->fetchrow_hashref) {
      push @tags, $tag->{tag_name};
    }

    $sth2 = $dbh->prepare("SELECT category_label FROM mt_category WHERE mt_category.category_id IN (SELECT placement_category_id FROM mt_placement WHERE placement_blog_id = ? AND placement_entry_id = ?)");
    $sth2->execute($entry->{entry_blog_id}, $entry->{entry_id});
    while (my $tag = $sth2->fetchrow_hashref) {
      push @tags, $tag->{category_label};
    }

    my $filename = $entry->{entry_basename};
    my $text = $entry->{entry_text};
    my $text_more = $entry->{entry_text_more};
    my $title = $entry->{entry_title};
    (my $display_title = $title) =~ s/"/&quot;/g;
    my $date = $entry->{entry_authored_on};

    my $datestr = substr $date, 0, 10;
    $filename =~ s/_/-/g;

    my $ext = 'html';
    if ($format =~ /textile/) { $ext = 'txtl'; }
    elsif ($format =~ /markdown/) { $ext = 'mdwn'; }
    else { $format = 'html'; }
    my $filename2 = '_posts/' . $datestr . '-' . $filename;
    my $msg = 'Entry ' . $entry->{entry_id} . ': ' . $title;
    if ($dogit) {
      open my $of, '>:utf8', "$filename2.$format";
      print $of "---\n";
      print $of "layout: post\n";
      print $of "title: \"$display_title\"\n";
      print $of "date: $date\n";
      if (@tags) {
        print $of "tags:\n";
        foreach my $tag (@tags) {
          print $of "- ", $tag, "\n";
        }
      }
      print $of "comments: true\n";
      print $of "---\n";
      print $of $text;
      close $of;
      system("git", "add", "$filename2.$format");
      system("git", "commit", "--date", $date, "-m", $msg);
    }
    $count->{posts}++;

    my $wxritem;
    $wxritem->{title} = $display_title;
    $datestr = substr $date, 0, 7;
    $datestr =~ s/-/\//g;
    $wxritem->{link} = $baseurl . $datestr . '/' . $filename . '.html';
    $wxritem->{'content:encoded'} = '<![CDATA[placeholder]]>';
    # Matches Jekyll's page.id
    $wxritem->{'dsq:thread_identifier'} = '/' . $datestr . '/' . $filename;
    $wxritem->{'wp:post_date_gmt'} = $date;
    $wxritem->{'wp:comment_status'} = 'open';
    $wxritem->{'wp:comment'} = [];

    # Walk through each comment on this post
    $sth2 = $dbh->prepare("SELECT * FROM mt_comment WHERE comment_blog_id = ? AND comment_entry_id = ?");
    $sth2->execute($entry->{entry_blog_id}, $entry->{entry_id});
    while (my $comment = $sth2->fetchrow_hashref) {
      my $wxrcomment;
      $wxrcomment->{'wp:comment_id'} = $comment->{comment_id};
      $wxrcomment->{'wp:comment_author'} = $comment->{comment_author};
      if ($comment->{comment_email} =~ /http:/) {
        $wxrcomment->{'wp:comment_author_email'} = '';
        $wxrcomment->{'wp:comment_author_url'} = $comment->{comment_email};
      } else {
        $wxrcomment->{'wp:comment_author_email'} = $comment->{comment_email};
        $wxrcomment->{'wp:comment_author_url'} = $comment->{comment_url};
      }
      $wxrcomment->{'wp:comment_author_IP'} = $comment->{comment_ip};
      $wxrcomment->{'wp:comment_date_gmt'} = $comment->{comment_created_on};
      $wxrcomment->{'wp:comment_content'} = '<![CDATA[' . $comment->{comment_text} . ']]>';
      $wxrcomment->{'wp:comment_approved'} = '1';
      $wxrcomment->{'wp:comment_parent'} = $comment->{comment_parent_id};

      push @{$wxritem->{'wp:comment'}}, $wxrcomment;
      $count->{comments}++;
    }

    push @{$wxr->{channel}->{item}}, $wxritem;
}

my $xs = XML::Simple->new(NoAttr => 1,
  NoEscape => 1,
  RootName => 'rss',
  SuppressEmpty => '');
open XML,">wxr.xml";
print XML "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print XML $xs->XMLout($wxr);
close XML;

print "Converted ", $count->{posts}, " posts with ", $count->{comments},
        " comments.\n";
