No description
Find a file
ryan 4c276a04d7 Clean up BMAD output directory
Removed temporary BMAD output artifacts:
- _bmad-output/ tech spec and artifacts

These were used for the initial library development workflow
and are no longer needed for the next phase of the project.

Note: Kept _bmad/ framework directory for future use.
2026-02-06 14:04:29 +00:00
.claude/commands Address Medium severity findings (F11-F22) from adversarial review 2026-02-06 13:48:01 +00:00
.crush/commands Clean up example files and enhance client with logging and client caching 2026-01-31 04:25:21 +00:00
.opencode/command Clean up example files and enhance client with logging and client caching 2026-01-31 04:25:21 +00:00
_bmad Address Medium severity findings (F11-F22) from adversarial review 2026-02-06 13:48:01 +00:00
example_requests Add implementation artifacts and example requests for GraphQL API work 2026-01-31 19:41:20 +00:00
real_responses Address Medium severity findings (F11-F22) from adversarial review 2026-02-06 13:48:01 +00:00
scripts Remove pyc stuff 2026-01-31 14:26:28 +00:00
suwayomi_graphql Address Low severity findings (F25-F29) from adversarial review 2026-02-06 14:01:10 +00:00
tests Address Medium severity findings (F11-F22) from adversarial review 2026-02-06 13:48:01 +00:00
.coverage Address Low severity findings (F25-F29) from adversarial review 2026-02-06 14:01:10 +00:00
.gitignore add ignore file 2026-01-31 14:27:20 +00:00
=4.0.0 Address Medium severity findings (F11-F22) from adversarial review 2026-02-06 13:48:01 +00:00
AGENTS.md Initial commit: Suwayomi Extension Updater project setup 2026-01-31 01:58:55 +00:00
capture_real_responses.py Address Medium severity findings (F11-F22) from adversarial review 2026-02-06 13:48:01 +00:00
CHANGELOG.md Address Low severity findings (F25-F29) from adversarial review 2026-02-06 14:01:10 +00:00
opencode.json Add the existing bits, gonna wipe and try claude 2026-02-05 18:55:48 +00:00
pyproject.toml Address Low severity findings (F25-F29) from adversarial review 2026-02-06 14:01:10 +00:00
README.md Address Low severity findings (F25-F29) from adversarial review 2026-02-06 14:01:10 +00:00
suwayomi_config.toml Clean up more stuff, remove stupid config options 2026-02-05 19:00:57 +00:00
test_real_smoke.py Address Medium severity findings (F11-F22) from adversarial review 2026-02-06 13:48:01 +00:00

Suwayomi GraphQL Async Client

An async Python client library for the Suwayomi GraphQL API.

Compatibility

  • Suwayomi Server: Tested with preview builds (2024-2026)
  • Python: 3.11, 3.12, 3.13
  • GraphQL API: Compatible with Suwayomi's GraphQL schema as of 2026

This library is tested against real Suwayomi server instances. While it should work with most recent versions, some older versions may have schema differences.

Features

  • Fully async using aiohttp and gql
  • Type-hinted for better IDE support
  • Async context manager support
  • Covers all major Suwayomi operations:
    • Extension management (list, install, update)
    • Library queries
    • Chapter operations
    • Download queue management

Installation

pip install -e .

For development:

pip install -e ".[dev]"

Usage

Basic Setup

import asyncio
from suwayomi_graphql import SuwayomiClient

async def main():
    # Connect to local or remote Suwayomi server
    # Note: Suwayomi does not require authentication for local servers
    async with SuwayomiClient("http://localhost:4567") as client:
        extensions = await client.fetch_extensions()
        print(f"Found {len(extensions)} extensions")

        manga_list = await client.fetch_library_manga_list()
        print(f"Library has {len(manga_list)} manga")

if __name__ == "__main__":
    asyncio.run(main())

Extension Operations

async with SuwayomiClient(server_url) as client:
    # List all extensions
    extensions = await client.fetch_extensions()
    for ext in extensions:
        if ext["hasUpdate"]:
            print(f"{ext['name']} has an update available")

    # Update an extension
    await client.update_extension("eu.kanade.tachiyomi.extension.all.mangadex")

    # Install an extension
    await client.install_extension("eu.kanade.tachiyomi.extension.en.mangaplus")

