├── .DS_Store ├── LICENSE ├── Other ├── .DS_Store ├── Install.sh ├── Products │ ├── .DS_Store │ └── Debug │ │ ├── .DS_Store │ │ └── WeChatPlugin.framework │ │ ├── Headers │ │ └── WeChatPlugin.h │ │ ├── Modules │ │ └── module.modulemap │ │ ├── Resources │ │ ├── Info.plist │ │ ├── MMStatusCell.nib │ │ ├── MMStatusImageMediaView.nib │ │ ├── MMStatusLinkMediaView.nib │ │ ├── MMTimeLineViewController.nib │ │ ├── TKAutoReplyWindowController.nib │ │ ├── TKRemoteControlCommands.plist │ │ ├── TKRemoteControlScript.scpt │ │ ├── TKRemoteControlWindowController.nib │ │ ├── Tabbar-TimeLine-HI@2x.png │ │ ├── Tabbar-TimeLine-Selected-HI@2x.png │ │ ├── Tabbar-TimeLine-Selected@2x.png │ │ ├── Tabbar-TimeLine@2x.png │ │ ├── comment_icon_highlighted@2x.png │ │ ├── comment_icon_normal@2x.png │ │ ├── en.lproj │ │ │ └── Localizable.strings │ │ ├── like_icon_highlighted@2x.png │ │ ├── like_icon_normal@2x.png │ │ ├── link_icon@2x.png │ │ ├── time_icon@2x.png │ │ └── zh-Hans.lproj │ │ │ └── Localizable.strings │ │ ├── Versions │ │ ├── A │ │ │ ├── Headers │ │ │ │ └── WeChatPlugin.h │ │ │ ├── Modules │ │ │ │ └── module.modulemap │ │ │ ├── Resources │ │ │ │ ├── Info.plist │ │ │ │ ├── MMStatusCell.nib │ │ │ │ ├── MMStatusImageMediaView.nib │ │ │ │ ├── MMStatusLinkMediaView.nib │ │ │ │ ├── MMTimeLineViewController.nib │ │ │ │ ├── TKAutoReplyWindowController.nib │ │ │ │ ├── TKRemoteControlCommands.plist │ │ │ │ ├── TKRemoteControlScript.scpt │ │ │ │ ├── TKRemoteControlWindowController.nib │ │ │ │ ├── Tabbar-TimeLine-HI@2x.png │ │ │ │ ├── Tabbar-TimeLine-Selected-HI@2x.png │ │ │ │ ├── Tabbar-TimeLine-Selected@2x.png │ │ │ │ ├── Tabbar-TimeLine@2x.png │ │ │ │ ├── comment_icon_highlighted@2x.png │ │ │ │ ├── comment_icon_normal@2x.png │ │ │ │ ├── en.lproj │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── like_icon_highlighted@2x.png │ │ │ │ ├── like_icon_normal@2x.png │ │ │ │ ├── link_icon@2x.png │ │ │ │ ├── time_icon@2x.png │ │ │ │ └── zh-Hans.lproj │ │ │ │ │ └── Localizable.strings │ │ │ └── WeChatPlugin │ │ └── Current │ │ │ ├── Headers │ │ │ └── WeChatPlugin.h │ │ │ ├── Modules │ │ │ └── module.modulemap │ │ │ ├── Resources │ │ │ ├── Info.plist │ │ │ ├── MMStatusCell.nib │ │ │ ├── MMStatusImageMediaView.nib │ │ │ ├── MMStatusLinkMediaView.nib │ │ │ ├── MMTimeLineViewController.nib │ │ │ ├── TKAutoReplyWindowController.nib │ │ │ ├── TKRemoteControlCommands.plist │ │ │ ├── TKRemoteControlScript.scpt │ │ │ ├── TKRemoteControlWindowController.nib │ │ │ ├── Tabbar-TimeLine-HI@2x.png │ │ │ ├── Tabbar-TimeLine-Selected-HI@2x.png │ │ │ ├── Tabbar-TimeLine-Selected@2x.png │ │ │ ├── Tabbar-TimeLine@2x.png │ │ │ ├── comment_icon_highlighted@2x.png │ │ │ ├── comment_icon_normal@2x.png │ │ │ ├── en.lproj │ │ │ │ └── Localizable.strings │ │ │ ├── like_icon_highlighted@2x.png │ │ │ ├── like_icon_normal@2x.png │ │ │ ├── link_icon@2x.png │ │ │ ├── time_icon@2x.png │ │ │ └── zh-Hans.lproj │ │ │ │ └── Localizable.strings │ │ │ └── WeChatPlugin │ │ └── WeChatPlugin ├── Screenshots │ ├── .DS_Store │ └── wechatplugin.png ├── Uninstall.sh └── insert_dylib ├── README.md ├── WeChatPlugin.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── TK.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── linden.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── timeaside.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── TK.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── WeChatPlugin.xcscheme │ │ └── xcschememanagement.plist │ ├── linden.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── WeChatPlugin.xcscheme │ │ └── xcschememanagement.plist │ └── timeaside.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── WeChatPlugin.xcscheme │ └── xcschememanagement.plist └── WeChatPlugin ├── .DS_Store ├── Info.plist ├── Sources ├── .DS_Store ├── Category │ ├── .DS_Store │ ├── MMChatsTableCellView+Hook.h │ ├── MMChatsTableCellView+Hook.m │ ├── NSDate+StatusTimeDescription.h │ ├── NSDate+StatusTimeDescription.m │ ├── NSObject+ObjectMap.h │ ├── NSObject+ObjectMap.m │ ├── NSString+XMLDictionary.h │ ├── NSString+XMLDictionary.m │ ├── NSViewController+Hook.h │ ├── NSViewController+Hook.m │ ├── WeChat+Hook.h │ └── WeChat+Hook.m ├── Common │ ├── Category │ │ ├── NSButton+Action.h │ │ ├── NSButton+Action.m │ │ ├── NSTextField+Action.h │ │ ├── NSTextField+Action.m │ │ ├── NSView+Action.h │ │ └── NSView+Action.m │ ├── Color.h │ └── TKPrefixHeader.pch ├── Config │ ├── TKWeChatPluginConfig.h │ └── TKWeChatPluginConfig.m ├── Controllers │ ├── TKRemoteControlController.h │ └── TKRemoteControlController.m ├── Image │ ├── .DS_Store │ ├── Tabbar-TimeLine-HI@2x.png │ ├── Tabbar-TimeLine-Selected-HI@2x.png │ ├── Tabbar-TimeLine-Selected@2x.png │ ├── Tabbar-TimeLine@2x.png │ ├── comment_icon_highlighted@2x.png │ ├── comment_icon_normal@2x.png │ ├── like_icon_highlighted@2x.png │ ├── like_icon_normal@2x.png │ ├── link_icon@2x.png │ └── time_icon@2x.png ├── JRSwizzle │ ├── JRSwizzle.h │ └── JRSwizzle.m ├── Models │ ├── TKAutoReplyModel.h │ ├── TKAutoReplyModel.m │ ├── TKBaseModel.h │ ├── TKBaseModel.m │ ├── TKIgnoreSessonModel.h │ ├── TKIgnoreSessonModel.m │ ├── TKRemoteControlModel.h │ └── TKRemoteControlModel.m ├── Status │ ├── .DS_Store │ ├── Model │ │ ├── .DS_Store │ │ ├── MMStatus.h │ │ ├── MMStatus.m │ │ ├── MMStatusImageMediaObject.h │ │ ├── MMStatusImageMediaObject.m │ │ ├── MMStatusLinkMediaObject.h │ │ ├── MMStatusLinkMediaObject.m │ │ ├── MMStatusMediaObject.h │ │ └── MMStatusMediaObject.m │ └── View │ │ ├── .DS_Store │ │ ├── MMStatusCell.h │ │ ├── MMStatusCell.m │ │ ├── MMStatusCell.xib │ │ ├── MMStatusCellDelegate.h │ │ ├── MMStatusImageMediaView.h │ │ ├── MMStatusImageMediaView.m │ │ ├── MMStatusImageMediaView.xib │ │ ├── MMStatusImagePreviewView.h │ │ ├── MMStatusImagePreviewView.m │ │ ├── MMStatusLinkMediaView.h │ │ ├── MMStatusLinkMediaView.m │ │ ├── MMStatusLinkMediaView.xib │ │ ├── MMStatusMediaView.h │ │ └── MMStatusMediaView.m ├── TimeLine │ ├── .DS_Store │ ├── Controller │ │ ├── .DS_Store │ │ ├── MMTimeLineMainViewController.h │ │ ├── MMTimeLineViewController.h │ │ └── MMTimeLineViewController.m │ ├── Mgr │ │ ├── .DS_Store │ │ ├── MMTimeLineMgr.h │ │ ├── MMTimeLineMgr.m │ │ └── MMTimeLineMgrDelegate.h │ └── View │ │ ├── .DS_Store │ │ └── MMTimeLineViewController.xib ├── Utils │ ├── .DS_Store │ ├── TKHelper.h │ ├── TKHelper.m │ ├── XMLReader.h │ └── XMLReader.m ├── Vendor │ ├── fishhook.c │ └── fishhook.h ├── Views │ ├── AutoReply │ │ ├── TKAutoReplyCell.h │ │ ├── TKAutoReplyCell.m │ │ ├── TKAutoReplyContentView.h │ │ └── TKAutoReplyContentView.m │ └── RemoteControl │ │ ├── TKRemoteControlCell.h │ │ └── TKRemoteControlCell.m └── WindowControllers │ ├── AutoReply │ ├── TKAutoReplyWindowController.h │ ├── TKAutoReplyWindowController.m │ └── TKAutoReplyWindowController.xib │ └── RemoteControl │ ├── TKRemoteControlWindowController.h │ ├── TKRemoteControlWindowController.m │ └── TKRemoteControlWindowController.xib ├── TKRemoteControlCommands.plist ├── TKRemoteControlScript.scpt ├── WeChatPlugin.h ├── en.lproj └── Localizable.strings ├── main.mm └── zh-Hans.lproj └── Localizable.strings /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/.DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Loveletter 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 | -------------------------------------------------------------------------------- /Other/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/.DS_Store -------------------------------------------------------------------------------- /Other/Install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | app_name="WeChat" 4 | shell_path="$(dirname "$0")" 5 | wechat_path="/Applications/WeChat.app" 6 | framework_name="WeChatPlugin" 7 | app_bundle_path="/Applications/${app_name}.app/Contents/MacOS" 8 | app_executable_path="${app_bundle_path}/${app_name}" 9 | app_executable_backup_path="${app_executable_path}_backup" 10 | framework_path="${app_bundle_path}/${framework_name}.framework" 11 | 12 | # 对 WeChat 赋予权限 13 | if [ ! -w "$wechat_path" ] 14 | then 15 | echo -e "\n\n为了将小助手写入微信, 请输入密码 : " 16 | sudo chown -R $(whoami) "$wechat_path" 17 | fi 18 | 19 | # 备份 WeChat 原始可执行文件 20 | if [ ! -f "$app_executable_backup_path" ] 21 | then 22 | cp "$app_executable_path" "$app_executable_backup_path" 23 | result="y" 24 | else 25 | read -t 150 -p "已安装微信小助手,是否覆盖?[y/n]:" result 26 | fi 27 | 28 | if [[ "$result" == 'y' ]]; then 29 | cp -r "${shell_path}/Products/Debug/${framework_name}.framework" ${app_bundle_path} 30 | ${shell_path}/insert_dylib --all-yes "${framework_path}/${framework_name}" "$app_executable_backup_path" "$app_executable_path" 31 | fi 32 | -------------------------------------------------------------------------------- /Other/Products/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/.DS_Store -------------------------------------------------------------------------------- /Other/Products/Debug/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/.DS_Store -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module WeChatPlugin { 2 | umbrella header "WeChatPlugin.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 17D47 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | WeChatPlugin 11 | CFBundleIdentifier 12 | Net.CodeTips.WeChatPlugin 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | WeChatPlugin 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSupportedPlatforms 22 | 23 | MacOSX 24 | 25 | CFBundleVersion 26 | 1 27 | DTCompiler 28 | com.apple.compilers.llvm.clang.1_0 29 | DTPlatformBuild 30 | 9C40b 31 | DTPlatformVersion 32 | GM 33 | DTSDKBuild 34 | 17C76 35 | DTSDKName 36 | macosx10.13 37 | DTXcode 38 | 0920 39 | DTXcodeBuild 40 | 9C40b 41 | NSHumanReadableCopyright 42 | Copyright © 2018年 CodeTips. All rights reserved. 43 | 44 | 45 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/MMStatusCell.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/MMStatusCell.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/MMStatusImageMediaView.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/MMStatusImageMediaView.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/MMStatusLinkMediaView.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/MMStatusLinkMediaView.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/MMTimeLineViewController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/MMTimeLineViewController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/TKAutoReplyWindowController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/TKAutoReplyWindowController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlCommands.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | executeCommand 8 | open /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app || open /System/Library/CoreServices/ScreenSaverEngine.app 9 | keyword 10 | ScreenSave 11 | function 12 | 屏幕保护 13 | enable 14 | 15 | command 16 | #remote.screensaver 17 | 18 | 19 | executeCommand 20 | /System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend 21 | keyword 22 | LockScreen 23 | function 24 | 锁屏 25 | enable 26 | 27 | command 28 | #remote.lockscreen 29 | 30 | 31 | executeCommand 32 | sleep 33 | keyword 34 | Sleep 35 | function 36 | 休眠 37 | enable 38 | 39 | command 40 | #remote.sleep 41 | 42 | 43 | executeCommand 44 | shutdown 45 | keyword 46 | Shutdown 47 | function 48 | 关机 49 | enable 50 | 51 | command 52 | #remote.shutdown 53 | 54 | 55 | executeCommand 56 | restart 57 | keyword 58 | Restart 59 | function 60 | 重启 61 | enable 62 | 63 | command 64 | #remote.restart 65 | 66 | 67 | executeCommand 68 | empty 69 | keyword 70 | EmptyTrash 71 | function 72 | 清空废纸篓 73 | enable 74 | 75 | command 76 | #remote.emptytrash 77 | 78 | 79 | 80 | 81 | executeCommand 82 | killQQ 83 | keyword 84 | KillQQ 85 | function 86 | 退出 QQ 87 | enable 88 | 89 | 90 | 91 | executeCommand 92 | killWeChat 93 | keyword 94 | KillWeChat 95 | function 96 | 退出 WeChat 97 | enable 98 | 99 | 100 | 101 | executeCommand 102 | killChrome 103 | keyword 104 | KillChrome 105 | function 106 | 退出 Chrome 107 | enable 108 | 109 | 110 | 111 | executeCommand 112 | killSafari 113 | keyword 114 | KillSafari 115 | function 116 | 退出 Safari 117 | enable 118 | 119 | 120 | 121 | executeCommand 122 | killAll 123 | keyword 124 | KillAll 125 | function 126 | 退出所有程序 127 | enable 128 | 129 | 130 | 131 | 132 | 133 | executeCommand 134 | musicToggle 135 | keyword 136 | Toggle 137 | function 138 | 播放/暂停 139 | enable 140 | 141 | 142 | 143 | executeCommand 144 | musicNext 145 | keyword 146 | Next 147 | function 148 | 下一首 149 | enable 150 | 151 | 152 | 153 | executeCommand 154 | musicPrevious 155 | keyword 156 | Previous 157 | function 158 | 上一首 159 | enable 160 | 161 | 162 | 163 | executeCommand 164 | musicVolumeUp 165 | keyword 166 | VolumeUp 167 | function 168 | 增大音量 169 | enable 170 | 171 | 172 | 173 | executeCommand 174 | musicVolumeDown 175 | keyword 176 | VolumeDown 177 | function 178 | 减小音量 179 | enable 180 | 181 | 182 | 183 | executeCommand 184 | musicLike 185 | keyword 186 | LikeChange 187 | function 188 | 喜欢/取消喜欢 189 | enable 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlWindowController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlWindowController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine-HI@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine-Selected-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine-Selected-HI@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine-Selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine-Selected@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/Tabbar-TimeLine@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/comment_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/comment_icon_highlighted@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/comment_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/comment_icon_normal@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/like_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/like_icon_highlighted@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/like_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/like_icon_normal@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/link_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/link_icon@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/time_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/time_icon@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/Localizable.strings -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module WeChatPlugin { 2 | umbrella header "WeChatPlugin.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 17D47 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | WeChatPlugin 11 | CFBundleIdentifier 12 | Net.CodeTips.WeChatPlugin 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | WeChatPlugin 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSupportedPlatforms 22 | 23 | MacOSX 24 | 25 | CFBundleVersion 26 | 1 27 | DTCompiler 28 | com.apple.compilers.llvm.clang.1_0 29 | DTPlatformBuild 30 | 9C40b 31 | DTPlatformVersion 32 | GM 33 | DTSDKBuild 34 | 17C76 35 | DTSDKName 36 | macosx10.13 37 | DTXcode 38 | 0920 39 | DTXcodeBuild 40 | 9C40b 41 | NSHumanReadableCopyright 42 | Copyright © 2018年 CodeTips. All rights reserved. 43 | 44 | 45 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMStatusCell.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMStatusCell.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMStatusImageMediaView.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMStatusImageMediaView.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMStatusLinkMediaView.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMStatusLinkMediaView.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMTimeLineViewController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/MMTimeLineViewController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKAutoReplyWindowController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKAutoReplyWindowController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlCommands.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | executeCommand 8 | open /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app || open /System/Library/CoreServices/ScreenSaverEngine.app 9 | keyword 10 | ScreenSave 11 | function 12 | 屏幕保护 13 | enable 14 | 15 | command 16 | #remote.screensaver 17 | 18 | 19 | executeCommand 20 | /System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend 21 | keyword 22 | LockScreen 23 | function 24 | 锁屏 25 | enable 26 | 27 | command 28 | #remote.lockscreen 29 | 30 | 31 | executeCommand 32 | sleep 33 | keyword 34 | Sleep 35 | function 36 | 休眠 37 | enable 38 | 39 | command 40 | #remote.sleep 41 | 42 | 43 | executeCommand 44 | shutdown 45 | keyword 46 | Shutdown 47 | function 48 | 关机 49 | enable 50 | 51 | command 52 | #remote.shutdown 53 | 54 | 55 | executeCommand 56 | restart 57 | keyword 58 | Restart 59 | function 60 | 重启 61 | enable 62 | 63 | command 64 | #remote.restart 65 | 66 | 67 | executeCommand 68 | empty 69 | keyword 70 | EmptyTrash 71 | function 72 | 清空废纸篓 73 | enable 74 | 75 | command 76 | #remote.emptytrash 77 | 78 | 79 | 80 | 81 | executeCommand 82 | killQQ 83 | keyword 84 | KillQQ 85 | function 86 | 退出 QQ 87 | enable 88 | 89 | 90 | 91 | executeCommand 92 | killWeChat 93 | keyword 94 | KillWeChat 95 | function 96 | 退出 WeChat 97 | enable 98 | 99 | 100 | 101 | executeCommand 102 | killChrome 103 | keyword 104 | KillChrome 105 | function 106 | 退出 Chrome 107 | enable 108 | 109 | 110 | 111 | executeCommand 112 | killSafari 113 | keyword 114 | KillSafari 115 | function 116 | 退出 Safari 117 | enable 118 | 119 | 120 | 121 | executeCommand 122 | killAll 123 | keyword 124 | KillAll 125 | function 126 | 退出所有程序 127 | enable 128 | 129 | 130 | 131 | 132 | 133 | executeCommand 134 | musicToggle 135 | keyword 136 | Toggle 137 | function 138 | 播放/暂停 139 | enable 140 | 141 | 142 | 143 | executeCommand 144 | musicNext 145 | keyword 146 | Next 147 | function 148 | 下一首 149 | enable 150 | 151 | 152 | 153 | executeCommand 154 | musicPrevious 155 | keyword 156 | Previous 157 | function 158 | 上一首 159 | enable 160 | 161 | 162 | 163 | executeCommand 164 | musicVolumeUp 165 | keyword 166 | VolumeUp 167 | function 168 | 增大音量 169 | enable 170 | 171 | 172 | 173 | executeCommand 174 | musicVolumeDown 175 | keyword 176 | VolumeDown 177 | function 178 | 减小音量 179 | enable 180 | 181 | 182 | 183 | executeCommand 184 | musicLike 185 | keyword 186 | LikeChange 187 | function 188 | 喜欢/取消喜欢 189 | enable 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlScript.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlScript.scpt -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlWindowController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlWindowController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine-HI@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine-Selected-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine-Selected-HI@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine-Selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine-Selected@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Tabbar-TimeLine@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/comment_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/comment_icon_highlighted@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/comment_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/comment_icon_normal@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/like_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/like_icon_highlighted@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/like_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/like_icon_normal@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/link_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/link_icon@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/time_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/time_icon@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module WeChatPlugin { 2 | umbrella header "WeChatPlugin.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 17D47 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | WeChatPlugin 11 | CFBundleIdentifier 12 | Net.CodeTips.WeChatPlugin 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | WeChatPlugin 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSupportedPlatforms 22 | 23 | MacOSX 24 | 25 | CFBundleVersion 26 | 1 27 | DTCompiler 28 | com.apple.compilers.llvm.clang.1_0 29 | DTPlatformBuild 30 | 9C40b 31 | DTPlatformVersion 32 | GM 33 | DTSDKBuild 34 | 17C76 35 | DTSDKName 36 | macosx10.13 37 | DTXcode 38 | 0920 39 | DTXcodeBuild 40 | 9C40b 41 | NSHumanReadableCopyright 42 | Copyright © 2018年 CodeTips. All rights reserved. 43 | 44 | 45 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMStatusCell.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMStatusCell.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMStatusImageMediaView.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMStatusImageMediaView.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMStatusLinkMediaView.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMStatusLinkMediaView.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMTimeLineViewController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/MMTimeLineViewController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKAutoReplyWindowController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKAutoReplyWindowController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlCommands.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | executeCommand 8 | open /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app || open /System/Library/CoreServices/ScreenSaverEngine.app 9 | keyword 10 | ScreenSave 11 | function 12 | 屏幕保护 13 | enable 14 | 15 | command 16 | #remote.screensaver 17 | 18 | 19 | executeCommand 20 | /System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend 21 | keyword 22 | LockScreen 23 | function 24 | 锁屏 25 | enable 26 | 27 | command 28 | #remote.lockscreen 29 | 30 | 31 | executeCommand 32 | sleep 33 | keyword 34 | Sleep 35 | function 36 | 休眠 37 | enable 38 | 39 | command 40 | #remote.sleep 41 | 42 | 43 | executeCommand 44 | shutdown 45 | keyword 46 | Shutdown 47 | function 48 | 关机 49 | enable 50 | 51 | command 52 | #remote.shutdown 53 | 54 | 55 | executeCommand 56 | restart 57 | keyword 58 | Restart 59 | function 60 | 重启 61 | enable 62 | 63 | command 64 | #remote.restart 65 | 66 | 67 | executeCommand 68 | empty 69 | keyword 70 | EmptyTrash 71 | function 72 | 清空废纸篓 73 | enable 74 | 75 | command 76 | #remote.emptytrash 77 | 78 | 79 | 80 | 81 | executeCommand 82 | killQQ 83 | keyword 84 | KillQQ 85 | function 86 | 退出 QQ 87 | enable 88 | 89 | 90 | 91 | executeCommand 92 | killWeChat 93 | keyword 94 | KillWeChat 95 | function 96 | 退出 WeChat 97 | enable 98 | 99 | 100 | 101 | executeCommand 102 | killChrome 103 | keyword 104 | KillChrome 105 | function 106 | 退出 Chrome 107 | enable 108 | 109 | 110 | 111 | executeCommand 112 | killSafari 113 | keyword 114 | KillSafari 115 | function 116 | 退出 Safari 117 | enable 118 | 119 | 120 | 121 | executeCommand 122 | killAll 123 | keyword 124 | KillAll 125 | function 126 | 退出所有程序 127 | enable 128 | 129 | 130 | 131 | 132 | 133 | executeCommand 134 | musicToggle 135 | keyword 136 | Toggle 137 | function 138 | 播放/暂停 139 | enable 140 | 141 | 142 | 143 | executeCommand 144 | musicNext 145 | keyword 146 | Next 147 | function 148 | 下一首 149 | enable 150 | 151 | 152 | 153 | executeCommand 154 | musicPrevious 155 | keyword 156 | Previous 157 | function 158 | 上一首 159 | enable 160 | 161 | 162 | 163 | executeCommand 164 | musicVolumeUp 165 | keyword 166 | VolumeUp 167 | function 168 | 增大音量 169 | enable 170 | 171 | 172 | 173 | executeCommand 174 | musicVolumeDown 175 | keyword 176 | VolumeDown 177 | function 178 | 减小音量 179 | enable 180 | 181 | 182 | 183 | executeCommand 184 | musicLike 185 | keyword 186 | LikeChange 187 | function 188 | 喜欢/取消喜欢 189 | enable 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlScript.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlScript.scpt -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlWindowController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlWindowController.nib -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine-HI@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine-Selected-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine-Selected-HI@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine-Selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine-Selected@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Tabbar-TimeLine@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/comment_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/comment_icon_highlighted@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/comment_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/comment_icon_normal@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/like_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/like_icon_highlighted@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/like_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/like_icon_normal@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/link_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/link_icon@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/time_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/time_icon@2x.png -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/Localizable.strings -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin -------------------------------------------------------------------------------- /Other/Products/Debug/WeChatPlugin.framework/WeChatPlugin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Products/Debug/WeChatPlugin.framework/WeChatPlugin -------------------------------------------------------------------------------- /Other/Screenshots/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Screenshots/.DS_Store -------------------------------------------------------------------------------- /Other/Screenshots/wechatplugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/Screenshots/wechatplugin.png -------------------------------------------------------------------------------- /Other/Uninstall.sh: -------------------------------------------------------------------------------- 1 | # !/bin/bash 2 | 3 | app_name="WeChat" 4 | framework_name="WeChatPlugin" 5 | app_bundle_path="/Applications/${app_name}.app/Contents/MacOS" 6 | app_executable_path="${app_bundle_path}/${app_name}" 7 | app_executable_backup_path="${app_executable_path}_backup" 8 | framework_path="${app_bundle_path}/${framework_name}.framework" 9 | # 备份WeChat原始可执行文件 10 | if [ -f "$app_executable_backup_path" ] 11 | then 12 | rm "$app_executable_path" 13 | rm -rf "$framework_path" 14 | mv "$app_executable_backup_path" "$app_executable_path" 15 | echo "\n\t卸载成功" 16 | else 17 | echo "\n\t未发现微信小助手" 18 | fi 19 | -------------------------------------------------------------------------------- /Other/insert_dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/Other/insert_dylib -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WeChatPlugin-macOS 2 | 3 | ![platform](https://img.shields.io/badge/platform-macos-lightgrey.svg) [![GitHub license](https://img.shields.io/github/license/CodeTips/WeChatPlugin-macOS.svg)](https://github.com/CodeTips/WeChatPlugin-macOS/blob/master/LICENSE) 4 | 5 | 6 | 7 | ### 说明 8 | 9 | * 包含功能: 自动回复、消息防撤回、远程控制、微信多开、会话置底、免认证登录、窗口置顶、会话多选删除、通知快捷回复、浏览朋友圈。 10 | * 部分功能基于[WeChatPlugin-MacOS](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS)开发,远程控制功能增强,配合[WeChatPlugin-iOS](https://github.com/CodeTips/WeChatPlugin-iOS)和越狱插件[WeChatPlugin](https://github.com/CodeTips/WeChatPlugin)可实现一键锁屏、关机等功能。菜单显示优化,本地化支持。原作者(**TK**)关键字去除,***个人强迫症***。 11 | * 朋友圈功能基于[WeChatPlugin](https://github.com/Natoto/WeChatPlugin)开发,优化图片显示逻辑,修复刷新导致显示异常的问题。目前最新版微信已经不支持。 12 | * 若使用中遇到遇到问题,请去以上提到的项目找解决方案,或者 **Issue me!** 13 | 14 | ### 依赖 15 | 16 | * [XMLReader](https://github.com/amarcadet/XMLReader) 17 | * [insert_dylib](https://github.com/Tyilo/insert_dylib) 18 | * [fishhook](https://github.com/facebook/fishhook) 19 | 20 | ### 最后 21 | * 使用愉快~ 22 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/TK.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/TK.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/linden.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/linden.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/timeaside.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/timeaside.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/TK.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/TK.xcuserdatad/xcschemes/WeChatPlugin.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 70 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/TK.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WeChatPlugin.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 528B4F911EA7383800BC6A89 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/linden.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/linden.xcuserdatad/xcschemes/WeChatPlugin.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 50 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/linden.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WeChatPlugin.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 528B4F911EA7383800BC6A89 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/timeaside.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/timeaside.xcuserdatad/xcschemes/WeChatPlugin.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 50 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /WeChatPlugin.xcodeproj/xcuserdata/timeaside.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WeChatPlugin.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 528B4F911EA7383800BC6A89 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WeChatPlugin/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2018年 CodeTips. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Category/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/MMChatsTableCellView+Hook.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMChatsTableCellView+hook.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/15. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (MMChatsTableCellViewHook) 12 | 13 | + (void)hookMMChatsTableCellView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/NSDate+StatusTimeDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+StatusTimeDescription.h 3 | // MacWeChatTimeLinePlugin 4 | // 5 | // Created by nato on 2017/3/17. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDate (StatusTimeDescription) 12 | 13 | - (NSString *)statusTimeDescription; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/NSDate+StatusTimeDescription.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+StatusTimeDescription.m 3 | // MacWeChatTimeLinePlugin 4 | // 5 | // Created by nato on 2017/3/17. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "NSDate+StatusTimeDescription.h" 10 | 11 | @implementation NSDate (StatusTimeDescription) 12 | 13 | - (NSString *)statusTimeDescription { 14 | NSCalendar *calendar = [NSCalendar currentCalendar]; 15 | NSString *res = [[NSString stringWithFormat:@"%@", [self dateByAddingTimeInterval:8 * 60 * 60]] substringToIndex:19]; 16 | if ([calendar isDateInToday:self]) { 17 | return [res substringFromIndex:11]; 18 | } 19 | else { 20 | NSString *year = [res substringToIndex:4]; 21 | if ([[NSString stringWithFormat:@"%@", [NSDate dateWithTimeIntervalSinceNow:8 * 60 * 60]] hasPrefix:year]) { 22 | return [res substringFromIndex:5]; 23 | } 24 | else { 25 | return res; 26 | } 27 | } 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/NSObject+ObjectMap.h: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2012 The Board of Trustees of The University of Alabama 2 | //All rights reserved. 3 | // 4 | //Redistribution and use in source and binary forms, with or without 5 | //modification, are permitted provided that the following conditions 6 | //are met: 7 | // 8 | //1. Redistributions of source code must retain the above copyright 9 | //notice, this list of conditions and the following disclaimer. 10 | //2. Redistributions in binary form must reproduce the above copyright 11 | //notice, this list of conditions and the following disclaimer in the 12 | //documentation and/or other materials provided with the distribution. 13 | //3. Neither the name of the University nor the names of the contributors 14 | //may be used to endorse or promote products derived from this software 15 | //without specific prior written permission. 16 | // 17 | //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 | //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 | //THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | //INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | //HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | //STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | //ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 | //OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | #import 32 | #import 33 | 34 | #define OMDateFormat @"yyyy-MM-dd'T'HH:mm:ss.SSS" 35 | #define OMTimeZone @"UTC" 36 | 37 | 38 | typedef NS_ENUM(NSInteger, CAPSDataType) { 39 | CAPSDataTypeJSON, 40 | CAPSDataTypeXML, 41 | CAPSDataTypeSOAP 42 | }; 43 | 44 | @interface NSObject (ObjectMap) 45 | 46 | // Universal Method 47 | -(NSDictionary *)propertyDictionary; 48 | -(NSString *)nameOfClass; 49 | 50 | 51 | #pragma mark - Init Methods 52 | /** 53 | Initializes an instance of a new object using JSON. 54 | 55 | @param data The JSON data to deserialize into the returned object. 56 | 57 | @return The newly-initialized object. 58 | */ 59 | - (instancetype)initWithJSONData:(NSData *)data; 60 | 61 | 62 | /** 63 | Initializes an instance of a new object using XML. 64 | 65 | @param data The XML data to deserialize into the returned object. 66 | 67 | @return The newly-initialized object. 68 | */ 69 | - (instancetype)initWithXMLData:(NSData *)data; 70 | 71 | 72 | /** 73 | Initializes an instance of a new object using SOAP. 74 | 75 | @param data The SOAP data to deserialize into the returned object. 76 | 77 | @return The newly-initialized object. 78 | */ 79 | - (instancetype)initWithSOAPData:(NSData *)data; 80 | 81 | 82 | /** 83 | Initializes an instance of a new object using unspecified object data and a specified type. 84 | 85 | @param data The unspecified data to deserialize into the returned object. 86 | @param type The type of unspecified data to deserialize. 87 | 88 | @return The newly-initialized object. 89 | */ 90 | - (instancetype)initWithObjectData:(NSData *)data type:(CAPSDataType)type; 91 | 92 | 93 | 94 | #pragma mark - Top Level Array from JSON 95 | /** 96 | Initializes an array of objects that are of a certain class from JSON data. 97 | 98 | @param objectClass The type of object to deserialize into. 99 | @param data The JSON data to deserialize into the array. 100 | 101 | @return The newly-initialized array. 102 | */ 103 | + (NSArray *)arrayOfType:(Class)objectClass FromJSONData:(NSData *)data; 104 | 105 | 106 | 107 | #pragma mark - Serialized Data/Strings from Objects 108 | -(NSData *)JSONData; 109 | -(NSString *)JSONString; 110 | -(NSData *)XMLData; 111 | -(NSString *)XMLString; 112 | -(NSData *)SOAPData; 113 | -(NSString *)SOAPString; 114 | -(NSDictionary *)objectDictionary; 115 | 116 | 117 | #pragma mark - New Object with properties of another Object 118 | -(id)initWithObject:(NSObject *)oldObject error:(NSError **)error; 119 | 120 | #pragma mark - Base64 Encode/Decode 121 | +(NSString *)encodeBase64WithData:(NSData *)objData; 122 | +(NSData *)base64DataFromString:(NSString *)string; 123 | 124 | @end 125 | 126 | @interface SOAPObject : NSObject 127 | @property (nonatomic, retain) id Header; 128 | @property (nonatomic, retain) id Body; 129 | @end -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/NSString+XMLDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+XMLDictionary.h 3 | // WeChatManagerClient 4 | // 5 | // Created by nato on 2016/11/11. 6 | // Copyright © 2016年 nato. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (XMLDictionary) 12 | 13 | - (NSDictionary *)xmlDictionary; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/NSString+XMLDictionary.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+XMLDictionary.m 3 | // WeChatManagerClient 4 | // 5 | // Created by nato on 2016/11/11. 6 | // Copyright © 2016年 nato. All rights reserved. 7 | // 8 | 9 | #import "NSString+XMLDictionary.h" 10 | #import "XMLReader.h" 11 | 12 | @implementation NSString (XMLDictionary) 13 | 14 | - (NSDictionary *)xmlDictionary { 15 | return [XMLReader dictionaryForXMLString:self error:nil]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/NSViewController+Hook.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSViewController+Hook.h 3 | // WeChatPlugin 4 | // 5 | // Created by Loveletter on 26/02/2018. 6 | // Copyright © 2018 CodeTips. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (NSViewController) 12 | 13 | + (void)hookNSViewController; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/NSViewController+Hook.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSViewController+Hook.m 3 | // WeChatPlugin 4 | // 5 | // Created by Loveletter on 26/02/2018. 6 | // Copyright © 2018 CodeTips. All rights reserved. 7 | // 8 | 9 | #import "NSViewController+Hook.h" 10 | #import "WeChatPlugin.h" 11 | #import "MMTimeLineMainViewController.h" 12 | #import "MMTimeLineViewController.h" 13 | 14 | @implementation NSObject (NSViewController) 15 | 16 | + (void)hookNSViewController 17 | { 18 | if (!CBGetClass(SnsTimeLineRequest)) { 19 | return; 20 | } 21 | CBRegisterClass(MMContactsViewController, MMTimeLineMainViewController); 22 | 23 | tk_hookMethod(objc_getClass("LeftViewController"), @selector(setViewControllers:), [self class], @selector(cb_setViewControllers:)); 24 | tk_hookMethod(objc_getClass("MMViewController"), @selector(viewDidLoad), [self class], @selector(cb_mmDidLoad)); 25 | tk_hookMethod(objc_getClass("MMPreviewViewController"), @selector(viewDidLoad), [self class], @selector(cb_preViewDidLoad)); 26 | tk_hookMethod(objc_getClass("MMPreviewPanel"), @selector(show), [self class], @selector(cb_preshow)); 27 | } 28 | 29 | 30 | - (void)cb_setViewControllers:(NSArray *)vcs { 31 | 32 | MMTimeLineMainViewController *timeLineMainVC = [[objc_getClass("MMTimeLineMainViewController") alloc] initWithNibName:@"MMContactsViewController" bundle:[NSBundle mainBundle]]; 33 | [timeLineMainVC setTitle:[[NSBundle mainBundle] localizedStringForKey:@"Tabbar.Chats" value:@"" table:0x0]]; 34 | 35 | 36 | MMTimeLineViewController *timeLineVC = [[objc_getClass("MMTimeLineViewController") alloc] initWithNibName:@"MMTimeLineViewController" bundle:[NSBundle pluginBundle]]; 37 | timeLineMainVC.detailViewController = (id)timeLineVC; 38 | 39 | MMTabbarItem *tabBarItem = [[objc_getClass("MMTabbarItem") alloc] initWithTitle:@"朋友圈" onStateImage:[[NSBundle pluginBundle] imageForResource:@"Tabbar-TimeLine-Selected"] onStateAlternateImage:[[NSBundle pluginBundle] imageForResource:@"Tabbar-TimeLine-Selected-HI"] offStateImage:[[NSBundle pluginBundle] imageForResource:@"Tabbar-TimeLine"] offStateAlternateImage:[[NSBundle pluginBundle] imageForResource:@"Tabbar-TimeLine-HI"]]; 40 | [timeLineMainVC setTabbarItem:tabBarItem]; 41 | 42 | NSMutableArray *viewControllers = [vcs mutableCopy]; 43 | [viewControllers addObject:timeLineMainVC]; 44 | [self cb_setViewControllers:[viewControllers copy]]; 45 | 46 | } 47 | 48 | -(void)cb_mmDidLoad{ 49 | NSLog(@"\n----\n ❤️ %@ didLoad \n----\n",NSStringFromClass([self class])); 50 | } 51 | -(void)cb_preViewDidLoad{ 52 | 53 | [self cb_preViewDidLoad]; 54 | } 55 | 56 | -(void)cb_preshow{ 57 | [self cb_preshow]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Category/WeChat+Hook.h: -------------------------------------------------------------------------------- 1 | // 2 | // WeChat+hook.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (WeChatHook) 12 | 13 | + (void)hookWeChat; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/Category/NSButton+Action.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSButton+Action.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSButton (Action) 12 | + (instancetype)tk_buttonWithTitle:(NSString *)title target:(id)target action:(SEL)action; 13 | + (instancetype)tk_checkboxWithTitle:(NSString *)title target:(id)target action:(SEL)action; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/Category/NSButton+Action.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSButton+Action.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "NSButton+Action.h" 10 | 11 | @implementation NSButton (Action) 12 | 13 | + (instancetype)tk_checkboxWithTitle:(NSString *)title target:(id)target action:(SEL)action { 14 | NSButton *btn = [NSButton tk_buttonWithTitle:title target:target action:action]; 15 | [btn setButtonType:NSButtonTypeSwitch]; 16 | 17 | return btn; 18 | } 19 | 20 | + (instancetype)tk_buttonWithTitle:(NSString *)title target:(id)target action:(SEL)action { 21 | NSButton *btn = ({ 22 | NSButton *btn = [[NSButton alloc] init]; 23 | btn.title = title; 24 | btn.target = target; 25 | btn.action = action; 26 | 27 | btn; 28 | }); 29 | 30 | return btn; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/Category/NSTextField+Action.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTextField+Action.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSTextField (Action) 12 | 13 | + (instancetype)tk_labelWithString:(NSString *)stringValue; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/Category/NSTextField+Action.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTextField+Action.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "NSTextField+Action.h" 10 | 11 | @implementation NSTextField (Action) 12 | 13 | + (instancetype)tk_labelWithString:(NSString *)stringValue { 14 | NSTextField *textField = ({ 15 | NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 200, 17)]; 16 | [textField setStringValue:stringValue]; 17 | [textField setBezeled:NO]; 18 | [textField setDrawsBackground:NO]; 19 | [textField setEditable:NO]; 20 | [textField setSelectable:NO]; 21 | 22 | textField; 23 | }); 24 | 25 | return textField; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/Category/NSView+Action.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+Action.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/20. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSView (Action) 12 | 13 | - (void)addSubviews:(NSArray *)subViews; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/Category/NSView+Action.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+Action.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/20. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "NSView+Action.h" 10 | 11 | @implementation NSView (Action) 12 | 13 | - (void)addSubviews:(NSArray *)subViews { 14 | for (NSView *v in subViews) { 15 | NSAssert([v isKindOfClass:[NSView class]], @"the elements must be a view!"); 16 | [self addSubview:v]; 17 | } 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/Color.h: -------------------------------------------------------------------------------- 1 | // 2 | // Color.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/20. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #ifndef Color_h 10 | #define Color_h 11 | 12 | #define TK_RGBA(r, g, b, a) [NSColor colorWithRed:(r) / 255.0 \ 13 | green:(g) / 255.0 \ 14 | blue:(b) / 255.0 \ 15 | alpha:(a)] 16 | 17 | #define TK_RGB(r, g, b) TK_RGBA(r, g, b, 1.0) 18 | #define TK_GRAYA(c, a) TK_RGBA(c, c, c, a) 19 | #define TK_GRAY(c) TK_GRAYA(c, 1.0) 20 | 21 | #define kBG1 TK_GRAY(0xec) 22 | #define kBG2 TK_GRAY(0xe3) 23 | #define kBG3 TK_GRAYA(0x2a, 0.5) 24 | #define kBG4 TK_GRAYA(0x7a, 0.5) 25 | 26 | #endif /* Color_h */ 27 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Common/TKPrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // TKPrefixHeader.pch 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/20. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #ifndef TKPrefixHeader_pch 10 | #define TKPrefixHeader_pch 11 | 12 | #ifdef __OBJC__ 13 | #import "Color.h" 14 | #import "NSView+Action.h" 15 | #import "NSButton+Action.h" 16 | #import "NSTextField+Action.h" 17 | #import 18 | #import 19 | #import "WeChatPlugin.h" 20 | #import "MMStatus.h" 21 | #import "MMStatusMediaObject.h" 22 | #import "MMStatusImageMediaObject.h" 23 | #import "MMStatusLinkMediaObject.h" 24 | #endif 25 | 26 | #define CBGetClass(classname) objc_getClass(#classname) 27 | #define CBRegisterClass(superclassname, subclassname) { Class class = objc_allocateClassPair(CBGetClass(superclassname), #subclassname, 0);objc_registerClassPair(class); } 28 | 29 | 30 | #endif /* TKPrefixHeader_pch */ 31 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Config/TKWeChatPluginConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKWeChatPluginConfig.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | @interface TKWeChatPluginConfig : NSObject 13 | 14 | @property (nonatomic, assign) BOOL preventRevokeEnable; /**< 是否开启防撤回 */ 15 | @property (nonatomic, assign) BOOL autoAuthEnable; /**< 是否免认证登录 */ 16 | @property (nonatomic, assign) BOOL autoLoginEnable; /**< 是否自动登录 */ 17 | @property (nonatomic, assign) BOOL onTop; /**< 是否要置顶微信 */ 18 | @property (nonatomic, assign) BOOL multipleSelectionEnable; /**< 是否要进行多选 */ 19 | @property (nonatomic, copy) NSMutableArray *autoReplyModels; /**< 自动回复的数组 */ 20 | @property (nonatomic, copy) NSMutableArray *remoteControlModels; /**< 远程控制的数组 */ 21 | @property (nonatomic, copy) NSMutableArray *ignoreSessionModels; /**< 聊天置底的数组 */ 22 | @property (nonatomic, copy) NSMutableArray *selectSessions; /**< 已经选中的会话 */ 23 | @property (nonatomic, copy) NSMutableSet *revokeMsgSet; /**< 撤回的消息集合 */ 24 | @property (nonatomic, copy) NSString *currentUserName; /**< 当前用户的id */ 25 | 26 | - (void)saveAutoReplyModels; 27 | - (void)saveRemoteControlModels; 28 | - (void)saveIgnoreSessionModels; 29 | 30 | + (instancetype)sharedConfig; 31 | 32 | @end 33 | 34 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Config/TKWeChatPluginConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKWeChatPluginConfig.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKWeChatPluginConfig.h" 10 | #import "TKRemoteControlModel.h" 11 | #import "TKAutoReplyModel.h" 12 | #import "TKIgnoreSessonModel.h" 13 | 14 | static NSString * const kTKPreventRevokeEnableKey = @"kTKPreventRevokeEnableKey"; 15 | static NSString * const kTKAutoAuthEnableKey = @"kTKAutoAuthEnableKey"; 16 | static NSString * const kTKAutoLoginEnableKey = @"kTKAutoLoginEnableKey"; 17 | static NSString * const kTKOnTopKey = @"kTKOnTopKey"; 18 | static NSString * const kTKWeChatResourcesPath = @"/Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/"; 19 | 20 | @interface TKWeChatPluginConfig () 21 | 22 | @property (nonatomic, copy) NSString *remoteControlPlistFilePath; 23 | @property (nonatomic, copy) NSString *autoReplyPlistFilePath; 24 | @property (nonatomic, copy) NSString *ignoreSessionPlistFilePath; 25 | 26 | @end 27 | 28 | @implementation TKWeChatPluginConfig 29 | 30 | + (instancetype)sharedConfig { 31 | static TKWeChatPluginConfig *config = nil; 32 | static dispatch_once_t onceToken; 33 | dispatch_once(&onceToken, ^{ 34 | config = [[TKWeChatPluginConfig alloc] init]; 35 | }); 36 | return config; 37 | } 38 | 39 | - (instancetype)init { 40 | self = [super init]; 41 | if (self) { 42 | _preventRevokeEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKPreventRevokeEnableKey]; 43 | _autoAuthEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKAutoAuthEnableKey]; 44 | _autoLoginEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKAutoLoginEnableKey]; 45 | _onTop = [[NSUserDefaults standardUserDefaults] boolForKey:kTKOnTopKey]; 46 | } 47 | return self; 48 | } 49 | 50 | - (void)setPreventRevokeEnable:(BOOL)preventRevokeEnable { 51 | _preventRevokeEnable = preventRevokeEnable; 52 | [[NSUserDefaults standardUserDefaults] setBool:preventRevokeEnable forKey:kTKPreventRevokeEnableKey]; 53 | [[NSUserDefaults standardUserDefaults] synchronize]; 54 | } 55 | 56 | - (void)setAutoAuthEnable:(BOOL)autoAuthEnable { 57 | _autoAuthEnable = autoAuthEnable; 58 | [[NSUserDefaults standardUserDefaults] setBool:autoAuthEnable forKey:kTKAutoAuthEnableKey]; 59 | [[NSUserDefaults standardUserDefaults] synchronize]; 60 | } 61 | 62 | - (void)setAutoLoginEnable:(BOOL)autoLoginEnable { 63 | _autoLoginEnable = autoLoginEnable; 64 | [[NSUserDefaults standardUserDefaults] setBool:autoLoginEnable forKey:kTKAutoLoginEnableKey]; 65 | [[NSUserDefaults standardUserDefaults] synchronize]; 66 | } 67 | 68 | - (void)setOnTop:(BOOL)onTop { 69 | _onTop = onTop; 70 | [[NSUserDefaults standardUserDefaults] setBool:_onTop forKey:kTKOnTopKey]; 71 | [[NSUserDefaults standardUserDefaults] synchronize]; 72 | } 73 | 74 | #pragma mark - 自动回复 75 | - (NSArray *)autoReplyModels { 76 | if (!_autoReplyModels) { 77 | _autoReplyModels = [self getModelsWithClass:[TKAutoReplyModel class] filePath:self.autoReplyPlistFilePath]; 78 | } 79 | return _autoReplyModels; 80 | } 81 | 82 | - (void)saveAutoReplyModels { 83 | NSMutableArray *needSaveModels = [NSMutableArray array]; 84 | [_autoReplyModels enumerateObjectsUsingBlock:^(TKAutoReplyModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 85 | if (model.hasEmptyKeywordOrReplyContent) { 86 | model.enable = NO; 87 | model.enableGroupReply = NO; 88 | } 89 | model.replyContent = model.replyContent == nil ? @"" : model.replyContent; 90 | model.keyword = model.keyword == nil ? @"" : model.keyword; 91 | [needSaveModels addObject:model.dictionary]; 92 | }]; 93 | [needSaveModels writeToFile:self.autoReplyPlistFilePath atomically:YES]; 94 | } 95 | 96 | #pragma mark - 远程控制 97 | - (NSArray *)remoteControlModels { 98 | if (!_remoteControlModels) { 99 | _remoteControlModels = ({ 100 | NSArray *originModels = [NSArray arrayWithContentsOfFile:self.remoteControlPlistFilePath]; 101 | NSMutableArray *newRemoteControlModels = [NSMutableArray array]; 102 | [originModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger idx, BOOL * _Nonnull stop) { 103 | NSMutableArray *newSubModels = [NSMutableArray array]; 104 | [subModels enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 105 | TKRemoteControlModel *model = [[TKRemoteControlModel alloc] initWithDict:obj]; 106 | [newSubModels addObject:model]; 107 | }]; 108 | [newRemoteControlModels addObject:newSubModels]; 109 | }]; 110 | newRemoteControlModels; 111 | }); 112 | } 113 | return _remoteControlModels; 114 | } 115 | 116 | - (void)saveRemoteControlModels { 117 | NSMutableArray *needSaveModels = [NSMutableArray array]; 118 | [_remoteControlModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger idx, BOOL * _Nonnull stop) { 119 | NSMutableArray *newSubModels = [NSMutableArray array]; 120 | [subModels enumerateObjectsUsingBlock:^(TKRemoteControlModel *obj, NSUInteger idx, BOOL * _Nonnull stop) { 121 | [newSubModels addObject:obj.dictionary]; 122 | }]; 123 | [needSaveModels addObject:newSubModels]; 124 | }]; 125 | [needSaveModels writeToFile:self.remoteControlPlistFilePath atomically:YES]; 126 | } 127 | 128 | #pragma mark - 置底 129 | - (NSArray *)ignoreSessionModels { 130 | if (!_ignoreSessionModels) { 131 | _ignoreSessionModels = [self getModelsWithClass:[TKIgnoreSessonModel class] filePath:self.ignoreSessionPlistFilePath]; 132 | } 133 | return _ignoreSessionModels; 134 | } 135 | 136 | - (void)saveIgnoreSessionModels { 137 | NSMutableArray *needSaveArray = [NSMutableArray array]; 138 | [self.ignoreSessionModels enumerateObjectsUsingBlock:^(TKBaseModel *obj, NSUInteger idx, BOOL * _Nonnull stop) { 139 | [needSaveArray addObject:obj.dictionary]; 140 | }]; 141 | 142 | [needSaveArray writeToFile:self.ignoreSessionPlistFilePath atomically:YES]; 143 | 144 | } 145 | 146 | #pragma mark - 选中的会话 147 | - (NSMutableArray *)selectSessions { 148 | if (!_selectSessions) { 149 | _selectSessions = [NSMutableArray array]; 150 | } 151 | return _selectSessions; 152 | } 153 | 154 | #pragma mark - 选中的会话 155 | - (NSMutableSet *)revokeMsgSet { 156 | if (!_revokeMsgSet) { 157 | _revokeMsgSet = [NSMutableSet set]; 158 | } 159 | return _revokeMsgSet; 160 | } 161 | 162 | #pragma mark - 获取沙盒上的 plist 文件,包括:远程控制,自动回复,置底列表。 163 | - (NSString *)remoteControlPlistFilePath { 164 | if (!_remoteControlPlistFilePath) { 165 | _remoteControlPlistFilePath = [self getSandboxFilePathWithPlistName:@"TKRemoteControlCommands.plist"]; 166 | } 167 | return _remoteControlPlistFilePath; 168 | } 169 | 170 | - (NSString *)autoReplyPlistFilePath { 171 | if (!_autoReplyPlistFilePath) { 172 | _autoReplyPlistFilePath = [self getSandboxFilePathWithPlistName:@"TKAutoReplyModels.plist"]; 173 | } 174 | return _autoReplyPlistFilePath; 175 | } 176 | 177 | - (NSString *)ignoreSessionPlistFilePath { 178 | if (!_ignoreSessionPlistFilePath) { 179 | _ignoreSessionPlistFilePath = [self getSandboxFilePathWithPlistName:@"TKIgnoreSessons.plist"]; 180 | } 181 | return _ignoreSessionPlistFilePath; 182 | } 183 | 184 | #pragma mark - common 185 | - (NSMutableArray *)getModelsWithClass:(Class)class filePath:(NSString *)filePath { 186 | NSArray *originModels = [NSArray arrayWithContentsOfFile:filePath]; 187 | NSMutableArray *newModels = [NSMutableArray array]; 188 | 189 | __weak Class weakClass = class; 190 | [originModels enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL * _Nonnull stop) { 191 | TKIgnoreSessonModel *model = [[weakClass alloc] initWithDict:obj]; 192 | [newModels addObject:model]; 193 | }]; 194 | return newModels; 195 | } 196 | 197 | - (NSString *)getSandboxFilePathWithPlistName:(NSString *)plistName { 198 | NSFileManager *manager = [NSFileManager defaultManager]; 199 | NSString *wechatPluginDirectory = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"TKWeChatPlugin"]; 200 | NSString *plistFilePath = [wechatPluginDirectory stringByAppendingPathComponent:plistName]; 201 | if ([manager fileExistsAtPath:plistFilePath]) { 202 | return plistFilePath; 203 | } 204 | 205 | [manager createDirectoryAtPath:wechatPluginDirectory withIntermediateDirectories:YES attributes:nil error:nil]; 206 | NSString *resourcesFilePath = [kTKWeChatResourcesPath stringByAppendingString:plistName]; 207 | if (![manager fileExistsAtPath:resourcesFilePath]) { 208 | return plistFilePath; 209 | } 210 | 211 | NSError *error = nil; 212 | [manager copyItemAtPath:resourcesFilePath toPath:plistFilePath error:&error]; 213 | if (!error) { 214 | return plistFilePath; 215 | } 216 | 217 | return resourcesFilePath; 218 | } 219 | 220 | @end 221 | 222 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Controllers/TKRemoteControlController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlController.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKRemoteControlController : NSObject 12 | 13 | + (void)executeRemoteControlCommandWithMsg:(NSString *)msg; 14 | + (void)executeShellCommand:(NSString *)msg; 15 | + (NSString *)remoteControlCommandsString; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Controllers/TKRemoteControlController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlController.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKRemoteControlController.h" 10 | #import "TKWeChatPluginConfig.h" 11 | #import "TKRemoteControlModel.h" 12 | #import "WeChatPlugin.h" 13 | 14 | // 执行 AppleScript 15 | static NSString * const kRemoteControlAppleScript = @"osascript /Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt"; 16 | 17 | @implementation TKRemoteControlController 18 | 19 | + (void)executeRemoteControlCommandWithMsg:(NSString *)msg { 20 | NSArray *remoteControlModels = [TKWeChatPluginConfig sharedConfig].remoteControlModels; 21 | [remoteControlModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger index, BOOL * _Nonnull stop) { 22 | [subModels enumerateObjectsUsingBlock:^(TKRemoteControlModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 23 | if (model.enable && ![model.keyword isEqualToString:@""] && ([msg isEqualToString:model.keyword] || [msg isEqualToString:model.command])) { 24 | if ([model.function isEqualToString:@"屏幕保护"] || [model.function isEqualToString:@"锁屏"]) { 25 | // 屏幕保护 & 锁屏 通过 Shell 命令来执行即可 26 | [self executeShellCommand:model.executeCommand]; 27 | } else { 28 | // 拼接相关参数,执行 AppleScript 29 | NSString *command = [NSString stringWithFormat:@"%@ %@",kRemoteControlAppleScript, model.executeCommand]; 30 | [self executeShellCommand:command]; 31 | // bug: 有些程序在第一次时会无法关闭,需要再次关闭 32 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 33 | if ([model.function isEqualToString:@"退出所有程序"]) { 34 | NSString *command = [NSString stringWithFormat:@"%@ %@",kRemoteControlAppleScript, model.executeCommand]; 35 | [self executeShellCommand:command]; 36 | } 37 | }); 38 | } 39 | if (![msg hasPrefix:@"#remote."]) { 40 | NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; 41 | NSString *callBack = [NSString stringWithFormat:@"小助手收到一条指令:%@",model.function]; 42 | MessageService *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; 43 | [service SendTextMessage:currentUserName toUsrName:currentUserName msgText:callBack atUserList:nil]; 44 | } 45 | } 46 | }]; 47 | }]; 48 | } 49 | 50 | /** 51 | 通过 NSTask 执行 Shell 命令 52 | 53 | @param cmd Terminal命令 54 | */ 55 | + (void)executeShellCommand:(NSString *)cmd { 56 | NSTask *task = [[NSTask alloc] init]; 57 | [task setLaunchPath:@"/bin/bash"]; 58 | [task setArguments:@[@"-c", cmd]]; 59 | [task launch]; 60 | } 61 | 62 | + (NSString *)remoteControlCommandsString { 63 | NSMutableString *replyContent = [NSMutableString stringWithFormat:@"远程控制指令:\n(功能-指令-是否开启)\n\n"]; 64 | 65 | NSArray *remoteControlModels = [TKWeChatPluginConfig sharedConfig].remoteControlModels; 66 | [remoteControlModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger index, BOOL * _Nonnull stop) { 67 | switch (index) { 68 | case 0: 69 | [replyContent appendString:@"macbook控制:\n"]; 70 | break; 71 | case 1: 72 | [replyContent appendString:@"app控制:\n"]; 73 | break; 74 | case 2: 75 | [replyContent appendString:@"网易云音乐控制:\n"]; 76 | break; 77 | default: 78 | break; 79 | } 80 | [subModels enumerateObjectsUsingBlock:^(TKRemoteControlModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 81 | [replyContent appendFormat:@"%@-%@-%@\n", model.function, model.keyword, model.enable ? @"开启":@"关闭"]; 82 | }]; 83 | [replyContent appendString:@"\n"]; 84 | }]; 85 | return replyContent; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/Tabbar-TimeLine-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/Tabbar-TimeLine-HI@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/Tabbar-TimeLine-Selected-HI@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/Tabbar-TimeLine-Selected-HI@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/Tabbar-TimeLine-Selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/Tabbar-TimeLine-Selected@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/Tabbar-TimeLine@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/Tabbar-TimeLine@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/comment_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/comment_icon_highlighted@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/comment_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/comment_icon_normal@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/like_icon_highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/like_icon_highlighted@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/like_icon_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/like_icon_normal@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/link_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/link_icon@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Image/time_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Image/time_icon@2x.png -------------------------------------------------------------------------------- /WeChatPlugin/Sources/JRSwizzle/JRSwizzle.h: -------------------------------------------------------------------------------- 1 | // JRSwizzle.h semver:1.0 2 | // Copyright (c) 2007-2011 Jonathan 'Wolf' Rentzsch: http://rentzsch.com 3 | // Some rights reserved: http://opensource.org/licenses/MIT 4 | // https://github.com/rentzsch/jrswizzle 5 | 6 | #import 7 | 8 | @interface NSObject (JRSwizzle) 9 | 10 | + (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_; 11 | + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/JRSwizzle/JRSwizzle.m: -------------------------------------------------------------------------------- 1 | // JRSwizzle.m semver:1.0 2 | // Copyright (c) 2007-2011 Jonathan 'Wolf' Rentzsch: http://rentzsch.com 3 | // Some rights reserved: http://opensource.org/licenses/MIT 4 | // https://github.com/rentzsch/jrswizzle 5 | 6 | #import "JRSwizzle.h" 7 | 8 | #if TARGET_OS_IPHONE 9 | #import 10 | #import 11 | #else 12 | #import 13 | #endif 14 | 15 | #define SetNSErrorFor(FUNC, ERROR_VAR, FORMAT,...) \ 16 | if (ERROR_VAR) { \ 17 | NSString *errStr = [NSString stringWithFormat:@"%s: " FORMAT,FUNC,##__VA_ARGS__]; \ 18 | *ERROR_VAR = [NSError errorWithDomain:@"NSCocoaErrorDomain" \ 19 | code:-1 \ 20 | userInfo:[NSDictionary dictionaryWithObject:errStr forKey:NSLocalizedDescriptionKey]]; \ 21 | } 22 | #define SetNSError(ERROR_VAR, FORMAT,...) SetNSErrorFor(__func__, ERROR_VAR, FORMAT, ##__VA_ARGS__) 23 | 24 | #if OBJC_API_VERSION >= 2 25 | #define GetClass(obj) object_getClass(obj) 26 | #else 27 | #define GetClass(obj) (obj ? obj->isa : Nil) 28 | #endif 29 | 30 | @implementation NSObject (JRSwizzle) 31 | 32 | + (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_ { 33 | #if OBJC_API_VERSION >= 2 34 | Method origMethod = class_getInstanceMethod(self, origSel_); 35 | if (!origMethod) { 36 | #if TARGET_OS_IPHONE 37 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self class]); 38 | #else 39 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]); 40 | #endif 41 | return NO; 42 | } 43 | 44 | Method altMethod = class_getInstanceMethod(self, altSel_); 45 | if (!altMethod) { 46 | #if TARGET_OS_IPHONE 47 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self class]); 48 | #else 49 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]); 50 | #endif 51 | return NO; 52 | } 53 | 54 | class_addMethod(self, 55 | origSel_, 56 | class_getMethodImplementation(self, origSel_), 57 | method_getTypeEncoding(origMethod)); 58 | class_addMethod(self, 59 | altSel_, 60 | class_getMethodImplementation(self, altSel_), 61 | method_getTypeEncoding(altMethod)); 62 | 63 | method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_)); 64 | return YES; 65 | #else 66 | // Scan for non-inherited methods. 67 | Method directOriginalMethod = NULL, directAlternateMethod = NULL; 68 | 69 | void *iterator = NULL; 70 | struct objc_method_list *mlist = class_nextMethodList(self, &iterator); 71 | while (mlist) { 72 | int method_index = 0; 73 | for (; method_index < mlist->method_count; method_index++) { 74 | if (mlist->method_list[method_index].method_name == origSel_) { 75 | assert(!directOriginalMethod); 76 | directOriginalMethod = &mlist->method_list[method_index]; 77 | } 78 | if (mlist->method_list[method_index].method_name == altSel_) { 79 | assert(!directAlternateMethod); 80 | directAlternateMethod = &mlist->method_list[method_index]; 81 | } 82 | } 83 | mlist = class_nextMethodList(self, &iterator); 84 | } 85 | 86 | // If either method is inherited, copy it up to the target class to make it non-inherited. 87 | if (!directOriginalMethod || !directAlternateMethod) { 88 | Method inheritedOriginalMethod = NULL, inheritedAlternateMethod = NULL; 89 | if (!directOriginalMethod) { 90 | inheritedOriginalMethod = class_getInstanceMethod(self, origSel_); 91 | if (!inheritedOriginalMethod) { 92 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]); 93 | return NO; 94 | } 95 | } 96 | if (!directAlternateMethod) { 97 | inheritedAlternateMethod = class_getInstanceMethod(self, altSel_); 98 | if (!inheritedAlternateMethod) { 99 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]); 100 | return NO; 101 | } 102 | } 103 | 104 | int hoisted_method_count = !directOriginalMethod && !directAlternateMethod ? 2 : 1; 105 | struct objc_method_list *hoisted_method_list = malloc(sizeof(struct objc_method_list) + (sizeof(struct objc_method)*(hoisted_method_count-1))); 106 | hoisted_method_list->obsolete = NULL; // soothe valgrind - apparently ObjC runtime accesses this value and it shows as uninitialized in valgrind 107 | hoisted_method_list->method_count = hoisted_method_count; 108 | Method hoisted_method = hoisted_method_list->method_list; 109 | 110 | if (!directOriginalMethod) { 111 | bcopy(inheritedOriginalMethod, hoisted_method, sizeof(struct objc_method)); 112 | directOriginalMethod = hoisted_method++; 113 | } 114 | if (!directAlternateMethod) { 115 | bcopy(inheritedAlternateMethod, hoisted_method, sizeof(struct objc_method)); 116 | directAlternateMethod = hoisted_method; 117 | } 118 | class_addMethods(self, hoisted_method_list); 119 | } 120 | 121 | // Swizzle. 122 | IMP temp = directOriginalMethod->method_imp; 123 | directOriginalMethod->method_imp = directAlternateMethod->method_imp; 124 | directAlternateMethod->method_imp = temp; 125 | 126 | return YES; 127 | #endif 128 | } 129 | 130 | + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ { 131 | return [GetClass((id)self) jr_swizzleMethod:origSel_ withMethod:altSel_ error:error_]; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKAutoReplyModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyModel.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/18. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKBaseModel.h" 10 | 11 | @interface TKAutoReplyModel : TKBaseModel 12 | 13 | @property (nonatomic, assign) BOOL enable; /**< 是否开启自动回复 */ 14 | @property (nonatomic, copy) NSString *keyword; /**< 自动回复关键字 */ 15 | @property (nonatomic, copy) NSString *replyContent; /**< 自动回复的内容 */ 16 | @property (nonatomic, assign) BOOL enableGroupReply; /**< 是否开启群聊自动回复 */ 17 | @property (nonatomic, assign) BOOL enableSingleReply; /**< 是否开启私聊自动回复 */ 18 | @property (nonatomic, assign) BOOL enableRegex; /**< 是否开启正则匹配 */ 19 | 20 | - (BOOL)hasEmptyKeywordOrReplyContent; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKAutoReplyModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyModel.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/18. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKAutoReplyModel.h" 10 | 11 | @implementation TKAutoReplyModel 12 | 13 | - (instancetype)initWithDict:(NSDictionary *)dict { 14 | self = [super init]; 15 | if (self) { 16 | self.enable = [dict[@"enable"] boolValue]; 17 | self.keyword = dict[@"keyword"]; 18 | self.replyContent = dict[@"replyContent"]; 19 | self.enableGroupReply = [dict[@"enableGroupReply"] boolValue]; 20 | self.enableSingleReply = [dict[@"enableSingleReply"] boolValue]; 21 | self.enableRegex = [dict[@"enableRegex"] boolValue]; 22 | } 23 | return self; 24 | } 25 | 26 | - (NSDictionary *)dictionary { 27 | return @{@"enable": @(self.enable), 28 | @"keyword": self.keyword, 29 | @"replyContent": self.replyContent, 30 | @"enableGroupReply": @(self.enableGroupReply), 31 | @"enableSingleReply": @(self.enableSingleReply), 32 | @"enableRegex": @(self.enableRegex)}; 33 | } 34 | 35 | - (BOOL)hasEmptyKeywordOrReplyContent { 36 | return (self.keyword == nil || self.replyContent == nil || [self.keyword isEqualToString:@""] || [self.replyContent isEqualToString:@""]); 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKBaseModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKBaseModel.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/17. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKBaseModel : NSObject 12 | 13 | - (instancetype)initWithDict:(NSDictionary *)dict; 14 | - (NSDictionary *)dictionary; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKBaseModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKBaseModel.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/17. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKBaseModel.h" 10 | 11 | @implementation TKBaseModel 12 | 13 | - (instancetype)initWithDict:(NSDictionary *)dict { 14 | NSAssert(NO, @"the mothed initWithDict: must be override by subclass"); 15 | return nil; 16 | } 17 | 18 | - (NSDictionary *)dictionary { 19 | NSAssert(NO, @"the mothed dictionary must be override by subclass"); 20 | return nil; 21 | } 22 | @end 23 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKIgnoreSessonModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKIgnoreSessonModel.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/15. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKBaseModel.h" 10 | 11 | @interface TKIgnoreSessonModel : TKBaseModel 12 | 13 | @property (nonatomic, copy) NSString *selfContact; 14 | @property (nonatomic, copy) NSString *userName; 15 | @property (nonatomic, assign) BOOL ignore; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKIgnoreSessonModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKIgnoreSessonModel.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/9/15. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKIgnoreSessonModel.h" 10 | 11 | @implementation TKIgnoreSessonModel 12 | 13 | - (instancetype)initWithDict:(NSDictionary *)dict { 14 | self = [super init]; 15 | if (self) { 16 | self.selfContact = dict[@"selfContact"]; 17 | self.userName = dict[@"userName"]; 18 | self.ignore = [dict[@"ignore"] boolValue]; 19 | } 20 | return self; 21 | } 22 | 23 | - (NSDictionary *)dictionary { 24 | return @{@"selfContact": self.selfContact, 25 | @"userName": self.userName, 26 | @"ignore": @(self.ignore)}; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKRemoteControlModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlModel.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKBaseModel.h" 10 | 11 | @interface TKRemoteControlModel : TKBaseModel 12 | 13 | @property (nonatomic, assign) BOOL enable; 14 | @property (nonatomic, copy) NSString *keyword; 15 | @property (nonatomic, copy) NSString *function; 16 | @property (nonatomic, copy) NSString *executeCommand; 17 | @property (nonatomic, copy) NSString *command; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Models/TKRemoteControlModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlModel.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKRemoteControlModel.h" 10 | 11 | @implementation TKRemoteControlModel 12 | 13 | - (instancetype)initWithDict:(NSDictionary *)dict { 14 | self = [super init]; 15 | if (self) { 16 | self.enable = [dict[@"enable"] boolValue]; 17 | self.keyword = dict[@"keyword"]; 18 | self.function = dict[@"function"]; 19 | self.executeCommand = dict[@"executeCommand"]; 20 | self.command = dict[@"command"]; 21 | } 22 | return self; 23 | } 24 | 25 | - (NSDictionary *)dictionary { 26 | return @{@"enable": @(self.enable), 27 | @"keyword": self.keyword, 28 | @"function": self.function, 29 | @"executeCommand": self.executeCommand, 30 | @"command": self.command}; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Status/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Status/Model/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatus.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatus.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, MMStatusMediaObjectType) { 12 | MMStatusMediaObjectTypeNone, 13 | MMStatusMediaObjectTypeImage, 14 | MMStatusMediaObjectTypeLink, 15 | }; 16 | 17 | @class MMStatusMediaObject; 18 | 19 | @interface MMStatus : NSObject 20 | 21 | @property (nonatomic, assign) NSUInteger statusId; 22 | @property (nonatomic, strong) NSString *profileImageURLString; 23 | @property (nonatomic, strong) NSImage *profileImage; 24 | @property (nonatomic, strong) NSString *nameString; 25 | @property (nonatomic, strong) NSString *timeString; 26 | @property (nonatomic, strong) NSString *sourceString; 27 | @property (nonatomic, strong) NSAttributedString *contentAttributedString; 28 | @property (nonatomic, assign) MMStatusMediaObjectType mediaType; 29 | @property (nonatomic, strong) MMStatusMediaObject *mediaObject; 30 | 31 | - (void)updateWithSnsObject:(SnsObject *)snsObject; 32 | 33 | -(void)valiateData; 34 | 35 | - (BOOL)hasSource; 36 | - (BOOL)hasContent; 37 | - (BOOL)hasMediaObject; 38 | 39 | @end 40 | 41 | 42 | 43 | @interface MMStatusSimple : NSObject 44 | 45 | @property (nonatomic, assign) NSUInteger statusId; 46 | @property (nonatomic, strong) NSString *profileImageURLString; 47 | @property (nonatomic, strong) NSString *nameString; 48 | @property (nonatomic, strong) NSString *timeString; 49 | @property (nonatomic, strong) NSString *sourceString; 50 | @property (nonatomic, strong) NSString * contentstring; 51 | @property (nonatomic, assign) MMStatusMediaObjectType mediaType; 52 | @property (nonatomic, strong) MMStatusMediaObject *mediaObject; 53 | 54 | - (void)updateWithSnsObject:(SnsObject *)snsObject; 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatus.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatus.m 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/3/24. 6 | // Copyright © 2017年 nato. All rights reserved. 7 | // 8 | 9 | #import "MMStatus.h" 10 | #import "NSDate+StatusTimeDescription.h" 11 | #import "NSString+XMLDictionary.h" 12 | 13 | @implementation MMStatus 14 | 15 | - (void)updateWithSnsObject:(SnsObject *)snsObject { 16 | _statusId = snsObject.id; 17 | WCContactData *contact = [[[CBGetClass(MMServiceCenter) defaultCenter] getService:CBGetClass(ContactStorage)] GetContact:snsObject.username]; 18 | _profileImageURLString = contact.m_nsHeadImgUrl; 19 | _nameString = contact.m_nsRemark.length ? contact.m_nsRemark : contact.m_nsNickName; 20 | _timeString = [[NSDate dateWithTimeIntervalSince1970:snsObject.createTime] statusTimeDescription]; 21 | 22 | NSString *timeLineObj = [[NSString alloc] initWithData:snsObject.objectDesc.buffer encoding:NSUTF8StringEncoding]; 23 | timeLineObj = [timeLineObj stringByReplacingOccurrencesOfString:@" " withString:@"\n"]; 24 | 25 | NSDictionary *timeLineObjDic = [timeLineObj xmlDictionary][@"TimelineObject"]; 26 | NSLog(@"%@", timeLineObjDic); 27 | 28 | NSDictionary *contentObjDic = timeLineObjDic[@"ContentObject"]; 29 | 30 | NSString *content = timeLineObjDic[@"contentDesc"]; 31 | NSMutableAttributedString *contentAttributedString = [NSMutableAttributedString new]; 32 | 33 | if ([content isKindOfClass:[NSString class]] && content.length) { 34 | [contentAttributedString appendAttributedString:[[NSAttributedString alloc] initWithString:content attributes:@{NSFontAttributeName: [NSFont systemFontOfSize:13]}]]; 35 | } 36 | self.contentAttributedString = contentAttributedString; 37 | 38 | NSString *appName = timeLineObjDic[@"appInfo"][@"appName"]; 39 | if ([appName isKindOfClass:[NSString class]] && appName.length) { 40 | _sourceString = appName; 41 | } 42 | 43 | NSString *contentStyle = contentObjDic[@"contentStyle"]; 44 | contentStyle = [contentStyle stringByReplacingOccurrencesOfString:@"![CDATA[" withString:@""]; 45 | contentStyle = [contentStyle stringByReplacingOccurrencesOfString:@"]" withString:@""]; 46 | NSInteger mediaStyle = [contentStyle integerValue]; 47 | NSArray *mediaList = contentObjDic[@"mediaList"][@"media"]; 48 | if ([mediaList isKindOfClass:[NSDictionary class]]) { 49 | if (mediaList.count) { 50 | mediaList = @[mediaList]; 51 | } 52 | else { 53 | mediaList = nil; 54 | } 55 | } 56 | 57 | if (mediaStyle == 1) { 58 | self.mediaType = MMStatusMediaObjectTypeImage; 59 | MMStatusImageMediaObject *mediaObject = [MMStatusImageMediaObject new]; 60 | NSMutableArray *imageInfos = [NSMutableArray new]; 61 | for (NSDictionary *media in mediaList) { 62 | MMStatusImageInfo *image = [MMStatusImageInfo new]; 63 | image.imageURLString = media[@"url"]; 64 | image.imageWidth = [media[@"size"][@"width"] doubleValue]; 65 | image.imageHeight = [media[@"size"][@"height"] doubleValue]; 66 | [imageInfos addObject:image]; 67 | } 68 | mediaObject.imageInfos = imageInfos.copy; 69 | self.mediaObject = mediaObject; 70 | } 71 | else if (mediaStyle == 3 || mediaStyle == 4 || mediaStyle == 5) { 72 | self.mediaType = MMStatusMediaObjectTypeLink; 73 | NSDictionary *media = mediaList.firstObject; 74 | NSString *title = contentObjDic[@"title"]; 75 | if (![title isKindOfClass:[NSString class]]) { 76 | title = media[@"title"]; 77 | } 78 | MMStatusLinkMediaObject *mediaObject = [MMStatusLinkMediaObject new]; 79 | mediaObject.linkURLString = contentObjDic[@"contentUrl"]; 80 | mediaObject.title = title; 81 | mediaObject.imageURLString = media[@"thumb"]; 82 | self.mediaObject = mediaObject; 83 | } 84 | } 85 | -(void)valiateData{ 86 | _sourceString = _sourceString?_sourceString:@""; 87 | _profileImageURLString = _profileImageURLString?_profileImageURLString:@""; 88 | _nameString = _nameString?_nameString:@""; 89 | 90 | } 91 | - (BOOL)hasSource { 92 | return self.sourceString.length; 93 | } 94 | 95 | - (BOOL)hasContent { 96 | return self.contentAttributedString.length; 97 | } 98 | 99 | - (BOOL)hasMediaObject { 100 | return self.mediaType != MMStatusMediaObjectTypeNone; 101 | } 102 | 103 | @end 104 | 105 | 106 | 107 | 108 | 109 | @implementation MMStatusSimple 110 | 111 | - (void)updateWithSnsObject:(SnsObject *)snsObject { 112 | _statusId = snsObject.id; 113 | WCContactData *contact = [[[CBGetClass(MMServiceCenter) defaultCenter] getService:CBGetClass(ContactStorage)] GetContact:snsObject.username]; 114 | _profileImageURLString = contact.m_nsHeadImgUrl; 115 | _nameString = contact.m_nsRemark.length ? contact.m_nsRemark : contact.m_nsNickName; 116 | _timeString = [[NSDate dateWithTimeIntervalSince1970:snsObject.createTime] statusTimeDescription]; 117 | 118 | NSString *timeLineObj = [[NSString alloc] initWithData:snsObject.objectDesc.buffer encoding:NSUTF8StringEncoding]; 119 | timeLineObj = [timeLineObj stringByReplacingOccurrencesOfString:@" " withString:@"\n"]; 120 | 121 | NSDictionary *timeLineObjDic = [timeLineObj xmlDictionary][@"TimelineObject"]; 122 | NSLog(@"%@", timeLineObjDic); 123 | 124 | NSDictionary *contentObjDic = timeLineObjDic[@"ContentObject"]; 125 | 126 | NSString *content = timeLineObjDic[@"contentDesc"]; 127 | // NSMutableAttributedString *contentAttributedString = [NSMutableAttributedString new]; 128 | // 129 | // if ([content isKindOfClass:[NSString class]] && content.length) { 130 | // [contentAttributedString appendAttributedString:[[NSAttributedString alloc] initWithString:content attributes:@{NSFontAttributeName: [NSFont systemFontOfSize:13]}]]; 131 | // } 132 | self.contentstring = content; 133 | 134 | NSString *appName = timeLineObjDic[@"appInfo"][@"appName"]; 135 | if ([appName isKindOfClass:[NSString class]] && appName.length) { 136 | _sourceString = appName; 137 | } 138 | 139 | NSString *contentStyle = contentObjDic[@"contentStyle"]; 140 | contentStyle = [contentStyle stringByReplacingOccurrencesOfString:@"![CDATA[" withString:@""]; 141 | contentStyle = [contentStyle stringByReplacingOccurrencesOfString:@"]" withString:@""]; 142 | NSInteger mediaStyle = [contentStyle integerValue]; 143 | NSArray *mediaList = contentObjDic[@"mediaList"][@"media"]; 144 | if ([mediaList isKindOfClass:[NSDictionary class]]) { 145 | if (mediaList.count) { 146 | mediaList = @[mediaList]; 147 | } 148 | else { 149 | mediaList = nil; 150 | } 151 | } 152 | 153 | if (mediaStyle == 1) { 154 | self.mediaType = MMStatusMediaObjectTypeImage; 155 | MMStatusImageMediaObject *mediaObject = [MMStatusImageMediaObject new]; 156 | NSMutableArray *imageInfos = [NSMutableArray new]; 157 | for (NSDictionary *media in mediaList) { 158 | MMStatusImageInfo *image = [MMStatusImageInfo new]; 159 | image.imageURLString = media[@"url"]; 160 | image.imageWidth = [media[@"size"][@"width"] doubleValue]; 161 | image.imageHeight = [media[@"size"][@"height"] doubleValue]; 162 | [imageInfos addObject:image]; 163 | } 164 | mediaObject.imageInfos = imageInfos.copy; 165 | self.mediaObject = mediaObject; 166 | } 167 | else if (mediaStyle == 3 || mediaStyle == 4 || mediaStyle == 5) { 168 | self.mediaType = MMStatusMediaObjectTypeLink; 169 | NSDictionary *media = mediaList.firstObject; 170 | NSString *title = contentObjDic[@"title"]; 171 | if (![title isKindOfClass:[NSString class]]) { 172 | title = media[@"title"]; 173 | } 174 | MMStatusLinkMediaObject *mediaObject = [MMStatusLinkMediaObject new]; 175 | mediaObject.linkURLString = contentObjDic[@"contentUrl"]; 176 | mediaObject.title = title; 177 | mediaObject.imageURLString = media[@"thumb"]; 178 | self.mediaObject = mediaObject; 179 | } 180 | } 181 | @end 182 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatusImageMediaObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusImageMediaObject.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusMediaObject.h" 10 | 11 | @interface MMStatusImageInfo : NSObject 12 | 13 | @property (nonatomic, strong) NSString *imageURLString; 14 | @property (nonatomic, strong) NSImage *image; 15 | @property (nonatomic, assign) CGFloat imageWidth; 16 | @property (nonatomic, assign) CGFloat imageHeight; 17 | 18 | @end 19 | 20 | @interface MMStatusImageMediaObject : MMStatusMediaObject 21 | 22 | @property (nonatomic, strong) NSArray *imageInfos; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatusImageMediaObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusImageMediaObject.m 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusImageMediaObject.h" 10 | 11 | @implementation MMStatusImageInfo 12 | 13 | @end 14 | @implementation MMStatusImageMediaObject 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatusLinkMediaObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusLinkMediaObject.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusMediaObject.h" 10 | 11 | @interface MMStatusLinkMediaObject : MMStatusMediaObject 12 | 13 | @property (nonatomic, strong) NSString *imageURLString; 14 | @property (nonatomic, strong) NSImage *image; 15 | @property (nonatomic, strong) NSString *title; 16 | @property (nonatomic, strong) NSString *linkURLString; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatusLinkMediaObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusLinkMediaObject.m 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusLinkMediaObject.h" 10 | 11 | @implementation MMStatusLinkMediaObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatusMediaObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusMediaObject.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MMStatusMediaObject : NSObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/Model/MMStatusMediaObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusMediaObject.m 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusMediaObject.h" 10 | 11 | @implementation MMStatusMediaObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Status/View/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusCell.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MMStatusCellDelegate.h" 11 | 12 | @class MMStatusMediaView; 13 | @class MMStatus; 14 | 15 | @interface MMStatusCell : NSTableCellView 16 | 17 | @property (weak) IBOutlet NSImageView *profileImageView; 18 | @property (weak) IBOutlet NSTextField *nameTextField; 19 | @property (weak) IBOutlet NSTextField *tagTextField; 20 | @property (weak) IBOutlet NSTextField *contentTextField; 21 | @property (weak) IBOutlet MMStatusMediaView *mediaView; 22 | @property (weak) MMStatusMediaView *mediaRealView; 23 | 24 | @property (nonatomic, strong, readonly) MMStatus *status; 25 | @property (nonatomic, weak) id delegate; 26 | 27 | @property (strong) IBOutlet NSLayoutConstraint *toTagTextFieldLayoutConstraint; 28 | @property (strong) IBOutlet NSLayoutConstraint *toContentTextFieldLayoutConstraint; 29 | 30 | - (void)updateMediaView:(MMStatusMediaView *)mediaView; 31 | - (void)updateViewWithStatus:(MMStatus *)status; 32 | 33 | + (CGFloat)calculateHeightForStatus:(MMStatus *)status inTableView:(NSTableView *)tableView; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusCellDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusCellDelegate.h 3 | // WeChatPlugin 4 | // 5 | // Created by nato on 2017/3/25. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MMStatusCell; 12 | @class MMStatusImageInfo; 13 | @protocol MMStatusCellDelegate 14 | 15 | @optional 16 | - (void)cell:(MMStatusCell *)cell didClickMediaLink:(NSString *)url; 17 | - (void)cell:(MMStatusCell *)cell didClickMediaImage:(MMStatusImageInfo *)imageInfo; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusImageMediaView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusImageMediaView.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusMediaView.h" 10 | 11 | @interface MMStatusImageMediaView : MMStatusMediaView 12 | 13 | @property (weak) IBOutlet NSImageView *imageView0; 14 | @property (weak) IBOutlet NSImageView *imageView1; 15 | @property (weak) IBOutlet NSImageView *imageView2; 16 | @property (weak) IBOutlet NSImageView *imageView3; 17 | @property (weak) IBOutlet NSImageView *imageView4; 18 | @property (weak) IBOutlet NSImageView *imageView5; 19 | @property (weak) IBOutlet NSImageView *imageView6; 20 | @property (weak) IBOutlet NSImageView *imageView7; 21 | @property (weak) IBOutlet NSImageView *imageView8; 22 | 23 | @property (nonatomic, strong, readonly) NSArray *imageViews; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusImageMediaView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusImageMediaView.m 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusImageMediaView.h" 10 | 11 | @implementation MMStatusImageMediaView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | _imageViews = @[self.imageView0, self.imageView1, self.imageView2, self.imageView3, self.imageView4, self.imageView5, self.imageView6, self.imageView7, self.imageView8]; 16 | for (NSImageView *imageView in _imageViews) { 17 | imageView.imageAlignment = NSImageAlignTopLeft; 18 | imageView.wantsLayer = true; 19 | imageView.layer.borderColor = [NSColor whiteColor].CGColor; 20 | imageView.layer.borderWidth = 1; 21 | } 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusImagePreviewView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusImagePreviewView.h 3 | // WeChatPlugin 4 | // 5 | // Created by Loveletter on 26/02/2018. 6 | // Copyright © 2018 CodeTips. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MMStatusImagePreviewView : NSImageView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusImagePreviewView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusImagePreviewView.m 3 | // WeChatPlugin 4 | // 5 | // Created by Loveletter on 26/02/2018. 6 | // Copyright © 2018 CodeTips. All rights reserved. 7 | // 8 | 9 | #import "MMStatusImagePreviewView.h" 10 | 11 | @implementation MMStatusImagePreviewView 12 | 13 | - (void) mouseDown:(NSEvent *)theEvent 14 | { 15 | [self removeFromSuperview]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusLinkMediaView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusLinkMediaView.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusMediaView.h" 10 | 11 | @interface MMStatusLinkMediaView : MMStatusMediaView 12 | 13 | @property (weak) IBOutlet NSImageView *iconImageView; 14 | @property (weak) IBOutlet NSTextField *titleTextField; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusLinkMediaView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusLinkMediaView.m 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusLinkMediaView.h" 10 | 11 | @implementation MMStatusLinkMediaView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | self.wantsLayer = true; 16 | self.layer.backgroundColor = [NSColor colorWithWhite:0.9 alpha:1.0].CGColor; 17 | self.iconImageView.wantsLayer = true; 18 | self.iconImageView.layer.backgroundColor = [NSColor colorWithWhite:0.9 alpha:1.0].CGColor; 19 | } 20 | 21 | - (void)drawRect:(NSRect)dirtyRect { 22 | [super drawRect:dirtyRect]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusLinkMediaView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusMediaView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusMediaView.h 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MMStatusMediaView : NSTableCellView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Status/View/MMStatusMediaView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMStatusMediaView.m 3 | // WeChatTimeLine 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMStatusMediaView.h" 10 | 11 | @implementation MMStatusMediaView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/TimeLine/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/Controller/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/TimeLine/Controller/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/Controller/MMTimeLineMainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMTimeLineMainViewController.h 3 | // MacWeChatTimeLinePlugin 4 | // 5 | // Created by nato on 16/8/16. 6 | // Copyright © 2016年 nato. All rights reserved. 7 | // 8 | 9 | #import "WeChatPlugin.h" 10 | 11 | @interface MMTimeLineMainViewController : MMContactsViewController 12 | 13 | - (void)tableView:(MMTableView *)arg1 rowGotMouseDown:(long long)arg2; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/Controller/MMTimeLineViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMTimeLineViewController.h 3 | // WeChatPlugin 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MMTimeLineViewController : NSViewController 12 | 13 | @property (weak) IBOutlet NSTableView *tableView; 14 | @property (weak) IBOutlet NSView *line; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/Mgr/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/TimeLine/Mgr/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/Mgr/MMTimeLineMgr.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMTimeLineMgr.h 3 | // WeChatPlugin 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MMTimeLineMgrDelegate.h" 11 | 12 | @class MMStatus; 13 | 14 | @interface MMTimeLineMgr : NSObject 15 | 16 | @property (nonatomic, weak) id delegate; 17 | 18 | - (void)updateTimeLineHead; 19 | - (void)updateTimeLineTail; 20 | 21 | - (NSUInteger)getTimeLineStatusCount; 22 | - (MMStatus *)getTimeLineStatusAtIndex:(NSUInteger)index; 23 | 24 | @property (nonatomic, strong) NSMutableArray * jsonlist; 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/Mgr/MMTimeLineMgr.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMTimeLineMgr.m 3 | // WeChatPlugin 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import "MMTimeLineMgr.h" 10 | #import "NSObject+ObjectMap.h" 11 | @interface MMTimeLineMgr () 12 | 13 | @property (nonatomic, assign, getter=isRequesting) BOOL requesting; 14 | @property (nonatomic, strong) NSString *firstPageMd5; 15 | @property (nonatomic, strong) SKBuiltinBuffer_t *session; 16 | @property (nonatomic, strong) NSMutableArray *statuses; 17 | 18 | @end 19 | 20 | @implementation MMTimeLineMgr 21 | 22 | #pragma mark - Network 23 | 24 | - (void)updateTimeLineHead { 25 | [self requestTimeLineDataAfterItemID:0]; 26 | } 27 | 28 | - (void)updateTimeLineTail { 29 | MMStatus *status = [self.statuses lastObject]; 30 | [self requestTimeLineDataAfterItemID:status.statusId]; 31 | } 32 | 33 | - (void)requestTimeLineDataAfterItemID:(unsigned long long)itemID { 34 | if (self.isRequesting) { 35 | return; 36 | } 37 | self.requesting = true; 38 | SnsTimeLineRequest *request = [[CBGetClass(SnsTimeLineRequest) alloc] init]; 39 | request.baseRequest = [CBGetClass(MMCGIRequestUtil) InitBaseRequestWithScene:0]; 40 | request.clientLatestId = 0; 41 | request.firstPageMd5 = itemID == 0 ? self.firstPageMd5 : @""; 42 | request.lastRequestTime = 0; 43 | request.maxId = itemID; 44 | request.minFilterId = 0; 45 | request.session = self.session; 46 | MMCGIWrap *cgiWrap = [[CBGetClass(MMCGIWrap) alloc] init]; 47 | cgiWrap.m_requestPb = request; 48 | cgiWrap.m_functionId = kMMCGIWrapTimeLineFunctionId; 49 | 50 | MMCGIService *cgiService = [[CBGetClass(MMServiceCenter) defaultCenter] getService:CBGetClass(MMCGIService)]; 51 | [cgiService RequestCGI:cgiWrap delegate:self]; 52 | 53 | } 54 | 55 | - (NSMutableArray *)jsonlist { 56 | if (!_jsonlist) { 57 | _jsonlist = [[NSMutableArray alloc] init]; 58 | } 59 | return _jsonlist; 60 | } 61 | #pragma mark - MMCGIDelegate 62 | 63 | - (void)OnResponseCGI:(BOOL)arg1 sessionId:(unsigned int)arg2 cgiWrap:(MMCGIWrap *)cgiWrap { 64 | NSLog(@"%d %d %@", arg1, arg2, cgiWrap); 65 | SnsTimeLineRequest *request = (SnsTimeLineRequest *)cgiWrap.m_requestPb; 66 | SnsTimeLineResponse *response = (SnsTimeLineResponse *)cgiWrap.m_responsePb; 67 | 68 | self.session = response.session; 69 | NSMutableArray *statuses = [NSMutableArray new]; 70 | NSString * jsonstr = @""; 71 | for (SnsObject *snsObject in response.objectList) { 72 | MMStatus *status = [MMStatus new]; 73 | [status updateWithSnsObject:snsObject]; 74 | [statuses addObject:status]; 75 | 76 | MMStatusSimple *st = [MMStatusSimple new]; 77 | [st updateWithSnsObject:snsObject]; 78 | NSString * stajson = [st JSONString]; 79 | jsonstr = [jsonstr stringByAppendingFormat:@"%@,",stajson]; 80 | } 81 | jsonstr = [jsonstr stringByAppendingFormat:@""]; 82 | NSLog(@"\n\njson:\n%@\n\n",jsonstr); 83 | 84 | dispatch_async(dispatch_get_main_queue(), ^{ 85 | BOOL isRefresh = request.maxId == 0; 86 | if (isRefresh) { 87 | self.firstPageMd5 = response.firstPageMd5; 88 | if (statuses.count) { 89 | self.statuses = statuses; 90 | } 91 | self.jsonlist = [@[jsonstr] mutableCopy]; 92 | } 93 | else { 94 | [self.statuses addObjectsFromArray:statuses]; 95 | [self.jsonlist addObject:jsonstr]; 96 | } 97 | self.requesting = false; 98 | if (self.delegate && [self.delegate respondsToSelector:@selector(onTimeLineStatusChange)]) { 99 | [self.delegate onTimeLineStatusChange]; 100 | } 101 | }); 102 | } 103 | 104 | #pragma mark - 105 | 106 | - (NSUInteger)getTimeLineStatusCount { 107 | return [self.statuses count]; 108 | } 109 | 110 | - (MMStatus *)getTimeLineStatusAtIndex:(NSUInteger)index { 111 | if (index >= self.statuses.count) { 112 | return nil; 113 | } 114 | else { 115 | return self.statuses[index]; 116 | } 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/Mgr/MMTimeLineMgrDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMTimeLineMgrDelegate.h 3 | // WeChatPlugin 4 | // 5 | // Created by nato on 2017/1/22. 6 | // Copyright © 2017年 github:natoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol MMTimeLineMgrDelegate 12 | 13 | - (void)onTimeLineStatusChange; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/View/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/TimeLine/View/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/TimeLine/View/MMTimeLineViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 81 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Utils/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/Sources/Utils/.DS_Store -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Utils/TKHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKHelper.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface TKHelper : NSObject 13 | 14 | /** 15 | 替换对象方法 16 | 17 | @param originalClass 原始类 18 | @param originalSelector 原始类的方法 19 | @param swizzledClass 替换类 20 | @param swizzledSelector 替换类的方法 21 | */ 22 | void tk_hookMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector); 23 | 24 | /** 25 | 替换类方法 26 | 27 | @param originalClass 原始类 28 | @param originalSelector 原始类的类方法 29 | @param swizzledClass 替换类 30 | @param swizzledSelector 替换类的类方法 31 | */ 32 | void tk_hookClassMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector); 33 | 34 | void tk_addMethod(Class originalClass,Class swizzledClass, SEL swizzledSelector); 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Utils/TKHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKHelper.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKHelper.h" 10 | 11 | @implementation TKHelper 12 | 13 | /** 14 | 替换对象方法 15 | 16 | @param originalClass 原始类 17 | @param originalSelector 原始类的方法 18 | @param swizzledClass 替换类 19 | @param swizzledSelector 替换类的方法 20 | */ 21 | void tk_hookMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector) { 22 | Method originalMethod = class_getInstanceMethod(originalClass, originalSelector); 23 | Method swizzledMethod = class_getInstanceMethod(swizzledClass, swizzledSelector); 24 | if(originalMethod && swizzledMethod) { 25 | method_exchangeImplementations(originalMethod, swizzledMethod); 26 | } 27 | } 28 | 29 | /** 30 | 替换类方法 31 | 32 | @param originalClass 原始类 33 | @param originalSelector 原始类的类方法 34 | @param swizzledClass 替换类 35 | @param swizzledSelector 替换类的类方法 36 | */ 37 | void tk_hookClassMethod(Class originalClass, SEL originalSelector, Class swizzledClass, SEL swizzledSelector) { 38 | Method originalMethod = class_getClassMethod(originalClass, originalSelector); 39 | Method swizzledMethod = class_getClassMethod(swizzledClass, swizzledSelector); 40 | if(originalMethod && swizzledMethod) { 41 | method_exchangeImplementations(originalMethod, swizzledMethod); 42 | } 43 | } 44 | 45 | void tk_addMethod(Class originalClass,Class swizzledClass, SEL swizzledSelector) 46 | { 47 | Method swizzledMethod = class_getInstanceMethod(swizzledClass, swizzledSelector); 48 | class_addMethod(originalClass,swizzledSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod)); 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Utils/XMLReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // XmlReader.h 3 | // XmlReader 4 | // 5 | // Created by Benoit C on 10/31/13. 6 | // Copyright (c) 2013 Benoit Caccinolo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface XMLReader : NSObject 13 | { 14 | NSMutableArray *dictionaryStack; 15 | NSMutableString *textInProgress; 16 | // NSError **errorPointer; 17 | } 18 | 19 | + (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)errorPointer; 20 | + (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)errorPointer; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Utils/XMLReader.m: -------------------------------------------------------------------------------- 1 | // 2 | // XmlReader.m 3 | // XmlReader 4 | // 5 | // Created by Benoit C on 10/31/13. 6 | // Copyright (c) 2013 Benoit Caccinolo. All rights reserved. 7 | // 8 | 9 | #import "XMLReader.h" 10 | 11 | NSString *const kXMLReaderTextNodeKey = @"text"; 12 | 13 | @interface XMLReader (Internal) 14 | 15 | - (id)initWithError:(NSError **)error; 16 | - (NSDictionary *)objectWithData:(NSData *)data; 17 | 18 | @end 19 | 20 | 21 | @implementation XMLReader 22 | 23 | #pragma mark - 24 | #pragma mark Public methods 25 | 26 | + (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)error 27 | { 28 | XMLReader *reader = [[XMLReader alloc] initWithError:error]; 29 | NSDictionary *rootDictionary = [reader objectWithData:data]; 30 | // [reader release]; 31 | return rootDictionary; 32 | } 33 | 34 | + (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)error 35 | { 36 | NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 37 | return [XMLReader dictionaryForXMLData:data error:error]; 38 | } 39 | 40 | #pragma mark - 41 | #pragma mark Parsing 42 | 43 | - (id)initWithError:(NSError **)error 44 | { 45 | if (self = [super init]) 46 | { 47 | // errorPointer = error; 48 | } 49 | return self; 50 | } 51 | 52 | //- (void)dealloc 53 | //{ 54 | // [dictionaryStack release]; 55 | // [textInProgress release]; 56 | // [super dealloc]; 57 | //} 58 | 59 | - (NSDictionary *)objectWithData:(NSData *)data 60 | { 61 | // Clear out any old data 62 | // [dictionaryStack release]; 63 | // [textInProgress release]; 64 | 65 | dictionaryStack = [[NSMutableArray alloc] init]; 66 | textInProgress = [[NSMutableString alloc] init]; 67 | 68 | // Initialize the stack with a fresh dictionary 69 | [dictionaryStack addObject:[NSMutableDictionary dictionary]]; 70 | 71 | // Parse the XML 72 | NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; 73 | parser.delegate = self; 74 | BOOL success = [parser parse]; 75 | 76 | // Return the stack's root dictionary on success 77 | if (success) 78 | { 79 | NSDictionary *resultDict = [dictionaryStack objectAtIndex:0]; 80 | return resultDict; 81 | } 82 | 83 | return nil; 84 | } 85 | 86 | #pragma mark - 87 | #pragma mark NSXMLParserDelegate methods 88 | 89 | - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 90 | { 91 | // Get the dictionary for the current level in the stack 92 | NSMutableDictionary *parentDict = [dictionaryStack lastObject]; 93 | 94 | // Create the child dictionary for the new element, and initilaize it with the attributes 95 | NSMutableDictionary *childDict = [NSMutableDictionary dictionary]; 96 | [childDict addEntriesFromDictionary:attributeDict]; 97 | 98 | // If there's already an item for this key, it means we need to create an array 99 | id existingValue = [parentDict objectForKey:elementName]; 100 | if (existingValue) 101 | { 102 | NSMutableArray *array = nil; 103 | if ([existingValue isKindOfClass:[NSMutableArray class]]) 104 | { 105 | // The array exists, so use it 106 | array = (NSMutableArray *) existingValue; 107 | } 108 | else 109 | { 110 | // Create an array if it doesn't exist 111 | array = [NSMutableArray array]; 112 | [array addObject:existingValue]; 113 | 114 | // Replace the child dictionary with an array of children dictionaries 115 | [parentDict setObject:array forKey:elementName]; 116 | } 117 | 118 | // Add the new child dictionary to the array 119 | [array addObject:childDict]; 120 | } 121 | else 122 | { 123 | // No existing value, so update the dictionary 124 | [parentDict setObject:childDict forKey:elementName]; 125 | } 126 | 127 | // Update the stack 128 | [dictionaryStack addObject:childDict]; 129 | } 130 | 131 | - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 132 | { 133 | // Pop the current dict 134 | [dictionaryStack removeLastObject]; 135 | // Set the text property 136 | if ([textInProgress length] > 0) 137 | { 138 | 139 | // Update the parent dict with text info 140 | NSMutableDictionary *dictInProgress = [dictionaryStack lastObject]; 141 | 142 | [dictInProgress setObject:textInProgress forKey:elementName]; 143 | 144 | textInProgress = [[NSMutableString alloc] init]; 145 | } 146 | else { 147 | 148 | } 149 | } 150 | 151 | - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 152 | { 153 | // Build the text value 154 | [textInProgress appendString:string]; 155 | } 156 | 157 | - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 158 | { 159 | // Set the error pointer to the parser's error object 160 | // *errorPointer = parseError; 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Vendor/fishhook.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #ifndef fishhook_h 25 | #define fishhook_h 26 | 27 | #include 28 | #include 29 | 30 | #if !defined(FISHHOOK_EXPORT) 31 | #define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) 32 | #else 33 | #define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif //__cplusplus 39 | 40 | /* 41 | * A structure representing a particular intended rebinding from a symbol 42 | * name to its replacement 43 | */ 44 | struct rebinding { 45 | const char *name; 46 | void *replacement; 47 | void **replaced; 48 | }; 49 | 50 | /* 51 | * For each rebinding in rebindings, rebinds references to external, indirect 52 | * symbols with the specified name to instead point at replacement for each 53 | * image in the calling process as well as for all future images that are loaded 54 | * by the process. If rebind_functions is called more than once, the symbols to 55 | * rebind are added to the existing list of rebindings, and if a given symbol 56 | * is rebound more than once, the later rebinding will take precedence. 57 | */ 58 | FISHHOOK_VISIBILITY 59 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); 60 | 61 | /* 62 | * Rebinds as above, but only in the specified image. The header should point 63 | * to the mach-o header, the slide should be the slide offset. Others as above. 64 | */ 65 | FISHHOOK_VISIBILITY 66 | int rebind_symbols_image(void *header, 67 | intptr_t slide, 68 | struct rebinding rebindings[], 69 | size_t rebindings_nel); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif //__cplusplus 74 | 75 | #endif //fishhook_h 76 | 77 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyCell.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/21. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TKAutoReplyModel.h" 11 | 12 | @interface TKAutoReplyCell : NSControl 13 | 14 | @property (nonatomic, strong) TKAutoReplyModel *model; 15 | @property (nonatomic, copy) void (^updateModel)(void); 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyCell.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/21. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKAutoReplyCell.h" 10 | 11 | @interface TKAutoReplyCell () 12 | 13 | @property (nonatomic, strong) NSButton *selectBtn; 14 | @property (nonatomic, strong) NSTextField *keywordLabel; 15 | @property (nonatomic, strong) NSTextField *replyContentLabel; 16 | @property (nonatomic, strong) NSBox *bottomLine; 17 | 18 | @end 19 | 20 | @implementation TKAutoReplyCell 21 | 22 | - (instancetype)init { 23 | self = [super init]; 24 | if (self) { 25 | [self initSubviews]; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)initSubviews { 31 | self.selectBtn = ({ 32 | NSButton *btn = [NSButton tk_checkboxWithTitle:@"" target:self action:@selector(clickSelectBtn:)]; 33 | btn.frame = NSMakeRect(5, 15, 20, 20); 34 | 35 | btn; 36 | }); 37 | 38 | self.keywordLabel = ({ 39 | NSTextField *label = [NSTextField tk_labelWithString:@""]; 40 | label.placeholderString = @"关键字"; 41 | [[label cell] setLineBreakMode:NSLineBreakByCharWrapping]; 42 | [[label cell] setTruncatesLastVisibleLine:YES]; 43 | label.font = [NSFont systemFontOfSize:10]; 44 | label.frame = NSMakeRect(30, 30, 160, 15); 45 | 46 | label; 47 | }); 48 | 49 | self.replyContentLabel = ({ 50 | NSTextField *label = [NSTextField tk_labelWithString:@""]; 51 | label.placeholderString = @"回复内容"; 52 | [[label cell] setLineBreakMode:NSLineBreakByCharWrapping]; 53 | [[label cell] setTruncatesLastVisibleLine:YES]; 54 | label.frame = NSMakeRect(30, 10, 160, 15); 55 | 56 | label; 57 | }); 58 | 59 | self.bottomLine = ({ 60 | NSBox *v = [[NSBox alloc] init]; 61 | v.boxType = NSBoxSeparator; 62 | v.frame = NSMakeRect(0, 0, 200, 1); 63 | 64 | v; 65 | }); 66 | 67 | [self addSubviews:@[self.selectBtn, 68 | self.keywordLabel, 69 | self.replyContentLabel, 70 | self.bottomLine]]; 71 | } 72 | 73 | - (void)clickSelectBtn:(NSButton *)btn { 74 | self.model.enable = btn.state; 75 | if (!self.model.enableSingleReply && !self.model.enableGroupReply && btn.state == YES) { 76 | self.model.enableSingleReply = YES; 77 | if (self.updateModel) self.updateModel(); 78 | } 79 | } 80 | 81 | - (void)setModel:(TKAutoReplyModel *)model { 82 | _model = model; 83 | if (model.keyword == nil && model.replyContent == nil) return; 84 | 85 | self.selectBtn.state = model.enable; 86 | self.keywordLabel.stringValue = model.keyword != nil ? model.keyword : @""; 87 | self.replyContentLabel.stringValue = model.replyContent != nil ? model.replyContent : @""; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyContentView.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/20. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TKAutoReplyModel.h" 11 | 12 | @interface TKAutoReplyContentView : NSView 13 | 14 | @property (nonatomic, strong) TKAutoReplyModel *model; 15 | @property (nonatomic, copy) void (^endEdit)(void); 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyContentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyContentView.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/20. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKAutoReplyContentView.h" 10 | 11 | @interface TKAutoReplyContentView () 12 | 13 | @property (nonatomic, strong) NSTextField *keywordLabel; 14 | @property (nonatomic, strong) NSTextField *keywordTextField; 15 | @property (nonatomic, strong) NSTextField *autoReplyLabel; 16 | @property (nonatomic, strong) NSTextField *autoReplyContentField; 17 | @property (nonatomic, strong) NSButton *enableGroupReplyBtn; 18 | @property (nonatomic, strong) NSButton *enableSingleReplyBtn; 19 | @property (nonatomic, strong) NSButton *enableRegexBtn; 20 | 21 | @end 22 | 23 | @implementation TKAutoReplyContentView 24 | 25 | - (instancetype)init { 26 | self = [super init]; 27 | if (self) { 28 | [self initSubviews]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)initSubviews { 34 | self.enableRegexBtn = ({ 35 | NSButton *btn = [NSButton tk_checkboxWithTitle:@"开启正则匹配" target:self action:@selector(clickEnableRegexBtn:)]; 36 | btn.frame = NSMakeRect(20, 15, 400, 20); 37 | 38 | btn; 39 | }); 40 | 41 | self.enableGroupReplyBtn = ({ 42 | NSButton *btn = [NSButton tk_checkboxWithTitle:@"开启群聊自动回复" target:self action:@selector(clickEnableGroupBtn:)]; 43 | btn.frame = NSMakeRect(20, 40, 400, 20); 44 | 45 | btn; 46 | }); 47 | 48 | self.enableSingleReplyBtn = ({ 49 | NSButton *btn = [NSButton tk_checkboxWithTitle:@"开启私聊自动回复" target:self action:@selector(clickEnableSingleBtn:)]; 50 | btn.frame = NSMakeRect(200, 40, 400, 20); 51 | 52 | btn; 53 | }); 54 | 55 | self.autoReplyContentField = ({ 56 | NSTextField *textField = [[NSTextField alloc] init]; 57 | textField.frame = NSMakeRect(20, 70, 350, 175); 58 | textField.placeholderString = @"请输入自动回复的内容(‘|’ 为随机回复其中任一内容)"; 59 | textField.delegate = self; 60 | 61 | textField; 62 | }); 63 | 64 | self.autoReplyLabel = ({ 65 | NSTextField *label = [NSTextField tk_labelWithString:@"自动回复:"]; 66 | label.frame = NSMakeRect(20, 250, 350, 20); 67 | 68 | label; 69 | }); 70 | 71 | self.keywordTextField = ({ 72 | NSTextField *textField = [[NSTextField alloc] init]; 73 | textField.frame = NSMakeRect(20, 290, 350, 50); 74 | textField.placeholderString = @"请输入关键字( ‘*’ 为任何消息都回复,‘|’ 为匹配多个关键字)"; 75 | textField.delegate = self; 76 | 77 | textField; 78 | }); 79 | 80 | self.keywordLabel = ({ 81 | NSTextField *label = [NSTextField tk_labelWithString:@"关键字:"]; 82 | label.frame = NSMakeRect(20, 345, 350, 20); 83 | 84 | label; 85 | }); 86 | 87 | [self addSubviews:@[self.enableRegexBtn, 88 | self.enableGroupReplyBtn, 89 | self.enableSingleReplyBtn, 90 | self.autoReplyContentField, 91 | self.autoReplyLabel, 92 | self.keywordTextField, 93 | self.keywordLabel]]; 94 | } 95 | 96 | - (void)clickEnableRegexBtn:(NSButton *)btn { 97 | self.model.enableRegex = btn.state; 98 | } 99 | 100 | - (void)clickEnableGroupBtn:(NSButton *)btn { 101 | self.model.enableGroupReply = btn.state; 102 | if (btn.state) { 103 | self.model.enable = YES; 104 | } else if(!self.model.enableSingleReply) { 105 | self.model.enable = NO; 106 | } 107 | 108 | if (self.endEdit) self.endEdit(); 109 | } 110 | 111 | - (void)clickEnableSingleBtn:(NSButton *)btn { 112 | self.model.enableSingleReply = btn.state; 113 | if (btn.state) { 114 | self.model.enable = YES; 115 | } else if(!self.model.enableGroupReply) { 116 | self.model.enable = NO; 117 | } 118 | if (self.endEdit) self.endEdit(); 119 | } 120 | 121 | - (void)viewDidMoveToSuperview { 122 | [super viewDidMoveToSuperview]; 123 | self.layer.backgroundColor = [kBG2 CGColor]; 124 | self.layer.borderWidth = 1; 125 | self.layer.borderColor = [TK_RGBA(0, 0, 0, 0.1) CGColor]; 126 | self.layer.cornerRadius = 3; 127 | self.layer.masksToBounds = YES; 128 | [self.layer setNeedsDisplay]; 129 | } 130 | 131 | - (void)setModel:(TKAutoReplyModel *)model { 132 | _model = model; 133 | self.keywordTextField.stringValue = model.keyword != nil ? model.keyword : @""; 134 | self.autoReplyContentField.stringValue = model.replyContent != nil ? model.replyContent : @""; 135 | self.enableGroupReplyBtn.state = model.enableGroupReply; 136 | self.enableSingleReplyBtn.state = model.enableSingleReply; 137 | self.enableRegexBtn.state = model.enableRegex; 138 | } 139 | 140 | - (void)controlTextDidEndEditing:(NSNotification *)notification { 141 | if (self.endEdit) self.endEdit(); 142 | } 143 | 144 | - (void)controlTextDidChange:(NSNotification *)notification { 145 | NSControl *control = notification.object; 146 | if (control == self.keywordTextField) { 147 | self.model.keyword = self.keywordTextField.stringValue; 148 | } else if (control == self.autoReplyContentField) { 149 | self.model.replyContent = self.autoReplyContentField.stringValue; 150 | } 151 | } 152 | 153 | - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector { 154 | BOOL result = NO; 155 | 156 | if (commandSelector == @selector(insertNewline:)) { 157 | [textView insertNewlineIgnoringFieldEditor:self]; 158 | result = YES; 159 | } else if (commandSelector == @selector(insertTab:)) { 160 | if (control == self.keywordTextField) { 161 | [self.autoReplyContentField becomeFirstResponder]; 162 | } else if (control == self.autoReplyContentField) { 163 | [self.keywordTextField becomeFirstResponder]; 164 | } 165 | } 166 | 167 | return result; 168 | } 169 | 170 | @end 171 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Views/RemoteControl/TKRemoteControlCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlCell.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKRemoteControlCell : NSView 12 | 13 | - (void)setupWithData:(id)data; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/Views/RemoteControl/TKRemoteControlCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlCell.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKRemoteControlCell.h" 10 | #import "TKRemoteControlModel.h" 11 | 12 | @interface TKRemoteControlCell () 13 | 14 | @property (nonatomic, strong) NSButton *selectBtn; 15 | @property (nonatomic, strong) NSTextField *textField; 16 | @property (nonatomic, strong) TKRemoteControlModel *model; 17 | 18 | @end 19 | 20 | @implementation TKRemoteControlCell 21 | 22 | - (instancetype)init { 23 | self = [super init]; 24 | if (self) { 25 | [self initSubviews]; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)initSubviews { 31 | self.selectBtn = ({ 32 | NSButton *btn = [NSButton tk_checkboxWithTitle:@"" target:self action:@selector(clickSelectBtn:)]; 33 | btn.frame = NSMakeRect(50, 10, 150, 30); 34 | 35 | btn; 36 | }); 37 | 38 | self.textField = ({ 39 | NSTextField *v = [[NSTextField alloc] init]; 40 | v.frame = NSMakeRect(200, 10, 250, 30); 41 | v.placeholderString = @"请输入匹配的关键词"; 42 | v.layer.cornerRadius = 10; 43 | v.layer.masksToBounds = YES; 44 | [v.layer setNeedsDisplay]; 45 | v.editable = YES; 46 | v.delegate = self; 47 | 48 | v; 49 | }); 50 | 51 | [self addSubviews:@[self.selectBtn, self.textField]]; 52 | } 53 | 54 | - (void)clickSelectBtn:(NSButton *)btn { 55 | self.model.enable = btn.state; 56 | } 57 | 58 | - (void)setupWithData:(id)data { 59 | TKRemoteControlModel *model = data; 60 | self.model = model; 61 | self.selectBtn.title = model.function; 62 | self.selectBtn.state = model.enable; 63 | self.textField.stringValue = model.keyword; 64 | } 65 | 66 | - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor { 67 | NSString *string = control.stringValue; 68 | self.model.keyword = string; 69 | return YES; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/WindowControllers/AutoReply/TKAutoReplyWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyWindowController.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TKAutoReplyModel.h" 11 | 12 | @interface TKAutoReplyWindowController : NSWindowController 13 | 14 | @property (nonatomic, copy) TKAutoReplyModel *model; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/WindowControllers/AutoReply/TKAutoReplyWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKAutoReplyWindowController.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKAutoReplyWindowController.h" 10 | #import "TKAutoReplyContentView.h" 11 | #import "WeChatPlugin.h" 12 | #import "TKAutoReplyCell.h" 13 | 14 | @interface TKAutoReplyWindowController () 15 | 16 | @property (nonatomic, strong) NSTableView *tableView; 17 | @property (nonatomic, strong) TKAutoReplyContentView *contentView; 18 | @property (nonatomic, strong) NSButton *addButton; 19 | @property (nonatomic, strong) NSButton *reduceButton; 20 | @property (nonatomic, strong) NSAlert *alert; 21 | 22 | @property (nonatomic, strong) NSMutableArray *autoReplyModels; 23 | @property (nonatomic, assign) NSInteger lastSelectIndex; 24 | 25 | @end 26 | 27 | @implementation TKAutoReplyWindowController 28 | 29 | - (void)windowDidLoad { 30 | [super windowDidLoad]; 31 | 32 | [self initSubviews]; 33 | [self setup]; 34 | } 35 | 36 | - (void)showWindow:(id)sender { 37 | [super showWindow:sender]; 38 | [self.tableView reloadData]; 39 | [self.contentView setHidden:YES]; 40 | if (self.autoReplyModels && self.autoReplyModels.count == 0) { 41 | [self addModel]; 42 | } 43 | if (self.autoReplyModels.count > 0 && self.tableView) { 44 | [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:self.autoReplyModels.count - 1] byExtendingSelection:YES]; 45 | } 46 | } 47 | 48 | - (void)initSubviews { 49 | NSScrollView *scrollView = ({ 50 | NSScrollView *scrollView = [[NSScrollView alloc] init]; 51 | scrollView.hasVerticalScroller = YES; 52 | scrollView.frame = NSMakeRect(30, 50, 200, 375); 53 | scrollView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 54 | 55 | scrollView; 56 | }); 57 | 58 | self.tableView = ({ 59 | NSTableView *tableView = [[NSTableView alloc] init]; 60 | tableView.frame = scrollView.bounds; 61 | tableView.allowsTypeSelect = YES; 62 | tableView.delegate = self; 63 | tableView.dataSource = self; 64 | NSTableColumn *column = [[NSTableColumn alloc] init]; 65 | column.title = @"自动回复列表"; 66 | column.width = 200; 67 | [tableView addTableColumn:column]; 68 | 69 | tableView; 70 | }); 71 | 72 | self.contentView = ({ 73 | TKAutoReplyContentView *contentView = [[TKAutoReplyContentView alloc] init]; 74 | contentView.frame = NSMakeRect(250, 50, 400, 375); 75 | contentView.hidden = YES; 76 | 77 | contentView; 78 | }); 79 | 80 | self.addButton = ({ 81 | NSButton *btn = [NSButton tk_buttonWithTitle:@"+" target:self action:@selector(addModel)]; 82 | btn.frame = NSMakeRect(30, 10, 40, 40); 83 | btn.bezelStyle = NSBezelStyleTexturedRounded; 84 | 85 | btn; 86 | }); 87 | 88 | self.reduceButton = ({ 89 | NSButton *btn = [NSButton tk_buttonWithTitle:@"-" target:self action:@selector(reduceModel)]; 90 | btn.frame = NSMakeRect(80, 10, 40, 40); 91 | btn.bezelStyle = NSBezelStyleTexturedRounded; 92 | btn.enabled = NO; 93 | 94 | btn; 95 | }); 96 | 97 | self.alert = ({ 98 | NSAlert *alert = [[NSAlert alloc] init]; 99 | [alert addButtonWithTitle:@"确定"]; 100 | [alert setMessageText:@"您还有一条自动回复设置未完成"]; 101 | [alert setInformativeText:@"请完善未完成的自动回复设置"]; 102 | 103 | alert; 104 | }); 105 | 106 | scrollView.contentView.documentView = self.tableView; 107 | 108 | [self.window.contentView addSubviews:@[scrollView, 109 | self.contentView, 110 | self.addButton, 111 | self.reduceButton]]; 112 | } 113 | 114 | - (void)setup { 115 | self.window.title = @"自动回复设置"; 116 | self.window.contentView.layer.backgroundColor = [kBG1 CGColor]; 117 | [self.window.contentView.layer setNeedsDisplay]; 118 | 119 | self.lastSelectIndex = -1; 120 | self.autoReplyModels = [[TKWeChatPluginConfig sharedConfig] autoReplyModels]; 121 | [self.tableView reloadData]; 122 | 123 | __weak typeof(self) weakSelf = self; 124 | self.contentView.endEdit = ^(void) { 125 | [weakSelf.tableView reloadData]; 126 | if (weakSelf.lastSelectIndex != -1) { 127 | [weakSelf.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:weakSelf.lastSelectIndex] byExtendingSelection:YES]; 128 | } 129 | }; 130 | } 131 | 132 | /** 133 | 关闭窗口事件 134 | 135 | */ 136 | - (BOOL)windowShouldClose:(id)sender { 137 | [[TKWeChatPluginConfig sharedConfig] saveAutoReplyModels]; 138 | return YES; 139 | } 140 | 141 | #pragma mark - addButton & reduceButton ClickAction 142 | - (void)addModel { 143 | if (self.contentView.hidden) { 144 | self.contentView.hidden = NO; 145 | } 146 | __block NSInteger emptyModelIndex = -1; 147 | [self.autoReplyModels enumerateObjectsUsingBlock:^(TKAutoReplyModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 148 | if (model.hasEmptyKeywordOrReplyContent) { 149 | emptyModelIndex = idx; 150 | *stop = YES; 151 | } 152 | }]; 153 | 154 | if (self.autoReplyModels.count > 0 && emptyModelIndex != -1) { 155 | [self.alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { 156 | if(returnCode == NSAlertFirstButtonReturn){ 157 | if (self.tableView.selectedRow != -1) { 158 | [self.tableView deselectRow:self.tableView.selectedRow]; 159 | } 160 | [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:emptyModelIndex] byExtendingSelection:YES]; 161 | } 162 | }]; 163 | return; 164 | }; 165 | 166 | TKAutoReplyModel *model = [[TKAutoReplyModel alloc] init]; 167 | [self.autoReplyModels addObject:model]; 168 | [self.tableView reloadData]; 169 | self.contentView.model = model; 170 | 171 | [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:self.autoReplyModels.count - 1] byExtendingSelection:YES]; 172 | } 173 | 174 | - (void)reduceModel { 175 | NSInteger index = self.tableView.selectedRow; 176 | if (index > -1) { 177 | [self.autoReplyModels removeObjectAtIndex:index]; 178 | [self.tableView reloadData]; 179 | if (self.autoReplyModels.count == 0) { 180 | self.contentView.hidden = YES; 181 | self.reduceButton.enabled = NO; 182 | } else { 183 | [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:self.autoReplyModels.count - 1] byExtendingSelection:YES]; 184 | } 185 | } 186 | } 187 | 188 | #pragma mark - NSTableViewDataSource && NSTableViewDelegate 189 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { 190 | return self.autoReplyModels.count; 191 | } 192 | 193 | - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { 194 | TKAutoReplyCell *cell = [[TKAutoReplyCell alloc] init]; 195 | cell.frame = NSMakeRect(0, 0, self.tableView.frame.size.width, 40); 196 | cell.model = self.autoReplyModels[row]; 197 | __weak typeof(self) weakSelf = self; 198 | cell.updateModel = ^{ 199 | weakSelf.contentView.model = weakSelf.autoReplyModels[row]; 200 | }; 201 | return cell; 202 | } 203 | 204 | - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row { 205 | return 50; 206 | } 207 | 208 | - (void)tableViewSelectionDidChange:(NSNotification *)notification { 209 | NSTableView *tableView = notification.object; 210 | self.contentView.hidden = tableView.selectedRow == -1; 211 | self.reduceButton.enabled = tableView.selectedRow != -1; 212 | 213 | if (tableView.selectedRow != -1) { 214 | TKAutoReplyModel *model = self.autoReplyModels[tableView.selectedRow]; 215 | self.contentView.model = model; 216 | self.lastSelectIndex = tableView.selectedRow; 217 | __block NSInteger emptyModelIndex = -1; 218 | [self.autoReplyModels enumerateObjectsUsingBlock:^(TKAutoReplyModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 219 | if (model.hasEmptyKeywordOrReplyContent) { 220 | emptyModelIndex = idx; 221 | *stop = YES; 222 | } 223 | }]; 224 | 225 | if (emptyModelIndex != -1 && tableView.selectedRow != emptyModelIndex) { 226 | [self.alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { 227 | if(returnCode == NSAlertFirstButtonReturn){ 228 | if (self.tableView.selectedRow != -1) { 229 | [self.tableView deselectRow:self.tableView.selectedRow]; 230 | } 231 | [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:emptyModelIndex] byExtendingSelection:YES]; 232 | } 233 | }]; 234 | } 235 | } 236 | } 237 | 238 | @end 239 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/WindowControllers/AutoReply/TKAutoReplyWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlWindowController.h 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TKRemoteControlWindowController : NSWindowController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TKRemoteControlWindowController.m 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/8/8. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import "TKRemoteControlWindowController.h" 10 | #import "TKRemoteControlModel.h" 11 | #import "TKWeChatPluginConfig.h" 12 | #import "TKRemoteControlCell.h" 13 | 14 | @interface TKRemoteControlWindowController () 15 | 16 | @property (nonatomic, weak) IBOutlet NSTabView *tabView; 17 | @property (nonatomic, strong) NSTableView *tableView; 18 | @property (nonatomic, strong) NSArray *remoteControlModels; 19 | 20 | @end 21 | 22 | @implementation TKRemoteControlWindowController 23 | 24 | - (void)windowDidLoad { 25 | [super windowDidLoad]; 26 | 27 | [self setup]; 28 | [self initSubviews]; 29 | } 30 | 31 | - (void)initSubviews { 32 | 33 | CGFloat tabViewWidth = self.tabView.frame.size.width; 34 | CGFloat tabViewHeight = self.tabView.frame.size.height; 35 | 36 | self.tableView = ({ 37 | NSTableView *tableView = [[NSTableView alloc] init]; 38 | tableView.frame = NSMakeRect(50, 50, tabViewWidth, tabViewHeight); 39 | tableView.delegate = self; 40 | tableView.dataSource = self; 41 | NSTableColumn *column = [[NSTableColumn alloc] init]; 42 | column.width = tabViewWidth - 100; 43 | [tableView addTableColumn:column]; 44 | tableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleNone; 45 | tableView.backgroundColor = [NSColor clearColor]; 46 | 47 | tableView; 48 | }); 49 | 50 | [self.tabView addSubview:self.tableView]; 51 | } 52 | 53 | - (void)setup { 54 | self.window.contentView.layer.backgroundColor = [NSColor whiteColor].CGColor; 55 | [self.window.contentView.layer setNeedsDisplay]; 56 | self.remoteControlModels = [[TKWeChatPluginConfig sharedConfig] remoteControlModels][0]; 57 | } 58 | 59 | /** 60 | 关闭窗口事件 61 | 62 | */ 63 | - (BOOL)windowShouldClose:(id)sender { 64 | [[TKWeChatPluginConfig sharedConfig] saveRemoteControlModels]; 65 | return YES; 66 | } 67 | 68 | #pragma mark - NSTableViewDataSource && NSTableViewDelegate 69 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{ 70 | return self.remoteControlModels.count; 71 | } 72 | 73 | - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{ 74 | TKRemoteControlCell *cell = [[TKRemoteControlCell alloc] init]; 75 | cell.frame = NSMakeRect(0, 0, self.tabView.frame.size.width, 40); 76 | [cell setupWithData:self.remoteControlModels[row]]; 77 | 78 | return cell; 79 | } 80 | 81 | - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row{ 82 | return 50; 83 | } 84 | 85 | #pragma mark - NSTabViewDelegate 86 | - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem { 87 | NSInteger selectTabIndex = [tabViewItem.identifier integerValue]; 88 | self.remoteControlModels = [[TKWeChatPluginConfig sharedConfig] remoteControlModels][selectTabIndex]; 89 | [self.tableView reloadData]; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /WeChatPlugin/TKRemoteControlCommands.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | executeCommand 8 | open /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app || open /System/Library/CoreServices/ScreenSaverEngine.app 9 | keyword 10 | ScreenSave 11 | function 12 | 屏幕保护 13 | enable 14 | 15 | command 16 | #remote.screensaver 17 | 18 | 19 | executeCommand 20 | /System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend 21 | keyword 22 | LockScreen 23 | function 24 | 锁屏 25 | enable 26 | 27 | command 28 | #remote.lockscreen 29 | 30 | 31 | executeCommand 32 | sleep 33 | keyword 34 | Sleep 35 | function 36 | 休眠 37 | enable 38 | 39 | command 40 | #remote.sleep 41 | 42 | 43 | executeCommand 44 | shutdown 45 | keyword 46 | Shutdown 47 | function 48 | 关机 49 | enable 50 | 51 | command 52 | #remote.shutdown 53 | 54 | 55 | executeCommand 56 | restart 57 | keyword 58 | Restart 59 | function 60 | 重启 61 | enable 62 | 63 | command 64 | #remote.restart 65 | 66 | 67 | executeCommand 68 | empty 69 | keyword 70 | EmptyTrash 71 | function 72 | 清空废纸篓 73 | enable 74 | 75 | command 76 | #remote.emptytrash 77 | 78 | 79 | 80 | 81 | executeCommand 82 | killQQ 83 | keyword 84 | KillQQ 85 | function 86 | 退出 QQ 87 | enable 88 | 89 | 90 | 91 | executeCommand 92 | killWeChat 93 | keyword 94 | KillWeChat 95 | function 96 | 退出 WeChat 97 | enable 98 | 99 | 100 | 101 | executeCommand 102 | killChrome 103 | keyword 104 | KillChrome 105 | function 106 | 退出 Chrome 107 | enable 108 | 109 | 110 | 111 | executeCommand 112 | killSafari 113 | keyword 114 | KillSafari 115 | function 116 | 退出 Safari 117 | enable 118 | 119 | 120 | 121 | executeCommand 122 | killAll 123 | keyword 124 | KillAll 125 | function 126 | 退出所有程序 127 | enable 128 | 129 | 130 | 131 | 132 | 133 | executeCommand 134 | musicToggle 135 | keyword 136 | Toggle 137 | function 138 | 播放/暂停 139 | enable 140 | 141 | 142 | 143 | executeCommand 144 | musicNext 145 | keyword 146 | Next 147 | function 148 | 下一首 149 | enable 150 | 151 | 152 | 153 | executeCommand 154 | musicPrevious 155 | keyword 156 | Previous 157 | function 158 | 上一首 159 | enable 160 | 161 | 162 | 163 | executeCommand 164 | musicVolumeUp 165 | keyword 166 | VolumeUp 167 | function 168 | 增大音量 169 | enable 170 | 171 | 172 | 173 | executeCommand 174 | musicVolumeDown 175 | keyword 176 | VolumeDown 177 | function 178 | 减小音量 179 | enable 180 | 181 | 182 | 183 | executeCommand 184 | musicLike 185 | keyword 186 | LikeChange 187 | function 188 | 喜欢/取消喜欢 189 | enable 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /WeChatPlugin/TKRemoteControlScript.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeTips/WeChatPlugin-macOS/35938a151a013ae7e4f782bd05c0839e3ac29bd3/WeChatPlugin/TKRemoteControlScript.scpt -------------------------------------------------------------------------------- /WeChatPlugin/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | WeChatPlugin 4 | 5 | Created by Loveletter on 28/02/2018. 6 | Copyright © 2018 CodeTips. All rights reserved. 7 | */ 8 | "PreventRevoke" = "Prevent Revoke"; 9 | "AutoReply" = "Auto Reply"; 10 | "NewWeChat" = "New WeChat"; 11 | "RemoteControl" = "Remote Control"; 12 | "WeChatOnTop" = "WeChat Stick"; 13 | "AutoAuthLogin" = "AutoAuth Login"; 14 | "Plugin" = "Plugin"; 15 | -------------------------------------------------------------------------------- /WeChatPlugin/main.mm: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // WeChatPlugin 4 | // 5 | // Created by TK on 2017/4/19. 6 | // Copyright © 2017年 tk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WeChat+hook.h" 11 | #import "MMChatsTableCellView+hook.h" 12 | #import "NSViewController+Hook.h" 13 | 14 | static void __attribute__((constructor)) initialize(void) { 15 | NSLog(@"++++++++ WeChatPlugin loaded ++++++++"); 16 | [NSObject hookWeChat]; 17 | [NSObject hookMMChatsTableCellView]; 18 | [NSObject hookNSViewController]; 19 | } 20 | -------------------------------------------------------------------------------- /WeChatPlugin/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | WeChatPlugin 4 | 5 | Created by Loveletter on 28/02/2018. 6 | Copyright © 2018 CodeTips. All rights reserved. 7 | */ 8 | "PreventRevoke" = "消息防撤回"; 9 | "AutoReply" = "自动回复设置"; 10 | "NewWeChat" = "登录新微信"; 11 | "RemoteControl" = "远程控制MacOS"; 12 | "WeChatOnTop" = "微信窗口置顶"; 13 | "AutoAuthLogin" = "免认证登录"; 14 | "Plugin" = "小助手"; 15 | --------------------------------------------------------------------------------