Skip to content

Commit ca92da9

Browse files
committed
Feature: Add Increaser
1 parent 1d5dd5e commit ca92da9

File tree

4 files changed

+69
-9
lines changed

4 files changed

+69
-9
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,22 @@ cmd2 = on_startswith("cmd2")
138138
async def _(): ...
139139
```
140140

141+
手动管理限制器使用记录的增加操作,适用于没有成功完成事件处理时避免给用户添加限制。
142+
```python
143+
from nonebot_plugin_limiter import Increaser
144+
145+
cmd = on_startswith("cmd")
146+
@cmd.handle(parameterless=[
147+
Cooldown(UserScope(), 100, limit = 2, set_increaser = True)
148+
])
149+
async def _(increaser: Increaser):
150+
if <not_meet_condition>:
151+
await cmd.finish("Run failed")
152+
else:
153+
increaser.execute() # 这会给该实体添加一条使用记录
154+
await cmd.finish("Run successed")
155+
```
156+
141157
使用固定窗口策略实现每日签到
142158
```python
143159
dailysign = on_startswith("签到")

nonebot_plugin_limiter/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
from .entity import SceneScope as SceneScope
2929
from .entity import UserSceneScope as UserSceneScope
3030
from .entity import UserScope as UserScope
31+
from .handler import Increaser as Increaser
3132
from .persist import load_usage_data as load_usage_data
3233
from .persist import save_usage_data as save_usage_data

nonebot_plugin_limiter/cooldown.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from nonebot.matcher import Matcher
1111
from nonebot.params import Depends
1212
from nonebot.rule import Rule as Rule
13-
from nonebot.typing import _DependentCallable
13+
from nonebot.typing import T_State, _DependentCallable
1414
from nonebot_plugin_alconna import UniMessage
1515
from tzlocal import get_localzone
1616

@@ -33,6 +33,7 @@ def _limit_dep_wrapper(limit: int | _DependentCallable[int]) -> _DependentCallab
3333
limit_dep = limit
3434
return limit_dep
3535

36+
# region: FixWindow
3637
@dataclass
3738
class FixWindowUsage:
3839
start_time: datetime
@@ -48,6 +49,7 @@ def Cooldown(
4849
*,
4950
limit: int | _DependentCallable[int] = 5,
5051
reject: None | str | Message | MessageSegment | MessageTemplate | UniMessage = None,
52+
set_increaser: bool = False,
5153
name: None | str = None,
5254
):
5355
"""
@@ -120,6 +122,7 @@ async def _limiter_dependency(
120122
bot: Bot,
121123
matcher: Matcher,
122124
event: Event,
125+
state: T_State,
123126
entity_id: str = Depends(entity_id_dep),
124127
limit: int = Depends(limit_dep),
125128
) -> None:
@@ -138,21 +141,30 @@ async def _limiter_dependency(
138141

139142
# Calculate reset time based on when the limitation was set
140143
reset_time = trigger.get_next_fire_time(usage.start_time, now)
141-
142144
assert reset_time is not None, "reset_time should not be None"
143-
if now >= reset_time:
145+
146+
def _increase_action():
144147
usage.start_time = now
145148
usage.available = limit - 1
146-
return
147149

150+
if now >= reset_time:
151+
if set_increaser:
152+
state["plugin_limiter:increaser"] = _increase_action
153+
else:
154+
_increase_action()
155+
return # Didn't exceed
156+
157+
# Exceed
148158
if isinstance(reject, UniMessage):
149159
await reject.finish(event, bot)
150160
else:
151161
await matcher.finish(reject)
152162

153163
return Depends(_limiter_dependency)
154164

165+
# endregin
155166

167+
# region: SlidingWindow
156168
@dataclass
157169
class SlidingWindowUsage:
158170
timestamps: deque[datetime] = field(default_factory=deque)
@@ -167,6 +179,7 @@ def SlidingWindowCooldown(
167179
*,
168180
limit: int | _DependentCallable[int] = 5,
169181
reject: None | str | Message | MessageSegment | MessageTemplate | UniMessage = None,
182+
set_increaser: bool = False,
170183
name: None | str = None,
171184
):
172185
"""
@@ -191,6 +204,10 @@ def SlidingWindowCooldown(
191204
可选,当超出限制时的响应行为。默认为 `None`。
192205
- 若为 `str` 或消息对象,将作为限制使用时的提示消息发送给用户。
193206
207+
set_increaser (bool):
208+
可选,是否获取限制器的增加器。默认为 False。
209+
- 当启用该选项时,限制器默认的自增将会关闭,需要在事件处理时依赖获取 Increaser 并手动操作增加。
210+
194211
name (None | str):
195212
可选,设置当前限制器的使用统计集合。默认为 `None` ,即私有集合。
196213
- 当传入 `str` ,将创建或加入一个同名公共集合,可用于与其他命令的限制器共享使用统计。
@@ -230,6 +247,7 @@ async def _limiter_dependency(
230247
bot: Bot,
231248
matcher: Matcher,
232249
event: Event,
250+
state: T_State,
233251
entity_id: str = Depends(entity_id_dep),
234252
limit: int = Depends(limit_dep),
235253
) -> None:
@@ -246,13 +264,22 @@ async def _limiter_dependency(
246264
while usage.timestamps and (now - usage.timestamps[0]).total_seconds() >= window_length:
247265
usage.timestamps.popleft()
248266

249-
if len(usage.timestamps) < limit:
267+
def _increase_action():
250268
usage.timestamps.append(now)
251-
return
252269

270+
if len(usage.timestamps) < limit:
271+
if set_increaser:
272+
state["plugin_limiter:increaser"] = _increase_action
273+
else:
274+
_increase_action()
275+
return # Didn't exceed
276+
277+
# Exceeded
253278
if isinstance(reject, UniMessage):
254279
await reject.finish(event, bot)
255280
else:
256281
await matcher.finish(reject)
257282

258283
return Depends(_limiter_dependency)
284+
285+
# endregin

nonebot_plugin_limiter/handler.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
1+
from collections.abc import Callable
2+
from typing import Annotated
3+
14
from nonebot.params import Depends
2-
from nonebot.typing import T_State, _DependentCallable
5+
from nonebot.typing import T_State
6+
7+
8+
class _FuncWrapper:
9+
def __init__(self, func: Callable) -> None:
10+
self._func = func
11+
12+
def execute(self):
13+
self._func()
14+
15+
def get_increaser(state: T_State):
16+
ret = state.get("plugin_limiter:increaser")
17+
if ret is None:
18+
raise KeyError("Cannot get increaser, make sure you have enabled `set_increaser` in cooldown policy.")
19+
return _FuncWrapper(ret)
320

4-
class Limiter:
5-
pass
21+
Increaser = Annotated[_FuncWrapper, Depends(get_increaser)]

0 commit comments

Comments
 (0)