Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion nonebot/internal/matcher/matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from contextlib import AsyncExitStack, contextmanager
from contextvars import ContextVar
from dataclasses import dataclass
from datetime import datetime, timedelta
from datetime import UTC, datetime, timedelta
import inspect
from pathlib import Path
import sys
Expand Down Expand Up @@ -257,6 +257,9 @@ def new(
else None
)

if isinstance(expire_time, datetime) and expire_time.utcoffset() is not None:
expire_time = expire_time.astimezone(UTC)

NewMatcher = type(
cls.__name__,
(cls,),
Expand Down
18 changes: 13 additions & 5 deletions nonebot/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import contextlib
from contextlib import AsyncExitStack
from datetime import datetime
from datetime import UTC, datetime
from typing import TYPE_CHECKING, Any

import anyio
Expand Down Expand Up @@ -361,10 +361,18 @@ async def _check_matcher(
返回:
bool: 是否符合运行条件
"""
if Matcher.expire_time and datetime.now() > Matcher.expire_time:
with contextlib.suppress(Exception):
Matcher.destroy()
return False
if Matcher.expire_time:
expire_time = Matcher.expire_time
if expire_time.utcoffset() is not None:
expire_time = expire_time.astimezone(UTC)
now = datetime.now(UTC)
else:
now = datetime.now()

if now > expire_time:
with contextlib.suppress(Exception):
Matcher.destroy()
return False

try:
if not await Matcher.check_perm(bot, event, stack, dependency_cache):
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ dev = [
test = [
"trio >=0.27.0",
"nonebug >=0.4.1, <0.5.0",
"tzdata >=2024.1",
"wsproto >=1.2.0, <2.0.0",
"werkzeug >=2.3.6, <4.0.0",
"pytest-cov >=7.0.0, <8.0.0",
Expand Down
7 changes: 7 additions & 0 deletions tests/plugins/matcher/matcher_expire.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

from nonebot.matcher import Matcher

test_temp_matcher = Matcher.new("test", temp=True)
test_datetime_matcher = Matcher.new(
"test", expire_time=datetime.now() - timedelta(seconds=1)
)
test_aware_datetime_matcher = Matcher.new(
"test",
expire_time=datetime(
2000, 11, 5, 1, 30, tzinfo=ZoneInfo("America/New_York"), fold=1
),
)
test_timedelta_matcher = Matcher.new("test", expire_time=timedelta(seconds=-1))
26 changes: 26 additions & 0 deletions tests/test_matcher/test_matcher.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import UTC, datetime
from pathlib import Path
import sys

Expand Down Expand Up @@ -349,6 +350,31 @@ async def test_datetime_expire(app: App):
assert test_datetime_matcher not in matchers[test_datetime_matcher.priority]


@pytest.mark.anyio
async def test_aware_datetime_expire(app: App):
from plugins.matcher.matcher_expire import test_aware_datetime_matcher

assert test_aware_datetime_matcher.expire_time == datetime(
2000, 11, 5, 6, 30, tzinfo=UTC
)

event = make_fake_event()()
with app.provider.context(
{test_aware_datetime_matcher.priority: [test_aware_datetime_matcher]}
):
async with app.test_matcher(test_aware_datetime_matcher) as ctx:
bot = ctx.create_bot()
assert (
test_aware_datetime_matcher
in matchers[test_aware_datetime_matcher.priority]
)
await check_and_run_matcher(test_aware_datetime_matcher, bot, event, {})
assert (
test_aware_datetime_matcher
not in matchers[test_aware_datetime_matcher.priority]
)


@pytest.mark.anyio
async def test_timedelta_expire(app: App):
from plugins.matcher.matcher_expire import test_timedelta_matcher
Expand Down
37 changes: 25 additions & 12 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading