def _process_xml(request, doc, device): books_on_device = set() book_nodes = [] was_modified = False x_annotations = qxml.get_child(doc, 'annotations') for x_book in qxml.list_children(x_annotations, 'book'): asin = x_book.getAttribute('key') if is_uuid(asin, x_book.getAttribute('type')): books_on_device.add(asin) x_annotations.removeChild(x_book) book_nodes.append(x_book) was_modified = True for x_collection in qxml.iter_children(x_annotations, 'collection'): for x_book in qxml.iter_children(x_collection, 'book'): asin = x_book.getAttribute('id') if is_uuid(asin, x_book.getAttribute('type')) and 'add' == x_book.getAttribute('action'): books_on_device.add(asin) if books_on_device or book_nodes: postprocess.enqueue(_process_sidecar_upload, device, books_on_device, book_nodes) if was_modified: qxml.remove_whitespace(x_annotations) if not len(x_annotations.childNodes): doc.removeChild(x_annotations) if not len(doc.childNodes): # there's no more content relevant to Amazon, just reply with an empty 200 raise ExceptionResponse() return was_modified
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)