Legimi update.
[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.cover import LegimiCornerCover, LegimiCover
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     
33     def __init__(self, username, password, publisher_id):
34         self.username = username
35         self.password = password
36         self.publisher_id = publisher_id
37         self._session = None
38
39     @property
40     def session(self):
41         if self._session is None:
42             session = requests.Session()
43             response = session.post(
44                 self.LOGIN_URL,
45                 data={
46                     'ValidationTrue': 'true',
47                     'UserName': self.username,
48                     'Password': self.password,
49                 })
50             self._session = session
51         return self._session
52         
53     def list(self):
54         return self.session.get('https://wydawca.legimi.com/publishers/publications')
55         
56     def upload(self, content):
57         response = self.session.post(
58             self.UPLOAD_URL,
59             files={
60                 "files": content,
61             })
62         model = response.json()['model']
63         return {
64             "name": model['Name'],
65             "token": model['Token'],
66             "url": model['Url'],
67         }
68
69 #    name=files[]
70 #    filename
71 #    content-type
72 #    response: json
73 #     success: true
74 #     model.Url
75
76     def send_book(self, book):
77         wlbook = book.wldocument(librarian2=True)
78         meta = wlbook.meta
79
80         cover = LegimiCornerCover(meta, width=1200).output_file()
81         epub_file = EpubBuilder(cover=LegimiCover, fundraising=fundraising).build(wlbook).get_file()
82         mobi_file = MobiBuilder(cover=LegimiCover, fundraising=fundraising).build(wlbook).get_file()
83
84         book_data = {
85             "Title": meta.title,
86             "Author": ", ".join(p.readable() for p in meta.authors),
87             "Year": meta.created_at[:4],
88
89             'GenreId': '11', # TODO
90             'Isbn': '',
91             'LanguageLocale': lang_code_3to2(meta.language),
92
93             'Description': description_add,
94         }
95         if meta.isbn_html:
96             isbn = meta.isbn_html
97             if isbn.upper().startswith('ISBN '):
98                 isbn = isbn[5:]
99             isbn = isbn.strip()
100             book_data['Isbn'] = isbn
101
102         files_data = {}
103
104         abstract = wlbook.tree.find('.//abstrakt')
105         if abstract is not None:
106             book_data['Description'] = transform_abstrakt(abstract)
107         
108
109         cover_data = self.upload(
110             (meta.url.slug + '.jpg', cover.get_file(), 'image/jpeg')
111         )
112         book_data.update({
113             "Cover.Name": cover_data['name'],
114             "Cover.Token": cover_data['token'],
115             "Cover.Url": cover_data['url'],
116         })
117
118         epub_data = self.upload(
119             (meta.url.slug + '.epub', epub_file, 'application/epub+zip')
120         )
121         files_data.update({
122             'BookEpub.Token': epub_data['token'],
123             'BookEpub.Name': epub_data['name'],
124         })
125
126         mobi_data = self.upload(
127             (meta.url.slug + '.mobi', mobi_file, 'application/x-mobipocket-ebook')
128         )
129         files_data.update({
130             'BookMobi.Token': mobi_data['token'],
131             'BookMobi.Name': mobi_data['name'],
132         })
133         
134         if book.legimi_id:
135             self.edit(
136                 book.legimi_id,
137                 book_data
138             )
139             self.edit_files(
140                 book.legimi_id,
141                 files_data
142             )
143         else:
144             legimi_id = self.create_book(book_data, files_data)
145             if legimi_id:
146                 book.legimi_id = legimi_id
147                 book.save(update_fields=['legimi_id'])
148
149     def get_description(self, wlbook):
150         description = ''
151         abstract = wlbook.tree.find('.//abstrakt')
152         if abstract is not None:
153             description = transform_abstrakt(abstract)
154         description += description_add
155         description += '<p>'
156         description += ', '.join(
157             '<a href="https://wolnelektury.pl/katalog/autor/{}/">{}</a>'.format(
158                 slugify(p.readable()),
159                 p.readable(),
160             )
161             for p in wlbook.meta.authors
162         ) + '<br>'
163         description += '<a href="https://wolnelektury.pl/katalog/lektura/{}/">{}</a><br>'.format(
164             wlbook.meta.url.slug,
165             wlbook.meta.title
166         )
167         if wlbook.meta.translators:
168             description += 'tłum. ' + ', '.join(p.readable() for p in wlbook.meta.translators) + '<br>'
169         description += 'Epoka: ' + ', '.join(
170             '<a href="https://wolnelektury.pl/katalog/epoka/{}/">{}</a>'.format(
171                 slugify(p),
172                 p,
173             )
174             for p in wlbook.meta.epochs
175         ) + ' '
176         description += 'Rodzaj: ' + ', '.join(
177             '<a href="https://wolnelektury.pl/katalog/rodzaj/{}/">{}</a>'.format(
178                 slugify(p),
179                 p,
180             )
181             for p in wlbook.meta.kinds
182         ) + ' '
183         description += 'Gatunek: ' + ', '.join(
184             '<a href="https://wolnelektury.pl/katalog/gatunek/{}/">{}</a>'.format(
185                 slugify(p),
186                 p,
187             )
188             for p in wlbook.meta.genres
189         ) + '</p>'
190
191         if wlbook.meta.audience:
192             description += '<p><em>{}</em> to lektura szkolna.'.format(wlbook.meta.title)
193             if wlbook.tree.find('//pe'):
194                 description += '<br>Ebook <em>{title}</em> zawiera przypisy opracowane specjalnie dla uczennic i uczniów {school}.'.format(
195                     title=wlbook.meta.title,
196                     school='szkoły podstawowej' if wlbook.meta.audience == 'SP' else 'liceum i technikum'
197                 )
198             description += '</p>'
199         return description
200
201     def create_book(self, book_data, files_data):
202         data = {
203             'createValidationTrue': 'true',
204             'PublisherId': self.publisher_id,#3609954
205             'IsLibraryPass': 'False',
206
207             'SamplesGenerationType': 'Quantity',
208             'SamplesGenerationPercent': '10',
209
210             'EnterToTheMarketType': 'No',
211             'EnterToTheMarketDate': date.today().strftime('%d.%m.%Y'),
212             'HidingDate': '',
213             'SalesNoLimitOption': 'false',
214             'SalesNoLimitKindle': 'false',
215             'SalesInStoreEbookGrossValue': '0,00',
216             'SalesPromotion': 'False',
217             'SalesPromotionGrossValue': '0,00',
218             'SalesPromotionDatesRange.DateStart': '',
219             'SalesPromotionDatesRange.DateEnd': '',
220         }
221
222         for form in 'Epub', 'Mobi', 'Pdf':
223             data.update({
224                 f'Book{form}.Token': '',
225                 f'Book{form}.Name': '',
226                 f'Book{form}.StorageName': '',
227                 f'Book{form}.Order': '',
228
229                 f'Sample{form}Type': 'Files',
230                 f'Sample{form}.Token': '',
231                 f'Sample{form}.Name': '',
232                 f'Sample{form}.StorageName': '',
233                 f'Sample{form}.Order': '',
234             })
235
236         data.update(book_data)
237         data.update(files_data)
238
239         response = self.session.post(self.CREATE_URL, data=data)
240         m = re.search(r'/(\d+)$', response.url)
241         if m is not None:
242             return m.group(1)
243
244     def edit(self, legimi_id, data):
245         current = {
246             'ValidationTrue': 'true',
247             'Is': legimi_id
248         }
249
250         current.update(data)
251         
252         self.session.post(
253             self.EDIT_URL % legimi_id,
254             data=current
255         )
256
257     def edit_files(self, legimi_id, files_data):
258         current = {
259             'ValidationTrue': 'true',
260             'Id': legimi_id,
261             'SamplesGenerationType': 'Quantity',
262             'SamplesGenerationPercent': '10',
263         }
264
265         for form in 'Epub', 'Mobi', 'Pdf':
266             current.update({
267                 f'Book{form}.Token': '',
268                 f'Book{form}.Name': '',
269                 f'Book{form}.StorageName': '',
270                 f'Book{form}.Order': '',
271
272                 f'Sample{form}.Type': 'Files',
273                 f'Sample{form}.Token': '',
274                 f'Sample{form}.Name': '',
275                 f'Sample{form}.StorageName': '',
276                 f'Sample{form}.Order': '',
277             })
278
279         current.update(files_data)
280  
281         response = self.session.post(
282             self.EDIT_FILES_URL % legimi_id,
283             data=current
284         )
285
286
287 legimi = Legimi(
288     settings.LEGIMI_USERNAME,
289     settings.LEGIMI_PASSWORD,
290     settings.LEGIMI_PUBLISHER_ID,
291 )