bgneal@535: """
bgneal@535: import_old_potd_comments.py - For importing comments on POTD's from SG101 1.0
bgneal@535: as csv files.
bgneal@535: 
bgneal@535: """
bgneal@535: from __future__ import with_statement
bgneal@535: import csv
bgneal@535: import optparse
bgneal@535: import sys
bgneal@535: from datetime import datetime
bgneal@535: 
bgneal@535: from django.core.management.base import LabelCommand, CommandError
bgneal@535: from django.contrib.auth.models import User
bgneal@535: from django.contrib.contenttypes.models import ContentType
bgneal@535: 
bgneal@535: from comments.models import Comment
bgneal@535: from potd.models import Photo
bgneal@535: import legacy.data
bgneal@535: from legacy.html2md import MarkdownWriter
bgneal@535: 
bgneal@535: 
bgneal@535: PHOTO_ID_OFFSET = 100
bgneal@535: ID_OFFSET = 3000
bgneal@535: 
bgneal@535: 
bgneal@535: class Command(LabelCommand):
bgneal@535:     args = '<filename filename ...>'
bgneal@535:     help = 'Imports POTD comments from the old database in CSV format'
bgneal@535:     option_list = LabelCommand.option_list + (
bgneal@535:         optparse.make_option("-p", "--progress", action="store_true",
bgneal@535:             help="Output a . after every 20 items to show progress"),
bgneal@537:         optparse.make_option("--fix-mode", action="store_true",
bgneal@537:             help="Only create comments if they don't exist already"),
bgneal@535:     )
bgneal@535:     md_writer = MarkdownWriter()
bgneal@535: 
bgneal@535:     def handle_label(self, filename, **options):
bgneal@535:         """
bgneal@535:         Process each line in the CSV file given by filename by
bgneal@535:         creating a new POTD comment.
bgneal@535: 
bgneal@535:         """
bgneal@535:         self.show_progress = options.get('progress')
bgneal@537:         self.fix_mode = options.get('fix_mode')
bgneal@535:         self.users = {}
bgneal@535: 
bgneal@535:         try:
bgneal@535:             with open(filename, "rb") as f:
bgneal@535:                 self.reader = csv.DictReader(f)
bgneal@535:                 num_rows = 0
bgneal@535:                 try:
bgneal@535:                     for row in self.reader:
bgneal@535:                         self.process_row(row)
bgneal@535:                         num_rows += 1
bgneal@535:                         if self.show_progress and num_rows % 20 == 0:
bgneal@535:                             sys.stdout.write('.')
bgneal@535:                             sys.stdout.flush()
bgneal@535:                 except csv.Error, e:
bgneal@535:                     raise CommandError("CSV error: %s %s %s" % (
bgneal@535:                         filename, self.reader.line_num, e))
bgneal@535: 
bgneal@535:                 print
bgneal@535: 
bgneal@535:         except IOError:
bgneal@535:             raise CommandError("Could not open file: %s" % filename)
bgneal@535: 
bgneal@535:     def process_row(self, row):
bgneal@535:         """
bgneal@535:         Process one row from the CSV file: create a Comment object for
bgneal@535:         the row and save it in the database.
bgneal@535: 
bgneal@535:         """
bgneal@537:         comment_id = int(row['cid']) + ID_OFFSET
bgneal@537: 
bgneal@537:         if self.fix_mode:
bgneal@537:             try:
bgneal@537:                 c = Comment.objects.get(pk=comment_id)
bgneal@537:             except Comment.DoesNotExist:
bgneal@537:                 pass
bgneal@537:             else:
bgneal@537:                 return
bgneal@537: 
bgneal@535:         try:
bgneal@535:             user = self._get_user(row['username'].decode('latin-1'))
bgneal@535:         except User.DoesNotExist:
bgneal@535:             print "Could not find user %s for comment %s; skipping." % (
bgneal@535:                     row['username'], row['cid'])
bgneal@535:             return
bgneal@535: 
bgneal@535:         pid = int(row['pid']) + PHOTO_ID_OFFSET
bgneal@535:         try:
bgneal@535:             photo = Photo.objects.get(id=pid)
bgneal@535:         except Photo.DoesNotExist:
bgneal@535:             print "Could not find photo %s for comment %s; skipping." % (
bgneal@535:                     pid, row['cid'])
bgneal@535:             return
bgneal@535: 
bgneal@535:         comment = Comment(
bgneal@537:             id=comment_id,
bgneal@535:             content_type=ContentType.objects.get_for_model(photo),
bgneal@535:             object_id=photo.id,
bgneal@535:             user=user,
bgneal@535:             comment=self.to_markdown(row['comment'].decode('latin-1')),
bgneal@535:             creation_date=datetime.strptime(row['date'], "%Y-%m-%d %H:%M:%S"),
bgneal@535:             ip_address='192.0.2.0',     # TEST-NET
bgneal@535:             is_public=True,
bgneal@535:             is_removed=False,
bgneal@535:         )
bgneal@535: 
bgneal@535:         comment.save()
bgneal@535: 
bgneal@535:     def _get_user(self, username):
bgneal@535:         """
bgneal@535:         Returns the user object with the given username.
bgneal@535:         Throws User.DoesNotExist if not found.
bgneal@535: 
bgneal@535:         """
bgneal@535:         try:
bgneal@535:             return self.users[username]
bgneal@535:         except KeyError:
bgneal@535:             pass
bgneal@535: 
bgneal@535:         try:
bgneal@535:             user = User.objects.get(username=username)
bgneal@535:         except User.DoesNotExist:
bgneal@535:             old_name = username.lower()
bgneal@535:             try:
bgneal@535:                 user = User.objects.get(
bgneal@535:                         username=legacy.data.KNOWN_USERNAME_CHANGES[old_name])
bgneal@535:             except KeyError:
bgneal@535:                 raise User.DoesNotExist
bgneal@535: 
bgneal@535:         self.users[username] = user
bgneal@535:         return user
bgneal@535: 
bgneal@535:     def to_markdown(self, s):
bgneal@535: 
bgneal@535:         s = s.replace('\n', '\n<br />')
bgneal@535:         self.md_writer.reset()
bgneal@535:         self.md_writer.feed(s)
bgneal@535:         return self.md_writer.markdown()