Skip to content

Commit

Permalink
Merge pull request #174 from Soulter/refactor-v3.3.0
Browse files Browse the repository at this point in the history
重写工程,提高稳定性
  • Loading branch information
Soulter authored Jul 26, 2024
2 parents 3db9367 + 6f5f365 commit b9a8994
Show file tree
Hide file tree
Showing 112 changed files with 3,412 additions and 3,242 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.10.13-bullseye
FROM python:3.10-slim
WORKDIR /AstrBot

COPY . /AstrBot/
Expand Down
66 changes: 17 additions & 49 deletions addons/plugins/helloworld/main.py
Original file line number Diff line number Diff line change
@@ -1,64 +1,32 @@
import os
import shutil
from nakuru.entities.components import *
flag_not_support = False
try:
from util.plugin_dev.api.v1.bot import Context, AstrMessageEvent, CommandResult
from util.plugin_dev.api.v1.config import *
from util.plugin_dev.api.v1.bot import (
AstrMessageEvent,
CommandResult,
)
except ImportError:
flag_not_support = True
print("导入接口失败。请升级到 AstrBot 最新版本。")


'''
注意改插件名噢!格式:XXXPlugin 或 Main
小提示:把此模板仓库 fork 之后 clone 到机器人文件夹下的 addons/plugins/ 目录下,然后用 Pycharm/VSC 等工具打开可获更棒的编程体验(自动补全等)
注意以格式 XXXPlugin 或 Main 来修改插件名。
提示:把此模板仓库 fork 之后 clone 到机器人文件夹下的 addons/plugins/ 目录下,然后用 Pycharm/VSC 等工具打开可获更棒的编程体验(自动补全等)
'''
class HelloWorldPlugin:
"""
初始化函数, 可以选择直接pass
AstrBot 会传递 context 给插件。
- context.register_commands: 注册指令
- context.register_task: 注册任务
- context.message_handler: 消息处理器(平台类插件用)
"""
def __init__(self) -> None:
pass
def __init__(self, context: Context) -> None:
self.context = context
self.context.register_commands("helloworld", "helloworld", "内置测试指令。", 1, self.helloworld)

"""
机器人程序会调用此函数。
"""
def run(self, ame: AstrMessageEvent):
if ame.message_str.startswith("helloworld"): # 如果消息文本以"helloworld"开头
return CommandResult(
hit=True, # 代表插件会响应此消息
success=True, # 插件响应类型为成功响应
message_chain=[Plain("Hello World!!")], # 消息链
command_name="helloworld" # 指令名
)
return CommandResult(
hit=False, # 插件不会响应此消息
success=False,
message_chain=None
)
"""
插件元信息。
当用户输入 plugin v 插件名称 时,会调用此函数,返回帮助信息。
返回参数要求(必填):dict{
"name": str, # 插件名称
"desc": str, # 插件简短描述
"help": str, # 插件帮助信息
"version": str, # 插件版本
"author": str, # 插件作者
"repo": str, # 插件仓库地址 [ 可选 ]
"homepage": str, # 插件主页 [ 可选 ]
}
指令处理函数。
- 需要接收两个参数:message: AstrMessageEvent, context: Context
- 返回 CommandResult 对象
"""
def info(self):
return {
"name": "helloworld",
"desc": "这是 AstrBot 的默认插件,支持关键词回复。",
"help": "输入 /keyword 查看关键词回复帮助。",
"version": "v1.3",
"author": "Soulter",
"repo": "https://github.com/Soulter/helloworld"
}
def helloworld(self, message: AstrMessageEvent, context: Context):
return CommandResult().message("Hello, World!")
4 changes: 2 additions & 2 deletions addons/plugins/helloworld/metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: helloworld # 这是你的插件的唯一识别名。
desc: 这是 AstrBot 的默认插件,支持关键词回复。 # 插件简短描述
help: 输入 /keyword 查看关键词回复帮助。 # 插件的帮助信息
desc: 这是 AstrBot 的默认插件
help:
version: v1.3 # 插件版本号。格式:v1.1.1 或者 v1.1
author: Soulter # 作者
repo: https://github.com/Soulter/helloworld # 插件的仓库地址
110 changes: 110 additions & 0 deletions astrbot/bootstrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import asyncio
import traceback
from astrbot.message.handler import MessageHandler
from astrbot.persist.helper import dbConn
from dashboard.server import AstrBotDashBoard
from model.provider.provider import Provider
from model.command.manager import CommandManager
from model.command.internal_handler import InternalCommandHandler
from model.plugin.manager import PluginManager
from model.platform.manager import PlatformManager
from typing import Dict, List, Union
from type.types import Context
from SparkleLogging.utils.core import LogManager
from logging import Logger
from util.cmd_config import CmdConfig
from util.metrics import MetricUploader
from util.config_utils import *
from util.updator.astrbot_updator import AstrBotUpdator

