diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ff6efd7..1612dc6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +### [v1.6 (2018-03-18)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6) + +* 新增 Alfred 快捷发送消息 & 打开聊天窗口 + ### [v1.5.1 (2018-03-03)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1) * 新增语音远程控制 mac diff --git a/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h b/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h index 6a7fb74f..5e3db351 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h +++ b/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h @@ -78,6 +78,8 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +- (void)startANewChatWithContact:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; @end @interface ContactStorage : NSObject @@ -88,8 +90,12 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @interface WCContactData : NSObject @property(retain, nonatomic) NSString *m_nsUsrName; // @synthesize m_nsUsrName; @property(nonatomic) unsigned int m_uiFriendScene; // @synthesize m_uiFriendScene; +@property(retain, nonatomic) NSString *m_nsNickName; // 用户昵称 +@property(retain, nonatomic) NSString *m_nsRemark; // 备注 +@property(retain, nonatomic) NSString *m_nsHeadImgUrl; // 头像 - (BOOL)isBrandContact; - (BOOL)isSelf; +- (id)getGroupDisplayName; @end @interface MessageData : NSObject @@ -103,7 +109,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; @property(nonatomic) long long mesSvrID; -@property(retain, nonatomic) NSString *msgVoiceText; +@property(retain, nonatomic) NSString *msgVoiceText; @property(copy, nonatomic) NSString *m_nsEmoticonMD5; - (BOOL)isChatRoomMessage; - (id)groupChatSenderDisplayName; @@ -153,6 +159,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)UntopSessionByUserName:(id)arg1; - (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; - (void)sortSessions; +- (id)getContact:(id)arg1; @end @interface LogoutCGI : NSTableCellView @@ -184,4 +191,31 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (id)getEmotionDataWithMD5:(id)arg1; @end +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSArray *, NSArray *, NSArray *))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMComplexContactSearchResult : NSObject +@property(retain, nonatomic) NSString *fieldValue; +@property(retain, nonatomic) WCContactData *contact; +@property(nonatomic) unsigned long long fieldType; // 1:备注 3:昵称 4:微信号 8:省份 7:市 9:国家 +@end + +@interface MMComplexGroupContactMembersSearchResult : NSObject +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end +@interface MMComplexGroupContactSearchResult : NSObject +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +@end + +@interface NSString (MD5) +- (id)md5String; +@end diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist b/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist index c1877b77..aa235f9b 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.5.1 + 1.6 CFBundleSupportedPlatforms MacOSX @@ -41,6 +41,7 @@ NSHumanReadableCopyright Copyright © 2017年 tk. All rights reserved. versionInfo - 👉 v1.5.1 (2018-03-03):\n新增语音远程控制 mac\n修复快捷回复后消息未读数未更新的问题\n优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n上版本更新内容(v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n + 👉 v1.6 (2018-03-18):\n新增 Alfred 快捷发消息 & 打开聊天窗口\n\n之前版本更新内容:\n👉 (v1.5.1) :\n👉🏻 新增语音远程控制 mac\n👉🏼 修复快捷回复后消息未读数未更新的问题\n👉🏽 优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n👉 (v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n👉🏻 优化防撤回提醒。 \n👉🏼 新增自动登录开关。 \n👉🏽 新增表情复制 & 存储。 \n👉🏾 新增通知中心快捷回复。\n👉🏿 自动回复 & 远程控制设置存储到本地。\n\n + diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Headers/WeChatPlugin.h b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Headers/WeChatPlugin.h index 6a7fb74f..5e3db351 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Headers/WeChatPlugin.h +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Headers/WeChatPlugin.h @@ -78,6 +78,8 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +- (void)startANewChatWithContact:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; @end @interface ContactStorage : NSObject @@ -88,8 +90,12 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @interface WCContactData : NSObject @property(retain, nonatomic) NSString *m_nsUsrName; // @synthesize m_nsUsrName; @property(nonatomic) unsigned int m_uiFriendScene; // @synthesize m_uiFriendScene; +@property(retain, nonatomic) NSString *m_nsNickName; // 用户昵称 +@property(retain, nonatomic) NSString *m_nsRemark; // 备注 +@property(retain, nonatomic) NSString *m_nsHeadImgUrl; // 头像 - (BOOL)isBrandContact; - (BOOL)isSelf; +- (id)getGroupDisplayName; @end @interface MessageData : NSObject @@ -103,7 +109,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; @property(nonatomic) long long mesSvrID; -@property(retain, nonatomic) NSString *msgVoiceText; +@property(retain, nonatomic) NSString *msgVoiceText; @property(copy, nonatomic) NSString *m_nsEmoticonMD5; - (BOOL)isChatRoomMessage; - (id)groupChatSenderDisplayName; @@ -153,6 +159,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)UntopSessionByUserName:(id)arg1; - (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; - (void)sortSessions; +- (id)getContact:(id)arg1; @end @interface LogoutCGI : NSTableCellView @@ -184,4 +191,31 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (id)getEmotionDataWithMD5:(id)arg1; @end +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSArray *, NSArray *, NSArray *))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMComplexContactSearchResult : NSObject +@property(retain, nonatomic) NSString *fieldValue; +@property(retain, nonatomic) WCContactData *contact; +@property(nonatomic) unsigned long long fieldType; // 1:备注 3:昵称 4:微信号 8:省份 7:市 9:国家 +@end + +@interface MMComplexGroupContactMembersSearchResult : NSObject +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end +@interface MMComplexGroupContactSearchResult : NSObject +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +@end + +@interface NSString (MD5) +- (id)md5String; +@end diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Info.plist b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Info.plist index c1877b77..aa235f9b 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Info.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.5.1 + 1.6 CFBundleSupportedPlatforms MacOSX @@ -41,6 +41,7 @@ NSHumanReadableCopyright Copyright © 2017年 tk. All rights reserved. versionInfo - 👉 v1.5.1 (2018-03-03):\n新增语音远程控制 mac\n修复快捷回复后消息未读数未更新的问题\n优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n上版本更新内容(v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n + 👉 v1.6 (2018-03-18):\n新增 Alfred 快捷发消息 & 打开聊天窗口\n\n之前版本更新内容:\n👉 (v1.5.1) :\n👉🏻 新增语音远程控制 mac\n👉🏼 修复快捷回复后消息未读数未更新的问题\n👉🏽 优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n👉 (v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n👉🏻 优化防撤回提醒。 \n👉🏼 新增自动登录开关。 \n👉🏽 新增表情复制 & 存储。 \n👉🏾 新增通知中心快捷回复。\n👉🏿 自动回复 & 远程控制设置存储到本地。\n\n + diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin index 8679234d..c8501ff5 100755 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Headers/WeChatPlugin.h b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Headers/WeChatPlugin.h index 6a7fb74f..5e3db351 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Headers/WeChatPlugin.h +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Headers/WeChatPlugin.h @@ -78,6 +78,8 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +- (void)startANewChatWithContact:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; @end @interface ContactStorage : NSObject @@ -88,8 +90,12 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @interface WCContactData : NSObject @property(retain, nonatomic) NSString *m_nsUsrName; // @synthesize m_nsUsrName; @property(nonatomic) unsigned int m_uiFriendScene; // @synthesize m_uiFriendScene; +@property(retain, nonatomic) NSString *m_nsNickName; // 用户昵称 +@property(retain, nonatomic) NSString *m_nsRemark; // 备注 +@property(retain, nonatomic) NSString *m_nsHeadImgUrl; // 头像 - (BOOL)isBrandContact; - (BOOL)isSelf; +- (id)getGroupDisplayName; @end @interface MessageData : NSObject @@ -103,7 +109,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; @property(nonatomic) long long mesSvrID; -@property(retain, nonatomic) NSString *msgVoiceText; +@property(retain, nonatomic) NSString *msgVoiceText; @property(copy, nonatomic) NSString *m_nsEmoticonMD5; - (BOOL)isChatRoomMessage; - (id)groupChatSenderDisplayName; @@ -153,6 +159,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)UntopSessionByUserName:(id)arg1; - (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; - (void)sortSessions; +- (id)getContact:(id)arg1; @end @interface LogoutCGI : NSTableCellView @@ -184,4 +191,31 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (id)getEmotionDataWithMD5:(id)arg1; @end +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSArray *, NSArray *, NSArray *))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMComplexContactSearchResult : NSObject +@property(retain, nonatomic) NSString *fieldValue; +@property(retain, nonatomic) WCContactData *contact; +@property(nonatomic) unsigned long long fieldType; // 1:备注 3:昵称 4:微信号 8:省份 7:市 9:国家 +@end + +@interface MMComplexGroupContactMembersSearchResult : NSObject +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end +@interface MMComplexGroupContactSearchResult : NSObject +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +@end + +@interface NSString (MD5) +- (id)md5String; +@end diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Info.plist b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Info.plist index c1877b77..aa235f9b 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Info.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.5.1 + 1.6 CFBundleSupportedPlatforms MacOSX @@ -41,6 +41,7 @@ NSHumanReadableCopyright Copyright © 2017年 tk. All rights reserved. versionInfo - 👉 v1.5.1 (2018-03-03):\n新增语音远程控制 mac\n修复快捷回复后消息未读数未更新的问题\n优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n上版本更新内容(v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n + 👉 v1.6 (2018-03-18):\n新增 Alfred 快捷发消息 & 打开聊天窗口\n\n之前版本更新内容:\n👉 (v1.5.1) :\n👉🏻 新增语音远程控制 mac\n👉🏼 修复快捷回复后消息未读数未更新的问题\n👉🏽 优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n👉 (v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n👉🏻 优化防撤回提醒。 \n👉🏼 新增自动登录开关。 \n👉🏽 新增表情复制 & 存储。 \n👉🏾 新增通知中心快捷回复。\n👉🏿 自动回复 & 远程控制设置存储到本地。\n\n + diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin index 8679234d..c8501ff5 100755 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/WeChatPlugin b/Other/Products/Debug/WeChatPlugin.framework/WeChatPlugin index 8679234d..c8501ff5 100755 Binary files a/Other/Products/Debug/WeChatPlugin.framework/WeChatPlugin and b/Other/Products/Debug/WeChatPlugin.framework/WeChatPlugin differ diff --git a/Other/ScreenShots/alfred_search.gif b/Other/ScreenShots/alfred_search.gif new file mode 100644 index 00000000..5bc8229f Binary files /dev/null and b/Other/ScreenShots/alfred_search.gif differ diff --git a/Podfile b/Podfile index 2efd0b97..67e89141 100644 --- a/Podfile +++ b/Podfile @@ -1,4 +1,5 @@ -platform :osx, '10.10' +platform :osx, '10.12' +inhibit_all_warnings! target 'WeChatPlugin' do pod 'GCDWebServer', '~> 3.4.2' diff --git a/README.md b/README.md index 68d01b94..f6420ea1 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ ## WeChatPlugin-MacOS -![platform](https://img.shields.io/badge/platform-macos-lightgrey.svg) [![release](https://img.shields.io/badge/release-v1.5.1-brightgreen.svg)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases) ![support](https://img.shields.io/badge/support-wechat%202.3.10-blue.svg) [![GitHub license](https://img.shields.io/github/license/TKkk-iOSer/WeChatPlugin-MacOS.svg)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/LICENSE) +![platform](https://img.shields.io/badge/platform-macos-lightgrey.svg) [![release](https://img.shields.io/badge/release-v1.6-brightgreen.svg)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases) ![support](https://img.shields.io/badge/support-wechat%202.3.10-blue.svg) [![GitHub license](https://img.shields.io/github/license/TKkk-iOSer/WeChatPlugin-MacOS.svg)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/LICENSE) - -微信小助手 v1.5.1 +微信小助手 v1.6 ![微信小助手.png](./Other/ScreenShots/wechatplugin.png) @@ -15,6 +14,8 @@ --- ### 更新日志 +* [新增 Alfred 快捷发送消息 & 打开聊天窗口(2018-03-18)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6) + * [新增语音远程控制mac & 优化撤回消息、快捷回复(2018-03-03)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1) * [新增小助手检测更新&表情包复制存储等等 (2018-02-24)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0) @@ -44,6 +45,7 @@ * 通知中心快捷回复 * 聊天窗口表情包复制 & 存储 * 小助手检测更新提醒 +* alfred 快捷发送消息 & 打开窗口 远程控制: @@ -60,7 +62,7 @@ --- ### TODO -- [ ] 增加`Alfred`搜索 +- [x] 增加`Alfred`搜索 - [ ] 查看单向好友 - [ ] 语音(视频转发) - [ ] 增加 brew 安装方式 @@ -99,6 +101,8 @@ * 语音远程控制 mac ![语音远程控制](./Other/ScreenShots/voice_remote_control.gif) +* Alfred 快速搜索 +![alfred](./Other/ScreenShots/alfred_search.gif) --- @@ -124,7 +128,7 @@ ![Permission denied.png](http://upload-images.jianshu.io/upload_images/965383-11e4480553ba086e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) -* 下载 WeChatPlugin, 用Xcode打开,先进行 Build (`command + B`),之后 Run (`command + R`)即可启动微信,此时插件注入完成。 +* 下载 WeChatPlugin, 进行`Pod install`,用Xcode打开,先进行 Build (`command + B`),之后 Run (`command + R`)即可启动微信,此时插件注入完成。 * 若 Error,提示找不到 Framework,先进行 Build。 * 若Error, 需要配置环境,请参考[我的博客](http://www.tkkk.fun/2017/04/21/macOS%E9%80%86%E5%90%91-%E5%BE%AE%E4%BF%A1%E5%B0%8F%E5%8A%A9%E6%89%8B/)。 diff --git a/WeChatPlugin.xcodeproj/project.pbxproj b/WeChatPlugin.xcodeproj/project.pbxproj index 3ca64ba2..4749e582 100644 --- a/WeChatPlugin.xcodeproj/project.pbxproj +++ b/WeChatPlugin.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 520F2009205E1DF900A36B1E /* TKWebServerManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 520F2007205E1DF900A36B1E /* TKWebServerManager.h */; }; + 520F200A205E1DF900A36B1E /* TKWebServerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 520F2008205E1DF900A36B1E /* TKWebServerManager.m */; }; 522547CF1F4AE5A700226A2A /* NSView+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 522547CD1F4AE5A700226A2A /* NSView+Action.h */; }; 522547D01F4AE5A700226A2A /* NSView+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 522547CE1F4AE5A700226A2A /* NSView+Action.m */; }; 522547DE1F4C312A00226A2A /* TKAutoReplyWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 522547D71F4C312A00226A2A /* TKAutoReplyWindowController.h */; }; @@ -63,6 +65,8 @@ /* Begin PBXFileReference section */ 13B308B4A92CE38341762A48 /* Pods-WeChatPlugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WeChatPlugin.release.xcconfig"; path = "Pods/Target Support Files/Pods-WeChatPlugin/Pods-WeChatPlugin.release.xcconfig"; sourceTree = ""; }; 17F7A08DC0E3A0626801414D /* libPods-WeChatPlugin.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-WeChatPlugin.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 520F2007205E1DF900A36B1E /* TKWebServerManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKWebServerManager.h; sourceTree = ""; }; + 520F2008205E1DF900A36B1E /* TKWebServerManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKWebServerManager.m; sourceTree = ""; }; 522547CD1F4AE5A700226A2A /* NSView+Action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+Action.h"; sourceTree = ""; }; 522547CE1F4AE5A700226A2A /* NSView+Action.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+Action.m"; sourceTree = ""; }; 522547D71F4C312A00226A2A /* TKAutoReplyWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKAutoReplyWindowController.h; sourceTree = ""; }; @@ -337,6 +341,8 @@ 52B5CF051F3B4631000D9DD9 /* XMLReader.m */, 5226D5C82040FC3E0013C048 /* TKVersionManager.h */, 5226D5C92040FC3E0013C048 /* TKVersionManager.m */, + 520F2007205E1DF900A36B1E /* TKWebServerManager.h */, + 520F2008205E1DF900A36B1E /* TKWebServerManager.m */, ); path = Utils; sourceTree = ""; @@ -383,6 +389,7 @@ 526F4D8D1F4AAC3800E46004 /* TKRemoteControlCell.h in Headers */, 52B5CF181F3B4631000D9DD9 /* TKRemoteControlModel.h in Headers */, 5226D5CA2040FC3E0013C048 /* TKVersionManager.h in Headers */, + 520F2009205E1DF900A36B1E /* TKWebServerManager.h in Headers */, 522547CF1F4AE5A700226A2A /* NSView+Action.h in Headers */, 526F4D911F4AAE6F00E46004 /* TKAutoReplyCell.h in Headers */, 52475C2E1F6B993E00760E3E /* MMChatsTableCellView+hook.h in Headers */, @@ -519,6 +526,7 @@ files = ( 52475C2F1F6B993E00760E3E /* MMChatsTableCellView+hook.m in Sources */, 526F4D921F4AAE6F00E46004 /* TKAutoReplyCell.m in Sources */, + 520F200A205E1DF900A36B1E /* TKWebServerManager.m in Sources */, 52B5CF151F3B4631000D9DD9 /* TKWeChatPluginConfig.m in Sources */, 522547E21F4C312A00226A2A /* TKRemoteControlWindowController.m in Sources */, 52B5CF131F3B4631000D9DD9 /* WeChat+hook.m in Sources */, diff --git a/WeChatPlugin/Info.plist b/WeChatPlugin/Info.plist index 32279fcc..8ff22e5d 100644 --- a/WeChatPlugin/Info.plist +++ b/WeChatPlugin/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.5.1 + 1.6 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSHumanReadableCopyright @@ -23,6 +23,7 @@ NSPrincipalClass versionInfo - 👉 v1.5.1 (2018-03-03):\n新增语音远程控制 mac\n修复快捷回复后消息未读数未更新的问题\n优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n上版本更新内容(v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n + 👉 v1.6 (2018-03-18):\n新增 Alfred 快捷发消息 & 打开聊天窗口\n\n之前版本更新内容:\n👉 (v1.5.1) :\n👉🏻 新增语音远程控制 mac\n👉🏼 修复快捷回复后消息未读数未更新的问题\n👉🏽 优化防撤回提醒 (显示撤回人昵称 & 消息类型) \n\n👉 (v1.5.0):\n👉🏻 新增自动登录开关 \n👉🏼 新增小助手检测更新 \n👉🏽 新增通知中心快捷回复 \n👉🏾 新增表情包复制 & 存储 \n👉🏿 自动回复 & 远程控制设置存储到本地 \n\n👉🏻 优化防撤回提醒。 \n👉🏼 新增自动登录开关。 \n👉🏽 新增表情复制 & 存储。 \n👉🏾 新增通知中心快捷回复。\n👉🏿 自动回复 & 远程控制设置存储到本地。\n\n + diff --git a/WeChatPlugin/Sources/Category/WeChat+hook.m b/WeChatPlugin/Sources/Category/WeChat+hook.m index dedc5a76..5d518c76 100644 --- a/WeChatPlugin/Sources/Category/WeChat+hook.m +++ b/WeChatPlugin/Sources/Category/WeChat+hook.m @@ -15,6 +15,7 @@ #import "TKIgnoreSessonModel.h" #import "fishhook.h" #import "TKVersionManager.h" +#import "TKWebServerManager.h" static char tkAutoReplyWindowControllerKey; // 自动回复窗口的关联 key static char tkRemoteControlWindowControllerKey; // 远程控制窗口的关联 key @@ -42,6 +43,9 @@ + (void)hookWeChat { tk_hookMethod(objc_getClass("MMNotificationService"), @selector(userNotificationCenter:didActivateNotification:), [self class], @selector(hook_userNotificationCenter:didActivateNotification:)); tk_hookMethod(objc_getClass("MMNotificationService"), @selector(getNotificationContentWithMsgData:), [self class], @selector(hook_getNotificationContentWithMsgData:)); + // 登录逻辑 + tk_hookMethod(objc_getClass("WeChat"), @selector(onAuthOK:), [self class], @selector(hook_onAuthOK:)); + // 替换沙盒路径 rebind_symbols((struct rebinding[2]) { { "NSSearchPathForDirectoriesInDomains", swizzled_NSSearchPathForDirectoriesInDomains, (void *)&original_NSSearchPathForDirectoriesInDomains }, @@ -339,7 +343,7 @@ - (void)hook_onRevokeMsg:(id)msg { }); [msgService AddLocalMsg:session msgData:newMsgData]; - } + } } /** @@ -421,7 +425,17 @@ - (void)hook_onLoginButtonClicked:(NSButton *)btn { } } +- (void)hook_onAuthOK:(BOOL)arg1 { + [self hook_onAuthOK:arg1]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [[TKWebServerManager shareManager] startServer]; + }); +} + - (void)hook_sendLogoutCGIWithCompletion:(id)arg1 { + [[TKWebServerManager shareManager] endServer]; + BOOL autoAuthEnable = [[TKWeChatPluginConfig sharedConfig] autoAuthEnable]; WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; if (autoAuthEnable && wechat.isAppTerminating) return; @@ -504,8 +518,8 @@ - (void)hook_makeKeyAndOrderFront:(nullable id)sender { - (void)autoReplyWithMsg:(AddMsg *)addMsg { if (addMsg.msgType != 1 && addMsg.msgType != 3) return; - ContactStorage *contactStorage = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("ContactStorage")]; - WCContactData *msgContact = [contactStorage GetContact:addMsg.fromUserName.string]; + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + WCContactData *msgContact = [sessionMgr getContact:addMsg.fromUserName.string]; if ([msgContact isBrandContact] || [msgContact isSelf]) { // 该消息为公众号或者本人发送的消息 return; diff --git a/WeChatPlugin/Sources/Utils/TKWebServerManager.h b/WeChatPlugin/Sources/Utils/TKWebServerManager.h new file mode 100644 index 00000000..0d136e7e --- /dev/null +++ b/WeChatPlugin/Sources/Utils/TKWebServerManager.h @@ -0,0 +1,18 @@ +// +// TKWebServerManager.h +// WeChatPlugin +// +// Created by TK on 2018/3/18. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface TKWebServerManager : NSObject + ++ (instancetype)shareManager; + +- (void)startServer; +- (void)endServer; + +@end diff --git a/WeChatPlugin/Sources/Utils/TKWebServerManager.m b/WeChatPlugin/Sources/Utils/TKWebServerManager.m new file mode 100644 index 00000000..b70f8629 --- /dev/null +++ b/WeChatPlugin/Sources/Utils/TKWebServerManager.m @@ -0,0 +1,201 @@ +// +// TKWebServerManager.m +// WeChatPlugin +// +// Created by TK on 2018/3/18. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKWebServerManager.h" +#import "WeChatPlugin.h" +#import +#import +#import + +@interface TKWebServerManager () + +@property (nonatomic, strong) GCDWebServer *webServer; +@end + +@implementation TKWebServerManager + ++ (instancetype)shareManager { + static TKWebServerManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[TKWebServerManager alloc] init]; + }); + return manager; +} + +- (void)startServer { + if (self.webServer) { + return; + } + NSDictionary *options = @{GCDWebServerOption_Port: @52700, + GCDWebServerOption_BindToLocalhost: @YES, + GCDWebServerOption_ConnectedStateCoalescingInterval: @2, + }; + + self.webServer = [[GCDWebServer alloc] init]; + [self addHandleForSearchUser]; + [self addHandleForOpenSession]; + [self addHandleForSendMsg]; + [self.webServer startWithOptions:options error:nil]; +} + +- (void)endServer { + if( [self.webServer isRunning] ) { + [self.webServer stop]; + [self.webServer removeAllHandlers]; + self.webServer = nil; + } +} + +- (void)addHandleForSearchUser { + __weak typeof(self) weakSelf = self; + + [self.webServer addHandlerForMethod:@"GET" path:@"/wechat-plugin/user" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerRequest * _Nonnull request) { + + NSDictionary *keyword = request.query ? request.query[@"keyword"] ? request.query[@"keyword"] : @"" : @""; + __block NSMutableArray *sessionList = [NSMutableArray array]; + __block BOOL hasResult = NO; + MMComplexContactSearchTaskMgr *searchMgr = [objc_getClass("MMComplexContactSearchTaskMgr") sharedInstance]; + [searchMgr doComplexContactSearch:keyword searchScene:31 complete:^(NSArray *contactResult, NSArray *brandSult, NSArray *groupResult) { + [contactResult enumerateObjectsUsingBlock:^(MMComplexContactSearchResult * _Nonnull contact, NSUInteger idx, BOOL * _Nonnull stop) { + [sessionList addObject:[weakSelf dictFromContactSearchResult:contact]]; + }]; + + [groupResult enumerateObjectsUsingBlock:^(MMComplexGroupContactSearchResult * _Nonnull group, NSUInteger idx, BOOL * _Nonnull stop) { + [sessionList addObject:[weakSelf dictFromGroupSearchResult:group]]; + }]; + + hasResult = YES; + } cancelable:YES]; + + while (!hasResult) {} + + return [GCDWebServerDataResponse responseWithJSONObject:sessionList]; + }]; +} + +- (void)addHandleForOpenSession { + [self.webServer addHandlerForMethod:@"POST" path:@"/wechat-plugin/open-session" requestClass:[GCDWebServerURLEncodedFormRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerURLEncodedFormRequest * _Nonnull request) { + NSDictionary *requestBody = [request arguments]; + + if (requestBody && requestBody[@"userId"]) { + dispatch_async(dispatch_get_main_queue(), ^{ + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + WCContactData *selectContact = [sessionMgr getContact:requestBody[@"userId"]]; + + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + [wechat startANewChatWithContact:selectContact]; + [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; + }); + return [GCDWebServerResponse responseWithStatusCode:200]; + } + + return [GCDWebServerResponse responseWithStatusCode:404]; + }]; +} + +- (void)addHandleForSendMsg { + [self.webServer addHandlerForMethod:@"POST" path:@"/wechat-plugin/send-message" requestClass:[GCDWebServerURLEncodedFormRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerURLEncodedFormRequest * _Nonnull request) { + NSDictionary *requestBody = [request arguments]; + if (requestBody && requestBody[@"userId"] && requestBody[@"content"]) { + dispatch_async(dispatch_get_main_queue(), ^{ + MessageService *messageService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + [messageService SendTextMessage:currentUserName + toUsrName:requestBody[@"userId"] + msgText:requestBody[@"content"] + atUserList:nil]; + }); + return [GCDWebServerResponse responseWithStatusCode:200]; + } + + return [GCDWebServerResponse responseWithStatusCode:404]; + }]; +} + +- (NSDictionary *)dictFromGroupSearchResult:(MMComplexGroupContactSearchResult *)result { + WCContactData *groupContact = result.groupContact; + + __block NSString *subTitle = @""; + if (result.searchType == 2) { + [result.groupMembersResult.membersSearchReults enumerateObjectsUsingBlock:^(MMComplexContactSearchResult * _Nonnull contact, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *matchStr =[self matchWithContactResult:contact]; + subTitle = [NSString stringWithFormat:@"成员:%@(%@)", contact.contact.m_nsNickName, matchStr]; + }]; + } + + NSString *imgPath = [self cacheAvatarPathFromHeadImgUrl:groupContact.m_nsHeadImgUrl]; + + return @{@"title": [NSString stringWithFormat:@"[群聊]%@",groupContact.getGroupDisplayName], + @"subTitle": subTitle, + @"icon": imgPath, + @"userId": groupContact.m_nsUsrName + }; +} + +- (NSString *)matchWithContactResult:(MMComplexContactSearchResult *)result { + NSString *matchStr = @""; + NSInteger type = result.fieldType; + + switch (type) { // 1:备注 3:昵称 4:微信号 7:市 8:省份 9:国家 + case 1: + matchStr = [NSString stringWithFormat:@"备注:%@",result.fieldValue]; + break; + case 3: + matchStr = [NSString stringWithFormat:@"昵称:%@",result.fieldValue]; + break; + case 4: + matchStr = [NSString stringWithFormat:@"微信号:%@",result.fieldValue]; + break; + case 7: + matchStr = [NSString stringWithFormat:@"城市:%@",result.fieldValue]; + break; + case 8: + matchStr = [NSString stringWithFormat:@"省份:%@",result.fieldValue]; + break; + case 9: + matchStr = [NSString stringWithFormat:@"国家:%@",result.fieldValue]; + break; + default: + matchStr = [NSString stringWithFormat:@"包含:%@",result.fieldValue]; + break; + } + + return matchStr; +} + +- (NSDictionary *)dictFromContactSearchResult:(MMComplexContactSearchResult *)result { + WCContactData *contact = result.contact; + + NSString *title = contact.m_nsNickName; + if(contact.m_nsRemark && ![contact.m_nsRemark isEqualToString:@""]) { + title = [NSString stringWithFormat:@"%@(%@)",contact.m_nsRemark, contact.m_nsNickName]; + } + + NSString *subTitle =[self matchWithContactResult:result]; + NSString *imgPath = [self cacheAvatarPathFromHeadImgUrl:contact.m_nsHeadImgUrl]; + + return @{@"title": title, + @"subTitle": subTitle, + @"icon": imgPath, + @"userId": contact.m_nsUsrName + }; +} + +// 获取本地图片缓存路径 +- (NSString *)cacheAvatarPathFromHeadImgUrl:(NSString *)imgUrl { + NSString *imgPath = @""; + if ([imgUrl respondsToSelector:@selector(md5String)]) { + NSString *imgMd5Str = [imgUrl performSelector:@selector(md5String)]; + MMAvatarService *avatarService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMAvatarService")]; + imgPath = [NSString stringWithFormat:@"%@/%@",[avatarService avatarCachePath], imgMd5Str]; + } + return imgPath; +} + +@end diff --git a/WeChatPlugin/WeChatPlugin.h b/WeChatPlugin/WeChatPlugin.h index 6a7fb74f..5e3db351 100644 --- a/WeChatPlugin/WeChatPlugin.h +++ b/WeChatPlugin/WeChatPlugin.h @@ -78,6 +78,8 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +- (void)startANewChatWithContact:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; @end @interface ContactStorage : NSObject @@ -88,8 +90,12 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @interface WCContactData : NSObject @property(retain, nonatomic) NSString *m_nsUsrName; // @synthesize m_nsUsrName; @property(nonatomic) unsigned int m_uiFriendScene; // @synthesize m_uiFriendScene; +@property(retain, nonatomic) NSString *m_nsNickName; // 用户昵称 +@property(retain, nonatomic) NSString *m_nsRemark; // 备注 +@property(retain, nonatomic) NSString *m_nsHeadImgUrl; // 头像 - (BOOL)isBrandContact; - (BOOL)isSelf; +- (id)getGroupDisplayName; @end @interface MessageData : NSObject @@ -103,7 +109,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; @property(nonatomic) long long mesSvrID; -@property(retain, nonatomic) NSString *msgVoiceText; +@property(retain, nonatomic) NSString *msgVoiceText; @property(copy, nonatomic) NSString *m_nsEmoticonMD5; - (BOOL)isChatRoomMessage; - (id)groupChatSenderDisplayName; @@ -153,6 +159,7 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)UntopSessionByUserName:(id)arg1; - (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; - (void)sortSessions; +- (id)getContact:(id)arg1; @end @interface LogoutCGI : NSTableCellView @@ -184,4 +191,31 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (id)getEmotionDataWithMD5:(id)arg1; @end +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSArray *, NSArray *, NSArray *))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMComplexContactSearchResult : NSObject +@property(retain, nonatomic) NSString *fieldValue; +@property(retain, nonatomic) WCContactData *contact; +@property(nonatomic) unsigned long long fieldType; // 1:备注 3:昵称 4:微信号 8:省份 7:市 9:国家 +@end + +@interface MMComplexGroupContactMembersSearchResult : NSObject +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end +@interface MMComplexGroupContactSearchResult : NSObject +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +@end + +@interface NSString (MD5) +- (id)md5String; +@end