Metadata-Version: 2.4
Name: pymabibli
Version: 0.0.1
Summary: An async Python client for mabibli.be, the libraries of the Province of Liège
Home-page: https://github.com/bestycame/pymabibli
Author: Bestycame
Author-email: bestycame@gmail.com
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3.9
Requires-Dist: beautifulsoup4>=4.12
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# Mabibli Python Client
## NOT OFFICIALLY SUPPORTED BY THE PROVINCE DE LIÈGE --

An async Python client library for [mabibli.be](https://mabibli.be/), the library network of the Province of Liège.
This client logs in with your library card and reads your account, loans and borrowing history, and can renew loans.
Developped for a Home Assistant integration. At least for now.

## Installation
You can install the package using pip:

```bash
pip install pymabibli
```

## Usage

Here's a basic example of how to use the client:

```python
import asyncio

from pymabibli import MabibliClient


async def main():
    async with MabibliClient("your-card-number", "your-password") as client:
        # Log in (also done automatically by the other methods)
        await client.login()

        # Get account information
        account = await client.get_account()
        print(f"Membership ends: {account.subscription_end}")

        # Get current loans
        loans = await client.get_loans()
        for loan in loans:
            print(f"{loan.title} [{loan.library}] due {loan.due_date}")

        # Get borrowing history
        history = await client.get_history()
        print(f"{len(history)} items borrowed")

        # Renew one loan
        messages = await client.renew_loan(loans[0])

        # Renew all loans ("Tout prolonger")
        messages = await client.renew_all()


asyncio.run(main())
```

You can pass your own `aiohttp.ClientSession` with `session=`; the client then leaves it open when closing.
The login is kept in the session's cookie jar, so each client needs a session of its own:
two cards sharing one session would see each other's account.
In Home Assistant, use `async_create_clientsession(hass)` per config entry, not the shared `async_get_clientsession(hass)`.

## Error Handling

The client provides specific exception classes:

### Exception Classes

- `MabibliError`: Base exception for all errors
- `MabibliAuthError`: Raised when the card number or password is rejected
- `MabibliConnectionError`: Raised when the site can't be reached or returns an unexpected page
- `MabibliRenewError`: Raised when a loan can't be renewed or the site refuses the renewal

### Example Error Handling

```python
from pymabibli import MabibliAuthError, MabibliClient, MabibliRenewError

async def renew_everything():
    async with MabibliClient("your-card-number", "your-password") as client:
        try:
            loans = await client.get_loans()
        except MabibliAuthError as e:
            print(f"Login failed: {e}")
            return

        for loan in loans:
            if not loan.renewable:
                continue
            try:
                await client.renew_loan(loan)
            except MabibliRenewError as e:
                print(f"Could not renew {loan.title}: {e}")
```

### Authentication

mabibli.be authenticates through a CAS server (`centralcas.gminvent.fr`).
The client logs in on first use and logs in again when the site's session expires.
Renewals are never retried automatically: if the session is lost during a renewal, `MabibliAuthError` is raised
and you should check the loan before trying again.

### API Methods

- `login() -> None`: Log in with the card number and password
- `get_account() -> Account`: Get name, card number and membership end date
- `get_loans() -> list[Loan]`: Get current loans, across all pages
- `get_history() -> list[Loan]`: Get previously borrowed items, newest first, across all pages
- `renew_loan(loan: Loan) -> list[Message]`: Renew one loan and return the site's messages
- `renew_all() -> list[Message]`: Renew all renewable loans and return the site's messages

## Development

```bash
pipenv install --dev
pipenv run pytest
pipenv run flake8
```

The scripts in `examples/` run against the real site with your own card.
`examples/renew.py` really renews a loan, after asking which one.

## License
This project is licensed under the MIT License - see the LICENSE file for details.
