|
1 | | -# -*- coding: utf-8 -*- |
2 | | - |
3 | 1 | from __future__ import (unicode_literals, division, absolute_import, print_function) |
| 2 | + |
| 3 | +from calibre.customize import StoreBase |
| 4 | +from calibre.gui2 import open_url |
| 5 | +from calibre.gui2.store import StorePlugin |
| 6 | +from calibre.gui2.store.search_result import SearchResult |
| 7 | +from calibre.gui2.store.web_store_dialog import WebStoreDialog |
| 8 | +from PyQt5.Qt import QUrl |
| 9 | + |
| 10 | +from .libgen_client import LibgenFictionClient |
| 11 | + |
4 | 12 | store_version = 5 # Needed for dynamic plugin loading |
5 | 13 |
|
6 | 14 | __license__ = 'MIT' |
7 | 15 | __copyright__ = 'Fallacious Reasoning' |
8 | 16 | __docformat__ = 'restructuredtext en' |
9 | 17 |
|
10 | | -##################################################################### |
11 | | -# Plug-in base class |
12 | | -##################################################################### |
13 | | - |
14 | | -# from calibre.customize import InterfaceActionBase |
15 | | - |
16 | 18 | PLUGIN_NAME = 'Libgen Fiction' |
17 | 19 | PLUGIN_DESCRIPTION = 'Adds a Libgen Fiction search provider to Calibre' |
18 | | -PLUGIN_VERSION_TUPLE = (0, 1, 0) |
19 | | -PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE]) |
20 | 20 | PLUGIN_AUTHORS = "Fallacious Reasoning (https://github.com/fallaciousreasoning/CalibreLibgenStore)" |
| 21 | +PLUGIN_VERSION = (0, 2, 0) |
21 | 22 |
|
22 | | -##################################################################### |
23 | | - |
24 | | -# import base64 |
25 | | -# import mimetypes |
26 | | -# import re |
27 | | -# import urllib |
28 | | -# import urllib2 |
29 | | -# from contextlib import closing |
30 | | - |
31 | | -# from lxml import etree |
32 | | - |
33 | | -from .libgen_client import LibgenFictionClient |
34 | | - |
35 | | -# from calibre import browser, url_slash_cleaner |
36 | | -# from calibre.constants import __appname__, __version__ |
37 | | -# from calibre.gui2.store.basic_config import BasicStoreConfig |
38 | | -from calibre.gui2.store.search_result import SearchResult |
39 | | -from calibre.gui2.store import StorePlugin |
40 | | - |
41 | | -from calibre.customize import StoreBase |
42 | | - |
43 | | - |
44 | | -libgen = LibgenFictionClient() |
| 23 | +class LibgenStore(StorePlugin): |
| 24 | + def genesis(self): |
| 25 | + ''' |
| 26 | + Initialize the Libgen Client |
| 27 | + ''' |
45 | 28 |
|
46 | | -def search(query, max_results=10, timeout=60): |
47 | | - print('CalibreLibgenStore:search:query = {}'.format(query)) |
| 29 | + print('LibgenStore:genesis: Initializing self.libgen') |
| 30 | + self.libgen = LibgenFictionClient() |
48 | 31 |
|
49 | | - libgen_results = libgen.search(query) |
50 | | - for result in libgen_results.results[:min(max_results, len(libgen_results.results))]: |
51 | | - print('CalibreLibgenStore:search:result.title = {}'.format(result.title)) |
| 32 | + def search(self, query, max_results=10, timeout=60): |
| 33 | + ''' |
| 34 | + Searches LibGen for Books. Since the mirror links are not direct |
| 35 | + downloads, it should not provide these as `s.downloads`. |
| 36 | + ''' |
52 | 37 |
|
53 | | - s = SearchResult() |
| 38 | + print('LibgenStore:search: query = ', query) |
54 | 39 |
|
55 | | - s.title = result.title |
56 | | - s.author = result.author |
57 | | - s.series = result.series |
58 | | - s.language = result.language |
| 40 | + libgen_results = self.libgen.search(query) |
59 | 41 |
|
60 | | - for download in result.downloads: |
61 | | - print('CalibreLibgenStore:search:result.download.url = {}'.format( |
62 | | - download.url)) |
| 42 | + for result in libgen_results.results[:min(max_results, len(libgen_results.results))]: |
| 43 | + print('LibgenStore:search: result.title = ', result.title) |
63 | 44 |
|
64 | | - s.downloads['{} ({} {})'.format( |
65 | | - download.format, |
66 | | - download.size, |
67 | | - download.unit |
68 | | - )] = download.url |
| 45 | + for mirror in result.mirrors[0:1]: # Calibre only shows 1 anyway |
| 46 | + print('LibgenStore:search: result.mirror.url = ', mirror.url) |
69 | 47 |
|
70 | | - s.formats = ', '.join(s.downloads.keys()) |
71 | | - s.drm = SearchResult.DRM_UNLOCKED |
72 | | - s.cover_url = result.image_url |
| 48 | + s = SearchResult() |
73 | 49 |
|
74 | | - # don't show results with no downloads |
75 | | - if not s.formats: |
76 | | - continue |
| 50 | + s.store_name = PLUGIN_NAME |
| 51 | + s.cover_url = result.image_url |
| 52 | + s.title = '{} ({}, {}{})'.format( |
| 53 | + result.title, result.language, mirror.size, mirror.unit) |
| 54 | + s.author = result.authors |
| 55 | + s.price = '0.00' |
| 56 | + s.detail_item = result.md5 |
| 57 | + s.drm = SearchResult.DRM_UNLOCKED |
| 58 | + s.formats = mirror.format |
| 59 | + s.plugin_author = PLUGIN_AUTHORS |
77 | 60 |
|
78 | | - yield s |
| 61 | + print('LibgenStore:search: s = ', s, sep='\n') |
79 | 62 |
|
| 63 | + yield s |
80 | 64 |
|
81 | | -class LibgenStore(StorePlugin): |
82 | | - def search(self, query, max_results=10, timeout=60): |
| 65 | + def open(self, parent=None, detail_item=None, external=False): |
83 | 66 | ''' |
84 | | - Searches LibGen for Books |
| 67 | + Open the specified item in the external, or Calibre's browser |
85 | 68 | ''' |
86 | | - for result in search(query, max_results, timeout): |
87 | | - yield result |
88 | 69 |
|
89 | | -if __name__ == '__main__': |
90 | | - import sys |
| 70 | + print('LibgenStore:open: locals() = ', locals()) |
| 71 | + |
| 72 | + detail_url = ( |
| 73 | + self.libgen.get_detail_url(detail_item) |
| 74 | + if detail_item |
| 75 | + else self.libgen.base_url |
| 76 | + ) |
| 77 | + |
| 78 | + print('LibgenStore:open: detail_url = ', detail_url) |
91 | 79 |
|
92 | | - query = ' '.join(sys.argv[1:]) if len(sys.argv) > 1 else "Stormlight Archive" |
93 | | - for result in search(' '.join(sys.argv[1:])): |
94 | | - print('=========================================================================================================\nTitle: {0}\nAuthor: {1}\nSeries: {2}\nLanguage: {3}\nDownloads: {4}'.format(result.title, result.author, result.series, result.language, len(result.downloads))) |
| 80 | + if external or self.config.get('open_external', False): |
| 81 | + open_url(QUrl(detail_url)) |
| 82 | + else: |
| 83 | + d = WebStoreDialog( |
| 84 | + self.gui, self.libgen.base_url, parent, detail_url) |
| 85 | + d.setWindowTitle(self.name) |
| 86 | + d.set_tags(self.config.get('tags', '')) |
| 87 | + d.exec_() |
95 | 88 |
|
96 | 89 | class LibgenStoreWrapper(StoreBase): |
97 | 90 | name = PLUGIN_NAME |
98 | 91 | description = PLUGIN_DESCRIPTION |
99 | 92 | supported_platforms = ['windows', 'osx', 'linux'] |
100 | 93 | author = PLUGIN_AUTHORS |
101 | | - version = PLUGIN_VERSION_TUPLE |
| 94 | + version = PLUGIN_VERSION |
102 | 95 | minimum_calibre_version = (1, 0, 0) |
103 | 96 | affiliate = False |
| 97 | + drm_free_only = True |
104 | 98 |
|
105 | 99 | def load_actual_plugin(self, gui): |
106 | 100 | ''' |
107 | 101 | This method must return the actual interface action plugin object. |
108 | 102 | ''' |
109 | | - #mod, cls = self.actual_plugin.split(':') |
110 | | - store = LibgenStore(gui, self.name) |
111 | | - self.actual_plugin_object = store#getattr(importlib.import_module(mod), cls)(gui, self.name) |
| 103 | + self.actual_plugin_object = LibgenStore(gui, self.name) |
112 | 104 | return self.actual_plugin_object |
0 commit comments