"""
事件处理
========

NoneBot 内部处理并按优先级分发事件给所有事件响应器，提供了多个插槽以进行事件的预处理等。
"""

import asyncio
from datetime import datetime

from nonebot.log import logger
from nonebot.rule import TrieRule
from nonebot.utils import escape_tag
from nonebot.matcher import matchers, Matcher
from nonebot.typing import Set, Type, Union, Optional, Iterable, NoReturn, Bot, Event
from nonebot.exception import IgnoredException, StopPropagation
from nonebot.typing import EventPreProcessor, RunPreProcessor, EventPostProcessor, RunPostProcessor

_event_preprocessors: Set[EventPreProcessor] = set()
_event_postprocessors: Set[EventPostProcessor] = set()
_run_preprocessors: Set[RunPreProcessor] = set()
_run_postprocessors: Set[RunPostProcessor] = set()


def event_preprocessor(func: EventPreProcessor) -> EventPreProcessor:
    """
    :说明:
      事件预处理。装饰一个函数，使它在每次接收到事件并分发给各响应器之前执行。
    :参数:
      事件预处理函数接收三个参数。

      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前 State
    """
    _event_preprocessors.add(func)
    return func


def event_postprocessor(func: EventPostProcessor) -> EventPostProcessor:
    """
    :说明:
      事件后处理。装饰一个函数，使它在每次接收到事件并分发给各响应器之后执行。
    :参数:
      事件后处理函数接收三个参数。

      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前事件运行前 State
    """
    _event_postprocessors.add(func)
    return func


def run_preprocessor(func: RunPreProcessor) -> RunPreProcessor:
    """
    :说明:
      运行预处理。装饰一个函数，使它在每次事件响应器运行前执行。
    :参数:
      运行预处理函数接收四个参数。

      * ``matcher: Matcher``: 当前要运行的事件响应器
      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前 State
    """
    _run_preprocessors.add(func)
    return func


def run_postprocessor(func: RunPostProcessor) -> RunPostProcessor:
    """
    :说明:
      运行后处理。装饰一个函数，使它在每次事件响应器运行后执行。
    :参数:
      运行后处理函数接收五个参数。

      * ``matcher: Matcher``: 运行完毕的事件响应器
      * ``exception: Optional[Exception]``: 事件响应器运行错误（如果存在）
      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前 State
    """
    _run_postprocessors.add(func)
    return func


async def _check_matcher(priority: int, bot: Bot, event: Event,
                         state: dict) -> Iterable[Type[Matcher]]:
    current_matchers = matchers[priority].copy()

    async def _check(Matcher: Type[Matcher], bot: Bot, event: Event,
                     state: dict) -> Optional[Type[Matcher]]:
        try:
            if await Matcher.check_perm(
                    bot, event) and await Matcher.check_rule(bot, event, state):
                return Matcher
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                f"<r><bg #f8bbd0>Rule check failed for {Matcher}.</bg #f8bbd0></r>"
            )
        return None

    async def _check_expire(Matcher: Type[Matcher]) -> Optional[Type[Matcher]]:
        if Matcher.temp or (Matcher.expire_time and
                            datetime.now() > Matcher.expire_time):
            return Matcher
        return None

    checking_tasks = [
        _check(Matcher, bot, event, state) for Matcher in current_matchers
    ]
    checking_expire_tasks = [
        _check_expire(Matcher) for Matcher in current_matchers
    ]
    results = await asyncio.gather(*checking_tasks, return_exceptions=True)
    expired = await asyncio.gather(*checking_expire_tasks)
    for expired_matcher in filter(lambda x: x and x in results, expired):
        try:
            matchers[priority].remove(expired_matcher)
        except Exception:
            pass
    return filter(lambda x: x, results)


async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
                       state: dict) -> Union[None, NoReturn]:
    logger.info(f"Event will be handled by {Matcher}")

    matcher = Matcher()

    coros = list(
        map(lambda x: x(matcher, bot, event, state), _run_preprocessors))
    if coros:
        try:
            await asyncio.gather(*coros)
        except IgnoredException:
            logger.opt(colors=True).info(
                f"Matcher {matcher} running is <b>cancelled</b>")
            return
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running RunPreProcessors. "
                "Running cancelled!</bg #f8bbd0></r>")
            return

    exception = None

    try:
        logger.debug(f"Running matcher {matcher}")
        await matcher.run(bot, event, state)
    except Exception as e:
        logger.opt(colors=True, exception=e).error(
            f"<r><bg #f8bbd0>Running matcher {matcher} failed.</bg #f8bbd0></r>"
        )
        exception = e

    coros = list(
        map(lambda x: x(matcher, exception, bot, event, state),
            _run_postprocessors))
    if coros:
        try:
            await asyncio.gather(*coros)
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
            )

    if matcher.block:
        raise StopPropagation


