Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.10
3.10
13 changes: 9 additions & 4 deletions astrbot/cli/commands/cmd_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ async def run_astrbot(astrbot_root: Path):


@click.option("--reload", "-r", is_flag=True, help="插件自动重载")
@click.option("--port", "-p", help="Astrbot Dashboard端口", required=False, type=str)
@click.option(
"--host", "-h", help="Astrbot Dashboard Host,默认::", required=False, type=str
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Outdated
)
@click.option(
"--port", "-p", help="Astrbot Dashboard端口,默认6185", required=False, type=str
)
@click.command()
def run(reload: bool, port: str) -> None:
def run(reload: bool, host: str, port: str) -> None:
Comment thread
LIghtJUNction marked this conversation as resolved.
Outdated
"""运行 AstrBot"""
try:
os.environ["ASTRBOT_CLI"] = "1"
Expand All @@ -43,8 +48,8 @@ def run(reload: bool, port: str) -> None:
os.environ["ASTRBOT_ROOT"] = str(astrbot_root)
sys.path.insert(0, str(astrbot_root))

if port:
os.environ["DASHBOARD_PORT"] = port
os.environ["DASHBOARD_PORT"] = port or "6185"
os.environ["DASHBOARD_HOST"] = host or "::"
Comment thread
LIghtJUNction marked this conversation as resolved.

