AstrBot 4.5.0__py3-none-any.whl → 4.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. astrbot/api/__init__.py +10 -11
  2. astrbot/api/event/__init__.py +5 -6
  3. astrbot/api/event/filter/__init__.py +37 -36
  4. astrbot/api/platform/__init__.py +7 -8
  5. astrbot/api/provider/__init__.py +7 -7
  6. astrbot/api/star/__init__.py +3 -4
  7. astrbot/api/util/__init__.py +2 -2
  8. astrbot/cli/__main__.py +5 -5
  9. astrbot/cli/commands/__init__.py +3 -3
  10. astrbot/cli/commands/cmd_conf.py +19 -16
  11. astrbot/cli/commands/cmd_init.py +3 -2
  12. astrbot/cli/commands/cmd_plug.py +8 -10
  13. astrbot/cli/commands/cmd_run.py +5 -6
  14. astrbot/cli/utils/__init__.py +6 -6
  15. astrbot/cli/utils/basic.py +14 -14
  16. astrbot/cli/utils/plugin.py +24 -15
  17. astrbot/cli/utils/version_comparator.py +10 -12
  18. astrbot/core/__init__.py +8 -6
  19. astrbot/core/agent/agent.py +3 -2
  20. astrbot/core/agent/handoff.py +6 -2
  21. astrbot/core/agent/hooks.py +9 -6
  22. astrbot/core/agent/mcp_client.py +50 -15
  23. astrbot/core/agent/message.py +168 -0
  24. astrbot/core/agent/response.py +2 -1
  25. astrbot/core/agent/run_context.py +2 -3
  26. astrbot/core/agent/runners/base.py +10 -13
  27. astrbot/core/agent/runners/tool_loop_agent_runner.py +52 -51
  28. astrbot/core/agent/tool.py +60 -41
  29. astrbot/core/agent/tool_executor.py +9 -3
  30. astrbot/core/astr_agent_context.py +3 -1
  31. astrbot/core/astrbot_config_mgr.py +29 -9
  32. astrbot/core/config/__init__.py +2 -2
  33. astrbot/core/config/astrbot_config.py +28 -26
  34. astrbot/core/config/default.py +44 -6
  35. astrbot/core/conversation_mgr.py +105 -36
  36. astrbot/core/core_lifecycle.py +68 -54
  37. astrbot/core/db/__init__.py +33 -18
  38. astrbot/core/db/migration/helper.py +18 -13
  39. astrbot/core/db/migration/migra_3_to_4.py +53 -34
  40. astrbot/core/db/migration/migra_45_to_46.py +1 -1
  41. astrbot/core/db/migration/shared_preferences_v3.py +2 -1
  42. astrbot/core/db/migration/sqlite_v3.py +26 -23
  43. astrbot/core/db/po.py +27 -18
  44. astrbot/core/db/sqlite.py +74 -45
  45. astrbot/core/db/vec_db/base.py +10 -14
  46. astrbot/core/db/vec_db/faiss_impl/document_storage.py +90 -77
  47. astrbot/core/db/vec_db/faiss_impl/embedding_storage.py +9 -3
  48. astrbot/core/db/vec_db/faiss_impl/vec_db.py +36 -31
  49. astrbot/core/event_bus.py +8 -6
  50. astrbot/core/file_token_service.py +6 -5
  51. astrbot/core/initial_loader.py +7 -5
  52. astrbot/core/knowledge_base/chunking/__init__.py +1 -3
  53. astrbot/core/knowledge_base/chunking/base.py +1 -0
  54. astrbot/core/knowledge_base/chunking/fixed_size.py +2 -0
  55. astrbot/core/knowledge_base/chunking/recursive.py +16 -10
  56. astrbot/core/knowledge_base/kb_db_sqlite.py +50 -48
  57. astrbot/core/knowledge_base/kb_helper.py +30 -17
  58. astrbot/core/knowledge_base/kb_mgr.py +6 -7
  59. astrbot/core/knowledge_base/models.py +10 -4
  60. astrbot/core/knowledge_base/parsers/__init__.py +3 -5
  61. astrbot/core/knowledge_base/parsers/base.py +1 -0
  62. astrbot/core/knowledge_base/parsers/markitdown_parser.py +2 -1
  63. astrbot/core/knowledge_base/parsers/pdf_parser.py +2 -1
  64. astrbot/core/knowledge_base/parsers/text_parser.py +1 -0
  65. astrbot/core/knowledge_base/parsers/util.py +1 -1
  66. astrbot/core/knowledge_base/retrieval/__init__.py +6 -8
  67. astrbot/core/knowledge_base/retrieval/manager.py +17 -14
  68. astrbot/core/knowledge_base/retrieval/rank_fusion.py +7 -3
  69. astrbot/core/knowledge_base/retrieval/sparse_retriever.py +11 -5
  70. astrbot/core/log.py +21 -13
  71. astrbot/core/message/components.py +123 -217
  72. astrbot/core/message/message_event_result.py +24 -24
  73. astrbot/core/persona_mgr.py +20 -11
  74. astrbot/core/pipeline/__init__.py +7 -7
  75. astrbot/core/pipeline/content_safety_check/stage.py +13 -9
  76. astrbot/core/pipeline/content_safety_check/strategies/__init__.py +1 -2
  77. astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py +12 -13
  78. astrbot/core/pipeline/content_safety_check/strategies/keywords.py +1 -0
  79. astrbot/core/pipeline/content_safety_check/strategies/strategy.py +6 -6
  80. astrbot/core/pipeline/context.py +4 -1
  81. astrbot/core/pipeline/context_utils.py +77 -7
  82. astrbot/core/pipeline/preprocess_stage/stage.py +12 -9
  83. astrbot/core/pipeline/process_stage/method/llm_request.py +125 -72
  84. astrbot/core/pipeline/process_stage/method/star_request.py +19 -17
  85. astrbot/core/pipeline/process_stage/stage.py +13 -10
  86. astrbot/core/pipeline/process_stage/utils.py +6 -5
  87. astrbot/core/pipeline/rate_limit_check/stage.py +37 -36
  88. astrbot/core/pipeline/respond/stage.py +23 -20
  89. astrbot/core/pipeline/result_decorate/stage.py +31 -23
  90. astrbot/core/pipeline/scheduler.py +12 -8
  91. astrbot/core/pipeline/session_status_check/stage.py +12 -8
  92. astrbot/core/pipeline/stage.py +10 -4
  93. astrbot/core/pipeline/waking_check/stage.py +24 -18
  94. astrbot/core/pipeline/whitelist_check/stage.py +10 -7
  95. astrbot/core/platform/__init__.py +6 -6
  96. astrbot/core/platform/astr_message_event.py +76 -110
  97. astrbot/core/platform/astrbot_message.py +11 -13
  98. astrbot/core/platform/manager.py +16 -15
  99. astrbot/core/platform/message_session.py +5 -3
  100. astrbot/core/platform/platform.py +16 -24
  101. astrbot/core/platform/platform_metadata.py +4 -4
  102. astrbot/core/platform/register.py +8 -8
  103. astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +23 -15
  104. astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +51 -33
  105. astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py +47 -29
  106. astrbot/core/platform/sources/dingtalk/dingtalk_event.py +7 -3
  107. astrbot/core/platform/sources/discord/client.py +9 -6
  108. astrbot/core/platform/sources/discord/components.py +18 -14
  109. astrbot/core/platform/sources/discord/discord_platform_adapter.py +45 -30
  110. astrbot/core/platform/sources/discord/discord_platform_event.py +38 -30
  111. astrbot/core/platform/sources/lark/lark_adapter.py +23 -17
  112. astrbot/core/platform/sources/lark/lark_event.py +21 -14
  113. astrbot/core/platform/sources/misskey/misskey_adapter.py +107 -67
  114. astrbot/core/platform/sources/misskey/misskey_api.py +153 -129
  115. astrbot/core/platform/sources/misskey/misskey_event.py +20 -15
  116. astrbot/core/platform/sources/misskey/misskey_utils.py +74 -62
  117. astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py +63 -44
  118. astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py +41 -26
  119. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py +36 -17
  120. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_event.py +3 -1
  121. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_server.py +12 -7
  122. astrbot/core/platform/sources/satori/satori_adapter.py +56 -38
  123. astrbot/core/platform/sources/satori/satori_event.py +34 -25
  124. astrbot/core/platform/sources/slack/client.py +11 -9
  125. astrbot/core/platform/sources/slack/slack_adapter.py +52 -36
  126. astrbot/core/platform/sources/slack/slack_event.py +34 -24
  127. astrbot/core/platform/sources/telegram/tg_adapter.py +38 -18
  128. astrbot/core/platform/sources/telegram/tg_event.py +32 -18
  129. astrbot/core/platform/sources/webchat/webchat_adapter.py +27 -17
  130. astrbot/core/platform/sources/webchat/webchat_event.py +14 -10
  131. astrbot/core/platform/sources/wechatpadpro/wechatpadpro_adapter.py +115 -120
  132. astrbot/core/platform/sources/wechatpadpro/wechatpadpro_message_event.py +9 -8
  133. astrbot/core/platform/sources/wechatpadpro/xml_data_parser.py +15 -16
  134. astrbot/core/platform/sources/wecom/wecom_adapter.py +35 -18
  135. astrbot/core/platform/sources/wecom/wecom_event.py +55 -48
  136. astrbot/core/platform/sources/wecom/wecom_kf.py +34 -44
  137. astrbot/core/platform/sources/wecom/wecom_kf_message.py +26 -10
  138. astrbot/core/platform/sources/wecom_ai_bot/WXBizJsonMsgCrypt.py +18 -10
  139. astrbot/core/platform/sources/wecom_ai_bot/__init__.py +3 -5
  140. astrbot/core/platform/sources/wecom_ai_bot/ierror.py +0 -1
  141. astrbot/core/platform/sources/wecom_ai_bot/wecomai_adapter.py +61 -37
  142. astrbot/core/platform/sources/wecom_ai_bot/wecomai_api.py +67 -28
  143. astrbot/core/platform/sources/wecom_ai_bot/wecomai_event.py +8 -9
  144. astrbot/core/platform/sources/wecom_ai_bot/wecomai_queue_mgr.py +18 -9
  145. astrbot/core/platform/sources/wecom_ai_bot/wecomai_server.py +14 -12
  146. astrbot/core/platform/sources/wecom_ai_bot/wecomai_utils.py +22 -12
  147. astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.py +40 -26
  148. astrbot/core/platform/sources/weixin_official_account/weixin_offacc_event.py +47 -45
  149. astrbot/core/platform_message_history_mgr.py +5 -3
  150. astrbot/core/provider/__init__.py +2 -3
  151. astrbot/core/provider/entites.py +8 -8
  152. astrbot/core/provider/entities.py +61 -75
  153. astrbot/core/provider/func_tool_manager.py +59 -55
  154. astrbot/core/provider/manager.py +40 -22
  155. astrbot/core/provider/provider.py +72 -46
  156. astrbot/core/provider/register.py +7 -7
  157. astrbot/core/provider/sources/anthropic_source.py +48 -30
  158. astrbot/core/provider/sources/azure_tts_source.py +17 -13
  159. astrbot/core/provider/sources/coze_api_client.py +27 -17
  160. astrbot/core/provider/sources/coze_source.py +104 -87
  161. astrbot/core/provider/sources/dashscope_source.py +18 -11
  162. astrbot/core/provider/sources/dashscope_tts.py +36 -23
  163. astrbot/core/provider/sources/dify_source.py +25 -20
  164. astrbot/core/provider/sources/edge_tts_source.py +21 -17
  165. astrbot/core/provider/sources/fishaudio_tts_api_source.py +22 -14
  166. astrbot/core/provider/sources/gemini_embedding_source.py +12 -13
  167. astrbot/core/provider/sources/gemini_source.py +72 -58
  168. astrbot/core/provider/sources/gemini_tts_source.py +8 -6
  169. astrbot/core/provider/sources/gsv_selfhosted_source.py +17 -14
  170. astrbot/core/provider/sources/gsvi_tts_source.py +11 -7
  171. astrbot/core/provider/sources/minimax_tts_api_source.py +50 -40
  172. astrbot/core/provider/sources/openai_embedding_source.py +6 -8
  173. astrbot/core/provider/sources/openai_source.py +102 -69
  174. astrbot/core/provider/sources/openai_tts_api_source.py +14 -6
  175. astrbot/core/provider/sources/sensevoice_selfhosted_source.py +13 -11
  176. astrbot/core/provider/sources/vllm_rerank_source.py +10 -4
  177. astrbot/core/provider/sources/volcengine_tts.py +38 -31
  178. astrbot/core/provider/sources/whisper_api_source.py +14 -12
  179. astrbot/core/provider/sources/whisper_selfhosted_source.py +15 -11
  180. astrbot/core/provider/sources/xinference_rerank_source.py +116 -0
  181. astrbot/core/provider/sources/xinference_stt_provider.py +197 -0
  182. astrbot/core/star/__init__.py +16 -11
  183. astrbot/core/star/config.py +10 -15
  184. astrbot/core/star/context.py +109 -84
  185. astrbot/core/star/filter/__init__.py +4 -3
  186. astrbot/core/star/filter/command.py +30 -28
  187. astrbot/core/star/filter/command_group.py +27 -24
  188. astrbot/core/star/filter/custom_filter.py +6 -5
  189. astrbot/core/star/filter/event_message_type.py +4 -2
  190. astrbot/core/star/filter/permission.py +4 -2
  191. astrbot/core/star/filter/platform_adapter_type.py +4 -2
  192. astrbot/core/star/filter/regex.py +4 -2
  193. astrbot/core/star/register/__init__.py +19 -19
  194. astrbot/core/star/register/star.py +6 -2
  195. astrbot/core/star/register/star_handler.py +96 -73
  196. astrbot/core/star/session_llm_manager.py +48 -14
  197. astrbot/core/star/session_plugin_manager.py +29 -15
  198. astrbot/core/star/star.py +1 -2
  199. astrbot/core/star/star_handler.py +13 -8
  200. astrbot/core/star/star_manager.py +151 -59
  201. astrbot/core/star/star_tools.py +44 -37
  202. astrbot/core/star/updator.py +10 -10
  203. astrbot/core/umop_config_router.py +10 -4
  204. astrbot/core/updator.py +13 -5
  205. astrbot/core/utils/astrbot_path.py +3 -5
  206. astrbot/core/utils/dify_api_client.py +33 -15
  207. astrbot/core/utils/io.py +66 -42
  208. astrbot/core/utils/log_pipe.py +1 -1
  209. astrbot/core/utils/metrics.py +7 -7
  210. astrbot/core/utils/path_util.py +15 -16
  211. astrbot/core/utils/pip_installer.py +5 -5
  212. astrbot/core/utils/session_waiter.py +19 -20
  213. astrbot/core/utils/shared_preferences.py +45 -20
  214. astrbot/core/utils/t2i/__init__.py +4 -1
  215. astrbot/core/utils/t2i/network_strategy.py +35 -26
  216. astrbot/core/utils/t2i/renderer.py +11 -5
  217. astrbot/core/utils/t2i/template_manager.py +14 -15
  218. astrbot/core/utils/tencent_record_helper.py +19 -13
  219. astrbot/core/utils/version_comparator.py +10 -13
  220. astrbot/core/zip_updator.py +43 -40
  221. astrbot/dashboard/routes/__init__.py +18 -18
  222. astrbot/dashboard/routes/auth.py +10 -8
  223. astrbot/dashboard/routes/chat.py +30 -21
  224. astrbot/dashboard/routes/config.py +92 -75
  225. astrbot/dashboard/routes/conversation.py +46 -39
  226. astrbot/dashboard/routes/file.py +4 -2
  227. astrbot/dashboard/routes/knowledge_base.py +47 -40
  228. astrbot/dashboard/routes/log.py +9 -4
  229. astrbot/dashboard/routes/persona.py +19 -16
  230. astrbot/dashboard/routes/plugin.py +69 -55
  231. astrbot/dashboard/routes/route.py +3 -1
  232. astrbot/dashboard/routes/session_management.py +130 -116
  233. astrbot/dashboard/routes/stat.py +34 -34
  234. astrbot/dashboard/routes/t2i.py +15 -12
  235. astrbot/dashboard/routes/tools.py +47 -52
  236. astrbot/dashboard/routes/update.py +32 -28
  237. astrbot/dashboard/server.py +30 -26
  238. astrbot/dashboard/utils.py +8 -4
  239. {astrbot-4.5.0.dist-info → astrbot-4.5.2.dist-info}/METADATA +4 -2
  240. astrbot-4.5.2.dist-info/RECORD +261 -0
  241. astrbot-4.5.0.dist-info/RECORD +0 -258
  242. {astrbot-4.5.0.dist-info → astrbot-4.5.2.dist-info}/WHEEL +0 -0
  243. {astrbot-4.5.0.dist-info → astrbot-4.5.2.dist-info}/entry_points.txt +0 -0
  244. {astrbot-4.5.0.dist-info → astrbot-4.5.2.dist-info}/licenses/LICENSE +0 -0