async def handle_event(bot: Bot, event: Event):
    """
    :说明:
       处理一个事件。调用该函数以实现分发事件。
    :参数:
      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
    :示例:

    .. code-block:: python

        import asyncio
        asyncio.create_task(handle_event(bot, event))
    """
    show_log = True
    log_msg = f"<m>{bot.type.upper()} </m>| {event.self_id} [{event.name}]: "
    if event.type == "message":
        log_msg += f"Message {event.id} from "
        log_msg += str(event.user_id)
        if event.detail_type == "group":
            log_msg += f"@[群:{event.group_id}]:"

        log_msg += ' "' + "".join(
            map(
                lambda x: escape_tag(str(x))
                if x.type == "text" else f"<le>{escape_tag(str(x))}</le>",
                event.message)) + '"'  # type: ignore
    elif event.type == "notice":
        log_msg += f"Notice {event.raw_event}"
    elif event.type == "request":
        log_msg += f"Request {event.raw_event}"
    elif event.type == "meta_event":
        # log_msg += f"MetaEvent {event.detail_type}"
        show_log = False
    if show_log:
        logger.opt(colors=True).info(log_msg)

    state = {}
    coros = list(map(lambda x: x(bot, event, state), _event_preprocessors))
    if coros:
        try:
            logger.debug("Running PreProcessors...")
            await asyncio.gather(*coros)
        except IgnoredException:
            logger.opt(
                colors=True).info(f"Event {event.name} is <b>ignored</b>")
            return
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running EventPreProcessors. "
                "Event ignored!</bg #f8bbd0></r>")
            return

    # Trie Match
    _, _ = TrieRule.get_value(bot, event, state)

    break_flag = False
    for priority in sorted(matchers.keys()):
        if break_flag:
            break

        if show_log:
            logger.debug(f"Checking for matchers in priority {priority}...")

        run_matchers = await _check_matcher(priority, bot, event, state)

        pending_tasks = [
            _run_matcher(matcher, bot, event, state.copy())
            for matcher in run_matchers
        ]

        results = await asyncio.gather(*pending_tasks, return_exceptions=True)

        for result in results:
            if result is StopPropagation:
                if not break_flag:
                    break_flag = True
                    logger.debug("Stop event propagation")

    coros = list(map(lambda x: x(bot, event, state), _event_postprocessors))
    if coros:
        try:
            logger.debug("Running PostProcessors...")
            await asyncio.gather(*coros)
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running EventPostProcessors</bg #f8bbd0></r>"
            )

nonebot/message.py
"""
事件处理
========

NoneBot 内部处理并按优先级分发事件给所有事件响应器，提供了多个插槽以进行事件的预处理等。
"""

import asyncio
from datetime import datetime

from nonebot.log import logger
from nonebot.rule import TrieRule
from nonebot.utils import escape_tag
from nonebot.matcher import matchers, Matcher
from nonebot.typing import Set, Type, Union, Optional, Iterable, NoReturn, Bot, Event
from nonebot.exception import IgnoredException, StopPropagation
from nonebot.typing import EventPreProcessor, RunPreProcessor, EventPostProcessor, RunPostProcessor

_event_preprocessors: Set[EventPreProcessor] = set()
_event_postprocessors: Set[EventPostProcessor] = set()
_run_preprocessors: Set[RunPreProcessor] = set()
_run_postprocessors: Set[RunPostProcessor] = set()


def event_preprocessor(func: EventPreProcessor) -> EventPreProcessor:
    """
    :说明:
      事件预处理。装饰一个函数，使它在每次接收到事件并分发给各响应器之前执行。
    :参数:
      事件预处理函数接收三个参数。

      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前 State
    """
    _event_preprocessors.add(func)
    return func


def event_postprocessor(func: EventPostProcessor) -> EventPostProcessor:
    """
    :说明:
      事件后处理。装饰一个函数，使它在每次接收到事件并分发给各响应器之后执行。
    :参数:
      事件后处理函数接收三个参数。

      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前事件运行前 State
    """
    _event_postprocessors.add(func)
    return func


def run_preprocessor(func: RunPreProcessor) -> RunPreProcessor:
    """
    :说明:
      运行预处理。装饰一个函数，使它在每次事件响应器运行前执行。
    :参数:
      运行预处理函数接收四个参数。

      * ``matcher: Matcher``: 当前要运行的事件响应器
      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前 State
    """
    _run_preprocessors.add(func)
    return func


def run_postprocessor(func: RunPostProcessor) -> RunPostProcessor:
    """
    :说明:
      运行后处理。装饰一个函数，使它在每次事件响应器运行后执行。
    :参数:
      运行后处理函数接收五个参数。

      * ``matcher: Matcher``: 运行完毕的事件响应器
      * ``exception: Optional[Exception]``: 事件响应器运行错误（如果存在）
      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
      * ``state: dict``: 当前 State
    """
    _run_postprocessors.add(func)
    return func


async def _check_matcher(priority: int, bot: Bot, event: Event,
                         state: dict) -> Iterable[Type[Matcher]]:
    current_matchers = matchers[priority].copy()

    async def _check(Matcher: Type[Matcher], bot: Bot, event: Event,
                     state: dict) -> Optional[Type[Matcher]]:
        try:
            if await Matcher.check_perm(
                    bot, event) and await Matcher.check_rule(bot, event, state):
                return Matcher
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                f"<r><bg #f8bbd0>Rule check failed for {Matcher}.</bg #f8bbd0></r>"
            )
        return None

    async def _check_expire(Matcher: Type[Matcher]) -> Optional[Type[Matcher]]:
        if Matcher.temp or (Matcher.expire_time and
                            datetime.now() > Matcher.expire_time):
            return Matcher
        return None

    checking_tasks = [
        _check(Matcher, bot, event, state) for Matcher in current_matchers
    ]
    checking_expire_tasks = [
        _check_expire(Matcher) for Matcher in current_matchers
    ]
    results = await asyncio.gather(*checking_tasks, return_exceptions=True)
    expired = await asyncio.gather(*checking_expire_tasks)
    for expired_matcher in filter(lambda x: x and x in results, expired):
        try:
            matchers[priority].remove(expired_matcher)
        except Exception:
            pass
    return filter(lambda x: x, results)


async def _run_matcher(Matcher: Type[Matcher], bot: Bot, event: Event,
                       state: dict) -> Union[None, NoReturn]:
    logger.info(f"Event will be handled by {Matcher}")

    matcher = Matcher()

    coros = list(
        map(lambda x: x(matcher, bot, event, state), _run_preprocessors))
    if coros:
        try:
            await asyncio.gather(*coros)
        except IgnoredException:
            logger.opt(colors=True).info(
                f"Matcher {matcher} running is <b>cancelled</b>")
            return
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running RunPreProcessors. "
                "Running cancelled!</bg #f8bbd0></r>")
            return

    exception = None

    try:
        logger.debug(f"Running matcher {matcher}")
        await matcher.run(bot, event, state)
    except Exception as e:
        logger.opt(colors=True, exception=e).error(
            f"<r><bg #f8bbd0>Running matcher {matcher} failed.</bg #f8bbd0></r>"
        )
        exception = e

    coros = list(
        map(lambda x: x(matcher, exception, bot, event, state),
            _run_postprocessors))
    if coros:
        try:
            await asyncio.gather(*coros)
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>"
            )

    if matcher.block:
        raise StopPropagation


