示例#1
0
文件: sidecar.py 项目: akleiw/KSP
def _process_sidecar_upload(device, book_ids, book_nodes):
	# book_ids is NOT a complete list of books on device
	for asin in book_ids:
		book = calibre.book(asin)
		if book:
			book.mark_on_device(device)

	for x_book in book_nodes:
		asin = x_book.getAttribute('key')
		book = calibre.book(asin)
		if not book:
			logging.warn("sidecar upload for unknown book %s", asin)
			continue

		for kind in ('last_read', 'bookmark', 'highlight', 'note'):
			for x_item in qxml.iter_children(x_book, kind):
				timestamp = x_item.getAttribute('timestamp') or None
				begin = x_item.getAttribute('begin') or None
				end = x_item.getAttribute('end') or begin
				pos = x_item.getAttribute('pos') or None
				state = x_item.getAttribute('state') or None
				text = qxml.get_text(x_item) if kind == 'note' else None

				if kind == 'last_read':
					annotations.set_last_read(device, asin, timestamp, begin, pos, state)
				else:
					action = x_item.getAttribute('action')
					if action == 'create':
						annotations.create(device, asin, kind, timestamp, begin, end, pos, state, text)
					elif action == 'delete':
						annotations.delete(device, asin, kind, timestamp, begin, end)
					elif action == 'modify':
						annotations.modify(device, asin, kind, timestamp, begin, end, text)
					else:
						logging.error("unknown sidecar action %s: %s", action, x_item)
示例#2
0
def _process_books_on_device(device, book_ids):
	# need to better express this, without exposing device.books
	for asin, last_downloaded in list(device.books.items()):
		if asin not in book_ids and last_downloaded > 0:
			# we know snapshot lists ALL books on the device
			logging.warn("%s no longer has book %s %s", device, asin, calibre.book(asin))
			device.books[asin] = 0

	for asin in book_ids:
		book = calibre.book(asin)
		if book:
			book.mark_on_device(device)
		else:
			logging.debug("%s has book unknown book %s", device, asin)
示例#3
0
def _process_books_on_device(device, book_ids):
    # need to better express this, without exposing device.books
    for asin, last_downloaded in list(device.books.items()):
        if asin not in book_ids and last_downloaded > 0:
            # we know snapshot lists ALL books on the device
            logging.warn("%s no longer has book %s %s", device, asin,
                         calibre.book(asin))
            device.books[asin] = 0

    for asin in book_ids:
        book = calibre.book(asin)
        if book:
            book.mark_on_device(device)
        else:
            logging.debug("%s has book unknown book %s", device, asin)
示例#4
0
文件: sidecar.py 项目: akleiw/KSP
	def call(self, request, device):
		if device.is_provisional():
			return None

		if request.command == 'GET':
			q = request.get_query_params()
			asin = q.get('key')
			if is_uuid(asin, q.get('type')):
				book = calibre.book(asin)
				if not book:
					logging.warn("tried to download sidecar for unknown book %s", asin)
					return None
				sidecar_data = formats.sidecar(book)
				if sidecar_data:
					content_type, data = sidecar_data
					return DummyResponse(headers = { 'Content-Type': content_type }, data = data)
				return None
		elif request.command == 'POST':
			q = request.get_query_params()
			lto = q.get('device_lto', -1)
			if lto != -1:
				try: device.lto = int(lto)
				except: pass

			with minidom.parseString(request.body_text()) as doc:
				if _process_xml(request, doc, device):
					if not request.is_signed():
						# drats
						xml = doc.toxml('UTF-8')
						request.update_body(xml)

		return self.call_upstream(request, device)
示例#5
0
def _collections(asin_mappings):
    collections = {}
    for name, asin_list in asin_mappings.items():
        books_list = [calibre.book(asin) for asin in asin_list]
        books_list = [b for b in books_list if b]
        books_with_files = [b for b in books_list if b.file_path]
        if books_with_files:  # if at least _some_ books in the collection have files
            collections[name] = books_list
    return collections
