Skip to content
Merged
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
13 changes: 0 additions & 13 deletions astrbot/cli/commands/cmd_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,6 @@
DASHBOARD_INITIAL_PASSWORD_ENV = "ASTRBOT_DASHBOARD_INITIAL_PASSWORD"


async def check_dashboard(astrbot_root: Path) -> None:
"""Check whether dashboard assets are available.

Args:
astrbot_root: AstrBot data directory path.
"""
from ..utils import check_dashboard as _check_dashboard

await _check_dashboard(astrbot_root)


def _initialize_config_from_env(astrbot_root: Path) -> None:
if DASHBOARD_INITIAL_PASSWORD_ENV not in os.environ:
return
Expand Down Expand Up @@ -60,8 +49,6 @@ async def initialize_astrbot(astrbot_root: Path, yes: bool = False) -> None:

_initialize_config_from_env(astrbot_root)

await check_dashboard(astrbot_root / "data")


@click.command()
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation prompts")
Expand Down
17 changes: 1 addition & 16 deletions astrbot/core/db/migration/migra_webchat_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from sqlalchemy import func, select
from sqlmodel import col

from astrbot.api import logger
from astrbot.core.db import BaseDatabase
from astrbot.core.db.po import ConversationV2, PlatformMessageHistory, PlatformSession

