Metadata-Version: 2.4
Name: bsm-api-client
Version: 1.2.1
Summary: A Python client library for the Bedrock Server Manager API
Author-email: DMedina559 <dmedina559-github@outlook.com>
Project-URL: Homepage, https://github.com/DMedina559/bsm-api-client
Project-URL: Bug Tracker, https://github.com/DMedina559/bsm-api-client/issues
Project-URL: Changelog, https://github.com/DMedina559/bsm-api-client/blob/main/docs/CHANGELOG.md
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Framework :: AsyncIO
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp<4.0.0,>=3.8.0
Requires-Dist: pydantic<2.12,>=2.11.0
Provides-Extra: dev
Requires-Dist: pytest<8.5,>=8.4.0; extra == "dev"
Requires-Dist: pytest-asyncio<1.2.0,>=1.1.0; extra == "dev"
Requires-Dist: black<25.2,>=25.1.0; extra == "dev"
Requires-Dist: flake8<7.4,>=7.3.0; extra == "dev"
Provides-Extra: cli
Requires-Dist: click<8.3,>=8.2.0; extra == "cli"
Requires-Dist: questionary<2.2,>=2.1.0; extra == "cli"
Provides-Extra: keywords
Requires-Dist: minecraft; extra == "keywords"
Requires-Dist: bedrock; extra == "keywords"
Requires-Dist: server; extra == "keywords"
Requires-Dist: manager; extra == "keywords"
Requires-Dist: api; extra == "keywords"
Requires-Dist: client; extra == "keywords"
Requires-Dist: asyncio; extra == "keywords"
Requires-Dist: aiohttp; extra == "keywords"
Requires-Dist: bsm; extra == "keywords"
Dynamic: license-file

<div style="text-align: center;">
    <img src="https://raw.githubusercontent.com/dmedina559/bedrock-server-manager/main/src/bedrock_server_manager/web/static/image/icon/favicon.svg" alt="BSM Logo" width="150">
</div>

# bsm-api-client

[![PyPI version](https://img.shields.io/pypi/v/bsm-api-client.svg)](https://pypi.org/project/bsm-api-client/)
[![Python Versions](https://img.shields.io/pypi/pyversions/bsm_api_client.svg)](https://pypi.org/project/bsm-api-client/)
[![License](https://img.shields.io/pypi/l/bsm-api-client.svg)](https://github.com/dmedina559/bsm-api-client/blob/main/LICENSE)

## Introduction

`bsm-api-client` is an asynchronous Python client library for interacting with the Bedrock Server Manager API. It provides a convenient way to manage Minecraft Bedrock Dedicated Servers through the manager's HTTP API.

## Features

*   Fully asynchronous using `asyncio` and `aiohttp`.
*   Context manager support for session management.
*   Handles authentication (JWT) automatically, including token refresh attempts.
*   Provides methods for most BSM API endpoints:
    *   Manager Information & Global Actions
    *   Server Listing, Status & Configuration
    *   Server Actions (Start, Stop, Command, Update, etc.)
    *   Content Management (Backups, Worlds, Addons)
    *   OS-specific Task Scheduling (Cron for Linux, Task Scheduler for Windows)
*   Custom exceptions for specific API errors, providing context like status codes and API messages.
*   Supports connecting via HTTP or HTTPS.

## Installation

Install the library using pip:

```bash
pip install bsm-api-client
```

or if you wish to use the Command Line Interface CLI:

```bash
pip install bsm-api-client[cli]
```

## Quick Start

Here's a basic example of how to initialize the client and fetch server information:

For a complete list of endpoints and examples, see [API_DOCS.md](https://github.com/DMedina559/bsm-api-client/blob/main/docs/API_DOCS.md)

```python
import asyncio
from bsm_api_client import BedrockServerManagerApi, APIError, CannotConnectError

async def main():
    client = BedrockServerManagerApi(
        base_url="http://host:port",    # e.g., "http://127.0.0.1:11325" or "https://bsm.example.internal"
        username="username",           # Username for BSM login
        password="password",           # Password for BSM login
        verify_ssl=True                # Set to False if using HTTPS with a self-signed cert
    )

    try:
        async with client: # Handles session and token management
            # Get manager info (no auth needed for this specific call, but client handles it)
            manager_info = await client.async_get_info()
            print(f"Manager OS: {manager_info.get('data', {}).get('os_type')}, Version: {manager_info.get('data', {}).get('app_version')}")

            # Get list of all servers
            servers = await client.async_get_servers_details()
            if servers:
                print("\nManaged Servers:")
                for server in servers:
                    print(f"  - Name: {server['name']}, Status: {server['status']}, Version: {server['version']}")
            else:
                print("No servers found.")

            # Example: Start a specific server (replace 'MyServer' with an actual server name)
            # server_name_to_start = "MyServer"
            # if any(s['name'] == server_name_to_start for s in servers):
            #     print(f"\nAttempting to start server: {server_name_to_start}")
            #     start_response = await client.async_start_server(server_name_to_start)
            #     print(f"Start response: {start_response.get('message')}")
            # else:
            #     print(f"\nServer '{server_name_to_start}' not found, cannot start.")

    except AuthError as e:
        print(f"Authentication Error: {e}")
    except ServerNotFoundError as e:
        print(f"Server Not Found Error: {e}")
    except APIError as e:
        print(f"An API Error occurred: {e}")
        print(f"  Status Code: {e.status_code}")
        print(f"  API Message: {e.api_message}")
        print(f"  API Errors: {e.api_errors}")
    except CannotConnectError as e:
        print(f"Connection Error: {e}")
    except ValueError as e:
        print(f"Input Error: {e}")
    finally:
        # The `async with client:` block handles closing the session.
        # If not using context manager, you would call:
        # await client.close()
        pass

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