Metadata-Version: 2.4
Name: async-social-bridge
Version: 0.1.0
Summary: Async messaging adapters for Meta platforms (WhatsApp, Messenger, Instagram). Send and parse messages with a clean, typed Python API.
Project-URL: Homepage, https://github.com/Umar4880/async-social-bridge
Project-URL: Repository, https://github.com/Umar4880/async-social-bridge
Project-URL: Issues, https://github.com/Umar4880/async-social-bridge/issues
Author: Umar4880
License-Expression: MIT
License-File: LICENSE
Keywords: async,chatbot,instagram,messenger,meta,webhook,whatsapp
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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: Topic :: Communications :: Chat
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Description-Content-Type: text/markdown

# async-social-bridge

**Async messaging adapters for Meta platforms (WhatsApp, Messenger, Instagram).**

Send and parse messages with a clean, typed Python API. Zero bloat — only `httpx` and `pydantic` as dependencies.

## Installation

```bash
pip install async-social-bridge
```

## Quick Start

### Parse incoming webhooks

```python
from chatbridge.meta import parse_webhook

# In your FastAPI / Flask webhook handler:
payload = await request.json()
messages = parse_webhook(payload)

for msg in messages:
    print(f"[{msg.platform}] {msg.sender_name or msg.sender_id}: {msg.text}")
```

### Send messages

```python
from chatbridge.meta import WhatsAppAdapter, MessengerAdapter

# WhatsApp
async with WhatsAppAdapter(access_token="your_token") as wa:
    result = await wa.send_text(
        receiver_id="your_phone_number_id",
        to="recipient_phone",
        text="Hello from chatbridge!"
    )
    print(result.success)       # True
    print(result.message_id)    # "wamid.xxx..."

# Messenger
async with MessengerAdapter(access_token="your_token") as fb:
    result = await fb.send_text(
        receiver_id="your_page_id",
        to="recipient_psid",
        text="Hello from chatbridge!"
    )
```

## Features

- **Async-first** — Built on `httpx` for non-blocking I/O
- **Typed models** — `IncomingMessage` and `SendResult` are Pydantic models with full type hints
- **Webhook parsing** — One function to normalize WhatsApp, Messenger, and Instagram payloads
- **Context manager** — Proper HTTP client lifecycle with `async with`
- **Minimal dependencies** — Only `httpx` and `pydantic`
- **Extensible** — Subclass `BaseAdapter` to add Telegram, Slack, or any other platform

## Models

### IncomingMessage

| Field         | Type            | Description                                    |
|---------------|-----------------|------------------------------------------------|
| `platform`    | `str`           | `"whatsapp"`, `"messenger"`, or `"instagram"`  |
| `sender_id`   | `str`           | Platform-specific sender identifier            |
| `receiver_id` | `str`           | Page ID, phone number ID, etc.                 |
| `text`        | `str`           | Message text content                           |
| `timestamp`   | `datetime`      | When the message was received                  |
| `metadata`    | `dict`          | Contains extra info (e.g., `sender_name`)      |
| `raw`         | `dict \| None`  | Original webhook JSON for advanced use         |

### SendResult

| Field          | Type            | Description                          |
|----------------|-----------------|--------------------------------------|
| `success`      | `bool`          | Whether the send succeeded           |
| `error`        | `str \| None`   | Error message if failed              |
| `status_code`  | `int \| None`   | HTTP status code                     |
| `metadata`     | `dict`          | Contains platform response (e.g. `message_id`)|
| `raw_response` | `dict \| None`  | Raw JSON response                    |

## Extending

Create your own adapter by subclassing `BaseAdapter`:

```python
from chatbridge.base import BaseAdapter
from chatbridge.models import SendResult

class TelegramAdapter(BaseAdapter):
    def __init__(self, bot_token: str):
        super().__init__(
            access_token=bot_token,
            base_url="https://api.telegram.org",
        )

    async def send_text(self, receiver_id: str, to: str, text: str) -> SendResult:
        resp = await self._client.post(
            f"/bot{self.access_token}/sendMessage",
            json={"chat_id": to, "text": text},
        )
        data = resp.json()
        return SendResult(
            success=data.get("ok", False),
            message_id=str(data.get("result", {}).get("message_id")),
            status_code=resp.status_code,
            raw_response=data,
        )
```

## License

MIT
