api for partner
authorRadek Czajka <rczajka@rczajka.pl>
Wed, 26 Feb 2025 15:12:02 +0000 (16:12 +0100)
committerRadek Czajka <rczajka@rczajka.pl>
Wed, 26 Feb 2025 15:12:02 +0000 (16:12 +0100)
requirements/requirements.txt
src/catalogue/api/serializers.py
src/catalogue/api/urls2.py
src/catalogue/api/views.py
src/catalogue/fields.py
src/catalogue/migrations/0049_book_html_nonotes_file_book_html_nonotes_file_etag_and_more.py [new file with mode: 0644]
src/catalogue/models/book.py

index c3934fe..898a609 100644 (file)
@@ -39,7 +39,7 @@ mutagen==1.47
 sorl-thumbnail==12.10.0
 
 # home-brewed & dependencies
-librarian==24.5.6
+librarian==24.5.7
 
 # celery tasks
 celery[redis]==5.4.0
index 5f96e02..3e3874d 100644 (file)
@@ -158,6 +158,37 @@ class BookSerializer2(serializers.ModelSerializer):
             'isbn_pdf', 'isbn_epub', 'isbn_mobi',
         ]
 
+class BookSerializer11Labs(serializers.ModelSerializer):
+    url = AbsoluteURLField()
+    href = AbsoluteURLField(view_name='catalogue_api_book', view_args=['slug'])
+    html = EmbargoURLField(source='html_nonotes_url')
+
+    authors = AuthorItemSerializer(many=True)
+    translators = AuthorItemSerializer(many=True)
+    epochs = EpochItemSerializer(many=True)
+    genres = GenreItemSerializer(many=True)
+    kinds = KindItemSerializer(many=True)
+    parent = serializers.HyperlinkedRelatedField(
+        read_only=True,
+        view_name='catalogue_api_book',
+        lookup_field='slug'
+    )
+
+    class Meta:
+        model = Book
+        fields = [
+            'slug', 'title', 'full_sort_key',
+            'href', 'url', 'language',
+            'authors', 'translators',
+            'epochs', 'genres', 'kinds',
+            #'children',
+            'parent', 'preview',
+            'html',
+            'cover_thumb', 'cover',
+            'isbn_pdf', 'isbn_epub', 'isbn_mobi',
+        ]
+
+
 class BookSerializer(LegacyMixin, serializers.ModelSerializer):
     author = serializers.CharField(source='author_unicode')
     kind = serializers.CharField(source='kind_unicode')
index 8748e2c..164cdca 100644 (file)
@@ -11,6 +11,10 @@ urlpatterns = [
          piwik_track_view(views.BookList2.as_view()),
          name='catalogue_api_book_list'
          ),
