From 0e8d52b59193c3e136670d7942b2d2991bc7d00d Mon Sep 17 00:00:00 2001 From: Futureppo Date: Wed, 26 Mar 2025 16:40:25 +0800 Subject: [PATCH 01/21] =?UTF-8?q?:ballon:=20feat:=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=8E=89=20/model=20=E5=8F=AF=E8=83=BD=E6=9A=B4=E9=9C=B2?= =?UTF-8?q?=E7=9A=84=20api=5Fkey?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed: 更新正则表达式 :balloon: auto fixes by pre-commit hooks Update main.py Update main.py chore: bugfixes --- packages/astrbot/main.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/astrbot/main.py b/packages/astrbot/main.py index b0f51d98f..1f5f23cd8 100644 --- a/packages/astrbot/main.py +++ b/packages/astrbot/main.py @@ -2,6 +2,7 @@ import aiohttp import datetime import builtins import traceback +import re import astrbot.api.star as star import astrbot.api.event.filter as filter from astrbot.api.event import AstrMessageEvent, MessageEventResult @@ -13,6 +14,7 @@ from astrbot.core.provider.sources.dify_source import ProviderDify from astrbot.core.utils.io import download_dashboard, get_dashboard_version from astrbot.core.star.star_handler import star_handlers_registry, StarHandlerMetadata from astrbot.core.star.star import star_map +from astrbot.core.star.star_manager import PluginManager from astrbot.core.star.filter.command import CommandFilter from astrbot.core.star.filter.command_group import CommandGroupFilter from astrbot.core.star.filter.permission import PermissionTypeFilter @@ -196,7 +198,29 @@ class Main(star.Star): return await self.context._star_manager.turn_on_plugin(oper2) event.set_result(MessageEventResult().message(f"插件 {oper2} 已启用。")) + elif oper1 == "get": + if not oper2: + raise Exception("请输入插件地址。") + if not event.is_admin(): + raise Exception( + "改指令限制仅管理员使用,且无法通过 /alter_cmd 更改。" + ) + if not oper2.startswith("http"): + oper2 = f"https://github.com/{oper2}" + logger.info(f"准备从 {oper2} 获取插件。") + + if self.context._star_manager: + star_mgr: PluginManager = self.context._star_manager + try: + await star_mgr.install_plugin(oper2) + event.set_result(MessageEventResult().message("获取插件成功。")) + except Exception as e: + logger.error(f"获取插件失败: {e}") + event.set_result( + MessageEventResult().message(f"获取插件失败: {e}") + ) + return else: # 获取插件帮助 plugin = self.context.get_registered_star(oper1) @@ -497,15 +521,20 @@ UID: {user_id} 此 ID 可用于设置管理员。 MessageEventResult().message("未找到任何 LLM 提供商。请先配置。") ) return + # 定义正则表达式匹配 API 密钥 + api_key_pattern = re.compile(r"key=[^&'\" ]+") if idx_or_name is None: models = [] try: models = await self.context.get_using_provider().get_models() except BaseException as e: + err_msg = api_key_pattern.sub( + "key=***", str(e) + ) message.set_result( MessageEventResult() - .message("获取模型列表失败: " + str(e)) + .message("获取模型列表失败: " + err_msg) .use_t2i(False) ) return From a38b00be6bbeaed947fc02ddded511984d367617 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 26 Mar 2025 13:41:18 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=F0=9F=90=9B=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=83=A8=E5=88=86=E5=8F=AF=E8=83=BD=E5=BD=A2=E6=88=90=20SQL=20?= =?UTF-8?q?=E6=B3=A8=E5=85=A5=E7=9A=84=E9=A3=8E=E9=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/db/sqlite.py | 33 +++++++++---------- astrbot/core/db/sqlite_init.sql | 8 +++-- .../process_stage/method/llm_request.py | 2 +- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/astrbot/core/db/sqlite.py b/astrbot/core/db/sqlite.py index 98e6af04e..65d68526e 100644 --- a/astrbot/core/db/sqlite.py +++ b/astrbot/core/db/sqlite.py @@ -128,24 +128,23 @@ class SQLiteDatabase(BaseDatabase): except sqlite3.ProgrammingError: c = self._get_conn(self.db_path).cursor() - where_clause = "" - if session_id or provider_type: - where_clause += " WHERE " - has = False - if session_id: - where_clause += f"session_id = '{session_id}'" - has = True - if provider_type: - if has: - where_clause += " AND " - where_clause += f"provider_type = '{provider_type}'" + conditions = [] + params = [] + + if session_id: + conditions.append("session_id = ?") + params.append(session_id) + + if provider_type: + conditions.append("provider_type = ?") + params.append(provider_type) + + sql = "SELECT * FROM llm_history" + if conditions: + sql += " WHERE " + " AND ".join(conditions) + + c.execute(sql, params) - c.execute( - """ - SELECT * FROM llm_history - """ - + where_clause - ) res = c.fetchall() histories = [] for row in res: diff --git a/astrbot/core/db/sqlite_init.sql b/astrbot/core/db/sqlite_init.sql index 900f4f2c0..a1ebc54b5 100644 --- a/astrbot/core/db/sqlite_init.sql +++ b/astrbot/core/db/sqlite_init.sql @@ -38,11 +38,13 @@ CREATE TABLE IF NOT EXISTS atri_vision( ); CREATE TABLE IF NOT EXISTS webchat_conversation( - user_id TEXT, - cid TEXT, + user_id TEXT, -- 会话 id + cid TEXT, -- 对话 id history TEXT, created_at INTEGER, updated_at INTEGER, title TEXT, persona_id TEXT -); \ No newline at end of file +); + +PRAGMA encoding = 'UTF-8'; \ No newline at end of file diff --git a/astrbot/core/pipeline/process_stage/method/llm_request.py b/astrbot/core/pipeline/process_stage/method/llm_request.py index 872875e8f..8d606d9e5 100644 --- a/astrbot/core/pipeline/process_stage/method/llm_request.py +++ b/astrbot/core/pipeline/process_stage/method/llm_request.py @@ -128,7 +128,7 @@ class LLMRequestSubStage(Stage): # max context length if ( - self.max_context_length != -1 # -1 为不限制 + self.max_context_length != -1 # -1 为不限制 and len(req.contexts) // 2 > self.max_context_length ): logger.debug("上下文长度超过限制,将截断。") From 89d3fd5fab001b07570a655f75d30b55701f6859 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 26 Mar 2025 13:50:11 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=F0=9F=8E=88=20perf:=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20WebUI=20=E5=AF=B9=E8=AF=9D=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E5=8E=86=E5=8F=B2=E6=A3=80=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/db/sqlite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/astrbot/core/db/sqlite.py b/astrbot/core/db/sqlite.py index 65d68526e..3a4f6c1b8 100644 --- a/astrbot/core/db/sqlite.py +++ b/astrbot/core/db/sqlite.py @@ -491,6 +491,7 @@ class SQLiteDatabase(BaseDatabase): # 搜索关键词 if search_query: + search_query = search_query.encode("unicode_escape").decode("utf-8") where_clauses.append( "(title LIKE ? OR user_id LIKE ? OR cid LIKE ? OR history LIKE ?)" ) From e0f029e2cb8de64f1522ef1afe1dfdc5a017f2d3 Mon Sep 17 00:00:00 2001 From: Gao Jinzhe <2968474907@qq.com> Date: Sun, 23 Mar 2025 14:35:44 +0800 Subject: [PATCH 04/21] Add files via upload --- packages/session_controller/main.py | 44 +++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/session_controller/main.py b/packages/session_controller/main.py index 89a98dca0..f73d87be5 100644 --- a/packages/session_controller/main.py +++ b/packages/session_controller/main.py @@ -1,5 +1,6 @@ import astrbot.api.message_components as Comp import copy +import json from astrbot.api import logger from astrbot.api.event import AstrMessageEvent, filter from astrbot.api.star import Context, Star, register @@ -54,8 +55,36 @@ class Waiter(Star): isinstance(messages[0], Comp.Plain) and messages[0].text.strip() in self.wake_prefix ): - yield event.plain_result("想要问什么呢?😄") - + try: + # 尝试使用 LLM 生成更生动的回复 + func_tools_mgr = self.context.get_llm_tool_manager() + + # 获取用户当前的对话信息 + curr_cid = await self.context.conversation_manager.get_curr_conversation_id(event.unified_msg_origin) + conversation = None + context = [] + + if curr_cid: + conversation = await self.context.conversation_manager.get_conversation(event.unified_msg_origin, curr_cid) + context = json.loads(conversation.history) if conversation.history else [] + else: + # 创建新对话 + curr_cid = await self.context.conversation_manager.new_conversation(event.unified_msg_origin) + + # 使用 LLM 生成回复 + yield event.request_llm( + prompt="用户只是@我或唤醒我,请友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。", + func_tool_manager=func_tools_mgr, + session_id=curr_cid, + contexts=context, + system_prompt="", + conversation=conversation + ) + except Exception as e: + logger.error(f"LLM response failed: {str(e)}") + # LLM 回复失败,使用原始预设回复 + yield event.plain_result("想要问什么呢?😄") + @session_waiter(60) async def empty_mention_waiter( controller: SessionController, event: AstrMessageEvent @@ -74,7 +103,16 @@ class Waiter(Star): try: await empty_mention_waiter(event) except TimeoutError as _: - yield event.plain_result("如果需要帮助,请再次 @ 我哦~") + try: + # 超时时也尝试使用 LLM 生成回复 + yield event.request_llm( + prompt="用户在提问后超时未回复,请生成一个温馨友好的提醒,告诉用户如果需要帮助可以再次提问,回答要符合人设。", + func_tool_manager=self.context.get_llm_tool_manager(), + system_prompt="" + ) + except Exception: + # LLM 回复失败,使用原始预设回复 + yield event.plain_result("如果需要帮助,请再次 @ 我哦~") except Exception as e: yield event.plain_result("发生错误,请联系管理员: " + str(e)) finally: From 3f0b6435d9c041fed36261b513c34d7634a1cd96 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 23 Mar 2025 06:39:12 +0000 Subject: [PATCH 05/21] :balloon: auto fixes by pre-commit hooks --- packages/session_controller/main.py | 30 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/session_controller/main.py b/packages/session_controller/main.py index f73d87be5..6bf3f71fb 100644 --- a/packages/session_controller/main.py +++ b/packages/session_controller/main.py @@ -58,19 +58,29 @@ class Waiter(Star): try: # 尝试使用 LLM 生成更生动的回复 func_tools_mgr = self.context.get_llm_tool_manager() - + # 获取用户当前的对话信息 - curr_cid = await self.context.conversation_manager.get_curr_conversation_id(event.unified_msg_origin) + curr_cid = await self.context.conversation_manager.get_curr_conversation_id( + event.unified_msg_origin + ) conversation = None context = [] - + if curr_cid: - conversation = await self.context.conversation_manager.get_conversation(event.unified_msg_origin, curr_cid) - context = json.loads(conversation.history) if conversation.history else [] + conversation = await self.context.conversation_manager.get_conversation( + event.unified_msg_origin, curr_cid + ) + context = ( + json.loads(conversation.history) + if conversation.history + else [] + ) else: # 创建新对话 - curr_cid = await self.context.conversation_manager.new_conversation(event.unified_msg_origin) - + curr_cid = await self.context.conversation_manager.new_conversation( + event.unified_msg_origin + ) + # 使用 LLM 生成回复 yield event.request_llm( prompt="用户只是@我或唤醒我,请友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。", @@ -78,13 +88,13 @@ class Waiter(Star): session_id=curr_cid, contexts=context, system_prompt="", - conversation=conversation + conversation=conversation, ) except Exception as e: logger.error(f"LLM response failed: {str(e)}") # LLM 回复失败,使用原始预设回复 yield event.plain_result("想要问什么呢?😄") - + @session_waiter(60) async def empty_mention_waiter( controller: SessionController, event: AstrMessageEvent @@ -108,7 +118,7 @@ class Waiter(Star): yield event.request_llm( prompt="用户在提问后超时未回复,请生成一个温馨友好的提醒,告诉用户如果需要帮助可以再次提问,回答要符合人设。", func_tool_manager=self.context.get_llm_tool_manager(), - system_prompt="" + system_prompt="", ) except Exception: # LLM 回复失败,使用原始预设回复 From a604b4943c813a6219d2796811d9126c84ae4560 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 26 Mar 2025 14:13:57 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=F0=9F=8E=88=20perf:=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=96=B0=E7=89=88=E6=9C=AC=E6=97=B6=E7=9A=84=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/zip_updator.py | 2 +- .../full/vertical-header/VerticalHeader.vue | 51 ++++++++++++++++--- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/astrbot/core/zip_updator.py b/astrbot/core/zip_updator.py index 4622b47cd..23ff3ba76 100644 --- a/astrbot/core/zip_updator.py +++ b/astrbot/core/zip_updator.py @@ -23,7 +23,7 @@ class ReleaseInfo: self.body = body def __str__(self) -> str: - return f"新版本: {self.version}, 发布于: {self.published_at}, 详细内容: {self.body}" + return f"\n{self.body}\n\n版本: {self.version} | 发布于: {self.published_at}" class RepoZipUpdator: diff --git a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue index 3d08c9cd6..014191945 100644 --- a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue +++ b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue @@ -5,6 +5,7 @@ import axios from 'axios'; import { md5 } from 'js-md5'; import { useAuthStore } from '@/stores/auth'; import { useCommonStore } from '@/stores/common'; +import { marked } from 'marked'; const customizer = useCustomizerStore(); let dialog = ref(false); @@ -15,6 +16,7 @@ let newPassword = ref(''); let newUsername = ref(''); let status = ref(''); let updateStatus = ref('') +let releaseMessage = ref(''); let hasNewVersion = ref(false); let botCurrVersion = ref(''); let dashboardHasNewVersion = ref(false); @@ -81,7 +83,13 @@ function checkUpdate() { axios.get('/api/update/check') .then((res) => { hasNewVersion.value = res.data.data.has_new_version; - updateStatus.value = res.data.message; + + if (res.data.data.has_new_version) { + releaseMessage.value = res.data.message; + updateStatus.value = '有新版本!'; + } else { + updateStatus.value = res.data.message; + } botCurrVersion.value = res.data.data.version; dashboardCurrentVersion.value = res.data.data.dashboard_version; dashboardHasNewVersion.value = res.data.data.dashboard_has_new_version; @@ -226,15 +234,23 @@ if (localStorage.getItem('change_pwd_hint') != null && localStorage.getItem('cha - +

