version numbers to support dynamic loading of get books plugins

This commit is contained in:
Kovid Goyal 2013-01-14 11:50:23 +05:30
parent 792d4284b3
commit d2e27f55b8
49 changed files with 155 additions and 106 deletions

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -21,4 +22,4 @@ class AmazonESKindleStore(AmazonUKKindleStore):
'&linkCode=ur2&camp=3626&creative=24790') '&linkCode=ur2&camp=3626&creative=24790')
search_url = 'http://www.amazon.es/s/?url=search-alias%3Ddigital-text&field-keywords=' search_url = 'http://www.amazon.es/s/?url=search-alias%3Ddigital-text&field-keywords='
author_article = 'de ' author_article = 'de '

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -21,4 +22,4 @@ class AmazonITKindleStore(AmazonUKKindleStore):
'linkCode=ur2&camp=3370&creative=23322') 'linkCode=ur2&camp=3370&creative=23322')
search_url = 'http://www.amazon.it/s/?url=search-alias%3Ddigital-text&field-keywords=' search_url = 'http://www.amazon.it/s/?url=search-alias%3Ddigital-text&field-keywords='
author_article = 'di ' author_article = 'di '

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -135,11 +136,11 @@ class AmazonKindleStore(StorePlugin):
title_xpath = './/h3[@class="newaps"]/a//text()' title_xpath = './/h3[@class="newaps"]/a//text()'
author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()' author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()'
price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()' price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()'
for data in doc.xpath(data_xpath): for data in doc.xpath(data_xpath):
if counter <= 0: if counter <= 0:
break break
# Even though we are searching digital-text only Amazon will still # Even though we are searching digital-text only Amazon will still
# put in results for non Kindle books (author pages). Se we need # put in results for non Kindle books (author pages). Se we need
# to explicitly check if the item is a Kindle book and ignore it # to explicitly check if the item is a Kindle book and ignore it
@ -147,7 +148,7 @@ class AmazonKindleStore(StorePlugin):
format = ''.join(data.xpath(format_xpath)) format = ''.join(data.xpath(format_xpath))
if 'kindle' not in format.lower(): if 'kindle' not in format.lower():
continue continue
# We must have an asin otherwise we can't easily reference the # We must have an asin otherwise we can't easily reference the
# book later. # book later.
asin_href = None asin_href = None
@ -161,7 +162,7 @@ class AmazonKindleStore(StorePlugin):
continue continue
else: else:
continue continue
cover_url = ''.join(data.xpath(cover_xpath)) cover_url = ''.join(data.xpath(cover_xpath))
title = ''.join(data.xpath(title_xpath)) title = ''.join(data.xpath(title_xpath))
@ -172,9 +173,9 @@ class AmazonKindleStore(StorePlugin):
pass pass
price = ''.join(data.xpath(price_xpath)) price = ''.join(data.xpath(price_xpath))
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.cover_url = cover_url.strip() s.cover_url = cover_url.strip()
s.title = title.strip() s.title = title.strip()

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -22,7 +23,7 @@ from calibre.gui2.store.search_result import SearchResult
from calibre.gui2.store.web_store_dialog import WebStoreDialog from calibre.gui2.store.web_store_dialog import WebStoreDialog
class BaenWebScriptionStore(BasicStoreConfig, StorePlugin): class BaenWebScriptionStore(BasicStoreConfig, StorePlugin):
def open(self, parent=None, detail_item=None, external=False): def open(self, parent=None, detail_item=None, external=False):
url = 'http://www.baenebooks.com/' url = 'http://www.baenebooks.com/'
@ -41,26 +42,26 @@ class BaenWebScriptionStore(BasicStoreConfig, StorePlugin):
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
url = 'http://www.baenebooks.com/searchadv.aspx?IsSubmit=true&SearchTerm=' + urllib2.quote(query) url = 'http://www.baenebooks.com/searchadv.aspx?IsSubmit=true&SearchTerm=' + urllib2.quote(query)
br = browser() br = browser()
counter = max_results counter = max_results
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read()) doc = html.fromstring(f.read())
for data in doc.xpath('//table//table//table//table//tr'): for data in doc.xpath('//table//table//table//table//tr'):
if counter <= 0: if counter <= 0:
break break
id = ''.join(data.xpath('./td[1]/a/@href')) id = ''.join(data.xpath('./td[1]/a/@href'))
if not id or not id.startswith('p-'): if not id or not id.startswith('p-'):
continue continue
title = ''.join(data.xpath('./td[1]/a/text()')) title = ''.join(data.xpath('./td[1]/a/text()'))
author = '' author = ''
cover_url = '' cover_url = ''
price = '' price = ''
with closing(br.open('http://www.baenebooks.com/' + id.strip(), timeout=timeout/4)) as nf: with closing(br.open('http://www.baenebooks.com/' + id.strip(), timeout=timeout/4)) as nf:
idata = html.fromstring(nf.read()) idata = html.fromstring(nf.read())
author = ''.join(idata.xpath('//span[@class="ProductNameText"]/../b/text()')) author = ''.join(idata.xpath('//span[@class="ProductNameText"]/../b/text()'))
@ -68,16 +69,16 @@ class BaenWebScriptionStore(BasicStoreConfig, StorePlugin):
price = ''.join(idata.xpath('//span[@class="variantprice"]/text()')) price = ''.join(idata.xpath('//span[@class="variantprice"]/text()'))
a, b, price = price.partition('$') a, b, price = price.partition('$')
price = b + price price = b + price
pnum = '' pnum = ''
mo = re.search(r'p-(?P<num>\d+)-', id.strip()) mo = re.search(r'p-(?P<num>\d+)-', id.strip())
if mo: if mo:
pnum = mo.group('num') pnum = mo.group('num')
if pnum: if pnum:
cover_url = 'http://www.baenebooks.com/' + ''.join(idata.xpath('//img[@id="ProductPic%s"]/@src' % pnum)) cover_url = 'http://www.baenebooks.com/' + ''.join(idata.xpath('//img[@id="ProductPic%s"]/@src' % pnum))
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.cover_url = cover_url s.cover_url = cover_url
s.title = title.strip() s.title = title.strip()
@ -86,5 +87,5 @@ class BaenWebScriptionStore(BasicStoreConfig, StorePlugin):
s.detail_item = id.strip() s.detail_item = id.strip()
s.drm = SearchResult.DRM_UNLOCKED s.drm = SearchResult.DRM_UNLOCKED
s.formats = 'RB, MOBI, EPUB, LIT, LRF, RTF, HTML' s.formats = 'RB, MOBI, EPUB, LIT, LRF, RTF, HTML'
yield s yield s

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -71,7 +72,7 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
with closing(br.open(search_result.detail_item, timeout=timeout)) as nf: with closing(br.open(search_result.detail_item, timeout=timeout)) as nf:
idata = html.fromstring(nf.read()) idata = html.fromstring(nf.read())
price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "ePub")]/text()')) price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "ePub")]/text()'))
if not price: if not price:
price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "MOBI")]/text()')) price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "MOBI")]/text()'))
@ -79,7 +80,7 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "PDF")]/text()')) price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "PDF")]/text()'))
price = '$' + price.split('$')[-1] price = '$' + price.split('$')[-1]
search_result.price = price.strip() search_result.price = price.strip()
cover_img = idata.xpath('//div[@id="content"]//img/@src') cover_img = idata.xpath('//div[@id="content"]//img/@src')
if cover_img: if cover_img:
for i in cover_img: for i in cover_img:
@ -87,7 +88,7 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
cover_url = 'http://www.bewrite.net/mm5/' + i cover_url = 'http://www.bewrite.net/mm5/' + i
search_result.cover_url = cover_url.strip() search_result.cover_url = cover_url.strip()
break break
formats = set([]) formats = set([])
if idata.xpath('boolean(//div[@id="content"]//td[contains(text(), "ePub")])'): if idata.xpath('boolean(//div[@id="content"]//td[contains(text(), "ePub")])'):
formats.add('EPUB') formats.add('EPUB')

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2012, Alex Stanev <alex@stanev.org>' __copyright__ = '2012, Alex Stanev <alex@stanev.org>'
@ -26,7 +27,7 @@ class BiblioStore(BasicStoreConfig, OpenSearchOPDSStore):
for s in OpenSearchOPDSStore.search(self, query, max_results, timeout): for s in OpenSearchOPDSStore.search(self, query, max_results, timeout):
yield s yield s
def get_details(self, search_result, timeout): def get_details(self, search_result, timeout):
# get format and DRM status # get format and DRM status
from calibre import browser from calibre import browser
@ -39,13 +40,13 @@ class BiblioStore(BasicStoreConfig, OpenSearchOPDSStore):
search_result.formats = '' search_result.formats = ''
if idata.xpath('.//span[@class="format epub"]'): if idata.xpath('.//span[@class="format epub"]'):
search_result.formats = 'EPUB' search_result.formats = 'EPUB'
if idata.xpath('.//span[@class="format pdf"]'): if idata.xpath('.//span[@class="format pdf"]'):
if search_result.formats == '': if search_result.formats == '':
search_result.formats = 'PDF' search_result.formats = 'PDF'
else: else:
search_result.formats.join(', PDF') search_result.formats.join(', PDF')
if idata.xpath('.//span[@class="format nodrm-icon"]'): if idata.xpath('.//span[@class="format nodrm-icon"]'):
search_result.drm = SearchResult.DRM_UNLOCKED search_result.drm = SearchResult.DRM_UNLOCKED
else: else:

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Alex Stanev <alex@stanev.org>' __copyright__ = '2011, Alex Stanev <alex@stanev.org>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2012, Florent FAYOLLE <florent.fayolle69@gmail.com>' __copyright__ = '2012, Florent FAYOLLE <florent.fayolle69@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -36,9 +37,9 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
url = 'http://ebooks.eharlequin.com/BANGSearch.dll?Type=FullText&FullTextField=All&FullTextCriteria=' + urllib2.quote(query) url = 'http://ebooks.eharlequin.com/BANGSearch.dll?Type=FullText&FullTextField=All&FullTextCriteria=' + urllib2.quote(query)
br = browser() br = browser()
counter = max_results counter = max_results
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read()) doc = html.fromstring(f.read())
@ -64,19 +65,19 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
s.price = price.strip() s.price = price.strip()
s.detail_item = 'http://ebooks.eharlequin.com/' + id.strip() s.detail_item = 'http://ebooks.eharlequin.com/' + id.strip()
s.formats = 'EPUB' s.formats = 'EPUB'
yield s yield s
def get_details(self, search_result, timeout): def get_details(self, search_result, timeout):
url = 'http://ebooks.eharlequin.com/en/ContentDetails.htm?ID=' url = 'http://ebooks.eharlequin.com/en/ContentDetails.htm?ID='
mo = re.search(r'\?ID=(?P<id>.+)', search_result.detail_item) mo = re.search(r'\?ID=(?P<id>.+)', search_result.detail_item)
if mo: if mo:
id = mo.group('id') id = mo.group('id')
if not id: if not id:
return return
br = browser() br = browser()
with closing(br.open(url + id, timeout=timeout)) as nf: with closing(br.open(url + id, timeout=timeout)) as nf:
idata = html.fromstring(nf.read()) idata = html.fromstring(nf.read())

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Alex Stanev <alex@stanev.org>' __copyright__ = '2011, Alex Stanev <alex@stanev.org>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>'
@ -68,7 +69,7 @@ class EmpikStore(BasicStoreConfig, StorePlugin):
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.cover_url = cover_url s.cover_url = cover_url
s.title = title.strip() + ' ' + formats s.title = title.strip() + ' ' + formats
s.author = author.strip() s.author = author.strip()
s.price = price s.price = price

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -11,10 +12,10 @@ from calibre.gui2.store.opensearch_store import OpenSearchOPDSStore
from calibre.gui2.store.search_result import SearchResult from calibre.gui2.store.search_result import SearchResult
class FeedbooksStore(BasicStoreConfig, OpenSearchOPDSStore): class FeedbooksStore(BasicStoreConfig, OpenSearchOPDSStore):
open_search_url = 'http://assets0.feedbooks.net/opensearch.xml?t=1253087147' open_search_url = 'http://assets0.feedbooks.net/opensearch.xml?t=1253087147'
web_url = 'http://feedbooks.com/' web_url = 'http://feedbooks.com/'
# http://www.feedbooks.com/catalog # http://www.feedbooks.com/catalog
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -38,7 +39,7 @@ class GoogleBooksStore(BasicStoreConfig, StorePlugin):
'ganpub': 'k352583', 'ganpub': 'k352583',
'ganclk': 'GOOG_1335335464', 'ganclk': 'GOOG_1335335464',
} }
url = 'http://gan.doubleclick.net/gan_click?lid=%(lid)s&pubid=%(pubid)s' % aff_id url = 'http://gan.doubleclick.net/gan_click?lid=%(lid)s&pubid=%(pubid)s' % aff_id
if detail_item: if detail_item:
detail_item += '&ganpub=%(ganpub)s&ganclk=%(ganclk)s' % aff_id detail_item += '&ganpub=%(ganpub)s&ganclk=%(ganclk)s' % aff_id
@ -53,9 +54,9 @@ class GoogleBooksStore(BasicStoreConfig, StorePlugin):
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
url = 'http://www.google.com/search?tbm=bks&q=' + urllib.quote_plus(query) url = 'http://www.google.com/search?tbm=bks&q=' + urllib.quote_plus(query)
br = browser() br = browser()
counter = max_results counter = max_results
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read()) doc = html.fromstring(f.read())
@ -76,22 +77,22 @@ class GoogleBooksStore(BasicStoreConfig, StorePlugin):
author = ', '.join(authors) author = ', '.join(authors)
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.title = title.strip() s.title = title.strip()
s.author = author.strip() s.author = author.strip()
s.detail_item = id.strip() s.detail_item = id.strip()
s.drm = SearchResult.DRM_UNKNOWN s.drm = SearchResult.DRM_UNKNOWN
yield s yield s
def get_details(self, search_result, timeout): def get_details(self, search_result, timeout):
br = browser() br = browser()
with closing(br.open(search_result.detail_item, timeout=timeout)) as nf: with closing(br.open(search_result.detail_item, timeout=timeout)) as nf:
doc = html.fromstring(nf.read()) doc = html.fromstring(nf.read())
search_result.cover_url = ''.join(doc.xpath('//div[@class="sidebarcover"]//img/@src')) search_result.cover_url = ''.join(doc.xpath('//div[@class="sidebarcover"]//img/@src'))
# Try to get the set price. # Try to get the set price.
price = ''.join(doc.xpath('//div[@id="gb-get-book-container"]//a/text()')) price = ''.join(doc.xpath('//div[@id="gb-get-book-container"]//a/text()'))
if 'read' in price.lower(): if 'read' in price.lower():
@ -101,10 +102,10 @@ class GoogleBooksStore(BasicStoreConfig, StorePlugin):
elif '-' in price: elif '-' in price:
a, b, price = price.partition(' - ') a, b, price = price.partition(' - ')
search_result.price = price.strip() search_result.price = price.strip()
search_result.formats = ', '.join(doc.xpath('//div[contains(@class, "download-panel-div")]//a/text()')).upper() search_result.formats = ', '.join(doc.xpath('//div[contains(@class, "download-panel-div")]//a/text()')).upper()
if not search_result.formats: if not search_result.formats:
search_result.formats = _('Unknown') search_result.formats = _('Unknown')
return True return True

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>'
@ -24,7 +25,7 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
class LegimiStore(BasicStoreConfig, StorePlugin): class LegimiStore(BasicStoreConfig, StorePlugin):
def open(self, parent=None, detail_item=None, external=False): def open(self, parent=None, detail_item=None, external=False):
plain_url = 'http://www.legimi.com/pl/ebooki/' plain_url = 'http://www.legimi.com/pl/ebooki/'
url = 'https://ssl.afiliant.com/affskrypt,,2f9de2,,11483,,,?u=(' + plain_url + ')' url = 'https://ssl.afiliant.com/affskrypt,,2f9de2,,11483,,,?u=(' + plain_url + ')'
detail_url = None detail_url = None
@ -42,17 +43,17 @@ class LegimiStore(BasicStoreConfig, StorePlugin):
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
url = 'http://www.legimi.com/pl/ebooki/?szukaj=' + urllib.quote_plus(query) url = 'http://www.legimi.com/pl/ebooki/?szukaj=' + urllib.quote_plus(query)
br = browser() br = browser()
drm_pattern = re.compile("zabezpieczona DRM") drm_pattern = re.compile("zabezpieczona DRM")
counter = max_results counter = max_results
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read()) doc = html.fromstring(f.read())
for data in doc.xpath('//div[@id="listBooks"]/div'): for data in doc.xpath('//div[@id="listBooks"]/div'):
if counter <= 0: if counter <= 0:
break break
id = ''.join(data.xpath('.//a[@class="plainLink"]/@href')) id = ''.join(data.xpath('.//a[@class="plainLink"]/@href'))
if not id: if not id:
continue continue
@ -73,7 +74,7 @@ class LegimiStore(BasicStoreConfig, StorePlugin):
drm = drm_pattern.search(''.join(idata.xpath('.//div[@id="fullBookFormats"]/p/text()'))) drm = drm_pattern.search(''.join(idata.xpath('.//div[@id="fullBookFormats"]/p/text()')))
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.cover_url = 'http://www.legimi.com/' + cover_url s.cover_url = 'http://www.legimi.com/' + cover_url
s.title = title.strip() s.title = title.strip()
@ -82,5 +83,5 @@ class LegimiStore(BasicStoreConfig, StorePlugin):
s.detail_item = 'http://www.legimi.com/' + id.strip() s.detail_item = 'http://www.legimi.com/' + id.strip()
s.formats = ', '.join(formats) s.formats = ', '.join(formats)
s.drm = SearchResult.DRM_LOCKED if drm else SearchResult.DRM_UNLOCKED s.drm = SearchResult.DRM_LOCKED if drm else SearchResult.DRM_UNLOCKED
yield s yield s

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Roman Mukhin <ramses_ru at hotmail.com>' __copyright__ = '2011, Roman Mukhin <ramses_ru at hotmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -26,7 +27,7 @@ class ManyBooksStore(BasicStoreConfig, OpenSearchOPDSStore):
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
''' '''
Manybooks uses a very strange opds feed. The opds Manybooks uses a very strange opds feed. The opds
main feed is structured like a stanza feed. The main feed is structured like a stanza feed. The
search result entries give very little information search result entries give very little information
and requires you to go to a detail link. The detail and requires you to go to a detail link. The detail
link has the wrong type specified (text/html instead link has the wrong type specified (text/html instead
@ -45,7 +46,7 @@ class ManyBooksStore(BasicStoreConfig, OpenSearchOPDSStore):
oquery.searchTerms = query oquery.searchTerms = query
oquery.count = max_results oquery.count = max_results
url = oquery.url() url = oquery.url()
counter = max_results counter = max_results
br = browser() br = browser()
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
@ -55,11 +56,11 @@ class ManyBooksStore(BasicStoreConfig, OpenSearchOPDSStore):
for data in doc.xpath('//*[local-name() = "entry"]'): for data in doc.xpath('//*[local-name() = "entry"]'):
if counter <= 0: if counter <= 0:
break break
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
detail_links = data.xpath('./*[local-name() = "link" and @type = "text/html"]') detail_links = data.xpath('./*[local-name() = "link" and @type = "text/html"]')
if not detail_links: if not detail_links:
continue continue
@ -73,7 +74,7 @@ class ManyBooksStore(BasicStoreConfig, OpenSearchOPDSStore):
# just in case. # just in case.
s.title = ''.join(data.xpath('./*[local-name() = "title"]//text()')).strip() s.title = ''.join(data.xpath('./*[local-name() = "title"]//text()')).strip()
s.author = ', '.join(data.xpath('./*[local-name() = "author"]//text()')).strip() s.author = ', '.join(data.xpath('./*[local-name() = "author"]//text()')).strip()
# Follow the detail link to get the rest of the info. # Follow the detail link to get the rest of the info.
with closing(br.open(detail_href, timeout=timeout/4)) as df: with closing(br.open(detail_href, timeout=timeout/4)) as df:
ddoc = etree.fromstring(df.read()) ddoc = etree.fromstring(df.read())
@ -89,9 +90,9 @@ class ManyBooksStore(BasicStoreConfig, OpenSearchOPDSStore):
s.author = s.author[1:] s.author = s.author[1:]
if s.author.endswith(','): if s.author.endswith(','):
s.author = s.author[:-1] s.author = s.author[:-1]
s.cover_url = ''.join(ddata.xpath('./*[local-name() = "link" and @rel = "http://opds-spec.org/thumbnail"][1]/@href')).strip() s.cover_url = ''.join(ddata.xpath('./*[local-name() = "link" and @rel = "http://opds-spec.org/thumbnail"][1]/@href')).strip()
for link in ddata.xpath('./*[local-name() = "link" and @rel = "http://opds-spec.org/acquisition"]'): for link in ddata.xpath('./*[local-name() = "link" and @rel = "http://opds-spec.org/acquisition"]'):
type = link.get('type') type = link.get('type')
href = link.get('href') href = link.get('href')

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2012, John Schember <john@nachtimwald.com>' __copyright__ = '2012, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Roman Mukhin <ramses_ru at hotmail.com>' __copyright__ = '2011, Roman Mukhin <ramses_ru at hotmail.com>'
@ -24,33 +25,33 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
class OzonRUStore(BasicStoreConfig, StorePlugin): class OzonRUStore(BasicStoreConfig, StorePlugin):
shop_url = 'http://www.ozon.ru' shop_url = 'http://www.ozon.ru'
def open(self, parent=None, detail_item=None, external=False): def open(self, parent=None, detail_item=None, external=False):
aff_id = '?partner=romuk' aff_id = '?partner=romuk'
# Use Kovid's affiliate id 30% of the time. # Use Kovid's affiliate id 30% of the time.
if random.randint(1, 10) in (1, 2, 3): if random.randint(1, 10) in (1, 2, 3):
aff_id = '?partner=kovidgoyal' aff_id = '?partner=kovidgoyal'
url = self.shop_url + aff_id url = self.shop_url + aff_id
detail_url = None detail_url = None
if detail_item: if detail_item:
# http://www.ozon.ru/context/detail/id/3037277/ # http://www.ozon.ru/context/detail/id/3037277/
detail_url = self.shop_url + '/context/detail/id/' + urllib2.quote(detail_item) + aff_id detail_url = self.shop_url + '/context/detail/id/' + urllib2.quote(detail_item) + aff_id
if external or self.config.get('open_external', False): if external or self.config.get('open_external', False):
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url))) open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
else: else:
d = WebStoreDialog(self.gui, url, parent, detail_url) d = WebStoreDialog(self.gui, url, parent, detail_url)
d.setWindowTitle(self.name) d.setWindowTitle(self.name)
d.set_tags(self.config.get('tags', '')) d.set_tags(self.config.get('tags', ''))
d.exec_() d.exec_()
def search(self, query, max_results=15, timeout=60): def search(self, query, max_results=15, timeout=60):
search_url = self.shop_url + '/webservice/webservice.asmx/SearchWebService?'\ search_url = self.shop_url + '/webservice/webservice.asmx/SearchWebService?'\
'searchText=%s&searchContext=ebook' % urllib2.quote(query) 'searchText=%s&searchContext=ebook' % urllib2.quote(query)
search_urls = [ search_url ] search_urls = [ search_url ]
## add this as the fist try if it looks like ozon ID ## add this as the fist try if it looks like ozon ID
if re.match("^\d{6,9}$", query): if re.match("^\d{6,9}$", query):
ozon_detail = self.shop_url + '/webservices/OzonWebSvc.asmx/ItemDetail?ID=%s' % query ozon_detail = self.shop_url + '/webservices/OzonWebSvc.asmx/ItemDetail?ID=%s' % query
@ -59,7 +60,7 @@ class OzonRUStore(BasicStoreConfig, StorePlugin):
xp_template = 'normalize-space(./*[local-name() = "{0}"]/text())' xp_template = 'normalize-space(./*[local-name() = "{0}"]/text())'
counter = max_results counter = max_results
br = browser() br = browser()
for url in search_urls: for url in search_urls:
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
raw = xml_to_unicode(f.read(), strip_encoding_pats=True, assume_utf8=True)[0] raw = xml_to_unicode(f.read(), strip_encoding_pats=True, assume_utf8=True)[0]
@ -86,10 +87,10 @@ class OzonRUStore(BasicStoreConfig, StorePlugin):
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
raw = xml_to_unicode(f.read(), verbose=True)[0] raw = xml_to_unicode(f.read(), verbose=True)[0]
doc = html.fromstring(raw) doc = html.fromstring(raw)
# example where we are going to find formats # example where we are going to find formats
# <div class="l"> # <div class="l">
# <p> # <p>
# Доступно: # Доступно:
# </p> # </p>
# </div> # </div>
@ -104,16 +105,16 @@ class OzonRUStore(BasicStoreConfig, StorePlugin):
search_result.formats = ', '.join(_parse_ebook_formats(formats)) search_result.formats = ', '.join(_parse_ebook_formats(formats))
# unfortunately no direct links to download books (only buy link) # unfortunately no direct links to download books (only buy link)
# search_result.downloads['BF2'] = self.shop_url + '/order/digitalorder.aspx?id=' + + urllib2.quote(search_result.detail_item) # search_result.downloads['BF2'] = self.shop_url + '/order/digitalorder.aspx?id=' + + urllib2.quote(search_result.detail_item)
#<p class="main-cost"><span class="main">215</span><span class="submain">00</span> руб.</p> #<p class="main-cost"><span class="main">215</span><span class="submain">00</span> руб.</p>
#<span itemprop="price" class="hidden">215.00</span> #<span itemprop="price" class="hidden">215.00</span>
#<meta itemprop="priceCurrency" content="RUR " /> #<meta itemprop="priceCurrency" content="RUR " />
# if the price not in the search result (the ID search case) # if the price not in the search result (the ID search case)
if not search_result.price: if not search_result.price:
price = doc.xpath(u'normalize-space(//*[@itemprop="price"]/text())') price = doc.xpath(u'normalize-space(//*[@itemprop="price"]/text())')
search_result.price = format_price_in_RUR(price) search_result.price = format_price_in_RUR(price)
return result return result
def format_price_in_RUR(price): def format_price_in_RUR(price):
@ -134,12 +135,12 @@ def format_price_in_RUR(price):
def _parse_ebook_formats(formatsStr): def _parse_ebook_formats(formatsStr):
''' '''
Creates a list with displayable names of the formats Creates a list with displayable names of the formats
:param formatsStr: string with comma separated book formats :param formatsStr: string with comma separated book formats
as it provided by ozon.ru as it provided by ozon.ru
:return: a list with displayable book formats :return: a list with displayable book formats
''' '''
formatsUnstruct = formatsStr.lower() formatsUnstruct = formatsStr.lower()
formats = [] formats = []
if 'epub' in formatsUnstruct: if 'epub' in formatsUnstruct:

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -14,7 +15,7 @@ class PragmaticBookshelfStore(BasicStoreConfig, OpenSearchOPDSStore):
open_search_url = 'http://pragprog.com/catalog/search-description' open_search_url = 'http://pragprog.com/catalog/search-description'
web_url = 'http://pragprog.com/' web_url = 'http://pragprog.com/'
# http://pragprog.com/catalog.opds # http://pragprog.com/catalog.opds
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2012, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2012, Tomasz Długosz <tomek3d@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>'
@ -73,5 +74,5 @@ class RW2010Store(BasicStoreConfig, StorePlugin):
s.detail_item = re.sub(r'%3D', '=', id) s.detail_item = re.sub(r'%3D', '=', id)
s.drm = SearchResult.DRM_UNLOCKED s.drm = SearchResult.DRM_UNLOCKED
s.formats = formats[0:-2].upper() s.formats = formats[0:-2].upper()
yield s yield s

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -36,7 +37,7 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
if detail_item: if detail_item:
detail_url = url + detail_item + aff_id detail_url = url + detail_item + aff_id
url = url + aff_id url = url + aff_id
if external or self.config.get('open_external', False): if external or self.config.get('open_external', False):
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url))) open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
else: else:
@ -47,9 +48,9 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
url = 'http://www.smashwords.com/books/search?query=' + urllib2.quote(query) url = 'http://www.smashwords.com/books/search?query=' + urllib2.quote(query)
br = browser() br = browser()
counter = max_results counter = max_results
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read()) doc = html.fromstring(f.read())
@ -57,7 +58,7 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
if counter <= 0: if counter <= 0:
break break
data = html.fromstring(html.tostring(data)) data = html.fromstring(html.tostring(data))
id = None id = None
id_a = data.xpath('//a[@class="bookTitle"]') id_a = data.xpath('//a[@class="bookTitle"]')
if id_a: if id_a:
@ -66,14 +67,14 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
id = id.split('/')[-1] id = id.split('/')[-1]
if not id: if not id:
continue continue
cover_url = '' cover_url = ''
c_url = data.get('style', None) c_url = data.get('style', None)
if c_url: if c_url:
mo = re.search(r'http://[^\'"]+', c_url) mo = re.search(r'http://[^\'"]+', c_url)
if mo: if mo:
cover_url = mo.group() cover_url = mo.group()
title = ''.join(data.xpath('//a[@class="bookTitle"]/text()')) title = ''.join(data.xpath('//a[@class="bookTitle"]/text()'))
subnote = ''.join(data.xpath('//span[@class="subnote"]/text()')) subnote = ''.join(data.xpath('//span[@class="subnote"]/text()'))
author = ''.join(data.xpath('//span[@class="subnote"]//a[1]//text()')) author = ''.join(data.xpath('//span[@class="subnote"]//a[1]//text()'))
@ -85,7 +86,7 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
price = '$0.00' price = '$0.00'
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.cover_url = cover_url s.cover_url = cover_url
s.title = title.strip() s.title = title.strip()
@ -93,12 +94,12 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
s.price = price.strip() s.price = price.strip()
s.detail_item = '/books/view/' + id.strip() s.detail_item = '/books/view/' + id.strip()
s.drm = SearchResult.DRM_UNLOCKED s.drm = SearchResult.DRM_UNLOCKED
yield s yield s
def get_details(self, search_result, timeout): def get_details(self, search_result, timeout):
url = 'http://www.smashwords.com/' url = 'http://www.smashwords.com/'
br = browser() br = browser()
with closing(br.open(url + search_result.detail_item, timeout=timeout)) as nf: with closing(br.open(url + search_result.detail_item, timeout=timeout)) as nf:
idata = html.fromstring(nf.read()) idata = html.fromstring(nf.read())