async def handle_event(bot: Bot, event: Event):
    """
    :说明:
       处理一个事件。调用该函数以实现分发事件。
    :参数:
      * ``bot: Bot``: Bot 对象
      * ``event: Event``: Event 对象
    :示例:

    .. code-block:: python

        import asyncio
        asyncio.create_task(handle_event(bot, event))
    """
    show_log = True
    log_msg = f"<m>{bot.type.upper()} </m>| {event.self_id} [{event.name}]: "
    if event.type == "message":
        log_msg += f"Message {event.id} from "
        log_msg += str(event.user_id)
        if event.detail_type == "group":
            log_msg += f"@[群:{event.group_id}]:"

        log_msg += ' "' + "".join(
            map(
                lambda x: escape_tag(str(x))
                if x.type == "text" else f"<le>{escape_tag(str(x))}</le>",
                event.message)) + '"'  # type: ignore
    elif event.type == "notice":
        log_msg += f"Notice {event.raw_event}"
    elif event.type == "request":
        log_msg += f"Request {event.raw_event}"
    elif event.type == "meta_event":
        # log_msg += f"MetaEvent {event.detail_type}"
        show_log = False
    if show_log:
        logger.opt(colors=True).info(log_msg)

    state = {}
    coros = list(map(lambda x: x(bot, event, state), _event_preprocessors))
    if coros:
        try:
            logger.debug("Running PreProcessors...")
            await asyncio.gather(*coros)
        except IgnoredException:
            logger.opt(
                colors=True).info(f"Event {event.name} is <b>ignored</b>")
            return
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running EventPreProcessors. "
                "Event ignored!</bg #f8bbd0></r>")
            return

    # Trie Match
    _, _ = TrieRule.get_value(bot, event, state)

    break_flag = False
    for priority in sorted(matchers.keys()):
        if break_flag:
            break

        if show_log:
            logger.debug(f"Checking for matchers in priority {priority}...")

        run_matchers = await _check_matcher(priority, bot, event, state)

        pending_tasks = [
            _run_matcher(matcher, bot, event, state.copy())
            for matcher in run_matchers
        ]

        results = await asyncio.gather(*pending_tasks, return_exceptions=True)

        for result in results:
            if isinstance(result, StopPropagation):
                if not break_flag:
                    break_flag = True
                    logger.debug("Stop event propagation")

    coros = list(map(lambda x: x(bot, event, state), _event_postprocessors))
    if coros:
        try:
            logger.debug("Running PostProcessors...")
            await asyncio.gather(*coros)
        except Exception as e:
            logger.opt(colors=True, exception=e).error(
                "<r><bg #f8bbd0>Error when running EventPostProcessors</bg #f8bbd0></r>"
            )

