Metadata-Version: 2.1
Name: arclet-entari
Version: 0.18.0rc1
Summary: Simple IM Framework based on satori-python
Author-Email: RF-Tar-Railt <rf_tar_railt@qq.com>
License: MIT
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: Programming Language :: Python :: 3.14
Classifier: License :: OSI Approved :: MIT License
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Framework :: AsyncIO
Classifier: Operating System :: OS Independent
Project-URL: homepage, https://arclet.top
Project-URL: repository, https://github.com/ArcletProject/Entari
Requires-Python: >=3.10
Requires-Dist: arclet-letoderea<0.22.0,>=0.21.1
Requires-Dist: arclet-alconna<2.0.0,>=1.8.44
Requires-Dist: satori-python-core<1.4.0,>=1.3.2
Requires-Dist: satori-python-client<1.4.0,>=1.3.2
Requires-Dist: arclet-alconna-tools>=0.7.3
Requires-Dist: nonestorage>=0.1.0
Requires-Dist: simpleeval>=1.0.3
Provides-Extra: yaml
Requires-Dist: ruamel-yaml>=0.18.10; extra == "yaml"
Provides-Extra: cron
Requires-Dist: croniter>=5.0.1; extra == "cron"
Provides-Extra: reload
Requires-Dist: watchfiles>=1.0.3; extra == "reload"
Provides-Extra: dotenv
Requires-Dist: python-dotenv>=1.0.1; extra == "dotenv"
Provides-Extra: full
Requires-Dist: croniter>=5.0.1; extra == "full"
Requires-Dist: watchfiles>=1.0.3; extra == "full"
Requires-Dist: python-dotenv>=1.0.1; extra == "full"
Requires-Dist: ruamel-yaml>=0.18.10; extra == "full"
Requires-Dist: entari-cli>=0.1.0; extra == "full"
Provides-Extra: pydantic
Requires-Dist: pydantic>=2.10.6; extra == "pydantic"
Provides-Extra: msgspec
Requires-Dist: msgspec>=0.19.0; extra == "msgspec"
Provides-Extra: toml
Requires-Dist: tomlkit>=0.13.3; extra == "toml"
Provides-Extra: cli
Requires-Dist: entari-cli>=0.1.0; extra == "cli"
Provides-Extra: rich
Requires-Dist: rich>=14.1.0; extra == "rich"
Description-Content-Type: text/markdown

<div align="center"> 
  
# Entari

  > _lí no etheclim, nann ze entám rish._

