def implementation(db, notify_changes, col, book_id, val, append): is_remote = notify_changes is not None field = db.field_metadata.custom_field_prefix + col with db.write_lock: if not db.has_id(book_id): return False, _('No book with id {} exists').format(book_id) try: fm = db.field_metadata[field] except KeyError: return False, _('No column with name {} exists').format(col) if fm['datatype'] == 'series': val, s_index = _get_series_values(val) if s_index is None: s_index = db.get_next_series_num_for(val, field=field) db.set_field(field, {book_id: val}), db.set_field(field + '_index', {book_id: s_index}) msg = _('Data set to: {} [{}]').format(db.field_for(field, book_id), db.field_for(field + '_index', book_id)) else: if append and fm['is_multiple']: val = list(db.field_for(field, book_id)) + [val] db.set_field(field, {book_id: val}) val = db.field_for(field, book_id) if isinstance(val, (tuple, list)): val = fm['is_multiple']['list_to_ui'].join(val) msg = _('Data set to: {}').format(val) if is_remote: notify_changes(metadata((book_id,))) return True, msg
def cdb_set_fields(ctx, rd, book_id, library_id): db = get_db(ctx, rd, library_id) if ctx.restriction_for(rd, db): raise HTTPForbidden('Cannot use the set fields interface with a user who has per library restrictions') data = load_payload_data(rd) try: changes, loaded_book_ids = data['changes'], frozenset(map(int, data.get('loaded_book_ids', ()))) all_dirtied = bool(data.get('all_dirtied')) if not isinstance(changes, dict): raise TypeError('changes must be a dict') except Exception: raise HTTPBadRequest( '''Data must be of the form {'changes': {'title': 'New Title', ...}, 'loaded_book_ids':[book_id1, book_id2, ...]'}''') dirtied = set() cdata = changes.pop('cover', False) if cdata is not False: if cdata is not None: try: cdata = standard_b64decode(cdata.split(',', 1)[-1].encode('ascii')) except Exception: raise HTTPBadRequest('Cover data is not valid base64 encoded data') try: fmt = what(None, cdata) except Exception: fmt = None if fmt not in ('jpeg', 'png'): raise HTTPBadRequest('Cover data must be either JPEG or PNG') dirtied |= db.set_cover({book_id: cdata}) for field, value in iteritems(changes): dirtied |= db.set_field(field, {book_id: value}) ctx.notify_changes(db.backend.library_path, metadata(dirtied)) all_ids = dirtied if all_dirtied else (dirtied & loaded_book_ids) all_ids |= {book_id} return {bid: book_as_json(db, bid) for bid in all_ids}
def cdb_set_fields(ctx, rd, book_id, library_id): db = get_db(ctx, rd, library_id) if ctx.restriction_for(rd, db): raise HTTPForbidden('Cannot use the set fields interface with a user who has per library restrictions') data = load_payload_data(rd) try: changes, loaded_book_ids = data['changes'], frozenset(map(int, data.get('loaded_book_ids', ()))) all_dirtied = bool(data.get('all_dirtied')) if not isinstance(changes, dict): raise TypeError('changes must be a dict') except Exception: raise HTTPBadRequest( '''Data must be of the form {'changes': {'title': 'New Title', ...}, 'loaded_book_ids':[book_id1, book_id2, ...]'}''') dirtied = set() cdata = changes.pop('cover', False) if cdata is not False: if cdata is not None: try: cdata = from_base64_bytes(cdata.split(',', 1)[-1]) except Exception: raise HTTPBadRequest('Cover data is not valid base64 encoded data') try: fmt = what(None, cdata) except Exception: fmt = None if fmt not in ('jpeg', 'png'): raise HTTPBadRequest('Cover data must be either JPEG or PNG') dirtied |= db.set_cover({book_id: cdata}) for field, value in iteritems(changes): dirtied |= db.set_field(field, {book_id: value}) ctx.notify_changes(db.backend.library_path, metadata(dirtied)) all_ids = dirtied if all_dirtied else (dirtied & loaded_book_ids) all_ids |= {book_id} return {bid: book_as_json(db, bid) for bid in all_ids}
def implementation(db, notify_changes, col, book_id, val, append): is_remote = notify_changes is not None field = db.field_metadata.custom_field_prefix + col with db.write_lock: if not db.has_id(book_id): return False, _('No book with id {} exists').format(book_id) try: fm = db.field_metadata[field] except KeyError: return False, _('No column with name {} exists').format(col) if fm['datatype'] == 'series': val, s_index = _get_series_values(val) if s_index is None: s_index = db.get_next_series_num_for(val, field=field) db.set_field(field, {book_id: val}), db.set_field(field + '_index', {book_id: s_index}) msg = _('Data set to: {} [{}]').format( db.field_for(field, book_id), db.field_for(field + '_index', book_id)) else: if append and fm['is_multiple']: val = list(db.field_for(field, book_id)) + [val] db.set_field(field, {book_id: val}) val = db.field_for(field, book_id) if isinstance(val, (tuple, list)): val = fm['is_multiple']['list_to_ui'].join(val) msg = _('Data set to: {}').format(val) if is_remote: notify_changes(metadata((book_id, ))) return True, msg
def cdb_set_cover(ctx, rd, book_id, library_id): db = get_db(ctx, rd, library_id) if ctx.restriction_for(rd, db): raise HTTPForbidden('Cannot use the add book interface with a user who has per library restrictions') rd.request_body_file.seek(0) dirtied = db.set_cover({book_id: rd.request_body_file}) ctx.notify_changes(db.backend.library_path, metadata(dirtied)) return tuple(dirtied)
def cdb_set_cover(ctx, rd, book_id, library_id): db = get_db(ctx, rd, library_id) if ctx.restriction_for(rd, db): raise HTTPForbidden('Cannot use the add book interface with a user who has per library restrictions') rd.request_body_file.seek(0) dirtied = db.set_cover({book_id: rd.request_body_file}) ctx.notify_changes(db.backend.library_path, metadata(dirtied)) return tuple(dirtied)
def cdb_set_fields(ctx, rd, book_id, library_id): db = get_db(ctx, rd, library_id) if ctx.restriction_for(rd, db): raise HTTPForbidden( 'Cannot use the set fields interface with a user who has per library restrictions' ) raw = rd.read() ct = rd.inheaders.get('Content-Type', all=True) ct = {x.lower().partition(';')[0] for x in ct} try: if MSGPACK_MIME in ct: data = msgpack_loads(raw) elif 'application/json' in ct: data = json_loads(raw) else: raise HTTPBadRequest('Only JSON or msgpack requests are supported') changes, loaded_book_ids = data['changes'], frozenset( map(int, data['loaded_book_ids'])) except Exception: raise HTTPBadRequest('Invalid encoded data') dirtied = set() cdata = changes.pop('cover', False) if cdata is not False: if cdata is not None: try: cdata = standard_b64decode( cdata.split(',', 1)[-1].encode('ascii')) except Exception: raise HTTPBadRequest( 'Cover data is not valid base64 encoded data') try: fmt = what(None, cdata) except Exception: fmt = None if fmt not in ('jpeg', 'png'): raise HTTPBadRequest('Cover data must be either JPEG or PNG') dirtied |= db.set_cover({book_id: cdata}) for field, value in changes.iteritems(): dirtied |= db.set_field(field, {book_id: value}) metadata(dirtied) return { bid: book_as_json(db, book_id) for bid in (dirtied & loaded_book_ids) | {book_id} }
def implementation(db, notify_changes, action, *args): is_remote = notify_changes is not None if action == 'field_metadata': return db.field_metadata if action == 'opf': book_id, mi = args with db.write_lock: if not db.has_id(book_id): return changed_ids = db.set_metadata(book_id, mi, force_changes=True, allow_case_change=False) if is_remote: notify_changes(metadata(changed_ids)) return db.get_metadata(book_id) if action == 'fields': book_id, fvals = args with db.write_lock: if not db.has_id(book_id): return mi = db.get_metadata(book_id) for field, val in fvals: if field.endswith('_index'): sname = mi.get(field[:-6]) if sname: mi.set(field[:-6], sname, extra=val) if field == 'series_index': mi.series_index = val # extra has no effect for the builtin series field elif field == 'cover': if is_remote: mi.cover_data = None, val[1] else: mi.cover = val read_cover(mi) else: mi.set(field, val) changed_ids = db.set_metadata(book_id, mi, force_changes=True, allow_case_change=True) if is_remote: notify_changes(metadata(changed_ids)) return db.get_metadata(book_id)
def cdb_set_fields(ctx, rd, book_id, library_id): db = get_db(ctx, rd, library_id) if ctx.restriction_for(rd, db): raise HTTPForbidden('Cannot use the set fields interface with a user who has per library restrictions') raw = rd.read() ct = rd.inheaders.get('Content-Type', all=True) ct = {x.lower().partition(';')[0] for x in ct} try: if MSGPACK_MIME in ct: data = msgpack_loads(raw) elif 'application/json' in ct: data = json_loads(raw) else: raise HTTPBadRequest('Only JSON or msgpack requests are supported') changes, loaded_book_ids = data['changes'], frozenset(map(int, data['loaded_book_ids'])) except Exception: raise HTTPBadRequest('Invalid encoded data') dirtied = set() for field, value in changes.iteritems(): dirtied |= db.set_field(field, {book_id: value}) metadata(dirtied) return {bid: book_as_json(db, book_id) for bid in (dirtied & loaded_book_ids) | {book_id}}
def implementation(db, notify_changes, action, *args): is_remote = notify_changes is not None if action == 'field_metadata': return db.field_metadata if action == 'opf': book_id, mi = args with db.write_lock: if not db.has_id(book_id): return changed_ids = db.set_metadata(book_id, mi, force_changes=True, allow_case_change=False) if is_remote: notify_changes(metadata(changed_ids)) return db.get_metadata(book_id) if action == 'fields': book_id, fvals = args with db.write_lock: if not db.has_id(book_id): return mi = db.get_metadata(book_id) for field, val in fvals: if field.endswith('_index'): sname = mi.get(field[:-6]) if sname: mi.set(field[:-6], sname, extra=val) if field == 'series_index': mi.series_index = val # extra has no effect for the builtin series field elif field == 'cover': if is_remote: mi.cover_data = None, val[1] else: mi.cover = val read_cover(mi) else: mi.set(field, val) changed_ids = db.set_metadata(book_id, mi, force_changes=True, allow_case_change=True) if is_remote: notify_changes(metadata(changed_ids)) return db.get_metadata(book_id)
def cdb_set_fields(ctx, rd, book_id, library_id): db = get_db(ctx, rd, library_id) if ctx.restriction_for(rd, db): raise HTTPForbidden('Cannot use the set fields interface with a user who has per library restrictions') raw = rd.read() ct = rd.inheaders.get('Content-Type', all=True) ct = {x.lower().partition(';')[0] for x in ct} try: if MSGPACK_MIME in ct: data = msgpack_loads(raw) elif 'application/json' in ct: data = json_loads(raw) else: raise HTTPBadRequest('Only JSON or msgpack requests are supported') changes, loaded_book_ids = data['changes'], frozenset(map(int, data['loaded_book_ids'])) except Exception: raise HTTPBadRequest('Invalid encoded data') dirtied = set() cdata = changes.pop('cover', False) if cdata is not False: if cdata is not None: try: cdata = standard_b64decode(cdata.split(',', 1)[-1].encode('ascii')) except Exception: raise HTTPBadRequest('Cover data is not valid base64 encoded data') try: fmt = what(None, cdata) except Exception: fmt = None if fmt not in ('jpeg', 'png'): raise HTTPBadRequest('Cover data must be either JPEG or PNG') dirtied |= db.set_cover({book_id: cdata}) for field, value in changes.iteritems(): dirtied |= db.set_field(field, {book_id: value}) ctx.notify_changes(db.backend.library_path, metadata(dirtied)) return {bid: book_as_json(db, book_id) for bid in (dirtied & loaded_book_ids) | {book_id}}