├── theos ├── Skua.plist ├── MakePackageInstall ├── control ├── Makefile └── Tweak.xm /theos: -------------------------------------------------------------------------------- 1 | /opt/theos -------------------------------------------------------------------------------- /Skua.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.tencent.mqq", 5 | ); 6 | }; 7 | } -------------------------------------------------------------------------------- /MakePackageInstall: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd `dirname $0` 3 | make clean 4 | make package install 5 | rm *.deb 6 | exit 0 7 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.naken.skua 2 | Name: Skua 3 | Depends: mobilesubstrate, firmware (>= 5.0) 4 | Version: 1.0 5 | Architecture: iphoneos-arm 6 | Description: Mobile QQ auto-reply bot 7 | Maintainer: snakeninny 8 | Author: snakeninny 9 | Homepage: http://iosre.com 10 | Section: Tweaks 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | THEOS_DEVICE_IP = 192.168.1.102 2 | TARGET = iphone:7.0:5.0 3 | ARCHS = armv7 armv7s arm64 4 | 5 | include theos/makefiles/common.mk 6 | 7 | TWEAK_NAME = Skua 8 | Skua_FILES = Tweak.xm 9 | 10 | include $(THEOS_MAKE_PATH)/tweak.mk 11 | 12 | after-install:: 13 | install.exec "killall -9 QQ" 14 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | @interface QQBaseChatViewController : UIViewController 2 | - (void)sendSpecialText:(NSString *)text; 3 | @end 4 | 5 | @interface QQChatViewController : QQBaseChatViewController 6 | @end 7 | 8 | @interface QQChatViewTable : UITableView 9 | @property(assign, nonatomic) QQChatViewController *supViewController; 10 | @end 11 | 12 | @interface QQChatCellModel : NSObject 13 | @property(retain, nonatomic) NSString* nick; 14 | @property(retain, nonatomic) NSString* content; 15 | @property(assign) BOOL isSelf; 16 | @property(retain, nonatomic) NSString* uin; 17 | @end 18 | 19 | @interface QQChatViewCell : UITableViewCell 20 | @property(retain, nonatomic) QQChatCellModel* data; 21 | @property(retain, nonatomic) NSString* nick; 22 | @end 23 | 24 | @interface QQTimeModel : NSObject 25 | @property(assign, nonatomic) double time; 26 | @end 27 | 28 | static NSMutableDictionary *dictionary; 29 | 30 | %hook QQChatViewTable 31 | - (void)addObject:(id)object // QQTimeModel or QQChatCellModel 32 | { 33 | %orig; 34 | 35 | QQChatViewController *controller = [self supViewController]; 36 | 37 | if ([object isKindOfClass:NSClassFromString(@"QQTimeModel")]) 38 | { 39 | NSDate *current = [NSDate dateWithTimeIntervalSince1970:[object time]]; 40 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 41 | [formatter setDateFormat:@"HH"]; 42 | NSString *date = [formatter stringFromDate:current]; 43 | [formatter release]; 44 | 45 | if ([date intValue] >= 1 && [date intValue] <= 5) 46 | { 47 | NSString *goToBedMessage = [[NSString alloc] initWithFormat:@"现在都凌晨%@点多了,早点休息吧,身体是革命的本钱啊!", date]; 48 | [controller sendSpecialText:goToBedMessage]; 49 | [goToBedMessage release]; 50 | } 51 | } 52 | else if ([object isKindOfClass:NSClassFromString(@"QQChatCell")] || [object isKindOfClass:NSClassFromString(@"QQChatCellModel")]) 53 | { 54 | if (![object isSelf]) // get rid of circle 55 | { 56 | NSString *content = [object content]; 57 | NSString *nick = [object nick]; 58 | 59 | if ([content rangeOfString:@"skua"].location != NSNotFound) 60 | { 61 | if ([nick isEqualToString:@"大名狗剩"]) 62 | { 63 | NSString *assistantMessage = [[NSString alloc] initWithString:@"好的主人。"]; 64 | [controller sendSpecialText:assistantMessage]; 65 | [assistantMessage release]; 66 | } 67 | else 68 | { 69 | NSString *jokeMessage = [[NSString alloc] initWithFormat:@"@%@ ,叫我干嘛?不理你~", nick]; 70 | [controller sendSpecialText:jokeMessage]; 71 | [jokeMessage release]; 72 | } 73 | } 74 | else 75 | { 76 | for (NSString *message in [dictionary allKeys]) 77 | { 78 | if ([content rangeOfString:message].location != NSNotFound) 79 | { 80 | NSString *replyMessage = [[NSString alloc] initWithFormat:@"你好@%@ ,%@", nick, [dictionary objectForKey:message]]; 81 | [controller sendSpecialText:replyMessage]; 82 | [replyMessage release]; 83 | break; 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | %end 91 | 92 | __attribute__((always_inline)) __attribute__((visibility("hidden"))) 93 | static inline void CreateSkuaDatabase(void) 94 | { 95 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 96 | NSString *documentsDirectory = [paths objectAtIndex:0]; 97 | NSString *filePath = [documentsDirectory stringByAppendingString:@"/skua.plist"]; 98 | if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) 99 | { 100 | NSString *welcomMessage = [[NSString alloc] initWithString:@"欢迎加入iOS应用逆向工程官方群。你可以先跟大家打个招呼,也可以去问题最集中的论坛ios.com转转。Have fun :)"]; 101 | NSString *replyMessage = [[NSString alloc] initWithString:@"iOS应用逆向工程Q群小秘书正在为您服务。有技术问题?QQ消息流动太快,留不住有用信息,大家现在可能都在忙,很可能遗漏这个问题。请您整理一下问题的来龙去脉,附带必要的调试信息,去我们的论坛iosre.com发帖,谢谢!"]; 102 | [dictionary release]; 103 | dictionary = nil; 104 | dictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys:welcomMessage, @"已加入群", replyMessage, @"求解决", replyMessage, @"求解答", replyMessage, @"为什么", replyMessage, @"么?", replyMessage, @"吗?", replyMessage, @"不?", nil]; // object: reply key: keyword 105 | [dictionary writeToFile:filePath atomically:YES]; 106 | [welcomMessage release]; 107 | [replyMessage release]; 108 | } 109 | else 110 | { 111 | [dictionary release]; 112 | dictionary = nil; 113 | dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath]; 114 | } 115 | } 116 | 117 | %ctor 118 | { 119 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 120 | %init; 121 | CreateSkuaDatabase(); 122 | [pool drain]; 123 | } 124 | --------------------------------------------------------------------------------