feat:初版
This commit is contained in:
192
WechatHook/callbacks.py
Normal file
192
WechatHook/callbacks.py
Normal file
@@ -0,0 +1,192 @@
|
||||
"""
|
||||
回调处理器
|
||||
|
||||
实现 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}")
|
||||
Reference in New Issue
Block a user