8d2939e4ac7782549570898d8f32ee1f6a2aab5c
[redakcja.git] / src / depot / legimi.py
1 from datetime import date
2 import re
3 from django.conf import settings
4 from librarian.functions import lang_code_3to2
5 from librarian.html import transform_abstrakt
6 from librarian.builders import EpubBuilder, MobiBuilder
7 from librarian.covers.marquise import MarquiseCover, LabelMarquiseCover
8 import requests
9 from slugify import slugify
10
11
12
13 fundraising=[
14             "Książka, którą czytasz, pochodzi z <a href=\"https://wolnelektury.pl/\">Wolnych Lektur</a>. Naszą misją jest wspieranie dzieciaków w dostępie do lektur szkolnych oraz zachęcanie ich do czytania. Miło Cię poznać!",
15             "Podoba Ci się to, co robimy? Jesteśmy organizacją pożytku publicznego. Wesprzyj Wolne Lektury drobną wpłatą: <a href=\"https://wolnelektury.pl/towarzystwo/\">wolnelektury.pl/towarzystwo/</a>",
16             "Przyjaciele Wolnych Lektur otrzymują dostęp do prapremier wcześniej niż inni. Zadeklaruj stałą wpłatę i dołącz do Towarzystwa Przyjaciół Wolnych Lektur: <a href=\"https://wolnelektury.pl/towarzystwo/\">wolnelektury.pl/towarzystwo/</a>",
17             "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: <a href=\"https://wolnelektury.pl/newsletter/zapisz-sie/\">wolnelektury.pl/newsletter/zapisz-sie/</a>",
18             "Przekaż 1% podatku na Wolne Lektury.<br/>\nKRS: 0000070056<br/>\nNazwa organizacji: Fundacja Nowoczesna Polska<br/>\nKażda wpłacona kwota zostanie przeznaczona na rozwój Wolnych Lektur."
19 ]
20
21 description_add = '<p>Książkę polecają <a href="https://wolnelektury.pl">Wolne Lektury</a> — najpopularniejsza biblioteka on-line.</p>'
22
23
24 class Legimi:
25     #BASE_URL = 'https://wydawca.legimi.com'
26     BASE_URL = 'https://panel.legimi.pl'
27     LOGIN_URL = BASE_URL + '/publishers/membership'
28     UPLOAD_URL = BASE_URL + '/administration/upload/start'
29     CREATE_URL = BASE_URL + '/publishers/publications/create'
30     EDIT_URL = BASE_URL + '/publishers/publications/edit/%s'
31     EDIT_FILES_URL = BASE_URL + '/publishers/publications/editfiles/%s'
32     EDIT_SALE_URL = BASE_URL + '/publishers/publications/editsale/%s'
33     
34     def __init__(self, username, password, publisher_id):
35         self.username = username
36         self.password = password
37         self.publisher_id = publisher_id
38         self._session = None
39
40     @property
41     def session(self):
42         if self._session is None:
43             session = requests.Session()
44             response = session.post(
45                 self.LOGIN_URL,
46                 data={
47                     'ValidationTrue': 'true',
48                     'UserName': self.username,
49                     'Password': self.password,
50                 })
51             self._session = session
52         return self._session
53         
54     def list(self):
55         return self.session.get('https://wydawca.legimi.com/publishers/publications')
56         
57     def upload(self, content):
58         response = self.session.post(
59             self.UPLOAD_URL,
60             files={
61                 "files": content,
62             })
63         model = response.json()['model']
64         return {
65             "name": model['Name'],
66             "token": model['Token'],
67             "url": model['Url'],
68         }
69
70 #    name=files[]
71 #    filename
72 #    content-type
73 #    response: json
74 #     success: true
75 #     model.Url
76
77     def send_book(self, book):
78         wlbook = book.wldocument(librarian2=True)
79         meta = wlbook.meta
80
81         cover = LabelMarquiseCover(meta, width=1200).output_file()
82         epub_file = EpubBuilder(cover=MarquiseCover, fundraising=fundraising).build(wlbook).get_file()
83         mobi_file = MobiBuilder(cover=MarquiseCover, fundraising=fundraising).build(wlbook).get_file()
84
85         book_data = {
86             "Title": meta.title,
87             "Author": ", ".join(p.readable() for p in meta.authors),
88             "Year": meta.created_at[:4],
89
90             'GenreId': str(self.get_genre(wlbook)),
91             'Isbn': '',
92             'LanguageLocale': lang_code_3to2(meta.language),
93
94             'Description': self.get_description(wlbook),
95         }
96         if meta.isbn_html:
97             isbn = meta.isbn_html
98             if isbn.upper().startswith('ISBN '):
99                 isbn = isbn[5:]
100             isbn = isbn.strip()
101             book_data['Isbn'] = isbn
102
103         files_data = {}
104
105         cover_data = self.upload(
106             (meta.url.slug + '.jpg', cover.get_file(), 'image/jpeg')
107         )
108         book_data.update({
109             "Cover.Name": cover_data['name'],
110             "Cover.Token": cover_data['token'],
111             "Cover.Url": cover_data['url'],
112         })
113
114         epub_data = self.upload(
115             (meta.url.slug + '.epub', epub_file, 'application/epub+zip')
116         )
117         files_data.update({
118             'BookEpub.Token': epub_data['token'],
119             'BookEpub.Name': epub_data['name'],
120         })
121
122         mobi_data = self.upload(
123             (meta.url.slug + '.mobi', mobi_file, 'application/x-mobipocket-ebook')
124         )
125         files_data.update({
126             'BookMobi.Token': mobi_data['token'],
127             'BookMobi.Name': mobi_data['name'],
128         })
129         
130         if book.legimi_id:
131             self.edit(
132                 book.legimi_id,
133                 book_data
134             )
135             self.edit_files(
136                 book.legimi_id,
137                 files_data
138             )
139         else:
140             legimi_id = self.create_book(book_data, files_data)
141             if legimi_id:
142                 book.legimi_id = legimi_id
143                 book.save(update_fields=['legimi_id'])
144
145     def get_description(self, wlbook):
146         description = ''
147         abstract = wlbook.tree.find('.//abstrakt')
148         if abstract is not None:
149             description = transform_abstrakt(abstract)
150         description += description_add
151         description += '<p>'
152         description += ', '.join(
153             '<a href="https://wolnelektury.pl/katalog/autor/{}/">{}</a>'.format(
154                 slugify(p.readable()),
155                 p.readable(),
156             )
157             for p in wlbook.meta.authors
158         ) + '<br>'
159         description += '<a href="https://wolnelektury.pl/katalog/lektura/{}/">{}</a><br>'.format(
160             wlbook.meta.url.slug,
161             wlbook.meta.title
162         )
163         if wlbook.meta.translators:
164             description += 'tłum. ' + ', '.join(p.readable() for p in wlbook.meta.translators) + '<br>'
165         description += 'Epoka: ' + ', '.join(
166             '<a href="https://wolnelektury.pl/katalog/epoka/{}/">{}</a>'.format(
167                 slugify(p),
168                 p,
169             )
170             for p in wlbook.meta.epochs
171         ) + ' '
172         description += 'Rodzaj: ' + ', '.join(
173             '<a href="https://wolnelektury.pl/katalog/rodzaj/{}/">{}</a>'.format(
174                 slugify(p),
175                 p,
176             )
177             for p in wlbook.meta.kinds
178         ) + ' '
179         description += 'Gatunek: ' + ', '.join(
180             '<a href="https://wolnelektury.pl/katalog/gatunek/{}/">{}</a>'.format(
181                 slugify(p),
182                 p,
183             )
184             for p in wlbook.meta.genres
185         ) + '</p>'
186
187         if wlbook.meta.audience:
188             description += '<p><em>{}</em> to lektura szkolna.'.format(wlbook.meta.title)
189             if wlbook.tree.find('//pe') is not None:
190                 description += '<br>Ebook <em>{title}</em> zawiera przypisy opracowane specjalnie dla uczennic i uczniów {school}.'.format(
191                     title=wlbook.meta.title,
192                     school='szkoły podstawowej' if wlbook.meta.audience == 'SP' else 'liceum i technikum'
193                 )
194             description += '</p>'
195         return description
196
197     def get_genre(self, wlbook):
198         epoch_map = {
199             'Starożytność': 80,
200             'Średniowiecze': 81,
201             'Renesans': 82,
202             'Barok': 83,
203             'Oświecenie': 84,
204             'Romantyzm': 85,
205             'Pozytywizm': 86,
206             'Modernizm': 87,
207             'Dwudziestolecie międzywojenne': 88,
208             'Współczesność': 90,
209         }
210
211         for epoch in wlbook.meta.epochs:
212             if epoch in epoch_map:
213                 return epoch_map[epoch]
214         return 11
215     
216     def create_book(self, book_data, files_data):
217         data = {
218             'createValidationTrue': 'true',
219             'PublisherId': self.publisher_id,#3609954
220             'IsLibraryPass': 'False',
221
222             'SamplesGenerationType': 'Quantity',
223             'SamplesGenerationPercent': '10',
224
225             'EnterToTheMarketType': 'No',
226             'EnterToTheMarketDate': date.today().strftime('%d.%m.%Y'),
227             'HidingDate': '',
228             'SalesNoLimitOption': 'false',
229             'SalesNoLimitKindle': 'false',
230             'SalesInStoreEbookGrossValue': '0,00',
231             'SalesPromotion': 'False',
232             'SalesPromotionGrossValue': '0,00',
233             'SalesPromotionDatesRange.DateStart': '',
234             'SalesPromotionDatesRange.DateEnd': '',
235         }
236
237         for form in 'Epub', 'Mobi', 'Pdf':
238             data.update({
239                 f'Book{form}.Token': '',
240                 f'Book{form}.Name': '',
241                 f'Book{form}.StorageName': '',
242                 f'Book{form}.Order': '',
243
244                 f'Sample{form}Type': 'Files',
245                 f'Sample{form}.Token': '',
246                 f'Sample{form}.Name': '',
247                 f'Sample{form}.StorageName': '',
248                 f'Sample{form}.Order': '',
249             })
250
251         data.update(book_data)
252         data.update(files_data)
253
254         response = self.session.post(self.CREATE_URL, data=data)
255         m = re.search(r'/(\d+)$', response.url)
256         if m is not None:
257             return m.group(1)
258
259     def edit(self, legimi_id, data):
260         current = {
261             'ValidationTrue': 'true',
262             'Is': legimi_id
263         }
264
265         current.update(data)
266         
267         self.session.post(
268             self.EDIT_URL % legimi_id,
269             data=current
270         )
271
272     def edit_files(self, legimi_id, files_data):
273         current = {
274             'ValidationTrue': 'true',
275             'Id': legimi_id,
276             'SamplesGenerationType': 'Quantity',
277             'SamplesGenerationPercent': '10',
278         }
279
280         for form in 'Epub', 'Mobi', 'Pdf':
281             current.update({
282                 f'Book{form}.Token': '',
283                 f'Book{form}.Name': '',
284                 f'Book{form}.StorageName': '',
285                 f'Book{form}.Order': '',
286
287                 f'Sample{form}.Type': 'Files',
288                 f'Sample{form}.Token': '',
289                 f'Sample{form}.Name': '',
290                 f'Sample{form}.StorageName': '',
291                 f'Sample{form}.Order': '',
292             })
293
294         current.update(files_data)
295  
296         response = self.session.post(
297             self.EDIT_FILES_URL % legimi_id,
298             data=current
299         )
300
301     def edit_sale(self, book):
302         assert book.legimi_id
303
304         words = book.wldocument().get_statistics()['total']['words_with_fn']
305
306         price = settings.LEGIMI_SMALL_PRICE
307         if words > settings.LEGIMI_SMALL_WORDS:
308             price = settings.LEGIMI_BIG_PRICE
309
310         abo = 'true' if words > settings.LEGIMI_BIG_WORDS else 'false'
311
312         data = {
313             'ValidationTrue': 'true',
314             'Id': book.legimi_id,
315             'SalesPromotionId': "0",
316             'IsLibraryPass': "False",
317             'OriginalEnterToTheMarketType': "No",
318             'OriginalHidingDate': "",
319             'OriginalEnterToTheMarketDate': "",
320             'EnterToTheMarketType': "No",
321             'EnterToTheMarketDate': "",
322             'HidingDate': "",
323             'SalesNoLimitOption': abo,
324             'SalesNoLimitKindle': abo,
325             'SalesInStoreEbookGrossValue': f'{price},00',
326             'SalesPromotion': "False",
327             'SalesPromotionGrossValue': "0,00",
328             'SalesPromotionDatesRange.DateStart': "",
329             'SalesPromotionDatesRange.DateEnd': "",
330         }
331
332         self.session.post(
333             self.EDIT_SALE_URL % book.legimi_id,
334             data=data
335         )
336         
337
338 legimi = Legimi(
339     settings.LEGIMI_USERNAME,
340     settings.LEGIMI_PASSWORD,
341     settings.LEGIMI_PUBLISHER_ID,
342 )