🎨 escape message before colorful log

This commit is contained in:
yanyongyu 2021-08-12 16:45:22 +08:00
parent a534f7b58c
commit f2b23f1b44
11 changed files with 68 additions and 53 deletions

View File

@ -232,8 +232,8 @@ def init(*, _env_file: Optional[str] = None, **kwargs):
default_filter.level = ( default_filter.level = (
"DEBUG" if config.debug else "DEBUG" if config.debug else
"INFO") if config.log_level is None else config.log_level "INFO") if config.log_level is None else config.log_level
logger.opt( logger.opt(colors=True).info(
colors=True).info(f"Current <y><b>Env: {env.environment}</b></y>") f"Current <y><b>Env: {escape_tag(env.environment)}</b></y>")
logger.opt(colors=True).debug( logger.opt(colors=True).debug(
f"Loaded <y><b>Config</b></y>: {escape_tag(str(config.dict()))}") f"Loaded <y><b>Config</b></y>: {escape_tag(str(config.dict()))}")

View File

@ -11,6 +11,7 @@ from dataclasses import dataclass, field
from typing import Any, Set, Dict, Type, Union, Optional, Callable, Awaitable, TYPE_CHECKING from typing import Any, Set, Dict, Type, Union, Optional, Callable, Awaitable, TYPE_CHECKING
from nonebot.log import logger from nonebot.log import logger
from nonebot.utils import escape_tag
from nonebot.config import Env, Config from nonebot.config import Env, Config
from nonebot.typing import T_BotConnectionHook, T_BotDisconnectionHook from nonebot.typing import T_BotConnectionHook, T_BotDisconnectionHook
@ -87,13 +88,13 @@ class Driver(abc.ABC):
* ``**kwargs``: 其他传递给适配器的参数 * ``**kwargs``: 其他传递给适配器的参数
""" """
if name in self._adapters: if name in self._adapters:
logger.opt( logger.opt(colors=True).debug(
colors=True).debug(f'Adapter "<y>{name}</y>" already exists') f'Adapter "<y>{escape_tag(name)}</y>" already exists')
return return
self._adapters[name] = adapter self._adapters[name] = adapter
adapter.register(self, self.config, **kwargs) adapter.register(self, self.config, **kwargs)
logger.opt( logger.opt(colors=True).debug(
colors=True).debug(f'Succeeded to load adapter "<y>{name}</y>"') f'Succeeded to load adapter "<y>{escape_tag(name)}</y>"')
@property @property
@abc.abstractmethod @abc.abstractmethod
@ -119,7 +120,7 @@ class Driver(abc.ABC):
* ``**kwargs`` * ``**kwargs``
""" """
logger.opt(colors=True).debug( logger.opt(colors=True).debug(
f"<g>Loaded adapters: {', '.join(self._adapters)}</g>") f"<g>Loaded adapters: {escape_tag(', '.join(self._adapters))}</g>")
@abc.abstractmethod @abc.abstractmethod
def on_startup(self, func: Callable) -> Callable: def on_startup(self, func: Callable) -> Callable:

View File