![Entari](https://img.shields.io/badge/Arclet-Entari-2564c2.svg)
[![Licence](https://img.shields.io/github/license/ArcletProject/Entari)](https://github.com/ArcletProject/Entari/blob/main/LICENSE)
[![PyPI](https://img.shields.io/pypi/v/arclet-entari)](https://pypi.org/project/arclet-entari)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/arclet-entari)](https://www.python.org/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ArcletProject/Entari)
[![Docs](https://img.shields.io/badge/docs-arclet.top-28d178)](https://arclet.top/tutorial/entari/)
[![QQ 群](https://img.shields.io/badge/QQ-654490750-yellow.svg)](https://jq.qq.com/?_wv=1027&k=PUPOnCSH)

</div>


一个基于 `Satori` 协议的灵活、高效的 IM framework

## 特性

- 基于 Satori 协议，一份代码即可对接多种平台
- 异步并发，基于 Python 的异步特性，即使有大量的事件传入，也能吞吐自如。在常规使用下能达到1000+ RPS
- 易上手的开发体验，没有过多的冗余代码，可以让开发者专注于业务逻辑
- 既可集成式也可分布式的配置文件，内建且可拓展的配置模型
- 即插即拔，可热重载、可重用的插件机制
- 自定义服务、自定义事件等高度可拓展的功能
- 高度可拓展的事件响应器，能够依托强大的、符合直觉依赖注入进行会话控制
- 内置强大的命令系统、定时任务系统与多种插件

## 示例

使用 `entari-cli` 命令行:
```shell
# 创建新的 entari 项目
$ entari init
是否创建新的虚拟环境? (Y/n): Y
请输入要选择的 Python 解释器路径
 0. cpython@3.11 (...)
 1. ...
请选择 (0): 0
虚拟环境将创建在 ...
...
```
```shell
# 运行
$ entari run
```

使用的配置文件:
```yaml
# entari.yml
basic:
  network:
    - type: ws
      host: "127.0.0.1"
      port: 5140
      path: "satori"
  ignore_self_message: true
  log:
    level: INFO
  prefix: ["/"]
plugins:
  $prelude:
    - ::auto_reload
  .record_message: {}
  ::auto_reload:
    watch_dirs: ["."]
  ::help: {}
  ::echo: {}
  ::inspect: {}
```

复读:

```python
from arclet.entari import Session, Entari, WS

app = Entari(WS(host="127.0.0.1", port=5140, path="satori"))

@app.on_message()
async def repeat(session: Session):
    await session.send(session.content)


app.run()
```

指令 `add {a} {b}`:

```python
from arclet.entari import Entari, WS, command

@command.on("add {a} {b}")
def add(a: int, b: int):
    return f"{a + b = }"


app = Entari(WS(port=5500, token="XXX"))
app.run()
```

编写插件:

```python
from arclet.entari import BasicConfModel, Session, MessageCreatedEvent, plugin


class Config(BasicConfModel):
    name: str


plugin.metadata(
    name="Hello, World!",
    author=["Arclet"],
    version="0.1.0",
    description="A simple plugin that replies 'Hello, World!' to every message.",
    config=Config
)
# or __plugin_metadata__ = PluginMetadata(...)

config = plugin.get_config(Config)

@plugin.listen(MessageCreatedEvent)  # or plugin.dispatch(MessageCreatedEvent)
async def _(session: Session):
    await session.send(f"Hello, World! {config.name}")
```

加载插件:

```diff
# entari.yml
plugins:
  $prelude:
    - ::auto_reload
  .record_message: {}
  ::auto_reload:
    watch_dirs: ["."]
  ::help: {}
  ::echo: {}
  ::inspect: {}
++ example_plugin: {}  # 加载 example_plugin 插件
```

在其他插件中导入插件:

```python
from arclet.entari import command, MessageChain, Image
from entari_plugin_browser import md2img  # entari: plugin


@command.on("md2img {content}")
async def _(content: str):
    return MessageChain(Image.of(raw=await md2img(content)))
```


## 配置文件

```yaml
basic:
  network:
    - type: ws
      host: "127.0.0.1"
      port: 5140
      path: "satori"
  ignore_self_message: true
  log:
    level: INFO
  prefix: ["/"]
plugins:
  $files: ["./plugins"]
  $prelude: ["::auto_reload"]
  .record_message:
    record_send: true
  .commands:
    use_config_prefix: false
  ::auto_reload:
    watch_dirs: ["."]
    watch_config: false
  ::echo: {}
  ::help:
    page_size: null
```

- `basic`: Entari 基础配置
  - `network`: 网络配置, 可写多个网络配置
    - `type`: 网络类型, 可填项有 `ws`, `websocket`, `wh`, `webhook`
    - `host`: satori 服务器地址
    - `port`: satori 服务器端口
    - `path`: satori 服务器路径
  - `ignore_self_message`: 是否忽略自己发送的消息事件
  - `log`: 日志配置
    - `level`: 日志等级, 可填项有 `TRACE` `DEBUG`, `INFO` 等
  - `prefix`: 指令前缀, 可留空
- `plugins`: 插件配置
  - `$files`: 额外的插件配置文件搜索目录
  - `$prelude`: 预加载插件列表
  - `.record_message`: 消息日志并配置
    - `record_send`: 是否记录发送消息 (默认为 `true`)
  - `.commands`: 指令插件配置 (适用于所有使用了 `command.on/command.command` 的插件)
    - `need_notice_me`: 指令是否需要 @ 机器人
    - `need_reply_me`: 指令是否需要回复机器人
    - `use_config_prefix`: 是否使用配置文件中的前缀
  - `::auto_reload`: 启用自动重载插件并配置
    - `watch_dirs`: 监听目录
    - `watch_config`: 是否监听配置文件的变化 (默认为 `true`)
  - `::echo`: 启用回声插件
  - `::help`: 启用帮助插件并配置
    - `help_command`: 帮助指令, 默认为 `help`
    - `help_alias`: 帮助指令别名, 默认为 `["帮助", "命令帮助"]`
    - `page_size`: 每页显示的指令数量, 留空则不分页

对于其他插件的配置, 有四种写法:

1. `foo.bar: {}` (仅启用插件)
2. `~foo.bar: xxxx` (禁用插件，即加载但不启用)
3. `foo.bar: {"key": "value"}` (启用插件并配置)
4. `?foo.bar: xxxx` (仅存储插件配置, 不加载插件)