Expand All @@ -23,8 +22,6 @@ async def migrate_webchat_session(db_helper: BaseDatabase) -> None:
This migration extracts all unique user_ids from platform_message_history
where platform_id='webchat' and creates corresponding PlatformSession records.
"""
logger.info("开始执行数据库迁移(WebChat 会话迁移)...")

try:
async with db_helper.get_db() as session:
# 从 platform_message_history 创建 PlatformSession
Expand All @@ -44,11 +41,8 @@ async def migrate_webchat_session(db_helper: BaseDatabase) -> None:
webchat_users = result.all()

if not webchat_users:
logger.info("没有找到需要迁移的 WebChat 数据")
return

logger.info(f"找到 {len(webchat_users)} 个 WebChat 会话需要迁移")

# 检查已存在的会话
existing_query = select(col(PlatformSession.session_id))
existing_result = await session.execute(existing_query)
Expand Down Expand Up @@ -83,7 +77,6 @@ async def migrate_webchat_session(db_helper: BaseDatabase) -> None:

# 检查是否已经存在该会话
if session_id in existing_session_ids:
logger.debug(f"会话 {session_id} 已存在,跳过")
skipped_count += 1
continue

Expand All @@ -106,13 +99,5 @@ async def migrate_webchat_session(db_helper: BaseDatabase) -> None:
if sessions_to_add:
session.add_all(sessions_to_add)
await session.commit()

logger.info(
f"WebChat 会话迁移完成!成功迁移: {len(sessions_to_add)}, 跳过: {skipped_count}",
)
else:
logger.info("没有新会话需要迁移")

except Exception as e:
logger.error(f"迁移过程中发生错误: {e}", exc_info=True)
except Exception:
raise
6 changes: 3 additions & 3 deletions astrbot/dashboard/api/static_files.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import FileResponse, PlainTextResponse
from fastapi.responses import FileResponse, HTMLResponse

from astrbot.dashboard.services.static_file_service import StaticFileService

Expand All @@ -13,8 +13,8 @@ def _static_folder(request: Request) -> str | None:
return getattr(request.app.state, "dashboard_static_folder", None)


def _not_found_response() -> PlainTextResponse:
return PlainTextResponse(service.get_not_found_message(), status_code=404)
def _not_found_response() -> HTMLResponse:
return HTMLResponse(service.get_not_found_message(), status_code=404)


async def serve_index(request: Request):
Expand Down
67 changes: 64 additions & 3 deletions astrbot/dashboard/services/static_file_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,70 @@ class StaticFileService:
"/tool-use",
)
NOT_FOUND_MESSAGE = (
"404 Not found。如果你初次使用打开面板发现 404, 请参考文档: "
"https://docs.astrbot.app/faq.html。如果你正在测试回调地址可达性,"
"显示这段文字说明测试成功了。"
"<!doctype html>"
'<html lang="zh-CN">'
"<head>"
'<meta charset="utf-8">'
'<meta name="viewport" content="width=device-width, initial-scale=1">'
"<title>404 · WebUI 文件缺失 / WebUI files are missing</title>"
"<style>"
"*{box-sizing:border-box}"
"body{margin:0;min-height:100vh;display:grid;place-items:center;padding:24px;"
"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;"
"background:#f6f7f9;color:#1f2328}"
"main{width:min(100%,680px);padding:32px;background:#fff;border:1px solid #e5e7eb;"
"border-radius:16px}"
".status{margin:0 0 8px;color:#6b7280;font-size:14px;font-weight:600;"
"letter-spacing:.08em}"
"h1{margin:0 0 12px;font-size:28px}"
"h2{margin:28px 0 10px;font-size:18px}"
"h3{margin:28px 0 10px;font-size:18px}"
"p{margin:0 0 20px;color:#4b5563;line-height:1.7}"
"code,pre{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}"
"code{padding:2px 6px;background:#f3f4f6;border-radius:6px;color:#111827}"
".action{display:inline-block;margin-bottom:24px;padding:10px 16px;border-radius:9px;"
"background:#3c96ca;color:#fff;text-decoration:none;font-weight:600}"
".action:hover{background:#327fab}"
".action:focus-visible{outline:3px solid rgba(60,150,202,.3);outline-offset:3px}"
".english{margin-top:4px;padding-top:28px;border-top:1px solid #e5e7eb}"
".english h2{margin:0 0 12px;font-size:24px}"
".label{margin-bottom:8px;font-size:14px;font-weight:600;color:#374151}"
"pre{margin:0;padding:16px;overflow:auto;border:1px solid #e5e7eb;border-radius:10px;"
"background:#f9fafb;color:#374151;line-height:1.6}"
".note{margin:20px 0 0;font-size:14px;color:#6b7280}"
"</style>"
"</head>"
"<body><main>"
'<p class="status">404 · NOT FOUND</p>'
"<h1>WebUI 文件缺失</h1>"
"<p>AstrBot 会在启动时检测并尝试下载 WebUI 文件。看到此页面说明下载失败或文件不完整,"
"请先尝试重启 AstrBot。</p>"
"<h2>手动安装</h2>"
"<p>如果问题仍然存在,请前往 Releases 下载与当前 AstrBot 版本匹配的 "
"<code>AstrBot-vx.x.x-dashboard.zip</code>,解压后将 "
"<code>dist</code> 文件夹放入 <code>AstrBot/data/</code>。</p>"
'<a class="action" href="https://github.com/AstrBotDevs/AstrBot/releases">'
"前往 Releases 下载</a>"
'<section class="english" lang="en">'
"<h2>WebUI files are missing</h2>"
"<p>AstrBot checks for WebUI files and attempts to download them at startup. "
"If you see this page, the download failed or the files are incomplete. "
"Try restarting AstrBot first.</p>"
"<h3>Manual installation</h3>"
"<p>If the issue persists, open Releases and download "
"<code>AstrBot-vx.x.x-dashboard.zip</code> matching your current AstrBot version. "
"Extract it and place the <code>dist</code> folder under "
"<code>AstrBot/data/</code>.</p>"
'<a class="action" href="https://github.com/AstrBotDevs/AstrBot/releases">'
"Open Releases</a>"
"</section>"
'<p class="label">目录结构 / Directory structure</p>'
"<pre>AstrBot/\n└── data/\n └── dist/\n ├── index.html\n"
" └── assets/</pre>"
'<p class="note">正在测试回调地址?看到此页面表示地址可达。<br>'
'<span lang="en">Testing a callback URL? This page confirms that the URL is '
"reachable.</span></p>"
"</main></body></html>"
)

def list_index_routes(self) -> tuple[str, ...]:
Expand Down
14 changes: 2 additions & 12 deletions tests/test_cli_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@


def test_init_yes_skips_install_confirmation(monkeypatch, tmp_path):
async def fake_check_dashboard(_data_path):
return None

def fail_confirm(*_args, **_kwargs):
pytest.fail("-y should skip the installation confirmation")

monkeypatch.chdir(tmp_path)
monkeypatch.setattr(cmd_init, "check_dashboard", fake_check_dashboard)
monkeypatch.delenv(cmd_init.DASHBOARD_INITIAL_PASSWORD_ENV, raising=False)
monkeypatch.setattr(cmd_init.click, "confirm", fail_confirm)

result = CliRunner().invoke(cmd_init.init, ["-y"])
Expand All @@ -25,18 +22,15 @@ def fail_confirm(*_args, **_kwargs):
assert (tmp_path / "data" / "config").is_dir()
assert (tmp_path / "data" / "plugins").is_dir()
assert (tmp_path / "data" / "temp").is_dir()
assert not (tmp_path / "data" / "cmd_config.json").exists()


@pytest.mark.asyncio
async def test_init_without_initial_password_env_does_not_create_config(
monkeypatch,
tmp_path,
):
async def fake_check_dashboard(_data_path):
return None

monkeypatch.delenv(cmd_init.DASHBOARD_INITIAL_PASSWORD_ENV, raising=False)
monkeypatch.setattr(cmd_init, "check_dashboard", fake_check_dashboard)
(tmp_path / ".astrbot").touch()

await cmd_init.initialize_astrbot(tmp_path)
Expand All @@ -49,12 +43,8 @@ async def test_init_uses_initial_password_env_to_create_config(
monkeypatch,
tmp_path,
):
async def fake_check_dashboard(_data_path):
return None

initial_password = "AstrBotInitialPassword123"
monkeypatch.setenv(cmd_init.DASHBOARD_INITIAL_PASSWORD_ENV, initial_password)
monkeypatch.setattr(cmd_init, "check_dashboard", fake_check_dashboard)
(tmp_path / ".astrbot").touch()

await cmd_init.initialize_astrbot(tmp_path)
Expand Down
7 changes: 7 additions & 0 deletions tests/test_fastapi_v1_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,13 @@ async def test_dashboard_static_dist_files_are_served(
assert page_response.status_code == 200
assert "/assets/index-demo.js" in page_response.text
assert missing_response.status_code == 404
assert missing_response.headers["content-type"].startswith("text/html")
assert "请先尝试重启 AstrBot" in missing_response.text
assert "<h2>手动安装</h2>" in missing_response.text
assert "WebUI files are missing" in missing_response.text
assert "Manual installation" in missing_response.text
assert "AstrBot-vx.x.x-dashboard.zip" in missing_response.text
assert "index.html" in missing_response.text
assert traversal_response.status_code == 404
assert api_response.status_code == 404

Expand Down
Loading