@ -16,6 +16,7 @@ from yarl import URL
from nonebot.log import logger from nonebot.log import logger
from nonebot.adapters import Bot from nonebot.adapters import Bot
from nonebot.utils import escape_tag
from nonebot.typing import overrides from nonebot.typing import overrides
from nonebot.config import Env, Config from nonebot.config import Env, Config
from nonebot.drivers import (ForwardDriver, HTTPPollingSetup, WebSocketSetup, from nonebot.drivers import (ForwardDriver, HTTPPollingSetup, WebSocketSetup,
@ -213,7 +214,8 @@ class Driver(ForwardDriver):
url = URL(setup.url) url = URL(setup.url)
if not url.is_absolute() or not url.host: if not url.is_absolute() or not url.host:
logger.opt(colors=True).error( logger.opt(colors=True).error(
f"<r><bg #f8bbd0>Error parsing url {url}</bg #f8bbd0></r>") f"<r><bg #f8bbd0>Error parsing url {escape_tag(str(url))}</bg #f8bbd0></r>"
)
return return
host = f"{url.host}:{url.port}" if url.port else url.host host = f"{url.host}:{url.port}" if url.port else url.host
return HTTPRequest(setup.http_version, url.scheme, url.path, return HTTPRequest(setup.http_version, url.scheme, url.path,
@ -226,8 +228,8 @@ class Driver(ForwardDriver):
setup_: Optional[HTTPPollingSetup] = None setup_: Optional[HTTPPollingSetup] = None
logger.opt(colors=True).info( logger.opt(colors=True).info(
f"Start http polling for <y>{setup.adapter.upper()} " f"Start http polling for <y>{escape_tag(setup.adapter.upper())} "
f"Bot {setup.self_id}</y>") f"Bot {escape_tag(setup.self_id)}</y>")
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
@ -265,7 +267,8 @@ class Driver(ForwardDriver):
else: else:
logger.opt(colors=True).error( logger.opt(colors=True).error(
"<r><bg #f8bbd0>Unsupported HTTP Version " "<r><bg #f8bbd0>Unsupported HTTP Version "
f"{request.http_version}</bg #f8bbd0></r>") f"{escape_tag(request.http_version)}</bg #f8bbd0></r>"
)
return return
logger.debug( logger.debug(
@ -284,7 +287,7 @@ class Driver(ForwardDriver):
asyncio.create_task(bot.handle_message(data)) asyncio.create_task(bot.handle_message(data))
except aiohttp.ClientResponseError as e: except aiohttp.ClientResponseError as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f"<r><bg #f8bbd0>Error occurred while requesting {setup_.url}. " f"<r><bg #f8bbd0>Error occurred while requesting {escape_tag(setup_.url)}. "
"Try to reconnect...</bg #f8bbd0></r>") "Try to reconnect...</bg #f8bbd0></r>")
await asyncio.sleep(setup_.poll_interval) await asyncio.sleep(setup_.poll_interval)
@ -313,7 +316,7 @@ class Driver(ForwardDriver):
url = URL(setup_.url) url = URL(setup_.url)
if not url.is_absolute() or not url.host: if not url.is_absolute() or not url.host:
logger.opt(colors=True).error( logger.opt(colors=True).error(
f"<r><bg #f8bbd0>Error parsing url {url}</bg #f8bbd0></r>" f"<r><bg #f8bbd0>Error parsing url {escape_tag(str(url))}</bg #f8bbd0></r>"
) )
await asyncio.sleep(setup_.reconnect_interval) await asyncio.sleep(setup_.reconnect_interval)
continue continue
@ -329,8 +332,9 @@ class Driver(ForwardDriver):
headers=headers, headers=headers,
timeout=30.) as ws: timeout=30.) as ws:
logger.opt(colors=True).info( logger.opt(colors=True).info(
f"WebSocket Connection to <y>{setup_.adapter.upper()} " f"WebSocket Connection to <y>{escape_tag(setup_.adapter.upper())} "
f"Bot {setup_.self_id}</y> succeeded!") f"Bot {escape_tag(setup_.self_id)}</y> succeeded!"
)
request = WebSocket( request = WebSocket(
"1.1", url.scheme, url.path, "1.1", url.scheme, url.path,
url.raw_query_string.encode("latin-1"), headers, url.raw_query_string.encode("latin-1"), headers,
@ -360,7 +364,7 @@ class Driver(ForwardDriver):
except (aiohttp.ClientResponseError, except (aiohttp.ClientResponseError,
aiohttp.ClientConnectionError) as e: aiohttp.ClientConnectionError) as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f"<r><bg #f8bbd0>Error while connecting to {url}. " f"<r><bg #f8bbd0>Error while connecting to {escape_tag(str(url))}. "
"Try to reconnect...</bg #f8bbd0></r>") "Try to reconnect...</bg #f8bbd0></r>")
finally: finally:
if bot: if bot:

View File

@ -27,6 +27,7 @@ from starlette.websockets import (WebSocketState, WebSocketDisconnect, WebSocket
from nonebot.log import logger from nonebot.log import logger
from nonebot.adapters import Bot from nonebot.adapters import Bot
from nonebot.utils import escape_tag
from nonebot.typing import overrides from nonebot.typing import overrides
from nonebot.config import Env, Config as NoneBotConfig from nonebot.config import Env, Config as NoneBotConfig
from nonebot.drivers import (ReverseDriver, ForwardDriver, HTTPPollingSetup, from nonebot.drivers import (ReverseDriver, ForwardDriver, HTTPPollingSetup,
@ -283,25 +284,26 @@ class Driver(ReverseDriver, ForwardDriver):
# Create Bot Object # Create Bot Object
BotClass = self._adapters[adapter] BotClass = self._adapters[adapter]
x_self_id, _ = await BotClass.check_permission(self, ws) self_id, _ = await BotClass.check_permission(self, ws)
if not x_self_id: if not self_id:
await ws.close(code=status.WS_1008_POLICY_VIOLATION) await ws.close(code=status.WS_1008_POLICY_VIOLATION)
return return
if x_self_id in self._clients: if self_id in self._clients:
logger.opt(colors=True).warning( logger.opt(colors=True).warning(
"There's already a reverse websocket connection, " "There's already a websocket connection, "
f"<y>{adapter.upper()} Bot {x_self_id}</y> ignored.") f"<y>{escape_tag(adapter.upper())} Bot {escape_tag(self_id)}</y> ignored."
)
await ws.close(code=status.WS_1008_POLICY_VIOLATION) await ws.close(code=status.WS_1008_POLICY_VIOLATION)
return return
bot = BotClass(x_self_id, ws) bot = BotClass(self_id, ws)
await ws.accept() await ws.accept()
logger.opt(colors=True).info( logger.opt(colors=True).info(
f"WebSocket Connection from <y>{adapter.upper()} " f"WebSocket Connection from <y>{escape_tag(adapter.upper())} "
f"Bot {x_self_id}</y> Accepted!") f"Bot {escape_tag(self_id)}</y> Accepted!")
self._bot_connect(bot) self._bot_connect(bot)
@ -328,7 +330,8 @@ class Driver(ReverseDriver, ForwardDriver):
url = httpx.URL(setup.url) url = httpx.URL(setup.url)
if not url.netloc: if not url.netloc:
logger.opt(colors=True).error( logger.opt(colors=True).error(
f"<r><bg #f8bbd0>Error parsing url {url}</bg #f8bbd0></r>") f"<r><bg #f8bbd0>Error parsing url {escape_tag(str(url))}</bg #f8bbd0></r>"
)
return return
return HTTPRequest( return HTTPRequest(
setup.http_version, url.scheme, url.path, url.query, { setup.http_version, url.scheme, url.path, url.query, {
@ -340,8 +343,8 @@ class Driver(ReverseDriver, ForwardDriver):
setup_: Optional[HTTPPollingSetup] = None setup_: Optional[HTTPPollingSetup] = None
logger.opt(colors=True).info( logger.opt(colors=True).info(
f"Start http polling for <y>{setup.adapter.upper()} " f"Start http polling for <y>{escape_tag(setup.adapter.upper())} "
f"Bot {setup.self_id}</y>") f"Bot {escape_tag(setup.self_id)}</y>")
try: try:
async with httpx.AsyncClient(http2=True) as session: async with httpx.AsyncClient(http2=True) as session:
@ -383,7 +386,7 @@ class Driver(ReverseDriver, ForwardDriver):
asyncio.create_task(bot.handle_message(data)) asyncio.create_task(bot.handle_message(data))
except httpx.HTTPError as e: except httpx.HTTPError as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f"<r><bg #f8bbd0>Error occurred while requesting {setup_.url}. " f"<r><bg #f8bbd0>Error occurred while requesting {escape_tag(setup_.url)}. "
"Try to reconnect...</bg #f8bbd0></r>") "Try to reconnect...</bg #f8bbd0></r>")
await asyncio.sleep(setup_.poll_interval) await asyncio.sleep(setup_.poll_interval)
@ -411,7 +414,7 @@ class Driver(ReverseDriver, ForwardDriver):
url = httpx.URL(setup_.url) url = httpx.URL(setup_.url)
if not url.netloc: if not url.netloc:
logger.opt(colors=True).error( logger.opt(colors=True).error(
f"<r><bg #f8bbd0>Error parsing url {url}</bg #f8bbd0></r>" f"<r><bg #f8bbd0>Error parsing url {escape_tag(str(url))}</bg #f8bbd0></r>"
) )
return return
@ -423,8 +426,8 @@ class Driver(ReverseDriver, ForwardDriver):
connection = Connect(setup_.url) connection = Connect(setup_.url)
async with connection as ws: async with connection as ws:
logger.opt(colors=True).info( logger.opt(colors=True).info(
f"WebSocket Connection to <y>{setup_.adapter.upper()} " f"WebSocket Connection to <y>{escape_tag(setup_.adapter.upper())} "
f"Bot {setup_.self_id}</y> succeeded!") f"Bot {escape_tag(setup_.self_id)}</y> succeeded!")
request = WebSocket("1.1", url.scheme, url.path, request = WebSocket("1.1", url.scheme, url.path,
url.query, headers, ws) url.query, headers, ws)

View File

@ -16,6 +16,7 @@ import uvicorn
from pydantic import BaseSettings from pydantic import BaseSettings
from nonebot.log import logger from nonebot.log import logger
from nonebot.utils import escape_tag
from nonebot.typing import overrides from nonebot.typing import overrides
from nonebot.config import Env, Config as NoneBotConfig from nonebot.config import Env, Config as NoneBotConfig
from nonebot.drivers import ReverseDriver, HTTPRequest, WebSocket as BaseWebSocket from nonebot.drivers import ReverseDriver, HTTPRequest, WebSocket as BaseWebSocket
@ -198,15 +199,16 @@ class Driver(ReverseDriver):
if self_id in self._clients: if self_id in self._clients:
logger.opt(colors=True).warning( logger.opt(colors=True).warning(
"There's already a reverse websocket connection, " "There's already a websocket connection, "
f"<y>{adapter.upper()} Bot {self_id}</y> ignored.") f"<y>{escape_tag(adapter.upper())} Bot {escape_tag(self_id)}</y> ignored."
)
raise exceptions.Forbidden(description='Client already exists.') raise exceptions.Forbidden(description='Client already exists.')
bot = BotClass(self_id, ws) bot = BotClass(self_id, ws)
await ws.accept() await ws.accept()
logger.opt(colors=True).info( logger.opt(colors=True).info(
f"WebSocket Connection from <y>{adapter.upper()} " f"WebSocket Connection from <y>{escape_tag(adapter.upper())} "
f"Bot {self_id}</y> Accepted!") f"Bot {escape_tag(self_id)}</y> Accepted!")
self._bot_connect(bot) self._bot_connect(bot)
try: try:

View File

@ -11,6 +11,7 @@ from typing import Set, Type, Optional, TYPE_CHECKING
from nonebot.log import logger from nonebot.log import logger
from nonebot.rule import TrieRule from nonebot.rule import TrieRule
from nonebot.utils import escape_tag
from nonebot.matcher import matchers, Matcher from nonebot.matcher import matchers, Matcher
from nonebot.exception import IgnoredException, StopPropagation, NoLogException from nonebot.exception import IgnoredException, StopPropagation, NoLogException
from nonebot.typing import T_State, T_EventPreProcessor, T_RunPreProcessor, T_EventPostProcessor, T_RunPostProcessor from nonebot.typing import T_State, T_EventPreProcessor, T_RunPreProcessor, T_EventPostProcessor, T_RunPostProcessor
@ -193,7 +194,7 @@ async def handle_event(bot: "Bot", event: "Event") -> Optional[Exception]:
asyncio.create_task(handle_event(bot, event)) asyncio.create_task(handle_event(bot, event))
""" """
show_log = True show_log = True
log_msg = f"<m>{bot.type.upper()} {bot.self_id}</m> | " log_msg = f"<m>{escape_tag(bot.type.upper())} {escape_tag(bot.self_id)}</m> | "
try: try:
log_msg += event.get_log_string() log_msg += event.get_log_string()
except NoLogException: except NoLogException:
@ -210,7 +211,7 @@ async def handle_event(bot: "Bot", event: "Event") -> Optional[Exception]:
await asyncio.gather(*coros) await asyncio.gather(*coros)
except IgnoredException as e: except IgnoredException as e:
logger.opt(colors=True).info( logger.opt(colors=True).info(
f"Event {event.get_event_name()} is <b>ignored</b>") f"Event {escape_tag(event.get_event_name())} is <b>ignored</b>")
return e return e
except Exception as e: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(

View File

@ -16,6 +16,7 @@ import tomlkit
from nonebot.log import logger from nonebot.log import logger
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.handler import Handler from nonebot.handler import Handler
from nonebot.utils import escape_tag
from nonebot.permission import Permission from nonebot.permission import Permission
from nonebot.typing import T_State, T_StateFactory, T_Handler, T_RuleChecker from nonebot.typing import T_State, T_StateFactory, T_Handler, T_RuleChecker
from nonebot.rule import Rule, startswith, endswith, keyword, command, shell_command, ArgumentParser, regex from nonebot.rule import Rule, startswith, endswith, keyword, command, shell_command, ArgumentParser, regex
@ -945,12 +946,13 @@ def _load_plugin(manager: PluginManager, plugin_name: str) -> Optional[Plugin]:
plugin = Plugin(plugin_name, module) plugin = Plugin(plugin_name, module)
plugins[plugin_name] = plugin plugins[plugin_name] = plugin
logger.opt( logger.opt(colors=True).success(
colors=True).success(f'Succeeded to import "<y>{plugin_name}</y>"') f'Succeeded to import "<y>{escape_tag(plugin_name)}</y>"')
return plugin return plugin
except Exception as e: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f'<r><bg #f8bbd0>Failed to import "{plugin_name}"</bg #f8bbd0></r>') f'<r><bg #f8bbd0>Failed to import "{escape_tag(plugin_name)}"</bg #f8bbd0></r>'
)
return None return None

View File

@ -80,6 +80,6 @@ def logger_wrapper(logger_name: str):
def log(level: str, message: str, exception: Optional[Exception] = None): def log(level: str, message: str, exception: Optional[Exception] = None):
return logger.opt(colors=True, exception=exception).log( return logger.opt(colors=True, exception=exception).log(
level, f"<m>{logger_name}</m> | " + message) level, f"<m>{escape_tag(logger_name)}</m> | " + message)
return log return log

View File

@ -256,7 +256,7 @@ class Bot(BaseBot):
WebSocketSetup("cqhttp", self_id, url, headers=headers)) WebSocketSetup("cqhttp", self_id, url, headers=headers))
except Exception as e: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f"<r><bg #f8bbd0>Bad url {url} for bot {self_id} " f"<r><bg #f8bbd0>Bad url {escape_tag(url)} for bot {escape_tag(self_id)} "
"in cqhttp forward websocket</bg #f8bbd0></r>") "in cqhttp forward websocket</bg #f8bbd0></r>")
@classmethod @classmethod
@ -309,7 +309,7 @@ class Bot(BaseBot):
调用 `_check_reply <#async-check-reply-bot-event>`_, `_check_at_me <#check-at-me-bot-event>`_, `_check_nickname <#check-nickname-bot-event>`_ 处理事件并转换为 `Event <#class-event>`_ 调用 `_check_reply <#async-check-reply-bot-event>`_, `_check_at_me <#check-at-me-bot-event>`_, `_check_nickname <#check-nickname-bot-event>`_ 处理事件并转换为 `Event <#class-event>`_
""" """
data = json.loads(message) data: dict = json.loads(message)
if not data: if not data:
return return
@ -342,7 +342,7 @@ class Bot(BaseBot):
await handle_event(self, event) await handle_event(self, event)
except Exception as e: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f"<r><bg #f8bbd0>Failed to handle event. Raw: {escape_tag(data)}</bg #f8bbd0></r>" f"<r><bg #f8bbd0>Failed to handle event. Raw: {escape_tag(str(data))}</bg #f8bbd0></r>"
) )
@overrides(BaseBot) @overrides(BaseBot)

