def require(self, module: str) -> Union[Channel, Any]: logger.debug(f"require {module}") if module in self.alive_channel_name_mapping: return self.alive_channel_name_mapping[module] channel = Channel(module) channel_token = channel_instance.set(channel) try: imported_module = importlib.import_module(module, module) channel._py_module = imported_module with self.behaviour_interface.require_context(module) as interface: for cube in channel.content: try: interface.allocate_cube(cube) except: logger.exception(f"an error occurred while loading the module's cube: {module}::{cube}") raise finally: channel_instance.reset(channel_token) self.channels.append(channel) if self.broadcast: token = saya_instance.set(self) self.broadcast.postEvent(SayaModuleInstalled( module=module, channel=channel, )) saya_instance.reset(token) return channel
def require_resolve(self, module: str) -> Channel: """导入模块, 并注入 Channel, 模块完成内容注册后返回该 Channel Args: module (str): 需为可被当前运行时访问的 Python Module 的引入路径 Returns: Channel: 已注册了内容的 Channel. """ channel = Channel(module) channel_token = channel_instance.set(channel) try: imported_module = importlib.import_module(module, module) channel._py_module = imported_module with self.behaviour_interface.require_context(module) as interface: for cube in channel.content: try: interface.allocate_cube(cube) except: logger.exception( f"an error occurred while loading the module's cube: {module}::{cube}" ) raise finally: channel_instance.reset(channel_token) return channel
def create_main_channel(self) -> Channel: """创建不可被卸载的 `__main__` 主程序模块 Returns: Channel: 属性 `name` 值为 `__main__`, 且无法被 `uninstall_channel` 卸载的模块. """ may_current = self.channels.get("__main__") if may_current: return may_current main_channel = Channel("__main__") self.channels["__main__"] = main_channel if self.broadcast: from .event import SayaModuleInstalled token = saya_instance.set(self) self.broadcast.postEvent( SayaModuleInstalled( module="__main__", channel=main_channel, )) saya_instance.reset(token) return main_channel
def uninstall_channel(self, channel: Channel): """卸载指定的 Channel Args: channel (Channel): 需要卸载的 Channel Raises: TypeError: 提供的 Channel 不在本 Saya 实例内 ValueError: 尝试卸载 __main__, 即主程序所属的模块 """ if channel not in self.channels.values(): raise TypeError("assert an existed channel") if channel.module == "__main__": raise ValueError("main channel cannot uninstall") # TODO: builtin signal(async or sync) if self.broadcast: from .event import SayaModuleUninstall token = saya_instance.set(self) self.broadcast.postEvent( SayaModuleUninstall( module=channel.module, channel=channel, )) saya_instance.reset(token) with self.behaviour_interface.require_context( channel.module) as interface: for cube in channel.content: try: interface.release_cube(cube) except: logger.exception( f"an error occurred while loading the module's cube: {channel.module}::{cube}" ) raise del self.channels[channel.module] channel._py_module = None if sys.modules.get(channel.module): del sys.modules[channel.module] if self.broadcast: from .event import SayaModuleUninstalled token = saya_instance.set(self) self.broadcast.postEvent( SayaModuleUninstalled(module=channel.module, )) saya_instance.reset(token)
def create_main_channel(self) -> Channel: may_current = self.alive_channel_name_mapping.get("__main__") if may_current: return may_current main_channel = Channel("__main__") self.channels.append(main_channel) if self.broadcast: token = saya_instance.set(self) self.broadcast.postEvent(SayaModuleInstalled( module="__main__", channel=main_channel, )) saya_instance.reset(token) return main_channel
def reload_channel(self, channel: Channel) -> None: """重载指定的模块 Args: channel (Channel): 指定需要重载的模块, 请使用 channels.get 方法获取 Raises: TypeError: 没有给定需要被重载的模块(`channel` 与 `module` 都不给定) ValueError: 没有通过 `module` 找到对应的 Channel """ self.uninstall_channel(channel) new_channel: Channel = self.require_resolve(channel.module) channel._name = new_channel._name channel._author = new_channel._author channel._description = new_channel._description channel._export = new_channel._export channel._py_module = new_channel._py_module channel.content = new_channel.content self.channels[channel.module] = channel
from .api import query from graia.application import GraiaMiraiApplication from graia.application.entry import GroupMessage from graia.application.group import Group, Member from graia.application.message.chain import MessageChain from graia.application.message.elements.internal import At, Plain from graia.saya import Saya from graia.saya.builtins.broadcast.behaviour import ListenerSchema from graia.saya.channel import Channel saya = Saya.current() channel = Channel.current() config = saya.current_env()["genshin"] @channel.use(ListenerSchema(listening_events=[GroupMessage])) async def genshin( app: GraiaMiraiApplication, group: Group, message: MessageChain, member: Member ): if message.asDisplay().startswith("!genshin "): uid = message.asDisplay().split(" ")[1] if len(uid) != 9: await app.sendGroupMessage( group, MessageChain.create([At(member.id), Plain(" Invalid uid!")]) ) return _s = await query(config["cookie"], uid) await app.sendGroupMessage( group, MessageChain.create([At(member.id), Plain(f" {_s}")]) )