-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from harmtemolder/master
Updated code to match new style search result page
- Loading branch information
Showing
5 changed files
with
309 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# “Compiled” | ||
*.zip | ||
|
||
# Calibre | ||
calibre | ||
|
||
# PyCharm | ||
.idea | ||
|
||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
share/python-wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.py,cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
cover/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
.pybuilder/ | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
# For a library or package, you might want to ignore these files since the code is | ||
# intended to run in multiple environments; otherwise, check them in: | ||
# .python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
|
||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||
__pypackages__/ | ||
|
||
# Celery stuff | ||
celerybeat-schedule | ||
celerybeat.pid | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ | ||
|
||
# pytype static type analyzer | ||
.pytype/ | ||
|
||
# Cython debug symbols | ||
cython_debug/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,112 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from __future__ import (unicode_literals, division, absolute_import, print_function) | ||
|
||
from calibre.customize import StoreBase | ||
from calibre.devices.usbms.driver import debug_print | ||
from calibre.gui2 import open_url | ||
from calibre.gui2.store import StorePlugin | ||
from calibre.gui2.store.search_result import SearchResult | ||
from calibre.gui2.store.web_store_dialog import WebStoreDialog | ||
from PyQt5.Qt import QUrl | ||
|
||
from .libgen_client import LibgenFictionClient | ||
|
||
store_version = 5 # Needed for dynamic plugin loading | ||
|
||
__license__ = 'MIT' | ||
__copyright__ = 'Fallacious Reasoning' | ||
__docformat__ = 'restructuredtext en' | ||
|
||
##################################################################### | ||
# Plug-in base class | ||
##################################################################### | ||
|
||
from calibre.customize import InterfaceActionBase | ||
|
||
PLUGIN_NAME = 'Libgen Fiction' | ||
PLUGIN_DESCRIPTION = 'Adds a Libfen Fiction search provider to Calibre' | ||
PLUGIN_VERSION_TUPLE = (0, 1, 0) | ||
PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE]) | ||
PLUGIN_DESCRIPTION = 'Adds a Libgen Fiction search provider to Calibre' | ||
PLUGIN_AUTHORS = "Fallacious Reasoning (https://github.com/fallaciousreasoning/CalibreLibgenStore)" | ||
PLUGIN_VERSION = (0, 2, 0) | ||
|
||
##################################################################### | ||
|
||
import base64 | ||
import mimetypes | ||
import re | ||
import urllib | ||
import urllib2 | ||
from contextlib import closing | ||
|
||
from lxml import etree | ||
|
||
from .libgen_client import LibgenFictionClient | ||
class LibgenStore(StorePlugin): | ||
def genesis(self): | ||
''' | ||
Initialize the Libgen Client | ||
''' | ||
debug_print('Libgen Fiction::__init__.py:LibgenStore:genesis') | ||
|
||
from calibre import browser, url_slash_cleaner | ||
from calibre.constants import __appname__, __version__ | ||
from calibre.gui2.store.basic_config import BasicStoreConfig | ||
from calibre.gui2.store.search_result import SearchResult | ||
from calibre.gui2.store import StorePlugin | ||
self.libgen = LibgenFictionClient() | ||
|
||
from calibre.customize import StoreBase | ||
def search(self, query, max_results=10, timeout=60): | ||
''' | ||
Searches LibGen for Books. Since the mirror links are not direct | ||
downloads, it should not provide these as `s.downloads`. | ||
''' | ||
|
||
debug_print('Libgen Fiction::__init__.py:LibgenStore:search:query =', | ||
query) | ||
|
||
web_url = 'http://libgen.io/' | ||
libgen = LibgenFictionClient() | ||
libgen_results = self.libgen.search(query) | ||
|
||
def search(query, max_results=10, timeout=60): | ||
libgen_results = libgen.search(query) | ||
for result in libgen_results.results[:min(max_results, len(libgen_results.results))]: | ||
s = SearchResult() | ||
for result in libgen_results.results[:min(max_results, len(libgen_results.results))]: | ||
debug_print('Libgen Fiction::__init__.py:LibgenStore:search:' | ||
'result.title =', | ||
result.title) | ||
|
||
s.title = result.title | ||
s.author = result.author | ||
s.series = result.series | ||
s.language = result.language | ||
for mirror in result.mirrors[0:1]: # Calibre only shows 1 anyway | ||
debug_print('Libgen Fiction::__init__.py:LibgenStore:search:' | ||
'result.mirror.url =', mirror.url) | ||
|
||
for download in result.downloads: | ||
s.downloads[download.format] = download.url | ||
s = SearchResult() | ||
|
||
s.formats = ', '.join(s.downloads.keys()) | ||
s.drm = SearchResult.DRM_UNLOCKED | ||
s.cover_url = result.image_url | ||
s.store_name = PLUGIN_NAME | ||
s.cover_url = result.image_url | ||
s.title = '{} ({}, {}{})'.format( | ||
result.title, result.language, mirror.size, mirror.unit) | ||
s.author = result.authors | ||
s.price = '0.00' | ||
s.detail_item = result.md5 | ||
s.drm = SearchResult.DRM_UNLOCKED | ||
s.formats = mirror.format | ||
s.plugin_author = PLUGIN_AUTHORS | ||
|
||
# don't show results with no downloads | ||
if not s.formats: | ||
continue | ||
debug_print('Libgen Fiction::__init__.py:LibgenStore:search:s =', | ||
s) | ||
|
||
yield s | ||
yield s | ||
|
||
|
||
class LibgenStore(StorePlugin): | ||
def search(self, query, max_results=10, timeout=60): | ||
def open(self, parent=None, detail_item=None, external=False): | ||
''' | ||
Searches LibGen for Books | ||
Open the specified item in the external, or Calibre's browser | ||
''' | ||
for result in search(query, max_results, timeout): | ||
yield result | ||
|
||
if __name__ == '__main__': | ||
import sys | ||
debug_print('Libgen Fiction::__init__.py:LibgenStore:open:locals() =', | ||
locals()) | ||
|
||
detail_url = ( | ||
self.libgen.get_detail_url(detail_item) | ||
if detail_item | ||
else self.libgen.base_url | ||
) | ||
|
||
debug_print('Libgen Fiction::__init__.py:LibgenStore:open:detail_url =', | ||
detail_url) | ||
|
||
query = ' '.join(sys.argv[1:]) if len(sys.argv) > 1 else "Stormlight Archive" | ||
for result in search(' '.join(sys.argv[1:])): | ||
print('=========================================================================================================\nTitle: {0}\nAuthor: {1}\nSeries: {2}\nLanguage: {3}\nDownloads: {4}'.format(result.title, result.author, result.series, result.language, len(result.downloads))) | ||
if external or self.config.get('open_external', False): | ||
open_url(QUrl(detail_url)) | ||
else: | ||
d = WebStoreDialog( | ||
self.gui, self.libgen.base_url, parent, detail_url) | ||
d.setWindowTitle(self.name) | ||
d.set_tags(self.config.get('tags', '')) | ||
d.exec_() | ||
|
||
class LibgenStoreWrapper(StoreBase): | ||
name = PLUGIN_NAME | ||
description = PLUGIN_DESCRIPTION | ||
supported_platforms = ['windows', 'osx', 'linux'] | ||
author = PLUGIN_AUTHORS | ||
version = PLUGIN_VERSION_TUPLE | ||
version = PLUGIN_VERSION | ||
minimum_calibre_version = (1, 0, 0) | ||
affiliate = False | ||
drm_free_only = True | ||
|
||
def load_actual_plugin(self, gui): | ||
''' | ||
This method must return the actual interface action plugin object. | ||
''' | ||
#mod, cls = self.actual_plugin.split(':') | ||
store = LibgenStore(gui, self.name) | ||
self.actual_plugin_object = store#getattr(importlib.import_module(mod), cls)(gui, self.name) | ||
return self.actual_plugin_object | ||
self.actual_plugin_object = LibgenStore(gui, self.name) | ||
return self.actual_plugin_object |
Oops, something went wrong.