if reload:
click.echo("启用插件自动重载")
Expand Down
14 changes: 7 additions & 7 deletions astrbot/core/config/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@
"username": "astrbot",
"password": "77b90590a8945a7d36c963981a307dc9",
"jwt_secret": "",
"host": "0.0.0.0",
"host": "::",
"port": 6185,
"disable_access_log": True,
},
Expand Down Expand Up @@ -273,14 +273,14 @@ class ChatProviderTemplate(TypedDict):
"is_sandbox": False,
"unified_webhook_mode": True,
"webhook_uuid": "",
"callback_server_host": "0.0.0.0",
"callback_server_host": "::",
"port": 6196,
},
"OneBot v11": {
"id": "default",
"type": "aiocqhttp",
"enable": False,
"ws_reverse_host": "0.0.0.0",
"ws_reverse_host": "::",
"ws_reverse_port": 6199,
"ws_reverse_token": "",
},
Expand All @@ -295,7 +295,7 @@ class ChatProviderTemplate(TypedDict):
"api_base_url": "https://api.weixin.qq.com/cgi-bin/",
"unified_webhook_mode": True,
"webhook_uuid": "",
"callback_server_host": "0.0.0.0",
"callback_server_host": "::",
"port": 6194,
"active_send_mode": False,
},
Expand All @@ -311,7 +311,7 @@ class ChatProviderTemplate(TypedDict):
"api_base_url": "https://qyapi.weixin.qq.com/cgi-bin/",
"unified_webhook_mode": True,
"webhook_uuid": "",
"callback_server_host": "0.0.0.0",
"callback_server_host": "::",
"port": 6195,
},
"企业微信智能机器人": {
Expand All @@ -325,7 +325,7 @@ class ChatProviderTemplate(TypedDict):
"encoding_aes_key": "",
"unified_webhook_mode": True,
"webhook_uuid": "",
"callback_server_host": "0.0.0.0",
"callback_server_host": "::",
"port": 6198,
},
"飞书(Lark)": {
Expand Down Expand Up @@ -399,7 +399,7 @@ class ChatProviderTemplate(TypedDict):
"slack_connection_mode": "socket", # webhook, socket
"unified_webhook_mode": True,
"webhook_uuid": "",
"slack_webhook_host": "0.0.0.0",
"slack_webhook_host": "::",
"slack_webhook_port": 6197,
"slack_webhook_path": "/astrbot-slack-webhook/callback",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,9 @@ async def _convert_handle_message_event(
def run(self) -> Awaitable[Any]:
if not self.host or not self.port:
logger.warning(
"aiocqhttp: 未配置 ws_reverse_host 或 ws_reverse_port,将使用默认值:http://0.0.0.0:6199",
"aiocqhttp: 未配置 ws_reverse_host 或 ws_reverse_port,将使用默认值:http://[::]:6199",
)
self.host = "0.0.0.0"
self.host = "::"
self.port = 6199

coro = self.bot.run_task(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, config: dict, event_queue: asyncio.Queue, botpy_client: Clien
self.secret = config["secret"]
self.port = config.get("port", 6196)
self.is_sandbox = config.get("is_sandbox", False)
self.callback_server_host = config.get("callback_server_host", "0.0.0.0")
self.callback_server_host = config.get("callback_server_host", "::")

if isinstance(self.port, str):
self.port = int(self.port)
Expand Down
2 changes: 1 addition & 1 deletion astrbot/core/platform/sources/slack/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(
self,
web_client: AsyncWebClient,
signing_secret: str,
host: str = "0.0.0.0",
host: str = "::",
port: int = 3000,
path: str = "/slack/events",
event_handler: Callable | None = None,
Expand Down
2 changes: 1 addition & 1 deletion astrbot/core/platform/sources/slack/slack_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(
self.signing_secret = platform_config.get("signing_secret")
self.connection_mode = platform_config.get("slack_connection_mode", "socket")
self.unified_webhook_mode = platform_config.get("unified_webhook_mode", False)
self.webhook_host = platform_config.get("slack_webhook_host", "0.0.0.0")
self.webhook_host = platform_config.get("slack_webhook_host", "::")
self.webhook_port = platform_config.get("slack_webhook_port", 3000)
self.webhook_path = platform_config.get(
"slack_webhook_path",
Expand Down
2 changes: 1 addition & 1 deletion astrbot/core/platform/sources/wecom/wecom_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class WecomServer:
def __init__(self, event_queue: asyncio.Queue, config: dict):
self.server = quart.Quart(__name__)
self.port = int(cast(str, config.get("port")))
self.callback_server_host = config.get("callback_server_host", "0.0.0.0")
self.callback_server_host = config.get("callback_server_host", "::")
self.server.add_url_rule(
"/callback/command",
view_func=self.verify,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def __init__(
self.token = self.config["token"]
self.encoding_aes_key = self.config["encoding_aes_key"]
self.port = int(self.config["port"])
self.host = self.config.get("callback_server_host", "0.0.0.0")
self.host = self.config.get("callback_server_host", "::")
self.bot_name = self.config.get("wecom_ai_bot_name", "")
self.initial_respond_text = self.config.get(
"wecomaibot_init_respond_text",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class WeixinOfficialAccountServer:
def __init__(self, event_queue: asyncio.Queue, config: dict):
self.server = quart.Quart(__name__)
self.port = int(cast(int | str, config.get("port")))
self.callback_server_host = config.get("callback_server_host", "0.0.0.0")
self.callback_server_host = config.get("callback_server_host", "::")
self.token = config.get("token")
self.encoding_aes_key = config.get("encoding_aes_key")
self.appid = config.get("appid")
Expand Down
55 changes: 39 additions & 16 deletions astrbot/dashboard/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from flask.json.provider import DefaultJSONProvider
from hypercorn.asyncio import serve
from hypercorn.config import Config as HyperConfig
from psutil._common import addr as psutil_addr
from quart import Quart, g, jsonify, request
from quart.logging import default_handler

Expand Down Expand Up @@ -168,7 +167,7 @@ def get_process_using_port(self, port: int) -> str:
"""获取占用端口的进程详细信息"""
try:
for conn in psutil.net_connections(kind="inet"):
Comment thread
LIghtJUNction marked this conversation as resolved.
Outdated
if cast(psutil_addr, conn.laddr).port == port:
if conn.laddr and conn.laddr.port == port:
try:
process = psutil.Process(conn.pid)
# 获取详细信息
Expand Down Expand Up @@ -197,29 +196,45 @@ def _init_jwt_secret(self):

def run(self):
ip_addr = []
if p := os.environ.get("DASHBOARD_PORT"):
port = p
else:
port = self.core_lifecycle.astrbot_config["dashboard"].get("port", 6185)
host = self.core_lifecycle.astrbot_config["dashboard"].get("host", "0.0.0.0")
enable = self.core_lifecycle.astrbot_config["dashboard"].get("enable", True)
conf = self.core_lifecycle.astrbot_config["dashboard"]
port = os.environ.get("DASHBOARD_PORT") or conf.get("port", 6185)
host = os.environ.get("DASHBOARD_HOST") or conf.get("host", "::")
enable = os.environ.get("DASHBOARD_ENABLE") or conf.get("enable", True)
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Outdated
Comment thread
LIghtJUNction marked this conversation as resolved.
Outdated

if not enable:
logger.info("WebUI 已被禁用")
return None

logger.info(f"正在启动 WebUI, 监听地址: http://{host}:{port}")
display_host = f"[{host}]" if ":" in host and "[" not in host else host
logger.info(f"正在启动 WebUI, 监听地址: http://{display_host}:{port}")

if host == "0.0.0.0":
if host == "::" or host == "0.0.0.0":
logger.info(
"提示: WebUI 将监听所有网络接口,请注意安全。(可在 data/cmd_config.json 中配置 dashboard.host 以修改 host)",
)

if host not in ["localhost", "127.0.0.1"]:
try:
ip_addr = get_local_ip_addresses()
except Exception as _:
pass
if host == "::" or host == "0.0.0.0":
try:
ip_addr = get_local_ip_addresses()
# 尝试获取 IPv6 地址
import socket
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The socket module is imported inline at line 221, but it's already imported at the top of the file (line 4). This duplicate import is unnecessary and inconsistent with the existing code structure.

Remove the inline import and use the existing socket import from the module level.

Suggested change
import socket

Copilot uses AI. Check for mistakes.

try:
for res in socket.getaddrinfo(
socket.gethostname(), None, socket.AF_INET6
):
ip: str = str(res[4][0])
if (
ip not in ip_addr
and not ip.startswith("fe80")
and ip != "::1"
):
ip_addr.append(ip)
except Exception:
pass
except Exception as _:
pass
Comment thread
LIghtJUNction marked this conversation as resolved.
Outdated
Comment thread
LIghtJUNction marked this conversation as resolved.
Outdated
Comment thread
LIghtJUNction marked this conversation as resolved.
Outdated
if isinstance(port, str):
port = int(port)

Expand All @@ -239,7 +254,12 @@ def run(self):
parts = [f"\n ✨✨✨\n AstrBot v{VERSION} WebUI 已启动,可访问\n\n"]
parts.append(f" ➜ 本地: http://localhost:{port}\n")
for ip in ip_addr:
parts.append(f" ➜ 网络: http://{ip}:{port}\n")
display_ip = f"[{ip}]" if ":" in ip else ip
parts.append(f" ➜ 网络: http://{display_ip}:{port}\n")

if any(":" in ip and not ip.startswith(("fe80", "::1")) for ip in ip_addr):
parts.append(" ➜ 提示: 检测到公网 IPv6 地址,已开启 IPv6 支持。\n")
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Outdated
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition any(":" in ip and not ip.startswith(("fe80", "::1")) for ip in ip_addr) on line 260 intends to detect public IPv6 addresses, but this logic is flawed. It will match any IPv6 address containing ":" that doesn't start with "fe80" or "::1", including private IPv6 addresses like those in the fd00::/8 range (Unique Local Addresses). This could result in displaying the "检测到公网 IPv6 地址" message for private IPv6 addresses, which is misleading.

Consider adding additional checks for other private IPv6 address ranges (e.g., fc00::/7 for ULA addresses) or improving the logic to more accurately identify public IPv6 addresses.

Copilot uses AI. Check for mistakes.

parts.append(" ➜ 默认用户名和密码: astrbot\n ✨✨✨\n")
display = "".join(parts)

Expand All @@ -252,7 +272,10 @@ def run(self):

# 配置 Hypercorn
config = HyperConfig()
config.bind = [f"{host}:{port}"]
if ":" in host and "[" not in host:
config.bind = [f"[{host}]:{port}"]
else:
config.bind = [f"{host}:{port}"]

# 根据配置决定是否禁用访问日志
disable_access_log = self.core_lifecycle.astrbot_config.get(
Expand Down
46 changes: 23 additions & 23 deletions dashboard/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
import { fileURLToPath, URL } from 'url';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vuetify from 'vite-plugin-vuetify';
import { fileURLToPath, URL } from "url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vuetify from "vite-plugin-vuetify";

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => ['v-list-recognize-title'].includes(tag)
}
}
isCustomElement: (tag) => ["v-list-recognize-title"].includes(tag),
},
},
}),
vuetify({
autoImport: true
})
autoImport: true,
}),
],
resolve: {
alias: {
mermaid: 'mermaid/dist/mermaid.js',
'@': fileURLToPath(new URL('./src', import.meta.url))
}
mermaid: "mermaid/dist/mermaid.js",
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
css: {
preprocessorOptions: {
scss: {}
}
scss: {},
},
},
build: {
chunkSizeWarningLimit: 1024 * 1024 // Set the limit to 1 MB
chunkSizeWarningLimit: 1024 * 1024, // Set the limit to 1 MB
},
optimizeDeps: {
exclude: ['vuetify'],
entries: ['./src/**/*.vue']
exclude: ["vuetify"],
entries: ["./src/**/*.vue"],
},
server: {
host: '0.0.0.0',
host: "::",
port: 3000,
proxy: {
'/api': {
target: 'http://127.0.0.1:6185/',
"/api": {
target: "http://127.0.0.1:6185/",
changeOrigin: true,
}
}
}
},
},
},
});
Loading