+    path('11labs/books/',
+         piwik_track_view(views.BookList11Labs.as_view()),
+         name='catalogue_api_book_list'
+         ),
     path('books/<slug:slug>/',
          piwik_track_view(views.BookDetail2.as_view()),
          name='catalogue_api_book'
index 9c8f4f1..b55b214 100644 (file)
@@ -196,6 +196,18 @@ class BookList2(ListAPIView):
         return books
 
 
+class BookList11Labs(BookList2):
+    serializer_class = serializers.BookSerializer11Labs
+
+    def get_queryset(self):
+        books = Book.objects.all()
+        books = books.filter(findable=True)
+        books = books.filter(license='')
+        books = order_books(books, True)
+
+        return books
+
+
 @vary_on_auth  # Because of 'liked'.
 class BookDetail(RetrieveAPIView):
     queryset = Book.objects.all()
index 9c5696f..2d35357 100644 (file)
@@ -398,6 +398,26 @@ class HtmlField(EbookField):
         return wldoc.as_html(gallery_path=gal_path, gallery_url=gal_url, base_url=absolute_url(gal_url))
 
 
+class HtmlNonotesField(EbookField):
+    ext = 'html'
+    for_parents = False
+    directory = 'html_nonotes'
+
+    @staticmethod
+    def transform(wldoc, book):
+        # ugly, but we can't use wldoc.book_info here
+        from librarian import DCNS
+        url_elem = wldoc.edoc.getroot().find('.//' + DCNS('identifier.url'))
+        if url_elem is None:
+            gal_url = ''
+            gal_path = ''
+        else:
+            slug = url_elem.text.rstrip('/').rsplit('/', 1)[1]
+            gal_url = gallery_url(slug=slug)
+            gal_path = gallery_path(slug=slug)
+        return wldoc.as_html(gallery_path=gal_path, gallery_url=gal_url, base_url=absolute_url(gal_url), flags=['nonotes'])
+
+
 class CoverField(EbookField):
     ext = 'jpg'
     directory = 'cover'
diff --git a/src/catalogue/migrations/0049_book_html_nonotes_file_book_html_nonotes_file_etag_and_more.py b/src/catalogue/migrations/0049_book_html_nonotes_file_book_html_nonotes_file_etag_and_more.py
new file mode 100644 (file)
index 0000000..bd297d4
--- /dev/null
@@ -0,0 +1,30 @@
+# Generated by Django 4.0.8 on 2025-02-26 14:46
+
+import catalogue.fields
+from django.db import migrations, models
+import fnpdjango.storage
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('catalogue', '0048_remove_collection_kind_remove_tag_for_books_and_more'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='book',
+            name='html_nonotes_file',
+            field=catalogue.fields.HtmlNonotesField(etag_field_name='html_nonotes_file_etag', storage=fnpdjango.storage.BofhFileSystemStorage()),
+        ),
+        migrations.AddField(
+            model_name='book',
+            name='html_nonotes_file_etag',
+            field=models.CharField(db_index=True, default='', editable=False, max_length=255),
+        ),
+        migrations.AddField(
+            model_name='book',
+            name='license',
+            field=models.CharField(blank=True, db_index=True, max_length=255, verbose_name='licencja'),
+        ),
+    ]
index 29e3754..4080cc2 100644 (file)
@@ -43,6 +43,7 @@ class Book(models.Model):
     common_slug = models.SlugField('wspólny slug', max_length=120, db_index=True)
     language = models.CharField('kod języka', max_length=3, db_index=True, default=app_settings.DEFAULT_LANGUAGE)
     description = models.TextField('opis', blank=True)
+    license = models.CharField('licencja', max_length=255, blank=True, db_index=True)
     abstract = models.TextField('abstrakt', blank=True)
     toc = models.TextField('spis treści', blank=True)
     created_at = models.DateTimeField('data utworzenia', auto_now_add=True, db_index=True)
@@ -62,6 +63,7 @@ class Book(models.Model):
     # files generated during publication
     xml_file = fields.XmlField(storage=bofh_storage, with_etag=False)
     html_file = fields.HtmlField(storage=bofh_storage)
+    html_nonotes_file = fields.HtmlNonotesField(storage=bofh_storage)
     fb2_file = fields.Fb2Field(storage=bofh_storage)
     txt_file = fields.TxtField(storage=bofh_storage)
     epub_file = fields.EpubField(storage=bofh_storage)
@@ -79,7 +81,7 @@ class Book(models.Model):
         'okładka dla Ebookpoint')
 
     ebook_formats = constants.EBOOK_FORMATS
-    formats = ebook_formats + ['html', 'xml']
+    formats = ebook_formats + ['html', 'xml', 'html_nonotes']
 
     parent = models.ForeignKey('self', models.CASCADE, blank=True, null=True, related_name='children')
     ancestor = models.ManyToManyField('self', blank=True, editable=False, related_name='descendant', symmetrical=False)
@@ -375,6 +377,9 @@ class Book(models.Model):
     def html_url(self):
         return self.media_url('html')
 
+    def html_nonotes_url(self):
+        return self.media_url('html_nonotes')
+
     def pdf_url(self):
         return self.media_url('pdf')
 
@@ -635,6 +640,7 @@ class Book(models.Model):
         book.findable = findable
         book.language = book_info.language
         book.title = book_info.title
+        book.license = book_info.license
         if book_info.variant_of:
             book.common_slug = book_info.variant_of.slug
         else:
@@ -704,6 +710,7 @@ class Book(models.Model):
         for format_ in constants.EBOOK_FORMATS_WITH_CHILDREN:
             if format_ not in dont_build:
                 getattr(book, '%s_file' % format_).build_delay()
+        book.html_nonotes_file.build_delay()
 
         if not settings.NO_SEARCH_INDEX and search_index and findable:
             tasks.index_book.delay(book.id)