From 842685bc24daac46f562bdde7ce527fd5e3b1474 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 16 Mar 2022 00:24:58 +0100 Subject: [PATCH] Legimi export, and some upgrades. --- .gitignore | 1 + requirements/requirements.txt | 17 +- src/depot/legimi.py | 235 ++++++++++++++++++ .../migrations/0008_book_legimi_id.py | 18 ++ src/documents/models/book.py | 1 + src/redakcja/settings/__init__.py | 6 +- src/redakcja/settings/defaults.py | 2 - src/redakcja/templates/503.html | 14 -- 8 files changed, 267 insertions(+), 27 deletions(-) create mode 100644 src/depot/legimi.py create mode 100644 src/documents/migrations/0008_book_legimi_id.py delete mode 100644 src/redakcja/templates/503.html diff --git a/.gitignore b/.gitignore index 26943157..99d35de3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ requirements.pybundle *~ *.swp .*.orig +*# /redakcja/media /static .sass-cache diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 8ec45da3..8948dffc 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -13,20 +13,19 @@ Wikidata==0.6.1 librarian==2.3.4 ## Django -Django==3.1.13 +Django==3.2.12 fnpdjango==0.5 -django-pipeline==2.0.5 -django-cas-ng==4.2.1 -sorl-thumbnail==12.7.0 -django-maintenancemode>=0.9 +django-pipeline==2.0.7 +django-cas-ng==4.3.0 +sorl-thumbnail==12.8.0 fnp-django-pagination==2.2.4 django-gravatar2==1.4.4 django-extensions==3.1.3 django-bootstrap4==3.0.1 -libsasscompiler==0.1.8 -django-debug-toolbar==3.2.1 +libsasscompiler==0.1.9 +django-debug-toolbar==3.2.4 django-admin-numeric-filter==0.1.6 -djangorestframework==3.12.4 -django-filter==2.4.0 +djangorestframework==3.13.1 +django-filter==21.1 sentry-sdk==0.12.2 diff --git a/src/depot/legimi.py b/src/depot/legimi.py new file mode 100644 index 00000000..3a6829a8 --- /dev/null +++ b/src/depot/legimi.py @@ -0,0 +1,235 @@ +from datetime import date +import re +from django.conf import settings +from librarian.functions import lang_code_3to2 +from librarian.html import transform_abstrakt +from librarian.builders import EpubBuilder, MobiBuilder +from librarian.cover import LegimiCornerCover, LegimiCover +import requests + + + +fundraising=[ + "Książka, którą czytasz, pochodzi z Wolnych Lektur. Naszą misją jest wspieranie dzieciaków w dostępie do lektur szkolnych oraz zachęcanie ich do czytania. Miło Cię poznać!", + "Podoba Ci się to, co robimy? Jesteśmy organizacją pożytku publicznego. Wesprzyj Wolne Lektury drobną wpłatą: wolnelektury.pl/towarzystwo/", + "Przyjaciele Wolnych Lektur otrzymują dostęp do prapremier wcześniej niż inni. Zadeklaruj stałą wpłatę i dołącz do Towarzystwa Przyjaciół Wolnych Lektur: wolnelektury.pl/towarzystwo/", + "Informacje o nowościach w naszej bibliotece w Twojej skrzynce mailowej? Nic prostszego, zapisz się do newslettera. Kliknij, by pozostawić swój adres e-mail: wolnelektury.pl/newsletter/zapisz-sie/", + "Przekaż 1% podatku na Wolne Lektury.
\nKRS: 0000070056
\nNazwa organizacji: Fundacja Nowoczesna Polska
\nKażda wpłacona kwota zostanie przeznaczona na rozwój Wolnych Lektur." +] + +class Legimi: + #BASE_URL = 'https://wydawca.legimi.com' + BASE_URL = 'https://panel.legimi.pl' + LOGIN_URL = BASE_URL + '/publishers/membership' + UPLOAD_URL = BASE_URL + '/administration/upload/start' + CREATE_URL = BASE_URL + '/publishers/publications/create' + EDIT_URL = BASE_URL + '/publishers/publications/edit/%s' + EDIT_FILES_URL = BASE_URL + '/publishers/publications/editfiles/%s' + + def __init__(self, username, password, publisher_id): + self.username = username + self.password = password + self.publisher_id = publisher_id + self._session = None + + @property + def session(self): + if self._session is None: + session = requests.Session() + response = session.post( + self.LOGIN_URL, + data={ + 'ValidationTrue': 'true', + 'UserName': self.username, + 'Password': self.password, + }) + self._session = session + return self._session + + def list(self): + return self.session.get('https://wydawca.legimi.com/publishers/publications') + + def upload(self, content): + response = self.session.post( + self.UPLOAD_URL, + files={ + "files": content, + }) + model = response.json()['model'] + return { + "name": model['Name'], + "token": model['Token'], + "url": model['Url'], + } + +# name=files[] +# filename +# content-type +# response: json +# success: true +# model.Url + + def send_book(self, book): + wlbook = book.wldocument(librarian2=True) + meta = wlbook.meta + + cover = LegimiCornerCover(meta, width=1200).output_file() + epub_file = EpubBuilder(cover=LegimiCover, fundraising=fundraising).build(wlbook).get_file() + mobi_file = MobiBuilder(cover=LegimiCover, fundraising=fundraising).build(wlbook).get_file() + + book_data = { + "Title": meta.title, + "Author": ", ".join(p.readable() for p in meta.authors), + "Year": meta.created_at[:4], + + 'GenreId': '11', # TODO + 'Isbn': '', + 'LanguageLocale': lang_code_3to2(meta.language), + + 'Description': '

