Upgrades
[redakcja.git] / src / depot / models.py
index 12bd9c2..23b6d9f 100644 (file)
@@ -1,11 +1,15 @@
 import json
 import os
 import tempfile
+import traceback
 import zipfile
 from datetime import datetime
+from django.conf import settings
 from django.db import models
+from django.utils.timezone import now
 from librarian.cover import make_cover
 from librarian.builders import EpubBuilder, MobiBuilder
+from .legimi import legimi
 
 
 class Package(models.Model):
@@ -35,18 +39,20 @@ class Package(models.Model):
         return json.loads(self.status_json)
 
     def set_status(self, status):
-        self.status_json = json.dumps(status, indent=4)
+        self.status_json = json.dumps(status, indent=4, ensure_ascii=False)
 
     def get_definition(self):
         return json.loads(self.definition_json)
 
     def set_definition(self, definition):
-        self.definition_json = json.dumps(definition, indent=4)
+        self.definition_json = json.dumps(definition, indent=4, ensure_ascii=False)
 
     def build(self):
         f = tempfile.NamedTemporaryFile(prefix='depot-', suffix='.zip', mode='wb', delete=False)
+        book_count = self.books.all().count()
         with zipfile.ZipFile(f, 'w') as z:
-            for book in self.books.all():
+            for i, book in enumerate(self.books.all()):
+                print(f'{i}/{book_count} {book.slug}')
                 self.build_for(book, z)
         f.close()
         with open(f.name, 'rb') as ff:
@@ -94,18 +100,71 @@ class Package(models.Model):
                 output = EpubBuilder(
                     cover=cover,
                     base_url=base_url,
-#                    fundraising=[]
+                    fundraising=item.get('fundraising', []),
                 ).build(wldoc2)
 
             elif item['type'] == 'mobi':
                 output = MobiBuilder(
                     cover=cover,
                     base_url=base_url,
+                    fundraising=item.get('fundraising', []),
                 ).build(wldoc2)
 
-            fname = f'{slug}/{slug}.{ext}'
+            fname = f'{slug}/{slug}.'
+            if 'slug' in item:
+                fname += item['slug'] + '.'
+            fname += ext
 
             z.writestr(
                 fname,
                 output.get_bytes()
             )
+
+
+class LegimiBookPublish(models.Model):
+    book = models.ForeignKey('documents.Book', models.CASCADE)
+    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.SET_NULL, null=True)
+    created_at = models.DateTimeField()
+    started_at = models.DateTimeField(null=True, blank=True)
+    finished_at = models.DateTimeField(null=True, blank=True)
+    status = models.PositiveSmallIntegerField(choices=[
+        (0, 'queued'),
+        (10, 'running'),
+        (100, 'done'),
+        (110, 'error'),
+    ], default=0)
+    error = models.TextField(blank=True)
+
+    @classmethod
+    def create_for(cls, book, user):
+        book.assert_publishable()
+        changes = book.get_current_changes(publishable=True)
+        me = cls.objects.create(book=book, user=user, created_at=now())
+        for change in changes:
+            me.legimichunkpublish_set.create(change=change)
+        return me
+
+    def publish(self):
+        self.status = 10
+        self.started_at = now()
+        self.save(update_fields=['status', 'started_at'])
+        try:
+            changes = [
+                p.change for p in
+                self.legimichunkpublish_set.order_by('change__chunk__number')
+            ]
+            legimi.send_book(self.book, changes=changes)
+            legimi.edit_sale(self.book)
+        except Exception:
+            self.status = 110
+            self.error = traceback.format_exc()
+        else:
+            self.status = 100
+            self.error = ''
+        self.finished_at = now()
+        self.save(update_fields=['status', 'finished_at', 'error'])
+
+
+class LegimiChunkPublish(models.Model):
+    book_publish = models.ForeignKey(LegimiBookPublish, models.CASCADE)
+    change = models.ForeignKey('documents.ChunkChange', models.CASCADE)