@@ -37,7 +37,10 @@ else:
37
37
  @register_platform_adapter("telegram", "telegram 适配器")
38
38
  class TelegramPlatformAdapter(Platform):
39
39
  def __init__(
40
- self, platform_config: dict, platform_settings: dict, event_queue: asyncio.Queue
40
+ self,
41
+ platform_config: dict,
42
+ platform_settings: dict,
43
+ event_queue: asyncio.Queue,
41
44
  ) -> None:
42
45
  super().__init__(event_queue)
43
46
  self.config = platform_config
@@ -45,13 +48,15 @@ class TelegramPlatformAdapter(Platform):
45
48
  self.client_self_id = uuid.uuid4().hex[:8]
46
49
 
47
50
  base_url = self.config.get(
48
- "telegram_api_base_url", "https://api.telegram.org/bot"
51
+ "telegram_api_base_url",
52
+ "https://api.telegram.org/bot",
49
53
  )
50
54
  if not base_url:
51
55
  base_url = "https://api.telegram.org/bot"
52
56
 
53
57
  file_base_url = self.config.get(
54
- "telegram_file_base_url", "https://api.telegram.org/file/bot"
58
+ "telegram_file_base_url",
59
+ "https://api.telegram.org/file/bot",
55
60
  )
56
61
  if not file_base_url:
