"""AstrBot 课表渲染插件主模块""" from typing import Any, AsyncGenerator from astrbot.api.event import filter, AstrMessageEvent, MessageEventResult from astrbot.api.star import Context, Star from astrbot.api import logger from astrbot.core import AstrBotConfig from astrbot.core.message.message_event_result import MessageEventResult from .schedule_utils import convert_tuple_schedule_to_dict from .schedule_renderer import ScheduleRenderer class SuanPlugin(Star): def __init__(self, context: Context, config: AstrBotConfig): super().__init__(context) self.config = config self.renderer = ScheduleRenderer(config) async def initialize(self): """可选择实现异步的插件初始化方法,当实例化该插件类之后会自动调用该方法。""" @filter.llm_tool(name='render_course_schedule_png') async def render_course_schedule_png(self, event: AstrMessageEvent, schedule: list[tuple], title: str) -> \ AsyncGenerator[MessageEventResult, Any]: """将完整的每周课表渲染为 png 格式的图片,或者说是得到一张课程表图片。 在调用之前可能需要先对 schedule 进行格式转换,本工具接收的数据类型是 list[tuple]。此外,应当尽可能将代表周数的元素从列表压缩为字符串以节约工具参数长度。 Args: schedule (list[tuple]): 包含数个元组的列表。每个元组的内部是按照顺序的如下元素: 0. str: 课程名称 1. str: 授课教师(可以为 None) 2. str: 教室(可以为 None) 3. str | list: 形如 `1-17` 表示从第 1 周到第 17 周;`1-3,5,7-17` 也是受支持的;list[int] 也是受支持的。 4. int: 星期几,int (1-7) 5. list: 当日第几节课,一般是相邻的两节,list[int] title (str): 图片名称,会被渲染在图片的顶部,格式上作为课程表标题。 """ # 转换为字典格式 schedule_dict = convert_tuple_schedule_to_dict(schedule) try: # 生成 HTML 内容 html_content = self.renderer.generate_html(schedule_dict, title) # 渲染为 PNG image_data = await self.renderer.render_to_png( html_content, debug_path='/home/fanfan/test.html' ) # 返回图片消息 from astrbot.api.message_components import Image yield event.chain_result([Image.fromBytes(image_data)]) except Exception as e: logger.error(f"渲染课表失败: {e}") yield event.plain_result(f"生成课表图片时出错: {str(e)}") @filter.llm_tool(name='render_daily_course_schedule_png') async def render_daily_course_schedule_png(self, event: AstrMessageEvent, schedule: list[tuple], title: str, weekday: int = None) -> \ AsyncGenerator[MessageEventResult, Any]: """将单日课程表渲染为 png 格式的图片,以垂直卡片形式展示当天的课程安排。 与 render_course_schedule_png 不同,此工具只展示一天的课程,以卡片列表形式呈现,更适合查看特定日期的详细安排。 Args: schedule (list[tuple]): 包含数个元组的列表。每个元组的内部是按照顺序的如下元素: 0. str: 课程名称 1. str: 授课教师(可以为 None) 2. str: 教室(可以为 None) 3. str | list: 形如 `1-17` 表示从第 1 周到第 17 周;list[int] 也是受支持的。 4. int: 星期几,int (1-7),此参数在单日视图中可选 5. list: 当日第几节课,list[int] title (str): 图片标题,如 "张三的课表"。 weekday (int, optional): 星期几 (1-7),用于在副标题显示。如为 None 则不显示星期信息。 """ # 转换为字典格式 schedule_dict = convert_tuple_schedule_to_dict(schedule) # 获取星期名称 weekday_names = {1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六', 7: '周日'} weekday_name = weekday_names.get(weekday, '') if weekday else '' try: # 生成单日 HTML 内容 html_content = self.renderer.generate_daily_html(schedule_dict, title, weekday_name) # 渲染为 PNG(使用较小的宽度适合单列卡片) image_data = await self.renderer.render_to_png( html_content, debug_path='/home/fanfan/test_daily.html', width=680 ) # 返回图片消息 from astrbot.api.message_components import Image yield event.chain_result([Image.fromBytes(image_data)]) except Exception as e: logger.error(f"渲染单日课表失败: {e}") yield event.plain_result(f"生成单日课表图片时出错: {str(e)}") async def terminate(self): """可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""