Skip to content

Commit bc8e165

Browse files
authored
✨ feat(plugins): Enhance PluginExtraData with ignore_statistics and limits features (#2098)
- Added ignore_statistics field to PluginExtraData to control call statistics. - Introduced limits parameter in PluginExtraData for rate limiting plugin usage. - Updated relevant plugins to utilize the new features for better control over plugin statistics and usage limits.
1 parent 5c067bc commit bc8e165

File tree

8 files changed

+85
-8
lines changed

8 files changed

+85
-8
lines changed

zhenxun/builtin_plugins/about.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from nonebot_plugin_uninfo import Uninfo
88

99
from zhenxun.configs.path_config import DATA_PATH
10-
from zhenxun.configs.utils import PluginExtraData
10+
from zhenxun.configs.utils import PluginCdBlock, PluginExtraData
1111
from zhenxun.services.log import logger
1212
from zhenxun.utils.message import MessageUtils
1313
from zhenxun.utils.platform import PlatformUtils
@@ -19,7 +19,12 @@
1919
指令:
2020
关于
2121
""".strip(),
22-
extra=PluginExtraData(author="HibiKier", version="0.1", menu_type="其他").to_dict(),
22+
extra=PluginExtraData(
23+
author="HibiKier",
24+
version="0.1",
25+
menu_type="其他",
26+
limits=[PluginCdBlock(cd=10, result="每10秒只能查看一次哦~")],
27+
).to_dict(),
2328
)
2429

2530

zhenxun/builtin_plugins/admin/plugin_switch/_data_source.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
from zhenxun.models.plugin_info import PluginInfo
55
from zhenxun.models.task_info import TaskInfo
66
from zhenxun.services.cache import CacheRoot
7-
from zhenxun.services.cache.runtime_cache import TaskInfoMemoryCache
7+
from zhenxun.services.cache.runtime_cache import (
8+
PluginInfoMemoryCache,
9+
TaskInfoMemoryCache,
10+
)
811
from zhenxun.utils.common_utils import CommonUtils
912
from zhenxun.utils.enum import BlockType, CacheType, PluginType
1013
from zhenxun.utils.exception import GroupInfoNotFound
@@ -181,6 +184,7 @@ async def set_all_plugin_status(
181184
await PluginInfo.filter(plugin_type=PluginType.NORMAL).update(
182185
default_status=status
183186
)
187+
await PluginInfoMemoryCache.refresh()
184188
return f"成功将所有功能进群默认状态修改为: {'开启' if status else '关闭'}"
185189
if group_id:
186190
if group := await GroupConsole.get_group_db(group_id=group_id):
@@ -203,6 +207,7 @@ async def set_all_plugin_status(
203207
status=status, block_type=None if status else BlockType.ALL
204208
)
205209
await CacheRoot.invalidate_cache(CacheType.PLUGINS)
210+
await PluginInfoMemoryCache.refresh()
206211
return f"成功将所有功能全局状态修改为: {'开启' if status else '关闭'}"
207212

208213
@classmethod

zhenxun/builtin_plugins/init/init_plugin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ async def _handle_setting(
8080
ignore_prompt=extra_data.ignore_prompt,
8181
parent=(plugin.parent_plugin.module_name if plugin.parent_plugin else None),
8282
impression=setting.impression,
83+
ignore_statistics=extra_data.ignore_statistics,
8384
)
8485
)
8586
if extra_data.limits:

zhenxun/builtin_plugins/statistics/statistics_hook.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from nonebot.message import run_postprocessor
77
from nonebot.plugin import PluginMetadata
88
from nonebot_plugin_apscheduler import scheduler
9-
from nonebot_plugin_session import EventSession
9+
from nonebot_plugin_uninfo import Uninfo
1010

1111
from zhenxun.configs.utils import PluginExtraData
1212
from zhenxun.models.plugin_info import PluginInfo
@@ -15,6 +15,7 @@
1515
from zhenxun.services.log import logger
1616
from zhenxun.services.message_load import should_pause_tasks
1717
from zhenxun.utils.enum import PluginType
18+
from zhenxun.utils.utils import get_entity_ids
1819

1920
__plugin_meta__ = PluginMetadata(
2021
name="功能调用统计",
@@ -33,25 +34,28 @@ async def _(
3334
matcher: Matcher,
3435
exception: Exception | None,
3536
bot: Bot,
36-
session: EventSession,
37+
session: Uninfo,
3738
event: Event,
3839
):
3940
if matcher.type == "notice" and not isinstance(event, PokeNotifyEvent):
4041
"""过滤除poke外的notice"""
4142
return
42-
if session.id1 and matcher.plugin:
43+
if matcher.plugin:
44+
entity = get_entity_ids(session)
4345
plugin = PluginInfoMemoryCache.get_by_module_path(matcher.plugin.module_name)
4446
if not plugin:
4547
plugin = await PluginInfo.get_plugin(module_path=matcher.plugin.module_name)
4648
if plugin:
4749
PluginInfoMemoryCache.set_plugin(plugin)
50+
if plugin and plugin.ignore_statistics:
51+
return
4852
plugin_type = plugin.plugin_type if plugin else None
4953
if plugin_type == PluginType.NORMAL:
5054
logger.debug(f"提交调用记录: {matcher.plugin_name}...", session=session)
5155
TEMP_LIST.append(
5256
Statistics(
53-
user_id=session.id1,
54-
group_id=session.id3 or session.id2,
57+
user_id=entity.user_id,
58+
group_id=entity.group_id,
5559
plugin_name=matcher.plugin_name,
5660
create_time=datetime.now(),
5761
bot_id=bot.self_id,

zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/data_source.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from zhenxun.configs.config import Config
88
from zhenxun.configs.utils import ConfigGroup
99
from zhenxun.models.plugin_info import PluginInfo as DbPluginInfo
10+
from zhenxun.services.cache.runtime_cache import PluginInfoMemoryCache
1011
from zhenxun.utils.enum import BlockType, PluginType
1112

1213
from .model import (
@@ -159,6 +160,8 @@ async def batch_update_plugins(cls, params: BatchUpdatePlugins) -> dict:
159160
plugins_to_update_other_fields, list(other_update_fields)
160161
)
161162
bulk_updated_count = len(plugins_to_update_other_fields)
163+
for plugin in plugins_to_update_other_fields:
164+
await PluginInfoMemoryCache.upsert_from_model(plugin)
162165
except Exception as e_bulk:
163166
errors.append(
164167
{
@@ -243,6 +246,8 @@ async def rename_menu_type(cls, old_name: str, new_name: str) -> dict:
243246
updated_count = await DbPluginInfo.filter(menu_type=old_name).update(
244247
menu_type=new_name
245248
)
249+
if updated_count:
250+
await PluginInfoMemoryCache.refresh()
246251
return {"success": True, "updated_count": updated_count}
247252
except Exception as e:
248253
# 可以添加更详细的日志记录

zhenxun/configs/utils/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ class PluginExtraData(BaseModel):
261261
"""常用sql"""
262262
is_show: bool = True
263263
"""是否显示在菜单中"""
264+
ignore_statistics: bool = False
265+
"""是否不统计调用次数"""
264266
smart_tools: list[AICallableTag] | None = None
265267
"""智能模式函数工具集"""
266268
introduction: str | None = None

zhenxun/models/plugin_info.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from tortoise import fields
44

55
from zhenxun.models.plugin_limit import PluginLimit # noqa: F401
6+
from zhenxun.services.cache.runtime_cache import PluginInfoMemoryCache
67
from zhenxun.services.db_context import Model
78
from zhenxun.utils.enum import BlockType, CacheType, PluginType
89

@@ -52,6 +53,10 @@ class PluginInfo(Model):
5253
"""父插件"""
5354
is_show = fields.BooleanField(default=True, description="是否显示在帮助中")
5455
"""是否显示在帮助中"""
56+
ignore_statistics = fields.BooleanField(
57+
default=False, description="是否不统计调用次数"
58+
)
59+
"""是否不统计调用次数"""
5560
impression = fields.FloatField(default=0, description="插件好感度限制")
5661
"""插件好感度限制"""
5762

@@ -64,6 +69,28 @@ class Meta: # pyright: ignore [reportIncompatibleVariableOverride]
6469
cache_key_field = "module"
6570
"""缓存键字段"""
6671

72+
@classmethod
73+
async def create(cls, *args, **kwargs):
74+
result = await super().create(*args, **kwargs)
75+
await PluginInfoMemoryCache.upsert_from_model(result)
76+
return result
77+
78+
@classmethod
79+
async def update_or_create(cls, *args, **kwargs):
80+
result = await super().update_or_create(*args, **kwargs)
81+
await PluginInfoMemoryCache.upsert_from_model(result[0])
82+
return result
83+
84+
async def save(self, *args, **kwargs):
85+
await super().save(*args, **kwargs)
86+
await PluginInfoMemoryCache.upsert_from_model(self)
87+
88+
async def delete(self, *args, **kwargs):
89+
module = self.module
90+
module_path = self.module_path
91+
await super().delete(*args, **kwargs)
92+
await PluginInfoMemoryCache.remove(module, module_path)
93+
6794
@classmethod
6895
async def get_plugin(
6996
cls, load_status: bool = True, filter_parent: bool = True, **kwargs
@@ -110,4 +137,6 @@ async def _run_script(cls):
110137
"ALTER TABLE plugin_info ADD COLUMN ignore_prompt boolean DEFAULT false;",
111138
"ALTER TABLE plugin_info ADD COLUMN impression float DEFAULT 0;",
112139
"CREATE INDEX idx_plugin_info_module ON plugin_info(module);",
140+
"ALTER TABLE plugin_info ADD COLUMN ignore_statistics"
141+
" boolean DEFAULT false;",
113142
]

zhenxun/services/cache/runtime_cache.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,11 +688,37 @@ def set_plugin(cls, plugin) -> None:
688688
cls._by_module[plugin.module] = plugin
689689
if getattr(plugin, "module_path", None):
690690
cls._by_module_path[plugin.module_path] = plugin
691+
cls._loaded = True
692+
cls._last_refresh = time.time()
691693

692694
@classmethod
693695
def remove_by_module(cls, module: str) -> None:
694696
cls._by_module.pop(module, None)
695697

698+
@classmethod
699+
async def upsert_from_model(cls, plugin) -> None:
700+
if not plugin:
701+
return
702+
async with cls._lock:
703+
if getattr(plugin, "module", None):
704+
cls._by_module[plugin.module] = plugin
705+
if getattr(plugin, "module_path", None):
706+
cls._by_module_path[plugin.module_path] = plugin
707+
cls._loaded = True
708+
cls._last_refresh = time.time()
709+
710+
@classmethod
711+
async def remove(
712+
cls, module: str | None = None, module_path: str | None = None
713+
) -> None:
714+
if not module and not module_path:
715+
return
716+
async with cls._lock:
717+
if module:
718+
cls._by_module.pop(module, None)
719+
if module_path:
720+
cls._by_module_path.pop(module_path, None)
721+
696722
@classmethod
697723
async def _refresh_loop(cls, interval: int) -> None:
698724
while True:

0 commit comments

Comments
 (0)