Library Operations

async with SuwayomiClient(server_url) as client:
    # Get all manga in library
    manga_list = await client.fetch_library_manga_list()

    for manga in manga_list:
        print(f"{manga['title']}: {manga['unreadCount']} unread chapters")

Chapter Operations

async with SuwayomiClient(server_url) as client:
    # Get chapters for a manga (with pagination)
    chapters = await client.fetch_manga_chapter_list(manga_id=123)

    # Get more chapters using cursor
    more_chapters = await client.fetch_manga_chapter_list(
        manga_id=123,
        after="cursor_string",
        first=50
    )

Download Queue Operations

async with SuwayomiClient(server_url) as client:
    # Check download status
    status = await client.get_download_status()
    print(f"Downloader state: {status['state']}")
    print(f"Queue length: {len(status['queue'])}")

    # Enqueue chapters for download
    chapter_ids = [1, 2, 3, 4, 5]
    await client.enqueue_chapter_downloads(chapter_ids)

    # Start the downloader
    await client.start_downloader()

    # Stop the downloader
    await client.stop_downloader()

    # Delete a downloaded chapter
    await client.delete_downloaded_chapter(chapter_id=1)

Error Handling

from suwayomi_graphql import (
    SuwayomiClient,
    SuwayomiConnectionError,
    SuwayomiAuthenticationError,
    SuwayomiGraphQLError,
    SuwayomiResponseError,
)

async with SuwayomiClient(server_url) as client:
    try:
        extensions = await client.fetch_extensions(timeout=60)
    except SuwayomiConnectionError as e:
        print(f"Connection failed: {e}")
    except SuwayomiAuthenticationError as e:
        print(f"Authentication failed: {e}")
    except SuwayomiGraphQLError as e:
        print(f"GraphQL error: {e}")
        print(f"Errors: {e.errors}")
    except SuwayomiResponseError as e:
        print(f"Invalid response: {e}")

Custom Timeouts

# Specify timeout per request (in seconds)
async with SuwayomiClient(server_url) as client:
    # Short timeout for quick operations
    status = await client.get_download_status(timeout=10)

    # Longer timeout for slow operations
    extensions = await client.fetch_extensions(timeout=300)

API Reference

SuwayomiClient

Constructor

SuwayomiClient(server_url: str)
  • server_url: Base URL of Suwayomi server (e.g., http://localhost:4567)

Note: Timeouts are specified per-request on individual methods (default: 60s for queries, 300s for mutations). Suwayomi does not require authentication for local servers. HTTP Basic Auth is not currently supported.

Methods

Extension Operations:

  • fetch_extensions() -> list[Extension] - List all extensions
  • update_extension(pkg_name: str) -> Extension - Update an extension
  • install_extension(pkg_name: str) -> Extension - Install an extension

Library Operations:

  • fetch_library_manga_list() -> list[MangaLibrary] - Get all manga in library

Chapter Operations:

  • fetch_manga_chapter_list(manga_id: int, after: str | None = None, first: int = 100) -> list[Chapter] - Get chapters for a manga with pagination

Download Operations:

  • get_download_status() -> DownloadStatus - Get current download queue status
  • enqueue_chapter_downloads(chapter_ids: list[int]) -> DownloadStatus - Add chapters to download queue
  • start_downloader() -> DownloadStatus - Start the download service
  • stop_downloader() -> DownloadStatus - Stop the download service
  • delete_downloaded_chapter(chapter_id: int) -> dict - Delete a downloaded chapter

Development

Running Tests

pytest

Building Package

python -m build

Versioning and Stability

This library follows Semantic Versioning:

  • MAJOR version for incompatible API changes
  • MINOR version for backwards-compatible functionality additions
  • PATCH version for backwards-compatible bug fixes

API Stability

  • Current Status: Alpha (0.x.x) - API may change between minor versions
  • Deprecation Policy: Once 1.0.0 is released, deprecated features will:
    • Emit warnings for at least one minor version before removal
    • Be documented in CHANGELOG.md with migration guidance
    • Only be removed in major version releases

Compatibility

This library is tested against the Suwayomi preview builds. While we strive for backwards compatibility, the Suwayomi GraphQL schema may evolve. Check the Compatibility section for supported versions.

All rights reserved.