示例#6
0
def _collections(asin_mappings):
	collections = {}
	for name, asin_list in asin_mappings.items():
		books_list = [ calibre.book(asin) for asin in asin_list ]
		books_list = [ b for b in books_list if b ]
		books_with_files = [ b for b in books_list if b.file_path ]
		if books_with_files: # if at least _some_ books in the collection have files
			collections[name] = books_list
	return collections
示例#7
0
def _process_item(device,
                  action=None,
                  cde_type=None,
                  key=None,
                  complete_status=None,
                  **extra):
    if key.startswith('KSP.') or cde_type.startswith('KSP.'):
        # KSP internal stuff, not relevant upstream
        return True

    if not features.allow_logs_upload and action == 'SND' and cde_type == 'CMND' and key.endswith(
            ':SYSLOG:UPLOAD'):
        return True

    if action in ('GET', 'DOWNLOAD') and cde_type in ('EBOK', 'PDOC',
                                                      'APNX') and is_uuid(
                                                          key, cde_type):
        book = calibre.book(key)
        if complete_status == 'COMPLETED':
            if book:
                book.mark_downloaded_by(device)
            else:
                logging.warn("%s successfully updated unknown book %s", device,
                             key)
        elif complete_status == 'FAILED':
            logging.warn("%s failed to update book %s", device, book or key)
        else:
            logging.warn("%s: unknown downloaded status %s for %s", device,
                         complete_status, book or key)
        return True

    if action == 'UPD_LPRD' and is_uuid(key, cde_type):
        if complete_status == 'COMPLETED':
            annotations.last_read_updated(device, key)
        elif complete_status == 'FAILED':
            logging.warn("%s failed to update last_read for book %s", device,
                         key)
        else:
            logging.warn("%s: unknown UPD_LPRD status %s for book %s", device,
                         complete_status, key)
        return True

    if action == 'UPD_ANOT' and is_uuid(key, cde_type):
        if complete_status == 'COMPLETED':
            annotations.annotations_updated(device, key)
        elif complete_status == 'FAILED':
            logging.warn("%s failed to update last_read for book %s", device,
                         key)
        else:
            logging.warn("%s: unknown UPD_LPRD status %s for book %s", device,
                         complete_status, key)
        return True

    return False
示例#8
0
	def book_response(self, asin, device, range_header):
		"""
		builds a BookResponse object for downloading the book contents
		"""
		book = calibre.book(asin, True)
		if not book:
			logging.warn("device %s tried to download book %s, but it is not in the library (anymore?)", device, asin)
			return None
		if not book.file_path:
			logging.warn("device %s tried to download book %s, but it has no file available", device, asin)
			return None

		bytes_range = _range(range_header, book.file_size)
		return _BookResponse(book, bytes_range)
示例#9
0
	def book_response(self, asin, device, range_header):
		"""
		builds a BookResponse object for downloading the book contents
		"""
		book = calibre.book(asin, True)
		if not book:
			logging.warn("device %s tried to download book %s, but it is not in the library (anymore?)", device, asin)
			return None
		if not book.file_path:
			logging.warn("device %s tried to download book %s, but it has no file available", device, asin)
			return None

		bytes_range = _range(range_header, book.file_size)
		return _BookResponse(book, bytes_range)
示例#10
0
 def call(self, request, device):
     q = request.get_query_params()
     asin = q.get('key')
     if q.get('type') == 'EBOK' and is_uuid(asin, 'EBOK'):
         book = calibre.book(asin)
         apnx_path = annotations.apnx_path(book)
         # logging.debug("looking for apnx of %s, found %s", book, apnx_path)
         if apnx_path:
             # APNX files are usually small (a few Ks at most),
             # so there's no need to do stream copying
             apnx_data = None
             with open(apnx_path, 'rb') as apnx:
                 apnx_data = apnx.read()
             if apnx_data:
                 return DummyResponse(headers=_HEADERS, data=apnx_data)
示例#11
0
	def call(self, request, device):
		q = request.get_query_params()
		asin = q.get('key')

		if is_uuid(asin, q.get('type')):
			kind = q.get('filter')
			book = calibre.book(asin)
			if not book:
				logging.warn("book not found %s", asin)
				return None
			if kind == 'last_read':
				return _last_read(book, device.serial)
			logging.warn("don't know how to filter annotations of kind %s", kind)
			return None

		return self.call_upstream(request, device)
