├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── Screenshot ├── Screenshot01.png └── Screenshot02.png ├── Tweaks ├── AutoRedEnvelopes.h ├── AutoRedEnvelopes.xm ├── AutoRedEnvelopesData.h ├── AutoRedEnvelopesData.m ├── CustomGame.h ├── CustomGame.xm ├── CustomRegion.h ├── CustomRegion.xm ├── CustomSelectAttachmentView.h ├── CustomSelectAttachmentView.xm ├── CustomStepCount.h ├── CustomStepCount.xm ├── KeepRunning.h ├── KeepRunning.xm ├── KeepRunningManager.h ├── KeepRunningManager.m ├── Settings.h └── Settings.xm ├── WeChatTweak.plist └── control /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/macos,sublimetext,windows,visualstudiocode,theos-tweak 2 | 3 | ### macOS ### 4 | *.DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | 8 | # Icon must end with two \r 9 | Icon 10 | # Thumbnails 11 | ._* 12 | # Files that might appear in the root of a volume 13 | .DocumentRevisions-V100 14 | .fseventsd 15 | .Spotlight-V100 16 | .TemporaryItems 17 | .Trashes 18 | .VolumeIcon.icns 19 | .com.apple.timemachine.donotpresent 20 | # Directories potentially created on remote AFP share 21 | .AppleDB 22 | .AppleDesktop 23 | Network Trash Folder 24 | Temporary Items 25 | .apdisk 26 | 27 | 28 | ### SublimeText ### 29 | # cache files for sublime text 30 | *.tmlanguage.cache 31 | *.tmPreferences.cache 32 | *.stTheme.cache 33 | 34 | # workspace files are user-specific 35 | *.sublime-workspace 36 | 37 | # project files should be checked into the repository, unless a significant 38 | # proportion of contributors will probably not be using SublimeText 39 | # *.sublime-project 40 | 41 | # sftp configuration file 42 | sftp-config.json 43 | 44 | # Package control specific files 45 | Package Control.last-run 46 | Package Control.ca-list 47 | Package Control.ca-bundle 48 | Package Control.system-ca-bundle 49 | Package Control.cache/ 50 | Package Control.ca-certs/ 51 | bh_unicode_properties.cache 52 | 53 | # Sublime-github package stores a github token in this file 54 | # https://packagecontrol.io/packages/sublime-github 55 | GitHub.sublime-settings 56 | 57 | 58 | ### Windows ### 59 | # Windows thumbnail cache files 60 | Thumbs.db 61 | ehthumbs.db 62 | ehthumbs_vista.db 63 | 64 | # Folder config file 65 | Desktop.ini 66 | 67 | # Recycle Bin used on file shares 68 | $RECYCLE.BIN/ 69 | 70 | # Windows Installer files 71 | *.cab 72 | *.msi 73 | *.msm 74 | *.msp 75 | 76 | # Windows shortcuts 77 | *.lnk 78 | 79 | 80 | ### VisualStudioCode ### 81 | .vscode/* 82 | !.vscode/settings.json 83 | !.vscode/tasks.json 84 | !.vscode/launch.json 85 | !.vscode/extensions.json 86 | 87 | 88 | ### THEOS-Tweak ### 89 | ._* 90 | *.deb 91 | .debmake 92 | _ 93 | obj 94 | .theos 95 | .DS_Store 96 | 97 | # End of https://www.gitignore.io/api/macos,sublimetext,windows,visualstudiocode,theos-tweak 98 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Sunnyyoung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | THEOS_DEVICE_IP = 192.168.2.7 2 | THEOS_DEVICE_PORT = 22 3 | ARCHS = armv7 arm64 4 | TARGET = iphone:latest:7.0 5 | 6 | include $(THEOS)/makefiles/common.mk 7 | 8 | TWEAK_NAME = WeChatTweak 9 | WeChatTweak_FRAMEWORKS = UIKit 10 | WeChatTweak_FILES = $(wildcard Tweaks/*.m) $(wildcard Tweaks/*.xm) 11 | 12 | include $(THEOS_MAKE_PATH)/tweak.mk 13 | 14 | after-install:: 15 | install.exec "killall -9 WeChat" 16 | 17 | after-uninstall:: 18 | install.exec "killall -9 WeChat" 19 | 20 | after-clean:: 21 | rm -rf ./.theos ./obj ./packages 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WeChatTweak-iOS 2 | 3 | 微信iOS客户端Tweak实现。 4 | 5 | ## Feature 6 | 7 | 1. 自动抢红包 8 | - 随机延时抢红包 9 | - 后台抢红包 10 | - 是否抢自己发出的 11 | 2. 自定义骰子数 12 | 3. 自定义猜拳结果 13 | 4. 自定义运动步数 14 | 15 | ## Requirement 16 | 17 | - Xcode 18 | - ldid 19 | - dpkg 20 | - [theos](https://github.com/theos/theos) 21 | 22 | ## Screenshot 23 | 24 | | 设置页面 | 自定义猜拳&骰子 | 25 | | :--------------------------------: | :--------------------------------: | 26 | | ![](./Screenshot/Screenshot01.png) | ![](./Screenshot/Screenshot02.png) | 27 | 28 | ## License 29 | 30 | The [MIT License](LICENSE). 31 | -------------------------------------------------------------------------------- /Screenshot/Screenshot01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunnyyoung/WeChatTweak-iOS/678affca569a97451e5cac54c492017a7f215e8f/Screenshot/Screenshot01.png -------------------------------------------------------------------------------- /Screenshot/Screenshot02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunnyyoung/WeChatTweak-iOS/678affca569a97451e5cac54c492017a7f215e8f/Screenshot/Screenshot02.png -------------------------------------------------------------------------------- /Tweaks/AutoRedEnvelopes.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | @interface NSString (NSString_SBJSON) 8 | 9 | - (id)JSONArray; 10 | - (id)JSONDictionary; 11 | - (id)JSONValue; 12 | 13 | @end 14 | 15 | @interface WCPayInfoItem: NSObject 16 | 17 | @property(retain, nonatomic) NSString *m_c2cNativeUrl; 18 | 19 | @end 20 | 21 | @interface CMessageWrap : NSObject 22 | 23 | @property (nonatomic) NSUInteger m_uiMessageType; // 消息类型 24 | @property (retain, nonatomic) NSString* m_nsFromUsr; // 发信人,可能是群或个人 25 | @property (retain, nonatomic) NSString* m_nsToUsr; // 收信人 26 | @property (retain, nonatomic) NSString* m_nsContent; // 消息内容 27 | @property (retain, nonatomic) WCPayInfoItem *m_oWCPayInfoItem; // PayInfo 28 | 29 | @end 30 | 31 | @interface CContact: NSObject 32 | 33 | @property(retain, nonatomic) NSString *m_nsUsrName; 34 | @property(retain, nonatomic) NSString *m_nsHeadImgUrl; 35 | 36 | - (id)getContactDisplayName; 37 | 38 | @end 39 | 40 | @interface CContactMgr : NSObject 41 | 42 | - (id)getSelfContact; 43 | 44 | @end 45 | 46 | @interface MMServiceCenter : NSObject 47 | 48 | + (instancetype)defaultCenter; 49 | - (id)getService:(Class)service; 50 | 51 | @end 52 | 53 | @interface WCRedEnvelopesLogicMgr: NSObject 54 | 55 | - (void)OpenRedEnvelopesRequest:(id)params; 56 | - (void)ReceiverQueryRedEnvelopesRequest:(id)arg1; 57 | 58 | @end 59 | 60 | @interface WCBizUtil : NSObject 61 | 62 | + (id)dictionaryWithDecodedComponets:(id)arg1 separator:(id)arg2; 63 | 64 | @end 65 | 66 | @interface SKBuiltinBuffer_t : NSObject 67 | 68 | @property(retain, nonatomic) NSData *buffer; 69 | @property(nonatomic) unsigned int iLen; 70 | 71 | @end 72 | 73 | @interface HongBaoRes : NSObject 74 | 75 | @property(retain, nonatomic) SKBuiltinBuffer_t *retText; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Tweaks/AutoRedEnvelopes.xm: -------------------------------------------------------------------------------- 1 | #import "AutoRedEnvelopes.h" 2 | #import "AutoRedEnvelopesData.h" 3 | 4 | %hook CMessageMgr 5 | 6 | - (void)AsyncOnAddMsg:(NSString *)msg MsgWrap:(CMessageWrap *)wrap { 7 | %orig; 8 | switch(wrap.m_uiMessageType) { 9 | case 49: { 10 | CContactMgr *contactManager = [[%c(MMServiceCenter) defaultCenter] getService:[%c(CContactMgr) class]]; 11 | CContact *selfContact = [contactManager getSelfContact]; 12 | 13 | if ([wrap.m_nsContent rangeOfString:@"wxpay://"].location != NSNotFound) { 14 | // 是否打开红包开关 15 | BOOL isAutoRedEnvelopes = [[NSUserDefaults standardUserDefaults] boolForKey:@"WeChatTweakAutoRedEnvelopesKey"]; 16 | // 是否抢自己发出的 17 | BOOL isAutoRedEnvelopesFromMe = [[NSUserDefaults standardUserDefaults] boolForKey:@"WeChatTweakAutoRedEnvelopesFromMeKey"]; 18 | // 群聊 19 | BOOL isChatRoom = ([wrap.m_nsFromUsr rangeOfString:@"@chatroom"].location != NSNotFound) || ([wrap.m_nsToUsr rangeOfString:@"@chatroom"].location != NSNotFound); 20 | // 自己发红包 21 | BOOL isFromMe = [wrap.m_nsFromUsr isEqualToString:selfContact.m_nsUsrName]; 22 | 23 | if (isAutoRedEnvelopes && isChatRoom && !(!isAutoRedEnvelopesFromMe && isFromMe)) { 24 | NSString *parametersString = [wrap.m_oWCPayInfoItem.m_c2cNativeUrl stringByReplacingOccurrencesOfString:@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" withString:@""]; 25 | NSDictionary *parametersDictionary = [%c(WCBizUtil) dictionaryWithDecodedComponets:parametersString separator:@"&"]; 26 | 27 | AutoRedEnvelopesData *data = [AutoRedEnvelopesData sharedInstance]; 28 | data.nickName = [selfContact getContactDisplayName] ?: @""; 29 | data.headImg = [selfContact m_nsHeadImgUrl] ?: @""; 30 | data.msgType = parametersDictionary[@"msgtype"] ?: @"1"; 31 | data.sendId = parametersDictionary[@"sendid"] ?: @""; 32 | data.channelId = parametersDictionary[@"channelid"] ?: @"1"; 33 | data.nativeUrl = wrap.m_oWCPayInfoItem.m_c2cNativeUrl ?: @""; 34 | data.sessionUserName = isFromMe ? wrap.m_nsToUsr : wrap.m_nsFromUsr; 35 | data.needsAutoOpen = YES; 36 | 37 | NSMutableDictionary *receiverQuery = [NSMutableDictionary dictionary]; 38 | receiverQuery[@"agreeDuty"] = @"0"; 39 | receiverQuery[@"inWay"] = @"0"; 40 | receiverQuery[@"nativeUrl"] = wrap.m_oWCPayInfoItem.m_c2cNativeUrl ?: @""; 41 | receiverQuery[@"channelId"] = parametersDictionary[@"channelid"] ?: @"1"; 42 | receiverQuery[@"msgType"] = parametersDictionary[@"msgtype"] ?: @"1"; 43 | receiverQuery[@"sendId"] = parametersDictionary[@"sendid"] ?: @""; 44 | WCRedEnvelopesLogicMgr *logicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]]; 45 | [logicMgr ReceiverQueryRedEnvelopesRequest:receiverQuery]; 46 | } 47 | } 48 | break; 49 | } 50 | default: 51 | break; 52 | } 53 | } 54 | 55 | %end 56 | 57 | %hook WCRedEnvelopesLogicMgr 58 | 59 | - (void)OnWCToHongbaoCommonResponse:(HongBaoRes *)arg1 Request:(id)arg2 { 60 | %orig; 61 | NSString *responseString = [[NSString alloc] initWithData:arg1.retText.buffer encoding:NSUTF8StringEncoding]; 62 | NSDictionary *responseDicrionary = [responseString JSONDictionary]; 63 | NSString *timingIdentifier = responseDicrionary[@"timingIdentifier"]; 64 | NSInteger receiveStatus = [responseDicrionary[@"receiveStatus"] integerValue]; 65 | 66 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 67 | AutoRedEnvelopesData *data = [AutoRedEnvelopesData sharedInstance]; 68 | BOOL isAutoRedEnvelopes = [userDefaults boolForKey:@"WeChatTweakAutoRedEnvelopesKey"]; 69 | BOOL isAutoRedEnvelopesDelayRandomly = [userDefaults boolForKey:@"WeChatTweakAutoRedEnvelopesDelayRandomlyKey"]; 70 | CGFloat delaySeconds = [userDefaults doubleForKey:@"WeChatTweakAutoRedEnvelopesDelaySecondsKey"]; 71 | CGFloat ramdomly = (double)(arc4random()/0x100000000); 72 | 73 | if (isAutoRedEnvelopes && timingIdentifier.length && receiveStatus != 2 && data.needsAutoOpen) { 74 | data.timingIdentifier = timingIdentifier; 75 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((isAutoRedEnvelopesDelayRandomly ? (ramdomly*delaySeconds) : delaySeconds) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 76 | WCRedEnvelopesLogicMgr *logicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]]; 77 | [logicMgr OpenRedEnvelopesRequest:[data keyValues]]; 78 | [data resetData]; 79 | }); 80 | } 81 | } 82 | 83 | %end 84 | -------------------------------------------------------------------------------- /Tweaks/AutoRedEnvelopesData.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | #import 8 | 9 | @interface AutoRedEnvelopesData : NSObject 10 | 11 | @property (nonatomic, copy) NSString *msgType; 12 | @property (nonatomic, copy) NSString *sendId; 13 | @property (nonatomic, copy) NSString *channelId; 14 | @property (nonatomic, copy) NSString *nickName; 15 | @property (nonatomic, copy) NSString *headImg; 16 | @property (nonatomic, copy) NSString *nativeUrl; 17 | @property (nonatomic, copy) NSString *sessionUserName; 18 | @property (nonatomic, copy) NSString *timingIdentifier; 19 | 20 | @property (nonatomic, assign) BOOL needsAutoOpen; 21 | 22 | + (instancetype)sharedInstance; 23 | - (void)resetData; 24 | - (NSDictionary *)keyValues; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Tweaks/AutoRedEnvelopesData.m: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | #import "AutoRedEnvelopesData.h" 8 | 9 | @implementation AutoRedEnvelopesData : NSObject 10 | 11 | + (instancetype)sharedInstance { 12 | static AutoRedEnvelopesData *sharedInstance; 13 | static dispatch_once_t onceToken; 14 | dispatch_once(&onceToken, ^{ 15 | sharedInstance = [[AutoRedEnvelopesData alloc] init]; 16 | }); 17 | return sharedInstance; 18 | } 19 | 20 | - (void)resetData { 21 | self.msgType = nil; 22 | self.sendId = nil; 23 | self.channelId = nil; 24 | self.nickName = nil; 25 | self.headImg = nil; 26 | self.nativeUrl = nil; 27 | self.sessionUserName = nil; 28 | self.timingIdentifier = nil; 29 | self.needsAutoOpen = NO; 30 | } 31 | 32 | - (NSDictionary *)keyValues { 33 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 34 | dictionary[@"msgType"] = self.msgType; 35 | dictionary[@"sendId"] = self.sendId; 36 | dictionary[@"channelId"] = self.channelId; 37 | dictionary[@"nickName"] = self.nickName; 38 | dictionary[@"headImg"] = self.headImg; 39 | dictionary[@"nativeUrl"] = self.nativeUrl; 40 | dictionary[@"sessionUserName"] = self.sessionUserName; 41 | dictionary[@"timingIdentifier"] = self.timingIdentifier; 42 | return dictionary; 43 | } 44 | 45 | @end -------------------------------------------------------------------------------- /Tweaks/CustomGame.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | @interface CMessageWrap : NSObject 8 | 9 | @property(nonatomic) unsigned int m_uiGameType; // 游戏类型 10 | @property(nonatomic) unsigned int m_uiGameContent; // 游戏内容 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Tweaks/CustomGame.xm: -------------------------------------------------------------------------------- 1 | #import "CustomGame.h" 2 | 3 | CMessageWrap *setDice(CMessageWrap *wrap, unsigned int point) { 4 | if (wrap.m_uiGameType == 2) { 5 | wrap.m_uiGameContent = point + 3; 6 | } 7 | return wrap; 8 | } 9 | 10 | CMessageWrap *setRPS(CMessageWrap *wrap, unsigned int type) { 11 | if (wrap.m_uiGameType == 1) { 12 | wrap.m_uiGameContent = type; 13 | } 14 | return wrap; 15 | } 16 | 17 | %hook GameController 18 | 19 | + (id)getMD5ByGameContent:(unsigned int)arg1 { 20 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 21 | NSInteger diceNumber = [userDefaults integerForKey:@"WeChatTweakCustomDiceNumberKey"]; 22 | NSInteger rpsResult = [userDefaults integerForKey:@"WeChatTweakCustomRPSResultKey"]; 23 | if (arg1 > 3 && arg1 < 10) { 24 | if (diceNumber) { 25 | return %orig(diceNumber + 3); 26 | } else { 27 | return %orig; 28 | } 29 | } else if (arg1 > 0 && arg1 < 4) { 30 | if (rpsResult) { 31 | return %orig(rpsResult); 32 | } else { 33 | return %orig; 34 | } 35 | } else { 36 | return %orig; 37 | } 38 | } 39 | 40 | %end 41 | 42 | %hook CMessageMgr 43 | 44 | - (void)AddEmoticonMsg:(id)arg1 MsgWrap:(id)arg2 { 45 | CMessageWrap *wrap = (CMessageWrap *)arg2; 46 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 47 | NSInteger diceNumber = [userDefaults integerForKey:@"WeChatTweakCustomDiceNumberKey"]; 48 | NSInteger rpsResult = [userDefaults integerForKey:@"WeChatTweakCustomRPSResultKey"]; 49 | if (wrap.m_uiGameType == 2) { 50 | if (diceNumber) { 51 | %orig(arg1, setDice(arg2, diceNumber)); 52 | } else { 53 | %orig; 54 | } 55 | } else if (wrap.m_uiGameType == 1) { 56 | if (rpsResult) { 57 | %orig(arg1, setRPS(arg2, rpsResult)); 58 | } else { 59 | %orig; 60 | } 61 | } else { 62 | %orig; 63 | } 64 | } 65 | 66 | %end 67 | 68 | %hook CEmoticonUploadMgr 69 | 70 | - (void)StartUpload:(id)arg1 { 71 | CMessageWrap *wrap = (CMessageWrap *)arg1; 72 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 73 | NSInteger diceNumber = [userDefaults integerForKey:@"WeChatTweakCustomDiceNumberKey"]; 74 | NSInteger rpsResult = [userDefaults integerForKey:@"WeChatTweakCustomRPSResultKey"]; 75 | if (wrap.m_uiGameType == 2) { 76 | if (diceNumber) { 77 | %orig(setDice(arg1, diceNumber)); 78 | } else { 79 | %orig; 80 | } 81 | } else if (wrap.m_uiGameType == 1) { 82 | if (rpsResult) { 83 | %orig(setRPS(arg1, rpsResult)); 84 | } else { 85 | %orig; 86 | } 87 | } else { 88 | %orig; 89 | } 90 | } 91 | 92 | %end 93 | -------------------------------------------------------------------------------- /Tweaks/CustomRegion.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | @protocol MMRegionPickerViewControllerDelegate 8 | 9 | - (void)MMRegionPickerDidChoosRegion:(NSArray *)arg1; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Tweaks/CustomRegion.xm: -------------------------------------------------------------------------------- 1 | #import "CustomRegion.h" 2 | 3 | %hook MMRegionPickerViewController 4 | 5 | - (void)viewDidLoad { 6 | %orig; 7 | 8 | [[self navigationItem] setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@"自定义" style:UIBarButtonItemStylePlain target:self action:@selector(setCustomRegion)]]; 9 | } 10 | 11 | %new 12 | - (void)setCustomRegion { 13 | UIAlertView *alert = [[UIAlertView alloc] init]; 14 | alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput; 15 | alert.delegate = self; 16 | alert.title = @"设置自定义地区"; 17 | [alert addButtonWithTitle:@"取消"]; 18 | [alert addButtonWithTitle:@"确定"]; 19 | [alert textFieldAtIndex:0].secureTextEntry = NO; 20 | [alert textFieldAtIndex:0].placeholder = @"国家"; 21 | [alert textFieldAtIndex:0].keyboardType = UIKeyboardTypeDefault; 22 | [alert textFieldAtIndex:1].secureTextEntry = NO; 23 | [alert textFieldAtIndex:1].placeholder = @"地区"; 24 | [alert textFieldAtIndex:1].keyboardType = UIKeyboardTypeDefault; 25 | [alert show]; 26 | } 27 | 28 | %new 29 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 30 | if (buttonIndex == 1) { 31 | NSString *country = [alertView textFieldAtIndex:0].text; 32 | NSString *province = [alertView textFieldAtIndex:1].text; 33 | [[self delegate] MMRegionPickerDidChoosRegion:@[@"", country, province]]; 34 | } 35 | } 36 | 37 | %end 38 | -------------------------------------------------------------------------------- /Tweaks/CustomSelectAttachmentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | @interface SelectAttachmentViewController : NSObject 8 | 9 | - (unsigned int)numberOfAttachment; 10 | - (id)getTextAtIndex:(unsigned long)arg1; 11 | - (id)getImageAtIndex:(unsigned long)arg1; 12 | - (void)OnAttachmentClicked:(id)arg1; 13 | - (void)updateView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Tweaks/CustomSelectAttachmentView.xm: -------------------------------------------------------------------------------- 1 | #import "CustomSelectAttachmentView.h" 2 | 3 | %hook SelectAttachmentViewController 4 | 5 | - (unsigned int)numberOfAttachment { 6 | return %orig + 2; 7 | } 8 | 9 | - (id)getTextAtIndex:(unsigned long)arg1 { 10 | if (arg1 == [self numberOfAttachment] - 1) { 11 | return @"猜拳"; 12 | } else if (arg1 == [self numberOfAttachment] - 2) { 13 | return @"骰子"; 14 | } else { 15 | return %orig; 16 | } 17 | } 18 | 19 | - (id)getImageAtIndex:(unsigned long)arg1 { 20 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 21 | if (arg1 == [self numberOfAttachment] - 1) { 22 | NSInteger rpsResult = [userDefaults integerForKey:@"WeChatTweakCustomRPSResultKey"]; 23 | if (rpsResult == 1) { 24 | return [UIImage imageNamed:@"JSB_J.pic"]; 25 | } else if (rpsResult == 2) { 26 | return [UIImage imageNamed:@"JSB_S.pic"]; 27 | } else if (rpsResult == 3) { 28 | return [UIImage imageNamed:@"JSB_B.pic"]; 29 | } else { 30 | return [UIImage imageNamed:@"JSB.pic"]; 31 | } 32 | } else if (arg1 == [self numberOfAttachment] - 2) { 33 | NSInteger diceNumber = [userDefaults integerForKey:@"WeChatTweakCustomDiceNumberKey"]; 34 | NSString *diceImageName = diceNumber == 0 ? @"dice.pic" : [NSString stringWithFormat:@"dice_%@.pic", @(diceNumber)]; 35 | return [UIImage imageNamed:diceImageName]; 36 | } else { 37 | return %orig; 38 | } 39 | } 40 | 41 | - (void)OnAttachmentClicked:(UIButton *)arg1 { 42 | NSInteger buttonIndex = arg1.tag % 18000; 43 | if (buttonIndex == [self numberOfAttachment] -1) { 44 | UIAlertView *alertView = [[UIAlertView alloc] init]; 45 | alertView.delegate = self; 46 | alertView.tag = 0; 47 | alertView.title = @"设置自定义猜拳结果"; 48 | [alertView addButtonWithTitle:@"不设置"]; 49 | [alertView addButtonWithTitle:@"✌️"]; 50 | [alertView addButtonWithTitle:@"👊"]; 51 | [alertView addButtonWithTitle:@"✋"]; 52 | [alertView addButtonWithTitle:@"取消"]; 53 | [alertView show]; 54 | } else if (buttonIndex == [self numberOfAttachment] - 2) { 55 | UIAlertView *alertView = [[UIAlertView alloc] init]; 56 | alertView.delegate = self; 57 | alertView.tag = 1; 58 | alertView.title = @"设置自定义骰子数"; 59 | [alertView addButtonWithTitle:@"不设置"]; 60 | [alertView addButtonWithTitle:@"1"]; 61 | [alertView addButtonWithTitle:@"2"]; 62 | [alertView addButtonWithTitle:@"3"]; 63 | [alertView addButtonWithTitle:@"4"]; 64 | [alertView addButtonWithTitle:@"5"]; 65 | [alertView addButtonWithTitle:@"6"]; 66 | [alertView addButtonWithTitle:@"取消"]; 67 | [alertView show]; 68 | } else { 69 | %orig; 70 | } 71 | } 72 | 73 | %new 74 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 75 | if (alertView.tag == 0) { 76 | // 设置自定义猜拳结果 77 | if (buttonIndex <= 3) { 78 | [[NSUserDefaults standardUserDefaults] setInteger:buttonIndex forKey:@"WeChatTweakCustomRPSResultKey"]; 79 | [self updateView]; 80 | } 81 | } else if (alertView.tag == 1) { 82 | // 设置自定义骰子数 83 | if (buttonIndex <= 6) { 84 | [[NSUserDefaults standardUserDefaults] setInteger:buttonIndex forKey:@"WeChatTweakCustomDiceNumberKey"]; 85 | [self updateView]; 86 | } 87 | } 88 | } 89 | 90 | %end -------------------------------------------------------------------------------- /Tweaks/CustomStepCount.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | @interface WCDeviceStepObject : NSObject 8 | 9 | @property(nonatomic) unsigned long hkStepCount; 10 | @property(nonatomic) unsigned long m7StepCount; 11 | 12 | @end -------------------------------------------------------------------------------- /Tweaks/CustomStepCount.xm: -------------------------------------------------------------------------------- 1 | #import "CustomStepCount.h" 2 | 3 | %hook WCDeviceStepObject 4 | 5 | - (unsigned long)m7StepCount { 6 | NSUInteger customStepCount = [[NSUserDefaults standardUserDefaults] integerForKey:@"WeChatTweakCustomStepCountKey"]; 7 | return customStepCount == 0 ? %orig : customStepCount; 8 | } 9 | 10 | %end 11 | -------------------------------------------------------------------------------- /Tweaks/KeepRunning.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | @interface MicroMessengerAppDelegate : NSObject 8 | 9 | - (void)applicationWillResignActive:(id)arg1; 10 | - (void)applicationDidBecomeActive:(id)arg1; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Tweaks/KeepRunning.xm: -------------------------------------------------------------------------------- 1 | #import "KeepRunning.h" 2 | #import "KeepRunningManager.h" 3 | 4 | %hook MicroMessengerAppDelegate 5 | 6 | - (void)applicationWillResignActive:(id)arg1 { 7 | %orig; 8 | BOOL isAutoRedEnvelopesKeepRunning = [[NSUserDefaults standardUserDefaults] boolForKey:@"WeChatTweakAutoRedEnvelopesKeepRunningKey"]; 9 | if (isAutoRedEnvelopesKeepRunning) { 10 | [[%c(KeepRunningManager) sharedInstance] startKeepRunning]; 11 | [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 12 | } 13 | } 14 | 15 | - (void)applicationDidBecomeActive:(id)arg1 { 16 | %orig; 17 | if ([KeepRunningManager sharedInstance].playing) { 18 | [[%c(KeepRunningManager) sharedInstance] stopKeepRunning]; 19 | [[UIApplication sharedApplication] endReceivingRemoteControlEvents]; 20 | } 21 | } 22 | 23 | %end 24 | -------------------------------------------------------------------------------- /Tweaks/KeepRunningManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | #import 8 | #import 9 | 10 | @interface KeepRunningManager : NSObject 11 | 12 | @property (nonatomic, readonly) BOOL playing; 13 | 14 | + (instancetype)sharedInstance; 15 | - (void)startKeepRunning; 16 | - (void)stopKeepRunning; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Tweaks/KeepRunningManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | #import "KeepRunningManager.h" 8 | 9 | @interface KeepRunningManager () 10 | 11 | @property (nonatomic, strong) AVAudioPlayer *audioPlayer; 12 | 13 | @end 14 | 15 | @implementation KeepRunningManager 16 | 17 | + (instancetype)sharedInstance { 18 | static KeepRunningManager *sharedInstance; 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^{ 21 | sharedInstance = [[KeepRunningManager alloc] init]; 22 | }); 23 | return sharedInstance; 24 | } 25 | 26 | - (instancetype)init { 27 | self = [super init]; 28 | if (self) { 29 | NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"pstncall" withExtension:@".mp3"]; 30 | self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil]; 31 | self.audioPlayer.numberOfLoops = -1; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)startKeepRunning { 37 | if (!self.audioPlayer.playing) { 38 | [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; 39 | [[AVAudioSession sharedInstance] setActive:YES error:nil]; 40 | [self.audioPlayer play]; 41 | } 42 | } 43 | 44 | - (void)stopKeepRunning { 45 | if (self.audioPlayer.playing) { 46 | [self.audioPlayer stop]; 47 | [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; 48 | [[AVAudioSession sharedInstance] setActive:NO error:nil]; 49 | } 50 | } 51 | 52 | - (BOOL)playing { 53 | return self.audioPlayer.playing; 54 | } 55 | 56 | @end -------------------------------------------------------------------------------- /Tweaks/Settings.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChatTweak.h 3 | // 4 | // Created by Sunnyyoung on 2017/01/01. 5 | // 6 | 7 | @interface MMTableView: UITableView 8 | @end 9 | 10 | @interface MMTableViewInfo 11 | 12 | - (id)getTableView; 13 | - (void)addSection:(id)arg1; 14 | - (void)insertSection:(id)arg1 At:(unsigned int)arg2; 15 | 16 | @end 17 | 18 | @interface MMTableViewSectionInfo 19 | 20 | + (id)sectionInfoDefaut; 21 | + (id)sectionInfoHeader:(id)arg1; 22 | + (id)sectionInfoFooter:(id)arg1; 23 | + (id)sectionInfoHeader:(id)arg1 Footer:(id)arg2; 24 | - (void)addCell:(id)arg1; 25 | 26 | @end 27 | 28 | @interface MMTableViewCellInfo 29 | 30 | + (id)normalCellForSel:(SEL)arg1 target:(id)arg2 title:(id)arg3 accessoryType:(long long)arg4; 31 | + (id)switchCellForSel:(SEL)arg1 target:(id)arg2 title:(id)arg3 on:(_Bool)arg4; 32 | + (id)normalCellForSel:(SEL)arg1 target:(id)arg2 title:(id)arg3 rightValue:(id)arg4 accessoryType:(long long)arg5; 33 | + (id)normalCellForTitle:(id)arg1 rightValue:(id)arg2; 34 | 35 | @end 36 | 37 | @interface NewSettingViewController: UINavigationController 38 | 39 | - (void)reloadTableData; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Tweaks/Settings.xm: -------------------------------------------------------------------------------- 1 | #import "Settings.h" 2 | 3 | %hook NewSettingViewController 4 | 5 | - (void)reloadTableData { 6 | %orig; 7 | 8 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 9 | BOOL isAutoRedEnvelopes = [userDefaults boolForKey:@"WeChatTweakAutoRedEnvelopesKey"]; 10 | BOOL isAutoRedEnvelopesKeepRunning = [userDefaults boolForKey:@"WeChatTweakAutoRedEnvelopesKeepRunningKey"]; 11 | BOOL isAutoRedEnvelopesDelayRandomly = [userDefaults boolForKey:@"WeChatTweakAutoRedEnvelopesDelayRandomlyKey"]; 12 | BOOL isAutoRedEnvelopesFromMe = [userDefaults boolForKey:@"WeChatTweakAutoRedEnvelopesFromMeKey"]; 13 | CGFloat delaySeconds = [userDefaults doubleForKey:@"WeChatTweakAutoRedEnvelopesDelaySecondsKey"]; 14 | NSUInteger customStepCount = [userDefaults integerForKey:@"WeChatTweakCustomStepCountKey"]; 15 | NSString *delaySecondsString = delaySeconds == 0 ? @"不延迟" : [NSString stringWithFormat:@"%.2f 秒", delaySeconds]; 16 | NSString *customStepCountString = customStepCount == 0 ? @"不设置" : [NSString stringWithFormat:@"%@ 步", @(customStepCount)]; 17 | 18 | // AutoRedEnvelopes Section 19 | MMTableViewSectionInfo *autoRedEnvelopesSectionInfo = [%c(MMTableViewSectionInfo) sectionInfoHeader:@"自动抢红包"]; 20 | MMTableViewCellInfo *autoRedEnvelopesCellInfo = [%c(MMTableViewCellInfo) switchCellForSel:@selector(switchAutoRedEnvelopes:) target:self title:@"自动抢红包" on:isAutoRedEnvelopes]; 21 | MMTableViewCellInfo *autoRedEnvelopesKeepRunningCellInfo = [%c(MMTableViewCellInfo) switchCellForSel:@selector(switchAutoRedEnvelopesKeepRunning:) target:self title:@"后台运行" on:isAutoRedEnvelopesKeepRunning]; 22 | MMTableViewCellInfo *autoRedEnvelopesFromMeCellInfo = [%c(MMTableViewCellInfo) switchCellForSel:@selector(switchAutoRedEnvelopesFromMe:) target:self title:@"抢自己发出的" on:isAutoRedEnvelopesFromMe]; 23 | MMTableViewCellInfo *autoRedEnvelopesDelayRandomlyCellInfo = [%c(MMTableViewCellInfo) switchCellForSel:@selector(switchAutoRedEnvelopesDelayRandomly:) target:self title:@"随机延迟" on:isAutoRedEnvelopesDelayRandomly]; 24 | MMTableViewCellInfo *autoRedEnvelopesDelaySecondsCellInfo = [%c(MMTableViewCellInfo) normalCellForSel:@selector(setAutoRedEnvelopesDelay) target:self title:@"自动抢红包延迟" rightValue:delaySecondsString accessoryType:1]; 25 | [autoRedEnvelopesSectionInfo addCell:autoRedEnvelopesCellInfo]; 26 | [autoRedEnvelopesSectionInfo addCell:isAutoRedEnvelopes ? autoRedEnvelopesKeepRunningCellInfo : nil]; 27 | [autoRedEnvelopesSectionInfo addCell:isAutoRedEnvelopes ? autoRedEnvelopesFromMeCellInfo : nil]; 28 | [autoRedEnvelopesSectionInfo addCell:isAutoRedEnvelopes ? autoRedEnvelopesDelayRandomlyCellInfo : nil]; 29 | [autoRedEnvelopesSectionInfo addCell:isAutoRedEnvelopes ? autoRedEnvelopesDelaySecondsCellInfo : nil]; 30 | 31 | // OtherSettings Section 32 | MMTableViewSectionInfo *otherSettingsSectionInfo = [%c(MMTableViewSectionInfo) sectionInfoHeader:@"其它设置"]; 33 | MMTableViewCellInfo *customStepCountCellInfo = [%c(MMTableViewCellInfo) normalCellForSel:@selector(setCustomStepCount) target:self title:@"自定义步数" rightValue:customStepCountString accessoryType:1]; 34 | [otherSettingsSectionInfo addCell:customStepCountCellInfo]; 35 | 36 | // Reload Data 37 | MMTableViewInfo *tableViewInfo = MSHookIvar(self, "m_tableViewInfo"); 38 | [tableViewInfo insertSection:autoRedEnvelopesSectionInfo At:0]; 39 | [tableViewInfo insertSection:otherSettingsSectionInfo At:1]; 40 | [[tableViewInfo getTableView] reloadData]; 41 | } 42 | 43 | %new 44 | - (void)switchAutoRedEnvelopes:(UISwitch *)sender { 45 | [[NSUserDefaults standardUserDefaults] setBool:sender.on forKey:@"WeChatTweakAutoRedEnvelopesKey"]; 46 | [self reloadTableData]; 47 | } 48 | 49 | %new 50 | - (void)switchAutoRedEnvelopesKeepRunning:(UISwitch *)sender { 51 | [[NSUserDefaults standardUserDefaults] setBool:sender.on forKey:@"WeChatTweakAutoRedEnvelopesKeepRunningKey"]; 52 | [self reloadTableData]; 53 | } 54 | 55 | %new 56 | - (void)switchAutoRedEnvelopesFromMe:(UISwitch *)sender { 57 | [[NSUserDefaults standardUserDefaults] setBool:sender.on forKey:@"WeChatTweakAutoRedEnvelopesFromMeKey"]; 58 | [self reloadTableData]; 59 | } 60 | 61 | %new 62 | - (void)switchAutoRedEnvelopesDelayRandomly:(UISwitch *)sender { 63 | [[NSUserDefaults standardUserDefaults] setBool:sender.on forKey:@"WeChatTweakAutoRedEnvelopesDelayRandomlyKey"]; 64 | [self reloadTableData]; 65 | } 66 | 67 | %new 68 | - (void)setAutoRedEnvelopesDelay { 69 | UIAlertView *alertView = [[UIAlertView alloc] init]; 70 | alertView.alertViewStyle = UIAlertViewStylePlainTextInput; 71 | alertView.delegate = self; 72 | alertView.title = @"设置延迟"; 73 | alertView.tag = 0; 74 | [alertView addButtonWithTitle:@"取消"]; 75 | [alertView addButtonWithTitle:@"确定"]; 76 | [alertView textFieldAtIndex:0].placeholder = @"输入延迟秒数"; 77 | [alertView textFieldAtIndex:0].keyboardType = UIKeyboardTypeDecimalPad; 78 | [alertView show]; 79 | } 80 | 81 | %new 82 | - (void)setCustomStepCount { 83 | UIAlertView *alertView = [[UIAlertView alloc] init]; 84 | alertView.alertViewStyle = UIAlertViewStylePlainTextInput; 85 | alertView.delegate = self; 86 | alertView.title = @"设置步数"; 87 | alertView.tag = 1; 88 | [alertView addButtonWithTitle:@"取消"]; 89 | [alertView addButtonWithTitle:@"确定"]; 90 | [alertView textFieldAtIndex:0].placeholder = @"输入自定义步数"; 91 | [alertView textFieldAtIndex:0].keyboardType = UIKeyboardTypeNumberPad; 92 | [alertView show]; 93 | } 94 | 95 | %new 96 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 97 | if (alertView.tag == 0) { 98 | // 设置自动抢红包延迟 99 | if (buttonIndex == 1) { 100 | CGFloat delaySeconds = [[alertView textFieldAtIndex:0].text doubleValue]; 101 | [[NSUserDefaults standardUserDefaults] setFloat:delaySeconds forKey:@"WeChatTweakAutoRedEnvelopesDelaySecondsKey"]; 102 | } 103 | } else if (alertView.tag == 1) { 104 | // 设置自定义步数 105 | if (buttonIndex == 1) { 106 | NSUInteger customStepCount = [[alertView textFieldAtIndex:0].text integerValue]; 107 | [[NSUserDefaults standardUserDefaults] setInteger:customStepCount forKey:@"WeChatTweakCustomStepCountKey"]; 108 | } 109 | } 110 | [self reloadTableData]; 111 | } 112 | 113 | %end 114 | -------------------------------------------------------------------------------- /WeChatTweak.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.tencent.xin" ); }; } 2 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: net.sunnyyoung.WeChatTweak 2 | Name: WeChatTweak 3 | Depends: mobilesubstrate 4 | Version: 1.0.0 5 | Architecture: iphoneos-arm 6 | Description: A tweak for WeChat iOS. 7 | Maintainer: Sunnyyoung 8 | Author: Sunnyyoung 9 | Section: Tweaks 10 | --------------------------------------------------------------------------------