# noVNC 客户端

[![PyPI version](https://img.shields.io/pypi/v/noVNC-client.svg)](https://pypi.org/project/noVNC-client/)
[![Python Version](https://img.shields.io/pypi/pyversions/noVNC-client.svg)](https://pypi.org/project/noVNC-client/)
[![License](https://img.shields.io/github/license/Haskely/noVNC-client.svg)](https://github.com/Haskely/noVNC-client/blob/main/LICENSE)
[![Downloads](https://static.pepy.tech/badge/noVNC-client)](https://pepy.tech/project/noVNC-client)

一个用于程序化控制 noVNC WebSocket 服务器的 Python 库。提供异步远程桌面自动化功能，包括鼠标控制、键盘输入和屏幕截图捕获。

## 功能特性

- **鼠标控制**: 移动、点击、滚动，具有精确的坐标控制
- **键盘输入**: 发送按键、文本输入和组合键
- **屏幕截图**: 以 PNG 格式捕获屏幕截图
- **异步/等待支持**: 为现代 Python 异步应用程序而构建
- **类型安全**: 完整的类型注释和综合的异常处理
- **上下文管理器**: 使用 `async with` 自动管理连接

## 安装

```bash
pip install noVNC-client
```

## 快速开始

```python
import asyncio
from novnc_client import NoVNCClient

async def main():
    # 连接到 noVNC 服务器
    async with NoVNCClient('localhost', 6080) as client:
        # 截取屏幕截图
        await client.take_screenshot('desktop.png')

        # 鼠标操作
        await client.mouse_click(100, 100)
        await client.mouse_scroll(200, 200, 'up', steps=3)

        # 键盘输入
        await client.type_text('Hello, World!')
        await client.key_combination('ctrl', 'enter')

        # 获取屏幕信息
        width, height = client.screen_size
        print(f"屏幕尺寸: {width}x{height}")

asyncio.run(main())
```

## API 参考

### 连接

```python
# 上下文管理器（推荐）
async with NoVNCClient('localhost', 6080) as client:
    # 你的代码
    pass

# 手动连接
client = NoVNCClient('localhost', 6080, timeout=15.0)
await client.connect()
try:
    # 你的代码
    pass
finally:
    await client.disconnect()
```

### 鼠标操作

```python
# 移动鼠标到坐标
await client.mouse_move(x, y)

# 在坐标处点击
await client.mouse_click(x, y, button='left')  # 'left', 'right', 'middle'

# 在坐标处滚动
await client.mouse_scroll(x, y, direction='up', steps=3)  # 'up', 'down'

# 获取当前鼠标位置
x, y = client.mouse_position
```

### 键盘操作

```python
# 发送单个按键
await client.key_tap('enter')
await client.key_down('shift')
await client.key_up('shift')

# 输入文本字符串
await client.type_text('Hello, World!', delay=0.01)

# 发送组合键
await client.key_combination('ctrl', 'c')
await client.key_combination('ctrl', 'shift', 'n')
await client.key_combination('alt', 'f4')
```

### 特殊按键

支持的特殊按键包括：
- **导航键**: `enter`, `tab`, `backspace`, `escape`, `delete`, `home`, `end`, `insert`
- **箭头键**: `left`, `up`, `right`, `down`, `page_up`, `page_down`
- **功能键**: `f1`, `f2`, ..., `f12`
- **修饰键**: `ctrl`, `alt`, `shift`, `win`

### 屏幕截图

```python
# 保存到文件
await client.take_screenshot('screenshot.png')

# 获取 PIL Image 对象
image = await client.take_screenshot()
print(f"图像尺寸: {image.width}x{image.height}")
print(f"图像模式: {image.mode}")

# 将 PIL Image 保存到文件
image.save('screenshot.png')

# 如果需要，转换为字节
from io import BytesIO
buffer = BytesIO()
image.save(buffer, format='PNG')
image_bytes = buffer.getvalue()
```

### 服务器信息

```python
# 获取屏幕尺寸
width, height = client.screen_size

# 获取详细服务器信息
info = client.server_info
if info:
    print(f"服务器: {info.server_name}")
    print(f"分辨率: {info.width}x{info.height}")
    print(f"像素格式: {info.pixel_format.bits_per_pixel} bits")
```

## 错误处理

```python
from novnc_client import (
    NoVNCClientError,
    ConnectionError,
    ScreenshotError,
    # ... 其他异常
)

try:
    async with NoVNCClient('localhost', 6080) as client:
        await client.take_screenshot('test.png')
except ConnectionError as e:
    print(f"连接失败: {e}")
except ScreenshotError as e:
    print(f"截图失败: {e}")
except NoVNCClientError as e:
    print(f"客户端错误: {e}")
```

## 高级用法

### 自动化示例

```python
async def automate_notepad():
    async with NoVNCClient('localhost', 6080) as client:
        # 打开运行对话框
        await client.key_combination('win', 'r')
        await asyncio.sleep(0.5)

        # 启动记事本
        await client.type_text('notepad')
        await client.key_tap('enter')
        await asyncio.sleep(1)

        # 输入内容
        await client.type_text('通过 noVNC 自动化文本输入!')

        # 全选并复制
        await client.key_combination('ctrl', 'a')
        await client.key_combination('ctrl', 'c')
```

### 鼠标位置跟踪

```python
async with NoVNCClient('localhost', 6080) as client:
    # 鼠标位置会自动跟踪
    await client.mouse_move(100, 100)
    x, y = client.mouse_position  # 返回 (100, 100)

    await client.mouse_click(200, 200)
    x, y = client.mouse_position  # 返回 (200, 200)
```

## 开发

```bash
# 安装依赖
uv sync

# 运行测试
uv run pytest

# 格式化代码
pre-commit install

# 提交更改
cz commit

# 发布到 PyPI
cz bump
git push
git push --tags
```

## 贡献

1. Fork 仓库
2. 创建功能分支
3. 进行更改
4. 为新功能添加测试
5. 提交拉取请求
