feat(cli): show ASCII logo and QR code only in interactive mode

- Move logo and print_logo to new astrbot/cli/banner.py module
  to avoid circular imports
- Add is_interactive() helper to detect TTY
- Show ASCII logo in run/init commands only in interactive mode
- Show WeChat QR code ASCII art only in interactive mode;
  non-interactive mode shows just the QR link
This commit is contained in:
LIghtJUNction
2026-04-10 22:42:43 +08:00
parent cb9d7c0bfa
commit 6a81739392
5 changed files with 66 additions and 22 deletions
+1 -8
View File
@@ -12,14 +12,7 @@ from . import __version__
from .commands import bk, conf, init, plug, run, uninstall
from .i18n import t
logo_tmpl = r"""
___ _______.___________..______ .______ ______ .___________.
/ \ / | || _ \ | _ \ / __ \ | |
/ ^ \ | (----`---| |----`| |_) | | |_) | | | | | `---| |----`
/ /_\ \ \ \ | | | / | _ < | | | | | |
/ _____ \ .----) | | | | |\ \----.| |_) | | `--' | | |
/__/ \__\ |_______/ |__| | _| `._____||______/ \______/ |__|
"""
from .banner import logo_tmpl
def print_version_detail() -> None:
+29
View File
@@ -0,0 +1,29 @@
"""ASCII logo and interactive mode utilities for CLI"""
import sys
logo_tmpl = r"""
___ _______.___________..______ .______ ______ .___________.
/ \ / | || _ \ | _ \ / __ \ | |
/ ^ \ | (----`---| |----`| |_) | | |_) | | | | | `---| |----`
/ /_\ \ \ \ | | | / | _ < | | | | | |
/ _____ \ .----) | | | | |\ \----.| |_) | | `--' | | |
/__/ \__\ |_______/ |__| | _| `._____||______/ \______/ |__|
"""
def is_interactive() -> bool:
"""Check if stdout is connected to a TTY (interactive terminal)"""
try:
return sys.stdout.isatty()
except Exception:
return False
def print_logo() -> None:
"""Print ASCII logo if in interactive mode"""
import click
if is_interactive():
click.echo(logo_tmpl)
+3
View File
@@ -23,9 +23,12 @@ async def initialize_astrbot(
admin_password: str | None,
) -> None:
"""Execute AstrBot initialization logic"""
from astrbot.cli.banner import print_logo
click.echo("=" * 60)
click.echo("AstrBot 初始化向导")
click.echo("=" * 60)
print_logo()
click.echo()
dot_astrbot = astrbot_root / ".astrbot"
+4
View File
@@ -382,6 +382,10 @@ def run(
click.echo("=" * 60)
click.echo("AstrBot 启动中...")
click.echo("=" * 60)
from astrbot.cli.banner import print_logo
print_logo()
click.echo()
if backend_only:
@@ -4,6 +4,7 @@ import asyncio
import base64
import hashlib
import io
import sys
import time
import uuid
from dataclasses import dataclass, field
@@ -817,23 +818,37 @@ class WeixinOCAdapter(Platform):
if not qrcode or not qrcode_url:
raise RuntimeError("qrcode response missing qrcode or qrcode_img_content")
qr_console_url = f"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data={quote(qrcode_url)}"
logger.info(
"weixin_oc(%s): QR session started, qr_link=%s 请使用手机微信扫码登录,二维码有效期 5 分钟,过期后会自动刷新。",
self.meta().id,
qr_console_url,
)
try:
qr = qrcode_lib.QRCode(border=1)
qr.add_data(qrcode_url)
qr.make(fit=True)
qr_buffer = io.StringIO()
qr.print_ascii(out=qr_buffer, tty=False)
# Only show QR code login info in interactive terminal
if sys.stdout.isatty():
logger.info(
"weixin_oc(%s): terminal QR code:\n%s",
"weixin_oc(%s): QR session started, qr_link=%s 请使用手机微信扫码登录,二维码有效期 5 分钟,过期后会自动刷新。",
self.meta().id,
qr_buffer.getvalue(),
qr_console_url,
)
try:
qr = qrcode_lib.QRCode(border=1)
qr.add_data(qrcode_url)
qr.make(fit=True)
qr_buffer = io.StringIO()
qr.print_ascii(out=qr_buffer, tty=False)
logger.info(
"weixin_oc(%s): terminal QR code:\n%s",
self.meta().id,
qr_buffer.getvalue(),
)
except Exception as e:
logger.warning(
"weixin_oc(%s): failed to render terminal QR code: %s",
self.meta().id,
e,
)
else:
# Non-interactive mode: just show the QR code link
logger.info(
"weixin_oc(%s): QR login link: %s",
self.meta().id,
qr_console_url,
)
except Exception as e:
logger.warning(
"weixin_oc(%s): failed to render terminal QR code: %s",
self.meta().id,