Kavita

Detalhes específicos da integração com Kavita, um servidor de biblioteca de quadrinhos/mangás self-hosted. Para o modelo geral de fonte remota (dado compartilhado com o Komga, diálogo de conexão, credenciais, decisão de ações em massa) ver Fontes Remotas; para o Komga especificamente, ver Komga.

Autenticação

Auth Key, enviada no header x-api-key em toda requisição. Cifrada e guardada como descrito em Fontes Remotas.

Organização e modo de raiz

  • Organização FOLDERS: espelha as pastas reais configuradas na biblioteca Kavita. SERIES: uma pasta por série, arquivos soltos dentro.
  • Modo de raiz MERGE: conteúdo direto na raiz do acervo. LIBRARY_FOLDER: dentro de uma pasta com o nome da biblioteca — esse sempre foi o único comportamento do Kavita antes da opção existir, então continua sendo o default (bibliotecas já adicionadas não mudam de comportamento sozinhas).
  • Kavita não tem equivalente a "capas HQ" do Komga — a capa vem sempre do mesmo endpoint, sem variante de qualidade.

Múltiplos servidores Kavita podem coexistir, cada um com sua própria credencial e bibliotecas.

Cliente e endpoints

KavitaClient fala com a API REST do Kavita (/api/...) via HttpURLConnection simples. Os pontos usados pelo InkShelf:

  • GET /api/Library/libraries — listagem de bibliotecas (conexão inicial e ping de disponibilidade).
  • POST /api/Series/v2 — séries de uma biblioteca, com filtro por libraryId; paginado de verdade, lendo o header de resposta Pagination (convenção própria do Kavita, não o X-Pagination mais comum de outras APIs) — sem isso, uma biblioteca grande perde silenciosamente tudo que passa da 1ª página (bug real já corrigido).
  • GET /api/Series/volumes?seriesId= — volumes de uma série, cada um já trazendo seus capítulos.
  • GET /api/Image/chapter-cover — capa de um capítulo, usada por ensureKavitaCover (ver Sistema de Capas).
  • POST /api/Reader/progress — progresso de leitura (ver abaixo).
  • POST /api/ReadingList/lists, /create, /update-by-chapter, GET /items, POST /delete-item — reading lists, usadas como substituto de favoritos (ver abaixo). Rota é ReadingList (PascalCase, sem hífen) — o controller não declara rota própria, herda o padrão default da API (api/[controller]), diferente de outros endpoints do Kavita que usam hífen.

Por que a contagem de itens pode diferir do Komga

Uma mesma pasta de arquivos pode aparecer com contagens diferentes entre Komga e Kavita: o modelo de dados do Kavita permite que um capítulo lógico agrupe múltiplos arquivos físicos (ChapterDto.Files, ex. uma pasta de imagens soltas viram 1 capítulo). Isso não é um bug de contagem do InkShelf — é assim que o Kavita já modela o conteúdo dele. O download de um capítulo (downloadChapterZip) já trata isso corretamente, compactando todos os arquivos do capítulo juntos.

Progresso de leitura

KavitaProgressSync empurra progresso via POST /api/Reader/progress, que exige 4 IDs no corpo (chapterId/volumeId/seriesId/libraryId — por isso FileEntity guarda remoteItemId/remoteVolumeId/remoteSeriesId/remoteLibraryId pra item Kavita, populados de graça durante o scan). Diferente do Komga, o Kavita não tem endpoint dedicado pra desmarcar como lido — "marcar como não lido" reenvia o mesmo endpoint com pageNum=0 (o servidor deriva "lido" de pageNum >= total de páginas do capítulo, sem campo completed separado).

Progresso da sincronização (barra determinada)

Uma sincronização de biblioteca grande mostra uma barra de progresso real (não indeterminada), baseada na contagem de séries — a única contagem barata de obter no início, antes de processar volume por volume. Não mostra número de itens visível (ex. "X de Y séries"): uma versão anterior mostrava, e foi removida por confundir com contagem de arquivos — a barra continua progredindo de forma correta, só sem o número ao lado.

Favoritos

O Kavita não tem favoritos nativos por capítulo (só "Want to Read" por série inteira). O InkShelf usa uma Reading List chamada "Favoritos" como substituto — ver o mecanismo geral em Fontes Remotas. Diferente do Komga, a API de reading list do Kavita é incremental de verdade: adicionar (update-by-chapter) e remover (delete-item) afetam só o item em questão, sem reescrever a lista inteira — inclusive dá pra remover um item específico, algo que a própria interface web do Kavita não expõe. KavitaFavoritesSync.push faz um diff contra o estado atual da lista no servidor e só envia os deltas.