mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Store: Get DRM status for all stores. Load extra details in a separate thread. delay loading covers where the cover url is gotten via extra details.
This commit is contained in:
parent
08b8ef818c
commit
2390a90e7b
@ -104,7 +104,7 @@ class StorePlugin(object): # {{{
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def get_details(self, search_result, timeout=60):
|
def get_details(self, search_result, timeout=60):
|
||||||
raise NotImplementedError()
|
pass
|
||||||
|
|
||||||
def get_settings(self):
|
def get_settings(self):
|
||||||
'''
|
'''
|
||||||
|
@ -85,6 +85,6 @@ class BaenWebScriptionStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price
|
s.price = price
|
||||||
s.detail_item = id.strip()
|
s.detail_item = id.strip()
|
||||||
s.drm = False
|
s.drm = SearchResult.DRM_UNLOCKED
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
@ -60,14 +60,6 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
|
|||||||
cover_url = ''
|
cover_url = ''
|
||||||
price = ''
|
price = ''
|
||||||
|
|
||||||
with closing(br.open(id.strip(), timeout=timeout/4)) as nf:
|
|
||||||
idata = html.fromstring(nf.read())
|
|
||||||
price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "ePub")]/text()'))
|
|
||||||
price = '$' + price.split('$')[-1]
|
|
||||||
cover_img = idata.xpath('//div[@id="content"]//img[1]/@src')
|
|
||||||
if cover_img:
|
|
||||||
cover_url = 'http://www.bewrite.net/mm5/' + cover_img[0]
|
|
||||||
|
|
||||||
counter -= 1
|
counter -= 1
|
||||||
|
|
||||||
s = SearchResult()
|
s = SearchResult()
|
||||||
@ -76,6 +68,19 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price.strip()
|
s.price = price.strip()
|
||||||
s.detail_item = id.strip()
|
s.detail_item = id.strip()
|
||||||
s.drm = False
|
s.drm = SearchResult.DRM_UNLOCKED
|
||||||
|
|
||||||
yield s
|
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())
|
||||||
|
price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "ePub")]/text()'))
|
||||||
|
price = '$' + price.split('$')[-1]
|
||||||
|
search_result.price = price.strip()
|
||||||
|
cover_img = idata.xpath('//div[@id="content"]//img[1]/@src')
|
||||||
|
if cover_img:
|
||||||
|
cover_url = 'http://www.bewrite.net/mm5/' + cover_img[0]
|
||||||
|
search_result.cover_url = cover_url.strip()
|
||||||
|
@ -78,5 +78,6 @@ class BNStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price
|
s.price = price
|
||||||
s.detail_item = id.strip()
|
s.detail_item = id.strip()
|
||||||
|
s.drm = SearchResult.DRM_UNKNOWN
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
@ -75,13 +75,6 @@ class DieselEbooksStore(BasicStoreConfig, StorePlugin):
|
|||||||
if price_elem:
|
if price_elem:
|
||||||
price = price_elem[0]
|
price = price_elem[0]
|
||||||
|
|
||||||
with closing(br.open('http://www.diesel-ebooks.com/item/' + id.strip(), timeout=timeout/4)) as nf:
|
|
||||||
idata = html.fromstring(nf.read())
|
|
||||||
if idata.xpath('boolean(//table[@class="format-info"]//tr[contains(th, "DRM") and contains(td, "No")])'):
|
|
||||||
drm = False
|
|
||||||
else:
|
|
||||||
drm = True
|
|
||||||
|
|
||||||
counter -= 1
|
counter -= 1
|
||||||
|
|
||||||
s = SearchResult()
|
s = SearchResult()
|
||||||
@ -90,6 +83,16 @@ class DieselEbooksStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price.strip()
|
s.price = price.strip()
|
||||||
s.detail_item = '/item/' + id.strip()
|
s.detail_item = '/item/' + id.strip()
|
||||||
s.drm = drm
|
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
|
||||||
|
def get_details(self, search_result, timeout):
|
||||||
|
url = 'http://www.diesel-ebooks.com/item/'
|
||||||
|
|
||||||
|
br = browser()
|
||||||
|
with closing(br.open(url + search_result.detail_item, timeout=timeout)) as nf:
|
||||||
|
idata = html.fromstring(nf.read())
|
||||||
|
if idata.xpath('boolean(//table[@class="format-info"]//tr[contains(th, "DRM") and contains(td, "No")])'):
|
||||||
|
search_result.drm = SearchResult.DRM_UNLOCKED
|
||||||
|
else:
|
||||||
|
search_result.drm = SearchResult.DRM_LOCKED
|
||||||
|
@ -7,6 +7,7 @@ __copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
import urllib2
|
import urllib2
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
@ -64,20 +65,6 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
|
|||||||
if not id:
|
if not id:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
price = ''
|
|
||||||
with closing(br.open('http://www.ebooks.com/ebooks/book_display.asp?IID=' + id.strip(), timeout=timeout)) as fp:
|
|
||||||
pdoc = html.fromstring(fp.read())
|
|
||||||
pdata = pdoc.xpath('//table[@class="price"]/tr/td/text()')
|
|
||||||
if len(pdata) >= 2:
|
|
||||||
price = pdata[1]
|
|
||||||
drm = False
|
|
||||||
for sec in ('Printing', 'Copying', 'Lending'):
|
|
||||||
if pdoc.xpath('boolean(//div[@class="formatTableInner"]//table//tr[contains(th, "%s") and contains(td, "Off")])' % sec):
|
|
||||||
drm = True
|
|
||||||
break
|
|
||||||
if not price:
|
|
||||||
continue
|
|
||||||
|
|
||||||
cover_url = ''.join(data.xpath('.//img[1]/@src'))
|
cover_url = ''.join(data.xpath('.//img[1]/@src'))
|
||||||
|
|
||||||
title = ''
|
title = ''
|
||||||
@ -94,8 +81,29 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.cover_url = cover_url
|
s.cover_url = cover_url
|
||||||
s.title = title.strip()
|
s.title = title.strip()
|
||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price.strip()
|
|
||||||
s.detail_item = '?url=http://www.ebooks.com/cj.asp?IID=' + id.strip() + '&cjsku=' + id.strip()
|
s.detail_item = '?url=http://www.ebooks.com/cj.asp?IID=' + id.strip() + '&cjsku=' + id.strip()
|
||||||
s.drm = drm
|
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
|
||||||
|
def get_details(self, search_result, timeout):
|
||||||
|
url = 'http://www.ebooks.com/ebooks/book_display.asp?IID='
|
||||||
|
|
||||||
|
mo = re.search(r'\?IID=(?P<id>\d+)', search_result.detail_item)
|
||||||
|
if mo:
|
||||||
|
id = mo.group('id')
|
||||||
|
if not id:
|
||||||
|
return
|
||||||
|
|
||||||
|
price = _('Not Available')
|
||||||
|
br = browser()
|
||||||
|
with closing(br.open(url + id, timeout=timeout)) as nf:
|
||||||
|
pdoc = html.fromstring(nf.read())
|
||||||
|
pdata = pdoc.xpath('//table[@class="price"]/tr/td/text()')
|
||||||
|
if len(pdata) >= 2:
|
||||||
|
price = pdata[1]
|
||||||
|
search_result.drm = SearchResult.DRM_UNLOCKED
|
||||||
|
for sec in ('Printing', 'Copying', 'Lending'):
|
||||||
|
if pdoc.xpath('boolean(//div[@class="formatTableInner"]//table//tr[contains(th, "%s") and contains(td, "Off")])' % sec):
|
||||||
|
search_result.drm = SearchResult.DRM_LOCKED
|
||||||
|
break
|
||||||
|
search_result.price = price.strip()
|
||||||
|
@ -7,6 +7,7 @@ __copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
import urllib2
|
import urllib2
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
@ -68,12 +69,6 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
|
|||||||
price = ''.join(data.xpath('.//div[@class="ourprice"]/font/text()'))
|
price = ''.join(data.xpath('.//div[@class="ourprice"]/font/text()'))
|
||||||
cover_url = ''.join(data.xpath('.//a[@href="%s"]/img/@src' % id))
|
cover_url = ''.join(data.xpath('.//a[@href="%s"]/img/@src' % id))
|
||||||
|
|
||||||
with closing(br.open('http://ebooks.eharlequin.com/' + id.strip(), timeout=timeout/4)) as nf:
|
|
||||||
idata = html.fromstring(nf.read())
|
|
||||||
drm = None
|
|
||||||
if idata.xpath('boolean(//div[@class="drm_head"])'):
|
|
||||||
drm = idata.xpath('boolean(//td[contains(., "Copy") and contains(., "not")])')
|
|
||||||
|
|
||||||
counter -= 1
|
counter -= 1
|
||||||
|
|
||||||
s = SearchResult()
|
s = SearchResult()
|
||||||
@ -82,6 +77,26 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price.strip()
|
s.price = price.strip()
|
||||||
s.detail_item = '?url=http://ebooks.eharlequin.com/' + id.strip()
|
s.detail_item = '?url=http://ebooks.eharlequin.com/' + id.strip()
|
||||||
s.drm = drm
|
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
|
||||||
|
def get_details(self, search_result, timeout):
|
||||||
|
url = 'http://ebooks.eharlequin.com/en/ContentDetails.htm?ID='
|
||||||
|
|
||||||
|
mo = re.search(r'\?ID=(?P<id>.+)', search_result.detail_item)
|
||||||
|
if mo:
|
||||||
|
id = mo.group('id')
|
||||||
|
if not id:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
br = browser()
|
||||||
|
with closing(br.open(url + id, timeout=timeout)) as nf:
|
||||||
|
idata = html.fromstring(nf.read())
|
||||||
|
drm = SearchResult.DRM_UNKNOWN
|
||||||
|
if idata.xpath('boolean(//div[@class="drm_head"])'):
|
||||||
|
if idata.xpath('boolean(//td[contains(., "Copy") and contains(., "not")])'):
|
||||||
|
drm = SearchResult.DRM_LOCKED
|
||||||
|
else:
|
||||||
|
drm = SearchResult.DRM_UNLOCKED
|
||||||
|
search_result.drm = drm
|
||||||
|
@ -90,3 +90,14 @@ class FeedbooksStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.detail_item = id.strip()
|
s.detail_item = id.strip()
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
|
||||||
|
def get_details(self, search_result, timeout):
|
||||||
|
url = 'http://m.feedbooks.com/'
|
||||||
|
|
||||||
|
br = browser()
|
||||||
|
with closing(br.open(url_slash_cleaner(url + search_result.detail_item), timeout=timeout)) as nf:
|
||||||
|
idata = html.fromstring(nf.read())
|
||||||
|
if idata.xpath('boolean(//div[contains(@class, "m-description-long")]//p[contains(., "DRM") or contains(b, "Protection")])'):
|
||||||
|
search_result.drm = SearchResult.DRM_LOCKED
|
||||||
|
else:
|
||||||
|
search_result.drm = SearchResult.DRM_UNLOCKED
|
||||||
|
@ -79,6 +79,6 @@ class GutenbergStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price.strip()
|
s.price = price.strip()
|
||||||
s.detail_item = '/ebooks/' + id.strip()
|
s.detail_item = '/ebooks/' + id.strip()
|
||||||
s.drm = False
|
s.drm = SearchResult.DRM_UNLOCKED
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
@ -63,7 +63,7 @@ class KoboStore(BasicStoreConfig, StorePlugin):
|
|||||||
if not id:
|
if not id:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
price = ''.join(data.xpath('.//span[@class="SCOurPrice"]/strong/text()'))
|
price = ''.join(data.xpath('.//li[@class="OurPrice"]/strong/text()'))
|
||||||
if not price:
|
if not price:
|
||||||
price = '$0.00'
|
price = '$0.00'
|
||||||
|
|
||||||
@ -71,6 +71,7 @@ class KoboStore(BasicStoreConfig, StorePlugin):
|
|||||||
|
|
||||||
title = ''.join(data.xpath('.//div[@class="SCItemHeader"]/h1/a[1]/text()'))
|
title = ''.join(data.xpath('.//div[@class="SCItemHeader"]/h1/a[1]/text()'))
|
||||||
author = ''.join(data.xpath('.//div[@class="SCItemSummary"]/span/a[1]/text()'))
|
author = ''.join(data.xpath('.//div[@class="SCItemSummary"]/span/a[1]/text()'))
|
||||||
|
drm = data.xpath('boolean(.//span[@class="SCAvailibilityFormatsText" and contains(text(), "DRM")])')
|
||||||
|
|
||||||
counter -= 1
|
counter -= 1
|
||||||
|
|
||||||
@ -80,5 +81,6 @@ class KoboStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price.strip()
|
s.price = price.strip()
|
||||||
s.detail_item = '?url=http://www.kobobooks.com/' + id.strip()
|
s.detail_item = '?url=http://www.kobobooks.com/' + id.strip()
|
||||||
|
s.drm = SearchResult.DRM_LOCKED if drm else SearchResult.DRM_UNLOCKED
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
@ -89,6 +89,6 @@ class ManyBooksStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price.strip()
|
s.price = price.strip()
|
||||||
s.detail_item = '/titles/' + id
|
s.detail_item = '/titles/' + id
|
||||||
s.drm = False
|
s.drm = SearchResult.DRM_UNLOCKED
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
@ -76,7 +76,7 @@ class MobileReadStore(BasicStoreConfig, StorePlugin):
|
|||||||
matches = heapq.nlargest(max_results, matches)
|
matches = heapq.nlargest(max_results, matches)
|
||||||
for score, book in matches:
|
for score, book in matches:
|
||||||
book.price = '$0.00'
|
book.price = '$0.00'
|
||||||
book.drm = False
|
book.drm = SearchResult.DRM_UNLOCKED
|
||||||
yield book
|
yield book
|
||||||
|
|
||||||
def update_book_list(self, timeout=10):
|
def update_book_list(self, timeout=10):
|
||||||
|
@ -68,5 +68,6 @@ class OpenLibraryStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
s.price = price
|
s.price = price
|
||||||
s.detail_item = id.strip()
|
s.detail_item = id.strip()
|
||||||
|
s.drm = SearchResult.DRM_UNKNOWN
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
@ -415,9 +415,10 @@ class DetailsThread(Thread):
|
|||||||
result, store_plugin, callback, timeout = self.tasks.get()
|
result, store_plugin, callback, timeout = self.tasks.get()
|
||||||
if result:
|
if result:
|
||||||
store_plugin.get_details(result, timeout)
|
store_plugin.get_details(result, timeout)
|
||||||
callback()
|
callback(result)
|
||||||
self.tasks.task_done()
|
self.tasks.task_done()
|
||||||
except:
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
class Matches(QAbstractItemModel):
|
class Matches(QAbstractItemModel):
|
||||||
@ -464,8 +465,12 @@ class Matches(QAbstractItemModel):
|
|||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
self.all_matches.append(result)
|
self.all_matches.append(result)
|
||||||
self.search_filter.add_search_result(result)
|
self.search_filter.add_search_result(result)
|
||||||
|
if result.cover_url:
|
||||||
|
result.cover_queued = True
|
||||||
self.cover_pool.add_task(result, self.filter_results)
|
self.cover_pool.add_task(result, self.filter_results)
|
||||||
self.details_pool.add_task(result, store_plugin, self.filter_results)
|
else:
|
||||||
|
result.cover_queued = False
|
||||||
|
self.details_pool.add_task(result, store_plugin, self.got_result_details)
|
||||||
self.filter_results()
|
self.filter_results()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
@ -485,6 +490,15 @@ class Matches(QAbstractItemModel):
|
|||||||
self.reorder_matches()
|
self.reorder_matches()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def got_result_details(self, result):
|
||||||
|
if not result.cover_queued and result.cover_url:
|
||||||
|
result.cover_queued = True
|
||||||
|
self.cover_pool.add_task(result, self.filter_results)
|
||||||
|
if result in self.matches:
|
||||||
|
row = self.matches.index(result)
|
||||||
|
self.dataChanged.emit(self.index(row, 0), self.index(row, self.columnCount() - 1))
|
||||||
|
self.filter_results()
|
||||||
|
|
||||||
def set_query(self, query):
|
def set_query(self, query):
|
||||||
self.query = query
|
self.query = query
|
||||||
|
|
||||||
|
@ -90,5 +90,6 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
|
|||||||
s.author = author.strip()
|
s.author = author.strip()
|
||||||
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
|
||||||
|
|
||||||
yield s
|
yield s
|
||||||
|
Loading…
x
Reference in New Issue
Block a user