mirror of
https://github.com/AstrBotDevs/AstrBot.git
synced 2026-09-24 16:39:52 +08:00
Merge remote-tracking branch 'origin' into dev
# Conflicts: # astrbot/builtin_stars/astrbot/main.py # astrbot/cli/__main__.py # astrbot/cli/commands/__init__.py # astrbot/core/provider/sources/openai_source.py
This commit is contained in:
@@ -176,7 +176,7 @@ class Main(star.Star):
|
||||
|
||||
if not session_curr_cid:
|
||||
logger.error(
|
||||
"当前未处于对话状态,无法主动回复,请确保 平台设置->会话隔离(unique_session) 未开启,并使用 /switch 序号 切换或者 /new 创建一个会话。",
|
||||
"当前未处于对话状态,无法主动回复,请确保 平台设置->会话隔离(unique_session) 未开启,并使用 /new 创建一个会话。",
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import click
|
||||
from click.shell_completion import get_completion_class
|
||||
|
||||
from . import __version__
|
||||
from .commands import bk, conf, init, plug, run, uninstall
|
||||
from .commands import bk, conf, init, password, plug, run, uninstall
|
||||
from .i18n import t
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ cli.add_command(plug)
|
||||
cli.add_command(conf)
|
||||
cli.add_command(uninstall)
|
||||
cli.add_command(bk)
|
||||
cli.add_command(password)
|
||||
|
||||
|
||||
@click.command()
|
||||
@@ -172,6 +173,5 @@ def version_cmd() -> None:
|
||||
|
||||
cli.add_command(version_cmd)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from .cmd_bk import bk
|
||||
from .cmd_conf import conf
|
||||
from .cmd_init import init
|
||||
from .cmd_password import password
|
||||
from .cmd_plug import plug
|
||||
from .cmd_run import run
|
||||
from .cmd_uninstall import uninstall
|
||||
|
||||
__all__ = ["bk", "conf", "init", "plug", "run", "uninstall"]
|
||||
__all__ = ["bk", "conf", "init", "password", "plug", "run", "uninstall"]
|
||||
|
||||
@@ -214,6 +214,22 @@ def set_dashboard_credentials(
|
||||
)
|
||||
|
||||
|
||||
def _set_dashboard_password(config: dict[str, Any], raw_password: str) -> None:
|
||||
"""Set dashboard password hashes and clear password migration flags."""
|
||||
_set_nested_item(
|
||||
config,
|
||||
"dashboard.pbkdf2_password",
|
||||
hash_dashboard_password(raw_password),
|
||||
)
|
||||
_set_nested_item(
|
||||
config,
|
||||
"dashboard.password",
|
||||
hash_legacy_dashboard_password(raw_password),
|
||||
)
|
||||
_set_nested_item(config, "dashboard.password_storage_upgraded", True)
|
||||
_set_nested_item(config, "dashboard.password_change_required", False)
|
||||
|
||||
|
||||
@click.group(name="conf")
|
||||
def conf() -> None:
|
||||
"""Configuration management commands.
|
||||
@@ -245,16 +261,7 @@ def set_config(key: str, value: str) -> None:
|
||||
|
||||
validated_value = CONFIG_VALIDATORS[key](value)
|
||||
if key == "dashboard.password":
|
||||
_set_nested_item(
|
||||
config,
|
||||
"dashboard.pbkdf2_password",
|
||||
hash_dashboard_password(validated_value),
|
||||
)
|
||||
_set_nested_item(
|
||||
config,
|
||||
"dashboard.password",
|
||||
hash_legacy_dashboard_password(validated_value),
|
||||
)
|
||||
_set_dashboard_password(config, validated_value)
|
||||
else:
|
||||
_set_nested_item(config, key, validated_value)
|
||||
_save_config(config)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import click
|
||||
|
||||
from .cmd_conf import (
|
||||
_load_config,
|
||||
_save_config,
|
||||
_set_dashboard_password,
|
||||
_set_nested_item,
|
||||
_validate_dashboard_password,
|
||||
_validate_dashboard_username,
|
||||
)
|
||||
|
||||
|
||||
@click.command(name="password")
|
||||
@click.option(
|
||||
"--username",
|
||||
help="Optional dashboard username to set together with the new password.",
|
||||
)
|
||||
def password(username: str | None) -> None:
|
||||
"""Change the AstrBot dashboard password."""
|
||||
config = _load_config()
|
||||
|
||||
new_password = click.prompt(
|
||||
"New dashboard password",
|
||||
hide_input=True,
|
||||
confirmation_prompt=True,
|
||||
)
|
||||
validated_password = _validate_dashboard_password(new_password)
|
||||
|
||||
if username is not None:
|
||||
validated_username = _validate_dashboard_username(username.strip())
|
||||
_set_nested_item(config, "dashboard.username", validated_username)
|
||||
|
||||
_set_dashboard_password(config, validated_password)
|
||||
_save_config(config)
|
||||
|
||||
click.echo("Dashboard password updated.")
|
||||
if username is not None:
|
||||
click.echo(f"Dashboard username updated: {validated_username}")
|
||||
@@ -1050,7 +1050,7 @@ CONFIG_METADATA_2: Any = {
|
||||
"id_whitelist": {
|
||||
"type": "list",
|
||||
"items": {"type": "string"},
|
||||
"hint": "只处理填写的 ID 发来的消息事件,为空时不启用。可使用 /sid 指令获取在平台上的会话 ID(类似 abc:GroupMessage:123)。管理员可使用 /wl 添加白名单",
|
||||
"hint": "只处理填写的 ID 发来的消息事件,为空时不启用。可使用 /sid 指令获取在平台上的会话 ID(类似 abc:GroupMessage:123)。管理员可在 WebUI 的平台设置中管理白名单",
|
||||
},
|
||||
"id_whitelist_log": {
|
||||
"type": "bool",
|
||||
|
||||
@@ -373,7 +373,7 @@ class ResultDecorateStage(Stage):
|
||||
return
|
||||
if time.time() - render_start > 3:
|
||||
logger.warning(
|
||||
"文本转图片耗时超过了 3 秒,如果觉得很慢可以使用 /t2i 关闭文本转图片模式。",
|
||||
"文本转图片耗时超过了 3 秒,如果觉得很慢可以在 WebUI 中关闭文本转图片模式。",
|
||||
)
|
||||
if url:
|
||||
if url.startswith("http"):
|
||||
|
||||
@@ -1153,9 +1153,9 @@ class ProviderOpenAIOfficial(Provider):
|
||||
or ("tool" in str(e).lower() and "support" in str(e).lower())
|
||||
or ("function" in str(e).lower() and "support" in str(e).lower())
|
||||
):
|
||||
# openai, ollama, gemini openai, siliconcloud 的错误提示与 code 不统一,只能通过字符串匹配
|
||||
logger.info(
|
||||
f"{self.get_model()} 不支持函数工具调用,已自动去除,不影响使用。",
|
||||
# openai, ollama, gemini openai, siliconcloud 的错误提示与 code 不统一,只能通过字符串匹配
|
||||
logger.warning(
|
||||
f"{self.get_model()} 不支持函数工具调用,已自动去除,不影响使用。如需永久关闭,可前往 WebUI 中关闭工具调用。",
|
||||
)
|
||||
payloads.pop("tools", None)
|
||||
return (
|
||||
@@ -1169,9 +1169,6 @@ class ProviderOpenAIOfficial(Provider):
|
||||
)
|
||||
# logger.error(f"发生了错误。Provider 配置如下: {self.provider_config}")
|
||||
|
||||
if "tool" in str(e).lower() and "support" in str(e).lower():
|
||||
logger.error("疑似该模型不支持函数调用工具调用。请输入 /tool off_all")
|
||||
|
||||
if is_connection_error(e):
|
||||
proxy = self.provider_config.get("proxy", "")
|
||||
log_connection_failure("OpenAI", e, proxy)
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import copy
|
||||
import json
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
from astrbot.cli.commands.cmd_conf import conf
|
||||
from astrbot.cli.commands.cmd_password import password
|
||||
from astrbot.core.config.default import DEFAULT_CONFIG
|
||||
from astrbot.core.utils.auth_password import verify_dashboard_password
|
||||
|
||||
|
||||
def _write_config(root):
|
||||
(root / ".astrbot").touch()
|
||||
data_dir = root / "data"
|
||||
data_dir.mkdir()
|
||||
config = copy.deepcopy(DEFAULT_CONFIG)
|
||||
config["dashboard"]["password_change_required"] = True
|
||||
config["dashboard"]["password_storage_upgraded"] = False
|
||||
config_path = data_dir / "cmd_config.json"
|
||||
config_path.write_text(
|
||||
json.dumps(config, ensure_ascii=False, indent=2),
|
||||
encoding="utf-8-sig",
|
||||
)
|
||||
return config_path
|
||||
|
||||
|
||||
def _read_config(config_path):
|
||||
return json.loads(config_path.read_text(encoding="utf-8-sig"))
|
||||
|
||||
|
||||
def test_password_command_changes_dashboard_password(monkeypatch, tmp_path):
|
||||
config_path = _write_config(tmp_path)
|
||||
monkeypatch.chdir(tmp_path)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
password,
|
||||
input="AstrbotChanged123\nAstrbotChanged123\n",
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
config = _read_config(config_path)
|
||||
dashboard_config = config["dashboard"]
|
||||
assert verify_dashboard_password(
|
||||
dashboard_config["pbkdf2_password"],
|
||||
"AstrbotChanged123",
|
||||
)
|
||||
assert verify_dashboard_password(
|
||||
dashboard_config["password"],
|
||||
"AstrbotChanged123",
|
||||
)
|
||||
assert dashboard_config["password_storage_upgraded"] is True
|
||||
assert dashboard_config["password_change_required"] is False
|
||||
|
||||
|
||||
def test_password_command_can_update_dashboard_username(monkeypatch, tmp_path):
|
||||
config_path = _write_config(tmp_path)
|
||||
monkeypatch.chdir(tmp_path)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
password,
|
||||
["--username", "astrbot-admin"],
|
||||
input="AstrbotChanged123\nAstrbotChanged123\n",
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
config = _read_config(config_path)
|
||||
assert config["dashboard"]["username"] == "astrbot-admin"
|
||||
|
||||
|
||||
def test_conf_set_dashboard_password_updates_password_state(monkeypatch, tmp_path):
|
||||
config_path = _write_config(tmp_path)
|
||||
monkeypatch.chdir(tmp_path)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
conf,
|
||||
["set", "dashboard.password", "AstrbotChanged123"],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
config = _read_config(config_path)
|
||||
dashboard_config = config["dashboard"]
|
||||
assert verify_dashboard_password(
|
||||
dashboard_config["pbkdf2_password"],
|
||||
"AstrbotChanged123",
|
||||
)
|
||||
assert dashboard_config["password_storage_upgraded"] is True
|
||||
assert dashboard_config["password_change_required"] is False
|
||||
Reference in New Issue
Block a user