""" 回调处理器 实现 Socket 回调的装饰器和处理机制 """ import copy import ctypes from ctypes import WINFUNCTYPE from functools import wraps from typing import Callable, List from loguru import logger # 全局回调列表 _GLOBAL_CONNECT_CALLBACK_LIST: List[Callable] = [] _GLOBAL_RECV_CALLBACK_LIST: List[Callable] = [] _GLOBAL_CLOSE_CALLBACK_LIST: List[Callable] = [] def CONNECT_CALLBACK(in_class: bool = False): """ 连接回调装饰器 Args: in_class: 是否是类方法 Usage: @CONNECT_CALLBACK() def on_connect(client_id): pass @CONNECT_CALLBACK(in_class=True) def on_connect(self, client_id): pass """ def decorator(f): @wraps(f) def wrapper(*args, **kwargs): return f(*args, **kwargs) if in_class: wrapper._wx_connect_handled = True else: _GLOBAL_CONNECT_CALLBACK_LIST.append(wrapper) return wrapper return decorator def RECV_CALLBACK(in_class: bool = False): """ 接收消息回调装饰器 Args: in_class: 是否是类方法 Usage: @RECV_CALLBACK() def on_receive(client_id, message_type, data): pass @RECV_CALLBACK(in_class=True) def on_receive(self, client_id, message_type, data): pass """ def decorator(f): @wraps(f) def wrapper(*args, **kwargs): return f(*args, **kwargs) if in_class: wrapper._wx_recv_handled = True else: _GLOBAL_RECV_CALLBACK_LIST.append(wrapper) return wrapper return decorator def CLOSE_CALLBACK(in_class: bool = False): """ 断开连接回调装饰器 Args: in_class: 是否是类方法 Usage: @CLOSE_CALLBACK() def on_close(client_id): pass @CLOSE_CALLBACK(in_class=True) def on_close(self, client_id): pass """ def decorator(f): @wraps(f) def wrapper(*args, **kwargs): return f(*args, **kwargs) if in_class: wrapper._wx_close_handled = True else: _GLOBAL_CLOSE_CALLBACK_LIST.append(wrapper) return wrapper return decorator def add_callback_handler(callback_handler): """ 添加回调处理器实例 Args: callback_handler: 包含回调方法的对象 """ import inspect for name, method in inspect.getmembers(callback_handler, callable): if hasattr(method, '_wx_connect_handled'): _GLOBAL_CONNECT_CALLBACK_LIST.append(method) logger.debug(f"注册连接回调: {name}") elif hasattr(method, '_wx_recv_handled'): _GLOBAL_RECV_CALLBACK_LIST.append(method) logger.debug(f"注册接收回调: {name}") elif hasattr(method, '_wx_close_handled'): _GLOBAL_CLOSE_CALLBACK_LIST.append(method) logger.debug(f"注册断开回调: {name}") @WINFUNCTYPE(None, ctypes.c_void_p) def wechat_connect_callback(client_id): """ 微信连接回调(C 函数) Args: client_id: 客户端 ID """ logger.info(f"[回调] 客户端连接: {client_id}") for func in _GLOBAL_CONNECT_CALLBACK_LIST: try: func(client_id) except Exception as e: logger.error(f"连接回调执行失败: {e}") @WINFUNCTYPE(None, ctypes.c_long, ctypes.c_char_p, ctypes.c_ulong) def wechat_recv_callback(client_id, data, length): """ 微信接收消息回调(C 函数) Args: client_id: 客户端 ID data: 消息数据(JSON 字符串) length: 数据长度 """ try: import json # 深拷贝数据 data = copy.deepcopy(data) json_data = data.decode('utf-8') dict_data = json.loads(json_data) msg_type = dict_data.get('type') msg_data = dict_data.get('data', {}) logger.info(f"[回调] 收到消息: type={msg_type}, data={msg_data}") # 调用所有注册的回调 for func in _GLOBAL_RECV_CALLBACK_LIST: try: func(client_id, msg_type, msg_data) except Exception as e: logger.error(f"接收回调执行失败: {e}") except Exception as e: logger.error(f"解析消息失败: {e}") @WINFUNCTYPE(None, ctypes.c_ulong) def wechat_close_callback(client_id): """ 微信断开连接回调(C 函数) Args: client_id: 客户端 ID """ logger.warning(f"[回调] 客户端断开: {client_id}") for func in _GLOBAL_CLOSE_CALLBACK_LIST: try: func(client_id) except Exception as e: logger.error(f"断开回调执行失败: {e}")