diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index cfb79f1cab..137cf3c27e 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -1366,24 +1366,6 @@ class StoreAmazonKindleStore(StoreBase): affiliate = False -class StoreSonyStore(StoreBase): - name = 'SONY Reader Store' - description = u'SONY Reader books.' - author = 'Kovid Goyal' - actual_plugin = 'calibre.gui2.store.stores.sony_plugin:SonyStore' - - headquarters = 'US' - formats = ['SONY'] - affiliate = False - - -class StoreSonyAUStore(StoreSonyStore): - name = 'SONY Reader (Australia) Store' - description = u'SONY Reader books (Australia).' - actual_plugin = 'calibre.gui2.store.stores.sony_au_plugin:SonyStore' - headquarters = 'AU' - - class StoreAmazonAUKindleStore(StoreBase): name = 'Amazon AU Kindle' author = u'Kovid Goyal' @@ -1758,16 +1740,6 @@ class StoreNextoStore(StoreBase): affiliate = True -class StoreNookUKStore(StoreBase): - name = 'Nook UK' - author = 'Charles Haley' - description = u'Barnes & Noble S.A.R.L, a subsidiary of Barnes & Noble, Inc., a leading retailer of content, digital media and educational products, is proud to bring the award-winning NOOK reading experience and a leading digital bookstore to the UK.' # noqa - actual_plugin = 'calibre.gui2.store.stores.nook_uk_plugin:NookUKStore' - - headquarters = 'UK' - formats = ['NOOK'] - - class StoreOpenBooksStore(StoreBase): name = 'Open Books' description = u'Comprehensive listing of DRM free e-books from a variety of sources provided by users of calibre.' @@ -1930,14 +1902,12 @@ plugins += [ StoreMillsBoonUKStore, StoreMobileReadStore, StoreNextoStore, - StoreNookUKStore, StoreOpenBooksStore, StoreOzonRUStore, StorePragmaticBookshelfStore, StorePublioStore, StoreRW2010Store, StoreSmashwordsStore, - StoreSonyStore, StoreSonyAUStore, StoreVirtualoStore, StoreWeightlessBooksStore, StoreWHSmithUKStore, diff --git a/src/calibre/gui2/store/stores/ebook_nl_plugin.py b/src/calibre/gui2/store/stores/ebook_nl_plugin.py index 029fd5040e..eaca1b327e 100644 --- a/src/calibre/gui2/store/stores/ebook_nl_plugin.py +++ b/src/calibre/gui2/store/stores/ebook_nl_plugin.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import (unicode_literals, division, absolute_import, print_function) -store_version = 1 # Needed for dynamic plugin loading +store_version = 2 # Needed for dynamic plugin loading __license__ = 'GPL 3' __copyright__ = '2011, John Schember ' @@ -48,32 +48,19 @@ class EBookNLStore(BasicStoreConfig, StorePlugin): counter = max_results with closing(br.open(url, timeout=timeout)) as f: doc = html.fromstring(f.read()) - for data in doc.xpath('//table[contains(@class, "productListing")]/tr'): + for data in doc.xpath('//div[@id="books"]/div[@itemtype="http://schema.org/Book"]'): if counter <= 0: break - details = data.xpath('./td/div[@class="prodImage"]/a') - if not details: - continue - details = details[0] - id = ''.join(details.xpath('./@href')).strip() - id = id[id.rfind('/')+1:] - i = id.rfind('?') - if i > 0: - id = id[:i] + id = ''.join(data.xpath('./meta[@itemprop="url"]/@content')).strip() if not id: continue - cover_url = 'http://www.ebook.nl/store/' + ''.join(details.xpath('./img/@src')) - title = ''.join(details.xpath('./img/@title')).strip() - author = ''.join(data.xpath('./td/div[@class="prodTitle"]/h3/a/text()')).strip() - price = ''.join(data.xpath('./td/div[@class="prodTitle"]/b/text()')) - pdf = data.xpath('boolean(./td/div[@class="prodTitle"]/' - 'p[contains(text(), "Bestandsformaat: Pdf")])') - epub = data.xpath('boolean(./td/div[@class="prodTitle"]/' - 'p[contains(text(), "Bestandsformaat: ePub")])') - nodrm = data.xpath('boolean(./td/div[@class="prodTitle"]/' - 'p[contains(text(), "zonder DRM") or' - ' contains(text(), "watermerk")])') + cover_url = 'http://www.ebook.nl/store/' + ''.join(data.xpath('.//img[@itemprop="image"]/@src')) + title = ''.join(data.xpath('./span[@itemprop="name"]/a/text()')).strip() + author = ''.join(data.xpath('./span[@itemprop="author"]/a/text()')).strip() + if author == ' ': + author = '' + price = ''.join(data.xpath('.//span[@itemprop="price"]//text()')) counter -= 1 s = SearchResult() @@ -81,16 +68,27 @@ class EBookNLStore(BasicStoreConfig, StorePlugin): s.title = title.strip() s.author = author.strip() s.price = price - if nodrm: - s.drm = SearchResult.DRM_UNLOCKED - else: - s.drm = SearchResult.DRM_LOCKED + s.drm = SearchResult.DRM_UNKNOWN s.detail_item = id - formats = [] - if epub: - formats.append('ePub') - if pdf: - formats.append('PDF') - s.formats = ','.join(formats) yield s + + def get_details(self, search_result, timeout): + br = browser() + with closing(br.open(search_result.detail_item, timeout=timeout)) as nf: + idata = html.fromstring(nf.read()) + formats = [] + if idata.xpath('.//div[@id="book_detail_body"]/ul/li[strong[contains(., "Type")]]/span[contains(., "ePub")]'): + if idata.xpath('.//div[@id="book_detail_body"]/ul/li[strong[contains(., "Type")]]/span[contains(., "EPUB3")]'): + formats.append('EPUB3') + else: + formats.append('EPUB') + if idata.xpath('.//div[@id="book_detail_body"]/ul/li[strong[contains(., "Type")]]/span[contains(., "Pdf")]'): + formats.append('PDF') + search_result.formats = ', '.join(formats) + + if idata.xpath('.//div[@id="book_detail_body"]/ul/li[strong[contains(., "Type")]]//span[@class="ePubAdobeDRM" or @class="ePubwatermerk" or @class="Pdfwatermark" or @class="PdfAdobeDRM"]'): + search_result.drm = SearchResult.DRM_LOCKED + if idata.xpath('.//div[@id="book_detail_body"]/ul/li[strong[contains(., "Type")]]//span[@class="ePubzonderDRM"]'): + search_result.drm = SearchResult.DRM_UNLOCKED + return True diff --git a/src/calibre/gui2/store/stores/nook_uk_plugin.py b/src/calibre/gui2/store/stores/nook_uk_plugin.py deleted file mode 100644 index 8eda06ede6..0000000000 --- a/src/calibre/gui2/store/stores/nook_uk_plugin.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import (unicode_literals, division, absolute_import, print_function) -store_version = 4 # Needed for dynamic plugin loading - -__license__ = 'GPL 3' -__copyright__ = '2012, John Schember ' -__docformat__ = 'restructuredtext en' - -import re -import urllib -from contextlib import closing - -from lxml import html - -from PyQt5.Qt import QUrl - -from calibre import browser, url_slash_cleaner -from calibre.gui2 import open_url -from calibre.gui2.store import StorePlugin -from calibre.gui2.store.basic_config import BasicStoreConfig -from calibre.gui2.store.search_result import SearchResult -from calibre.gui2.store.web_store_dialog import WebStoreDialog - - -class NookUKStore(BasicStoreConfig, StorePlugin): - - def open(self, parent=None, detail_item=None, external=False): - url = 'http://www.nook.com/gb/store' - detail_url = '' - - if external or self.config.get('open_external', False): - if detail_item: - url = detail_url + detail_item - - open_url(QUrl(url_slash_cleaner(url))) - else: - if detail_item: - detail_url = detail_url + detail_item - else: - detail_url = None - d = WebStoreDialog(self.gui, url, parent, detail_item) - d.setWindowTitle(self.name) - d.set_tags(self.config.get('tags', '')) - d.exec_() - - def search(self, query, max_results=10, timeout=60): - url = u'http://uk.nook.com/s/%s?s%%5Bdref%%5D=1&s%%5Bkeyword%%5D=%s' % (query.replace(' ', '-'), urllib.quote(query)) - - br = browser() - - counter = max_results - with closing(br.open(url, timeout=timeout)) as f: - raw = f.read() - doc = html.fromstring(raw) - for data in doc.xpath('//ul[contains(@class, "product_list")]/li'): - if counter <= 0: - break - - id_ = ''.join(data.xpath('.//span[contains(@class, "image")]/a/@href')) - if not id_: - continue - if id_.startswith('/gb'): - id_ = id_[3:] - id_ = 'http://uk.nook.com' + id_.strip() - - cover_url = ''.join(data.xpath('.//span[contains(@class, "image")]//img/@data-src')) - - title = ''.join(data.xpath('.//div[contains(@class, "title")]//text()')).strip() - if not title: - continue - - author = ', '.join(data.xpath('.//div[contains(@class, "contributor")]//a/text()')).strip() - price = ''.join(data.xpath('.//div[contains(@class, "action")]//a//text()')).strip() - price = re.sub(r'[^\d.,£]', '', price) - - counter -= 1 - - s = SearchResult() - s.cover_url = cover_url - s.title = title.strip() - s.author = author.strip() - s.price = price.strip() - s.detail_item = id_ - s.drm = SearchResult.DRM_UNKNOWN - s.formats = 'Nook' - - yield s diff --git a/src/calibre/gui2/store/stores/sony_au_plugin.py b/src/calibre/gui2/store/stores/sony_au_plugin.py deleted file mode 100644 index 860da67c20..0000000000 --- a/src/calibre/gui2/store/stores/sony_au_plugin.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python2 -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai -from __future__ import (unicode_literals, division, absolute_import, - print_function) -store_version = 1 # Needed for dynamic plugin loading - -__license__ = 'GPL v3' -__copyright__ = '2012, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - -import urllib -from contextlib import closing - -from lxml import html, etree - -from PyQt5.Qt import QUrl - -from calibre import browser, url_slash_cleaner -from calibre.gui2 import open_url -from calibre.gui2.store import StorePlugin -from calibre.gui2.store.basic_config import BasicStoreConfig -from calibre.gui2.store.search_result import SearchResult -from calibre.gui2.store.web_store_dialog import WebStoreDialog - - -class SonyStore(BasicStoreConfig, StorePlugin): - - SEARCH_URL = 'https://au.readerstore.sony.com/catalog/search/?query=%s' - STORE_URL = 'https://au.readerstore.sony.com/store/' - - def open(self, parent=None, detail_item=None, external=False): - if detail_item: - if external or self.config.get('open_external', False): - open_url(QUrl(url_slash_cleaner(detail_item))) - else: - d = WebStoreDialog(self.gui, self.STORE_URL, parent, detail_item) - d.setWindowTitle(self.name) - d.set_tags(self.config.get('tags', '')) - d.exec_() - else: - open_url(QUrl(self.STORE_URL)) - - def search(self, query, max_results=10, timeout=60): - url = self.SEARCH_URL % urllib.quote_plus(query) - - br = browser() - - counter = max_results - with closing(br.open(url, timeout=timeout)) as f: - doc = html.fromstring(f.read()) - for item in doc.xpath('//div[@id="searchresult-list"]/descendant::div[contains(@class, "doc-item")]'): - if counter <= 0: - break - - s = SearchResult() - s.price = _('Not Available') - p = ''.join(item.xpath('descendant::p[@class="doc-price"]/descendant::span[@itemprop="price"]/text()')).strip() - if p: - s.price = 'AUD ' + p.split('$')[-1] - - title = item.xpath('descendant::h3[@class="doc-title"]') - if not title: - continue - title = etree.tostring(title[0], method='text', encoding=unicode) - if not title: - continue - st = item.xpath('descendant::p[@class="doc-subtitle"]') - if st: - st = etree.tostring(st[0], method='text', encoding=unicode) - if st and st.strip(): - title = title.strip() + ': ' + st - s.title = title.strip() - aut = item.xpath('descendant::p[@class="doc-author"]') - if not aut: - continue - s.author = etree.tostring(aut[0], method='text', encoding=unicode).strip() - if not s.author: - continue - du = ''.join(item.xpath('descendant::h3[position() = 1 and @class="doc-title"]/descendant::a[position() = 1 and @href]/@href')).strip() - if not du: - continue - detail_url = 'https://au.readerstore.sony.com'+du - s.detail_item = detail_url - - counter -= 1 - - cover_url = ''.join(item.xpath( - 'descendant::p[@class="doc-cover" and position() = 1]/' - 'descendant::img[position() = 1 and @src]/@src')) - if cover_url: - s.cover_url = url_slash_cleaner(cover_url) - - s.drm = SearchResult.DRM_UNKNOWN - s.formats = 'Sony' - - yield s - diff --git a/src/calibre/gui2/store/stores/sony_plugin.py b/src/calibre/gui2/store/stores/sony_plugin.py deleted file mode 100644 index cabad78a52..0000000000 --- a/src/calibre/gui2/store/stores/sony_plugin.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python2 -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai -from __future__ import (unicode_literals, division, absolute_import, - print_function) -store_version = 2 # Needed for dynamic plugin loading - -__license__ = 'GPL v3' -__copyright__ = '2012, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - -import urllib -from contextlib import closing - -from lxml import html, etree - -from PyQt5.Qt import QUrl - -from calibre import browser, url_slash_cleaner -from calibre.gui2 import open_url -from calibre.gui2.store import StorePlugin -from calibre.gui2.store.basic_config import BasicStoreConfig -from calibre.gui2.store.search_result import SearchResult -from calibre.gui2.store.web_store_dialog import WebStoreDialog - - -class SonyStore(BasicStoreConfig, StorePlugin): - - def open(self, parent=None, detail_item=None, external=False): - if detail_item: - if external or self.config.get('open_external', False): - open_url(QUrl(url_slash_cleaner(detail_item))) - else: - d = WebStoreDialog(self.gui, 'http://ebookstore.sony.com', parent, detail_item) - d.setWindowTitle(self.name) - d.set_tags(self.config.get('tags', '')) - d.exec_() - else: - open_url(QUrl('http://ebookstore.sony.com')) - - def search(self, query, max_results=10, timeout=60): - url = 'http://ebookstore.sony.com/search?keyword=%s'%urllib.quote_plus( - query) - - br = browser() - - counter = max_results - with closing(br.open(url, timeout=timeout)) as f: - doc = html.fromstring(f.read()) - for item in doc.xpath('//div[contains(@class, "searchResult")]/' - 'descendant::li[contains(@class, "hreview")]'): - if counter <= 0: - break - - curr = ''.join(item.xpath('descendant::div[@class="pricing"]/p[@class="price money"]/descendant::*[@class="currency"]/@title')).strip() - amt = ''.join(item.xpath('descendant::div[@class="pricing"]/p[@class="price money"]/descendant::*[@class="amount"]/text()')).strip() - s = SearchResult() - s.price = (curr+' '+amt) if (curr and amt) else _('Not Available') - title = item.xpath('descendant::h3[@class="item"]') - if not title: - continue - title = etree.tostring(title[0], method='text', - encoding=unicode) - if not title: - continue - s.title = title.strip() - s.author = ''.join(item.xpath( - 'descendant::li[contains(@class, "author")]/' - 'a[@class="fn"]/text()')).strip() - if not s.author: - continue - detail_url = ''.join(item.xpath('descendant::h3[@class="item"]' - '/descendant::a[@class="fn" and @href]/@href')) - if not detail_url: - continue - if detail_url.startswith('/'): - detail_url = 'http:'+detail_url - s.detail_item = detail_url - - counter -= 1 - - cover_url = ''.join(item.xpath( - 'descendant::li[@class="coverart"]/' - 'descendant::img[@src]/@src')) - if cover_url: - if cover_url.startswith('//'): - cover_url = 'http:' + cover_url - elif cover_url.startswith('/'): - cover_url = 'http://ebookstore.sony.com'+cover_url - s.cover_url = url_slash_cleaner(cover_url) - - s.drm = SearchResult.DRM_UNKNOWN - s.formats = 'Sony' - - yield s -