Metadata-Version: 2.4
Name: digitalguide
Version: 0.0.534
Summary: A Python Library to write digital guides for telegram
Author: Soeren Etler
License: MIT
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests
Requires-Dist: redis
Requires-Dist: pymongo
Requires-Dist: mongoengine
Requires-Dist: pywa
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: flake8; extra == "test"
Requires-Dist: boto3; extra == "test"
Requires-Dist: Pillow; extra == "test"
Dynamic: author
Dynamic: description
Dynamic: description-content-type
Dynamic: license
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: summary

# Digital Guides

A Python library for building interactive, state-machine-driven conversational guides on WhatsApp (via the WhatsApp Cloud API and [pywa](https://github.com/david-lev/pywa)).

## Overview

Digital Guides lets you define guided experiences as JSON — each **state** contains a list of **handlers** that match incoming messages and a list of **actions** that are sent in response. The library handles webhook parsing, pattern matching, message sending, and persistence so you can focus on the conversation flow.

## Installation

```bash
pip install digitalguide
```

With MongoDB persistence and pywa (WhatsApp Cloud API client):

```bash
pip install "digitalguide[full]"
```

With image processing (PIL) and S3 storage:

```bash
pip install "digitalguide[full]" boto3 Pillow
```

## Configuration

Create a `config.ini` file in your working directory:

```ini
[bot]
bot_name = my_bot_name   # used as the MongoDB database alias

[space]
space_name = my-s3-bucket
space_region = fra1
space_endpoint = https://fra1.digitaloceanspaces.com
```

Set S3/DigitalOcean Spaces credentials as environment variables:

```bash
export SPACES_KEY=your_access_key
export SPACES_SECRET=your_secret_key
```

## Quick Start

### 1. Define states and actions as JSON

```python
handlers_json = [
    {
        "handler": "MessageHandler",
        "filter": "regex",
        "regex": "WEITER_PATTERN",   # matches "weiter", "next", "ok", etc.
        "action": "welcome_action"
    },
    {
        "handler": "MessageHandler",
        "filter": "text",
        "action": "fallback_action"
    }
]

actions_json = [
    {"type": "message", "text": "Willkommen, {profile_name}!"},
    {"type": "message", "text": "Schreib etwas, um fortzufahren."},
    {"type": "return", "state": "next_state"}
]
```

### 2. Build handlers and actions

```python
from digitalguide.generateStates import read_state
from digitalguide.generateActions import Action

handlers = read_state(handlers_json)
action = Action(actions_json)
```

### 3. Process an incoming webhook

The library uses [pywa](https://github.com/david-lev/pywa) for WhatsApp Cloud API integration. Register a handler on your `PyWa` client and dispatch the incoming update through your state's handler list:

```python
from pywa import WhatsApp
from pywa.types import Message, CallbackButton, CallbackSelection
import redis

wa = WhatsApp(
    phone_id="YOUR_PHONE_NUMBER_ID",
    token="YOUR_ACCESS_TOKEN",
    server=None,           # e.g. a Flask or FastAPI app
    callback_url="https://your-domain.com/webhook",
    verify_token="YOUR_VERIFY_TOKEN",
)

r = redis.Redis()         # Redis client used to track in-flight messages

def handle_update(client: WhatsApp, update: Message | CallbackButton | CallbackSelection):
    context = {"state": "start"}   # load from your persistence layer

    for handler in handlers:
        if handler.check_update(update):
            new_state = handler.callback(client, update, context, r)
            break
```

`update` is a `pywa.types.Message`, `CallbackButton`, or `CallbackSelection` object delivered by pywa's webhook dispatcher. `r` is a Redis client used to track in-flight messages.

## Action Types

| Type | Description |
|------|-------------|
| `message` | Send a text message. Supports `reply_buttons` and interactive list via `button` + `section_title` + `rows`. |
| `photo` | Send an image by `url` or media `id`. |
| `video` | Send a video by `url`. |
| `audio` / `voice` | Send audio by `url` or media `id`. |
| `sticker` | Send a sticker by `url`. |
| `carousel` | Send a card carousel with `text` and `cards`. |
| `venue` | Send a location pin with `title`, `address`, `latitude`, `longitude`. |
| `poll` | Send a text poll with `question` and `options` list. |
| `function` | Call a special action function by `func` (`module:function_name`) with extra keyword arguments. |
| `return` | Transition to a new state. Must be the last item; returns `state` string to the caller. |

### Message placeholders

Inside `text` fields you can use:

- `{profile_name}` — the user's WhatsApp display name
- `{echo}` — the user's last message text
- `{any_context_key}` — any value stored in the `context` dict

## Handler Types

### `MessageHandler`

Matches incoming messages. Supported `filter` values:

| Filter | Matches |
|--------|---------|
| `regex` | A named pattern (e.g. `JA_PATTERN`) or a custom regex string |
| `text` | Any text message |
| `photo` | Any image message |
| `voice` | Any audio/voice message |

Named patterns available: `EMOJI_PATTERN`, `JA_PATTERN`, `NEIN_PATTERN`, `WEITER_PATTERN`, `ZURUECK_PATTERN`, `WOHIN_PATTERN`, `JAHRESZAHL_PATTERN`, `KOMMAZAHL_PATTERN`, `DATENSCHUTZ_PATTERN`.

### `CommandHandler`

Matches a specific command string (e.g. `/start`):

```json
{"handler": "CommandHandler", "command": "start", "action": "start_action"}
```

### `TypeHandler`

Matches by update type. Currently supports `"Update"`.

## Special Actions

Register additional action functions by passing an `action_functions` dict to `Action`:

```python
from digitalguide.special_actions import contextActions, writeActions

action_functions = {
    **contextActions.whatsapp_action_functions,
    **writeActions.whatsapp_action_functions,
}

action = Action(actions_json, action_functions=action_functions)
```

Or reference them directly in JSON with `module:function` syntax:

```json
{"type": "function", "func": "contextActions:save_text_to_context", "key": "user_answer"}
```

Available modules:

- `contextActions` — save values to the session context
- `writeActions` — persist user-sent media (photo, voice, video, document) to S3
- `imageActions` — image overlay and GIF generation
- `listenfrageActions` — listening/survey question tracking
- `schaetzfragenActions` — year/decimal estimation questions with feedback

## Data Persistence

When `[full]` dependencies are installed and MongoDB is connected, the library automatically persists:

- `WhatsAppUser` — user profile name and WhatsApp ID (created on first interaction)
- `WhatsAppInteraction` — every incoming message with its state and timestamp
- `WhatsAppUserContextState` — per-user session context and current state

Connect MongoDB before processing updates:

```python
import mongoengine
mongoengine.register_connection(alias="my_bot_name", name="my_bot_name", host="mongodb://localhost")
```

## Running Tests

```bash
pip install "digitalguide[test]"
pytest
```

## License

MIT
