Metadata-Version: 2.4
Name: chatgen
Version: 0.1.0
Summary: Generate self-contained HTML mock-ups of chat conversations styled like popular messaging & dating apps.
Project-URL: Homepage, https://github.com/RuNeira/screenshots-generator
Project-URL: Repository, https://github.com/RuNeira/screenshots-generator
Project-URL: Issues, https://github.com/RuNeira/screenshots-generator/issues
Author-email: George Kasparyants <gg_plastt@mail.ru>
License-Expression: MIT
License-File: LICENSE
Keywords: chat,conversation,html,imessage,instagram,messaging,mockup,screenshot,telegram,ui,whatsapp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
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 :: Multimedia :: Graphics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup :: HTML
Requires-Python: >=3.10
Requires-Dist: jinja2>=3.1
Provides-Extra: screenshots
Requires-Dist: playwright>=1.40; extra == 'screenshots'
Description-Content-Type: text/markdown

# chatgen

Generate **self-contained HTML mock-ups of chat conversations** styled exactly like
popular platforms — messengers (iMessage, WhatsApp, Telegram, Instagram DM, Messenger,
Signal, Discord, Snapchat, VK, Slack, LINE, X/Twitter DM, WeChat, Viber) and dating apps
(Tinder, Bumble, Hinge). Feed it a dialog (participants + messages with timestamps),
pick a platform, device, and theme, and get back ready-to-open HTML — or a PNG
screenshot.

By default the output is a **clean, edge-to-edge screenshot** (just the screen, no
device bezel). The phone frame is an opt-in.

## Install

```bash
pip install chatgen          # or:  uv add chatgen

# optional, for PNG export:
pip install "chatgen[screenshots]"
playwright install chromium
```

## Quickstart

```python
from datetime import datetime
from chatgen import Generator, Dialog, Participant, Message, Text, Image
from chatgen import Platform, DeviceView, Theme, MessageStatus

me  = Participant(id="me",  name="You", is_self=True)
her = Participant(id="her", name="Alex Rivera", subtitle="online")

dialog = Dialog(participants=[me, her], messages=[
    Message(her, datetime(2026, 5, 31, 9, 40), Text("Hey! How's it going? 😊")),
    Message(me,  datetime(2026, 5, 31, 9, 41), Text("Pretty good! You?"),
            status=MessageStatus.READ),
    Message(her, datetime(2026, 5, 31, 9, 42), Image(src="alex_selfie.jpg")),
])

gen = Generator()

# 1) Clean screenshot HTML (default — no device frame)
html = gen.generate(dialog, platform=Platform.WHATSAPP,
                    view=DeviceView.IPHONE_15_PRO, theme=Theme.DARK)
open("chat.html", "w").write(html)

# 2) With the phone bezel (opt-in)
html_framed = gen.generate(dialog, platform=Platform.IMESSAGE,
                           view=DeviceView.IPHONE_15_PRO, theme=Theme.LIGHT,
                           show_frame=True)

# 3) PNG screenshot (needs the 'screenshots' extra)
gen.generate_png(dialog, platform=Platform.TELEGRAM,
                 view=DeviceView.IPHONE_15_PRO, theme=Theme.LIGHT,
                 path="chat.png", scale=2)
```

## API

```python
Generator().generate(dialog, platform, view, theme, **kwargs) -> str   # HTML
Generator().generate_png(dialog, platform, view, theme, *, path=None, scale=2, **kwargs) -> bytes
```

- **`dialog`** — a `Dialog` (see model below).
- **`platform`** — a `Platform` enum member or a registry-key string.
- **`view`** — a `DeviceView`: `IPHONE_15_PRO`, `IPHONE_SE`, `PIXEL_8`, `ANDROID`, `WEB`.
- **`theme`** — `Theme.LIGHT` or `Theme.DARK`.

### Common kwargs

