1 # -*- coding: utf-8 -*-
 
   2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 
   3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 
   5 from datetime import datetime
 
  10 from django.core.management.base import BaseCommand
 
  12 from api.helpers import timestamp
 
  13 from api.settings import MOBILE_INIT_DB
 
  14 from catalogue.models import Book, Tag
 
  17 class Command(BaseCommand):
 
  18     help = 'Creates an initial SQLite file for the mobile app.'
 
  20     def handle(self, **options):
 
  21         # those should be versioned
 
  22         last_checked = timestamp(datetime.now())
 
  23         db = init_db(last_checked)
 
  24         for b in Book.objects.all():
 
  26         for t in Tag.objects.exclude(
 
  27                 category__in=('book', 'set', 'theme')).exclude(book_count=0):
 
  28             # only add non-empty tags
 
  35 def pretty_size(size):
 
  36     """ Turns size in bytes into a prettier string.
 
  38         >>> pretty_size(100000)
 
  43     units = ['B', 'KiB', 'MiB', 'GiB']
 
  46     while size > 1000 and units:
 
  50         return "%.1f %s" % (size, unit)
 
  51     return "%d %s" % (size, unit)
 
  54     if not isinstance(value, unicode):
 
  55         value = unicode(value, 'utf-8')
 
  57     # try to replace chars
 
  58     value = re.sub('[^a-zA-Z0-9\\s\\-]{1}', replace_char, value)
 
  60     value = re.sub(r'[^a-z0-9{|}]+', '~', value)
 
  62     return value.encode('ascii', 'ignore')
 
  66 def init_db(last_checked):
 
  67     if not os.path.isdir(MOBILE_INIT_DB):
 
  68         os.makedirs(MOBILE_INIT_DB)
 
  69     db = sqlite3.connect(os.path.join(MOBILE_INIT_DB, 'initial.db-%d' % last_checked))
 
  73     id INTEGER PRIMARY KEY, 
 
  77     html_file_size INTEGER, 
 
  79     parent_number INTEGER,
 
  86 CREATE INDEX IF NOT EXISTS book_title_index ON book (sort_key);
 
  87 CREATE INDEX IF NOT EXISTS book_title_index ON book (title);
 
  88 CREATE INDEX IF NOT EXISTS book_parent_index ON book (parent);
 
  91     id INTEGER PRIMARY KEY, 
 
  96 CREATE INDEX IF NOT EXISTS tag_name_index ON tag (name);
 
  97 CREATE INDEX IF NOT EXISTS tag_category_index ON tag (category);
 
  98 CREATE INDEX IF NOT EXISTS tag_sort_key_index ON tag (sort_key);
 
 100 CREATE TABLE state (last_checked INTEGER);
 
 103     db.executescript(schema)
 
 104     db.execute("INSERT INTO state VALUES (:last_checked)", locals())
 
 108 def current(last_checked):
 
 109     target = os.path.join(MOBILE_INIT_DB, 'initial.db')
 
 110     if os.path.lexists(target):
 
 113         'initial.db-%d' % last_checked,
 
 121         (id, title, cover, html_file,  html_file_size, parent, parent_number, sort_key, pretty_size, authors) 
 
 123         (:id, :title, :cover, :html_file, :html_file_size, :parent, :parent_number, :sort_key, :size_str, :authors);
 
 125 book_tag_sql = "INSERT INTO book_tag (book, tag) VALUES (:book, :tag);"
 
 128         (id, category, name, sort_key, books)
 
 130         (:id, :category, :name, :sort_key, :book_ids);
 
 132 categories = {'author': 'autor',
 
 140 def add_book(db, book):
 
 144         html_file = book.html_file.url
 
 145         html_file_size = book.html_file.size
 
 147         html_file = html_file_size = None
 
 149         cover = book.cover.url
 
 152     parent = book.parent_id
 
 153     parent_number = book.parent_number
 
 154     sort_key = book.sort_key
 
 155     size_str = pretty_size(html_file_size)
 
 156     authors = ", ".join(t.name for t in book.tags.filter(category='author'))
 
 157     db.execute(book_sql, locals())
 
 160 def add_tag(db, tag):
 
 162     #    category = categories[tag.category] # localized names here?
 
 163     category = tag.category
 
 165     sort_key = tag.sort_key
 
 167     books = Book.tagged_top_level([tag])
 
 168     book_ids = ','.join(str(b.id) for b in books)
 
 169     db.execute(tag_sql, locals())