logger: Logger = LogManager.GetLogger(log_name='astrbot')


class AstrBotBootstrap():
def __init__(self) -> None:
self.context = Context()
self.config_helper: CmdConfig = CmdConfig()

# load configs and ensure the backward compatibility
init_configs()
try_migrate_config()
self.configs = inject_to_context(self.context)
logger.info("AstrBot v" + self.context.version)
self.context.config_helper = self.config_helper

# apply proxy settings
http_proxy = self.context.base_config.get("http_proxy")
https_proxy = self.context.base_config.get("https_proxy")
if http_proxy:
os.environ['HTTP_PROXY'] = http_proxy
if https_proxy:
os.environ['HTTPS_PROXY'] = https_proxy
os.environ['NO_PROXY'] = 'https://api.sgroup.qq.com'

if http_proxy and https_proxy:
logger.info(f"使用代理: {http_proxy}, {https_proxy}")
else:
logger.info("未使用代理。")

async def run(self):
self.command_manager = CommandManager()
self.plugin_manager = PluginManager(self.context)
self.updator = AstrBotUpdator()
self.cmd_handler = InternalCommandHandler(self.command_manager, self.plugin_manager)
self.db_conn_helper = dbConn()

# load llm provider
self.llm_instance: Provider = None
self.load_llm()

self.message_handler = MessageHandler(self.context, self.command_manager, self.db_conn_helper, self.llm_instance)
self.platfrom_manager = PlatformManager(self.context, self.message_handler)
self.dashboard = AstrBotDashBoard(self.context, plugin_manager=self.plugin_manager, astrbot_updator=self.updator)
self.metrics_uploader = MetricUploader(self.context)

self.context.metrics_uploader = self.metrics_uploader
self.context.updator = self.updator
self.context.plugin_updator = self.plugin_manager.updator
self.context.message_handler = self.message_handler

# load plugins, plugins' commands.
self.load_plugins()
self.command_manager.register_from_pcb(self.context.plugin_command_bridge)

# load platforms
platform_tasks = self.load_platform()
# load metrics uploader
metrics_upload_task = asyncio.create_task(self.metrics_uploader.upload_metrics(), name="metrics-uploader")
# load dashboard
self.dashboard.run_http_server()
dashboard_task = asyncio.create_task(self.dashboard.ws_server(), name="dashboard")
tasks = [metrics_upload_task, dashboard_task, *platform_tasks, *self.context.ext_tasks]
tasks = [self.handle_task(task) for task in tasks]
await asyncio.gather(*tasks)

async def handle_task(self, task: Union[asyncio.Task, asyncio.Future]):
while True:
try:
result = await task
return result
except Exception as e:
logger.error(traceback.format_exc())
logger.error(f"{task.get_name()} 任务发生错误,将在 5 秒后重试。")
await asyncio.sleep(5)

def load_llm(self):
if 'openai' in self.configs and \
len(self.configs['openai']['key']) and \
self.configs['openai']['key'][0] is not None:
from model.provider.openai_official import ProviderOpenAIOfficial
from model.command.openai_official_handler import OpenAIOfficialCommandHandler
self.openai_command_handler = OpenAIOfficialCommandHandler(self.command_manager)
self.llm_instance = ProviderOpenAIOfficial(self.context)
self.openai_command_handler.set_provider(self.llm_instance)
logger.info("已启用 OpenAI API 支持。")

def load_plugins(self):
self.plugin_manager.plugin_reload()

def load_platform(self):
return self.platfrom_manager.load_platforms()
Loading

0 comments on commit b9a8994

Please sign in to comment.