nonebot/message.py
diff --git a/archive/2.0.0a5/README.md b/archive/2.0.0a6/README.md
similarity index 100%
rename from archive/2.0.0a5/README.md
rename to archive/2.0.0a6/README.md
diff --git a/archive/2.0.0a6/advanced/README.md b/archive/2.0.0a6/advanced/README.md
new file mode 100644
index 000000000000..92c6af3eb19f
--- /dev/null
+++ b/archive/2.0.0a6/advanced/README.md
@@ -0,0 +1,7 @@
+# 深入
+
+## 它如何工作？
+
+<!-- TODO: how to work -->
+
+~~未填坑~~
diff --git a/archive/2.0.0a6/advanced/permission.md b/archive/2.0.0a6/advanced/permission.md
new file mode 100644
index 000000000000..30e200024508
--- /dev/null
+++ b/archive/2.0.0a6/advanced/permission.md
@@ -0,0 +1 @@
+# 权限控制
\ No newline at end of file
diff --git a/archive/2.0.0a6/advanced/runtime-hook.md b/archive/2.0.0a6/advanced/runtime-hook.md
new file mode 100644
index 000000000000..ed3968a48a9d
--- /dev/null
+++ b/archive/2.0.0a6/advanced/runtime-hook.md
@@ -0,0 +1 @@
+# 运行时插槽
\ No newline at end of file
diff --git a/archive/2.0.0a6/advanced/scheduler.md b/archive/2.0.0a6/advanced/scheduler.md
new file mode 100644
index 000000000000..99d906d34a61
--- /dev/null
+++ b/archive/2.0.0a6/advanced/scheduler.md
@@ -0,0 +1 @@
+# 定时任务
\ No newline at end of file
diff --git a/archive/2.0.0a5/api/README.md b/archive/2.0.0a6/api/README.md
similarity index 100%
rename from archive/2.0.0a5/api/README.md
rename to archive/2.0.0a6/api/README.md
diff --git a/archive/2.0.0a5/api/adapters/README.md b/archive/2.0.0a6/api/adapters/README.md
similarity index 100%
rename from archive/2.0.0a5/api/adapters/README.md
rename to archive/2.0.0a6/api/adapters/README.md
diff --git a/archive/2.0.0a5/api/adapters/cqhttp.md b/archive/2.0.0a6/api/adapters/cqhttp.md
similarity index 100%
rename from archive/2.0.0a5/api/adapters/cqhttp.md
rename to archive/2.0.0a6/api/adapters/cqhttp.md
diff --git a/archive/2.0.0a5/api/config.md b/archive/2.0.0a6/api/config.md
similarity index 100%
rename from archive/2.0.0a5/api/config.md
rename to archive/2.0.0a6/api/config.md
diff --git a/archive/2.0.0a5/api/drivers/README.md b/archive/2.0.0a6/api/drivers/README.md
similarity index 100%
rename from archive/2.0.0a5/api/drivers/README.md
rename to archive/2.0.0a6/api/drivers/README.md
diff --git a/archive/2.0.0a5/api/drivers/fastapi.md b/archive/2.0.0a6/api/drivers/fastapi.md
similarity index 100%
rename from archive/2.0.0a5/api/drivers/fastapi.md
rename to archive/2.0.0a6/api/drivers/fastapi.md
diff --git a/archive/2.0.0a5/api/exception.md b/archive/2.0.0a6/api/exception.md
similarity index 100%
rename from archive/2.0.0a5/api/exception.md
rename to archive/2.0.0a6/api/exception.md
diff --git a/archive/2.0.0a5/api/log.md b/archive/2.0.0a6/api/log.md
similarity index 100%
rename from archive/2.0.0a5/api/log.md
rename to archive/2.0.0a6/api/log.md
diff --git a/archive/2.0.0a5/api/matcher.md b/archive/2.0.0a6/api/matcher.md
similarity index 100%
rename from archive/2.0.0a5/api/matcher.md
rename to archive/2.0.0a6/api/matcher.md
diff --git a/archive/2.0.0a5/api/message.md b/archive/2.0.0a6/api/message.md
similarity index 100%
rename from archive/2.0.0a5/api/message.md
rename to archive/2.0.0a6/api/message.md
diff --git a/archive/2.0.0a5/api/nonebot.md b/archive/2.0.0a6/api/nonebot.md
similarity index 100%
rename from archive/2.0.0a5/api/nonebot.md
rename to archive/2.0.0a6/api/nonebot.md
diff --git a/archive/2.0.0a5/api/permission.md b/archive/2.0.0a6/api/permission.md
similarity index 100%
rename from archive/2.0.0a5/api/permission.md
rename to archive/2.0.0a6/api/permission.md
diff --git a/archive/2.0.0a5/api/plugin.md b/archive/2.0.0a6/api/plugin.md
similarity index 100%
rename from archive/2.0.0a5/api/plugin.md
rename to archive/2.0.0a6/api/plugin.md
diff --git a/archive/2.0.0a5/api/rule.md b/archive/2.0.0a6/api/rule.md
similarity index 100%
rename from archive/2.0.0a5/api/rule.md
rename to archive/2.0.0a6/api/rule.md
diff --git a/archive/2.0.0a5/api/sched.md b/archive/2.0.0a6/api/sched.md
similarity index 100%
rename from archive/2.0.0a5/api/sched.md
rename to archive/2.0.0a6/api/sched.md
diff --git a/archive/2.0.0a5/api/typing.md b/archive/2.0.0a6/api/typing.md
similarity index 100%
rename from archive/2.0.0a5/api/typing.md
rename to archive/2.0.0a6/api/typing.md
diff --git a/archive/2.0.0a5/api/utils.md b/archive/2.0.0a6/api/utils.md
similarity index 100%
rename from archive/2.0.0a5/api/utils.md
rename to archive/2.0.0a6/api/utils.md
diff --git a/archive/2.0.0a5/guide/README.md b/archive/2.0.0a6/guide/README.md
similarity index 96%
rename from archive/2.0.0a5/guide/README.md
rename to archive/2.0.0a6/guide/README.md
index 43b7f32557ec..cacb58ac1986 100644
--- a/archive/2.0.0a5/guide/README.md
+++ b/archive/2.0.0a6/guide/README.md
@@ -18,12 +18,6 @@ NoneBot2 是一个可扩展的 Python 异步机器人框架，它会对机器人
 
 需要注意的是，NoneBot 仅支持 Python 3.7+ 及 CQHTTP(OneBot) 插件 v11+。
 
-## 它如何工作？
-
-<!-- TODO: how to work -->
-
-~~未填坑~~
-
 ## 特色
 
 - 提供直观的测试前端
diff --git a/archive/2.0.0a5/guide/basic-configuration.md b/archive/2.0.0a6/guide/basic-configuration.md
similarity index 100%
rename from archive/2.0.0a5/guide/basic-configuration.md
rename to archive/2.0.0a6/guide/basic-configuration.md
diff --git a/archive/2.0.0a5/guide/creating-a-handler.md b/archive/2.0.0a6/guide/creating-a-handler.md
similarity index 100%
rename from archive/2.0.0a5/guide/creating-a-handler.md
rename to archive/2.0.0a6/guide/creating-a-handler.md
diff --git a/archive/2.0.0a5/guide/creating-a-matcher.md b/archive/2.0.0a6/guide/creating-a-matcher.md
similarity index 100%
rename from archive/2.0.0a5/guide/creating-a-matcher.md
rename to archive/2.0.0a6/guide/creating-a-matcher.md
diff --git a/archive/2.0.0a5/guide/creating-a-plugin.md b/archive/2.0.0a6/guide/creating-a-plugin.md
similarity index 100%
rename from archive/2.0.0a5/guide/creating-a-plugin.md
rename to archive/2.0.0a6/guide/creating-a-plugin.md
diff --git a/archive/2.0.0a5/guide/creating-a-project.md b/archive/2.0.0a6/guide/creating-a-project.md
similarity index 100%
rename from archive/2.0.0a5/guide/creating-a-project.md
rename to archive/2.0.0a6/guide/creating-a-project.md
diff --git a/archive/2.0.0a5/guide/end-or-start.md b/archive/2.0.0a6/guide/end-or-start.md
similarity index 79%
rename from archive/2.0.0a5/guide/end-or-start.md
rename to archive/2.0.0a6/guide/end-or-start.md
index f1b0baa98ee1..117801148485 100644
--- a/archive/2.0.0a5/guide/end-or-start.md
+++ b/archive/2.0.0a6/guide/end-or-start.md
@@ -5,3 +5,5 @@
 - 请千万注意事件处理器的优先级设定
 - 在匹配规则中请勿使用耗时极长的函数
 - 同一个用户可以**跨群**(**私聊**)继续他的事件处理（除非做出权限限制，将在后续介绍）