{{ botCurrVersion }}

{{ updateStatus }}
+
+ +
+
- 💡 TIP: 跳到旧版本或者切换到某个版本不会重新下载管理面板文件,这可能会造成部分数据显示错误。您可在 此处 - 找到对应的面板文件 dist.zip,解压后替换 data/dist 文件夹即可。当然,前端源代码在 dashboard 目录下,你也可以自己使用 npm install 和 npm build 构建。 + 💡 TIP: 跳到旧版本或者切换到某个版本不会重新下载管理面板文件,这可能会造成部分数据显示错误。您可在 此处 + 找到对应的面板文件 dist.zip,解压后替换 data/dist 文件夹即可。当然,前端源代码在 dashboard 目录下,你也可以自己使用 npm install 和 npm build + 构建。
@@ -269,7 +285,7 @@ if (localStorage.getItem('change_pwd_hint') != null && localStorage.getItem('cha - +
@@ -319,7 +335,8 @@ if (localStorage.getItem('change_pwd_hint') != null && localStorage.getItem('cha

- + 下载并更新 @@ -379,4 +396,24 @@ if (localStorage.getItem('change_pwd_hint') != null && localStorage.getItem('cha - \ No newline at end of file + + + \ No newline at end of file From a156b1af14c2cf082889d2d6f9a3ceb5b2a3fdfc Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 26 Mar 2025 14:33:45 +0800 Subject: [PATCH 07/21] =?UTF-8?q?=E2=9C=A8=20feat:=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E6=8C=87=E4=BB=A4=E4=B8=8B=E8=BD=BD=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=20/plugin=20get?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/star/star_manager.py | 5 ++++- astrbot/dashboard/routes/conversation.py | 12 ------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/astrbot/core/star/star_manager.py b/astrbot/core/star/star_manager.py index c49027268..8a2bed689 100644 --- a/astrbot/core/star/star_manager.py +++ b/astrbot/core/star/star_manager.py @@ -332,7 +332,10 @@ class PluginManager: ) # 绑定 llm_tool handler for func_tool in llm_tools.func_list: - if func_tool.handler.__module__ == metadata.module_path: + if ( + func_tool.handler + and func_tool.handler.__module__ == metadata.module_path + ): func_tool.handler_module_path = metadata.module_path func_tool.handler = functools.partial( func_tool.handler, metadata.star_cls diff --git a/astrbot/dashboard/routes/conversation.py b/astrbot/dashboard/routes/conversation.py index a3c2db793..aa8b0af36 100644 --- a/astrbot/dashboard/routes/conversation.py +++ b/astrbot/dashboard/routes/conversation.py @@ -53,13 +53,6 @@ class ConversationRoute(Route): exclude_platforms.split(",") if exclude_platforms else [] ) - logger.info( - f"获取对话列表: page={page}, page_size={page_size}, " - f"platforms={platform_list}, message_types={message_type_list}, " - f"search={search_query}, exclude_ids={exclude_id_list}, " - f"exclude_platforms={exclude_platform_list}" - ) - # 限制页面大小,防止请求过大数据 if page < 1: page = 1 @@ -79,7 +72,6 @@ class ConversationRoute(Route): exclude_ids=exclude_id_list, exclude_platforms=exclude_platform_list, ) - logger.info(f"获取到 {len(conversations)} 条对话,总数: {total_count}") except Exception as e: logger.error(f"数据库查询出错: {str(e)}\n{traceback.format_exc()}") return Response().error(f"数据库查询出错: {str(e)}").__dict__ @@ -98,10 +90,6 @@ class ConversationRoute(Route): "total_pages": total_pages, }, } - - logger.info( - f"返回对话列表成功: {json.dumps(result, ensure_ascii=False)[:200]}..." - ) return Response().ok(result).__dict__ except Exception as e: From fb19d4d45bb9161a7af066dc2a0e4fc511da76f1 Mon Sep 17 00:00:00 2001 From: zhx Date: Wed, 26 Mar 2025 15:06:33 +0800 Subject: [PATCH 08/21] =?UTF-8?q?fix:=20install=5Fplugin=5Ffrom=5Ffile=20?= =?UTF-8?q?=E6=96=B9=E6=B3=95load=E4=BC=A0=E5=8F=82=E6=95=B0=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=96=87=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/star/star_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astrbot/core/star/star_manager.py b/astrbot/core/star/star_manager.py index 8a2bed689..67796decc 100644 --- a/astrbot/core/star/star_manager.py +++ b/astrbot/core/star/star_manager.py @@ -606,4 +606,4 @@ class PluginManager: except BaseException as e: logger.warning(f"删除插件压缩包失败: {str(e)}") # await self.reload() - await self.load(desti_dir) + await self.load(specified_dir_name=dir_name) From 67a0172b289bb6d099b0bca02bb45e06f740a720 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 26 Mar 2025 15:30:06 +0800 Subject: [PATCH 09/21] =?UTF-8?q?=F0=9F=93=A6=20release:=20v3.5.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/config/default.py | 2 +- changelogs/v3.5.0.md | 59 ++++++++++++++++++++++++++++++++++ pyproject.toml | 1 + uv.lock | 11 +++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 changelogs/v3.5.0.md diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index 310d7ee28..c45c8d813 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -2,7 +2,7 @@ 如需修改配置,请在 `data/cmd_config.json` 中修改或者在管理面板中可视化修改。 """ -VERSION = "3.4.39" +VERSION = "3.5.0" DB_PATH = "data/data_v3.db" # 默认配置 diff --git a/changelogs/v3.5.0.md b/changelogs/v3.5.0.md new file mode 100644 index 000000000..e0b68bd4e --- /dev/null +++ b/changelogs/v3.5.0.md @@ -0,0 +1,59 @@ +# What's Changed + +> 📢 AstrBot 上架宝塔面板 Docker 应用商店了! +> 📢 在升级前,请完整阅读本次更新日志。 + +## ✨ 新增的功能 + +1. ‼️ 新增支持接入 MCP 服务器 @Soulter @AraragiEro +1. ‼️ 新增支持本地渲染 Markdown,并支持自定义字体,详见 -> [#957](https://github.com/Soulter/AstrBot/issues/957#issuecomment-2749981802) +2. 新增支持在 WebUI 管理所有与大模型的对话 +3. 适配完整的 function-calling 流程。[#804](https://github.com/Soulter/AstrBot/issues/804) [#566](https://github.com/Soulter/AstrBot/issues/566) +4. 新增支持消息平台热重载,不再需要重启 AstrBot +5. 新增支持阿里云百炼应用的 RAG 应用 [#878](https://github.com/Soulter/AstrBot/issues/878) +6. 新增 `/plugin get` OP 指令下载插件。如 `/plugin get Raven95676/astrbot_plugin_wordle` +7. 新增 `/newgroup` OP 指令,支持私聊 bot 给指定群聊创建新的对话。by @LunarMeal +8. Gewechat 下支持 `添加好友`, `接收/发送视频`, `获取群信息`, `接收/发送表情包` by @Moyuyanli @Soulter @XuYingJie-cmd @NiceAir +9. Telegram 下支持接收和处理表情包(Sticker) @Raven95676 + + +## 🎈 功能性优化 + +0. 更加美观的 WebUI 设计,降低疲劳程度。 +1. 微信下,忽略 `微信团队` 的消息 [#859](https://github.com/Soulter/AstrBot/issues/859) +2. 完善 Dify 的图片输入功能 [#893](https://github.com/Soulter/AstrBot/issues/893) +3. 消息平台和配置提供商配置页中,自动更新旧的配置项 +4. 优化钉钉在配置错误之后堵塞整个线程的问题 [#885](https://github.com/Soulter/AstrBot/issues/885) +5. WebUI 删除插件时提供二次确认避免误删 @zhx8702 +6. WebUI 优化新版本时的信息显示 +7. 发送消息失败时的报错回显优化 +8. 改善所有消息平台的优雅退出逻辑 +9. 空 @ 时调用 LLM 获得更加富有人格的回复 by @advent259141 + +## 🐛 修复的 Bug + +1. 修复图片没有被存储到聊天上下文历史记录 +2. 修复 Telegram 下无法识别图片描述(Caption) [#910](https://github.com/Soulter/AstrBot/issues/910) +3. 修复 Telegram Topic 群组下引用消息来源错误的问题 [#908](https://github.com/Soulter/AstrBot/issues/908) +4. 修复 Telegram 下 `/start` 指令的一些问题 [#751](https://github.com/Soulter/AstrBot/issues/751) +5. WebUI 插件市场卡片显示风格的过滤问题。[#927](https://github.com/Soulter/AstrBot/issues/927) +6. 统一 SSL 证书验证逻辑,修复 `SSLCertVerificationError` 的问题。by @IGCrystal [#950](https://github.com/Soulter/AstrBot/issues/950) +7. 修复可能形成 SQL 注入的风险 +8. 修复本地上传插件时无法重载插件的问题 [#995](https://github.com/Soulter/AstrBot/issues/995) by @zhx8702 + +## 🧩 新增的插件 + +1. astrbot_plugin_majsoul-master - 雀魂多功能插件 - by @kterna +2. astrbot_plugin_server - 可视化服务器状态卡片,/status 或 /状态查询 查看 - by @yanfd @Meguminlove +3. astrbot_plugin_Getcwm - 刺猬猫小说数据获取与画图插件 - by @Li-shi-ling +4. astrbot_plugin_anti_withdrawal - 防撤回插件,目前只支持微信私聊群聊的文本消息,将撤回的消息记录并发送给设定的人 - by @NiceAir +5. astrbot_plugin_hello77 - 游戏梗自动回复插件 - by @ttq7 +6. astrbot_plugin_push_lite - Webhook 轻量级推送插件 - @Raven95676 +7. astrbot_plugin_pokecheck - 检测“戳”关键词的插件 - @huanyan434 +8. astrbot_plugin_MultiAI_PollPad - 轮询调用配置的大语言模型输出多个结果。同时将 AI 结果拷贝至在线文本编辑器 - by @Ynkcc +9. astrbot_plugin_box - / - by @Zhalslar +10. astrbot_plugin_Translation - 通过调用百度翻译 API 实现翻译文本 - by @zengweis +11. astrbot_plugin_wordle_2 - Wordle 游戏插件 - by @Raven95676 @whzcc +12. astrbot_plugin_mai_sgin - 舞萌出勤与退勤签到插件 - by @Rinyin +13. astrbot_plugin_Lolicon - Lolicon API 随机动漫图片插件 - by @ttq7 +14. astrbot_plugin_aiocensor - 综合内容安全+群管插件 - by @Raven95676 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 30195047c..20f61c95b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ dependencies = [ "colorlog>=6.9.0", "cryptography>=44.0.2", "dashscope>=1.22.2", + "defusedxml>=0.7.1", "dingtalk-stream>=0.22.1", "docstring-parser>=0.16", "googlesearch-python>=1.3.0", diff --git a/uv.lock b/uv.lock index 57880f340..835b323b3 100644 --- a/uv.lock +++ b/uv.lock @@ -206,6 +206,7 @@ dependencies = [ { name = "colorlog" }, { name = "cryptography" }, { name = "dashscope" }, + { name = "defusedxml" }, { name = "dingtalk-stream" }, { name = "docstring-parser" }, { name = "googlesearch-python" }, @@ -240,6 +241,7 @@ requires-dist = [ { name = "colorlog", specifier = ">=6.9.0" }, { name = "cryptography", specifier = ">=44.0.2" }, { name = "dashscope", specifier = ">=1.22.2" }, + { name = "defusedxml", specifier = ">=0.7.1" }, { name = "dingtalk-stream", specifier = ">=0.22.1" }, { name = "docstring-parser", specifier = ">=0.16" }, { name = "googlesearch-python", specifier = ">=1.3.0" }, @@ -537,6 +539,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/08/06/5dc2f9e391faf8f980c11e8dea5b06e0fc8d08aeca6298e12e6bc5a8ca4b/dashscope-1.22.2-py3-none-any.whl", hash = "sha256:781952cc9ce38cd2080a9d9f1cfabda55013dd2c996d3eca49863c8532db26b9", size = 1273150 }, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604 }, +] + [[package]] name = "dingtalk-stream" version = "0.22.1" From bbf85f8a1251ed38e6531c6e903236b0c4fd64ef Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 26 Mar 2025 15:43:56 +0800 Subject: [PATCH 10/21] =?UTF-8?q?=F0=9F=90=9B=20fix:=20remove=20error=20lo?= =?UTF-8?q?gging=20for=20empty=20result=20and=20refresh=20extensions=20aft?= =?UTF-8?q?er=20upload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/zip_updator.py | 1 - dashboard/src/views/ExtensionMarketplace.vue | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/astrbot/core/zip_updator.py b/astrbot/core/zip_updator.py index 23ff3ba76..7a27c1940 100644 --- a/astrbot/core/zip_updator.py +++ b/astrbot/core/zip_updator.py @@ -56,7 +56,6 @@ class RepoZipUpdator: raise Exception(f"请求失败,状态码: {response.status}") result = await response.json() if not result: - logger.error("返回空的结果") return [] # if latest: # ret = self.github_api_release_parser([result[0]]) diff --git a/dashboard/src/views/ExtensionMarketplace.vue b/dashboard/src/views/ExtensionMarketplace.vue index 959439375..3dfaea0d7 100644 --- a/dashboard/src/views/ExtensionMarketplace.vue +++ b/dashboard/src/views/ExtensionMarketplace.vue @@ -357,6 +357,7 @@ export default { this.upload_file = ""; this.onLoadingDialogResult(1, res.data.message); this.dialog = false; + this.getExtensions(); // this.$refs.wfr.check(); }).catch((err) => { this.loading_ = false; @@ -380,6 +381,7 @@ export default { this.extension_url = ""; this.onLoadingDialogResult(1, res.data.message); this.dialog = false; + this.getExtensions(); // this.$refs.wfr.check(); }).catch((err) => { this.loading_ = false; From 32b0cc1865a7ee9172c0b413c0dd5d28fea9612b Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Wed, 26 Mar 2025 16:16:03 +0800 Subject: [PATCH 11/21] Update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 509db0b63..8f7dff593 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,12 @@ AstrBot 是一个松耦合、异步、支持多消息平台部署、具有易用 ## ✨ 主要功能 1. **大语言模型对话**。支持各种大语言模型,包括 OpenAI API、Google Gemini、Llama、Deepseek、ChatGLM 等,支持接入本地部署的大模型,通过 Ollama、LLMTuner。具有多轮对话、人格情境、多模态能力,支持图片理解、语音转文字(Whisper)。 -2. **多消息平台接入**。支持接入 QQ(OneBot)、QQ 频道、微信(Gewechat)、飞书、Telegram。后续将支持钉钉、Discord、WhatsApp、小爱音响。支持速率限制、白名单、关键词过滤、百度内容审核。 -3. **Agent**。原生支持部分 Agent 能力,如代码执行器、自然语言待办、网页搜索。对接 [Dify 平台](https://astrbot.app/others/dify.html),便捷接入 Dify 智能助手、知识库和 Dify 工作流。 -4. **插件扩展**。深度优化的插件机制,支持[开发插件](https://astrbot.app/dev/plugin.html)扩展功能,极简开发。已支持安装多个插件。 -5. **可视化管理面板**。支持可视化修改配置、插件管理、日志查看等功能,降低配置难度。集成 WebChat,可在面板上与大模型对话。 -6. **高稳定性、高模块化**。基于事件总线和流水线的架构设计,高度模块化,低耦合。 +2. **支持 MCP**。AstrBot 现已支持接入 MCP 服务器。 +3. **多消息平台接入**。支持接入 QQ(OneBot)、QQ 频道、微信(Gewechat)、飞书、Telegram。后续将支持钉钉、Discord、WhatsApp、小爱音响。支持速率限制、白名单、关键词过滤、百度内容审核。 +4. **Agent**。原生支持部分 Agent 能力,如代码执行器、自然语言待办、网页搜索。对接 [Dify 平台](https://astrbot.app/others/dify.html),便捷接入 Dify 智能助手、知识库和 Dify 工作流。 +5. **插件扩展**。深度优化的插件机制,支持[开发插件](https://astrbot.app/dev/plugin.html)扩展功能,极简开发。已支持安装多个插件。 +6. **可视化管理面板**。支持可视化修改配置、插件管理、日志查看等功能,降低配置难度。集成 WebChat,可在面板上与大模型对话。 +7. **高稳定性、高模块化**。基于事件总线和流水线的架构设计,高度模块化,低耦合。 > [!TIP] > 管理面板在线体验 Demo: [https://demo.astrbot.app/](https://demo.astrbot.app/) From a221de9a2b31ab63ca7f637301132979bd052372 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 26 Mar 2025 17:56:51 +0800 Subject: [PATCH 12/21] =?UTF-8?q?=F0=9F=90=9B=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20LLM=20=E5=93=8D=E5=BA=94=E5=90=8E=E4=BA=8B=E4=BB=B6=E9=92=A9?= =?UTF-8?q?=E5=AD=90=E6=97=A0=E6=B3=95=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../process_stage/method/llm_request.py | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/astrbot/core/pipeline/process_stage/method/llm_request.py b/astrbot/core/pipeline/process_stage/method/llm_request.py index 8d606d9e5..7d41f7ecc 100644 --- a/astrbot/core/pipeline/process_stage/method/llm_request.py +++ b/astrbot/core/pipeline/process_stage/method/llm_request.py @@ -140,6 +140,26 @@ class LLMRequestSubStage(Stage): need_loop = False logger.debug(f"提供商请求 Payload: {req}") llm_response = await provider.text_chat(**req.__dict__) # 请求 LLM + + # 执行 LLM 响应后的事件钩子。 + handlers = star_handlers_registry.get_handlers_by_event_type( + EventType.OnLLMResponseEvent + ) + for handler in handlers: + try: + logger.debug( + f"hook(on_llm_response) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}" + ) + await handler.handler(event, llm_response) + except BaseException: + logger.error(traceback.format_exc()) + + if event.is_stopped(): + logger.info( + f"{star_map[handler.handler_module_path].name} - {handler.handler_name} 终止了事件传播。" + ) + return + async for result in self._handle_llm_response(event, req, llm_response): if isinstance(result, ProviderRequest): # 有函数工具调用并且返回了结果,我们需要再次请求 LLM @@ -148,25 +168,6 @@ class LLMRequestSubStage(Stage): else: yield - # 执行 LLM 响应后的事件钩子。 - handlers = star_handlers_registry.get_handlers_by_event_type( - EventType.OnLLMResponseEvent - ) - for handler in handlers: - try: - logger.debug( - f"hook(on_llm_response) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}" - ) - await handler.handler(event, llm_response) - except BaseException: - logger.error(traceback.format_exc()) - - if event.is_stopped(): - logger.info( - f"{star_map[handler.handler_module_path].name} - {handler.handler_name} 终止了事件传播。" - ) - return - asyncio.create_task( Metric.upload( llm_tick=1, From 3e325debcc9fc758ab3749a6290b543cc16fbde7 Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Wed, 26 Mar 2025 20:51:53 +0800 Subject: [PATCH 13/21] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8f7dff593..8d1f17ebc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- -![6e1279651f16d7fdf4727558b72bbaf1](https://github.com/user-attachments/assets/ead4c551-fc3c-48f7-a6f7-afbfdb820512) + +![yjtp](https://github.com/user-attachments/assets/dcc74009-c57e-4b66-9ae3-0a81fc001255)

From 005e9eae7c15ee2c766b5da67f64e50d537e7388 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Thu, 27 Mar 2025 10:04:40 +0800 Subject: [PATCH 14/21] =?UTF-8?q?=F0=9F=90=9B=20fix:=20=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=97=B6=E6=B2=A1=E6=9C=89=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=8A=A0=E9=80=9F=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/star/updator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astrbot/core/star/updator.py b/astrbot/core/star/updator.py index 5f98af9c1..d439e98cc 100644 --- a/astrbot/core/star/updator.py +++ b/astrbot/core/star/updator.py @@ -41,7 +41,7 @@ class PluginUpdator(RepoZipUpdator): plugin_path = os.path.join(self.plugin_store_path, plugin.root_dir_name) logger.info(f"正在更新插件,路径: {plugin_path},仓库地址: {repo_url}") - await self.download_from_repo_url(plugin_path, repo_url) + await self.download_from_repo_url(plugin_path, repo_url, proxy=proxy) try: remove_dir(plugin_path) From 42ff9a4d3433bdd3dbfb6056f19b50a92634fe84 Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Thu, 27 Mar 2025 10:39:18 +0800 Subject: [PATCH 15/21] Update README.md --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8d1f17ebc..98ae9be72 100644 --- a/README.md +++ b/README.md @@ -30,15 +30,18 @@ AstrBot 是一个松耦合、异步、支持多消息平台部署、具有易用 +## ✨ 近期更新 + +1. AstrBot 现已支持接入 [MCP](https://modelcontextprotocol.io/) 服务器! + ## ✨ 主要功能 1. **大语言模型对话**。支持各种大语言模型,包括 OpenAI API、Google Gemini、Llama、Deepseek、ChatGLM 等,支持接入本地部署的大模型,通过 Ollama、LLMTuner。具有多轮对话、人格情境、多模态能力,支持图片理解、语音转文字(Whisper)。 -2. **支持 MCP**。AstrBot 现已支持接入 MCP 服务器。 -3. **多消息平台接入**。支持接入 QQ(OneBot)、QQ 频道、微信(Gewechat)、飞书、Telegram。后续将支持钉钉、Discord、WhatsApp、小爱音响。支持速率限制、白名单、关键词过滤、百度内容审核。 -4. **Agent**。原生支持部分 Agent 能力,如代码执行器、自然语言待办、网页搜索。对接 [Dify 平台](https://astrbot.app/others/dify.html),便捷接入 Dify 智能助手、知识库和 Dify 工作流。 -5. **插件扩展**。深度优化的插件机制,支持[开发插件](https://astrbot.app/dev/plugin.html)扩展功能,极简开发。已支持安装多个插件。 -6. **可视化管理面板**。支持可视化修改配置、插件管理、日志查看等功能,降低配置难度。集成 WebChat,可在面板上与大模型对话。 -7. **高稳定性、高模块化**。基于事件总线和流水线的架构设计,高度模块化,低耦合。 +2. **多消息平台接入**。支持接入 QQ(OneBot)、QQ 频道、微信(Gewechat)、飞书、Telegram。后续将支持钉钉、Discord、WhatsApp、小爱音响。支持速率限制、白名单、关键词过滤、百度内容审核。 +3. **Agent**。原生支持部分 Agent 能力,如代码执行器、自然语言待办、网页搜索。对接 [Dify 平台](https://astrbot.app/others/dify.html),便捷接入 Dify 智能助手、知识库和 Dify 工作流。 +4. **插件扩展**。深度优化的插件机制,支持[开发插件](https://astrbot.app/dev/plugin.html)扩展功能,极简开发。已支持安装多个插件。 +5. **可视化管理面板**。支持可视化修改配置、插件管理、日志查看等功能,降低配置难度。集成 WebChat,可在面板上与大模型对话。 +6. **高稳定性、高模块化**。基于事件总线和流水线的架构设计,高度模块化,低耦合。 > [!TIP] > 管理面板在线体验 Demo: [https://demo.astrbot.app/](https://demo.astrbot.app/) From fb85a7bb354a26ac6b675619fe394057c2cb5e25 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Thu, 27 Mar 2025 15:54:23 +0800 Subject: [PATCH 16/21] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20demo=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/__init__.py | 1 + astrbot/dashboard/routes/auth.py | 9 +++++- astrbot/dashboard/routes/plugin.py | 50 ++++++++++++++++++++++++++++++ astrbot/dashboard/routes/stat.py | 8 +++++ astrbot/dashboard/routes/update.py | 8 +++++ 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/astrbot/core/__init__.py b/astrbot/core/__init__.py index 9749dee24..cfedf92e5 100644 --- a/astrbot/core/__init__.py +++ b/astrbot/core/__init__.py @@ -24,3 +24,4 @@ pip_installer = PipInstaller(astrbot_config.get("pip_install_arg", "")) web_chat_queue = asyncio.Queue(maxsize=32) web_chat_back_queue = asyncio.Queue(maxsize=32) WEBUI_SK = "Advanced_System_for_Text_Response_and_Bot_Operations_Tool" +DEMO_MODE = os.getenv("DEMO_MODE", False) diff --git a/astrbot/dashboard/routes/auth.py b/astrbot/dashboard/routes/auth.py index 34ba8fd3f..896bea4e7 100644 --- a/astrbot/dashboard/routes/auth.py +++ b/astrbot/dashboard/routes/auth.py @@ -2,7 +2,7 @@ import jwt import datetime from .route import Route, Response, RouteContext from quart import request -from astrbot.core import WEBUI_SK +from astrbot.core import WEBUI_SK, DEMO_MODE from astrbot import logger @@ -40,6 +40,13 @@ class AuthRoute(Route): return Response().error("用户名或密码错误").__dict__ async def edit_account(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + password = self.config["dashboard"]["password"] post_data = await request.json diff --git a/astrbot/dashboard/routes/plugin.py b/astrbot/dashboard/routes/plugin.py index 32dc99176..3ffa1c557 100644 --- a/astrbot/dashboard/routes/plugin.py +++ b/astrbot/dashboard/routes/plugin.py @@ -15,6 +15,7 @@ from astrbot.core.star.filter.command_group import CommandGroupFilter from astrbot.core.star.filter.permission import PermissionTypeFilter from astrbot.core.star.filter.regex import RegexFilter from astrbot.core.star.star_handler import EventType +from astrbot.core import DEMO_MODE class PluginRoute(Route): @@ -50,6 +51,13 @@ class PluginRoute(Route): } async def reload_plugins(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + data = await request.json plugin_name = data.get("name", None) try: @@ -187,6 +195,13 @@ class PluginRoute(Route): return handlers async def install_plugin(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + post_data = await request.json repo_url = post_data["url"] @@ -205,6 +220,13 @@ class PluginRoute(Route): return Response().error(str(e)).__dict__ async def install_plugin_upload(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + try: file = await request.files file = file["file"] @@ -220,6 +242,13 @@ class PluginRoute(Route): return Response().error(str(e)).__dict__ async def uninstall_plugin(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + post_data = await request.json plugin_name = post_data["name"] try: @@ -232,6 +261,13 @@ class PluginRoute(Route): return Response().error(str(e)).__dict__ async def update_plugin(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + post_data = await request.json plugin_name = post_data["name"] proxy: str = post_data.get("proxy", None) @@ -247,6 +283,13 @@ class PluginRoute(Route): return Response().error(str(e)).__dict__ async def off_plugin(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + post_data = await request.json plugin_name = post_data["name"] try: @@ -258,6 +301,13 @@ class PluginRoute(Route): return Response().error(str(e)).__dict__ async def on_plugin(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + post_data = await request.json plugin_name = post_data["name"] try: diff --git a/astrbot/dashboard/routes/stat.py b/astrbot/dashboard/routes/stat.py index e73c09455..337e544af 100644 --- a/astrbot/dashboard/routes/stat.py +++ b/astrbot/dashboard/routes/stat.py @@ -8,6 +8,7 @@ from quart import request from astrbot.core.core_lifecycle import AstrBotCoreLifecycle from astrbot.core.db import BaseDatabase from astrbot.core.config import VERSION +from astrbot.core import DEMO_MODE class StatRoute(Route): @@ -29,6 +30,13 @@ class StatRoute(Route): self.core_lifecycle = core_lifecycle async def restart_core(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + await self.core_lifecycle.restart() return Response().ok().__dict__ diff --git a/astrbot/dashboard/routes/update.py b/astrbot/dashboard/routes/update.py index e9ada18f5..bd0782088 100644 --- a/astrbot/dashboard/routes/update.py +++ b/astrbot/dashboard/routes/update.py @@ -6,6 +6,7 @@ from astrbot.core.updator import AstrBotUpdator from astrbot.core import logger, pip_installer from astrbot.core.utils.io import download_dashboard, get_dashboard_version from astrbot.core.config.default import VERSION +from astrbot.core import DEMO_MODE class UpdateRoute(Route): @@ -126,6 +127,13 @@ class UpdateRoute(Route): return Response().error(e.__str__()).__dict__ async def install_pip_package(self): + if DEMO_MODE: + return ( + Response() + .error("You are not permitted to do this operation in demo mode") + .__dict__ + ) + data = await request.json package = data.get("package", "") if not package: From c7484d0cc9b62df5170f417907786616494afed4 Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Fri, 28 Mar 2025 13:23:29 +0800 Subject: [PATCH 17/21] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98ae9be72..23247b2b9 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ AstrBot 是一个松耦合、异步、支持多消息平台部署、具有易用 > [!TIP] > 管理面板在线体验 Demo: [https://demo.astrbot.app/](https://demo.astrbot.app/) > -> 用户名: `astrbot`, 密码: `astrbot`。未配置 LLM,无法在聊天页使用大模型。(不要再修改 demo 的登录密码了 😭) +> 用户名: `astrbot`, 密码: `astrbot`。未配置 LLM,无法在聊天页使用大模型。 ## ✨ 使用方式 From c33c07e4af7395335cb429fbfce1de1818a67bdc Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Fri, 28 Mar 2025 13:24:41 +0800 Subject: [PATCH 18/21] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23247b2b9..a5dd762ae 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ _✨ 易上手的多平台 LLM 聊天机器人及开发框架 ✨_ Docker pull Static Badge [![wakatime](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e.svg?style=for-the-badge&color=76bad9)](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e) -![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fstats&query=v&label=7%E6%97%A5%E6%B4%BB%E8%B7%83%E9%87%8F&cacheSeconds=60&style=for-the-badge&color=3b618e) +![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fstats&query=v&label=7%E6%97%A5%E6%B4%BB%E8%B7%83%E9%87%8F&cacheSeconds=3600&style=for-the-badge&color=3b618e) English日本語 | From 93a1699a3525f7e157804a3d240b388c00da0d17 Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:20:33 +0800 Subject: [PATCH 19/21] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a5dd762ae..7493d557d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ _✨ 易上手的多平台 LLM 聊天机器人及开发框架 ✨_ Docker pull Static Badge [![wakatime](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e.svg?style=for-the-badge&color=76bad9)](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e) -![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fstats&query=v&label=7%E6%97%A5%E6%B4%BB%E8%B7%83%E9%87%8F&cacheSeconds=3600&style=for-the-badge&color=3b618e) +![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fstats&query=v&label=7%E6%97%A5%E6%B4%BB%E8%B7%83%E9%87%8F&cacheSeconds=10800&style=for-the-badge&color=3b618e) English日本語 | From 20e41a7f737a1f05bfbbe91594011f418c590ad9 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Fri, 28 Mar 2025 23:45:19 +0800 Subject: [PATCH 20/21] =?UTF-8?q?=F0=9F=90=9B=20fix:=20newgroup=20?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=E5=90=8D=E6=98=BE=E7=A4=BA=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/astrbot/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astrbot/main.py b/packages/astrbot/main.py index 1f5f23cd8..30d6d99ce 100644 --- a/packages/astrbot/main.py +++ b/packages/astrbot/main.py @@ -760,7 +760,7 @@ UID: {user_id} 此 ID 可用于设置管理员。 ) else: message.set_result( - MessageEventResult().message("请输入群聊 ID。/newgroup 群聊ID。") + MessageEventResult().message("请输入群聊 ID。/groupnew 群聊ID。") ) @filter.command("switch") From 8a0665b2225f2555ca91c0042a3a1e22216c6cf9 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Sat, 29 Mar 2025 16:36:02 +0800 Subject: [PATCH 21/21] =?UTF-8?q?=F0=9F=8E=88=20feat:=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=20Dockerfile=EF=BC=8C=E6=B7=BB=E5=8A=A0=20Node.js=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BE=9D=E8=B5=96=E5=AE=89?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 8 +++++--- Dockerfile_with_node | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 Dockerfile_with_node diff --git a/Dockerfile b/Dockerfile index 0b46d5d48..1b2314970 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,12 +9,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3-dev \ libffi-dev \ libssl-dev \ + ca-certificates \ + bash \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -RUN python -m pip install -r requirements.txt --no-cache-dir - -RUN python -m pip install socksio wechatpy cryptography --no-cache-dir +RUN python -m pip install uv +RUN uv pip install -r requirements.txt --no-cache-dir --system +RUN uv pip install socksio uv pyffmpeg --no-cache-dir --system EXPOSE 6185 EXPOSE 6186 diff --git a/Dockerfile_with_node b/Dockerfile_with_node new file mode 100644 index 000000000..3bd37468a --- /dev/null +++ b/Dockerfile_with_node @@ -0,0 +1,35 @@ +FROM python:3.10-slim + +WORKDIR /AstrBot + +COPY . /AstrBot/ + +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + build-essential \ + python3-dev \ + libffi-dev \ + libssl-dev \ + curl \ + unzip \ + ca-certificates \ + bash \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Installation of Node.js +ENV NVM_DIR="/root/.nvm" +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash && \ + . "$NVM_DIR/nvm.sh" && \ + nvm install 22 && \ + nvm use 22 +RUN /bin/bash -c ". \"$NVM_DIR/nvm.sh\" && node -v && npm -v" + +RUN python -m pip install uv +RUN uv pip install -r requirements.txt --no-cache-dir --system +RUN uv pip install socksio uv pyffmpeg --no-cache-dir --system + +EXPOSE 6185 +EXPOSE 6186 + +CMD ["python", "main.py"]