diff --git a/astrbot/cli/__main__.py b/astrbot/cli/__main__.py index 4ba45df5f..f1d879b86 100644 --- a/astrbot/cli/__main__.py +++ b/astrbot/cli/__main__.py @@ -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: diff --git a/astrbot/cli/banner.py b/astrbot/cli/banner.py new file mode 100644 index 000000000..ea75ecf3a --- /dev/null +++ b/astrbot/cli/banner.py @@ -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) diff --git a/astrbot/cli/commands/cmd_init.py b/astrbot/cli/commands/cmd_init.py index 6c8577793..bffb5f99b 100644 --- a/astrbot/cli/commands/cmd_init.py +++ b/astrbot/cli/commands/cmd_init.py @@ -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" diff --git a/astrbot/cli/commands/cmd_run.py b/astrbot/cli/commands/cmd_run.py index a2bf0d81f..3a045a184 100644 --- a/astrbot/cli/commands/cmd_run.py +++ b/astrbot/cli/commands/cmd_run.py @@ -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: diff --git a/astrbot/core/platform/sources/weixin_oc/weixin_oc_adapter.py b/astrbot/core/platform/sources/weixin_oc/weixin_oc_adapter.py index d3badb884..0aee360d0 100644 --- a/astrbot/core/platform/sources/weixin_oc/weixin_oc_adapter.py +++ b/astrbot/core/platform/sources/weixin_oc/weixin_oc_adapter.py @@ -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,