View File

@ -8,6 +8,7 @@ from typing import Any, Tuple, Union, Optional, TYPE_CHECKING
import httpx import httpx
from nonebot.log import logger from nonebot.log import logger
from nonebot.utils import escape_tag
from nonebot.typing import overrides from nonebot.typing import overrides
from nonebot.message import handle_event from nonebot.message import handle_event
from nonebot.adapters import Bot as BaseBot from nonebot.adapters import Bot as BaseBot
@ -82,7 +83,7 @@ class Bot(BaseBot):
@overrides(BaseBot) @overrides(BaseBot)
async def handle_message(self, message: bytes): async def handle_message(self, message: bytes):
data = json.loads(message) data: dict = json.loads(message)
if not data: if not data:
return return
@ -104,7 +105,7 @@ class Bot(BaseBot):
await handle_event(self, event) await handle_event(self, event)
except Exception as e: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f"<r><bg #f8bbd0>Failed to handle event. Raw: {data}</bg #f8bbd0></r>" f"<r><bg #f8bbd0>Failed to handle event. Raw: {escape_tag(str(data))}</bg #f8bbd0></r>"
) )
return return

View File

@ -6,15 +6,16 @@ import httpx
from aiocache import Cache, cached from aiocache import Cache, cached
from aiocache.serializers import PickleSerializer from aiocache.serializers import PickleSerializer
from nonebot.log import logger
from nonebot.utils import escape_tag
from nonebot.typing import overrides
from nonebot.message import handle_event
from nonebot.adapters import Bot as BaseBot from nonebot.adapters import Bot as BaseBot
from nonebot.drivers import Driver, HTTPRequest, HTTPResponse from nonebot.drivers import Driver, HTTPRequest, HTTPResponse
from nonebot.log import logger
from nonebot.message import handle_event
from nonebot.typing import overrides
from .config import Config as FeishuConfig from .config import Config as FeishuConfig
from .event import (Event, GroupMessageEvent, MessageEvent, from .event import (Event, GroupMessageEvent, MessageEvent, PrivateMessageEvent,
PrivateMessageEvent, get_event_model) get_event_model)
from .exception import ActionFailed, ApiNotAvailable, NetworkError from .exception import ActionFailed, ApiNotAvailable, NetworkError
from .message import Message, MessageSegment, MessageSerializer from .message import Message, MessageSegment, MessageSerializer
from .utils import AESCipher, log from .utils import AESCipher, log
@ -202,7 +203,7 @@ class Bot(BaseBot):
处理事件并转换为 `Event <#class-event>`_ 处理事件并转换为 `Event <#class-event>`_
""" """
data = json.loads(message) data: dict = json.loads(message)
if data.get("type") == "url_verification": if data.get("type") == "url_verification":
return return
@ -229,7 +230,7 @@ class Bot(BaseBot):
await handle_event(self, event) await handle_event(self, event)
except Exception as e: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
f"<r><bg #f8bbd0>Failed to handle event. Raw: {message}</bg #f8bbd0></r>" f"<r><bg #f8bbd0>Failed to handle event. Raw: {escape_tag(str(data))}</bg #f8bbd0></r>"
) )
def _construct_url(self, path: str) -> str: def _construct_url(self, path: str) -> str: