async def run( self, bot: Bot, event: Event, state: T_State, stack: Optional[AsyncExitStack] = None, dependency_cache: Optional[T_DependencyCache] = None, ): try: await self.simple_run(bot, event, state, stack, dependency_cache) except RejectedException: await self.resolve_reject() type_ = await self.update_type(bot, event) permission = await self.update_permission(bot, event) Matcher.new( type_, Rule(), permission, self.handlers, temp=True, priority=0, block=True, plugin=self.plugin, module=self.module, expire_time=datetime.now() + bot.config.session_expire_timeout, default_state=self.state, default_parser=self.__class__._default_parser, default_type_updater=self.__class__._default_type_updater, default_permission_updater=self.__class__._default_permission_updater, ) except PausedException: type_ = await self.update_type(bot, event) permission = await self.update_permission(bot, event) Matcher.new( type_, Rule(), permission, self.handlers, temp=True, priority=0, block=True, plugin=self.plugin, module=self.module, expire_time=datetime.now() + bot.config.session_expire_timeout, default_state=self.state, default_parser=self.__class__._default_parser, default_type_updater=self.__class__._default_type_updater, default_permission_updater=self.__class__._default_permission_updater, ) except FinishedException: pass
async def run(self, bot: "Bot", event: "Event", state: T_State): b_t = current_bot.set(bot) e_t = current_event.set(event) try: # Refresh preprocess state state_ = await self._default_state_factory( bot, event) if self._default_state_factory else self.state state_.update(state) for _ in range(len(self.handlers)): handler = self.handlers.pop(0) await self.run_handler(handler, bot, event, state_) except RejectedException: self.handlers.insert(0, handler) # type: ignore Matcher.new( "message", Rule(), USER(event.get_session_id(), perm=self.permission), # type:ignore self.handlers, temp=True, priority=0, block=True, module=self.module, default_state=self.state, expire_time=datetime.now() + bot.config.session_expire_timeout) except PausedException: Matcher.new( "message", Rule(), USER(event.get_session_id(), perm=self.permission), # type:ignore self.handlers, temp=True, priority=0, block=True, module=self.module, default_state=self.state, expire_time=datetime.now() + bot.config.session_expire_timeout) except FinishedException: pass except StopPropagation: self.block = True finally: logger.info(f"Matcher {self} running complete") current_bot.reset(b_t) current_event.reset(e_t)
def sv_sw(name: str, usage: Union[str, Message, MessageSegment] = "", hierarchy: str = "top") -> Rule: """ :Summary: 使用此规则可以控制在不同群内的功能开关 :Args: ``name``: 功能名字,使用相同name的功能以相同的开关控制 ``usage``: 功能说明,可传入Message来添加图片信息 ``hierarchy``: 层级,查看帮助时top以外的功能不会显示在总菜单中,而是在指定层级的功能中显示 """ if name not in func_ls: func_ls[name] = [usage, hierarchy] async def _checker(bot: Bot, event: GroupMessageEvent, state: T_State): if hasattr(event, 'group_id') and str(event.group_id) in group_func_off\ and name in group_func_off[str(event.group_id)]: return False else: return True return Rule(_checker)
def check(command_name: str, event_type: Event = GroupMessageEvent) -> Rule: """Check the policy of each command by name.""" _name = command_name async def _check(bot: Bot, event: Event, state: dict) -> bool: """Rule wrapper for "check" item in the policy control.""" logger.debug('Checking command: [%s].' % _name) if not isinstance(event, event_type): return False bid = f'{event.self_id}' gid = f'{event.group_id}' sid = event.user_id try: # Check the whitelist policy by name. in_whitelist = ('+' not in policy_config[bid][gid][_name] or sid in policy_config[bid][gid][_name]['+']) # Check the blacklist policy by name. not_in_blacklist = ('-' not in policy_config[bid][gid][_name] or sid not in policy_config[bid][gid][_name]['-']) # Combine the whitelist and blacklist together return in_whitelist and not_in_blacklist except Exception: return True return Rule(_check)
def on_metaevent( rule: Optional[Union[Rule, T_RuleChecker]] = None, *, handlers: Optional[List[Union[T_Handler, Dependent]]] = None, temp: bool = False, priority: int = 1, block: bool = False, state: Optional[T_State] = None, _depth: int = 0, ) -> Type[Matcher]: """ 注册一个元事件响应器。 参数: rule: 事件响应规则 handlers: 事件处理函数列表 temp: 是否为临时事件响应器(仅执行一次) priority: 事件响应器优先级 block: 是否阻止事件向更低优先级传递 state: 默认 state """ matcher = Matcher.new( "meta_event", Rule() & rule, Permission(), temp=temp, priority=priority, block=block, handlers=handlers, plugin=_current_plugin.get(), module=_get_matcher_module(_depth + 1), default_state=state, ) _store_matcher(matcher) return matcher
def new(cls, type_: str = "", rule: Rule = Rule(), permission: Permission = Permission(), handlers: Optional[list] = None, temp: bool = False, priority: int = 1, block: bool = False, *, module: Optional[str] = None, default_state: Optional[dict] = None, expire_time: Optional[datetime] = None) -> Type["Matcher"]: """创建新的 Matcher Returns: Type["Matcher"]: 新的 Matcher 类 """ NewMatcher = type( "Matcher", (Matcher, ), { "module": module, "type": type_, "rule": rule, "permission": permission, "handlers": handlers or [], "temp": temp, "expire_time": expire_time, "priority": priority, "block": block, "_default_state": default_state or {} }) matchers[priority].append(NewMatcher) return NewMatcher
def raw_keyword(keyword: str) -> Rule: """Ensure the raw message contains the target keyword.""" async def _raw_keyword(bot: Bot, event: Event, state: dict) -> bool: """Rule wrapper for raw_keyword.""" return keyword in str(event.message) return Rule(_raw_keyword)
def to_me(): if plugin_config.haruka_to_me: from nonebot.rule import to_me return to_me() async def _to_me(bot: Bot, event: Event, state: dict): return True return Rule(_to_me)
def check_banlist() -> Rule: ''' 检查目标是否存在于封禁名单 :return: bool ''' async def _chech_banlist(bot: Bot, event: Event, state: dict) -> bool: # 获取目标信息 user = str(event.user_id) # 名单目录 BAN_LIST_USER_PATH = Path( '.') / 'ATRI' / 'utils' / 'utils_rule' / 'ban_list_user.json' # 检查文件是否存在,如不存在,自动创建并写入默认值 if not BAN_LIST_USER_PATH.is_file(): with open(BAN_LIST_USER_PATH, 'w') as f: f.write(json.dumps({})) # 读取文件 with open(BAN_LIST_USER_PATH, 'r') as f: data_user = json.load(f) return user not in data_user return Rule(_chech_banlist)
def check_white_list_all() -> Rule: """ :说明: 私聊消息全都上,群聊消息则判断是否为指定群聊 :参数: 无 """ async def _check(bot: Bot, event: Event, state: T_State) -> bool: if isinstance(event, GroupMessageEvent): if event.group_id in bot.config.GroupList.values(): return True else: return False elif isinstance(event, PrivateMessageEvent): if event.message_type == 'private': return True else: return False else: return False return Rule(_check) # type:ignore
def to_me(): if config.haruka_to_me: from nonebot.rule import to_me return to_me() async def _to_me(bot: Bot, event: Event, state: T_State) -> bool: return True return Rule(_to_me)
def on(type: str = "", rule: Optional[Union[Rule, RuleChecker]] = None, permission: Optional[Permission] = None, *, handlers: Optional[List[Handler]] = None, temp: bool = False, priority: int = 1, block: bool = False, state: Optional[dict] = None) -> Type[Matcher]: """ :说明: 注册一个基础事件响应器,可自定义类型。 :参数: * ``type: str``: 事件响应器类型 * ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则 * ``permission: Optional[Permission]``: 事件响应权限 * ``handlers: Optional[List[Handler]]``: 事件处理函数列表 * ``temp: bool``: 是否为临时事件响应器(仅执行一次) * ``priority: int``: 事件响应器优先级 * ``block: bool``: 是否阻止事件向更低优先级传递 * ``state: Optional[dict]``: 默认的 state :返回: - ``Type[Matcher]`` """ matcher = Matcher.new(type, Rule() & rule, permission or Permission(), temp=temp, priority=priority, block=block, handlers=handlers, default_state=state) _tmp_matchers.add(matcher) return matcher
def on_metaevent(rule: Optional[Union[Rule, RuleChecker]] = None, *, handlers: Optional[List[Handler]] = None, temp: bool = False, priority: int = 1, block: bool = False, state: Optional[dict] = None) -> Type[Matcher]: """ :说明: 注册一个元事件响应器。 :参数: * ``rule: Optional[Union[Rule, RuleChecker]]``: 事件响应规则 * ``handlers: Optional[List[Handler]]``: 事件处理函数列表 * ``temp: bool``: 是否为临时事件响应器(仅执行一次) * ``priority: int``: 事件响应器优先级 * ``block: bool``: 是否阻止事件向更低优先级传递 * ``state: Optional[dict]``: 默认的 state :返回: - ``Type[Matcher]`` """ matcher = Matcher.new("meta_event", Rule() & rule, Permission(), temp=temp, priority=priority, block=block, handlers=handlers, default_state=state) _tmp_matchers.add(matcher) return matcher
def __init__(self, type_: str = "", rule: Optional[Rule] = None, permission: Optional[Permission] = None, handlers: Optional[list] = None, temp: bool = False, priority: int = 1, block: bool = False, *, module: Optional[str] = None, default_state: Optional[dict] = None, expire_time: Optional[datetime] = None): """ :说明: 创建一个事件响应器组合,参数为默认值,与 ``Matcher.new`` 一致 """ self.matchers: List[Type[Matcher]] = [] """ :类型: ``List[Type[Matcher]]`` :说明: 组内事件响应器列表 """ self.type = type_ self.rule = rule or Rule() self.permission = permission or Permission() self.handlers = handlers self.temp = temp self.priority = priority self.block = block self.module = module self.expire_time = expire_time self._default_state = default_state self._default_parser: Optional[ArgsParser] = None
def chat_me() -> Rule: """ :说明: 通过 ``event.is_tome()`` 判断事件是否与机器人有关 :参数: * 无 """ async def _chat_me(bot: "Bot", event: "Event", state: T_State) -> bool: if event.is_tome(): try: if event.group_id: group_id = event.group_id except: group_id = None try: if group_id in nonebot.get_driver().config.dict()['bangroup']: logger.info('{} 处在黑名单,拒绝回复'.format(group_id)) return False if event.user_id in nonebot.get_driver().config.dict( )['bangroup']: logger.info('{} 处在黑名单,拒绝回复'.format(event.user_id)) return False except: return True return True else: return False return Rule(_chat_me)
def on_request(self, docs: str, block: bool = True) -> Type[Matcher]: a = 0 cmd_list = self._load_cmds() while True: _type = "request" + str(a) if _type not in cmd_list: break else: a += 1 cmd_list[_type] = CommandInfo(type=_type, docs=docs, aliases=list()).dict() self._save_cmds(cmd_list) matcher = Matcher.new( "request", Rule() & self.rule, Permission(), temp=self.temp, priority=self.priority, block=block, handlers=self.handlers, default_state=self.state, ) return matcher
async def run(self, bot: Bot, event: Event, state: dict): b_t = current_bot.set(bot) e_t = current_event.set(event) try: # Refresh preprocess state self.state.update(state) for _ in range(len(self.handlers)): handler = self.handlers.pop(0) annotation = typing.get_type_hints(handler) BotType = annotation.get("bot") if BotType and inspect.isclass(BotType) and not isinstance( bot, BotType): continue await handler(bot, event, self.state) except RejectedException: self.handlers.insert(0, handler) # type: ignore Matcher.new( self.type, Rule(), USER(event.user_id, perm=self.permission), # type:ignore self.handlers, temp=True, priority=0, block=True, module=self.module, default_state=self.state, expire_time=datetime.now() + bot.config.session_expire_timeout) except PausedException: Matcher.new( self.type, Rule(), USER(event.user_id, perm=self.permission), # type:ignore self.handlers, temp=True, priority=0, block=True, module=self.module, default_state=self.state, expire_time=datetime.now() + bot.config.session_expire_timeout) except FinishedException: pass finally: logger.info(f"Matcher {self} running complete") current_bot.reset(b_t) current_event.reset(e_t)
def on_metaevent(rule: Union[Rule, RuleChecker] = Rule(), *, handlers: Optional[List[Handler]] = None, temp: bool = False, priority: int = 1, block: bool = False, state: Optional[dict] = None) -> Type[Matcher]: matcher = Matcher.new("meta_event", Rule() & rule, Permission(), temp=temp, priority=priority, block=block, handlers=handlers, default_state=state) _tmp_matchers.add(matcher) return matcher
def check_switch(func_name: str, notice: bool) -> Rule: async def _check_switch(bot: Bot, event: GroupMessageEvent, state: dict) -> bool: # 获取目标信息 group = event.group_id return check_control_function(func_name, group) return Rule(_check_switch)
def ckimg(file: str) -> Rule: async def _ckimg(bot: Bot, event: Event, state: dict) -> bool: for seg in event.message: if seg.type == "image" and seg.data["file"] == file: return True return False return Rule(_ckimg)
def on_notice(rule: Union[Rule, RuleChecker] = Rule(), *, handlers=[], temp=False, priority: int = 1, block: bool = False, state={}) -> Type[Matcher]: matcher = Matcher.new("notice", Rule() & rule, Permission(), temp=temp, priority=priority, block=block, handlers=handlers, default_state=state) _tmp_matchers.add(matcher) return matcher
def on_message(rule: Union[Rule, RuleChecker] = Rule(), permission: Permission = Permission(), *, handlers: Optional[list] = None, temp: bool = False, priority: int = 1, block: bool = True, state: Optional[dict] = None) -> Type[Matcher]: matcher = Matcher.new("message", Rule() & rule, permission, temp=temp, priority=priority, block=block, handlers=handlers, default_state=state) _tmp_matchers.add(matcher) return matcher
def is_in_service(service: str) -> Rule: async def _is_in_service(bot, event, state) -> bool: user = str(event.user_id) if isinstance(event, GroupMessageEvent): return sv.auth_service(service, user, str(event.group_id)) else: return sv.auth_service(service, user, None) return Rule(_is_in_service)
def keyword(*keywords: str, normal: bool = True) -> Rule: async def _keyword(bot: Bot, event: CQEvent, state: T_State) -> bool: if event.get_type() != "message": return False text = event.get_plaintext() if normal: text = normalize_str(text) return bool(text and any(kw in text for kw in keywords)) return Rule(_keyword)
def simple_command(cmd: str, aliases: set = None) -> Rule: """Recognize a command that does not contain any parameters.""" commands = set([cmd]) | (aliases or set()) # generate the commands async def _simple_command(bot: Bot, event: Event, state: dict) -> bool: """Rule wrapper for simple_command.""" return str(event.message).strip() in commands return Rule(_simple_command)
def check_sepi() -> Rule: """检查目标是否是涩批""" async def _check_sepi(bot: Bot, event: Event, state: dict) -> bool: if event.user_id in SP_list: await bot.send(event, "你可少冲点吧!涩批!哼唧") return False else: return True return Rule(_check_sepi)
def isPixivURL() -> Rule: async def isPixivURL_(bot: "Bot", event: "Event", state: T_State) -> bool: if event.get_type() != "message": return False msg = str(event.get_message()) if re.findall("https://www.pixiv.net/artworks/(\d+)|illust_id=(\d+)", msg): return True return False return Rule(isPixivURL_)
def check_service(self, only_to_me: bool = False, only_group: bool = True) -> Rule: async def _cs(bot: Bot, event: CQEvent, state: T_State) -> bool: if not 'group_id' in event.__dict__: return not only_group else: group_id = event.group_id return self.check_enabled(group_id) and not priv.check_block_group(group_id) and priv.check_priv(event, self.use_priv) rule = Rule(_cs) if only_to_me: rule = rule & (to_me()) return rule
def decorator(func: Callable): matcher = on_message(rule=Rule(fullmatch_checker), **kwargs) @wraps(func) @self._pre_check(only_to_me=only_to_me) async def wrapper(bot: Bot, event: Event, state: T_State): await func(bot, event) logger.info( f'消息{event.get_session_id()}已被on_fullmatch处理器{func.__name__}处理。' ) matcher.handle()(wrapper)
def new(cls, type_: str = "", rule: Optional[Rule] = None, permission: Optional[Permission] = None, handlers: Optional[List[Handler]] = None, temp: bool = False, priority: int = 1, block: bool = False, *, module: Optional[str] = None, default_state: Optional[dict] = None, expire_time: Optional[datetime] = None) -> Type["Matcher"]: """ :说明: 创建一个新的事件响应器,并存储至 `matchers <#matchers>`_ :参数: * ``type_: str``: 事件响应器类型,与 ``event.type`` 一致时触发,空字符串表示任意 * ``rule: Optional[Rule]``: 匹配规则 * ``permission: Optional[Permission]``: 权限 * ``handlers: Optional[List[Handler]]``: 事件处理函数列表 * ``temp: bool``: 是否为临时事件响应器,即触发一次后删除 * ``priority: int``: 响应优先级 * ``block: bool``: 是否阻止事件向更低优先级的响应器传播 * ``module: Optional[str]``: 事件响应器所在模块名称 * ``default_state: Optional[dict]``: 默认状态 ``state`` * ``expire_time: Optional[datetime]``: 事件响应器最终有效时间点,过时即被删除 :返回: - ``Type[Matcher]``: 新的事件响应器类 """ NewMatcher = type( "Matcher", (Matcher, ), { "module": module, "type": type_, "rule": rule or Rule(), "permission": permission or Permission(), "handlers": handlers or [], "temp": temp, "expire_time": expire_time, "priority": priority, "block": block, "_default_state": default_state or {} }) matchers[priority].append(NewMatcher) return NewMatcher