+
+如果你还不能满足，前往 [进阶](../advanced/README.md) 获得更多的功能信息。
diff --git a/archive/2.0.0a5/guide/getting-started.md b/archive/2.0.0a6/guide/getting-started.md
similarity index 100%
rename from archive/2.0.0a5/guide/getting-started.md
rename to archive/2.0.0a6/guide/getting-started.md
diff --git a/archive/2.0.0a5/guide/installation.md b/archive/2.0.0a6/guide/installation.md
similarity index 100%
rename from archive/2.0.0a5/guide/installation.md
rename to archive/2.0.0a6/guide/installation.md
diff --git a/archive/2.0.0a5/guide/loading-a-plugin.md b/archive/2.0.0a6/guide/loading-a-plugin.md
similarity index 76%
rename from archive/2.0.0a5/guide/loading-a-plugin.md
rename to archive/2.0.0a6/guide/loading-a-plugin.md
index bb7db02df95e..b648b4b6295a 100644
--- a/archive/2.0.0a5/guide/loading-a-plugin.md
+++ b/archive/2.0.0a6/guide/loading-a-plugin.md
@@ -83,7 +83,39 @@ if __name__ == "__main__":
 
 <!-- TODO: 子插件 -->
 
-~~待填坑~~
+在插件中同样可以加载子插件，例如如下插件目录结构：
+
+<!-- prettier-ignore-start -->
+:::vue
+foo_plugin
+├── `plugins`
+│   ├── `sub_plugin1`
+│   │  └── \_\_init\_\_.py
+│   └── `sub_plugin2.py`
+├── `__init__.py`
+└── config.py
+:::
+<!-- prettier-ignore-end -->
+
+在插件目录下的 `__init__.py` 中添加如下代码：
+
+```python
+from pathlib import Path
+
+import nonebot
+
+# store all subplugins
+_sub_plugins = set()
+# load sub plugins
+_sub_plugins |= nonebot.load_plugins(
+    str((Path(__file__).parent / "plugins").resolve()))
+```
+
+插件将会被加载并存储于 `_sub_plugins` 中。
+
+:::tip 提示
+如果在父插件中需要定义事件响应器，应在**子插件被加载后**进行定义
+:::
 
 ## 运行结果
 
diff --git a/archive/2.0.0a5/sidebar.config.json b/archive/2.0.0a6/sidebar.config.json
similarity index 87%
rename from archive/2.0.0a5/sidebar.config.json
rename to archive/2.0.0a6/sidebar.config.json
index 94ec57abf3e0..bee7b291fe88 100644
--- a/archive/2.0.0a5/sidebar.config.json
+++ b/archive/2.0.0a6/sidebar.config.json
@@ -15,6 +15,10 @@
           "text": "指南",
           "link": "/guide/"
         },
+        {
+          "text": "进阶",
+          "link": "/advanced/"
+        },
         {
           "text": "API",
           "link": "/api/"
@@ -22,6 +26,10 @@
         {
           "text": "插件广场",
           "link": "/plugin-store"
+        },
+        {
+          "text": "更新日志",
+          "link": "/changelog"
         }
       ],
       "sidebarDepth": 2,
@@ -52,6 +60,19 @@
             ]
           }
         ],