57
62
  file_base_url = "https://api.telegram.org/file/bot"
@@ -59,10 +64,12 @@ class TelegramPlatformAdapter(Platform):
59
64
  self.base_url = base_url
60
65
 
61
66
  self.enable_command_register = self.config.get(
62
- "telegram_command_register", True
67
+ "telegram_command_register",
68
+ True,
63
69
  )
64
70
  self.enable_command_refresh = self.config.get(
65
- "telegram_command_auto_refresh", True
71
+ "telegram_command_auto_refresh",
72
+ True,
66
73
  )
67
74
  self.last_command_hash = None
68
75
 
@@ -85,11 +92,15 @@ class TelegramPlatformAdapter(Platform):
85
92
 
86
93
  @override
87
94
  async def send_by_session(
88
- self, session: MessageSesion, message_chain: MessageChain
95
+ self,
96
+ session: MessageSesion,
97
+ message_chain: MessageChain,
89
98
  ):
90
99
  from_username = session.session_id
91
100
  await TelegramPlatformEvent.send_with_client(
92
- self.client, message_chain, from_username
101
+ self.client,
102
+ message_chain,
103
+ from_username,
93
104
  )
94
105
  await super().send_by_session(session, message_chain)
95
106
 
@@ -131,7 +142,7 @@ class TelegramPlatformAdapter(Platform):
131
142
 
