Skip to content
Closed
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
8 changes: 7 additions & 1 deletion tooldelta/extend_functions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,11 @@ def activate_functions():
func.when_activate()


def restore_console_cmds():
"""恢复内置扩展提供的控制台命令。"""
for func in registered_functions:
func.when_console_cmd_reset()


def import_functions():
from . import gamerule_warnings, fast_plugin_download
from . import gamerule_warnings, fast_plugin_download, plugin_config
4 changes: 4 additions & 0 deletions tooldelta/extend_functions/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ def __init__(self, frame: "ToolDelta"):
self.frame = frame

def when_activate(self): ...

def when_console_cmd_reset(self):
"""控制台命令重置后的扩展钩子。"""
return None
4 changes: 4 additions & 0 deletions tooldelta/extend_functions/fast_plugin_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def __init__(self, frame):

def when_activate(self):
super().when_activate()
self.when_console_cmd_reset()

def when_console_cmd_reset(self):
"""注册快速下载插件的控制台命令。"""
self.frame.add_console_cmd_trigger(
["plg add"],
"插件 ID",
Expand Down
158 changes: 158 additions & 0 deletions tooldelta/extend_functions/plugin_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
"""插件市场源和 GitHub 镜像的控制台配置命令。"""

from urllib.parse import urlparse

from ..constants import PLUGIN_MARKET_SOURCE_OFFICIAL
from ..constants.tooldelta_cfg import LAUNCH_CFG_STD
from ..plugin_market import market
from ..utils import cfg, fmts, urlmethod
from . import regist_extend_function
from .basic import ExtendFunction


CONFIG_PATH = "ToolDelta基本配置.json"
CONFIG_KEYS = {
"plugin_market": "插件市场源",
"github_mirror": "全局GitHub镜像",
}
CONFIG_KEYS_HINT = "plugin_market|github_mirror"


def _normalize_url(value: str) -> str:
"""校验并规范化配置 URL。"""
if any(char.isspace() for char in value):
raise ValueError
parsed = urlparse(value)
if parsed.scheme not in ("http", "https") or not parsed.netloc:
raise ValueError
return value.rstrip("/")


@regist_extend_function
class PluginConfig(ExtendFunction):
"""管理插件市场源和全局 GitHub 镜像。"""

def when_activate(self):
"""激活扩展并注册控制台命令。"""
super().when_activate()
self.when_console_cmd_reset()

def when_console_cmd_reset(self):
"""注册插件源配置命令。"""
self.frame.add_console_cmd_trigger(
["plg config set"],
f"<{CONFIG_KEYS_HINT}> <URL>",
"设置插件市场源或全局 GitHub 镜像",
self.on_set_config,
)
self.frame.add_console_cmd_trigger(
["plg config unset"],
f"<{CONFIG_KEYS_HINT}>",
"清除插件市场源或全局 GitHub 镜像的自定义值",
self.on_unset_config,
)
self.frame.add_console_cmd_trigger(
["plg config list"],
None,
"查看插件市场源和全局 GitHub 镜像",
self.on_list_config,
)

def on_set_config(self, args: list[str]) -> None:
"""设置并立即应用指定配置。"""
if len(args) != 2:
self._print_usage("set")
return
key, value = args
if not self._check_key(key):
return
try:
value = _normalize_url(value)
except ValueError:
fmts.print_err("URL 必须是包含主机名的 http:// 或 https:// 地址")
return
if self._save_config(key, value):
self._apply_config(key, value)
fmts.print_suc(f"已设置 {key}: {value},当前进程已生效")

def on_unset_config(self, args: list[str]) -> None:
"""清除指定配置并恢复运行时默认值。"""
if len(args) != 1:
self._print_usage("unset")
return
key = args[0]
if not self._check_key(key):
return
if self._save_config(key, ""):
self._apply_config(key, "")
effective_value = self._get_effective_value(key)
fmts.print_suc(f"已清除 {key} 的自定义值,当前使用: {effective_value}")

def on_list_config(self, args: list[str]) -> None:
"""显示配置值及当前生效值。"""
if args:
self._print_usage("list")
return
configs = self._load_config()
if configs is None:
return
fmts.print_inf("插件源配置:")
for key, config_key in CONFIG_KEYS.items():
configured_value = configs[config_key] or "自动"
effective_value = self._get_effective_value(key)
fmts.print_inf(f" {key}: 配置={configured_value},当前={effective_value}")

@staticmethod
def _check_key(key: str) -> bool:
"""检查命令使用的配置键。"""
if key in CONFIG_KEYS:
return True
fmts.print_err(f"未知配置项 {key!r},可用项: {', '.join(CONFIG_KEYS)}")
return False

@staticmethod
def _load_config() -> dict | None:
"""读取 ToolDelta 基本配置。"""
try:
return cfg.get_cfg(CONFIG_PATH, LAUNCH_CFG_STD)
except (OSError, cfg.ConfigError) as err:
fmts.print_err(f"读取 ToolDelta 基本配置失败: {err}")
return None

def _save_config(self, key: str, value: str) -> bool:
"""保留其他配置项并持久化指定值。"""
configs = self._load_config()
if configs is None:
return False
configs[CONFIG_KEYS[key]] = value
try:
cfg.write_default_cfg_file(CONFIG_PATH, configs, force=True)
except OSError as err:
fmts.print_err(f"保存 ToolDelta 基本配置失败: {err}")
return False
return True

@staticmethod
def _apply_config(key: str, value: str) -> None:
"""将配置应用到当前运行中的客户端。"""
if key == "plugin_market":
market.set_source_url(value or PLUGIN_MARKET_SOURCE_OFFICIAL)
return
urlmethod.set_global_github_src_url(value)

@staticmethod
def _get_effective_value(key: str) -> str:
"""获取当前进程实际使用的配置值。"""
if key == "plugin_market":
return market.plugin_market_content_url
return urlmethod.get_global_github_src_url()

@staticmethod
def _print_usage(command: str) -> None:
"""输出子命令的正确用法。"""
usages = {
"set": f"plg config set <{CONFIG_KEYS_HINT}> <URL>",
"unset": f"plg config unset <{CONFIG_KEYS_HINT}>",
"list": "plg config list",
}
fmts.print_err(f"用法: {usages[command]}")
1 change: 1 addition & 0 deletions tooldelta/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ def reload(self, deep_reload: bool = False):
fmts.print_inf("重载: 正在保存数据缓存文件..")
utils.safe_close(SysStatus.RELOAD)
self.cmd_manager.reset_cmds()
extend_functions.restore_console_cmds()
fmts.print_inf("重载: 正在重新载入插件..")
self.plugin_group.reload(deep_reload)
fmts.print_suc("重载插件: 全部插件重载成功!")
Expand Down
16 changes: 13 additions & 3 deletions tooldelta/plugin_market.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,21 @@ def __init__(self):
self._cached_plugins_id_map = {}
self._cached_market_filetree: FILETREE = {}
try:
self.plugin_market_content_url = cfg.get_cfg(
source_url = cfg.get_cfg(
"ToolDelta基本配置.json", {"插件市场源": str}
)["插件市场源"]
except Exception:
self.plugin_market_content_url = PLUGIN_MARKET_SOURCE_OFFICIAL
source_url = PLUGIN_MARKET_SOURCE_OFFICIAL
self.set_source_url(source_url)

def set_source_url(self, source_url: str) -> None:
"""切换插件市场源并清空已有缓存。"""
self.plugin_market_content_url = (
source_url or PLUGIN_MARKET_SOURCE_OFFICIAL
)
self._cached_market_tree.clear()
self._cached_plugins_id_map.clear()
self._cached_market_filetree.clear()

def enter_plugin_market(self, source_url: str | None = None, in_game=False) -> None:
"""
Expand All @@ -77,7 +87,7 @@ def enter_plugin_market(self, source_url: str | None = None, in_game=False) -> N
in_game (bool, optional): 是否在游戏内调用的插件市场命令
"""
if source_url:
self.plugin_market_content_url = source_url
self.set_source_url(source_url)

fmts.ansi_save_screen()
fmts.clean_print("§6正在连接到插件市场..")
Expand Down