示例#12
0
    def call(self, request, device):
        q = request.get_query_params()
        asin = q.get('key')

        if is_uuid(asin, q.get('type')):
            kind = q.get('filter')
            book = calibre.book(asin)
            if not book:
                logging.warn("book not found %s", asin)
                return None
            if kind == 'last_read':
                return _last_read(book, device.serial)
            logging.warn("don't know how to filter annotations of kind %s",
                         kind)
            return None

        return self.call_upstream(request, device)
示例#13
0
文件: images.py 项目: akleiw/KSP
	def call(self, request, device):
		if request.path.startswith('/images/P/'):
			asin = asin[10:asin.find('.', 11)]
			if is_uuid(asin):
				book = calibre.book(asin)
				# logging.debug("looking for cover of %s %s", asin, book)
				if book and book.file_path:
					image_path = os.path.join(os.path.dirname(book.file_path), "cover.jpg")
					image_data = None
					if os.path.isfile(image_path):
						try:
							with open(image_path, 'rb') as fi:
								image_data = fi.read()
						except:
							logging.exception("failed to read cover for %s", book)
					if image_data:
						return DummyResponse(headers = _HEADERS, data = image_data)
				return 404 # forces Kindle 4 PC to use the cover from the .mobi file, if any

		return DummyResponse(303, headers = { 'Location: http://' + _ECX + request.path })
示例#14
0
def _process_item(device, action = None, cde_type = None, key = None, complete_status = None, **extra):
	if key.startswith('KSP.') or cde_type.startswith('KSP.'):
		# KSP internal stuff, not relevant upstream
		return True

	if not features.allow_logs_upload and action == 'SND' and cde_type == 'CMND' and key.endswith(':SYSLOG:UPLOAD'):
		return True

	if action in ('GET', 'DOWNLOAD') and cde_type in ('EBOK', 'PDOC', 'APNX') and is_uuid(key, cde_type):
		book = calibre.book(key)
		if complete_status == 'COMPLETED':
			if book:
				book.mark_downloaded_by(device)
			else:
				logging.warn("%s successfully updated unknown book %s", device, key)
		elif complete_status == 'FAILED':
			logging.warn("%s failed to update book %s", device, book or key)
		else:
			logging.warn("%s: unknown downloaded status %s for %s", device, complete_status, book or key)
		return True

	if action == 'UPD_LPRD' and is_uuid(key, cde_type):
		if complete_status == 'COMPLETED':
			annotations.last_read_updated(device, key)
		elif complete_status == 'FAILED':
			logging.warn("%s failed to update last_read for book %s", device, key)
		else:
			logging.warn("%s: unknown UPD_LPRD status %s for book %s", device, complete_status, key)
		return True

	if action == 'UPD_ANOT' and is_uuid(key, cde_type):
		if complete_status == 'COMPLETED':
			annotations.annotations_updated(device, key)
		elif complete_status == 'FAILED':
			logging.warn("%s failed to update last_read for book %s", device, key)
		else:
			logging.warn("%s: unknown UPD_LPRD status %s for book %s", device, complete_status, key)
		return True

	return False
示例#15
0
    def call(self, request, device):
        if request.path.startswith('/images/P/'):
            asin = request.path[10:]
            asin = asin[:asin.find('.', 11)]
            if is_uuid(asin):
                book = calibre.book(asin)
                # logging.debug("looking for cover of %s %s", asin, book)
                if book and book.file_path:
                    image_path = os.path.join(os.path.dirname(book.file_path),
                                              "cover.jpg")
                    image_data = None
                    if os.path.isfile(image_path):
                        try:
                            with open(image_path, 'rb') as fi:
                                image_data = fi.read()
                        except:
                            logging.exception("failed to read cover for %s",
                                              book)
                    if image_data:
                        return DummyResponse(headers=_HEADERS, data=image_data)
                return 404  # forces Kindle 4 PC to use the cover from the .mobi file, if any

        return DummyResponse(
            303, headers={'Location: http://' + _ECX + request.path})