{"id":25858767,"url":"https://github.com/arcletproject/entari","last_synced_at":"2026-03-09T03:02:41.186Z","repository":{"id":57411317,"uuid":"442723483","full_name":"ArcletProject/Entari","owner":"ArcletProject","description":"A simple IM framework based on Satori Protocol. 基于 Satori 跨平台协议的 IM 框架","archived":false,"fork":false,"pushed_at":"2026-03-06T09:53:15.000Z","size":1494,"stargazers_count":31,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-06T13:57:14.171Z","etag":null,"topics":["asyncio","bot","bot-framework","chatbot","python","satori","satori-protocol"],"latest_commit_sha":null,"homepage":"https://arclet.top","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ArcletProject.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-12-29T09:29:38.000Z","updated_at":"2026-03-06T09:53:20.000Z","dependencies_parsed_at":"2023-12-05T15:42:03.984Z","dependency_job_id":"fc37350e-62af-41a8-884a-a1bfa6967c87","html_url":"https://github.com/ArcletProject/Entari","commit_stats":{"total_commits":65,"total_committers":2,"mean_commits":32.5,"dds":0.3538461538461538,"last_synced_commit":"765e38f131ca89e7339a38b9dace85700c408140"},"previous_names":["arcletproject/entari","arcletproject/edoves"],"tags_count":65,"template":false,"template_full_name":null,"purl":"pkg:github/ArcletProject/Entari","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcletProject%2FEntari","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcletProject%2FEntari/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcletProject%2FEntari/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcletProject%2FEntari/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ArcletProject","download_url":"https://codeload.github.com/ArcletProject/Entari/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcletProject%2FEntari/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30281165,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncio","bot","bot-framework","chatbot","python","satori","satori-protocol"],"created_at":"2025-03-01T20:33:25.734Z","updated_at":"2026-03-09T03:02:41.150Z","avatar_url":"https://github.com/ArcletProject.png","language":"Python","readme":"\u003cdiv align=\"center\"\u003e \n  \n# Entari\n\n  \u003e _lí no etheclim, nann ze entám rish._\n\n![Entari](https://img.shields.io/badge/Arclet-Entari-2564c2.svg)\n[![Licence](https://img.shields.io/github/license/ArcletProject/Entari)](https://github.com/ArcletProject/Entari/blob/main/LICENSE)\n[![PyPI](https://img.shields.io/pypi/v/arclet-entari)](https://pypi.org/project/arclet-entari)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/arclet-entari)](https://www.python.org/)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ArcletProject/Entari)\n[![Docs](https://img.shields.io/badge/docs-arclet.top-28d178)](https://arclet.top/tutorial/entari/)\n[![QQ 群](https://img.shields.io/badge/QQ-654490750-yellow.svg)](https://jq.qq.com/?_wv=1027\u0026k=PUPOnCSH)\n\n\u003c/div\u003e\n\n\n一个基于 `Satori` 协议的灵活、高效的 IM framework\n\n## 特性\n\n- 基于 Satori 协议，一份代码即可对接多种平台\n- 异步并发，基于 Python 的异步特性，即使有大量的事件传入，也能吞吐自如。在常规使用下能达到1000+ RPS\n- 易上手的开发体验，没有过多的冗余代码，可以让开发者专注于业务逻辑\n- 既可集成式也可分布式的配置文件，内建且可拓展的配置模型\n- 即插即拔，可热重载、可重用的插件机制\n- 自定义服务、自定义事件等高度可拓展的功能\n- 高度可拓展的事件响应器，能够依托强大的、符合直觉依赖注入进行会话控制\n- 内置强大的命令系统、定时任务系统与多种插件\n\n## 示例\n\n使用 `entari-cli` 命令行:\n```shell\n# 创建新的 entari 项目\n$ entari init\n是否创建新的虚拟环境? (Y/n): Y\n请输入要选择的 Python 解释器路径\n 0. cpython@3.11 (...)\n 1. ...\n请选择 (0): 0\n虚拟环境将创建在 ...\n...\n```\n```shell\n# 运行\n$ entari run\n```\n\n使用的配置文件:\n```yaml\n# entari.yml\nbasic:\n  network:\n    - type: ws\n      host: \"127.0.0.1\"\n      port: 5140\n      path: \"satori\"\n  ignore_self_message: true\n  log:\n    level: INFO\n  prefix: [\"/\"]\nplugins:\n  $prelude:\n    - ::auto_reload\n  .record_message: {}\n  ::auto_reload:\n    watch_dirs: [\".\"]\n  ::help: {}\n  ::echo: {}\n  ::inspect: {}\n```\n\n复读:\n\n```python\nfrom arclet.entari import Session, Entari, WS\n\napp = Entari(WS(host=\"127.0.0.1\", port=5140, path=\"satori\"))\n\n@app.on_message()\nasync def repeat(session: Session):\n    await session.send(session.content)\n\n\napp.run()\n```\n\n指令 `add {a} {b}`:\n\n```python\nfrom arclet.entari import Entari, WS, command\n\n@command.on(\"add {a} {b}\")\ndef add(a: int, b: int):\n    return f\"{a + b = }\"\n\n\napp = Entari(WS(port=5500, token=\"XXX\"))\napp.run()\n```\n\n编写插件:\n\n```python\nfrom arclet.entari import BasicConfModel, Session, MessageCreatedEvent, plugin\n\n\nclass Config(BasicConfModel):\n    name: str\n\n\nplugin.metadata(\n    name=\"Hello, World!\",\n    author=[\"Arclet\"],\n    version=\"0.1.0\",\n    description=\"A simple plugin that replies 'Hello, World!' to every message.\",\n    config=Config\n)\n# or __plugin_metadata__ = PluginMetadata(...)\n\nconfig = plugin.get_config(Config)\n\n@plugin.listen(MessageCreatedEvent)  # or plugin.dispatch(MessageCreatedEvent)\nasync def _(session: Session):\n    await session.send(f\"Hello, World! {config.name}\")\n```\n\n加载插件:\n\n```diff\n# entari.yml\nplugins:\n  $prelude:\n    - ::auto_reload\n  .record_message: {}\n  ::auto_reload:\n    watch_dirs: [\".\"]\n  ::help: {}\n  ::echo: {}\n  ::inspect: {}\n++ example_plugin: {}  # 加载 example_plugin 插件\n```\n\n在其他插件中导入插件:\n\n```python\nfrom arclet.entari import command, MessageChain, Image\nfrom entari_plugin_browser import md2img  # entari: plugin\n\n\n@command.on(\"md2img {content}\")\nasync def _(content: str):\n    return MessageChain(Image.of(raw=await md2img(content)))\n```\n\n\n## 配置文件\n\n```yaml\nbasic:\n  network:\n    - type: ws\n      host: \"127.0.0.1\"\n      port: 5140\n      path: \"satori\"\n  ignore_self_message: true\n  log:\n    level: INFO\n  prefix: [\"/\"]\nplugins:\n  $files: [\"./plugins\"]\n  $prelude: [\"::auto_reload\"]\n  .record_message:\n    record_send: true\n  .commands:\n    use_config_prefix: false\n  ::auto_reload:\n    watch_dirs: [\".\"]\n    watch_config: false\n  ::echo: {}\n  ::help:\n    page_size: null\n```\n\n- `basic`: Entari 基础配置\n  - `network`: 网络配置, 可写多个网络配置\n    - `type`: 网络类型, 可填项有 `ws`, `websocket`, `wh`, `webhook`\n    - `host`: satori 服务器地址\n    - `port`: satori 服务器端口\n    - `path`: satori 服务器路径\n  - `ignore_self_message`: 是否忽略自己发送的消息事件\n  - `log`: 日志配置\n    - `level`: 日志等级, 可填项有 `TRACE` `DEBUG`, `INFO` 等\n  - `prefix`: 指令前缀, 可留空\n- `plugins`: 插件配置\n  - `$files`: 额外的插件配置文件搜索目录\n  - `$prelude`: 预加载插件列表\n  - `.record_message`: 消息日志并配置\n    - `record_send`: 是否记录发送消息 (默认为 `true`)\n  - `.commands`: 指令插件配置 (适用于所有使用了 `command.on/command.command` 的插件)\n    - `need_notice_me`: 指令是否需要 @ 机器人\n    - `need_reply_me`: 指令是否需要回复机器人\n    - `use_config_prefix`: 是否使用配置文件中的前缀\n  - `::auto_reload`: 启用自动重载插件并配置\n    - `watch_dirs`: 监听目录\n    - `watch_config`: 是否监听配置文件的变化 (默认为 `true`)\n  - `::echo`: 启用回声插件\n  - `::help`: 启用帮助插件并配置\n    - `help_command`: 帮助指令, 默认为 `help`\n    - `help_alias`: 帮助指令别名, 默认为 `[\"帮助\", \"命令帮助\"]`\n    - `page_size`: 每页显示的指令数量, 留空则不分页\n\n对于其他插件的配置, 有四种写法:\n\n1. `foo.bar: {}` (仅启用插件)\n2. `~foo.bar: xxxx` (禁用插件，即加载但不启用)\n3. `foo.bar: {\"key\": \"value\"}` (启用插件并配置)\n4. `?foo.bar: xxxx` (仅存储插件配置, 不加载插件)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcletproject%2Fentari","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farcletproject%2Fentari","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcletproject%2Fentari/lists"}