#! python3.6
"""
Export Comments from BLogger XML

Takes in a Blogger export XML file and spits out each comment in a separate
file, such that can be used with the [Pelican Comment System]
(https://bernhard.scheirle.de/posts/2014/March/29/static-comments-via-email/).

May be simple to extend to export posts as well.

For a more detailed description, read my blog post at
    http://blog.minchin.ca/2016/12/blogger-comments-exported.html

Author: Wm. Minchin -- minchinweb@gmail.com
License: MIT
Changes:

 - 2016.12.29 -- initial release
 - 2017.01.10 -- clean-up for addition in Pelican Comment System repo
"""

from pathlib import Path

import untangle

###############################################################################
# Constants                                                                   #
###############################################################################

BLOGGER_EXPORT = r'c:\tmp\blog.xml'
COMMENTS_DIR = 'comments'
COMMENT_EXT = '.md'
AUTHORS_FILENAME = 'authors.txt'

###############################################################################
# Main Code Body                                                              #
###############################################################################

authors_and_pics = []


def main():
    obj = untangle.parse(BLOGGER_EXPORT)

    templates = 0
    posts = 0
    comments = 0
    settings = 0
    others = 0

    for entry in obj.feed.entry:
        try:
            full_type = entry.category['term']
        except TypeError:
            # if a post is under multiple categories
            for my_category in entry.category:
                full_type = my_category['term']
                # str.find() uses a return of `-1` to denote failure
                if full_type.find('#') != -1:
                    break
            else:
                others += 1

        simple_type = full_type[full_type.find('#')+1:]

        if 'settings' == simple_type:
            settings += 1
        elif 'post' == simple_type:
            posts += 1
            # process posts here
        elif 'comment' == simple_type:
            comments += 1
            process_comment(entry, obj)
        elif 'template' == simple_type:
            templates += 1
        else:
            others += 1

    export_authors()

    print('''
            {} template
            {} posts (including drafts)
            {} comments
            {} settings
            {} other entries'''.format(templates,
                                       posts,
                                       comments,
                                       settings,
                                       others))


def process_comment(entry, obj):
    # e.g. "tag:blogger.com,1999:blog-26967745.post-4115122471434984978"
    comment_id = entry.id.cdata
    # in ISO 8601 format, usable as is
    comment_published = entry.published.cdata
    comment_body = entry.content.cdata
    comment_post_id = entry.thr_in_reply_to['ref']
    comment_author = entry.author.name.cdata
    comment_author_pic = entry.author.gd_image['src']
    comment_author_email = entry.author.email.cdata

    # add author and pic to global list
    global authors_and_pics
    authors_and_pics.append((comment_author, comment_author_pic))

    # use this for a filename for the comment
    # e.g. "4115122471434984978"
    comment_short_id = comment_id[comment_id.find('post-')+5:]

    comment_text = "date: {}\nauthor: {}\nemail: {}\n\n{}\n"\
                        .format(comment_published,
                                comment_author,
                                comment_author_email,
                                comment_body)

    # article
    for entry in obj.feed.entry:
        entry_id = entry.id.cdata
        if entry_id == comment_post_id:
            article_entry = entry
            break
    else:
        print("No matching article for comment", comment_id, comment_post_id)
        # don't process comment further
        return

    # article slug
    for link in article_entry.link:
        if link['rel'] == 'alternate':
            article_link = link['href']
            break
    else:
        article_title = article_entry.title.cdata
        print('Could not find slug for', article_title)
        article_link = article_title.lower().replace(' ', '-')

    article_slug = article_link[article_link.rfind('/')+1:
                                                    article_link.find('.html')]

    comment_filename = Path(COMMENTS_DIR).resolve()
    # folder; if it doesn't exist, create it
    comment_filename = comment_filename / article_slug
    comment_filename.mkdir(parents=True, exist_ok=True)
    # write the comment file
    comment_filename = comment_filename / (comment_short_id + COMMENT_EXT)
    comment_filename.write_text(comment_text)


def export_authors():
    to_export = set(authors_and_pics)
    to_export = list(to_export)
    to_export.sort()

    str_export = ''
    for i in to_export:
        str_export += (i[0] + '\t\t' + i[1] + '\n')

    authors_filename = Path(COMMENTS_DIR).resolve() / AUTHORS_FILENAME
    authors_filename.write_text(str_export)


if __name__ == "__main__":
    main()
