mirror of
https://github.com/Sunnyyoung/WeChatTweak-macOS.git
synced 2026-03-03 16:45:37 +08:00
81 lines
3.0 KiB
Objective-C
81 lines
3.0 KiB
Objective-C
//
|
|
// WeChatTweakPlugin.m
|
|
// WeChatTweak
|
|
//
|
|
// Runtime recall marking plugin.
|
|
// Hooks FFProcessReqsvrZZ's DelRevokedMsg:msgData: to prepend
|
|
// "[已撤回]" to recalled text messages.
|
|
//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <objc/runtime.h>
|
|
#import <objc/message.h>
|
|
|
|
static IMP sOriginalDelRevokedMsg = NULL;
|
|
|
|
static void hooked_DelRevokedMsg(id self, SEL _cmd, id session, id msgData) {
|
|
@try {
|
|
// Only modify text messages (messageType == 1)
|
|
BOOL shouldMark = NO;
|
|
if ([msgData respondsToSelector:NSSelectorFromString(@"messageType")]) {
|
|
NSInteger msgType = ((NSInteger (*)(id, SEL))objc_msgSend)(
|
|
msgData, NSSelectorFromString(@"messageType"));
|
|
shouldMark = (msgType == 1);
|
|
}
|
|
|
|
if (shouldMark && [msgData respondsToSelector:NSSelectorFromString(@"msgContent")]) {
|
|
NSString *content = ((NSString *(*)(id, SEL))objc_msgSend)(
|
|
msgData, NSSelectorFromString(@"msgContent"));
|
|
if (content && ![content hasPrefix:@"[已撤回]"]) {
|
|
NSString *marked = [NSString stringWithFormat:@"[已撤回] %@", content];
|
|
if ([msgData respondsToSelector:NSSelectorFromString(@"setMsgContent:")]) {
|
|
((void (*)(id, SEL, id))objc_msgSend)(
|
|
msgData, NSSelectorFromString(@"setMsgContent:"), marked);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Persist the modification
|
|
SEL modifySel = NSSelectorFromString(@"ModifyMsgData:msgData:");
|
|
if ([self respondsToSelector:modifySel]) {
|
|
NSMethodSignature *sig = [self methodSignatureForSelector:modifySel];
|
|
if (sig) {
|
|
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig];
|
|
[inv setTarget:self];
|
|
[inv setSelector:modifySel];
|
|
[inv setArgument:&session atIndex:2];
|
|
[inv setArgument:&msgData atIndex:3];
|
|
[inv invoke];
|
|
}
|
|
}
|
|
} @catch (NSException *exception) {
|
|
NSLog(@"[WeChatTweak] Exception in hooked_DelRevokedMsg: %@", exception);
|
|
}
|
|
|
|
// Call original (binary-patched to return 0, effectively a no-op)
|
|
if (sOriginalDelRevokedMsg) {
|
|
((void (*)(id, SEL, id, id))sOriginalDelRevokedMsg)(self, _cmd, session, msgData);
|
|
}
|
|
}
|
|
|
|
__attribute__((constructor))
|
|
static void WeChatTweakPluginInit(void) {
|
|
NSLog(@"[WeChatTweak] Plugin loaded.");
|
|
|
|
Class cls = NSClassFromString(@"FFProcessReqsvrZZ");
|
|
if (!cls) {
|
|
NSLog(@"[WeChatTweak] FFProcessReqsvrZZ class not found. Plugin inactive.");
|
|
return;
|
|
}
|
|
|
|
SEL sel = NSSelectorFromString(@"DelRevokedMsg:msgData:");
|
|
Method method = class_getInstanceMethod(cls, sel);
|
|
if (!method) {
|
|
NSLog(@"[WeChatTweak] DelRevokedMsg:msgData: not found. Plugin inactive.");
|
|
return;
|
|
}
|
|
|
|
sOriginalDelRevokedMsg = method_setImplementation(method, (IMP)hooked_DelRevokedMsg);
|
|
NSLog(@"[WeChatTweak] Successfully hooked DelRevokedMsg:msgData:");
|
|
}
|