132
143
  if commands:
133
144
  current_hash = hash(
134
- tuple((cmd.command, cmd.description) for cmd in commands)
145
+ tuple((cmd.command, cmd.description) for cmd in commands),
135
146
  )
136
147
  if current_hash == self.last_command_hash:
137
148
  return
@@ -153,7 +164,9 @@ class TelegramPlatformAdapter(Platform):
153
164
  continue
154
165
  for event_filter in handler_metadata.event_filters:
155
166
  cmd_info = self._extract_command_info(
156
- event_filter, handler_metadata, skip_commands
167
+ event_filter,
168
+ handler_metadata,
169
+ skip_commands,
157
170
  )
158
171
  if cmd_info:
159
172
  cmd_name, description = cmd_info
@@ -164,7 +177,9 @@ class TelegramPlatformAdapter(Platform):
164
177
 
165
178
  @staticmethod
166
179
  def _extract_command_info(
167
- event_filter, handler_metadata, skip_commands: set
180
+ event_filter,
181
+ handler_metadata,
182
+ skip_commands: set,
168
183
  ) -> tuple[str, str] | None:
169
184
  """从事件过滤器中提取指令信息"""
170
185
  cmd_name = None
@@ -199,11 +214,12 @@ class TelegramPlatformAdapter(Platform):
199
214
  async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
