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:
John Schember 2011-04-20 21:09:01 -04:00
parent 08b8ef818c
commit 2390a90e7b
15 changed files with 110 additions and 49 deletions

View File

@ -104,7 +104,7 @@ class StorePlugin(object): # {{{
raise NotImplementedError()
def get_details(self, search_result, timeout=60):
raise NotImplementedError()
pass
def get_settings(self):
'''

View File

@ -85,6 +85,6 @@ class BaenWebScriptionStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price
s.detail_item = id.strip()
s.drm = False
s.drm = SearchResult.DRM_UNLOCKED
yield s

View File

@ -60,14 +60,6 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
cover_url = ''
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
s = SearchResult()
@ -76,6 +68,19 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = id.strip()
s.drm = False
s.drm = SearchResult.DRM_UNLOCKED
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()

View File

@ -78,5 +78,6 @@ class BNStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price
s.detail_item = id.strip()
s.drm = SearchResult.DRM_UNKNOWN
yield s

View File

@ -74,13 +74,6 @@ class DieselEbooksStore(BasicStoreConfig, StorePlugin):
price_elem = data.xpath('//td[@class="price"]/text()')
if price_elem:
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
@ -90,6 +83,16 @@ class DieselEbooksStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = '/item/' + id.strip()
s.drm = drm
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

View File

@ -7,6 +7,7 @@ __copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import random
import re
import urllib2
from contextlib import closing
@ -63,20 +64,6 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
id = id.split('=')[-1]
if not id:
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'))
@ -94,8 +81,29 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
s.cover_url = cover_url
s.title = title.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.drm = drm
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()

View File

@ -7,6 +7,7 @@ __copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import random
import re
import urllib2
from contextlib import closing
@ -68,12 +69,6 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
price = ''.join(data.xpath('.//div[@class="ourprice"]/font/text()'))
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
s = SearchResult()
@ -82,6 +77,26 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = '?url=http://ebooks.eharlequin.com/' + id.strip()
s.drm = drm
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

View File

@ -90,3 +90,14 @@ class FeedbooksStore(BasicStoreConfig, StorePlugin):
s.detail_item = id.strip()
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

View File

@ -79,6 +79,6 @@ class GutenbergStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = '/ebooks/' + id.strip()
s.drm = False
s.drm = SearchResult.DRM_UNLOCKED
yield s

View File

@ -63,7 +63,7 @@ class KoboStore(BasicStoreConfig, StorePlugin):
if not id:
continue
price = ''.join(data.xpath('.//span[@class="SCOurPrice"]/strong/text()'))
price = ''.join(data.xpath('.//li[@class="OurPrice"]/strong/text()'))
if not price:
price = '$0.00'
@ -71,6 +71,7 @@ class KoboStore(BasicStoreConfig, StorePlugin):
title = ''.join(data.xpath('.//div[@class="SCItemHeader"]/h1/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
@ -80,5 +81,6 @@ class KoboStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = '?url=http://www.kobobooks.com/' + id.strip()
s.drm = SearchResult.DRM_LOCKED if drm else SearchResult.DRM_UNLOCKED
yield s

View File

@ -89,6 +89,6 @@ class ManyBooksStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = '/titles/' + id
s.drm = False
s.drm = SearchResult.DRM_UNLOCKED
yield s

View File

@ -76,7 +76,7 @@ class MobileReadStore(BasicStoreConfig, StorePlugin):
matches = heapq.nlargest(max_results, matches)
for score, book in matches:
book.price = '$0.00'
book.drm = False
book.drm = SearchResult.DRM_UNLOCKED
yield book
def update_book_list(self, timeout=10):

View File

@ -68,5 +68,6 @@ class OpenLibraryStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price
s.detail_item = id.strip()
s.drm = SearchResult.DRM_UNKNOWN
yield s

View File

@ -415,9 +415,10 @@ class DetailsThread(Thread):
result, store_plugin, callback, timeout = self.tasks.get()
if result:
store_plugin.get_details(result, timeout)
callback()
callback(result)
self.tasks.task_done()
except:
traceback.print_exc()
continue
class Matches(QAbstractItemModel):
@ -464,8 +465,12 @@ class Matches(QAbstractItemModel):
self.layoutAboutToBeChanged.emit()
self.all_matches.append(result)
self.search_filter.add_search_result(result)
self.cover_pool.add_task(result, self.filter_results)
self.details_pool.add_task(result, store_plugin, self.filter_results)
if result.cover_url:
result.cover_queued = True
self.cover_pool.add_task(result, self.filter_results)
else:
result.cover_queued = False
self.details_pool.add_task(result, store_plugin, self.got_result_details)
self.filter_results()
self.layoutChanged.emit()
@ -485,6 +490,15 @@ class Matches(QAbstractItemModel):
self.reorder_matches()
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):
self.query = query

View File

@ -90,5 +90,6 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = '/books/view/' + id.strip()
s.drm = SearchResult.DRM_UNLOCKED
yield s