X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/2d538a50605add2666172861744229599487f1b2..14f2c24a604e36cad62ba9f6f8d71bf500f8e35a:/src/depot/publishers/woblink.py
diff --git a/src/depot/publishers/woblink.py b/src/depot/publishers/woblink.py
index 00dca5ec..f77d6185 100644
--- a/src/depot/publishers/woblink.py
+++ b/src/depot/publishers/woblink.py
@@ -8,7 +8,7 @@ from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe
from librarian.builders.html import SnippetHtmlBuilder
from librarian.functions import lang_code_3to2
-from catalogue.models import Author, Thema
+from catalogue.models import Audience, Author, Thema
from .. import models
from .base import BasePublisher
from .woblink_constants import WOBLINK_CATEGORIES
@@ -20,8 +20,8 @@ class WoblinkError(ValueError):
class NoPrice(WoblinkError):
def as_html(self):
return format_html(
- 'Brak okreÅlonej ceny.',
- price=self.args[0].id
+ 'Brak okreÅlonej ceny.',
+ site=self.args[0].id
)
class NoIsbn(WoblinkError):
@@ -124,11 +124,15 @@ class Woblink(BasePublisher):
STEP1_URL = BASE_URL + 'catalog/edit/%s'
STEP2_URL = BASE_URL + 'catalog/edit/%s/2'
STEP3_URL = BASE_URL + 'catalog/edit/%s/3'
+ STEP4_URL = BASE_URL + 'catalog/edit/%s/4'
+ STEP5_URL = BASE_URL + 'catalog/edit/%s/5'
UPLOAD_URL = BASE_URL + 'file/upload-%s'
JOB_STATUS_URL = BASE_URL + 'task/status'
GENERATE_DEMO_URL = BASE_URL + 'task/run/generate-%s-demo/%s/%d'
CHECK_DEMO_URL = BASE_URL + 'task/run/check-%s-demo/%s'
+ SEARCH_CATALOGUE_URL = BASE_URL + '{category}/autocomplete/{term}'
+
ROLE_AUTHOR = 1
ROLE_TRANSLATOR = 4
@@ -148,6 +152,28 @@ class Woblink(BasePublisher):
data=data,
)
+ def search_catalogue(self, category, term):
+ return self.session.get(
+ self.SEARCH_CATALOGUE_URL.format(category=category, term=term)
+ ).json()
+
+ def search_author_catalogue(self, term):
+ return [
+ {
+ 'id': item['autId'],
+ 'text': item['autFullname']
+ }
+ for item in self.search_catalogue('author', term)
+ ]
+ def search_series_catalogue(self, term):
+ return [
+ {
+ 'id': item['id'],
+ 'text': item['name']
+ }
+ for item in self.search_catalogue('series', term)
+ ]
+
def get_isbn(self, meta, errors=None):
if not meta.isbn_epub:
if errors is not None:
@@ -194,6 +220,12 @@ class Woblink(BasePublisher):
if errors is not None:
errors.append(NoMainThemaWarning())
thema_codes.extend(meta.thema)
+
+ thema_codes.extend(
+ Audience.objects.filter(code__in=meta.audiences).exclude(
+ thema='').values_list('thema', flat=True)
+ )
+
if not thema_codes:
if errors is not None:
errors.append(NoThema())
@@ -219,25 +251,35 @@ class Woblink(BasePublisher):
return category_ids
def get_series(self, meta, errors=None):
- pass
+ return list(Audience.objects.filter(code__in=meta.audiences).exclude(
+ woblink=None).values_list('woblink', flat=True))
def get_abstract(self, wldoc, errors=None, description_add=None):
description = self.get_description(wldoc, description_add)
parts = description.split('\n', 1)
- if len(parts) == 1 or len(parts[0]) > 200:
- p1 = description[:200].rsplit(' ', 1)[0]
- p2 = description[len(p1):]
- p1 += 'â¦'
- p2 = 'â¦' + p2
+ if len(parts) == 1 or len(parts[0]) > 240:
+ # No newline found here.
+ # Try to find last sentence end..
+ parts = re.split(r' \.', description[240::-1], 1)
+ if len(parts) == 2:
+ p1 = parts[1][::-1] + '.'
+ p2 = description[len(p1) + 1:]
+ else:
+ # No sentence end found.
+ # Just find a space.
+ p1 = description[:240].rsplit(' ', 1)[0]
+ p2 = description[len(p1) + 1:]
+ p1 += 'â¦'
+ p2 = 'â¦' + p2
parts = [p1, p2]
m = re.search(r'<[^>]+$', parts[0])
if m is not None:
- parts[0] = parts[:-len(m.group(0))]
+ parts[0] = parts[0][:-len(m.group(0))]
parts[1] = m.group(0) + parts[1]
opened = []
- for tag in re.findall(r'<[^>]+[^/>]>', parts[0]):
+ for tag in re.findall(r'<[^>]*[^/>]>', parts[0]):
if tag[1] == '/':
opened.pop()
else:
@@ -253,26 +295,32 @@ class Woblink(BasePublisher):
def get_lang2code(self, meta, errors=None):
return lang_code_3to2(meta.language)
- def get_price(self, shop, wldoc, errors=None):
- stats = wldoc.get_statistics()['total']
+ def get_price(self, site, wldoc, errors=None):
+ try:
+ stats = wldoc.get_statistics()['total']
+ except:
+ if errors:
+ errors.append(NoPrice(site))
+ return 0
words = stats['words_with_fn']
pages = stats['chars_with_fn'] / 1800
- price = shop.get_price(words, pages)
+ price = site.get_price(words, pages)
if price is None:
if errors:
- errors.append(NoPrice(shop))
+ errors.append(NoPrice(site))
return 0
return price
- def can_publish(self, shop, book):
+ def can_publish(self, site, book):
wldoc = book.wldocument(librarian2=True)
d = {
'warnings': [],
'errors': [],
+ 'info': [],
}
errors = []
- book_data = self.get_book_data(shop, wldoc, errors)
+ book_data = self.get_book_data(site, wldoc, errors)
for error in errors:
if not isinstance(error, Warning):
errlist = d['errors']
@@ -281,11 +329,15 @@ class Woblink(BasePublisher):
errlist.append(error.as_html())
if book_data.get('genres'):
- d['comment'] = format_html(
+ d['info'].append(format_html(
'W kategoriach: {cat} ({price} zÅ)',
cat=', '.join(self.describe_category(g) for g in book_data['genres']),
- price=book_data['price']
- )
+ price=book_data['price'],
+ ))
+ d['info'].append(mark_safe(
+ '' + book_data['abstract']['header'] +
+ '
' + book_data['abstract']['rest']
+ ))
return d
@@ -313,44 +365,54 @@ class Woblink(BasePublisher):
if m is not None:
return m.group(1)
- def send_book(self, shop, book, changes=None):
+ def send_book(self, site_book_publish, changes=None):
+ site_book = site_book_publish.site_book
+ book = site_book.book
+ site = site_book.site
wldoc = book.wldocument(librarian2=True, changes=changes, publishable=False) # TODO pub
meta = wldoc.meta
- book_data = self.get_book_data(shop, wldoc)
+ book_data = self.get_book_data(site, wldoc)
- if not book.woblink_id:
- #book.woblink_id = 2959868
+ if not site_book.external_id:
woblink_id = self.create_book(book_data['isbn'])
assert woblink_id
- book.woblink_id = woblink_id
- book.save(update_fields=['woblink_id'])
-
- self.edit_step1(book.woblink_id, book_data)
- self.edit_step2(book.woblink_id, book_data)
- self.edit_step3(book.woblink_id, book_data)
- self.send_cover(book.woblink_id, wldoc)
- texts = shop.get_texts()
- self.send_epub(
- book.woblink_id, wldoc, book.gallery_path(),
+ site_book.external_id = woblink_id
+ site_book.save(update_fields=['external_id'])
+ woblink_id = site_book.external_id
+
+ self.edit_step1(woblink_id, book_data)
+ self.edit_step2(woblink_id, book_data)
+ self.edit_step3(woblink_id, book_data)
+ cover_id = self.send_cover(woblink_id, wldoc)
+
+ texts = site.get_texts()
+ epub_id, epub_demo = self.send_epub(
+ woblink_id, wldoc, book.gallery_path(),
fundraising=texts
)
- self.send_mobi(
- book.woblink_id, wldoc, book.gallery_path(),
+ mobi_id, mobi_demo = self.send_mobi(
+ woblink_id, wldoc, book.gallery_path(),
fundraising=texts
)
+ self.edit_step4(
+ woblink_id, book_data,
+ cover_id, epub_id, epub_demo, mobi_id, mobi_demo,
+ )
+ self.edit_step5(woblink_id, book_data)
- def get_book_data(self, shop, wldoc, errors=None):
+ def get_book_data(self, site, wldoc, errors=None):
return {
"title": wldoc.meta.title,
"isbn": self.get_isbn(wldoc.meta, errors=errors),
"authors": self.get_authors_data(wldoc.meta, errors=errors),
"abstract": self.get_abstract(
- wldoc, errors=errors, description_add=shop.description_add
+ wldoc, errors=errors, description_add=site.description_add
),
"lang2code": self.get_lang2code(wldoc.meta, errors=errors),
"genres": self.get_genres(wldoc.meta, errors=errors),
- "price": self.get_price(shop, wldoc, errors=errors),
+ "price": self.get_price(site, wldoc, errors=errors),
+ "series": self.get_series(wldoc.meta, errors=errors),
}
def with_form_name(self, data, name):
@@ -371,6 +433,14 @@ class Woblink(BasePublisher):
for (author_type, author_id) in data['authors']
]
+ series_data = [
+ {
+ 'PublicationId': woblink_id,
+ 'SeriesId': series_id,
+ }
+ for series_id in data['series']
+ ]
+
d = {
'pubTitle': book_data['title'],
'npwAuthorHasPublications': json.dumps(authors_data),
@@ -378,8 +448,7 @@ class Woblink(BasePublisher):
'pubNote': data['abstract']['rest'],
'pubCulture': data['lang2code'],
'npwPublicationHasAwards': '[]',
- 'npwPublicationHasSeriess': '[]', # TODO
- # "[{\"Id\":6153,\"PublicationId\":73876,\"SeriesId\":1615,\"Tome\":null}]"
+ 'npwPublicationHasSeriess': json.dumps(series_data),
}
d = self.with_form_name(d, 'EditPublicationStep1')
d['roles'] = [author_type for (author_type, author_id) in data['authors']]
@@ -402,8 +471,8 @@ class Woblink(BasePublisher):
if legacy is None:
legacy = WOBLINK_CATEGORIES[p].get('legacy')
else:
- gd.setdefault(p, {})
- ds[p]['isMain'] = True
+ gd.setdefault(g, {})
+ gd[g]['isMain'] = True
gd = [
{
"pubId": woblink_id,
@@ -423,15 +492,35 @@ class Woblink(BasePublisher):
def edit_step3(self, woblink_id, book_data):
d = {
'pubBasePrice': book_data['price'],
- 'pubPremiereDate': '2023-08-09', #date.today().isoformat(),
+ 'pubPremiereDate': date.today().isoformat(),
'pubIsLicenseIndefinite': '1',
'pubFileFormat': 'epub+mobi',
'pubIsAcs': '0',
'pubPublisherIndex': '',
+ 'save_and_continue': '',
}
d = self.with_form_name(d, 'EditPublicationStep3')
return self.session.post(self.STEP3_URL % woblink_id, data=d)
+ def edit_step4(self, woblink_id, book_data, cover_id, epub_id, epub_demo, mobi_id, mobi_demo):
+ d = {
+ 'pubCoverResId': cover_id,
+ 'pubEpubResId': epub_id,
+ 'pubEpubDemoResId': epub_demo,
+ 'pubMobiResId': mobi_id,
+ 'pubMobiDemoResId': mobi_demo,
+ 'pubFileFormat': 'epub+mobi',
+ 'pubId': woblink_id,
+ 'save_and_continue': '',
+ }
+ d = self.with_form_name(d, 'EditPublicationStep4')
+ return self.session.post(self.STEP4_URL % woblink_id, data=d)
+
+ def edit_step5(self, woblink_id, book_data):
+ d = {'save': ''}
+ d = self.with_form_name(d, 'EditPublicationStep5')
+ return self.session.post(self.STEP5_URL % woblink_id, data=d)
+
def wait_for_job(self, job_id):
while True:
response = self.session.post(
@@ -441,16 +530,21 @@ class Woblink(BasePublisher):
data = response.json()[job_id]
if data['ready']:
assert data['successful']
- return
+ return data.get('returnValue')
sleep(2)
- def upload_file(self, woblink_id, filename, content, form_name, field_name, mime_type):
+ def upload_file(self, woblink_id, filename, content, field_name, mime_type):
+ form_name = f'Upload{field_name}'
+ id_field = f'pub{field_name}ResId'
+ field_name = field_name.lower()
+
data = {
'pubId': woblink_id,
}
files = {
field_name: (filename, content, mime_type)
}
+
response = self.session.post(
self.UPLOAD_URL % field_name,
data=self.with_form_name(data, form_name),
@@ -458,8 +552,10 @@ class Woblink(BasePublisher):
)
resp_data = response.json()
assert resp_data['success'] is True
+ file_id = resp_data[id_field]
if 'jobId' in resp_data:
self.wait_for_job(resp_data['jobId'])
+ return file_id
def generate_demo(self, woblink_id, file_format, check=True):
percent = 10
@@ -468,7 +564,7 @@ class Woblink(BasePublisher):
self.GENERATE_DEMO_URL % (file_format, woblink_id, percent),
).json()['jobId']
try:
- self.wait_for_job(job_id)
+ file_id = self.wait_for_job(job_id)
except AssertionError:
if percent < 50:
percent += 10
@@ -483,6 +579,7 @@ class Woblink(BasePublisher):
self.CHECK_DEMO_URL % (file_format, woblink_id)
).json()['jobId']
)
+ return file_id
def send_epub(self, woblink_id, doc, gallery_path, fundraising=None):
from librarian.builders import EpubBuilder
@@ -490,15 +587,15 @@ class Woblink(BasePublisher):
base_url='file://' + gallery_path + '/',
fundraising=fundraising or [],
).build(doc).get_file()
- self.upload_file(
+ file_id = self.upload_file(
woblink_id,
doc.meta.url.slug + '.epub',
content,
- 'UploadEpub',
- 'epub',
+ 'Epub',
'application/epub+zip'
)
- self.generate_demo(woblink_id, 'epub')
+ demo_id = self.generate_demo(woblink_id, 'epub')
+ return file_id, demo_id
def send_mobi(self, woblink_id, doc, gallery_path, fundraising=None):
from librarian.builders import MobiBuilder
@@ -506,15 +603,15 @@ class Woblink(BasePublisher):
base_url='file://' + gallery_path + '/',
fundraising=fundraising or [],
).build(doc).get_file()
- self.upload_file(
+ file_id = self.upload_file(
woblink_id,
doc.meta.url.slug + '.mobi',
content,
- 'UploadMobi',
- 'mobi',
+ 'Mobi',
'application/x-mobipocket-ebook'
)
- self.generate_demo(woblink_id, 'mobi', check=False)
+ demo_id = self.generate_demo(woblink_id, 'mobi', check=False)
+ return file_id, demo_id
def send_cover(self, woblink_id, doc):
from librarian.cover import make_cover
@@ -524,11 +621,11 @@ class Woblink(BasePublisher):
content = io.BytesIO()
cover.final_image().save(content, cover.format)
content.seek(0)
- self.upload_file(
+ file_id = self.upload_file(
woblink_id,
doc.meta.url.slug + '.jpeg',
content,
- 'UploadCover',
- 'cover',
+ 'Cover',
cover.mime_type()
)
+ return file_id