—

', + } + if meta.isbn_html: + isbn = meta.isbn_html + if isbn.upper().startswith('ISBN '): + isbn = isbn[5:] + isbn = isbn.strip() + book_data['Isbn'] = isbn + + files_data = {} + + abstract = wlbook.tree.find('.//abstrakt') + if abstract is not None: + book_data['Description'] = transform_abstrakt(abstract) + + + cover_data = self.upload( + (meta.url.slug + '.jpg', cover.get_file(), 'image/jpeg') + ) + book_data.update({ + "Cover.Name": cover_data['name'], + "Cover.Token": cover_data['token'], + "Cover.Url": cover_data['url'], + }) + + epub_data = self.upload( + (meta.url.slug + '.epub', epub_file, 'application/epub+zip') + ) + files_data.update({ + 'BookEpub.Token': epub_data['token'], + 'BookEpub.Name': epub_data['name'], + }) + + mobi_data = self.upload( + (meta.url.slug + '.mobi', mobi_file, 'application/x-mobipocket-ebook') + ) + files_data.update({ + 'BookMobi.Token': mobi_data['token'], + 'BookMobi.Name': mobi_data['name'], + }) + + if book.legimi_id: + self.edit( + book.legimi_id, + book_data + ) + self.edit_files( + book.legimi_id, + files_data + ) + else: + legimi_id = self.create_book(book_data, files_data) + if legimi_id: + book.legimi_id = legimi_id + book.save(update_fields=['legimi_id']) + + def create_book(self, book_data, files_data): + data = { + 'createValidationTrue': 'true', + 'PublisherId': self.publisher_id,#3609954 + 'IsLibraryPass': 'False', + + 'SamplesGenerationType': 'Quantity', + 'SamplesGenerationPercent': '10', + + 'EnterToTheMarketType': 'No', + 'EnterToTheMarketDate': date.today().strftime('%d.%m.%Y'), + 'HidingDate': '', + 'SalesNoLimitOption': 'false', + 'SalesNoLimitKindle': 'false', + 'SalesInStoreEbookGrossValue': '0,00', + 'SalesPromotion': 'False', + 'SalesPromotionGrossValue': '0,00', + 'SalesPromotionDatesRange.DateStart': '', + 'SalesPromotionDatesRange.DateEnd': '', + } + + for form in 'Epub', 'Mobi', 'Pdf': + data.update({ + f'Book{form}.Token': '', + f'Book{form}.Name': '', + f'Book{form}.StorageName': '', + f'Book{form}.Order': '', + + f'Sample{form}Type': 'Files', + f'Sample{form}.Token': '', + f'Sample{form}.Name': '', + f'Sample{form}.StorageName': '', + f'Sample{form}.Order': '', + }) + + data.update(book_data) + data.update(files_data) + + response = self.session.post(self.CREATE_URL, data=data) + m = re.search(r'/(\d+)$', response.url) + if m is not None: + return m.group(1) + + def edit(self, legimi_id, data): + current = { + 'ValidationTrue': 'true', + 'Is': legimi_id + } + + current.update(data) + + self.session.post( + self.EDIT_URL % legimi_id, + data=current + ) + + def edit_files(self, legimi_id, files_data): + current = { + 'ValidationTrue': 'true', + 'Id': legimi_id, + 'SamplesGenerationType': 'Quantity', + 'SamplesGenerationPercent': '10', + } + + for form in 'Epub', 'Mobi', 'Pdf': + current.update({ + f'Book{form}.Token': '', + f'Book{form}.Name': '', + f'Book{form}.StorageName': '', + f'Book{form}.Order': '', + + f'Sample{form}.Type': 'Files', + f'Sample{form}.Token': '', + f'Sample{form}.Name': '', + f'Sample{form}.StorageName': '', + f'Sample{form}.Order': '', + }) + + current.update(files_data) + + response = self.session.post( + self.EDIT_FILES_URL % legimi_id, + data=current + ) + + +legimi = Legimi( + settings.LEGIMI_USERNAME, + settings.LEGIMI_PASSWORD, + settings.LEGIMI_PUBLISHER_ID, +) diff --git a/src/documents/migrations/0008_book_legimi_id.py b/src/documents/migrations/0008_book_legimi_id.py new file mode 100644 index 00000000..8ba97afe --- /dev/null +++ b/src/documents/migrations/0008_book_legimi_id.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2022-03-15 18:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('documents', '0007_book_dc'), + ] + + operations = [ + migrations.AddField( + model_name='book', + name='legimi_id', + field=models.CharField(blank=True, max_length=255), + ), + ] diff --git a/src/documents/models/book.py b/src/documents/models/book.py index e649180d..41e0bcd6 100644 --- a/src/documents/models/book.py +++ b/src/documents/models/book.py @@ -52,6 +52,7 @@ class Book(models.Model): related_name='document_books', related_query_name='document_book', ) + legimi_id = models.CharField(max_length=255, blank=True) class NoTextError(BaseException): pass diff --git a/src/redakcja/settings/__init__.py b/src/redakcja/settings/__init__.py index 46b80da1..25ae5675 100644 --- a/src/redakcja/settings/__init__.py +++ b/src/redakcja/settings/__init__.py @@ -53,7 +53,6 @@ if CAS_SERVER_URL: MIDDLEWARE += [ 'django.contrib.admindocs.middleware.XViewMiddleware', 'fnp_django_pagination.middleware.PaginationMiddleware', - 'maintenancemode.middleware.MaintenanceModeMiddleware', ] if DEBUG: @@ -128,7 +127,7 @@ PIPELINE = { 'CSS_COMPRESSOR': None, 'JS_COMPRESSOR': None, 'COMPILERS': ( - 'pipeline.compilers.sass.SASSCompiler', + 'libsasscompiler.LibSassCompiler', ), # CSS and JS files to compress @@ -267,6 +266,9 @@ PIPELINE = { } +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' + + SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' diff --git a/src/redakcja/settings/defaults.py b/src/redakcja/settings/defaults.py index 62521250..b7025565 100644 --- a/src/redakcja/settings/defaults.py +++ b/src/redakcja/settings/defaults.py @@ -18,8 +18,6 @@ DATABASES = { DEBUG = False -MAINTENANCE_MODE = False - ADMINS = ( (u'Radek Czajka', 'radoslaw.czajka@nowoczesnapolska.org.pl'), ) diff --git a/src/redakcja/templates/503.html b/src/redakcja/templates/503.html deleted file mode 100644 index 1c1d39a1..00000000 --- a/src/redakcja/templates/503.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "error_base.html" %} - -{% block "content" %} - -

Serwis tymczasowo niedostępny

- -

-Platfroma redakcyjna serwisu Wolne Lektury jest -tymczasowo niedostępna z powodu prac administracyjnych. -

- -

Prosimy o wyrozumiałość i ponowne odwiedziny.

- -{% endblock "content" %} -- 2.20.1