e9727daaffa508436f333b8028653bb1e700a8b4
[redakcja.git] / apps / catalogue / management / commands / insert_isbn.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 #
6 import csv
7
8 import sys
9 from django.contrib.auth.models import User
10 from lxml import etree
11 from optparse import make_option
12
13 from collections import defaultdict
14 from django.core.management import BaseCommand
15
16 from catalogue.models import Book
17 from librarian import RDFNS, DCNS
18
19 CONTENT_TYPES = {
20     'pdf':  'application/pdf',
21     'epub': 'application/epub+zip',
22     'mobi': 'application/x-mobipocket-ebook',
23     'txt':  'text/plain',
24     'html': 'text/html',
25 }
26
27
28 ISBN_TEMPLATES = (
29     r'<dc:relation.hasFormat id="%(format)s" xmlns:dc="http://purl.org/dc/elements/1.1/">%(url)s'
30     r'</dc:relation.hasFormat>',
31     r'<meta refines="#%(format)s" id="%(format)s-id" property="dcterms:identifier">ISBN-%(isbn)s</meta>',
32     r'<meta refines="#%(format)s-id" property="identifier-type">ISBN</meta>',
33     r'<meta refines="#%(format)s" property="dcterms:format">%(content_type)s</meta>',
34 )
35
36
37 def url_for_format(slug, format):
38     if format == 'html':
39         return 'https://wolnelektury.pl/katalog/lektura/%s.html' % slug
40     else:
41         return 'http://wolnelektury.pl/media/book/%(format)s/%(slug)s.%(format)s' % {'slug': slug, 'format': format}
42
43
44 class Command(BaseCommand):
45     option_list = BaseCommand.option_list + (
46         # make_option('-q', '--quiet', action='store_false', dest='verbose',
47         #     default=True, help='Less output'),
48         # make_option('-d', '--dry-run', action='store_true', dest='dry_run',
49         #     default=False, help="Don't actually touch anything"),
50         make_option(
51             '-u', '--username', dest='username', metavar='USER',
52             help='Assign commits to this user (required, preferably yourself).'),
53     )
54     args = 'csv_file'
55
56     def handle(self, csv_file, **options):
57         username = options.get('username')
58
59         if username:
60             user = User.objects.get(username=username)
61         else:
62             print 'Please provide a username.'
63             sys.exit(1)
64
65         csvfile = open(csv_file, 'rb')
66         isbn_lists = defaultdict(list)
67         for slug, format, isbn in csv.reader(csvfile, delimiter=','):
68             isbn_lists[slug].append((format, isbn))
69         csvfile.close()
70
71         for slug, isbn_list in isbn_lists.iteritems():
72             book = Book.objects.get(dc_slug=slug)
73             chunk = book.chunk_set.first()
74             old_head = chunk.head
75             src = old_head.materialize()
76             tree = etree.fromstring(src)
77             isbn_node = tree.find('.//' + DCNS("relation.hasFormat"))
78             if isbn_node is not None:
79                 raise Exception('%s already contains ISBN metadata!' % slug)
80             desc = tree.find(".//" + RDFNS("Description"))
81             for format, isbn in isbn_list:
82                 for template in ISBN_TEMPLATES:
83                     isbn_xml = template % {
84                         'format': format,
85                         'isbn': isbn,
86                         'content_type': CONTENT_TYPES[format],
87                         'url': url_for_format(slug, format),
88                     }
89                     element = etree.XML(isbn_xml)
90                     element.tail = '\n'
91                     desc.append(element)
92             new_head = chunk.commit(
93                 etree.tostring(tree, encoding=unicode),
94                 author=user,
95                 description='automatyczne dodanie isbn'
96             )
97             print 'committed %s' % slug
98             if old_head.publishable:
99                 new_head.set_publishable(True)
100             else:
101                 print 'Warning: %s not publishable' % slug