1 from datetime import date
3 from django.conf import settings
4 from django.utils.html import escape
5 from django.utils.safestring import mark_safe
6 from librarian.functions import lang_code_3to2
7 from librarian.builders import EpubBuilder, MobiBuilder
8 from librarian.covers.marquise import MarquiseCover, LabelMarquiseCover
9 from catalogue.models import Audience
10 from .base import BasePublisher
13 class Legimi(BasePublisher):
14 BASE_URL = 'https://panel.legimi.pl'
15 LOGIN_URL = BASE_URL + '/publishers/membership'
16 UPLOAD_URL = BASE_URL + '/administration/upload/start'
17 CREATE_URL = BASE_URL + '/publishers/publications/create'
18 EDIT_URL = BASE_URL + '/publishers/publications/edit/%s'
19 EDIT_FILES_URL = BASE_URL + '/publishers/publications/editfiles/%s'
20 EDIT_SALE_URL = BASE_URL + '/publishers/publications/editsale/%s'
23 'Dla dzieci i młodzieży': 94,
24 'Książki dla dzieci': 15,
25 'Literatura młodzieżowa': 24,
27 'Kryminał klasyczny': 31,
28 'Kryminał współczesny': 32,
29 'Kryminał historyczny': 30,
32 'Słowniki i leksykony': 14,
38 'Dwudziestolecie międzywojenne': 88,
47 'Fantastyka i sci-fi': 25,
49 'Science fiction': 27,
51 'Antyki i kolekcjonerstwo': 53,
52 'Astrologia i wróżbiarstwo': 54,
53 'Zdrowie i rodzina': 57,
55 'Medycyna i zdrowie': 58,
59 'Kultura i sztuka': 64,
62 'Eseje literackie': 49,
65 'Wakacje i podróże': 69,
68 'Obyczajowe i romanse': 93,
72 'Powieść przygodowa': 42,
73 'Współczesna powieść przygodowa': 44,
74 'Historyczna powieść przygodowa': 43,
75 'Powieść historyczna': 46,
76 'Powieść psychologiczna': 47,
77 'Powieść religijna': 45,
79 'Romans klasyczny': 38,
80 'Romans współczesny': 39,
81 'Literatura erotyczna': 40,
82 'Romans historyczny': 37,
84 'Sensacja, thriller, horror': 91,
90 'Literatura faktu, reportaże, biografie': 92,
91 'Literatura faktu': 16,
96 'Historia literatury i krytyka literacka': 23,
97 'Literatura popularnonaukowa': 22,
99 'Społeczno-polityczne': 72,
100 'Poezja i dramat': 95,
103 'Religia i duchowość': 51,
104 'Nauka i nowe technologie': 98,
105 'Nauka i technika': 61,
107 'Nauki humanistyczne': 63,
108 'Technologia i Internet': 75,
109 'Specjalistyczne': 99,
110 'Biznes i finanse': 1,
115 'Rozwój osobisty': 7,
116 'Kariera i sukces zawodowy': 8,
117 'Psychologia, motywacja': 9,
127 'ValidationTrue': 'true',
128 'UserName': self.username,
129 'Password': self.password,
132 def can_publish(self, site, book):
139 meta = book.wldocument(librarian2=True).meta
141 d['errors'].append('Nieprawidłowy dokument.')
143 thema = self.get_thema(meta)
145 d['info'].append(mark_safe(
146 "w kategorii " + ", ".join(
147 "<b><tt>{code}</tt></b>".format(code=escape(t))
151 if not meta.thema_main:
152 d['warnings'].append('Brak głównej kategorii Thema')
154 d['errors'].append('Brak kategorii Thema.')
158 return self.session.get('https://wydawca.legimi.com/publishers/publications')
160 def upload(self, content):
161 response = self.session.post(
166 model = response.json()['model']
168 "name": model['Name'],
169 "token": model['Token'],
173 def get_thema(self, meta):
176 thema.append(meta.thema_main)
177 thema.extend(meta.thema)
180 Audience.objects.filter(code__in=meta.audiences).exclude(
181 thema=None).values_list('thema', flat=True)
185 def send_book(self, site_book_publish, changes=None):
186 site_book = site_book_publish.site_book
187 site = site_book.site
188 book = site_book.book
189 wlbook = book.wldocument(librarian2=True, changes=changes)
192 cover = LabelMarquiseCover(meta, width=1200).output_file()
193 texts = site.get_texts()
194 epub_file = EpubBuilder(
197 base_url='file://' + book.gallery_path() + '/'
198 ).build(wlbook).get_file()
199 mobi_file = MobiBuilder(
202 base_url='file://' + book.gallery_path() + '/'
203 ).build(wlbook).get_file()
207 "Author": ", ".join(p.readable() for p in meta.authors),
208 "Year": str(date.today().year),
210 'GenreId': str(self.get_genre(wlbook)),
211 'themaCategories': ';'.join(self.get_thema(meta)),
214 'LanguageLocale': lang_code_3to2(meta.language),
216 'Description': self.get_description(wlbook, site.description_add),
219 isbn = meta.isbn_html
220 if isbn.upper().startswith(('ISBN ', 'ISBN-')):
223 book_data['Isbn'] = isbn
227 cover_data = self.upload(
228 (meta.url.slug + '.jpg', cover.get_file(), 'image/jpeg')
231 "Cover.Name": cover_data['name'],
232 "Cover.Token": cover_data['token'],
233 "Cover.Url": cover_data['url'],
236 epub_data = self.upload(
237 (meta.url.slug + '.epub', epub_file, 'application/epub+zip')
240 'BookEpub.Token': epub_data['token'],
241 'BookEpub.Name': epub_data['name'],
242 'SampleEpubType': 'Generation',
245 mobi_data = self.upload(
246 (meta.url.slug + '.mobi', mobi_file, 'application/x-mobipocket-ebook')
249 'BookMobi.Token': mobi_data['token'],
250 'BookMobi.Name': mobi_data['name'],
253 if site_book.external_id:
255 site_book.external_id,
259 site_book.external_id,
263 legimi_id = self.create_book(book_data, files_data)
265 site_book.external_id = legimi_id
266 site_book.save(update_fields=['external_id'])
268 self.edit_sale(site_book)
270 def get_genre(self, wlbook):
271 if wlbook.meta.legimi and wlbook.meta.legimi in self.CATEGORIES:
272 return self.CATEGORIES[wlbook.meta.legimi]
273 for epoch in wlbook.meta.epochs:
274 if epoch in self.CATEGORIES:
275 return self.CATEGORIES[epoch]
276 return self.CATEGORIES['Lektury']
278 def create_book(self, book_data, files_data):
280 'createValidationTrue': 'true',
281 'PublisherId': self.publisher_handle,
282 'IsLibraryPass': 'False',
284 'SamplesGenerationType': 'Quantity',
285 'SamplesGenerationPercent': '10',
287 'EnterToTheMarketType': 'No',
288 'EnterToTheMarketDate': '',
290 'SalesNoLimitOption': 'false',
291 'SalesNoLimitKindle': 'false',
292 'SalesInStoreEbookGrossValue': '0,00',
293 'SalesPromotion': 'False',
294 'SalesPromotionGrossValue': '0,00',
295 'SalesPromotionDatesRange.DateStart': '',
296 'SalesPromotionDatesRange.DateEnd': '',
299 for form in 'Epub', 'Mobi', 'Pdf':
301 f'Book{form}.Token': '',
302 f'Book{form}.Name': '',
303 f'Book{form}.StorageName': '',
304 f'Book{form}.Order': '',
306 f'Sample{form}Type': 'Files',
307 f'Sample{form}.Token': '',
308 f'Sample{form}.Name': '',
309 f'Sample{form}.StorageName': '',
310 f'Sample{form}.Order': '',
313 data.update(book_data)
314 data.update(files_data)
316 response = self.session.post(self.CREATE_URL, data=data)
317 m = re.search(r'/(\d+)$', response.url)
321 def edit(self, legimi_id, data):
323 'ValidationTrue': 'true',
330 self.EDIT_URL % legimi_id,
334 def edit_files(self, legimi_id, files_data):
336 'ValidationTrue': 'true',
338 'SamplesGenerationType': 'Quantity',
339 'SamplesGenerationPercent': '10',
342 for form in 'Epub', 'Mobi', 'Pdf':
344 f'Book{form}.Token': '',
345 f'Book{form}.Name': '',
346 f'Book{form}.StorageName': '',
347 f'Book{form}.Order': '',
349 f'Sample{form}.Type': 'Files',
350 f'Sample{form}.Token': '',
351 f'Sample{form}.Name': '',
352 f'Sample{form}.StorageName': '',
353 f'Sample{form}.Order': '',
356 current.update(files_data)
358 response = self.session.post(
359 self.EDIT_FILES_URL % legimi_id,
363 def edit_sale(self, site_book):
364 book = site_book.book
365 assert site_book.external_id
367 words = book.wldocument(librarian2=True).get_statistics()['total']['words_with_fn']
369 price = settings.LEGIMI_SMALL_PRICE
370 if words > settings.LEGIMI_SMALL_WORDS:
371 price = settings.LEGIMI_BIG_PRICE
373 abo = 'true' if words > settings.LEGIMI_BIG_WORDS else 'false'
376 'ValidationTrue': 'true',
377 'Id': site_book.external_id,
378 'SalesPromotionId': "0",
379 'IsLibraryPass': "False",
380 'OriginalEnterToTheMarketType': "No",
381 'OriginalHidingDate': "",
382 'OriginalEnterToTheMarketDate': "",
383 'EnterToTheMarketType': "Yes",
384 'EnterToTheMarketDate': "",
386 'SalesNoLimitOption': abo,
387 'SalesNoLimitKindle': abo,
388 'SalesInStoreEbookGrossValue': f'{price},00',
389 'SalesPromotion': "False",
390 'SalesPromotionGrossValue': "0,00",
391 'SalesPromotionDatesRange.DateStart': "",
392 'SalesPromotionDatesRange.DateEnd': "",
396 self.EDIT_SALE_URL % site_book.external_id,