From 687ef176ebb381248bca50f6ee21aa8729779cba Mon Sep 17 00:00:00 2001 From: Rpeng <1941447882@qq.com> Date: Tue, 1 Apr 2025 01:35:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A3=9E=E4=B9=A6=E6=9C=BA=E5=99=A8?= =?UTF-8?q?=E4=BA=BA=E9=80=9A=E7=9F=A5Cookie=E8=BF=87=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 8 +++- main.py | 55 +++++++++++++++++++++ requirements.txt | Bin 100 -> 1076 bytes utils/notifier.py | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 utils/notifier.py diff --git a/.env.example b/.env.example index 4c219609..38f94e72 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,8 @@ OPENAI_API_KEY=your_api_key_here -COOKIES_STR=your_cookies_here \ No newline at end of file +COOKIES_STR=your_cookies_here +# 飞书通知配置 +ENABLE_FEISHU_NOTIFY=true +FEISHU_APP_ID=xxx +FEISHU_APP_SECRET=xxx +FEISHU_RECEIVE_ID=xxx +FEISHU_RECEIVE_ID_TYPE=open_id \ No newline at end of file diff --git a/main.py b/main.py index e5a735de..2b2a2038 100644 --- a/main.py +++ b/main.py @@ -13,6 +13,7 @@ from XianyuAgent import XianyuReplyBot from context_manager import ChatContextManager +from utils.notifier import NotificationManager, FeishuNotifier class XianyuLive: def __init__(self, cookies_str): @@ -32,6 +33,46 @@ def __init__(self, cookies_str): self.heartbeat_task = None self.ws = None + # 添加通知管理器 + self.notification_manager = self._init_notification_manager() + + # 添加Cookie过期检测 + self.cookie_check_interval = 3600 # 每小时检查一次Cookie + self.last_cookie_check_time = time.time() + + def _init_notification_manager(self): + """初始化通知管理器""" + manager = NotificationManager() + + # 飞书通知 + if os.getenv("ENABLE_FEISHU_NOTIFY", "false").lower() == "true": + feishu_notifier = FeishuNotifier( + app_id=os.getenv("FEISHU_APP_ID", ""), + app_secret=os.getenv("FEISHU_APP_SECRET", ""), + receive_id_type=os.getenv("FEISHU_RECEIVE_ID_TYPE", "chat_id"), + receive_id=os.getenv("FEISHU_RECEIVE_ID", "") + ) + manager.add_notifier(feishu_notifier) + logger.info("已启用飞书通知") + + return manager + + async def check_cookie_valid(self): + """检查Cookie是否有效""" + try: + # 尝试获取token,如果失败则说明Cookie已过期 + token_response = self.xianyu.get_token(self.cookies, self.device_id) + if token_response.get('ret') and token_response['ret'][0] != "SUCCESS::调用成功": + logger.error(f"Cookie已过期: {token_response}") + self.notification_manager.notify_cookie_expired() + return False + return True + except Exception as e: + logger.error(f"检查Cookie时出错: {e}") + self.notification_manager.notify_error("Cookie检查错误", str(e)) + return False + + async def send_msg(self, ws, cid, toid, text): text = { "contentType": 1, @@ -340,8 +381,20 @@ async def handle_heartbeat_response(self, message_data): return False async def main(self): + # 系统启动通知 + self.notification_manager.notify_system_start() + while True: try: + # 检查Cookie是否有效 + current_time = time.time() + if current_time - self.last_cookie_check_time >= self.cookie_check_interval: + self.last_cookie_check_time = current_time + if not await self.check_cookie_valid(): + logger.warning("Cookie无效,等待30分钟后重试...") + await asyncio.sleep(1800) # 等待30分钟后重试 + continue + headers = { "Cookie": self.cookies_str, "Host": "wss-goofish.dingtalk.com", @@ -399,6 +452,7 @@ async def main(self): except websockets.exceptions.ConnectionClosed: logger.warning("WebSocket连接已关闭") + self.notification_manager.notify_error("连接错误", "WebSocket连接已关闭", "系统将在5秒后尝试重连") if self.heartbeat_task: self.heartbeat_task.cancel() try: @@ -409,6 +463,7 @@ async def main(self): except Exception as e: logger.error(f"连接发生错误: {e}") + self.notification_manager.notify_error("连接错误", str(e), "系统将在5秒后尝试重连") if self.heartbeat_task: self.heartbeat_task.cancel() try: diff --git a/requirements.txt b/requirements.txt index d6eb70b5419ef17961f8b8990d6026479561a78b..238407c30a4d7baa695a055011713e40fb8896c3 100644 GIT binary patch literal 1076 zcmZvb%T9w}5QS%L;-l0EcwM-3HD4xU0?HEMH zDY#3cv=ur%`b*F=&)?e<|26PFTt(~xjxr=xN4$f#aBT7>#EI)xum=?Ttvlu1xm%%= zxhqwaxpLIBf-_Qa>FP_zh#Qs5aYAe+er{*3qG(OmT3jX1*|t{?MAXxMV(r{C-hoG| z?|55-6kA!N;@m4zz4!Kl!po$gSri`ad`il^W1o1pk3GI-QYBnXb401)JmDw#%$ZG^ ztFRSHEyx;{Fp8>YX##&S^Ishky6~ArSFcgLv<>-6yRsWslvZqm`X;@R-gac2xjS{M zwbuz7lM=Qk@=O=BmE(3ZBV*kE!)TK`uEuWRHT+6FmTtHls5Yh=b?!EOz=<|lyBymt zgmyCaal}tWKcyKvC~k_W=QRrVRHoYWq- literal 100 zcmWlRM-IRs3 bool: + """ + 发送通知 + + Args: + title: 通知标题 + content: 通知内容 + + Returns: + bool: 是否发送成功 + """ + pass + + +class FeishuNotifier(BaseNotifier): + """飞书通知器""" + + def __init__(self, app_id: str, app_secret: str, receive_id_type: str, receive_id: str): + """ + 初始化飞书通知器 + + Args: + app_id: 飞书应用的App ID + app_secret: 飞书应用的App Secret + receive_id_type: 接收者ID类型,可选值: "open_id", "user_id", "union_id", "email", "chat_id" + receive_id: 接收者ID + """ + try: + self.client = lark.Client.builder().app_id(app_id).app_secret(app_secret).build() + self.receive_id_type = receive_id_type + self.receive_id = receive_id + except ImportError: + logger.error("未安装lark_oapi库,请使用pip install lark_oapi安装") + raise + + def send(self, title: str, content: str) -> bool: + try: + # 构建消息请求 + req_content = json.dumps({"text": title + "\n" + content}) + req: CreateMessageRequest = CreateMessageRequest.builder() \ + .receive_id_type(self.receive_id_type) \ + .request_body(CreateMessageRequestBody.builder() + .receive_id(self.receive_id) + .msg_type("text") + .content(req_content) + .build()) \ + .build() + + logger.debug(f"Receive ID : {self.receive_id}") + # 发送消息 + resp: CreateMessageResponse = self.client.im.v1.message.create(req) + + if resp.success(): + logger.info(f"飞书通知发送成功: {title}") + return True + else: + logger.error(f"飞书通知发送失败: {resp.msg}") + return False + except Exception as e: + logger.error(f"飞书通知发送失败: {e}") + return False + + +class NotificationManager: + """通知管理器""" + + def __init__(self): + self.notifiers: List[BaseNotifier] = [] + + def add_notifier(self, notifier: BaseNotifier): + """添加通知器""" + self.notifiers.append(notifier) + + def notify(self, title: str, content: str) -> bool: + """发送通知到所有通知器""" + success = False + for notifier in self.notifiers: + if notifier.send(title, content): + success = True + return success + + def notify_error(self, error_type: str, error_msg: str, details: str = "") -> bool: + """发送错误通知""" + title = f"闲鱼自动客服系统错误: {error_type}" + content = f"错误信息: {error_msg}\n\n详细信息: {details}" + return self.notify(title, content) + + def notify_cookie_expired(self) -> bool: + """发送Cookie过期通知""" + title = "闲鱼自动客服系统警告: Cookie已过期" + content = "您的闲鱼Cookie已过期,请尽快更新Cookie以保持系统正常运行。" + return self.notify(title, content) + + def notify_system_start(self) -> bool: + """发送系统启动通知""" + title = "闲鱼自动客服系统: 已启动" + content = f"系统已成功启动,当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" + return self.notify(title, content) \ No newline at end of file