mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-09-28 16:20:56 +08:00
✨ 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.
This commit is contained in:
@@ -7,7 +7,7 @@ from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
|||||||
from nonebot_plugin_uninfo import Uninfo
|
from nonebot_plugin_uninfo import Uninfo
|
||||||
|
|
||||||
from zhenxun.configs.path_config import DATA_PATH
|
from zhenxun.configs.path_config import DATA_PATH
|
||||||
from zhenxun.configs.utils import PluginExtraData
|
from zhenxun.configs.utils import PluginCdBlock, PluginExtraData
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
from zhenxun.utils.message import MessageUtils
|
from zhenxun.utils.message import MessageUtils
|
||||||
from zhenxun.utils.platform import PlatformUtils
|
from zhenxun.utils.platform import PlatformUtils
|
||||||
@@ -19,7 +19,12 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
指令:
|
指令:
|
||||||
关于
|
关于
|
||||||
""".strip(),
|
""".strip(),
|
||||||
extra=PluginExtraData(author="HibiKier", version="0.1", menu_type="其他").to_dict(),
|
extra=PluginExtraData(
|
||||||
|
author="HibiKier",
|
||||||
|
version="0.1",
|
||||||
|
menu_type="其他",
|
||||||
|
limits=[PluginCdBlock(cd=10, result="每10秒只能查看一次哦~")],
|
||||||
|
).to_dict(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ from zhenxun.models.group_console import GroupConsole
|
|||||||
from zhenxun.models.plugin_info import PluginInfo
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
from zhenxun.models.task_info import TaskInfo
|
from zhenxun.models.task_info import TaskInfo
|
||||||
from zhenxun.services.cache import CacheRoot
|
from zhenxun.services.cache import CacheRoot
|
||||||
from zhenxun.services.cache.runtime_cache import TaskInfoMemoryCache
|
from zhenxun.services.cache.runtime_cache import (
|
||||||
|
PluginInfoMemoryCache,
|
||||||
|
TaskInfoMemoryCache,
|
||||||
|
)
|
||||||
from zhenxun.utils.common_utils import CommonUtils
|
from zhenxun.utils.common_utils import CommonUtils
|
||||||
from zhenxun.utils.enum import BlockType, CacheType, PluginType
|
from zhenxun.utils.enum import BlockType, CacheType, PluginType
|
||||||
from zhenxun.utils.exception import GroupInfoNotFound
|
from zhenxun.utils.exception import GroupInfoNotFound
|
||||||
@@ -181,6 +184,7 @@ class PluginManager:
|
|||||||
await PluginInfo.filter(plugin_type=PluginType.NORMAL).update(
|
await PluginInfo.filter(plugin_type=PluginType.NORMAL).update(
|
||||||
default_status=status
|
default_status=status
|
||||||
)
|
)
|
||||||
|
await PluginInfoMemoryCache.refresh()
|
||||||
return f"成功将所有功能进群默认状态修改为: {'开启' if status else '关闭'}"
|
return f"成功将所有功能进群默认状态修改为: {'开启' if status else '关闭'}"
|
||||||
if group_id:
|
if group_id:
|
||||||
if group := await GroupConsole.get_group_db(group_id=group_id):
|
if group := await GroupConsole.get_group_db(group_id=group_id):
|
||||||
@@ -203,6 +207,7 @@ class PluginManager:
|
|||||||
status=status, block_type=None if status else BlockType.ALL
|
status=status, block_type=None if status else BlockType.ALL
|
||||||
)
|
)
|
||||||
await CacheRoot.invalidate_cache(CacheType.PLUGINS)
|
await CacheRoot.invalidate_cache(CacheType.PLUGINS)
|
||||||
|
await PluginInfoMemoryCache.refresh()
|
||||||
return f"成功将所有功能全局状态修改为: {'开启' if status else '关闭'}"
|
return f"成功将所有功能全局状态修改为: {'开启' if status else '关闭'}"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ async def _handle_setting(
|
|||||||
ignore_prompt=extra_data.ignore_prompt,
|
ignore_prompt=extra_data.ignore_prompt,
|
||||||
parent=(plugin.parent_plugin.module_name if plugin.parent_plugin else None),
|
parent=(plugin.parent_plugin.module_name if plugin.parent_plugin else None),
|
||||||
impression=setting.impression,
|
impression=setting.impression,
|
||||||
|
ignore_statistics=extra_data.ignore_statistics,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if extra_data.limits:
|
if extra_data.limits:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from nonebot.matcher import Matcher
|
|||||||
from nonebot.message import run_postprocessor
|
from nonebot.message import run_postprocessor
|
||||||
from nonebot.plugin import PluginMetadata
|
from nonebot.plugin import PluginMetadata
|
||||||
from nonebot_plugin_apscheduler import scheduler
|
from nonebot_plugin_apscheduler import scheduler
|
||||||
from nonebot_plugin_session import EventSession
|
from nonebot_plugin_uninfo import Uninfo
|
||||||
|
|
||||||
from zhenxun.configs.utils import PluginExtraData
|
from zhenxun.configs.utils import PluginExtraData
|
||||||
from zhenxun.models.plugin_info import PluginInfo
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
@@ -15,6 +15,7 @@ from zhenxun.services.cache.runtime_cache import PluginInfoMemoryCache
|
|||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
from zhenxun.services.message_load import should_pause_tasks
|
from zhenxun.services.message_load import should_pause_tasks
|
||||||
from zhenxun.utils.enum import PluginType
|
from zhenxun.utils.enum import PluginType
|
||||||
|
from zhenxun.utils.utils import get_entity_ids
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
__plugin_meta__ = PluginMetadata(
|
||||||
name="功能调用统计",
|
name="功能调用统计",
|
||||||
@@ -33,25 +34,28 @@ async def _(
|
|||||||
matcher: Matcher,
|
matcher: Matcher,
|
||||||
exception: Exception | None,
|
exception: Exception | None,
|
||||||
bot: Bot,
|
bot: Bot,
|
||||||
session: EventSession,
|
session: Uninfo,
|
||||||
event: Event,
|
event: Event,
|
||||||
):
|
):
|
||||||
if matcher.type == "notice" and not isinstance(event, PokeNotifyEvent):
|
if matcher.type == "notice" and not isinstance(event, PokeNotifyEvent):
|
||||||
"""过滤除poke外的notice"""
|
"""过滤除poke外的notice"""
|
||||||
return
|
return
|
||||||
if session.id1 and matcher.plugin:
|
if matcher.plugin:
|
||||||
|
entity = get_entity_ids(session)
|
||||||
plugin = PluginInfoMemoryCache.get_by_module_path(matcher.plugin.module_name)
|
plugin = PluginInfoMemoryCache.get_by_module_path(matcher.plugin.module_name)
|
||||||
if not plugin:
|
if not plugin:
|
||||||
plugin = await PluginInfo.get_plugin(module_path=matcher.plugin.module_name)
|
plugin = await PluginInfo.get_plugin(module_path=matcher.plugin.module_name)
|
||||||
if plugin:
|
if plugin:
|
||||||
PluginInfoMemoryCache.set_plugin(plugin)
|
PluginInfoMemoryCache.set_plugin(plugin)
|
||||||
|
if plugin and plugin.ignore_statistics:
|
||||||
|
return
|
||||||
plugin_type = plugin.plugin_type if plugin else None
|
plugin_type = plugin.plugin_type if plugin else None
|
||||||
if plugin_type == PluginType.NORMAL:
|
if plugin_type == PluginType.NORMAL:
|
||||||
logger.debug(f"提交调用记录: {matcher.plugin_name}...", session=session)
|
logger.debug(f"提交调用记录: {matcher.plugin_name}...", session=session)
|
||||||
TEMP_LIST.append(
|
TEMP_LIST.append(
|
||||||
Statistics(
|
Statistics(
|
||||||
user_id=session.id1,
|
user_id=entity.user_id,
|
||||||
group_id=session.id3 or session.id2,
|
group_id=entity.group_id,
|
||||||
plugin_name=matcher.plugin_name,
|
plugin_name=matcher.plugin_name,
|
||||||
create_time=datetime.now(),
|
create_time=datetime.now(),
|
||||||
bot_id=bot.self_id,
|
bot_id=bot.self_id,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from tortoise.exceptions import DoesNotExist
|
|||||||
from zhenxun.configs.config import Config
|
from zhenxun.configs.config import Config
|
||||||
from zhenxun.configs.utils import ConfigGroup
|
from zhenxun.configs.utils import ConfigGroup
|
||||||
from zhenxun.models.plugin_info import PluginInfo as DbPluginInfo
|
from zhenxun.models.plugin_info import PluginInfo as DbPluginInfo
|
||||||
|
from zhenxun.services.cache.runtime_cache import PluginInfoMemoryCache
|
||||||
from zhenxun.utils.enum import BlockType, PluginType
|
from zhenxun.utils.enum import BlockType, PluginType
|
||||||
|
|
||||||
from .model import (
|
from .model import (
|
||||||
@@ -159,6 +160,8 @@ class ApiDataSource:
|
|||||||
plugins_to_update_other_fields, list(other_update_fields)
|
plugins_to_update_other_fields, list(other_update_fields)
|
||||||
)
|
)
|
||||||
bulk_updated_count = len(plugins_to_update_other_fields)
|
bulk_updated_count = len(plugins_to_update_other_fields)
|
||||||
|
for plugin in plugins_to_update_other_fields:
|
||||||
|
await PluginInfoMemoryCache.upsert_from_model(plugin)
|
||||||
except Exception as e_bulk:
|
except Exception as e_bulk:
|
||||||
errors.append(
|
errors.append(
|
||||||
{
|
{
|
||||||
@@ -243,6 +246,8 @@ class ApiDataSource:
|
|||||||
updated_count = await DbPluginInfo.filter(menu_type=old_name).update(
|
updated_count = await DbPluginInfo.filter(menu_type=old_name).update(
|
||||||
menu_type=new_name
|
menu_type=new_name
|
||||||
)
|
)
|
||||||
|
if updated_count:
|
||||||
|
await PluginInfoMemoryCache.refresh()
|
||||||
return {"success": True, "updated_count": updated_count}
|
return {"success": True, "updated_count": updated_count}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 可以添加更详细的日志记录
|
# 可以添加更详细的日志记录
|
||||||
|
|||||||
@@ -261,6 +261,8 @@ class PluginExtraData(BaseModel):
|
|||||||
"""常用sql"""
|
"""常用sql"""
|
||||||
is_show: bool = True
|
is_show: bool = True
|
||||||
"""是否显示在菜单中"""
|
"""是否显示在菜单中"""
|
||||||
|
ignore_statistics: bool = False
|
||||||
|
"""是否不统计调用次数"""
|
||||||
smart_tools: list[AICallableTag] | None = None
|
smart_tools: list[AICallableTag] | None = None
|
||||||
"""智能模式函数工具集"""
|
"""智能模式函数工具集"""
|
||||||
introduction: str | None = None
|
introduction: str | None = None
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from typing_extensions import Self
|
|||||||
from tortoise import fields
|
from tortoise import fields
|
||||||
|
|
||||||
from zhenxun.models.plugin_limit import PluginLimit # noqa: F401
|
from zhenxun.models.plugin_limit import PluginLimit # noqa: F401
|
||||||
|
from zhenxun.services.cache.runtime_cache import PluginInfoMemoryCache
|
||||||
from zhenxun.services.db_context import Model
|
from zhenxun.services.db_context import Model
|
||||||
from zhenxun.utils.enum import BlockType, CacheType, PluginType
|
from zhenxun.utils.enum import BlockType, CacheType, PluginType
|
||||||
|
|
||||||
@@ -52,6 +53,10 @@ class PluginInfo(Model):
|
|||||||
"""父插件"""
|
"""父插件"""
|
||||||
is_show = fields.BooleanField(default=True, description="是否显示在帮助中")
|
is_show = fields.BooleanField(default=True, description="是否显示在帮助中")
|
||||||
"""是否显示在帮助中"""
|
"""是否显示在帮助中"""
|
||||||
|
ignore_statistics = fields.BooleanField(
|
||||||
|
default=False, description="是否不统计调用次数"
|
||||||
|
)
|
||||||
|
"""是否不统计调用次数"""
|
||||||
impression = fields.FloatField(default=0, description="插件好感度限制")
|
impression = fields.FloatField(default=0, description="插件好感度限制")
|
||||||
"""插件好感度限制"""
|
"""插件好感度限制"""
|
||||||
|
|
||||||
@@ -64,6 +69,28 @@ class PluginInfo(Model):
|
|||||||
cache_key_field = "module"
|
cache_key_field = "module"
|
||||||
"""缓存键字段"""
|
"""缓存键字段"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def create(cls, *args, **kwargs):
|
||||||
|
result = await super().create(*args, **kwargs)
|
||||||
|
await PluginInfoMemoryCache.upsert_from_model(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def update_or_create(cls, *args, **kwargs):
|
||||||
|
result = await super().update_or_create(*args, **kwargs)
|
||||||
|
await PluginInfoMemoryCache.upsert_from_model(result[0])
|
||||||
|
return result
|
||||||
|
|
||||||
|
async def save(self, *args, **kwargs):
|
||||||
|
await super().save(*args, **kwargs)
|
||||||
|
await PluginInfoMemoryCache.upsert_from_model(self)
|
||||||
|
|
||||||
|
async def delete(self, *args, **kwargs):
|
||||||
|
module = self.module
|
||||||
|
module_path = self.module_path
|
||||||
|
await super().delete(*args, **kwargs)
|
||||||
|
await PluginInfoMemoryCache.remove(module, module_path)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_plugin(
|
async def get_plugin(
|
||||||
cls, load_status: bool = True, filter_parent: bool = True, **kwargs
|
cls, load_status: bool = True, filter_parent: bool = True, **kwargs
|
||||||
@@ -110,4 +137,6 @@ class PluginInfo(Model):
|
|||||||
"ALTER TABLE plugin_info ADD COLUMN ignore_prompt boolean DEFAULT false;",
|
"ALTER TABLE plugin_info ADD COLUMN ignore_prompt boolean DEFAULT false;",
|
||||||
"ALTER TABLE plugin_info ADD COLUMN impression float DEFAULT 0;",
|
"ALTER TABLE plugin_info ADD COLUMN impression float DEFAULT 0;",
|
||||||
"CREATE INDEX idx_plugin_info_module ON plugin_info(module);",
|
"CREATE INDEX idx_plugin_info_module ON plugin_info(module);",
|
||||||
|
"ALTER TABLE plugin_info ADD COLUMN ignore_statistics"
|
||||||
|
" boolean DEFAULT false;",
|
||||||
]
|
]
|
||||||
|
|||||||
+26
@@ -688,11 +688,37 @@ class PluginInfoMemoryCache:
|
|||||||
cls._by_module[plugin.module] = plugin
|
cls._by_module[plugin.module] = plugin
|
||||||
if getattr(plugin, "module_path", None):
|
if getattr(plugin, "module_path", None):
|
||||||
cls._by_module_path[plugin.module_path] = plugin
|
cls._by_module_path[plugin.module_path] = plugin
|
||||||
|
cls._loaded = True
|
||||||
|
cls._last_refresh = time.time()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_by_module(cls, module: str) -> None:
|
def remove_by_module(cls, module: str) -> None:
|
||||||
cls._by_module.pop(module, None)
|
cls._by_module.pop(module, None)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def upsert_from_model(cls, plugin) -> None:
|
||||||
|
if not plugin:
|
||||||
|
return
|
||||||
|
async with cls._lock:
|
||||||
|
if getattr(plugin, "module", None):
|
||||||
|
cls._by_module[plugin.module] = plugin
|
||||||
|
if getattr(plugin, "module_path", None):
|
||||||
|
cls._by_module_path[plugin.module_path] = plugin
|
||||||
|
cls._loaded = True
|
||||||
|
cls._last_refresh = time.time()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def remove(
|
||||||
|
cls, module: str | None = None, module_path: str | None = None
|
||||||
|
) -> None:
|
||||||
|
if not module and not module_path:
|
||||||
|
return
|
||||||
|
async with cls._lock:
|
||||||
|
if module:
|
||||||
|
cls._by_module.pop(module, None)
|
||||||
|
if module_path:
|
||||||
|
cls._by_module_path.pop(module_path, None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def _refresh_loop(cls, interval: int) -> None:
|
async def _refresh_loop(cls, interval: int) -> None:
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
Reference in New Issue
Block a user