mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-03 20:27:13 +08:00
feat(system-settings): add unified tools for querying and updating system settings
This commit is contained in:
331
app/agent/tools/impl/_system_setting_utils.py
Normal file
331
app/agent/tools/impl/_system_setting_utils.py
Normal file
@@ -0,0 +1,331 @@
|
||||
"""系统设置工具共用的键解析与分组元数据。"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from app.core.config import Settings
|
||||
from app.schemas.types import SystemConfigKey
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SettingSpec:
|
||||
"""描述一个可被 Agent 读写的系统设置项。"""
|
||||
|
||||
key: str
|
||||
source: str
|
||||
group: str
|
||||
label: str
|
||||
|
||||
|
||||
SYSTEMCONFIG_SETTING_METADATA = {
|
||||
SystemConfigKey.Downloaders.value: {
|
||||
"group": "downloaders",
|
||||
"label": "下载器配置",
|
||||
},
|
||||
SystemConfigKey.MediaServers.value: {
|
||||
"group": "media_servers",
|
||||
"label": "媒体服务器配置",
|
||||
},
|
||||
SystemConfigKey.Notifications.value: {
|
||||
"group": "notifications",
|
||||
"label": "消息通知配置",
|
||||
},
|
||||
SystemConfigKey.NotificationSwitchs.value: {
|
||||
"group": "notification_switches",
|
||||
"label": "通知场景开关",
|
||||
},
|
||||
SystemConfigKey.Directories.value: {
|
||||
"group": "directories",
|
||||
"label": "目录配置",
|
||||
},
|
||||
SystemConfigKey.Storages.value: {
|
||||
"group": "storages",
|
||||
"label": "存储配置",
|
||||
},
|
||||
SystemConfigKey.IndexerSites.value: {
|
||||
"group": "search_sites",
|
||||
"label": "搜索站点范围",
|
||||
},
|
||||
SystemConfigKey.RssSites.value: {
|
||||
"group": "subscribe_sites",
|
||||
"label": "订阅站点范围",
|
||||
},
|
||||
SystemConfigKey.UserSiteAuthParams.value: {
|
||||
"group": "site_auth",
|
||||
"label": "站点认证参数",
|
||||
},
|
||||
SystemConfigKey.AIAgentConfig.value: {
|
||||
"group": "ai_agent",
|
||||
"label": "AI 智能体配置",
|
||||
},
|
||||
SystemConfigKey.CustomIdentifiers.value: {
|
||||
"group": "custom_identifiers",
|
||||
"label": "自定义识别词",
|
||||
},
|
||||
SystemConfigKey.CustomReleaseGroups.value: {
|
||||
"group": "customization",
|
||||
"label": "自定义制作组/字幕组",
|
||||
},
|
||||
SystemConfigKey.Customization.value: {
|
||||
"group": "customization",
|
||||
"label": "自定义占位符",
|
||||
},
|
||||
SystemConfigKey.TransferExcludeWords.value: {
|
||||
"group": "transfer",
|
||||
"label": "整理屏蔽词",
|
||||
},
|
||||
SystemConfigKey.TorrentsPriority.value: {
|
||||
"group": "filter_rules",
|
||||
"label": "种子优先级规则",
|
||||
},
|
||||
SystemConfigKey.CustomFilterRules.value: {
|
||||
"group": "filter_rules",
|
||||
"label": "用户自定义规则",
|
||||
},
|
||||
SystemConfigKey.UserFilterRuleGroups.value: {
|
||||
"group": "filter_rules",
|
||||
"label": "用户规则组",
|
||||
},
|
||||
SystemConfigKey.SearchFilterRuleGroups.value: {
|
||||
"group": "filter_rules",
|
||||
"label": "搜索默认过滤规则组",
|
||||
},
|
||||
SystemConfigKey.SubscribeFilterRuleGroups.value: {
|
||||
"group": "filter_rules",
|
||||
"label": "订阅默认过滤规则组",
|
||||
},
|
||||
SystemConfigKey.BestVersionFilterRuleGroups.value: {
|
||||
"group": "filter_rules",
|
||||
"label": "洗版默认过滤规则组",
|
||||
},
|
||||
SystemConfigKey.SubscribeDefaultParams.value: {
|
||||
"group": "subscribe_defaults",
|
||||
"label": "订阅默认参数",
|
||||
},
|
||||
SystemConfigKey.DefaultMovieSubscribeConfig.value: {
|
||||
"group": "subscribe_defaults",
|
||||
"label": "默认电影订阅规则",
|
||||
},
|
||||
SystemConfigKey.DefaultTvSubscribeConfig.value: {
|
||||
"group": "subscribe_defaults",
|
||||
"label": "默认电视剧订阅规则",
|
||||
},
|
||||
SystemConfigKey.UserInstalledPlugins.value: {
|
||||
"group": "plugins",
|
||||
"label": "已安装插件列表",
|
||||
},
|
||||
SystemConfigKey.PluginFolders.value: {
|
||||
"group": "plugins",
|
||||
"label": "插件文件夹分组配置",
|
||||
},
|
||||
SystemConfigKey.PluginInstallReport.value: {
|
||||
"group": "plugins",
|
||||
"label": "插件安装统计",
|
||||
},
|
||||
SystemConfigKey.NotificationSendTime.value: {
|
||||
"group": "notifications",
|
||||
"label": "通知发送时间",
|
||||
},
|
||||
SystemConfigKey.NotificationTemplates.value: {
|
||||
"group": "notifications",
|
||||
"label": "通知模板",
|
||||
},
|
||||
SystemConfigKey.ScrapingSwitchs.value: {
|
||||
"group": "scraping",
|
||||
"label": "刮削开关设置",
|
||||
},
|
||||
SystemConfigKey.FollowSubscribers.value: {
|
||||
"group": "subscribe_sites",
|
||||
"label": "Follow 订阅分享者",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
LIST_ITEM_MATCH_FIELD_DEFAULTS = {
|
||||
SystemConfigKey.Downloaders.value: "name",
|
||||
SystemConfigKey.MediaServers.value: "name",
|
||||
SystemConfigKey.Notifications.value: "name",
|
||||
SystemConfigKey.NotificationSwitchs.value: "type",
|
||||
SystemConfigKey.Directories.value: "name",
|
||||
SystemConfigKey.Storages.value: "name",
|
||||
}
|
||||
|
||||
|
||||
GROUP_ALIASES = {
|
||||
"all": "all",
|
||||
"全部": "all",
|
||||
"settings": "settings",
|
||||
"basic": "settings",
|
||||
"基础设置": "settings",
|
||||
"基础配置": "settings",
|
||||
"systemconfig": "systemconfig",
|
||||
"system_config": "systemconfig",
|
||||
"系统设置": "systemconfig",
|
||||
"系统配置": "systemconfig",
|
||||
"downloaders": "downloaders",
|
||||
"downloader": "downloaders",
|
||||
"下载器": "downloaders",
|
||||
"media_servers": "media_servers",
|
||||
"mediaservers": "media_servers",
|
||||
"media-servers": "media_servers",
|
||||
"媒体服务器": "media_servers",
|
||||
"notifications": "notifications",
|
||||
"notification": "notifications",
|
||||
"消息通知": "notifications",
|
||||
"通知": "notifications",
|
||||
"notification_switches": "notification_switches",
|
||||
"notification_switchs": "notification_switches",
|
||||
"通知开关": "notification_switches",
|
||||
"storages": "storages",
|
||||
"storage": "storages",
|
||||
"存储": "storages",
|
||||
"directories": "directories",
|
||||
"directory": "directories",
|
||||
"目录": "directories",
|
||||
"search_sites": "search_sites",
|
||||
"indexer_sites": "search_sites",
|
||||
"搜索站点": "search_sites",
|
||||
"subscribe_sites": "subscribe_sites",
|
||||
"rss_sites": "subscribe_sites",
|
||||
"订阅站点": "subscribe_sites",
|
||||
"site_auth": "site_auth",
|
||||
"site_auth_params": "site_auth",
|
||||
"站点认证": "site_auth",
|
||||
"ai_agent": "ai_agent",
|
||||
"agent": "ai_agent",
|
||||
"智能体": "ai_agent",
|
||||
"custom_identifiers": "custom_identifiers",
|
||||
"自定义识别词": "custom_identifiers",
|
||||
"filter_rules": "filter_rules",
|
||||
"过滤规则": "filter_rules",
|
||||
"subscribe_defaults": "subscribe_defaults",
|
||||
"订阅默认": "subscribe_defaults",
|
||||
"plugins": "plugins",
|
||||
"插件": "plugins",
|
||||
"customization": "customization",
|
||||
"自定义": "customization",
|
||||
"transfer": "transfer",
|
||||
"整理": "transfer",
|
||||
"scraping": "scraping",
|
||||
"刮削": "scraping",
|
||||
"misc": "misc",
|
||||
"其他": "misc",
|
||||
}
|
||||
|
||||
|
||||
def _normalize_token(value: str) -> str:
|
||||
return str(value).strip().lower().replace("-", "_")
|
||||
|
||||
|
||||
def _build_specs() -> tuple[dict[str, SettingSpec], dict[str, SettingSpec]]:
|
||||
core_specs = {
|
||||
key: SettingSpec(key=key, source="settings", group="settings", label=key)
|
||||
for key in Settings.model_fields.keys()
|
||||
}
|
||||
system_specs = {}
|
||||
for item in SystemConfigKey:
|
||||
metadata = SYSTEMCONFIG_SETTING_METADATA.get(item.value, {})
|
||||
system_specs[item.value] = SettingSpec(
|
||||
key=item.value,
|
||||
source="systemconfig",
|
||||
group=metadata.get("group", "misc"),
|
||||
label=metadata.get("label", item.value),
|
||||
)
|
||||
return core_specs, system_specs
|
||||
|
||||
|
||||
CORE_SETTING_SPECS, SYSTEMCONFIG_SETTING_SPECS = _build_specs()
|
||||
ALL_SETTING_SPECS = {**CORE_SETTING_SPECS, **SYSTEMCONFIG_SETTING_SPECS}
|
||||
|
||||
|
||||
SETTING_KEY_ALIASES = {}
|
||||
for key in CORE_SETTING_SPECS:
|
||||
SETTING_KEY_ALIASES[_normalize_token(key)] = key
|
||||
for item in SystemConfigKey:
|
||||
SETTING_KEY_ALIASES[_normalize_token(item.value)] = item.value
|
||||
SETTING_KEY_ALIASES[_normalize_token(item.name)] = item.value
|
||||
|
||||
SINGLE_KEY_GROUP_ALIASES = {
|
||||
_normalize_token(alias): next(
|
||||
(
|
||||
spec.key
|
||||
for spec in SYSTEMCONFIG_SETTING_SPECS.values()
|
||||
if spec.group == canonical_group
|
||||
),
|
||||
None,
|
||||
)
|
||||
for alias, canonical_group in GROUP_ALIASES.items()
|
||||
if canonical_group not in {"all", "settings", "systemconfig"}
|
||||
and len(
|
||||
[
|
||||
spec.key
|
||||
for spec in SYSTEMCONFIG_SETTING_SPECS.values()
|
||||
if spec.group == canonical_group
|
||||
]
|
||||
)
|
||||
== 1
|
||||
}
|
||||
|
||||
|
||||
def normalize_group(group: Optional[str]) -> str:
|
||||
if not group:
|
||||
return "all"
|
||||
normalized = GROUP_ALIASES.get(_normalize_token(group))
|
||||
if not normalized:
|
||||
raise ValueError(
|
||||
"group 不支持,支持值包括 all/settings/systemconfig 以及"
|
||||
" downloaders、media_servers、notifications、storages、directories、"
|
||||
"search_sites、subscribe_sites、site_auth、ai_agent 等分类别名"
|
||||
)
|
||||
return normalized
|
||||
|
||||
|
||||
def resolve_setting_spec(setting_key: Optional[str]) -> Optional[SettingSpec]:
|
||||
"""把精确键名、枚举名或单键分组别名解析为统一的设置定义。"""
|
||||
|
||||
if not setting_key:
|
||||
return None
|
||||
|
||||
normalized = _normalize_token(setting_key)
|
||||
resolved_key = SETTING_KEY_ALIASES.get(normalized) or SINGLE_KEY_GROUP_ALIASES.get(
|
||||
normalized
|
||||
)
|
||||
if not resolved_key:
|
||||
return None
|
||||
return ALL_SETTING_SPECS.get(resolved_key)
|
||||
|
||||
|
||||
def list_setting_specs(
|
||||
group: Optional[str] = "all", keyword: Optional[str] = None
|
||||
) -> list[SettingSpec]:
|
||||
"""按分组和关键字筛选可查询的设置项。"""
|
||||
|
||||
normalized_group = normalize_group(group)
|
||||
if normalized_group == "all":
|
||||
specs = list(ALL_SETTING_SPECS.values())
|
||||
elif normalized_group == "settings":
|
||||
specs = list(CORE_SETTING_SPECS.values())
|
||||
elif normalized_group == "systemconfig":
|
||||
specs = list(SYSTEMCONFIG_SETTING_SPECS.values())
|
||||
else:
|
||||
specs = [
|
||||
spec
|
||||
for spec in SYSTEMCONFIG_SETTING_SPECS.values()
|
||||
if spec.group == normalized_group
|
||||
]
|
||||
|
||||
if keyword:
|
||||
normalized_keyword = _normalize_token(keyword)
|
||||
specs = [
|
||||
spec
|
||||
for spec in specs
|
||||
if normalized_keyword in _normalize_token(spec.key)
|
||||
or normalized_keyword in _normalize_token(spec.group)
|
||||
or normalized_keyword in _normalize_token(spec.label)
|
||||
]
|
||||
|
||||
return sorted(specs, key=lambda spec: (spec.source, spec.group, spec.key))
|
||||
|
||||
|
||||
def get_default_list_match_field(setting_key: str) -> Optional[str]:
|
||||
return LIST_ITEM_MATCH_FIELD_DEFAULTS.get(setting_key)
|
||||
Reference in New Issue
Block a user