Legimi button!
authorRadek Czajka <rczajka@rczajka.pl>
Thu, 14 Jul 2022 09:28:28 +0000 (11:28 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Thu, 14 Jul 2022 09:28:28 +0000 (11:28 +0200)
src/depot/legimi.py
src/depot/management/commands/depot.py [new file with mode: 0644]
src/depot/migrations/0002_legimibookpublish_legimichunkpublish.py [new file with mode: 0644]
src/depot/models.py
src/depot/urls.py [new file with mode: 0644]
src/depot/views.py
src/documents/models/book.py
src/documents/templates/documents/book_detail.html
src/redakcja/urls.py

index 99f7062..1810ec5 100644 (file)
@@ -175,8 +175,8 @@ class Legimi:
 #     success: true
 #     model.Url
 
-    def send_book(self, book):
-        wlbook = book.wldocument(librarian2=True)
+    def send_book(self, book, changes=None):
+        wlbook = book.wldocument(librarian2=True, changes=changes)
         meta = wlbook.meta
 
         cover = LabelMarquiseCover(meta, width=1200).output_file()
diff --git a/src/depot/management/commands/depot.py b/src/depot/management/commands/depot.py
new file mode 100644 (file)
index 0000000..4b8b99a
--- /dev/null
@@ -0,0 +1,10 @@
+from django.core.management.base import BaseCommand
+from depot.models import LegimiBookPublish
+
+
+class Command(BaseCommand):
+    def handle(self, **options):
+        for p in LegimiBookPublish.objects.filter(status=0).order_by('created_at'):
+            print(p, p.book.slug, p.created_at)
+            p.publish()
+
diff --git a/src/depot/migrations/0002_legimibookpublish_legimichunkpublish.py b/src/depot/migrations/0002_legimibookpublish_legimichunkpublish.py
new file mode 100644 (file)
index 0000000..3826606
--- /dev/null
@@ -0,0 +1,38 @@
+# Generated by Django 3.2.12 on 2022-07-14 10:36
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('documents', '0008_book_legimi_id'),
+        ('depot', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='LegimiBookPublish',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('created_at', models.DateTimeField()),
+                ('started_at', models.DateTimeField(blank=True, null=True)),
+                ('finished_at', models.DateTimeField(blank=True, null=True)),
+                ('status', models.PositiveSmallIntegerField(choices=[(0, 'queued'), (10, 'running'), (100, 'done'), (110, 'error')], default=0)),
+                ('error', models.TextField(blank=True)),
+                ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='documents.book')),
+                ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='LegimiChunkPublish',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('book_publish', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='depot.legimibookpublish')),
+                ('change', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='documents.chunkchange')),
+            ],
+        ),
+    ]
index e3b6dfd..b68b536 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):
@@ -115,3 +119,51 @@ class Package(models.Model):
                 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)
+        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)
diff --git a/src/depot/urls.py b/src/depot/urls.py
new file mode 100644 (file)
index 0000000..9804515
--- /dev/null
@@ -0,0 +1,11 @@
+from django.urls import path
+from . import views
+
+
+urlpatterns = [
+    path(
+        'legimi-publish/<int:book_id>/',
+        views.LegimiPublishView.as_view(),
+        name='depot_legimi_publish'
+    )
+]
index 91ea44a..5e468b6 100644 (file)
@@ -1,3 +1,17 @@
-from django.shortcuts import render
+from django.contrib.auth.mixins import PermissionRequiredMixin
+from django.shortcuts import get_object_or_404, redirect
+from django.views import View
+from documents.models import Book
+from . import models
 
-# Create your views here.
+
+class LegimiPublishView(PermissionRequiredMixin, View):
+    permission_required = 'depot.add_legimibookpublish'
+
+    def post(self, request, book_id):
+        book = get_object_or_404(Book, pk=book_id)
+        try:
+            publish = models.LegimiBookPublish.create_for(book, request.user)
+        except AssertionError:
+            pass
+        return redirect(book.get_absolute_url())
index 41e0bcd..1580f74 100644 (file)
@@ -278,6 +278,9 @@ class Book(models.Model):
         except IndexError:
             return None
 
+    def last_legimi_publish(self):
+        return self.legimibookpublish_set.order_by('-created_at').first()
+
     def assert_publishable(self):
         assert self.chunk_set.exists(), _('No chunks in the book.')
         try:
index 7737754..f89e1e7 100644 (file)
             {{ publish_options_form.as_p }}
             <img src="{{ STATIC_URL }}img/angel-left.png" style="vertical-align: middle" />
             <button id="publish-button" type="submit">
-                <span>{% trans "Publish" %}</span></button>
+              <span>{% trans "Publish" %}</span></button>
             <img src="{{ STATIC_URL }}img/angel-right.png" style="vertical-align: middle" />
-            </form>
+        </form>
+
+        {% if perms.depot.add_legimibookpublish %}
+          <hr>
+          <form method="post" action="{% url 'depot_legimi_publish' book.pk %}">
+            {% csrf_token %}
+            <button class="btn btn-primary" type="submit">Opublikuj na Legimi<br><small>w kategorii: {{ doc.book_info.legimi|default_if_none:doc.book_info.epoch }}</small></button>
+            {% with llp=book.last_legimi_publish %}
+              {% if llp %}
+                {{ llp.created_at }} &rarr;
+                {{ llp.started_at }} &rarr;
+                {{ llp.finished_at }}
+                ({{ llp.get_status_display }})
+                <!-- {{ llp.id }} -->
+              {% endif %}
+            {% endwith %}
+          </form>
+        {% endif %}
+
     {% else %}
         <a href="{% url 'cas_ng_login' %}">{% trans "Log in to publish." %}</a>
     {% endif %}
     <ul><li>{{ publishable_error }}</li></ul>
 {% endif %}
 
-</div>
+
+
+    </div>
   </div>
 </div>
 </div>
 
+
 {% if doc %}
   <div class="card mt-4">
     <div class="card-header">
           </tr>
         </thead>
         <tbody>
-          {% with stats=book.wldocument.get_statistics %}
+          {% with stats=doc.get_statistics %}
             {% include 'documents/book_stats.html' with book=book stats=stats depth=0 %}
           {% endwith %}
         </tbody>
index 6e60730..2f36af1 100644 (file)
@@ -26,6 +26,7 @@ urlpatterns = [
     url(r'^editor/', include('wiki.urls')),
     url(r'^images/', include('wiki_img.urls')),
     url(r'^cover/', include('cover.urls')),
+    url(r'^depot/', include('depot.urls')),
     url(r'^wlxml/', include('wlxml.urls')),
 
     path('api/', include('redakcja.api.urls')),