View File

@ -2,6 +2,7 @@
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
from __future__ import (unicode_literals, division, absolute_import, from __future__ import (unicode_literals, division, absolute_import,
print_function) print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -35,9 +36,9 @@ class WeightlessBooksStore(BasicStoreConfig, StorePlugin):
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
url = 'http://weightlessbooks.com/?s=' + urllib.quote_plus(query) url = 'http://weightlessbooks.com/?s=' + urllib.quote_plus(query)
br = browser() br = browser()
counter = max_results counter = max_results
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read()) doc = html.fromstring(f.read())
@ -50,20 +51,20 @@ class WeightlessBooksStore(BasicStoreConfig, StorePlugin):
continue continue
cover_url = ''.join(data.xpath('.//div[@class="cover"]/a/img/@src')) cover_url = ''.join(data.xpath('.//div[@class="cover"]/a/img/@src'))
price = ''.join(data.xpath('.//div[@class="buy_buttons"]/b[1]/text()')) price = ''.join(data.xpath('.//div[@class="buy_buttons"]/b[1]/text()'))
if not price: if not price:
continue continue
formats = ', '.join(data.xpath('.//select[@class="eStore_variation"]//option//text()')) formats = ', '.join(data.xpath('.//select[@class="eStore_variation"]//option//text()'))
formats = formats.upper() formats = formats.upper()
title = ''.join(data.xpath('.//h3/a/text()')) title = ''.join(data.xpath('.//h3/a/text()'))
author = ''.join(data.xpath('.//h3//text()')) author = ''.join(data.xpath('.//h3//text()'))
author = author.replace(title, '') author = author.replace(title, '')
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.cover_url = cover_url s.cover_url = cover_url
s.title = title.strip() s.title = title.strip()
@ -72,5 +73,5 @@ class WeightlessBooksStore(BasicStoreConfig, StorePlugin):
s.detail_item = id.strip() s.detail_item = id.strip()
s.drm = SearchResult.DRM_UNLOCKED s.drm = SearchResult.DRM_UNLOCKED
s.formats = formats s.formats = formats
yield s yield s

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>'

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>' __copyright__ = '2011, John Schember <john@nachtimwald.com>'
@ -20,25 +21,25 @@ class XinXiiStore(BasicStoreConfig, OpenSearchOPDSStore):
open_search_url = 'http://www.xinxii.com/catalog-search/' open_search_url = 'http://www.xinxii.com/catalog-search/'
web_url = 'http://xinxii.com/' web_url = 'http://xinxii.com/'
# http://www.xinxii.com/catalog/ # http://www.xinxii.com/catalog/
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
''' '''
XinXii's open search url is: XinXii's open search url is:
http://www.xinxii.com/catalog-search/query/?keywords={searchTerms}&amp;pw={startPage?}&amp;doc_lang={docLang}&amp;ff={docFormat},{docFormat},{docFormat} http://www.xinxii.com/catalog-search/query/?keywords={searchTerms}&amp;pw={startPage?}&amp;doc_lang={docLang}&amp;ff={docFormat},{docFormat},{docFormat}
This url requires the docLang and docFormat. However, the search itself This url requires the docLang and docFormat. However, the search itself
sent to XinXii does not require them. They can be ignored. We cannot sent to XinXii does not require them. They can be ignored. We cannot
push this into the stanard OpenSearchOPDSStore search because of the push this into the stanard OpenSearchOPDSStore search because of the
required attributes. required attributes.
XinXii doesn't return all info supported by OpenSearchOPDSStore search XinXii doesn't return all info supported by OpenSearchOPDSStore search
function so this one is modified to remove parts that are used. function so this one is modified to remove parts that are used.
''' '''
url = 'http://www.xinxii.com/catalog-search/query/?keywords=' + urllib.quote_plus(query) url = 'http://www.xinxii.com/catalog-search/query/?keywords=' + urllib.quote_plus(query)
counter = max_results counter = max_results
br = browser() br = browser()
with closing(br.open(url, timeout=timeout)) as f: with closing(br.open(url, timeout=timeout)) as f:
@ -46,29 +47,29 @@ class XinXiiStore(BasicStoreConfig, OpenSearchOPDSStore):
for data in doc.xpath('//*[local-name() = "entry"]'): for data in doc.xpath('//*[local-name() = "entry"]'):
if counter <= 0: if counter <= 0:
break break
counter -= 1 counter -= 1
s = SearchResult() s = SearchResult()
s.detail_item = ''.join(data.xpath('./*[local-name() = "id"]/text()')).strip() s.detail_item = ''.join(data.xpath('./*[local-name() = "id"]/text()')).strip()
for link in data.xpath('./*[local-name() = "link"]'): for link in data.xpath('./*[local-name() = "link"]'):
rel = link.get('rel') rel = link.get('rel')
href = link.get('href') href = link.get('href')
type = link.get('type') type = link.get('type')
if rel and href and type: if rel and href and type:
if rel in ('http://opds-spec.org/thumbnail', 'http://opds-spec.org/image/thumbnail'): if rel in ('http://opds-spec.org/thumbnail', 'http://opds-spec.org/image/thumbnail'):
s.cover_url = href s.cover_url = href
if rel == 'alternate': if rel == 'alternate':
s.detail_item = href s.detail_item = href
s.formats = 'EPUB, PDF' s.formats = 'EPUB, PDF'
s.title = ' '.join(data.xpath('./*[local-name() = "title"]//text()')).strip() s.title = ' '.join(data.xpath('./*[local-name() = "title"]//text()')).strip()
s.author = ', '.join(data.xpath('./*[local-name() = "author"]//*[local-name() = "name"]//text()')).strip() s.author = ', '.join(data.xpath('./*[local-name() = "author"]//*[local-name() = "name"]//text()')).strip()
price_e = data.xpath('.//*[local-name() = "price"][1]') price_e = data.xpath('.//*[local-name() = "price"][1]')
if price_e: if price_e:
price_e = price_e[0] price_e = price_e[0]
@ -76,6 +77,6 @@ class XinXiiStore(BasicStoreConfig, OpenSearchOPDSStore):
price = ''.join(price_e.xpath('.//text()')).strip() price = ''.join(price_e.xpath('.//text()')).strip()
s.price = currency_code + ' ' + price s.price = currency_code + ' ' + price
s.price = s.price.strip() s.price = s.price.strip()
yield s yield s

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
store_version = 1 # Needed for dynamic plugin loading
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>' __copyright__ = '2011, Tomasz Długosz <tomek3d@gmail.com>'