'Add a book to the database. The result cache is not updated.
:param:`paths` List of paths to book files or file-like objects'

def add_books(self, paths, formats, metadata, add_duplicates=True, return_ids=False):

    (formats, metadata) = (iter(formats), iter(metadata))
    duplicates = []
    ids = []
    postimport = []
    for path in paths:
        mi = metadata.next()
        self._add_newbook_tag(mi)
        format = formats.next()
        if ((not add_duplicates) and self.has_book(mi)):
            duplicates.append((path, format, mi))
            continue
        series_index = (self.get_next_series_num_for(mi.series) if (mi.series_index is None) else mi.series_index)
        aus = (mi.author_sort if mi.author_sort else self.author_sort_from_authors(mi.authors))
        title = mi.title
        if isinstance(aus, str):
            aus = aus.decode(preferred_encoding, 'replace')
        if isinstance(title, str):
            title = title.decode(preferred_encoding)
        obj = self.conn.execute('INSERT    INTO    books(title,    series_index,    author_sort)    VALUES    (?,    ?,    ?)', (title, series_index, aus))
        id = obj.lastrowid
        self.data.books_added([id], self)
        ids.append(id)
        if (mi.timestamp is None):
            mi.timestamp = utcnow()
        if (mi.pubdate is None):
            mi.pubdate = UNDEFINED_DATE
        self.set_metadata(id, mi, commit=True, ignore_errors=True)
        npath = self.run_import_plugins(path, format)
        format = os.path.splitext(npath)[(-1)].lower().replace('.', '').upper()
        stream = lopen(npath, 'rb')
        format = check_ebook_format(stream, format)
        self.add_format(id, format, stream, index_is_id=True)
        stream.close()
        postimport.append((id, format))
    self.conn.commit()
    self.data.refresh_ids(self, ids)
    for (book_id, fmt) in postimport:
        run_plugins_on_postimport(self, book_id, fmt)
    if duplicates:
        paths = list((duplicate[0] for duplicate in duplicates))
        formats = list((duplicate[1] for duplicate in duplicates))
        metadata = list((duplicate[2] for duplicate in duplicates))
        return ((paths, formats, metadata), (ids if return_ids else len(ids)))
    return (None, (ids if return_ids else len(ids)))
