🤖 自动格式化代码 [skip ci]
This commit is contained in:
@@ -53,13 +53,13 @@ class ActionPlanner:
|
||||
goal = goal_reason[0]
|
||||
reasoning = goal_reason[1] if len(goal_reason) > 1 else "没有明确原因"
|
||||
elif isinstance(goal_reason, dict):
|
||||
goal = goal_reason.get('goal')
|
||||
reasoning = goal_reason.get('reasoning', "没有明确原因")
|
||||
goal = goal_reason.get("goal")
|
||||
reasoning = goal_reason.get("reasoning", "没有明确原因")
|
||||
else:
|
||||
# 如果是其他类型,尝试转为字符串
|
||||
goal = str(goal_reason)
|
||||
reasoning = "没有明确原因"
|
||||
|
||||
|
||||
goal_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||
goals_str += goal_str
|
||||
else:
|
||||
@@ -68,7 +68,11 @@ class ActionPlanner:
|
||||
goals_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||
|
||||
# 获取聊天历史记录
|
||||
chat_history_list = observation_info.chat_history[-20:] if len(observation_info.chat_history) >= 20 else observation_info.chat_history
|
||||
chat_history_list = (
|
||||
observation_info.chat_history[-20:]
|
||||
if len(observation_info.chat_history) >= 20
|
||||
else observation_info.chat_history
|
||||
)
|
||||
chat_history_text = ""
|
||||
for msg in chat_history_list:
|
||||
chat_history_text += f"{msg.get('detailed_plain_text', '')}\n"
|
||||
@@ -85,15 +89,21 @@ class ActionPlanner:
|
||||
personality_text = f"你的名字是{self.name},{self.personality_info}"
|
||||
|
||||
# 构建action历史文本
|
||||
action_history_list = conversation_info.done_action[-10:] if len(conversation_info.done_action) >= 10 else conversation_info.done_action
|
||||
action_history_list = (
|
||||
conversation_info.done_action[-10:]
|
||||
if len(conversation_info.done_action) >= 10
|
||||
else conversation_info.done_action
|
||||
)
|
||||
action_history_text = "你之前做的事情是:"
|
||||
for action in action_history_list:
|
||||
if isinstance(action, dict):
|
||||
action_type = action.get('action')
|
||||
action_reason = action.get('reason')
|
||||
action_status = action.get('status')
|
||||
action_type = action.get("action")
|
||||
action_reason = action.get("reason")
|
||||
action_status = action.get("status")
|
||||
if action_status == "recall":
|
||||
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
action_history_text += (
|
||||
f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
)
|
||||
elif action_status == "done":
|
||||
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||
elif isinstance(action, tuple):
|
||||
@@ -102,7 +112,9 @@ class ActionPlanner:
|
||||
action_reason = action[1] if len(action) > 1 else "未知原因"
|
||||
action_status = action[2] if len(action) > 2 else "done"
|
||||
if action_status == "recall":
|
||||
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
action_history_text += (
|
||||
f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
)
|
||||
elif action_status == "done":
|
||||
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||
|
||||
@@ -147,7 +159,14 @@ end_conversation: 结束对话,长时间没回复或者当你觉得谈话暂
|
||||
reason = result["reason"]
|
||||
|
||||
# 验证action类型
|
||||
if action not in ["direct_reply", "fetch_knowledge", "wait", "listening", "rethink_goal", "end_conversation"]:
|
||||
if action not in [
|
||||
"direct_reply",
|
||||
"fetch_knowledge",
|
||||
"wait",
|
||||
"listening",
|
||||
"rethink_goal",
|
||||
"end_conversation",
|
||||
]:
|
||||
logger.warning(f"未知的行动类型: {action},默认使用listening")
|
||||
action = "listening"
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import time
|
||||
import asyncio
|
||||
import traceback
|
||||
from typing import Optional, Dict, Any, List
|
||||
from typing import Optional, Dict, Any, List
|
||||
from src.common.logger import get_module_logger
|
||||
from ..message.message_base import UserInfo
|
||||
from ..config.config import global_config
|
||||
from .chat_states import NotificationManager, create_new_message_notification, create_cold_chat_notification
|
||||
from .message_storage import MongoDBMessageStorage
|
||||
from .message_storage import MongoDBMessageStorage
|
||||
|
||||
logger = get_module_logger("chat_observer")
|
||||
|
||||
@@ -51,7 +51,6 @@ class ChatObserver:
|
||||
|
||||
self.waiting_start_time: float = time.time() # 等待开始时间,初始化为当前时间
|
||||
|
||||
|
||||
# 运行状态
|
||||
self._running: bool = False
|
||||
self._task: Optional[asyncio.Task] = None
|
||||
@@ -94,10 +93,11 @@ class ChatObserver:
|
||||
message: 消息数据
|
||||
"""
|
||||
try:
|
||||
|
||||
# 发送新消息通知
|
||||
# logger.info(f"发送新ccchandleer消息通知: {message}")
|
||||
notification = create_new_message_notification(sender="chat_observer", target="observation_info", message=message)
|
||||
notification = create_new_message_notification(
|
||||
sender="chat_observer", target="observation_info", message=message
|
||||
)
|
||||
# logger.info(f"发送新消ddddd息通知: {notification}")
|
||||
# print(self.notification_manager)
|
||||
await self.notification_manager.send_notification(notification)
|
||||
@@ -131,7 +131,6 @@ class ChatObserver:
|
||||
notification = create_cold_chat_notification(sender="chat_observer", target="pfc", is_cold=is_cold)
|
||||
await self.notification_manager.send_notification(notification)
|
||||
|
||||
|
||||
def new_message_after(self, time_point: float) -> bool:
|
||||
"""判断是否在指定时间点后有新消息
|
||||
|
||||
@@ -197,7 +196,7 @@ class ChatObserver:
|
||||
if new_messages:
|
||||
self.last_message_read = new_messages[-1]
|
||||
self.last_message_time = new_messages[-1]["time"]
|
||||
|
||||
|
||||
# print(f"获取数据库中找到的新消息: {new_messages}")
|
||||
|
||||
return new_messages
|
||||
@@ -215,7 +214,7 @@ class ChatObserver:
|
||||
|
||||
if new_messages:
|
||||
self.last_message_read = new_messages[-1]["message_id"]
|
||||
|
||||
|
||||
logger.debug(f"获取指定时间点111之前的消息: {new_messages}")
|
||||
|
||||
return new_messages
|
||||
@@ -239,7 +238,7 @@ class ChatObserver:
|
||||
try:
|
||||
# print("等待事件")
|
||||
await asyncio.wait_for(self._update_event.wait(), timeout=1)
|
||||
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
# print("超时")
|
||||
pass # 超时后也执行一次检查
|
||||
@@ -347,7 +346,6 @@ class ChatObserver:
|
||||
|
||||
return time_info
|
||||
|
||||
|
||||
def get_cached_messages(self, limit: int = 50) -> List[Dict[str, Any]]:
|
||||
"""获取缓存的消息历史
|
||||
|
||||
@@ -368,6 +366,6 @@ class ChatObserver:
|
||||
if not self.message_cache:
|
||||
return None
|
||||
return self.message_cache[0]
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return f"ChatObserver for {self.stream_id}"
|
||||
|
||||
@@ -140,7 +140,6 @@ class NotificationManager:
|
||||
self._active_states.add(notification.type)
|
||||
else:
|
||||
self._active_states.discard(notification.type)
|
||||
|
||||
|
||||
# 调用目标接收者的处理器
|
||||
target = notification.target
|
||||
@@ -181,7 +180,7 @@ class NotificationManager:
|
||||
history = history[-limit:]
|
||||
|
||||
return history
|
||||
|
||||
|
||||
def __str__(self):
|
||||
str = ""
|
||||
for target, handlers in self._handlers.items():
|
||||
@@ -295,5 +294,3 @@ class ChatStateManager:
|
||||
|
||||
current_time = datetime.now().timestamp()
|
||||
return (current_time - self.state_info.last_message_time) <= threshold
|
||||
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ class Conversation:
|
||||
self.observation_info.bind_to_chat_observer(self.chat_observer)
|
||||
# print(self.chat_observer.get_cached_messages(limit=)
|
||||
|
||||
|
||||
self.conversation_info = ConversationInfo()
|
||||
except Exception as e:
|
||||
logger.error(f"初始化对话实例:注册信息组件失败: {e}")
|
||||
@@ -96,7 +95,7 @@ class Conversation:
|
||||
|
||||
# 执行行动
|
||||
await self._handle_action(action, reason, self.observation_info, self.conversation_info)
|
||||
|
||||
|
||||
for goal in self.conversation_info.goal_list:
|
||||
# 检查goal是否为元组类型,如果是元组则使用索引访问,如果是字典则使用get方法
|
||||
if isinstance(goal, tuple):
|
||||
@@ -151,7 +150,7 @@ class Conversation:
|
||||
|
||||
if action == "direct_reply":
|
||||
self.waiter.wait_accumulated_time = 0
|
||||
|
||||
|
||||
self.state = ConversationState.GENERATING
|
||||
self.generated_reply = await self.reply_generator.generate(observation_info, conversation_info)
|
||||
print(f"生成回复: {self.generated_reply}")
|
||||
@@ -174,7 +173,6 @@ class Conversation:
|
||||
|
||||
await self._send_reply()
|
||||
|
||||
|
||||
conversation_info.done_action[-1].update(
|
||||
{
|
||||
"status": "done",
|
||||
@@ -184,7 +182,7 @@ class Conversation:
|
||||
|
||||
elif action == "fetch_knowledge":
|
||||
self.waiter.wait_accumulated_time = 0
|
||||
|
||||
|
||||
self.state = ConversationState.FETCHING
|
||||
knowledge = "TODO:知识"
|
||||
topic = "TODO:关键词"
|
||||
@@ -199,7 +197,7 @@ class Conversation:
|
||||
|
||||
elif action == "rethink_goal":
|
||||
self.waiter.wait_accumulated_time = 0
|
||||
|
||||
|
||||
self.state = ConversationState.RETHINKING
|
||||
await self.goal_analyzer.analyze_goal(conversation_info, observation_info)
|
||||
|
||||
@@ -208,7 +206,6 @@ class Conversation:
|
||||
logger.info("倾听对方发言...")
|
||||
await self.waiter.wait_listening(conversation_info)
|
||||
|
||||
|
||||
elif action == "end_conversation":
|
||||
self.should_continue = False
|
||||
logger.info("决定结束对话...")
|
||||
@@ -239,9 +236,7 @@ class Conversation:
|
||||
return
|
||||
|
||||
try:
|
||||
await self.direct_sender.send_message(
|
||||
chat_stream=self.chat_stream, content=self.generated_reply
|
||||
)
|
||||
await self.direct_sender.send_message(chat_stream=self.chat_stream, content=self.generated_reply)
|
||||
self.chat_observer.trigger_update() # 触发立即更新
|
||||
if not await self.chat_observer.wait_for_update():
|
||||
logger.warning("等待消息更新超时")
|
||||
|
||||
@@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
|
||||
from typing import List, Dict, Any
|
||||
from src.common.database import db
|
||||
|
||||
|
||||
class MessageStorage(ABC):
|
||||
"""消息存储接口"""
|
||||
|
||||
|
||||
@@ -26,24 +26,24 @@ class ObservationInfoHandler(NotificationHandler):
|
||||
# 获取通知类型和数据
|
||||
notification_type = notification.type
|
||||
data = notification.data
|
||||
|
||||
|
||||
if notification_type == NotificationType.NEW_MESSAGE:
|
||||
# 处理新消息通知
|
||||
logger.debug(f"收到新消息通知data: {data}")
|
||||
message_id = data.get("message_id")
|
||||
processed_plain_text = data.get("processed_plain_text")
|
||||
detailed_plain_text = data.get("detailed_plain_text")
|
||||
detailed_plain_text = data.get("detailed_plain_text")
|
||||
user_info = data.get("user_info")
|
||||
time_value = data.get("time")
|
||||
|
||||
|
||||
message = {
|
||||
"message_id": message_id,
|
||||
"processed_plain_text": processed_plain_text,
|
||||
"detailed_plain_text": detailed_plain_text,
|
||||
"user_info": user_info,
|
||||
"time": time_value
|
||||
"time": time_value,
|
||||
}
|
||||
|
||||
|
||||
self.observation_info.update_from_message(message)
|
||||
|
||||
elif notification_type == NotificationType.COLD_CHAT:
|
||||
@@ -161,7 +161,7 @@ class ObservationInfo:
|
||||
# logger.debug(f"更新信息from_message: {message}")
|
||||
self.last_message_time = message["time"]
|
||||
self.last_message_id = message["message_id"]
|
||||
|
||||
|
||||
self.last_message_content = message.get("processed_plain_text", "")
|
||||
|
||||
user_info = UserInfo.from_dict(message.get("user_info", {}))
|
||||
@@ -233,4 +233,3 @@ class ObservationInfo:
|
||||
self.unprocessed_messages.clear()
|
||||
self.chat_history_count = len(self.chat_history)
|
||||
self.new_messages_count = 0
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Programmable Friendly Conversationalist
|
||||
# Prefrontal cortex
|
||||
import datetime
|
||||
|
||||
# import asyncio
|
||||
from typing import List, Optional, Tuple, TYPE_CHECKING
|
||||
from src.common.logger import get_module_logger
|
||||
@@ -63,13 +64,13 @@ class GoalAnalyzer:
|
||||
goal = goal_reason[0]
|
||||
reasoning = goal_reason[1] if len(goal_reason) > 1 else "没有明确原因"
|
||||
elif isinstance(goal_reason, dict):
|
||||
goal = goal_reason.get('goal')
|
||||
reasoning = goal_reason.get('reasoning', "没有明确原因")
|
||||
goal = goal_reason.get("goal")
|
||||
reasoning = goal_reason.get("reasoning", "没有明确原因")
|
||||
else:
|
||||
# 如果是其他类型,尝试转为字符串
|
||||
goal = str(goal_reason)
|
||||
reasoning = "没有明确原因"
|
||||
|
||||
|
||||
goal_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||
goals_str += goal_str
|
||||
else:
|
||||
@@ -140,14 +141,12 @@ class GoalAnalyzer:
|
||||
except Exception as e:
|
||||
logger.error(f"分析对话目标时出错: {str(e)}")
|
||||
content = ""
|
||||
|
||||
|
||||
# 使用改进后的get_items_from_json函数处理JSON数组
|
||||
success, result = get_items_from_json(
|
||||
content, "goal", "reasoning",
|
||||
required_types={"goal": str, "reasoning": str},
|
||||
allow_array=True
|
||||
content, "goal", "reasoning", required_types={"goal": str, "reasoning": str}, allow_array=True
|
||||
)
|
||||
|
||||
|
||||
if success:
|
||||
# 判断结果是单个字典还是字典列表
|
||||
if isinstance(result, list):
|
||||
@@ -157,7 +156,7 @@ class GoalAnalyzer:
|
||||
goal = item.get("goal", "")
|
||||
reasoning = item.get("reasoning", "")
|
||||
conversation_info.goal_list.append((goal, reasoning))
|
||||
|
||||
|
||||
# 返回第一个目标作为当前主要目标(如果有)
|
||||
if result:
|
||||
first_goal = result[0]
|
||||
@@ -168,7 +167,7 @@ class GoalAnalyzer:
|
||||
reasoning = result.get("reasoning", "")
|
||||
conversation_info.goal_list.append((goal, reasoning))
|
||||
return (goal, "", reasoning)
|
||||
|
||||
|
||||
# 如果解析失败,返回默认值
|
||||
return ("", "", "")
|
||||
|
||||
@@ -293,7 +292,6 @@ class GoalAnalyzer:
|
||||
return False, False, f"分析出错: {str(e)}"
|
||||
|
||||
|
||||
|
||||
class DirectMessageSender:
|
||||
"""直接发送消息到平台的发送器"""
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ def get_items_from_json(
|
||||
"""
|
||||
content = content.strip()
|
||||
result = {}
|
||||
|
||||
|
||||
# 设置默认值
|
||||
if default_values:
|
||||
result.update(default_values)
|
||||
@@ -41,7 +41,7 @@ def get_items_from_json(
|
||||
if array_match:
|
||||
array_content = array_match.group()
|
||||
json_array = json.loads(array_content)
|
||||
|
||||
|
||||
# 确认是数组类型
|
||||
if isinstance(json_array, list):
|
||||
# 验证数组中的每个项目是否包含所有必需字段
|
||||
@@ -49,7 +49,7 @@ def get_items_from_json(
|
||||
for item in json_array:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
|
||||
|
||||
# 检查是否有所有必需字段
|
||||
if all(field in item for field in items):
|
||||
# 验证字段类型
|
||||
@@ -59,22 +59,22 @@ def get_items_from_json(
|
||||
if field in item and not isinstance(item[field], expected_type):
|
||||
type_valid = False
|
||||
break
|
||||
|
||||
|
||||
if not type_valid:
|
||||
continue
|
||||
|
||||
|
||||
# 验证字符串字段不为空
|
||||
string_valid = True
|
||||
for field in items:
|
||||
if isinstance(item[field], str) and not item[field].strip():
|
||||
string_valid = False
|
||||
break
|
||||
|
||||
|
||||
if not string_valid:
|
||||
continue
|
||||
|
||||
|
||||
valid_items.append(item)
|
||||
|
||||
|
||||
if valid_items:
|
||||
return True, valid_items
|
||||
except json.JSONDecodeError:
|
||||
|
||||
@@ -49,22 +49,26 @@ class ReplyGenerator:
|
||||
goal = goal_reason[0]
|
||||
reasoning = goal_reason[1] if len(goal_reason) > 1 else "没有明确原因"
|
||||
elif isinstance(goal_reason, dict):
|
||||
goal = goal_reason.get('goal')
|
||||
reasoning = goal_reason.get('reasoning', "没有明确原因")
|
||||
goal = goal_reason.get("goal")
|
||||
reasoning = goal_reason.get("reasoning", "没有明确原因")
|
||||
else:
|
||||
# 如果是其他类型,尝试转为字符串
|
||||
goal = str(goal_reason)
|
||||
reasoning = "没有明确原因"
|
||||
|
||||
|
||||
goal_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||
goals_str += goal_str
|
||||
else:
|
||||
goal = "目前没有明确对话目标"
|
||||
reasoning = "目前没有明确对话目标,最好思考一个对话目标"
|
||||
goals_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||
|
||||
|
||||
# 获取聊天历史记录
|
||||
chat_history_list = observation_info.chat_history[-20:] if len(observation_info.chat_history) >= 20 else observation_info.chat_history
|
||||
chat_history_list = (
|
||||
observation_info.chat_history[-20:]
|
||||
if len(observation_info.chat_history) >= 20
|
||||
else observation_info.chat_history
|
||||
)
|
||||
chat_history_text = ""
|
||||
for msg in chat_history_list:
|
||||
chat_history_text += f"{msg.get('detailed_plain_text', '')}\n"
|
||||
@@ -81,15 +85,21 @@ class ReplyGenerator:
|
||||
personality_text = f"你的名字是{self.name},{self.personality_info}"
|
||||
|
||||
# 构建action历史文本
|
||||
action_history_list = conversation_info.done_action[-10:] if len(conversation_info.done_action) >= 10 else conversation_info.done_action
|
||||
action_history_list = (
|
||||
conversation_info.done_action[-10:]
|
||||
if len(conversation_info.done_action) >= 10
|
||||
else conversation_info.done_action
|
||||
)
|
||||
action_history_text = "你之前做的事情是:"
|
||||
for action in action_history_list:
|
||||
if isinstance(action, dict):
|
||||
action_type = action.get('action')
|
||||
action_reason = action.get('reason')
|
||||
action_status = action.get('status')
|
||||
action_type = action.get("action")
|
||||
action_reason = action.get("reason")
|
||||
action_status = action.get("status")
|
||||
if action_status == "recall":
|
||||
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
action_history_text += (
|
||||
f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
)
|
||||
elif action_status == "done":
|
||||
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||
elif isinstance(action, tuple):
|
||||
@@ -98,7 +108,9 @@ class ReplyGenerator:
|
||||
action_reason = action[1] if len(action) > 1 else "未知原因"
|
||||
action_status = action[2] if len(action) > 2 else "done"
|
||||
if action_status == "recall":
|
||||
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
action_history_text += (
|
||||
f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||
)
|
||||
elif action_status == "done":
|
||||
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Waiter:
|
||||
self.chat_observer = ChatObserver.get_instance(stream_id)
|
||||
self.personality_info = Individuality.get_instance().get_prompt(type="personality", x_person=2, level=2)
|
||||
self.name = global_config.BOT_NICKNAME
|
||||
|
||||
|
||||
self.wait_accumulated_time = 0
|
||||
|
||||
async def wait(self, conversation_info: ConversationInfo) -> bool:
|
||||
@@ -38,20 +38,20 @@ class Waiter:
|
||||
# 检查是否超时
|
||||
if time.time() - wait_start_time > 300:
|
||||
self.wait_accumulated_time += 300
|
||||
|
||||
|
||||
logger.info("等待超过300秒,结束对话")
|
||||
wait_goal = {
|
||||
"goal": f"你等待了{self.wait_accumulated_time/60}分钟,思考接下来要做什么",
|
||||
"reason": "对方很久没有回复你的消息了"
|
||||
"goal": f"你等待了{self.wait_accumulated_time / 60}分钟,思考接下来要做什么",
|
||||
"reason": "对方很久没有回复你的消息了",
|
||||
}
|
||||
conversation_info.goal_list.append(wait_goal)
|
||||
print(f"添加目标: {wait_goal}")
|
||||
|
||||
|
||||
return True
|
||||
|
||||
await asyncio.sleep(1)
|
||||
logger.info("等待中...")
|
||||
|
||||
|
||||
async def wait_listening(self, conversation_info: ConversationInfo) -> bool:
|
||||
"""等待倾听
|
||||
|
||||
@@ -73,14 +73,13 @@ class Waiter:
|
||||
self.wait_accumulated_time += 300
|
||||
logger.info("等待超过300秒,结束对话")
|
||||
wait_goal = {
|
||||
"goal": f"你等待了{self.wait_accumulated_time/60}分钟,思考接下来要做什么",
|
||||
"reason": "对方话说一半消失了,很久没有回复"
|
||||
"goal": f"你等待了{self.wait_accumulated_time / 60}分钟,思考接下来要做什么",
|
||||
"reason": "对方话说一半消失了,很久没有回复",
|
||||
}
|
||||
conversation_info.goal_list.append(wait_goal)
|
||||
print(f"添加目标: {wait_goal}")
|
||||
|
||||
|
||||
return True
|
||||
|
||||
await asyncio.sleep(1)
|
||||
logger.info("等待中...")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user