193 lines
4.7 KiB
Python
193 lines
4.7 KiB
Python
"""
|
||
回调处理器
|
||
|
||
实现 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}")
|