| kwarg | default | meaning |
|-------|---------|---------|
| `show_frame` | `False` | draw the phone bezel + drop shadow (screenshot-first by default) |
| `show_status_bar` | `True` | render the OS status bar (clock/signal/battery) |
| `clock` | `"9:41"` | status-bar time |
| `battery` | `100` | status-bar battery percent |
| `typing` | `False` | show a "typing…" indicator bubble for the other person |
| `wallpaper` | `None` | chat background — a named preset (`"sunset"`, `"ocean"`, … see `list_wallpapers()`) or any raw CSS color/gradient — WhatsApp & Telegram |
| `animate` | `False` | when the HTML page opens, reveal messages **one-by-one** (fade + slide-up, scrolling to follow). Opt-in; works on every platform & device. `generate_png` ignores it (a still can't animate). |
| `animate_start` | `300` | ms before the first message appears (with `animate`) |
| `animate_delay` | `450` | ms between each message appearing (with `animate`) |

`animate` degrades gracefully: with JavaScript disabled or `prefers-reduced-motion`, all
messages show immediately.

`Message(reply_to=...)` renders an inline reply quote inside the bubble.

**Devices** (`view`): `iphone_15_pro`, `iphone_16_pro`, `iphone_15_pro_max`, `iphone_se`,
`pixel_8`, `pixel_9`, `galaxy_s24`, `android`, `web`.

### Platform-specific kwargs

| platform | kwargs |
|----------|--------|
| `imessage` | `show_contact_avatar` |
| `whatsapp` | `show_wallpaper`, `is_group` |
| `telegram` | `accent` (hex color) |
| `tinder`   | `show_match_banner` (uses `dialog.meta["matched_at"]`) |
| `bumble`   | `show_expiry`, `expiry_label` |
| `hinge`    | reads `dialog.meta["liked"]` for the context card |

## Data model

```python
Participant(id, name, avatar=None, is_self=False, subtitle=None, age=None, distance=None, bio=None)
Dialog(participants, messages, meta={})
Message(sender, timestamp, content, status=MessageStatus.SENT, reactions=[], reply_to=None)
Reaction(emoji, by)
```

Content types: `Text(body)`, `Image(src, caption)`, `Voice(duration_seconds, transcript)`,
`Sticker(src)`, `GIF(src, caption)`, `File(name, size)`, `Location(label, map_image)`,
`System(text)`.

**Avatars & images** (`avatar` / `src`) accept any of: an `http(s)` URL, a local file path
(embedded as a data-URI so the HTML stays self-contained), an existing `data:` URI, or
`None` (a deterministic initials-on-color placeholder is generated).

**Graceful degradation:** each platform declares which content types it natively renders;
unsupported types fall back to a readable bubble (e.g. Tinder renders a `Voice` as
"🎤 Voice message") instead of breaking.

## Supported platforms

```python
from chatgen import list_platforms
list_platforms()
# ['bumble', 'discord', 'hinge', 'imessage', 'instagram', 'line', 'messenger',
#  'signal', 'slack', 'snapchat', 'telegram', 'tinder', 'twitter', 'viber',
#  'vk', 'wechat', 'whatsapp']

from chatgen import list_wallpapers
list_wallpapers()  # 122 named wallpaper themes for the `wallpaper` kwarg
# mood gradients:   sunset, ocean, dusk, forest, rose, midnight, peach, lavender,
#                   mint, graphite, fire, ice, grape, coral, emerald, twilight,
#                   sakura, steel, gold, denim, noir, candy
# Telegram-style:   aurora, tropic, berry, lagoon, blossom, instaglow, seafoam,
# (multi-point      peony, marine, nebula, citrus, orchid, ember, glacier,
#  "freeform")      meadow, rosegold, cobalt
# solid colors:     sand, sage, fog, linen, clay, stone, ink, espresso, mist,
#                   almond, moss, dove, pine, navy, wine, slateblue
# editor/aesthetic: dracula, nord, solarized, solarized_dark, gruvbox, monokai,
#                   catppuccin, tokyonight, onedark, github_dark, vaporwave,
#                   synthwave, matrix, terminal, paper, kraft, chalkboard
# css patterns:     dots, dots_dark, grid, cross, blueprint, carbon, graph, stars
# image patterns:   doodle, polka, hearts, triangles, hexagons, waves, memphis,
# (SVG, embedded)   confetti, circuit, starfield, zigzag, seigaiha, plus,
#                   diamonds, bubbles, leafy, herringbone, rings, crosshatch2,
#                   terrazzo, scales, stars_small
# photo wallpapers: photo_mountain, photo_forest, photo_ocean, photo_city,
# (JPEG, embedded)  photo_desert, photo_dunes, photo_leaves, photo_sky,
#                   photo_coast, photo_woods, photo_alps, photo_pines,
#                   photo_planks, photo_marina, photo_harvest, photo_canal,
#                   photo_village, photo_trail, photo_lights, photo_greenery
```

Image wallpapers (SVG patterns + photos, in `chatgen/assets/wallpapers/`) are
base64-embedded into the output, so the HTML stays self-contained. Preview them
all on one conversation: `python examples/wallpaper_grid.py`.

(Or pass any raw CSS `background` value — color, gradient, or `url(...)` — directly.)

## Adding a platform

Platforms are plugins. Create a renderer, a `screen.html`, and a `style.css`:

```python
# chatgen/platforms/<group>/<name>/renderer.py
from chatgen.platforms.base import Capabilities, PlatformRenderer
from chatgen.registry import register_platform

@register_platform("signal")
class SignalRenderer(PlatformRenderer):
    capabilities = Capabilities()          # toggle off unsupported content types
    kwargs_schema = {"accent": "#3a76f0"}  # platform-specific options + defaults

    def build_context(self, dialog, device, theme, **kwargs):
        other = dialog.others[0] if dialog.others else None
        return {"header_name": other.name if other else "Signal"}
```

Templates live in `<name>/templates/screen.html` (import shared macros with
`{% import "macros.html" as m %}` and use `m.content_block(msg, caps, "<prefix>")`),
styled by `<name>/style.css`. Register the module in
`chatgen/platforms/__init__.py`.

## Examples gallery

```bash
python examples/generate_gallery.py
# open examples/out/index.html
```

## Development

Managed with [uv](https://docs.astral.sh/uv/):

```bash
uv sync              # create .venv with the project + dev group
uv run pytest -q     # run the test suite
uv build             # build sdist + wheel into dist/
uvx twine check dist/*
```

CI runs the suite on Python 3.10–3.13 (`.github/workflows/ci.yml`).

## Releasing (PyPI)

Publishing is automated via **PyPI Trusted Publishing** (OIDC — no API token stored).

1. One-time: on PyPI, add a GitHub publisher for project `chatgen` →
   owner `RuNeira`, repo `screenshots-generator`, workflow `publish.yml`,
   environment `pypi`.
2. Bump `version` in `pyproject.toml`, commit.
3. Tag and create a GitHub Release (`vX.Y.Z`). The `publish.yml` workflow verifies
   the tag matches the version, builds, and uploads to PyPI.

