PageSourceSearch

https://docs.ncatbot.xyz/assets/index.html-B1ccP1us.js

js ncatbot.xyz collected 2026-09-25 20:06:15 UTC 60,977 bytes, 87 lines download raw bytes

1import{_ as p,c as d,a as n,d as h,b as a,e as i,w as l,r as e,o as r}from"./app-X5ZAzaQf.js";const g={};function y(A,s){const k=e("Mermaid"),t=e("RouteLink");return r(),d("div",null,[s[9]||(s[9]=n('<blockquote><p>热重载、依赖管理、跨插件交互、多步对话设计、事件驱动工作流编排。</p></blockquote><hr><h2 id="目录" tabindex="-1"><a class="header-anchor" href="#目录"><span>目录</span></a></h2><ul><li><a href="#%E7%83%AD%E9%87%8D%E8%BD%BD%E6%9C%BA%E5%88%B6">热重载机制</a></li><li><a href="#%E6%8F%92%E4%BB%B6%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86">插件依赖管理</a></li><li><a href="#%E8%B7%A8%E6%8F%92%E4%BB%B6%E4%BA%A4%E4%BA%92">跨插件交互</a></li><li><a href="#%E5%A4%9A%E6%AD%A5%E5%AF%B9%E8%AF%9D%E8%AE%BE%E8%AE%A1">多步对话设计</a></li><li><a href="#%E4%BA%8B%E4%BB%B6%E9%A9%B1%E5%8A%A8%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%BC%96%E6%8E%92">事件驱动工作流编排</a></li></ul><hr><h2 id="热重载机制" tabindex="-1"><a class="header-anchor" href="#热重载机制"><span>热重载机制</span></a></h2><p>NcatBot 支持开发时修改插件代码后自动重载,无需重启整个 Bot。</p><h3 id="工作原理" tabindex="-1"><a class="header-anchor" href="#工作原理"><span>工作原理</span></a></h3>',8)),h(k,{id:"mermaid-46",code:"eJyN0b9PwkAUB/Cdv+KNddA/oAOTIQ7EFBcGYy6X8oCL7R3e9YhuLoCGGIgD0Zi4YAKTYVBjYPB/MbaV/8L22gARB2+6H5+89745hWcauYv7jDYk9QuQrBaVAXNZi/IASlWgCkrMwyoN3CbKLVFJwRF6gtagolHjlnDKKXE83WC8nLA/ijhrUTCPpepusViq2hCNL6PXfng1i0a9r8VbOLiLHl7WpGJDSwdWXXhJWcKpjztwHM8/4m
1k/fL4OO9MTYysJdco2EGkGJa7gSvsorR0IB6OwNzfKKafMBs0Napl5LFPUvB+KAEG0UUKCCMkZSfauJxQS+OzeguDZyRx8ds54DjdaJJNIbItTzHuAFU8Wy/snOKC85qHM2q1s3sgXNe0hWNF7Jx52QV2ovexK/fISlUs58SlndVQBWMveTTSafU/G0eNw09rwr6BiFTTLY/46jUcYZ8Eq9nbIuqdVE5pZKFX4Aaw04R0="}),s[10]||(s[10]=n(`<h3 id="流程" tabindex="-1"><a class="header-anchor" href="#流程"><span>流程</span></a></h3><ol><li><strong><code>effective_hot_reload()</code></strong> 为真时,<strong>FileWatcherService</strong> 监控 <code>plugins/</code>(或配置的 <code>plugin.plugins_dir</code>)下的文件变更</li><li>检测到变化后,将变更的文件夹名放入 <code>_reload_queue</code>(线程安全)</li><li><strong><code>_reload_consumer</code></strong> 异步任务从队列中取出,映射到插件名</li><li>执行完整的 <strong>卸载 → 重新扫描 → 加载</strong> 周期</li></ol><h3 id="开发体验" tabindex="-1"><a class="header-anchor" href="#开发体验"><span>开发体验</span></a></h3><p>在启用热重载(<code>plugin.hot_reload: true</code> 且未被 CLI 关闭)时,修改插件代码后保存文件,Bot 自动完成重载——无需手动重启(与是否开启 <code>debug</code> 无关)。</p><h3 id="注意事项" tabindex="-1"><a class="header-anchor" href="#注意事项"><span>注意事项</span></a></h3><ul><li>热重载会执行完整的卸载/加载周期:<strong><code>on_close()</code> → Mixin 保存 → 清理 → 重新加载 → <code>on_load()</code></strong></li><li>全局变量会被重置——状态应保存在 <code>self.data</code> 中(DataMixin 自动持久化)</li><li>Handler 会被撤销并重新注册——确保所有 Handler 都在类定义或 <code>on_load()</code> 中注册</li><li><code>__pycache__</code> 会被自动清除,确保新代码生效</li></ul><hr><h2 id="插件依赖管理" tabindex="-1"><a class="header-anchor" href="#插件依赖管理"><span>插件依赖管理</span></a></h2><h3 id="插件间依赖" tabindex="-1"><a class="header-anchor" href="#插件间依赖"><span>插件间依赖</span></a></h3><p>在 <code>manifest.toml</code> 中通过 <code>[dependencies]</code> 声明对其他插件的依赖:</p><div class="language-toml line-numbers-mode" data-ext="toml" data-title="toml"><button class="copy" title="复制代码" data-copied="已复制"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">[</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">dependencies</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">]</span></span>
2<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">rbac</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&gt;=1.0.0</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span></span>
3<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">config_manager</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&gt;=0.5.0</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="拓扑排序" tabindex="-1"><a class="header-anchor" href="#拓扑排序"><span>拓扑排序</span></a></h3><p>框架使用 <strong>Kahn 算法</strong>对所有插件进行拓扑排序,确保被依赖的插件先加载:</p><div class="language-yaml line-numbers-mode" data-ext="yaml" data-title="yaml"><button class="copy" title="复制代码" data-copied="已复制"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">如果 A 依赖 B,B 依赖 C:</span></span>
4<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965;">加载顺序</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;"> C → B → A</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="错误检测" tabindex="-1"><a class="header-anchor" href="#错误检测"><span>错误检测</span></a></h3><table><thead><tr><th>
4错误类型</th><th>说明</th></tr></thead><tbody><tr><td><code>PluginMissingDependencyError</code></td><td>依赖的插件不存在</td></tr><tr><td><code>PluginCircularDependencyError</code></td><td>检测到循环依赖(A → B → A)</td></tr><tr><td><code>PluginVersionError</code></td><td>版本约束不满足</td></tr></tbody></table><h3 id="pip-依赖" tabindex="-1"><a class="header-anchor" href="#pip-依赖"><span>pip 依赖</span></a></h3><p>在 <code>manifest.toml</code> 的 <code>[pip_dependencies]</code> 中声明 Python 包依赖:</p><div class="language-toml line-numbers-mode" data-ext="toml" data-title="toml"><button class="copy" title="复制代码" data-copied="已复制"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">[</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">pip_dependencies</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">]</span></span>
5<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">aiohttp</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&gt;=3.8.0</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span></span>
6<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">beautifulsoup4</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&gt;=4.12.0</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>框架在加载时会自动检查这些包是否已安装,未安装时提示用户确认安装。</p>`,20)),a("blockquote",null,[a("p",null,[s[1]||(s[1]=i("示例:")),h(t,{to:"/examples/common/06_external_api/"},{default:l(()=>s[0]||(s[0]=[i("examples/common/06_external_api/manifest.toml")])),_:1}),s[2]||(s[2]=i(" 声明了 ")),s[3]||(s[3]=a("code",null,"aiohttp",-1)),s[4]||(s[4]=i(" 依赖。"))])]),s[11]||(s[11]=n(`<h3 id="版本约束语法" tabindex="-1"><a class="header-anchor" href="#版本约束语法"><span>版本约束语法</span></a></h3><p>使用 Python <code>packaging.specifiers</code> 标准语法:</p><table><thead><tr><th>语法</th><th>含义</th></tr></thead><tbody><tr><td><code>&gt;=1.0.0</code></td><td>大于等于 1.0.0</td></tr><tr><td><code>&gt;=1.0.0,&lt;2.0.0</code></td><td>大于等于 1.0.0 且小于 2.0.0</td></tr><tr><td><code>==1.2.3</code></td><td>精确匹配</td></tr><tr><td><code>~=1.4</code></td><td>兼容版本(≥1.4, &lt;2.0)</td></tr></tbody></table><hr><h2 id="跨插件交互" tabindex="-1"><a class="header-anchor" href="#跨插件交互"><span>跨插件交互</span></a></h2><h3 id="获取其他插件实例" tabindex="-1"><a class="header-anchor" href="#获取其他插件实例"><span>获取其他插件实例</span></a></h3><div class="language-python line-numbers-mode" data-ext="python" data-title="python"><button class="copy" title="复制代码" data-copied="已复制"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">class</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994;"> MyPlugin</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">NcatBotPlugin</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">):</span></span>
7<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">    name </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">my_plugin</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span></span>
8<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">    version </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">1.0.0</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span></span>
9<span class="line"></span>
10<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    async</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> def</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> on_load</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">
10self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">):</span></span>
11<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">        # 获取其他插件实例</span></span>
12<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        rbac_plugin </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">get_plugin</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">rbac</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
13<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        if</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> rbac_plugin</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
14<span class="line"><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">            LOG</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">info</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">RBAC 插件已加载: </span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">%s</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> rbac_plugin</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">version</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
15<span class="line"></span>
16<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">        # 列出所有已加载插件</span></span>
17<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        all_plugins </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">list_plugins</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">()</span></span>
18<span class="line"><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">        LOG</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">info</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">已加载插件: </span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">%s</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> all_plugins</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="跨插件-python-导入" tabindex="-1"><a class="header-anchor" href="#跨插件-python-导入"><span>跨插件 Python 导入</span></a></h3><p>框架将 <code>plugins/</code> 目录添加到 <code>sys.path</code>,每个插件文件夹相当于一个 Python 包。因此可以直接导入其他插件的模块:</p><div class="language-python line-numbers-mode" data-ext="python" data-title="python"><button class="copy" title="复制代码" data-copied="已复制"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;"># 在 plugin_a/main.py 中导入 plugin_b 的模块</span></span>
19<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">from</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> plugin_b</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">utils </span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">
19import</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> some_helper</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>注意</strong>:</p><ul><li>使用跨插件导入时,务必在 <code>manifest.toml</code> 中声明依赖关系,确保加载顺序正确</li><li>插件根目录在 <code>sys.path</code> 中的优先级低于标准库和第三方包</li></ul><hr><h2 id="多步对话设计" tabindex="-1"><a class="header-anchor" href="#多步对话设计"><span>多步对话设计</span></a></h2><p>多步对话是 Bot 开发中的常见需求——通过 <code>wait_event()</code> 串联多轮交互。</p><h3 id="设计模式" tabindex="-1"><a class="header-anchor" href="#设计模式"><span>设计模式</span></a></h3>`,16)),h(k,{id:"mermaid-269",code:"eJxLy8kvT85ILCpRCHHiUgACZ1+X6OdTVjzr2P60f+LLhsanE/c+2b0kVkFX104hOMQ1wDD62dqlL1ctUTC0UnixftHL6etiwfrAcmBV4Y6eIYbR5YmZJfGpZal5JVYKz9d2Pt3X+nT2vKdLeiGqwWpAqmtebGt9Nn1bjYKzo5+zq0/00/5pz7Z1oCtSgggrwZShST+b0/lsagfE/BqwS4xgrjQC2r57+fPda9HdagR3qxERbgWrRnMrmiSqI5z9/dw8g3yjny9c92LdEohjIMZBZSAB6hjmGv1k/9yna2c8m7rhWS/QfQB1eafo"}),s[12]||(s[12]=n(`<h3 id="封装辅助方法" tabindex="-1"><a class="header-anchor" href="#封装辅助方法"><span>封装辅助方法</span></a></h3><p>推荐将 <code>wait_event</code> 的通用逻辑封装为辅助方法:</p><div class="language-python line-numbers-mode" data-ext="python" data-title="python"><button class="copy" title="复制代码" data-copied="已复制"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">TIMEOUT</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;"> 30</span><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">  # 每步超时秒数</span></span>
20<span class="line"></span>
21<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">async</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> def</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> _wait_user_reply</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> group_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> user_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">):</span></span>
22<span class="line"><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">    &quot;&quot;&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">等待指定用户在指定群的下一条消息</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;&quot;&quot;</span></span>
23<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">    event </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;"> await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">wait_event</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span></span>
24<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">        predicate</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">lambda</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> e</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> (</span></span>
25<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965;">            hasattr</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">e</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">user_id</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
26<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">            and</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;"> str</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">e</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">user_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> ==</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;"> str</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">user_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
27<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">            and</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;"> hasattr</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">e</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">group_id</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
28<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">            and</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;"> str</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">e</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">group_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> ==</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;"> str</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">group_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
29<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">            and</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;"> hasattr</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">e</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">raw_message</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
30<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">        ),</span></span>
31<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">        timeout</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">
31TIMEOUT</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span></span>
32<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    )</span></span>
33<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    return</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> event</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">raw_message</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">strip</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">()</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="完整多步对话示例" tabindex="-1"><a class="header-anchor" href="#完整多步对话示例"><span>完整多步对话示例</span></a></h3><div class="language-python line-numbers-mode" data-ext="python" data-title="python"><button class="copy" title="复制代码" data-copied="已复制"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">@</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">registrar</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">on_group_command</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">注册</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
34<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">async</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> def</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> on_register</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> event</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> GroupMessageEvent</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">):</span></span>
35<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">    gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> uid </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> event</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">group_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> event</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">user_id</span></span>
36<span class="line"></span>
37<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">    # 步骤 1: 询问名字</span></span>
38<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    await</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> event</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">reply</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">f</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&quot;📝 请输入你的名字(</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">{TIMEOUT}</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">秒内回复,输入「取消」退出):&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
39<span class="line"></span>
40<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    try</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
41<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        name </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;"> await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">_wait_user_reply</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> uid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
42<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    except</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> asyncio</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">TimeoutError</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
43<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">
43post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">⏰ 注册超时,已取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
44<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span></span>
45<span class="line"></span>
46<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    if</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> name </span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">==</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
47<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">❌ 注册已取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
48<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span></span>
49<span class="line"></span>
50<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">    # 步骤 2: 询问年龄</span></span>
51<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">f</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&quot;好的,</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">{</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">name</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">}</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">!请输入你的年龄:&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
52<span class="line"></span>
53<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    try</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
54<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        age_str </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;"> await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">_wait_user_reply</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> uid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
55<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    except</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> asyncio</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">TimeoutError</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
56<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">
56post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">⏰ 注册超时,已取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
57<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span></span>
58<span class="line"></span>
59<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    if</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> age_str </span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">==</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
60<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">❌ 注册已取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
61<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span></span>
62<span class="line"></span>
63<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    if</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> not</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> age_str</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">isdigit</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">():</span></span>
64<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">❌ 年龄必须是数字,注册已取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
65<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span></span>
66<span class="line"></span>
67<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">    age </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;"> int</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">age_str</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
68<span class="line"></span>
69<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">    # 步骤 3: 确认</span></span>
70<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">
70post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span></span>
71<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span></span>
72<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">        text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">f</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&quot;请确认你的信息:</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">\\n</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">  名字: </span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">{</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">name</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">}\\n</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">  年龄: </span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">{</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">age</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">}\\n</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">回复「确认」完成注册:&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span></span>
73<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    )</span></span>
74<span class="line"></span>
75<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    try</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
76<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        confirm </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;"> await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">_wait_user_reply</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> uid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
77<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    except</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> asyncio</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">TimeoutError</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
78<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">⏰ 确认超时,已取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
79<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span></span>
80<span class="line"></span>
81<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    if</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> confirm </span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">!=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">确认</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span></span>
82<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">
82post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">❌ 注册已取消</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
83<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span></span>
84<span class="line"></span>
85<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">    # 保存数据</span></span>
86<span class="line"><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">    self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">setdefault</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">users</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {})[</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965;">str</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">uid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)]</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">name</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> name</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;"> &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">age</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">:</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> age</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">}</span></span>
87<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    await</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> self</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">api</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">qq</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">post_group_msg</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">gid</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> text</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">f</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">&quot;✅ 注册成功!欢迎你,</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">
87{</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">name</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">}</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">(</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">{</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">age</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">}</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">岁)&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>`,5)),a("blockquote",null,[a("p",null,[s[6]||(s[6]=i("完整代码:")),h(t,{to:"/examples/qq/07_dialog_and_menu/"},{default:l(()=>s[5]||(s[5]=[i("examples/qq/07_dialog_and_menu/main.py")])),_:1})])]),s[13]||(s[13]=n('<h3 id="设计要点" tabindex="-1"><a class="header-anchor" href="#设计要点"><span>设计要点</span></a></h3><table><thead><tr><th>要点</th><th>说明</th></tr></thead><tbody><tr><td><strong>超时处理</strong></td><td>每步都应设置超时(<code>asyncio.TimeoutError</code>)</td></tr><tr><td><strong>取消机制</strong></td><td>检测用户输入&quot;取消&quot;以退出流程</td></tr><tr><td><strong>输入验证</strong></td><td>在每步验证输入合法性</td></tr><tr><td><strong>状态持久化</strong></td><td>结果保存到 <code>self.data</code>(DataMixin)</td></tr><tr><td><strong>用户隔离</strong></td><td><code>predicate</code> 中限定 <code>user_id</code> + <code>group_id</code></td></tr></tbody></table><hr><h2 id="事件驱动工作流编排" tabindex="-1"><a class="header-anchor" href="#事件驱动工作流编排"><span>事件驱动工作流编排</span></a></h2><p>当需求超越线性多步对话——需要等待生命周期事件、并发协调多个任务、或在非插件模式下用 <code>run_async()</code> 自行编排——本节提供常见模式。</p><h3 id="何时用装饰器-vs-wait-event-编排" tabindex="-1"><a class="header-anchor" href="#何时用装饰器-vs-wait-event-编排"><span>何时用装饰器 vs wait_event 编排</span></a></h3><table><thead><tr><th>场景</th><th>推荐方式</th><th>原因</th></tr></thead><tbody><tr><td>单命令 → 单响应</td><td>装饰器(模式 A)</td><td>声明式,框架自动路由</td></tr><tr><td>命令 → 等用户回复 → 完成</td><td>装饰器触发 + <code>wait_event</code></td><td>线性流程,handler 内顺序执行</td></tr><tr><td>启动后自定义编排逻辑</td><td><code>run_async()</code> + dispatcher</td><td>脱离插件体系,完全掌控执行流</td></tr><tr><td>后台持续监控 + 按条件触发</td><td><code>events()</code> 流 + <code>create_task</code></td><td>响应式,长期运行</td></tr><tr><td>多人并发输入收集</td><td>多个 <code>wait_event</code> + <code>asyncio.wait</code></td><td>并发等待,先到先得</td></tr></tbody></table><hr><h2 id="下一步" tabindex="-1"><a class="header-anchor" href="#下一步"><span>下一步</span></a></h2>',9)),a("ul",null,[a("li",null,[h(t,{to:"/notes/guide/3.%20%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91/11.%20%E6%A1%88%E4%BE%8B%E7%A0%94%E7%A9%B6.html"},{default:l(()=>s[7]||(s[7]=[i("实战案例与调试")])),_:1}
87),s[8]||(s[8]=i(" — 综合实战案例分析、调试与排查"))])])])}const c=p(g,[["render",y],["__file","index.html.vue"]]),D=JSON.parse('{"path":"/guide/uwanjc8v/","title":"高级模式","lang":"zh-CN","frontmatter":{"title":"高级模式","createTime":"2026/03/19 17:26:45","permalink":"/guide/uwanjc8v/","description":"热重载、依赖管理、跨插件交互、多步对话设计、事件驱动工作流编排。 目录 热重载机制 插件依赖管理 跨插件交互 多步对话设计 事件驱动工作流编排 热重载机制 NcatBot 支持开发时修改插件代码后自动重载,无需重启整个 Bot。 工作原理 流程 effective_hot_reload() 为真时,FileWatcherService 监控 plugi...","head":[["meta",{"property":"og:url","content":"http://docs.ncatbot.xyz/guide/uwanjc8v/"}],["meta",{"property":"og:site_name","content":"NcatBot 文档"}],["meta",{"property":"og:title","content":"高级模式"}],["meta",{"property":"og:description","content":"热重载、依赖管理、跨插件交互、多步对话设计、事件驱动工作流编排。 目录 热重载机制 插件依赖管理 跨插件交互 多步对话设计 事件驱动工作流编排 热重载机制 NcatBot 支持开发时修改插件代码后自动重载,无需重启整个 Bot。 工作原理 流程 effective_hot_reload() 为真时,FileWatcherService 监控 plugi..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2026-04-17T14:13:00.000Z"}],["meta",{"property":"article:modified_time","content":"2026-04-17T14:13:00.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"高级模式\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2026-04-17T14:13:00.000Z\\",\\"author\\":[]}"]]},"headers":[],"readingTime":{"minutes":5.32,"words":1596},"git":{"updatedTime":1776435180000,"contributors":[{"name":"GEYUANwuqi","username":"GEYUANwuqi","email":"[email protected]","commits":1,"avatar":"https://gravatar.com/avatar/1cf26d82e91dff657f3fa4d4911cdabcf7b76396339e886e69f99b15d4c8c808?d=retro"}]},"autoDesc":true,"filePathRelative":"notes/guide/3. 插件开发/10. 模式.md"}');export{c as comp,D as data};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.