+        "/advanced/": [
+          {
+            "title": "进阶",
+            "collapsable": false,
+            "sidebar": "auto",
+            "children": [
+              "",
+              "scheduler",
+              "permission",
+              "runtime-hook"
+            ]
+          }
+        ],
         "/api/": [
           {
             "title": "NoneBot Api Reference",
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 009bc113eacf..8faed7a543a2 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -79,8 +79,10 @@ module.exports = context => ({
         nav: [
           { text: "主页", link: "/" },
           { text: "指南", link: "/guide/" },
+          { text: "进阶", link: "/advanced/" },
           { text: "API", link: "/api/" },
-          { text: "插件广场", link: "/plugin-store" }
+          { text: "插件广场", link: "/plugin-store" },
+          { text: "更新日志", link: "/changelog" }
         ],
         sidebarDepth: 2,
         sidebar: {
@@ -110,6 +112,19 @@ module.exports = context => ({
               ]
             }
           ],
+          "/advanced/": [
+            {
+              title: "进阶",
+              collapsable: false,
+              sidebar: "auto",
+              children: [
+                "",
+                "scheduler",
+                "permission",
+                "runtime-hook"
+              ]
+            }
+          ],
           "/api/": [
             {
               title: "NoneBot Api Reference",
diff --git a/docs/.vuepress/versions.json b/docs/.vuepress/versions.json
index aa00d565a6b9..b28457942352 100644
--- a/docs/.vuepress/versions.json
+++ b/docs/.vuepress/versions.json
@@ -1,4 +1,4 @@
 [
-  "2.0.0a5",
+  "2.0.0a6",
   "2.0.0a4"
 ]
\ No newline at end of file
diff --git a/docs/advanced/README.md b/docs/advanced/README.md
new file mode 100644
index 000000000000..92c6af3eb19f
--- /dev/null
+++ b/docs/advanced/README.md
@@ -0,0 +1,7 @@
+# 深入
+
+## 它如何工作？
+
+<!-- TODO: how to work -->
+
+~~未填坑~~
diff --git a/docs/advanced/permission.md b/docs/advanced/permission.md
new file mode 100644
index 000000000000..30e200024508
--- /dev/null
+++ b/docs/advanced/permission.md
@@ -0,0 +1 @@
+# 权限控制
\ No newline at end of file
diff --git a/docs/advanced/runtime-hook.md b/docs/advanced/runtime-hook.md
new file mode 100644
index 000000000000..ed3968a48a9d
--- /dev/null
+++ b/docs/advanced/runtime-hook.md
@@ -0,0 +1 @@
+# 运行时插槽
\ No newline at end of file
diff --git a/docs/advanced/scheduler.md b/docs/advanced/scheduler.md
new file mode 100644
index 000000000000..99d906d34a61
--- /dev/null
+++ b/docs/advanced/scheduler.md
@@ -0,0 +1 @@
+# 定时任务
\ No newline at end of file
diff --git a/docs/guide/README.md b/docs/guide/README.md
index 43b7f32557ec..cacb58ac1986 100644
--- a/docs/guide/README.md
+++ b/docs/guide/README.md
@@ -18,12 +18,6 @@ NoneBot2 是一个可扩展的 Python 异步机器人框架，它会对机器人
 
 需要注意的是，NoneBot 仅支持 Python 3.7+ 及 CQHTTP(OneBot) 插件 v11+。
 
-## 它如何工作？
-
-<!-- TODO: how to work -->
-
-~~未填坑~~
-
 ## 特色
 
 - 提供直观的测试前端
diff --git a/docs/guide/end-or-start.md b/docs/guide/end-or-start.md
index f1b0baa98ee1..117801148485 100644
--- a/docs/guide/end-or-start.md
+++ b/docs/guide/end-or-start.md
@@ -5,3 +5,5 @@
 - 请千万注意事件处理器的优先级设定
 - 在匹配规则中请勿使用耗时极长的函数
 - 同一个用户可以**跨群**(**私聊**)继续他的事件处理（除非做出权限限制，将在后续介绍）
+
+如果你还不能满足，前往 [进阶](../advanced/README.md) 获得更多的功能信息。
diff --git a/docs/guide/loading-a-plugin.md b/docs/guide/loading-a-plugin.md
index bb7db02df95e..b648b4b6295a 100644
--- a/docs/guide/loading-a-plugin.md
+++ b/docs/guide/loading-a-plugin.md
@@ -83,7 +83,39 @@ if __name__ == "__main__":
 
 <!-- TODO: 子插件 -->
 
-~~待填坑~~
+在插件中同样可以加载子插件，例如如下插件目录结构：
+
+<!-- prettier-ignore-start -->
+:::vue
+foo_plugin
+├── `plugins`
+│   ├── `sub_plugin1`
+│   │  └── \_\_init\_\_.py
+│   └── `sub_plugin2.py`
+├── `__init__.py`
+└── config.py
+:::
+<!-- prettier-ignore-end -->
+
+在插件目录下的 `__init__.py` 中添加如下代码：
+
+```python
+from pathlib import Path
+
+import nonebot
+
+# store all subplugins
+_sub_plugins = set()
+# load sub plugins
+_sub_plugins |= nonebot.load_plugins(
+    str((Path(__file__).parent / "plugins").resolve()))
+```
+
+插件将会被加载并存储于 `_sub_plugins` 中。
+
+:::tip 提示
+如果在父插件中需要定义事件响应器，应在**子插件被加载后**进行定义
+:::
 
 ## 运行结果
 
diff --git a/nonebot/message.py b/nonebot/message.py
index af0849a5f36d..90af9a96adce 100644
--- a/nonebot/message.py
+++ b/nonebot/message.py
@@ -244,7 +244,7 @@ async def handle_event(bot: Bot, event: Event):
         results = await asyncio.gather(*pending_tasks, return_exceptions=True)
 
         for result in results:
-            if result is StopPropagation:
+            if isinstance(result, StopPropagation):
                 if not break_flag:
                     break_flag = True
                     logger.debug("Stop event propagation")
diff --git a/pages/changelog.md b/pages/changelog.md
new file mode 100644
index 000000000000..ef8bad8fedab
--- /dev/null
+++ b/pages/changelog.md
@@ -0,0 +1,14 @@
+---
+sidebar: auto
+---
+
+# 更新日志
+
+## v2.0.0a6
+
+- 修复 block 失效问题 (hotfix)
+
+## v2.0.0a5
+
+- 更新插件指南文档
+- 修复临时事件响应器运行后删除造成的多次响应问题
diff --git a/poetry.lock b/poetry.lock
index 9e3185f498f7..a4d8902d6a75 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1026,7 +1026,7 @@ reference = "aliyun"
 
 [[package]]
 name = "regex"
-version = "2020.11.11"
+version = "2020.11.13"
 description = "Alternative regular expression module, to replace re."
 category = "main"
 optional = true
@@ -1120,7 +1120,7 @@ reference = "aliyun"
 
 [[package]]
 name = "sphinx"
-version = "3.3.0"
+version = "3.3.1"
 description = "Python documentation generator"
 category = "dev"
 optional = false
@@ -1366,7 +1366,7 @@ reference = "aliyun"
 
 [[package]]
 name = "urllib3"
-version = "1.26.1"
+version = "1.26.2"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 category = "main"
 optional = false
@@ -1508,14 +1508,14 @@ reference = "aliyun"
 
 [extras]
 cli = ["nb-cli"]
-full = ["nb-cli", "nonebot-test"]
+full = ["nb-cli", "nonebot-test", "apscheduler"]
 scheduler = ["apscheduler"]
 test = ["nonebot-test"]
 
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.7"
-content-hash = "3760d7d6c8119c6fa29e171cabbecc5e705d2bb3faff82f7211a19e27925abfe"
+content-hash = "1d1ddae66f1495be07658ec5a004c4819445f785317c556030c9edb05612917e"
 
 [metadata.files]
 aiofiles = [
@@ -1909,47 +1909,47 @@ pyyaml = [
     {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
 ]
 regex = [
-    {file = "regex-2020.11.11-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dd7bee615680d940dd44ac0a479f2bc5f73d6ca63a5915cd8d30739c14ca522c"},
-    {file = "regex-2020.11.11-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3002ee2d4e8bbe4656237627203d8290a562d1fc1962deee470905ab63570345"},
-    {file = "regex-2020.11.11-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:064d2fc83ab4ee0055fcc1ef38ec60e505742850a40061f854ac64cb3d8d6dd3"},
-    {file = "regex-2020.11.11-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:83a390a653c13be1ab26287240df1fd9324ca8a0d31b603fa57cd7d9520648fa"},
-    {file = "regex-2020.11.11-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:412969d58ecd4f576510ec88bcb7602e9e582bbef78859ed8c9ca4de4f9e891c"},
-    {file = "regex-2020.11.11-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:ccfea4911ac28a8f744096bce1559e0bd86b09a53c8a9d5856ca8e1f5f4de1f5"},
-    {file = "regex-2020.11.11-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:cefcdb2ac3b67fd9f7244820ce1965c8cf352366199cc1358d67c6cc3c5c8bbc"},
-    {file = "regex-2020.11.11-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:9e8b3187f6beea8e56cb4b33c35049cbe376cf69aefaee5bc035309d88c98ca5"},
-    {file = "regex-2020.11.11-cp36-cp36m-win32.whl", hash = "sha256:787e44e5f4fd027dd90b5ee0240b05dc1752cb43c2903617f25baa495fe551e9"},
-    {file = "regex-2020.11.11-cp36-cp36m-win_amd64.whl", hash = "sha256:a9f76d9122359b09e38f27cd9c41729169171cf0fd73ec5b22cc4628f9e486ca"},
-    {file = "regex-2020.11.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6d128368def4b0cd95c0fc9d99a89ae73c083b25e67f27a410830e30f9df0edc"},
-    {file = "regex-2020.11.11-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:df50ba964812606663ca9d23d374036bc5ae3d71e86168409cdd84ca7948d8a3"},
-    {file = "regex-2020.11.11-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d1e57c16c4840f1c3543507742e99b8398609474a0e6a6925476914479de3488"},
-    {file = "regex-2020.11.11-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6e50b3b417ab2fd67bfa6235f0df4782fe2ff8be83f0c4435e1dc43d25052ee8"},
-    {file = "regex-2020.11.11-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bb17a7fe9c47167337009ce18cd6e6b3edf3ca0063bf6bed6ce02515129c016a"},
-    {file = "regex-2020.11.11-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:826d0119f14f9a9ce25999a13ed5922c785b50e469800f6e5a6721318650ef49"},
-    {file = "regex-2020.11.11-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:8cc3717146ce4040419639cf45455663a002a554806ddac46304acc5bd41dae2"},
-    {file = "regex-2020.11.11-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:86ad88c7c2512094a85b0a01ce053bab1e28eafb8f3868bb8c22f4903e33f147"},
-    {file = "regex-2020.11.11-cp37-cp37m-win32.whl", hash = "sha256:e03867f3baf64ecab47dfc9ddb58afc67acb6a0f80f6cf8ff9fa82962ec4d1cd"},
-    {file = "regex-2020.11.11-cp37-cp37m-win_amd64.whl", hash = "sha256:56d1e298bb6482d0466399a6383181bf2627c37ad414e205b3ce0f85aa140be7"},
-    {file = "regex-2020.11.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:19ac2bf0048a2f4d460ee20647e84ca160512a7ee8af844dc9207720778470f1"},
-    {file = "regex-2020.11.11-cp38-cp38-manylinux1_i686.whl", hash = "sha256:84ab584dcb5e81815040d86148805a808acb0bee303d19638fe2f9488d704bc1"},
-    {file = "regex-2020.11.11-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4159ecf20dffea07f4a7241b2a236f90eb622c7e8caab9f43caba5f27ca37284"},
-    {file = "regex-2020.11.11-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:8060be04baec546fe3afa6975d2998e15d1b655d7255f0e6b0ed3f482cccc218"},
-    {file = "regex-2020.11.11-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:cdb98be55db1b94c950822cbc10d3d768f01e184365851ebb42cd377486ced7b"},
-    {file = "regex-2020.11.11-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:11d9100bd874ce8b2a037db9150e732cd768359fc25fe5f77973208aa24eb13e"},
-    {file = "regex-2020.11.11-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:0951c78fa4cb26d1278a4b3784fcf973fc97ec39c07483328a74b034b0cc569c"},
-    {file = "regex-2020.11.11-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:c8b1ad791debd67221fb1266f8d09730ae927acacb32d0dad9fd07a7d341a28f"},
-    {file = "regex-2020.11.11-cp38-cp38-win32.whl", hash = "sha256:beae9db1545f8116cfc9301a9601e9c975bb56ca22a38ac0fe06a72c3460f31a"},
-    {file = "regex-2020.11.11-cp38-cp38-win_amd64.whl", hash = "sha256:48e94218f06317b6d32feb4ecff8b6025695450009bcb3291fb23daf79689431"},
-    {file = "regex-2020.11.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c67fd5f3ad81f8301184354014e8e7510ab77e0c7e450a427d77f28ae8effbef"},
-    {file = "regex-2020.11.11-cp39-cp39-manylinux1_i686.whl", hash = "sha256:e7cdd5ee8053c82607432b7ebad37e2ece54548fef2b254f7bce6f7831904586"},
-    {file = "regex-2020.11.11-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:394b5be4fa72354a78763b317f82997ad881896dd4a860e429a6fa74afaacb07"},
-    {file = "regex-2020.11.11-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:3b46a4c73ec1f25361147a7a0fd86084f3627dc78d09bcbe14e70db12683efec"},
-    {file = "regex-2020.11.11-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:267d1b13f863e664150948ce2a9ed4927bf4ac7a068780f1ee8af83352aa17a2"},
-    {file = "regex-2020.11.11-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:68267a7a5fb0bd9676b86f967143b6a6ecefb3eed4042ecc9e7f0e014aef8f74"},
-    {file = "regex-2020.11.11-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:e899b69dd5d26655cb454835ea2fceb18832c9ee9c4fb45dc4cf8a6089d35312"},
-    {file = "regex-2020.11.11-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:396411bb5a7849aeda9c49873b8295919fdc118c50b57122b09cb2097047c118"},
-    {file = "regex-2020.11.11-cp39-cp39-win32.whl", hash = "sha256:32f8714c4bcc4b0d2aa259b1647e3c5b6cfe2e923c6c124234a5e03408224227"},
-    {file = "regex-2020.11.11-cp39-cp39-win_amd64.whl", hash = "sha256:bf02ab95ff5261ba108725dbd795bf6395eaac1b8468b41472d82d35b12b0295"},
-    {file = "regex-2020.11.11.tar.gz", hash = "sha256:0a235841237d4487329bcabcb5b902858f7967f5e684e08e968367f25b2c3d37"},
+    {file = "regex-2020.11.13-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85"},
+    {file = "regex-2020.11.13-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70"},
+    {file = "regex-2020.11.13-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee"},
+    {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5"},
+    {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7"},
+    {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31"},
+    {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa"},
+    {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6"},
+    {file = "regex-2020.11.13-cp36-cp36m-win32.whl", hash = "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e"},
+    {file = "regex-2020.11.13-cp36-cp36m-win_amd64.whl", hash = "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884"},
+    {file = "regex-2020.11.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b"},
+    {file = "regex-2020.11.13-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88"},
+    {file = "regex-2020.11.13-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0"},
+    {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1"},
+    {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0"},
+    {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512"},
+    {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba"},
+    {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538"},
+    {file = "regex-2020.11.13-cp37-cp37m-win32.whl", hash = "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4"},
+    {file = "regex-2020.11.13-cp37-cp37m-win_amd64.whl", hash = "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444"},
+    {file = "regex-2020.11.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f"},
+    {file = "regex-2020.11.13-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d"},
+    {file = "regex-2020.11.13-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af"},
+    {file = "regex-2020.11.13-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f"},
+    {file = "regex-2020.11.13-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b"},
+    {file = "regex-2020.11.13-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8"},
+    {file = "regex-2020.11.13-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5"},
+    {file = "regex-2020.11.13-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b"},
+    {file = "regex-2020.11.13-cp38-cp38-win32.whl", hash = "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c"},
+    {file = "regex-2020.11.13-cp38-cp38-win_amd64.whl", hash = "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683"},
+    {file = "regex-2020.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc"},
+    {file = "regex-2020.11.13-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364"},
+    {file = "regex-2020.11.13-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e"},
+    {file = "regex-2020.11.13-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e"},
+    {file = "regex-2020.11.13-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917"},
+    {file = "regex-2020.11.13-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b"},
+    {file = "regex-2020.11.13-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9"},
+    {file = "regex-2020.11.13-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c"},
+    {file = "regex-2020.11.13-cp39-cp39-win32.whl", hash = "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"},
+    {file = "regex-2020.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d"},
+    {file = "regex-2020.11.13.tar.gz", hash = "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562"},
 ]
 requests = [
     {file = "requests-2.25.0-py2.py3-none-any.whl", hash = "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998"},
@@ -1972,8 +1972,8 @@ snowballstemmer = [
     {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"},
 ]
 sphinx = [
-    {file = "Sphinx-3.3.0-py3-none-any.whl", hash = "sha256:3abdb2c57a65afaaa4f8573cbabd5465078eb6fd282c1e4f87f006875a7ec0c7"},
-    {file = "Sphinx-3.3.0.tar.gz", hash = "sha256:1c21e7c5481a31b531e6cbf59c3292852ccde175b504b00ce2ff0b8f4adc3649"},
+    {file = "Sphinx-3.3.1-py3-none-any.whl", hash = "sha256:d4e59ad4ea55efbb3c05cde3bfc83bfc14f0c95aa95c3d75346fcce186a47960"},
+    {file = "Sphinx-3.3.1.tar.gz", hash = "sha256:1e8d592225447104d1172be415bc2972bd1357e3e12fdc76edf2261105db4300"},
 ]
 sphinx-markdown-builder = []
 sphinxcontrib-applehelp = [
@@ -2023,8 +2023,8 @@ untokenize = [
     {file = "untokenize-0.1.1.tar.gz", hash = "md5:50d325dff09208c624cc603fad33bb0d"},
 ]
 urllib3 = [
-    {file = "urllib3-1.26.1-py2.py3-none-any.whl", hash = "sha256:61ad24434555a42c0439770462df38b47d05d9e8e353d93ec3742900975e3e65"},
-    {file = "urllib3-1.26.1.tar.gz", hash = "sha256:097116a6f16f13482d2a2e56792088b9b2920f4eb6b4f84a2c90555fb673db74"},
+    {file = "urllib3-1.26.2-py2.py3-none-any.whl", hash = "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"},
+    {file = "urllib3-1.26.2.tar.gz", hash = "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08"},
 ]
 uvicorn = [
     {file = "uvicorn-0.11.8-py3-none-any.whl", hash = "sha256:4b70ddb4c1946e39db9f3082d53e323dfd50634b95fd83625d778729ef1730ef"},
diff --git a/pyproject.toml b/pyproject.toml
index afb696c4815c..c9f38794205e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,13 +1,13 @@
 [tool.poetry]
 name = "nonebot2"
-version = "2.0.0-alpha.5"
+version = "2.0.0-alpha.6"
 description = "An asynchronous python bot framework."
 authors = ["yanyongyu <yanyongyu_1@126.com>"]
 license = "MIT"
 readme = "README.md"
-homepage = "https://docs.nonebot.dev/"
+homepage = "https://v2.nonebot.dev/"
 repository = "https://github.com/nonebot/nonebot2"
-documentation = "https://docs.nonebot.dev/"
+documentation = "https://v2.nonebot.dev/"
 keywords = ["bot", "qq", "qqbot", "mirai", "coolq"]
 classifiers = [
   "Development Status :: 5 - Production/Stable",
@@ -43,7 +43,7 @@ sphinx-markdown-builder = { git = "https://github.com/nonebot/sphinx-markdown-bu
 cli = ["nb-cli"]
 test = ["nonebot-test"]
 scheduler = ["apscheduler"]
-full = ["nb-cli", "nonebot-test", "scheduler"]
+full = ["nb-cli", "nonebot-test", "apscheduler"]
 
 [[tool.poetry.source]]
 name = "aliyun"

修复阻止事件传递信号无效的问题
抛出的异常应为 StopPropagation 的一个实例
