1- # -*- coding: utf-8 -*-
2-
31from __future__ import (unicode_literals , division , absolute_import , print_function )
2+
3+ from calibre .customize import StoreBase
4+ from calibre .devices .usbms .driver import debug_print
5+ from calibre .gui2 import open_url
6+ from calibre .gui2 .store import StorePlugin
7+ from calibre .gui2 .store .search_result import SearchResult
8+ from calibre .gui2 .store .web_store_dialog import WebStoreDialog
9+ from PyQt5 .Qt import QUrl
10+
11+ from .libgen_client import LibgenFictionClient
12+
413store_version = 5 # Needed for dynamic plugin loading
514
615__license__ = 'MIT'
716__copyright__ = 'Fallacious Reasoning'
817__docformat__ = 'restructuredtext en'
918
10- #####################################################################
11- # Plug-in base class
12- #####################################################################
13-
14- from calibre .customize import InterfaceActionBase
15-
1619PLUGIN_NAME = 'Libgen Fiction'
17- PLUGIN_DESCRIPTION = 'Adds a Libfen 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+ PLUGIN_DESCRIPTION = 'Adds a Libgen Fiction search provider to Calibre'
2021PLUGIN_AUTHORS = "Fallacious Reasoning (https://github.com/fallaciousreasoning/CalibreLibgenStore)"
22+ PLUGIN_VERSION = (0 , 2 , 0 )
2123
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
24+ class LibgenStore (StorePlugin ):
25+ def genesis (self ):
26+ '''
27+ Initialize the Libgen Client
28+ '''
29+ debug_print ('Libgen Fiction::__init__.py:LibgenStore:genesis' )
3430
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
31+ self .libgen = LibgenFictionClient ()
4032
41- from calibre .customize import StoreBase
33+ def search (self , query , max_results = 10 , timeout = 60 ):
34+ '''
35+ Searches LibGen for Books. Since the mirror links are not direct
36+ downloads, it should not provide these as `s.downloads`.
37+ '''
4238
39+ debug_print ('Libgen Fiction::__init__.py:LibgenStore:search:query =' ,
40+ query )
4341
44- web_url = 'http://libgen.io/'
45- libgen = LibgenFictionClient ()
42+ libgen_results = self .libgen .search (query )
4643
47- def search ( query , max_results = 10 , timeout = 60 ) :
48- libgen_results = libgen . search ( query )
49- for result in libgen_results . results [: min ( max_results , len ( libgen_results . results ))]:
50- s = SearchResult ( )
44+ for result in libgen_results . results [: min ( max_results , len ( libgen_results . results ))] :
45+ debug_print ( 'Libgen Fiction::__init__.py:LibgenStore: search:'
46+ 'result.title =' ,
47+ result . title )
5148
52- s .title = result .title
53- s .author = result .author
54- s .series = result .series
55- s .language = result .language
49+ for mirror in result .mirrors [0 :1 ]: # Calibre only shows 1 anyway
50+ debug_print ('Libgen Fiction::__init__.py:LibgenStore:search:'
51+ 'result.mirror.url =' , mirror .url )
5652
57- for download in result .downloads :
58- s .downloads [download .format ] = download .url
53+ s = SearchResult ()
5954
60- s .formats = ', ' .join (s .downloads .keys ())
61- s .drm = SearchResult .DRM_UNLOCKED
62- s .cover_url = result .image_url
55+ s .store_name = PLUGIN_NAME
56+ s .cover_url = result .image_url
57+ s .title = '{} ({}, {}{})' .format (
58+ result .title , result .language , mirror .size , mirror .unit )
59+ s .author = result .authors
60+ s .price = '0.00'
61+ s .detail_item = result .md5
62+ s .drm = SearchResult .DRM_UNLOCKED
63+ s .formats = mirror .format
64+ s .plugin_author = PLUGIN_AUTHORS
6365
64- # don't show results with no downloads
65- if not s .formats :
66- continue
66+ debug_print ('Libgen Fiction::__init__.py:LibgenStore:search:s =' ,
67+ s )
6768
68- yield s
69+ yield s
6970
70-
71- class LibgenStore (StorePlugin ):
72- def search (self , query , max_results = 10 , timeout = 60 ):
71+ def open (self , parent = None , detail_item = None , external = False ):
7372 '''
74- Searches LibGen for Books
73+ Open the specified item in the external, or Calibre's browser
7574 '''
76- for result in search (query , max_results , timeout ):
77- yield result
7875
79- if __name__ == '__main__' :
80- import sys
76+ debug_print ('Libgen Fiction::__init__.py:LibgenStore:open:locals() =' ,
77+ locals ())
78+
79+ detail_url = (
80+ self .libgen .get_detail_url (detail_item )
81+ if detail_item
82+ else self .libgen .base_url
83+ )
84+
85+ debug_print ('Libgen Fiction::__init__.py:LibgenStore:open:detail_url =' ,
86+ detail_url )
8187
82- query = ' ' .join (sys .argv [1 :]) if len (sys .argv ) > 1 else "Stormlight Archive"
83- for result in search (' ' .join (sys .argv [1 :])):
84- print ('=========================================================================================================\n Title: {0}\n Author: {1}\n Series: {2}\n Language: {3}\n Downloads: {4}' .format (result .title , result .author , result .series , result .language , len (result .downloads )))
88+ if external or self .config .get ('open_external' , False ):
89+ open_url (QUrl (detail_url ))
90+ else :
91+ d = WebStoreDialog (
92+ self .gui , self .libgen .base_url , parent , detail_url )
93+ d .setWindowTitle (self .name )
94+ d .set_tags (self .config .get ('tags' , '' ))
95+ d .exec_ ()
8596
8697class LibgenStoreWrapper (StoreBase ):
8798 name = PLUGIN_NAME
8899 description = PLUGIN_DESCRIPTION
89100 supported_platforms = ['windows' , 'osx' , 'linux' ]
90101 author = PLUGIN_AUTHORS
91- version = PLUGIN_VERSION_TUPLE
102+ version = PLUGIN_VERSION
92103 minimum_calibre_version = (1 , 0 , 0 )
93104 affiliate = False
105+ drm_free_only = True
94106
95107 def load_actual_plugin (self , gui ):
96108 '''
97109 This method must return the actual interface action plugin object.
98110 '''
99- #mod, cls = self.actual_plugin.split(':')
100- store = LibgenStore (gui , self .name )
101- self .actual_plugin_object = store #getattr(importlib.import_module(mod), cls)(gui, self.name)
102- return self .actual_plugin_object
111+ self .actual_plugin_object = LibgenStore (gui , self .name )
112+ return self .actual_plugin_object
0 commit comments