200
215
  if not update.effective_chat:
201
216
  logger.warning(
202
- "Received a start command without an effective chat, skipping /start reply."
217
+ "Received a start command without an effective chat, skipping /start reply.",
203
218
  )
204
219
  return
205
220
  await context.bot.send_message(
206
- chat_id=update.effective_chat.id, text=self.config["start_message"]
221
+ chat_id=update.effective_chat.id,
222
+ text=self.config["start_message"],
207
223
  )
208
224
 
209
225
  async def message_handler(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -213,7 +229,10 @@ class TelegramPlatformAdapter(Platform):
213
229
  await self.handle_msg(abm)
214
230
 
215
231
  async def convert_message(
216
- self, update: Update, context: ContextTypes.DEFAULT_TYPE, get_reply=True
232
+ self,
233
+ update: Update,
234
+ context: ContextTypes.DEFAULT_TYPE,
235
+ get_reply=True,
217
236
  ) -> AstrBotMessage | None:
218
237
  """转换 Telegram 的消息对象为 AstrBotMessage 对象。
219
238
 
@@ -244,7 +263,8 @@ class TelegramPlatformAdapter(Platform):
244
263
  logger.warning("[Telegram] Received a message without a from_user.")
245
264
  return None
246
265
  message.sender = MessageMember(
247
- str(_from_user.id), _from_user.username or "Unknown"
266
+ str(_from_user.id),
267
+ _from_user.username or "Unknown",
248
268
  )
249
269
  message.self_id = str(context.bot.username)
250
270
  message.raw_message = update
@@ -274,7 +294,7 @@ class TelegramPlatformAdapter(Platform):
274
294
  message_str=reply_abm.message_str,
275
295
  text=reply_abm.message_str,
276
296
  qq=reply_abm.sender.user_id,
277
- )
297
+ ),
278
298
  )
279
299
 
280
300
  if update.message.text:
@@ -320,7 +340,7 @@ class TelegramPlatformAdapter(Platform):
320
340
 
321
341
  if message.message_str.strip() == "/start":
322
342
  await self.start(update, context)
323
- return
343
+ return None
324
344
 
325
345
  elif update.message.voice:
326
346
  file = await update.message.voice.get_file()
@@ -358,7 +378,7 @@ class TelegramPlatformAdapter(Platform):
358
378
  file_path = file.file_path
359
379
  if file_path is None:
360
380
  logger.warning(
361
- f"Telegram document file_path is None, cannot save the file {file_name}."
381
+ f"Telegram document file_path is None, cannot save the file {file_name}.",
362
382
  )
363
383
  else:
364
384
  message.message.append(Comp.File(file=file_path, name=file_name))
@@ -369,7 +389,7 @@ class TelegramPlatformAdapter(Platform):
369
389
  file_path = file.file_path
370
390
  if file_path is None:
371
391
  logger.warning(
372
- f"Telegram video file_path is None, cannot save the file {file_name}."
392
+ f"Telegram video file_path is None, cannot save the file {file_name}.",
373
393
  )
374
394
  else:
375
395
  message.message.append(Comp.Video(file=file_path, path=file.file_path))
@@ -1,22 +1,24 @@
1
+ import asyncio
1
2
  import os
2
3
  import re
3
- import asyncio
4
+
4
5
  import telegramify_markdown
6
+ from telegram import ReactionTypeCustomEmoji, ReactionTypeEmoji
7
+ from telegram.ext import ExtBot
8
+
9
+ from astrbot import logger
5
10
  from astrbot.api.event import AstrMessageEvent, MessageChain
6
- from astrbot.api.platform import AstrBotMessage, PlatformMetadata, MessageType
7
11
  from astrbot.api.message_components import (
8
- Plain,
9
- Image,
10
- Reply,
11
12
  At,
12
13
  File,
14
+ Image,
15
+ Plain,
13
16
  Record,
17
+ Reply,
14
18
  )
15
- from telegram.ext import ExtBot
16
- from astrbot.core.utils.io import download_file
17
- from astrbot import logger
19
+ from astrbot.api.platform import AstrBotMessage, MessageType, PlatformMetadata
18
20
  from astrbot.core.utils.astrbot_path import get_astrbot_data_path
19
- from telegram import ReactionTypeEmoji, ReactionTypeCustomEmoji
21
+ from astrbot.core.utils.io import download_file
20
22
 
21
23
 
22
24
  class TelegramPlatformEvent(AstrMessageEvent):
@@ -68,7 +70,10 @@ class TelegramPlatformEvent(AstrMessageEvent):
68
70
 
69
71
  @classmethod
70
72
  async def send_with_client(
71
- cls, client: ExtBot, message: MessageChain, user_name: str
73
+ cls,
74
+ client: ExtBot,
75
+ message: MessageChain,
76
+ user_name: str,
72
77
  ):
73
78
  image_path = None
74
79
 
@@ -104,14 +109,18 @@ class TelegramPlatformEvent(AstrMessageEvent):
104
109
  for chunk in chunks:
105
110
  try:
106
111
  md_text = telegramify_markdown.markdownify(
107
- chunk, max_line_length=None, normalize_whitespace=False
112
+ chunk,
113
+ max_line_length=None,
114
+ normalize_whitespace=False,
108
115
  )
109
116
  await client.send_message(
110
- text=md_text, parse_mode="MarkdownV2", **payload
117
+ text=md_text,
118
+ parse_mode="MarkdownV2",
119
+ **payload,
111
120
  )
112
121
  except Exception as e:
113
122
  logger.warning(
114
- f"MarkdownV2 send failed: {e}. Using plain text instead."
123
+ f"MarkdownV2 send failed: {e}. Using plain text instead.",
115
124
  )
116
125
  await client.send_message(text=chunk, **payload)
117
126
  elif isinstance(i, Image):
@@ -137,8 +146,7 @@ class TelegramPlatformEvent(AstrMessageEvent):
137
146
  await super().send(message)
138
147
 
139
148
  async def react(self, emoji: str | None, big: bool = False):
140
- """
141
- 给原消息添加 Telegram 反应:
149
+ """给原消息添加 Telegram 反应:
142
150
  - 普通 emoji:传入 '👍'、'😂' 等
143
151
  - 自定义表情:传入其 custom_emoji_id(纯数字字符串)
144
152
  - 取消本机器人的反应:传入 None 或空字符串
@@ -216,7 +224,9 @@ class TelegramPlatformEvent(AstrMessageEvent):
216
224
  i.file = path
217
225
 
218
226
  await self.client.send_document(
219
- document=i.file, filename=i.name, **payload
227
+ document=i.file,
228
+ filename=i.name,
229
+ **payload,
220
230
  )
221
231
  continue
222
232
  elif isinstance(i, Record):
@@ -263,7 +273,9 @@ class TelegramPlatformEvent(AstrMessageEvent):
263
273
  if delta and current_content != delta:
264
274
  try:
265
275
  markdown_text = telegramify_markdown.markdownify(
266
- delta, max_line_length=None, normalize_whitespace=False
276
+ delta,
277
+ max_line_length=None,
278
+ normalize_whitespace=False,
267
279
  )
268
280
  await self.client.edit_message_text(
269
281
  text=markdown_text,
@@ -274,7 +286,9 @@ class TelegramPlatformEvent(AstrMessageEvent):
274
286
  except Exception as e:
275
287
  logger.warning(f"Markdown转换失败,使用普通文本: {e!s}")
276
288
  await self.client.edit_message_text(
277
- text=delta, chat_id=payload["chat_id"], message_id=message_id
289
+ text=delta,
290
+ chat_id=payload["chat_id"],
291
+ message_id=message_id,
278
292
  )
279
293
  except Exception as e:
280
294
  logger.warning(f"编辑消息失败(streaming): {e!s}")
@@ -1,24 +1,27 @@
1
- import time
2
1
  import asyncio
3
- import uuid
4
2
  import os
5
- from typing import Awaitable, Any, Callable
3
+ import time
4
+ import uuid
5
+ from collections.abc import Awaitable, Callable
6
+ from typing import Any
7
+
8
+ from astrbot import logger
9
+ from astrbot.core.message.components import Image, Plain, Record
10
+ from astrbot.core.message.message_event_result import MessageChain
6
11
  from astrbot.core.platform import (
7
- Platform,
8
12
  AstrBotMessage,
9
13
  MessageMember,
10
14
  MessageType,
15
+ Platform,
11
16
  PlatformMetadata,
12
17
  )
13
- from astrbot.core.message.message_event_result import MessageChain
14
- from astrbot.core.message.components import Plain, Image, Record # noqa: F403
15
- from astrbot import logger
16
- from .webchat_queue_mgr import webchat_queue_mgr, WebChatQueueMgr
17
- from .webchat_event import WebChatMessageEvent
18
18
  from astrbot.core.platform.astr_message_event import MessageSesion
19
- from ...register import register_platform_adapter
20
19
  from astrbot.core.utils.astrbot_path import get_astrbot_data_path
21
20
 
21
+ from ...register import register_platform_adapter
22
+ from .webchat_event import WebChatMessageEvent
23
+ from .webchat_queue_mgr import WebChatQueueMgr, webchat_queue_mgr
24
+
22
25
 
23
26
  class QueueListener:
24
27
  def __init__(self, webchat_queue_mgr: WebChatQueueMgr, callback: Callable) -> None:
@@ -35,7 +38,7 @@ class QueueListener:
35
38
  await self.callback(data)
36
39
  except Exception as e:
37
40
  logger.error(
38
- f"Error processing message from conversation {conversation_id}: {e}"
41
+ f"Error processing message from conversation {conversation_id}: {e}",
39
42
  )
40
43
  break
41
44
 
@@ -66,7 +69,10 @@ class QueueListener:
66
69
  @register_platform_adapter("webchat", "webchat")
67
70
  class WebChatAdapter(Platform):
68
71
  def __init__(
69
- self, platform_config: dict, platform_settings: dict, event_queue: asyncio.Queue
72
+ self,
73
+ platform_config: dict,
74
+ platform_settings: dict,
75
+ event_queue: asyncio.Queue,
70
76
  ) -> None:
71
77
  super().__init__(event_queue)
72
78
 
@@ -77,11 +83,15 @@ class WebChatAdapter(Platform):
77
83
  os.makedirs(self.imgs_dir, exist_ok=True)
78
84
 
79
85
  self.metadata = PlatformMetadata(
80
- name="webchat", description="webchat", id="webchat"
86
+ name="webchat",
87
+ description="webchat",
88
+ id="webchat",
81
89
  )
82
90
 
83
91
  async def send_by_session(
84
- self, session: MessageSesion, message_chain: MessageChain
92
+ self,
93
+ session: MessageSesion,
94
+ message_chain: MessageChain,
85
95
  ):
86
96
  await WebChatMessageEvent._send(message_chain, session.session_id)
87
97
  await super().send_by_session(session, message_chain)
@@ -106,13 +116,13 @@ class WebChatAdapter(Platform):
106
116
  if isinstance(payload["image_url"], list):
107
117
  for img in payload["image_url"]:
108
118
  abm.message.append(
109
- Image.fromFileSystem(os.path.join(self.imgs_dir, img))
119
+ Image.fromFileSystem(os.path.join(self.imgs_dir, img)),
110
120
  )
111
121
  else:
112
122
  abm.message.append(
113
123
  Image.fromFileSystem(
114
- os.path.join(self.imgs_dir, payload["image_url"])
115
- )
124
+ os.path.join(self.imgs_dir, payload["image_url"]),
125
+ ),
116
126
  )
117
127
  if payload["audio_url"]:
118
128
  if isinstance(payload["audio_url"], list):
@@ -1,11 +1,13 @@
1
+ import base64
1
2
  import os
2
3
  import uuid
3
- import base64
4
+
4
5
  from astrbot.api import logger
5
6
  from astrbot.api.event import AstrMessageEvent, MessageChain
6
- from astrbot.api.message_components import Plain, Image, Record
7
- from astrbot.core.utils.io import download_image_by_url
7
+ from astrbot.api.message_components import Image, Plain, Record
8
8
  from astrbot.core.utils.astrbot_path import get_astrbot_data_path
9
+ from astrbot.core.utils.io import download_image_by_url
10
+
9
11
  from .webchat_queue_mgr import webchat_queue_mgr
10
12
 
11
13
  imgs_dir = os.path.join(get_astrbot_data_path(), "webchat", "imgs")
@@ -26,7 +28,7 @@ class WebChatMessageEvent(AstrMessageEvent):
26
28
  "type": "end",
27
29
  "data": "",
28
30
  "streaming": False,
29
- } # end means this request is finished
31
+ }, # end means this request is finished
30
32
  )
31
33
  return ""
32
34
 
@@ -41,7 +43,7 @@ class WebChatMessageEvent(AstrMessageEvent):
41
43
  "data": data,
42
44
  "streaming": streaming,
43
45
  "chain_type": message.type,
44
- }
46
+ },
45
47
  )
46
48
  elif isinstance(comp, Image):
47
49
  # save image to local
@@ -70,7 +72,7 @@ class WebChatMessageEvent(AstrMessageEvent):
70
72
  "cid": cid,
71
73
  "data": data,
72
74
  "streaming": streaming,
73
- }
75
+ },
74
76
  )
75
77
  elif isinstance(comp, Record):
76
78
  # save record to local
@@ -94,7 +96,7 @@ class WebChatMessageEvent(AstrMessageEvent):
94
96
  "cid": cid,
95
97
  "data": data,
96
98
  "streaming": streaming,
97
- }
99
+ },
98
100
  )
99
101
  else:
100
102
  logger.debug(f"webchat 忽略: {comp.type}")
@@ -118,12 +120,14 @@ class WebChatMessageEvent(AstrMessageEvent):
118
120
  "data": final_data,
119
121
  "streaming": True,
120
122
  "cid": cid,
121
- }
123
+ },
122
124
  )
123
125
  final_data = ""
124
126
  continue
125
127
  final_data += await WebChatMessageEvent._send(
126
- chain, session_id=self.session_id, streaming=True
128
+ chain,
129
+ session_id=self.session_id,
130
+ streaming=True,
127
131
  )
128
132
 
129
133
  await web_chat_back_queue.put(
@@ -132,6 +136,6 @@ class WebChatMessageEvent(AstrMessageEvent):
132
136
  "data": final_data,
133
137
  "streaming": True,
134
138
  "cid": cid,
135
- }
139
+ },
136
140
  )
137
141
  await super().send_streaming(generator, use_fallback)