diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..e90bf391 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,24 @@ + + +### 问题描述 + + +### 版本 + +* MacOS Version: +* WeChat Version: +* WeChatPlugin Version: + +### 日志 + + diff --git a/.gitignore b/.gitignore index f3143b7e..bca9dad4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ # Xcode # .DS_Store -*.xcuserstate \ No newline at end of file +*.xcuserstate + +# CocoaPods +# +Pods/ +Podfile.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index a2224398..b2a2a236 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,69 @@ # 更新日志 +### [v2.0 (2023-03-12)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v2.) + +- 适配 3.7.0 +- 新增撤回消息定位 +- 新增群聊监控 +- 移除官方已支持的功能(自动登录,移除会话,标为未读等等) + +### [v1.7.5 (2019-01-13)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.5) + +- 适配 2.3.22 +- 新增禁止微信检测更新开关 +- 优化 XML解析(在此感谢 @wangliangliang2 提醒) + +###[v1.7.3 (2018-10-23)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.3) + +- 适配2.3.19 +- 菜单栏新增 alfred 开关 +- 更改更新弹窗逻辑 +- 新增自带浏览器浏览开关 + +### [v1.7.1 (2018-07-24)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.1) + +* 适配微信 Version. 2.3.17 +* 新增 alfred 搜索最近聊天列表 +* 新增 alfred 查看用户聊天记录 + +### [v1.7 (2018-05-12)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7) + +* 新增不同账户设置不同的自动回复&远程控制 +* 自动回复新增总开关&指定联系人 +* 远程控制新增控制小助手配置 +* 新增一键已读 +* 新增一键清除空回话 +* 新增国际化(支持英、简、繁) +* 新增关于小助手 +* 新增在线更新小助手 +* 去除微信url转链处理(从此直接打开抖音链接🌝 +* 修复无法免认证登录&多开等bug + +### [v1.6.1 (2018-04-07)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1) + +* 自动回复新增延迟回复 +* 调整置顶模式快捷键 +* 修复bug & 优化代码 +* 更新 README.md 文档 + +### [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 +* 修复快捷回复后消息未读数未更新的问题 +* 优化防撤回提醒 (显示撤回人昵称 & 消息类型) + +### [v1.5.0 (2018-02-24)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0) + +* 优化防撤回提醒 +* 新增自动登录开关 +* 新增小助手检测更新 +* 新增通知中心快捷回复 +* 新增表情包复制 & 存储 +* 自动回复 & 远程控制设置存储到本地 ### [v1.4.0 (2017-10-11)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0) diff --git a/Install.md b/Install.md new file mode 100644 index 00000000..eeff8405 --- /dev/null +++ b/Install.md @@ -0,0 +1,52 @@ + + +## Install + +**第一次安装需要输入密码,仅是为了获取写入微信文件夹的权限** + +**0. 懒癌版安装&升级** + +打开`应用程序-实用工具-Terminal(终端)`,执行下面的命令安装 [Oh My WeChat](https://github.com/lmk123/oh-my-wechat): + +```sh +curl -o- -L https://raw.githubusercontent.com/lmk123/oh-my-wechat/master/install.sh | bash -s +``` + +然后运行 `omw` 即可。 + +> 可以访问 [Oh My WeChat 的项目主页](https://github.com/lmk123/oh-my-wechat#oh-my-wechat)查看更多用法。 + +**1. 普通安装** + +* 点击`clone or download`按钮下载 WeChatPlugin 并解压 + +![clone or download](./Other/ScreenShots/install_download.png) + +* 从`应用程序-实用工具`中打开Terminal(终端) + +![terminal](./Other/ScreenShots/terminal_path.png) + +* 拖动解压后`Install.sh` 文件到终端中回车即可. + +![terminal](./Other/ScreenShots/install_terminal.png) + +**2. 若想修改源码&重编译(需要安装Cocoapods)** + +* 先更改微信的 owner 以获取写入微信文件夹的权限,否则会出现类似**Permission denied**的错误。 + +`sudo chown -R $(whoami) /Applications/WeChat.app` + +![Permission denied.png](http://upload-images.jianshu.io/upload_images/965383-11e4480553ba086e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + +* 下载 WeChatPlugin, 进行`Pod install`。 +* 用Xcode打开,编辑 Scheme,在 Debug 模式下启动 WeChat。 +![](http://upload-images.jianshu.io/upload_images/965383-26dbb068acb8998f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![edit scheme](http://upload-images.jianshu.io/upload_images/965383-7fbd4dc6e8d161dc.gif?imageMogr2/auto-orient/strip) +* 之后 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/)。 + +## 卸载 + +* 打开Terminal(终端),拖动解压后`Uninstall.sh` 文件到 Terminal 回车即可。 \ No newline at end of file diff --git a/Other/Install.sh b/Other/Install.sh index e6c4c00a..ea65de13 100755 --- a/Other/Install.sh +++ b/Other/Install.sh @@ -1,14 +1,26 @@ #!/bin/bash +wechat_path="/Applications/WeChat.app" + +if [ ! -d "$wechat_path" ] +then +wechat_path="/Applications/微信.app" +if [ ! -d "$wechat_path" ] +then +echo -e "\n\n应用程序文件夹中未发现微信,请检查微信是否有重命名或者移动路径位置" +exit +fi +fi + app_name="WeChat" shell_path="$(dirname "$0")" -wechat_path="/Applications/WeChat.app" framework_name="WeChatPlugin" -app_bundle_path="/Applications/${app_name}.app/Contents/MacOS" +app_bundle_path="${wechat_path}/Contents/MacOS" app_executable_path="${app_bundle_path}/${app_name}" app_executable_backup_path="${app_executable_path}_backup" framework_path="${app_bundle_path}/${framework_name}.framework" + # 对 WeChat 赋予权限 if [ ! -w "$wechat_path" ] then @@ -16,9 +28,10 @@ echo -e "\n\n为了将小助手写入微信, 请输入密码 : " sudo chown -R $(whoami) "$wechat_path" fi -# 备份 WeChat 原始可执行文件 -if [ ! -f "$app_executable_backup_path" ] +# 判断是否已经存在备份文件 或者 是否强制覆盖安装 +if [ ! -f "$app_executable_backup_path" ] || [ -n "$1" -a "$1" = "--force" ] then +# 备份 WeChat 原始可执行文件 cp "$app_executable_path" "$app_executable_backup_path" result="y" else diff --git a/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h b/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h index cf445b9d..3429ecc5 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h +++ b/Other/Products/Debug/WeChatPlugin.framework/Headers/WeChatPlugin.h @@ -13,8 +13,28 @@ FOUNDATION_EXPORT double WeChatPluginVersionNumber; FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; +@class WCContactData; + #pragma mark - 微信原始的部分类与方法 +@interface MMSystemLinkInfo : NSObject +@property(retain, nonatomic) NSMutableAttributedString *msgContent; + +@end +@interface MMContactProfileController : NSViewController +@property(copy, nonatomic) NSString *groupName; +@property(nonatomic) struct CGRect relativeToRect; +@property(nonatomic) unsigned long long preferredEdge; +@property(retain, nonatomic) WCContactData *contactData; +- (void)sendGetContactRequest:(id)arg1 withGroupName:(id)arg2; +- (void)showInView:(id)arg1; +@end + + +@interface MMBrandChatsViewController : NSObject +- (void)startChatWithContact:(id)arg1; +@end + @interface MMLoginOneClickViewController : NSViewController @property(nonatomic) NSTextField *descriptionLabel; - (void)onLoginButtonClicked:(id)arg1; @@ -28,25 +48,48 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)AutoAuth; - (void)ManualLogin:(id)arg1 withPassword:(id)arg2; - (void)ManualLogout; +- (void)FFAddSvrMsgImgVCZZ; - (void)QRCodeLoginWithUserName:(id)arg1 password:(id)arg2; +- (void)onAuthOKOfUser:(id)arg1 withSessionKey:(id)arg2 withServerId:(id)arg3 autoAuthKey:(id)arg4 isAutoAuth:(BOOL)arg5; @end @interface MMLoginViewController : NSObject @property(retain, nonatomic) MMLoginOneClickViewController *oneClickViewController; @end +@interface MMHandoffButton : NSView +@end + +@interface MMMainViewController : NSObject +@property(nonatomic) __weak MMHandoffButton *handoffButton; +@end + @interface MMMainWindowController : NSWindowController @property(retain, nonatomic) MMLoginViewController *loginViewController; +@property(retain, nonatomic) MMMainViewController *mainViewController; - (void)onAuthOK; - (void)onLogOut; @end -@interface MessageService : NSObject +@interface MMVoiceTranscribeCGI : NSObject +- (void)transcribeVoiceMessage:(id)arg1 withCompletion:(void (^)(void))arg2; +@end + +@interface FFProcessReqsvrZZ : NSObject - (void)onRevokeMsg:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1 sessionMsgList:(id)arg2; - (void)OnSyncBatchAddMsgs:(NSArray *)arg1 isFirstSync:(BOOL)arg2; -- (id)SendTextMessage:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; +- (void)FFImgToOnFavInfoInfoVCZZ:(id)arg1 isFirstSync:(BOOL)arg2; +- (id)FFProcessTReqZZ:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; - (id)GetMsgData:(id)arg1 svrId:(long)arg2; - (void)AddLocalMsg:(id)arg1 msgData:(id)arg2; +- (void)TranscribeVoiceMessage:(id)arg1 completion:(void (^)(void))arg2; +- (BOOL)ClearUnRead:(id)arg1 FromID:(unsigned int)arg2 ToID:(unsigned int)arg3; +- (BOOL)ClearUnRead:(id)arg1 FromCreateTime:(unsigned int)arg2 ToCreateTime:(unsigned int)arg3; +- (BOOL)HasMsgInChat:(id)arg1; +- (id)GetMsgListWithChatName:(id)arg1 fromCreateTime:(unsigned int)arg2 localId:(NSInteger)arg3 limitCnt:(NSInteger)arg4 hasMore:(char *)arg5 sortAscend:(BOOL)arg6; +- (void)DelMsg:(id)arg1 msgList:(id)arg2 isDelAll:(BOOL)arg3 isManual:(BOOL)arg4; @end @interface MMServiceCenter : NSObject @@ -64,10 +107,27 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic, setter=SetMsgType:) int msgType; // @synthesize msgType; @property(retain, nonatomic, setter=SetToUserName:) SKBuiltinString_t *toUserName; // @synthesize toUserName; @property (nonatomic, assign) unsigned int createTime; +@property(nonatomic, setter=SetNewMsgId:) long long newMsgId; +@end + +@interface MMChatMessageViewController : NSViewController +@property(retain, nonatomic) WCContactData *chatContact; +@property(nonatomic) __weak NSTableView *messageTableView; +- (void)scrollToMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(unsigned int)arg1 needHighLighted:(BOOL)arg2; +- (void)onClickSession; +- (void)reloadTableView; +@end + +@interface MMChatDetailSplitViewController : NSObject +@property(retain, nonatomic) MMChatMessageViewController *chatMessageViewController; @end @interface MMChatsViewController : NSViewController @property(nonatomic) __weak NSTableView *tableView; +@property(retain, nonatomic) MMBrandChatsViewController *brandChatsViewController; +@property(retain, nonatomic) MMChatDetailSplitViewController *chatDetailSplitViewController; @end @interface WeChat : NSObject @@ -75,16 +135,67 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +@property(nonatomic) BOOL hasAuthOK; +- (void)startANewChatWithContact:(id)arg1; +- (void)_clearAllUnreadMessages:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; +- (void)checkForUpdatesInBackground; +- (void)FFAddRecvFavZZ:(BOOL)arg1; @end @interface ContactStorage : NSObject - (id)GetSelfContact; - (id)GetContact:(id)arg1; +- (id)GetAllBrandContacts; +- (id)GetAllFavContacts; +- (id)GetAllFriendContacts; +@end + +@interface GroupStorage : NSObject +{ + NSMutableDictionary *m_dictGroupContacts; +} +- (id)GetAllGroups; +- (id)GetGroupMemberContact:(id)arg1; +- (void)notifyModifyGroupContactsOnMainThread:(id)arg1; +//- (id)GetGroupMemberListWithGroupContact:(id)arg1; +- (id)GetGroupMemberListWithGroupContact:(id)arg1 limit:(unsigned int)arg2 filterSelf:(BOOL)arg3; +@end + +@interface ChatRoomData : NSObject +{ + NSMutableDictionary *m_dicData; +} @end @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; // 头像 +@property(retain, nonatomic) NSString *m_nsHeadHDImgUrl; +@property(retain, nonatomic) NSString *m_nsHeadHDMd5; +@property(retain, nonatomic) NSString *m_nsAliasName; +@property(retain, nonatomic) NSString *avatarCacheKey; +@property(readonly, nonatomic) unsigned long long groupMemberCount; +@property(retain, nonatomic) ChatRoomData *m_chatRoomData; +@property(nonatomic) BOOL m_isShowRedDot; +- (BOOL)isBrandContact; +- (BOOL)isSelf; +- (id)innerGetGroupDisplayName; +- (NSString *)groupChatDisplayNameInGroup:(id)arg1; +- (id)getContactDisplayUsrName; +- (BOOL)isGroupChat; +- (BOOL)isMMChat; +- (BOOL)isMMContact; +- (BOOL)containsMember:(id)arg1; +- (id)displayRegion; +- (BOOL)isStickyFolder; +@end + +@interface WCPayInfoItem : NSObject +@property(retain, nonatomic) NSString *m_nsFeeDesc; @end @interface MessageData : NSObject @@ -93,25 +204,66 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(retain, nonatomic) NSString *toUsrName; @property(retain, nonatomic) NSString *msgContent; @property(retain, nonatomic) NSString *msgPushContent; +@property(retain, nonatomic) NSString *realChatUserName; +@property(retain, nonatomic) WCPayInfoItem *m_oWCPayInfoItem; // @dynamic m_oWCPayInfoItem; +@property(retain, nonatomic) NSString *m_nsAppName; +@property(retain, nonatomic) NSString *m_nsSourceDisplayname; @property(nonatomic) int messageType; @property(nonatomic) int msgStatus; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; +@property(nonatomic) long long mesSvrID; +@property(retain, nonatomic) NSString *msgVoiceText; +@property(copy, nonatomic) NSString *m_nsEmoticonMD5; +- (BOOL)isChatRoomMessage; +- (NSString *)groupChatSenderDisplayName; +- (id)getRealMessageContent; +- (id)getChatRoomUsrName; +- (BOOL)isSendFromSelf; +- (BOOL)isCustomEmojiMsg; +- (BOOL)isImgMsg; +- (BOOL)isVideoMsg; +- (BOOL)isVoiceMsg; +- (BOOL)canForward; +- (BOOL)IsPlayingSound; +- (id)summaryString:(BOOL)arg1; +- (BOOL)isEmojiAppMsg; +- (BOOL)isAppBrandMsg; +- (BOOL)IsUnPlayed; +- (void)SetPlayed; +@property(retain, nonatomic) NSString *m_nsTitle; +- (id)originalImageFilePath; +@property(retain, nonatomic) NSString *m_nsVideoPath; +@property(retain, nonatomic) NSString *m_nsFilePath; +@property(retain, nonatomic) NSString *m_nsAppMediaUrl; +@property(nonatomic) MessageData *m_refMessageData; +@property(nonatomic) unsigned int m_uiDownloadStatus; +- (void)SetPlayingSoundStatus:(BOOL)arg1; @end @interface CUtility : NSObject + (BOOL)HasWechatInstance; ++ (BOOL)FFSvrChatInfoMsgWithImgZZ; + (unsigned long long)getFreeDiskSpace; + (void)ReloadSessionForMsgSync; + (id)GetCurrentUserName; ++ (id)GetContactByUsrName:(id)arg1; ++ (BOOL)IsStickyChatsFolder:(id)arg1; +@end + +@interface MMSessionInfoPackedInfo: NSObject +@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MessageData *m_msgData; @end @interface MMSessionInfo : NSObject @property(nonatomic) BOOL m_bIsTop; // @synthesize m_bIsTop; @property(nonatomic) BOOL m_bShowUnReadAsRedDot; @property(nonatomic) BOOL m_isMentionedUnread; // @synthesize +@property BOOL isInGroupBox; @property(retain, nonatomic) NSString *m_nsUserName; // @synthesize m_nsUserName; -@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MMSessionInfoPackedInfo *m_packedInfo; +@property(nonatomic) unsigned int m_uUnReadCount; @end @protocol MMChatsTableCellViewDelegate @@ -129,21 +281,294 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @end @interface MMSessionMgr : NSObject -@property(retain, nonatomic) NSMutableArray *m_arrSession; -- (id)GetSessionAtIndex:(unsigned long long)arg1; -- (void)MuteSessionByUserName:(id)arg1; +//@property(retain, nonatomic) NSMutableArray *m_arrSession; +- (id)getSessionAtIndex:(unsigned long long)arg1; +- (id)sessionInfoByUserName:(id)arg1; +- (void)muteSessionByUserName:(id)arg1; +- (void)onUnReadCountChange:(id)arg1; //- (void)TopSessionByUserName:(id)arg1; -- (void)UnmuteSessionByUserName:(id)arg1; -- (void)UntopSessionByUserName:(id)arg1; -- (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; +- (void)unmuteSessionByUserName:(id)arg1; +- (void)untopSessionByUserName:(id)arg1; +- (void)changeSessionUnreadCountWithUserName:(id)arg1 to:(unsigned int)arg2; +- (void)removeSessionOfUser:(id)arg1 isDelMsg:(BOOL)arg2; - (void)sortSessions; +- (void)FFDataSvrMgrSvrFavZZ; +- (id)getContact:(id)arg1; +- (id)getSessionContact:(id)arg1; +- (void)onModifyContacts:(id)arg1; +- (NSMutableArray *)getAllSessions; @end @interface LogoutCGI : NSTableCellView - (void)sendLogoutCGIWithCompletion:(id)arg1; +- (void)FFVCRecvDataAddDataToMsgChatMgrRecvZZ:(id)arg1; @end @interface MMNotificationService : NSObject - (id)getNotificationContentWithMsgData:(id)arg1; - (void)userNotificationCenter:(id)arg1 didActivateNotification:(id)arg2; @end + +@interface MMMessageTableItem : NSObject +@property(retain, nonatomic) MessageData *message; +@end + +@interface MMStickerMessageCellView : NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(nonatomic) MMChatMessageViewController *delegate; +- (BOOL)allowCopy; +- (void)contextMenuCopy; +- (id)contextMenu; +@end + +@interface MMImageMessageCellView: NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@end + +@interface MMSystemMessageCellView: NSObject +@property(nonatomic) id delegate; +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(retain, nonatomic) NSTextView *msgTextView; +- (void)populateWithMessage:(id)arg1; +@end +@interface EmoticonMgr : NSObject +@property(retain, nonatomic) MessageData *message; +- (id)getEmotionDataWithMD5:(id)arg1; +- (id)getEmotionImgWithMD5:(id)arg1; +- (void)addFavEmoticon:(id)arg1; +- (void)addEmoticonToUploadQueueWithMD5:(id)arg1; +- (void)setAppStickerToastViewDelegate:(id)arg1; +@end + +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSString *,NSArray *, NSArray *, NSArray *,id))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMBasicSearchResult : NSObject +@end + +@interface MMSearchResultItem : NSObject +@property(retain, nonatomic) MMBasicSearchResult *result; +@end + +@interface MMSearchResultContainer : NSObject +@property(nonatomic) unsigned long long logicSearchResultFlag; // @synthesize +@end + +@interface MMContactSearchLogic : NSObject +{ + unsigned long long _logicSearchResultFlag; // 2.3.19 失效 +} +@property(retain, nonatomic) NSMutableArray *contactResults; +- (void)doSearchWithKeyword:(id)arg1 searchScene:(unsigned long long)arg2 resultIsShownBlock:(id)arg3 completion:(id)arg4; +@property(retain, nonatomic) NSMutableArray *groupResults; +@property(nonatomic) BOOL isBrandContactSearched; +@property(nonatomic) BOOL isChatLogSearched; +@property(nonatomic) BOOL isContactSearched; +@property(nonatomic) BOOL isGroupContactSearched; +@property(retain, nonatomic) NSMutableArray *oaResults; +- (void)clearAllResults; // 2.3.19 失效 +- (void)clearDataWhenSearchEnd; +- (void)reloadSearchResultDataWithKeyword:(id)arg1 completionBlock:(id)arg2; // 2.3.17 +- (void)reloadSearchResultDataWithCompletionBlock:(id)arg1; // 2.3.13 +- (void)reloadSearchResultDataWithKeyword:(id)arg1 resultContainer:(id)arg2 completionBlock:(id)arg3; +@property(retain, nonatomic) MMSearchResultContainer *searchResultContainer; +@end + +@interface MMComplexContactSearchResult : MMBasicSearchResult +@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 : MMBasicSearchResult +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end + +@interface MMComplexGroupContactSearchResult : MMBasicSearchResult +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +- (id)_getImageFromCacheWithMD5Key:(id)arg1; +- (void)avatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +- (void)getAvatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +@end + +@interface NSString (MD5) +- (id)md5String; +@end + +@interface MMSessionPickerLogic : NSObject +@property(nonatomic) NSArray *selectedUserNames; +@end + + +@interface MMSessionListView : NSObject +{ + MMSessionPickerLogic *m_logic; +} +@end + +@interface MMSessionPickerWindow : NSWindowController ++ (id)shareInstance; +- (void)beginSheetForWindow:(id)arg1 completionHandler:(void(^)(id a1))arg2; +@property(retain, nonatomic) id choosenViewController; // @synthesize +@property(retain, nonatomic) id listViewController; // @synthesize +- (void)setShowsGroupChats:(BOOL)arg1; +- (void)setShowsOfficialAccounts:(BOOL)arg1; +- (void)setShowsOtherNonhumanChats:(BOOL)arg1; +- (void)setType:(unsigned long long)arg1; + +@end + +@interface AFHTTPResponseSerializer : NSObject +@end + +@interface AFURLSessionManager : NSObject +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + progress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock + destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(void (^)(NSURLResponse *response, NSURL * filePath, NSError * error))completionHandler; +- (id)initWithSessionConfiguration:(id)arg1; +@end + +@interface AFHTTPRequestSerializer : NSObject ++ (id)serializer; +@property(nonatomic) unsigned long long cachePolicy; +@end + +@interface AFHTTPSessionManager : NSObject ++ (AFHTTPSessionManager *)manager; +@property(retain, nonatomic) AFHTTPRequestSerializer *requestSerializer; +@property(retain, nonatomic) AFHTTPResponseSerializer *responseSerializer; +@end + +@interface MMURLHandler : NSObject ++ (id)defaultHandler; +- (void)startGetA8KeyWithURL:(id)arg1; +- (BOOL)openURLWithDefault:(id)arg1; ++ (BOOL)containsHTTPString:(id)arg1; +- (void)openURLWithDefault:(id)arg1 useA8Key:(BOOL)arg2; +- (BOOL)preHandleUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface UserDefaultsService : NSObject +- (void)setString:(id)arg1 forKey:(id)arg2; +- (id)stringForKey:(id)arg1; +@end + +@interface MMLinkInfo : NSObject ++ (NSRange)rangeOfUrlInString:(id)arg1 withRange:(NSRange)arg2; +@end + +@interface MMCDNDownloadMgr : NSObject +- (BOOL)downloadImageWithMessage:(id)arg1 disableHevc:(BOOL)arg2 downloadType:(unsigned long long)arg3; +@end + +@interface MMMessageVideoService : NSObject +- (BOOL)downloadVideoWithMessage:(id)arg1; +@end + +@interface MMVoiceMessagePlayer : NSObject ++ (id)defaultPlayer; +- (void)playWithVoiceMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)playVoiceWithMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)stop; +@end + +@interface MultiPlatformStatusSyncMgr : NSObject +- (void)markVoiceMessageAsRead:(id)arg1; +@end + +@interface EmoticonDownloadMgr : NSObject +- (void)downloadEmoticonWithMessageData:(id)arg1; +@end + +@interface PathUtility : NSObject ++ (id)GetCurUserCachePath; ++ (id)emoticonPath:(id)arg1; ++ (id)getMsgVideoPathWithMessage:(id)arg1; ++ (id)getMsgVideoPathWithUserName:(id)arg1 localId:(unsigned int)arg2; +@end + +@interface MMExtensionCenter : NSObject +- (id)getExtension:(id)arg1; +@end + +@interface MMExtension : NSObject +- (BOOL)registerExtension:(id)arg1; +- (void)unregisterExtension:(id)arg1; +- (id)getExtensionListForSelector:(SEL)arg1; +@end + +@interface EmoticonMsgInfo : NSObject +@property(copy, nonatomic) NSString *cdnUrl; +@property(copy, nonatomic) NSString *m_nsMD5; +@end + +@protocol EmoticonDownloadMgrExt +@optional +- (void)emoticonDownloadFailed:(EmoticonMsgInfo *)arg1; +- (void)emoticonDownloadFinished:(EmoticonMsgInfo *)arg1; +@end + +@protocol IGroupMgrExt + +@end + +@interface MMChatMangerSearchReportMgr : NSObject +@property(retain, nonatomic) NSMutableArray *brandContactSearchResults; +@property(retain, nonatomic) NSMutableArray *chatLogSearchResults; +@property(retain, nonatomic) NSMutableArray *contactSearchResults; +@property(retain, nonatomic) NSMutableArray *groupContactSearchResults; +@end + +@interface MMWebViewHelper : NSObject ++ (BOOL)preHandleWebUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface XMLDictionaryParser : NSObject ++ (id)sharedInstance; +- (id)dictionaryWithString:(id)arg1; +@end + +@interface MMEmoticonData : NSObject +@property(retain, nonatomic) NSString *md5; // @synthesize md5=_md5; +@end + +@interface MMStickerPickerCell : NSView +@property(retain, nonatomic) MMEmoticonData *emoticonData; // @synthesize emoticonData=_emoticonData; +@property(nonatomic) __weak NSScrollView *collectionView; +@end + +@interface MMStickerCollectionViewController : NSViewController +@property(nonatomic) __weak id delegate; +@end + +@interface MMStickerPicker : NSViewController +- (void)hide; +@end + +@interface MMVoiceTranslateMgr : NSObject +- (void)doTranslate:(id)arg1 isAuto:(BOOL)arg2; +- (void)updateTranscribeVoiceMessage:(id)arg1 voiceText:(id)arg2 voiceToTextStatus:(unsigned int)arg3; +@end + +@interface MMAppBrandMessageCellView : NSObject ++ (id)makeAppBrandTableItemWithItem:(id)arg1; +@end + +@interface MMUnsupportedCellView : NSObject ++ (id)makeUnsupportedTableItemWithItem:(id)arg1; +@end + +@interface MMPayTransferCellView : NSObject ++ (id)makePayTransferTableItemWithItem:(id)arg1; +@end + + diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/Base.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/Base.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..a4d60950 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/Base.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/Base.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/Base.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..ba99cd79 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/Base.lproj/TKRemoteControlWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist b/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist index 1953c6c7..baf9b6cc 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 17C88 + 22D68 CFBundleDevelopmentRegion en CFBundleExecutable @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.7.5 CFBundleSupportedPlatforms MacOSX @@ -27,18 +27,26 @@ DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 9C40b + 14A400 + DTPlatformName + macosx DTPlatformVersion - GM + 12.3 DTSDKBuild - 17C76 + 21E226 DTSDKName - macosx10.13 + macosx12.3 DTXcode - 0920 + 1401 DTXcodeBuild - 9C40b + 14A400 + LSMinimumSystemVersion + 10.12 NSHumanReadableCopyright Copyright © 2017年 tk. All rights reserved. + showUpdateWindow + + versionInfo + v1.7.5(2019-01-13):\n👉🏻 适配微信 Version. 2.3.22\n👉🏼 菜单栏新增是否允许微信启动时检测更新(非AppStore版本)\n👉🏽 优化 XML 解析\n\n\n\nv1.7.3 (2018-10-22):\n👉🏻 适配微信 Version. 2.3.19\n👉🏼 修复安全漏洞(请务必更新,若有安装QQ插件也需要更新)\n👉🏽 菜单栏-关于小助手-新增 alfred 开关(若不使用 aflred 可关闭) \n\nv1.7.1 (2018-07-24):\n👉🏻 适配微信 Version. 2.3.17\n👉🏼 新增 alfred 搜索最近聊天列表\n👉🏽 新增 alfred 查看用户聊天记录\n (需更新wechat-alfred-workflow)\n\nv1.7 (2018-05-12):\n👉🏻 新增不同账户设置不同的自动回复&远程控制\n👉🏼 自动回复新增总开关&指定联系人\n👉🏽 远程控制新增控制小助手配置\n👉🏾 新增一键已读\n👉 新增一键清除空回话\n👉🏻 新增国际化(支持英、简、繁)\n👉🏼 新增关于小助手\n👉🏽 新增在线更新小助手 \n👉🏾 去除微信url转链处理(从此直接打开抖音链接🌝 \n👉🏿 修复无法免认证登录&多开等bug \n diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKAutoReplyWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKAutoReplyWindowController.nib index ae319cd9..702159a1 100644 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKAutoReplyWindowController.nib and b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKAutoReplyWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKDownloadWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKDownloadWindowController.nib new file mode 100644 index 00000000..fff221ba Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKDownloadWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlCommands.plist b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlCommands.plist index 4a039a4c..6c0b3bb2 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlCommands.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlCommands.plist @@ -9,9 +9,11 @@ keyword ScreenSave function - 屏幕保护 + Assistant.Directive.ScreenSave enable + type + 1 executeCommand @@ -19,9 +21,11 @@ keyword LockScreen function - 锁屏 + Assistant.Directive.LockScreen enable + type + 1 executeCommand @@ -29,9 +33,11 @@ keyword Sleep function - 休眠 + Assistant.Directive.Sleep enable + type + 2 executeCommand @@ -39,9 +45,11 @@ keyword Shutdown function - 关机 + Assistant.Directive.Shutdown enable + type + 2 executeCommand @@ -49,9 +57,11 @@ keyword Restart function - 重启 + Assistant.Directive.Restart enable + type + 2 executeCommand @@ -59,9 +69,23 @@ keyword EmptyTrash function - 清空废纸篓 + Assistant.Directive.EmptyTrash enable + type + 2 + + + executeCommand + mute + keyword + Mute + function + Assistant.Directive.Mute + enable + + type + 2 @@ -71,19 +95,23 @@ keyword KillQQ function - 退出 QQ + Assistant.Directive.KillQQ enable + type + 2 executeCommand killWeChat keyword - KillWeChat + killWeChat function - 退出 WeChat + Assistant.Directive.KillWeChat enable + type + 2 executeCommand @@ -91,9 +119,11 @@ keyword KillChrome function - 退出 Chrome + Assistant.Directive.KillChrome enable + type + 2 executeCommand @@ -101,9 +131,23 @@ keyword KillSafari function - 退出 Safari + Assistant.Directive.KillSafari enable + type + 2 + + + executeCommand + killFirefox + keyword + killFirefox + function + Assistant.Directive.KillFirefox + enable + + type + 2 executeCommand @@ -111,9 +155,11 @@ keyword KillAll function - 退出所有程序 + Assistant.Directive.KillAll enable + type + 2 @@ -123,9 +169,11 @@ keyword Toggle function - 播放/暂停 + Assistant.Directive.Toggle enable + type + 2 executeCommand @@ -133,9 +181,11 @@ keyword Next function - 下一首 + Assistant.Directive.Next enable + type + 2 executeCommand @@ -143,9 +193,11 @@ keyword Previous function - 上一首 + Assistant.Directive.Previous enable + type + 2 executeCommand @@ -153,9 +205,11 @@ keyword VolumeUp function - 增大音量 + Assistant.Directive.VolumeUp enable + type + 2 executeCommand @@ -163,9 +217,11 @@ keyword VolumeDown function - 减小音量 + Assistant.Directive.VolumeDown enable + type + 2 executeCommand @@ -173,9 +229,61 @@ keyword LikeChange function - 喜欢/取消喜欢 + Assistant.Directive.LikeChange + enable + + type + 2 + + + + + executeCommand + getDirectiveList + keyword + getDirective + function + Assistant.Directive.GetList + enable + + type + 3 + + + executeCommand + PreventRevokeSwitch + keyword + PreventRevokeSwitch + function + Assistant.Directive.PreventRevokeSwitch + enable + + type + 3 + + + executeCommand + AutoReplySwitch + keyword + AutoReplySwitch + function + Assistant.Directive.AutoReplySwitch + enable + + type + 3 + + + executeCommand + AutoAuthSwitch + keyword + AutoAuthSwitch + function + Assistant.Directive.AutoAuthSwitch enable + type + 3 diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt index a2d8dd34..b33ba035 100644 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt and b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlWindowController.nib deleted file mode 100644 index d74c58a6..00000000 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlWindowController.nib and /dev/null differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/Localizable.strings new file mode 100644 index 00000000..3ce3c06e Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..7beb627a Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..5b00ae8e --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Resources/en.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,53 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset0 HelveticaNeue-Bold; +\f3\fnil\fcharset134 PingFangSC-Regular;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs34 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs34 \cf2 Feature +\fs47\fsmilli23660 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs30 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Message auto reply\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Prevent message recall\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Remote control(support voice control)\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Multiple WeChat\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Auth Login\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session Sticky Bottom\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Windows Sticky Top\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session multiple delete\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Login Switch\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Quick reply to notifications\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Copy or Export Sticker\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Update plugin\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Reply or Open session by Alfred +\f3\fs32 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/Localizable.strings new file mode 100644 index 00000000..dac51801 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..caa429c2 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..8411d6cd --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,213 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Regular;\f5\fnil\fcharset0 AppleColorEmoji; +} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;\red255\green255\blue255; +\red52\green110\blue183;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;\cssrgb\c100000\c100000\c100000; +\cssrgb\c25490\c51373\c76863;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2} +{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3} +{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs48 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d3\'ef\'d2\'f4 +\f1 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'bf\'aa +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'c2\'bc\'c3\'e2\'c8\'cf\'d6\'a4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f1 ( +\f4 \strike \strikec2 \'c0\'e0\'cb\'c6\'d6\'c3\'b6\'a5 +\f1 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'b6\'af\'b5\'c7\'c2\'bc\'bf\'aa\'b9\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6 +\f1 & +\f4 \'b4\'e6\'b4\'a2 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f1 \ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0\cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'b4\'b0\'bf\'da\ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1 \cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'d2\'bb\'bc\'fc\'d2\'d1\'b6\'c1 +\f1 \cb1 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls1\ilvl0\cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d2\'bb\'bc\'fc\'c7\'e5\'b3\'fd\'bf\'d5\'bb\'e1\'bb\'b0 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d6\'a7\'b3\'d6\'b9\'fa\'bc\'ca\'bb\'af +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'bb\'bc\'fc\'b8\'fc\'d0\'c2 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c8\'a5\'b3\'fd\'ce\'a2\'d0\'c5 +\f1 url +\f4 \'d7\'aa\'c1\'b4\'a3\'a8\'b4\'d3\'b4\'cb\'d6\'b1\'bd\'d3\'b4\'f2\'bf\'aa\'b6\'b6\'d2\'f4\'c1\'b4\'bd\'d3 +\f5 \uc0\u55356 \u57117 \ +\ls1\ilvl0 +\f1 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'cb\'d1\'cb\'f7\'d7\'ee\'bd\'fc\'c1\'c4\'cc\'ec\'a1\'a2\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc +\f5 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 + +\f1 \cf2 \kerning1\expnd0\expndtw0 \'95 +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'c6\'b3\'fd\'bb\'e1\'bb\'b0(\'b2\'bb\'c9\'be\'b3\'fd\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc)\cb1 \ + +\f1 \cf5 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d6\'be\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls2\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'ca\'ca\'c5\'e4 +\f1 2.3.17 & +\f4 \'bc\'d3\'c7\'bf +\f1 alfred +\f4 \'cb\'d1\'cb\'f7 +\f1 (2018-07-24)}} +\f2\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls3\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'d0\'c2\'d4\'f6\'ba\'c3\'b6\'e0\'b9\'a6\'c4\'dc +\f1 \'85(2018-05-12)}} +\f3\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls4\ilvl0 +\f1\b0\fs32 \cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'d1\'d3\'b3\'d9 +\f1 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'b6\'a5\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f1 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f1 Alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f1 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d3\'ef\'d2\'f4\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 mac & +\f4 \'d3\'c5\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2 +\f1 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6\'b4\'e6\'b4\'a2\'b5\'c8\'b5\'c8 +\f1 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 & +\f4 \'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd\'b5\'c8\'b5\'c8 +\f1 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f1 & +\f4 \'c3\'e2\'c8\'cf\'d6\'a4 +\f1 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'b8\'b4\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc\'cf\'fb\'ca\'a7\'b5\'c4 +\f1 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'b9\'b9\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'a3\'ac\'ca\'b5\'cf\'d6\'b6\'e0\'bb\'d8\'b8\'b4 +\f1 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'cf\'ea\'cf\'b8\'c4\'da\'c8\'dd\'c7\'eb\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f1\b0 \cf5 CHANGELOG}} +\f1\b0 \cf5 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/Localizable.strings new file mode 100644 index 00000000..b3c69032 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..16831867 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..635b6745 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..4739ae65 --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,155 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Light;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d5\'5a\'d2\'f4 +\f0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'e9\'5f +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'e4\'9b\'c3\'e2\'d5\'4a\'d7\'43 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f0 ( +\f4 \strike \strikec2 \'ee\'90\'cb\'c6\'d6\'c3\'ed\'94 +\f0 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'95\'fe\'d4\'92\'b6\'e0\'df\'78\'84\'68\'b3\'fd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'84\'d3\'b5\'c7\'e4\'9b\'e9\'5f\'ea\'50 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6 +\f0 & +\f4 \'b4\'e6\'83\'a6 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'b4\'b0\'bf\'da +\f0 \ +\pard\tx566\pardeftab720\partightenfactor0 + +\fs36\fsmilli18200 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d5\'49 +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls2\ilvl0 +\f0\b0\fs32 \cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'d1\'d3\'df\'74 +\f0 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'ed\'94\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f0 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f0 Alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f0 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d5\'5a\'d2\'f4\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 mac & +\f4 \'83\'9e\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2 +\f0 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6\'b4\'e6\'83\'a6\'b5\'c8\'b5\'c8 +\f0 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 & +\f4 \'b6\'e0\'df\'78\'84\'68\'b3\'fd\'b5\'c8\'b5\'c8 +\f0 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f0 & +\f4 \'c3\'e2\'d5\'4a\'d7\'43 +\f0 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'8f\'cd\'c1\'c4\'cc\'ec\'d3\'9b\'e4\'9b\'cf\'fb\'ca\'a7\'b5\'c4 +\f0 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'98\'8b\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'a3\'ac\'8c\'8d\'ac\'46\'b6\'e0\'bb\'d8\'8f\'cd +\f0 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'d4\'94\'bc\'9a\'83\'c8\'c8\'dd\'d5\'88\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f0\b0 \cf3 CHANGELOG}} +\f0\b0\fs36\fsmilli18200 \cf2 \ +} \ No newline at end of file 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 cf445b9d..3429ecc5 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Headers/WeChatPlugin.h +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Headers/WeChatPlugin.h @@ -13,8 +13,28 @@ FOUNDATION_EXPORT double WeChatPluginVersionNumber; FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; +@class WCContactData; + #pragma mark - 微信原始的部分类与方法 +@interface MMSystemLinkInfo : NSObject +@property(retain, nonatomic) NSMutableAttributedString *msgContent; + +@end +@interface MMContactProfileController : NSViewController +@property(copy, nonatomic) NSString *groupName; +@property(nonatomic) struct CGRect relativeToRect; +@property(nonatomic) unsigned long long preferredEdge; +@property(retain, nonatomic) WCContactData *contactData; +- (void)sendGetContactRequest:(id)arg1 withGroupName:(id)arg2; +- (void)showInView:(id)arg1; +@end + + +@interface MMBrandChatsViewController : NSObject +- (void)startChatWithContact:(id)arg1; +@end + @interface MMLoginOneClickViewController : NSViewController @property(nonatomic) NSTextField *descriptionLabel; - (void)onLoginButtonClicked:(id)arg1; @@ -28,25 +48,48 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)AutoAuth; - (void)ManualLogin:(id)arg1 withPassword:(id)arg2; - (void)ManualLogout; +- (void)FFAddSvrMsgImgVCZZ; - (void)QRCodeLoginWithUserName:(id)arg1 password:(id)arg2; +- (void)onAuthOKOfUser:(id)arg1 withSessionKey:(id)arg2 withServerId:(id)arg3 autoAuthKey:(id)arg4 isAutoAuth:(BOOL)arg5; @end @interface MMLoginViewController : NSObject @property(retain, nonatomic) MMLoginOneClickViewController *oneClickViewController; @end +@interface MMHandoffButton : NSView +@end + +@interface MMMainViewController : NSObject +@property(nonatomic) __weak MMHandoffButton *handoffButton; +@end + @interface MMMainWindowController : NSWindowController @property(retain, nonatomic) MMLoginViewController *loginViewController; +@property(retain, nonatomic) MMMainViewController *mainViewController; - (void)onAuthOK; - (void)onLogOut; @end -@interface MessageService : NSObject +@interface MMVoiceTranscribeCGI : NSObject +- (void)transcribeVoiceMessage:(id)arg1 withCompletion:(void (^)(void))arg2; +@end + +@interface FFProcessReqsvrZZ : NSObject - (void)onRevokeMsg:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1 sessionMsgList:(id)arg2; - (void)OnSyncBatchAddMsgs:(NSArray *)arg1 isFirstSync:(BOOL)arg2; -- (id)SendTextMessage:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; +- (void)FFImgToOnFavInfoInfoVCZZ:(id)arg1 isFirstSync:(BOOL)arg2; +- (id)FFProcessTReqZZ:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; - (id)GetMsgData:(id)arg1 svrId:(long)arg2; - (void)AddLocalMsg:(id)arg1 msgData:(id)arg2; +- (void)TranscribeVoiceMessage:(id)arg1 completion:(void (^)(void))arg2; +- (BOOL)ClearUnRead:(id)arg1 FromID:(unsigned int)arg2 ToID:(unsigned int)arg3; +- (BOOL)ClearUnRead:(id)arg1 FromCreateTime:(unsigned int)arg2 ToCreateTime:(unsigned int)arg3; +- (BOOL)HasMsgInChat:(id)arg1; +- (id)GetMsgListWithChatName:(id)arg1 fromCreateTime:(unsigned int)arg2 localId:(NSInteger)arg3 limitCnt:(NSInteger)arg4 hasMore:(char *)arg5 sortAscend:(BOOL)arg6; +- (void)DelMsg:(id)arg1 msgList:(id)arg2 isDelAll:(BOOL)arg3 isManual:(BOOL)arg4; @end @interface MMServiceCenter : NSObject @@ -64,10 +107,27 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic, setter=SetMsgType:) int msgType; // @synthesize msgType; @property(retain, nonatomic, setter=SetToUserName:) SKBuiltinString_t *toUserName; // @synthesize toUserName; @property (nonatomic, assign) unsigned int createTime; +@property(nonatomic, setter=SetNewMsgId:) long long newMsgId; +@end + +@interface MMChatMessageViewController : NSViewController +@property(retain, nonatomic) WCContactData *chatContact; +@property(nonatomic) __weak NSTableView *messageTableView; +- (void)scrollToMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(unsigned int)arg1 needHighLighted:(BOOL)arg2; +- (void)onClickSession; +- (void)reloadTableView; +@end + +@interface MMChatDetailSplitViewController : NSObject +@property(retain, nonatomic) MMChatMessageViewController *chatMessageViewController; @end @interface MMChatsViewController : NSViewController @property(nonatomic) __weak NSTableView *tableView; +@property(retain, nonatomic) MMBrandChatsViewController *brandChatsViewController; +@property(retain, nonatomic) MMChatDetailSplitViewController *chatDetailSplitViewController; @end @interface WeChat : NSObject @@ -75,16 +135,67 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +@property(nonatomic) BOOL hasAuthOK; +- (void)startANewChatWithContact:(id)arg1; +- (void)_clearAllUnreadMessages:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; +- (void)checkForUpdatesInBackground; +- (void)FFAddRecvFavZZ:(BOOL)arg1; @end @interface ContactStorage : NSObject - (id)GetSelfContact; - (id)GetContact:(id)arg1; +- (id)GetAllBrandContacts; +- (id)GetAllFavContacts; +- (id)GetAllFriendContacts; +@end + +@interface GroupStorage : NSObject +{ + NSMutableDictionary *m_dictGroupContacts; +} +- (id)GetAllGroups; +- (id)GetGroupMemberContact:(id)arg1; +- (void)notifyModifyGroupContactsOnMainThread:(id)arg1; +//- (id)GetGroupMemberListWithGroupContact:(id)arg1; +- (id)GetGroupMemberListWithGroupContact:(id)arg1 limit:(unsigned int)arg2 filterSelf:(BOOL)arg3; +@end + +@interface ChatRoomData : NSObject +{ + NSMutableDictionary *m_dicData; +} @end @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; // 头像 +@property(retain, nonatomic) NSString *m_nsHeadHDImgUrl; +@property(retain, nonatomic) NSString *m_nsHeadHDMd5; +@property(retain, nonatomic) NSString *m_nsAliasName; +@property(retain, nonatomic) NSString *avatarCacheKey; +@property(readonly, nonatomic) unsigned long long groupMemberCount; +@property(retain, nonatomic) ChatRoomData *m_chatRoomData; +@property(nonatomic) BOOL m_isShowRedDot; +- (BOOL)isBrandContact; +- (BOOL)isSelf; +- (id)innerGetGroupDisplayName; +- (NSString *)groupChatDisplayNameInGroup:(id)arg1; +- (id)getContactDisplayUsrName; +- (BOOL)isGroupChat; +- (BOOL)isMMChat; +- (BOOL)isMMContact; +- (BOOL)containsMember:(id)arg1; +- (id)displayRegion; +- (BOOL)isStickyFolder; +@end + +@interface WCPayInfoItem : NSObject +@property(retain, nonatomic) NSString *m_nsFeeDesc; @end @interface MessageData : NSObject @@ -93,25 +204,66 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(retain, nonatomic) NSString *toUsrName; @property(retain, nonatomic) NSString *msgContent; @property(retain, nonatomic) NSString *msgPushContent; +@property(retain, nonatomic) NSString *realChatUserName; +@property(retain, nonatomic) WCPayInfoItem *m_oWCPayInfoItem; // @dynamic m_oWCPayInfoItem; +@property(retain, nonatomic) NSString *m_nsAppName; +@property(retain, nonatomic) NSString *m_nsSourceDisplayname; @property(nonatomic) int messageType; @property(nonatomic) int msgStatus; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; +@property(nonatomic) long long mesSvrID; +@property(retain, nonatomic) NSString *msgVoiceText; +@property(copy, nonatomic) NSString *m_nsEmoticonMD5; +- (BOOL)isChatRoomMessage; +- (NSString *)groupChatSenderDisplayName; +- (id)getRealMessageContent; +- (id)getChatRoomUsrName; +- (BOOL)isSendFromSelf; +- (BOOL)isCustomEmojiMsg; +- (BOOL)isImgMsg; +- (BOOL)isVideoMsg; +- (BOOL)isVoiceMsg; +- (BOOL)canForward; +- (BOOL)IsPlayingSound; +- (id)summaryString:(BOOL)arg1; +- (BOOL)isEmojiAppMsg; +- (BOOL)isAppBrandMsg; +- (BOOL)IsUnPlayed; +- (void)SetPlayed; +@property(retain, nonatomic) NSString *m_nsTitle; +- (id)originalImageFilePath; +@property(retain, nonatomic) NSString *m_nsVideoPath; +@property(retain, nonatomic) NSString *m_nsFilePath; +@property(retain, nonatomic) NSString *m_nsAppMediaUrl; +@property(nonatomic) MessageData *m_refMessageData; +@property(nonatomic) unsigned int m_uiDownloadStatus; +- (void)SetPlayingSoundStatus:(BOOL)arg1; @end @interface CUtility : NSObject + (BOOL)HasWechatInstance; ++ (BOOL)FFSvrChatInfoMsgWithImgZZ; + (unsigned long long)getFreeDiskSpace; + (void)ReloadSessionForMsgSync; + (id)GetCurrentUserName; ++ (id)GetContactByUsrName:(id)arg1; ++ (BOOL)IsStickyChatsFolder:(id)arg1; +@end + +@interface MMSessionInfoPackedInfo: NSObject +@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MessageData *m_msgData; @end @interface MMSessionInfo : NSObject @property(nonatomic) BOOL m_bIsTop; // @synthesize m_bIsTop; @property(nonatomic) BOOL m_bShowUnReadAsRedDot; @property(nonatomic) BOOL m_isMentionedUnread; // @synthesize +@property BOOL isInGroupBox; @property(retain, nonatomic) NSString *m_nsUserName; // @synthesize m_nsUserName; -@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MMSessionInfoPackedInfo *m_packedInfo; +@property(nonatomic) unsigned int m_uUnReadCount; @end @protocol MMChatsTableCellViewDelegate @@ -129,21 +281,294 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @end @interface MMSessionMgr : NSObject -@property(retain, nonatomic) NSMutableArray *m_arrSession; -- (id)GetSessionAtIndex:(unsigned long long)arg1; -- (void)MuteSessionByUserName:(id)arg1; +//@property(retain, nonatomic) NSMutableArray *m_arrSession; +- (id)getSessionAtIndex:(unsigned long long)arg1; +- (id)sessionInfoByUserName:(id)arg1; +- (void)muteSessionByUserName:(id)arg1; +- (void)onUnReadCountChange:(id)arg1; //- (void)TopSessionByUserName:(id)arg1; -- (void)UnmuteSessionByUserName:(id)arg1; -- (void)UntopSessionByUserName:(id)arg1; -- (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; +- (void)unmuteSessionByUserName:(id)arg1; +- (void)untopSessionByUserName:(id)arg1; +- (void)changeSessionUnreadCountWithUserName:(id)arg1 to:(unsigned int)arg2; +- (void)removeSessionOfUser:(id)arg1 isDelMsg:(BOOL)arg2; - (void)sortSessions; +- (void)FFDataSvrMgrSvrFavZZ; +- (id)getContact:(id)arg1; +- (id)getSessionContact:(id)arg1; +- (void)onModifyContacts:(id)arg1; +- (NSMutableArray *)getAllSessions; @end @interface LogoutCGI : NSTableCellView - (void)sendLogoutCGIWithCompletion:(id)arg1; +- (void)FFVCRecvDataAddDataToMsgChatMgrRecvZZ:(id)arg1; @end @interface MMNotificationService : NSObject - (id)getNotificationContentWithMsgData:(id)arg1; - (void)userNotificationCenter:(id)arg1 didActivateNotification:(id)arg2; @end + +@interface MMMessageTableItem : NSObject +@property(retain, nonatomic) MessageData *message; +@end + +@interface MMStickerMessageCellView : NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(nonatomic) MMChatMessageViewController *delegate; +- (BOOL)allowCopy; +- (void)contextMenuCopy; +- (id)contextMenu; +@end + +@interface MMImageMessageCellView: NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@end + +@interface MMSystemMessageCellView: NSObject +@property(nonatomic) id delegate; +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(retain, nonatomic) NSTextView *msgTextView; +- (void)populateWithMessage:(id)arg1; +@end +@interface EmoticonMgr : NSObject +@property(retain, nonatomic) MessageData *message; +- (id)getEmotionDataWithMD5:(id)arg1; +- (id)getEmotionImgWithMD5:(id)arg1; +- (void)addFavEmoticon:(id)arg1; +- (void)addEmoticonToUploadQueueWithMD5:(id)arg1; +- (void)setAppStickerToastViewDelegate:(id)arg1; +@end + +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSString *,NSArray *, NSArray *, NSArray *,id))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMBasicSearchResult : NSObject +@end + +@interface MMSearchResultItem : NSObject +@property(retain, nonatomic) MMBasicSearchResult *result; +@end + +@interface MMSearchResultContainer : NSObject +@property(nonatomic) unsigned long long logicSearchResultFlag; // @synthesize +@end + +@interface MMContactSearchLogic : NSObject +{ + unsigned long long _logicSearchResultFlag; // 2.3.19 失效 +} +@property(retain, nonatomic) NSMutableArray *contactResults; +- (void)doSearchWithKeyword:(id)arg1 searchScene:(unsigned long long)arg2 resultIsShownBlock:(id)arg3 completion:(id)arg4; +@property(retain, nonatomic) NSMutableArray *groupResults; +@property(nonatomic) BOOL isBrandContactSearched; +@property(nonatomic) BOOL isChatLogSearched; +@property(nonatomic) BOOL isContactSearched; +@property(nonatomic) BOOL isGroupContactSearched; +@property(retain, nonatomic) NSMutableArray *oaResults; +- (void)clearAllResults; // 2.3.19 失效 +- (void)clearDataWhenSearchEnd; +- (void)reloadSearchResultDataWithKeyword:(id)arg1 completionBlock:(id)arg2; // 2.3.17 +- (void)reloadSearchResultDataWithCompletionBlock:(id)arg1; // 2.3.13 +- (void)reloadSearchResultDataWithKeyword:(id)arg1 resultContainer:(id)arg2 completionBlock:(id)arg3; +@property(retain, nonatomic) MMSearchResultContainer *searchResultContainer; +@end + +@interface MMComplexContactSearchResult : MMBasicSearchResult +@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 : MMBasicSearchResult +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end + +@interface MMComplexGroupContactSearchResult : MMBasicSearchResult +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +- (id)_getImageFromCacheWithMD5Key:(id)arg1; +- (void)avatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +- (void)getAvatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +@end + +@interface NSString (MD5) +- (id)md5String; +@end + +@interface MMSessionPickerLogic : NSObject +@property(nonatomic) NSArray *selectedUserNames; +@end + + +@interface MMSessionListView : NSObject +{ + MMSessionPickerLogic *m_logic; +} +@end + +@interface MMSessionPickerWindow : NSWindowController ++ (id)shareInstance; +- (void)beginSheetForWindow:(id)arg1 completionHandler:(void(^)(id a1))arg2; +@property(retain, nonatomic) id choosenViewController; // @synthesize +@property(retain, nonatomic) id listViewController; // @synthesize +- (void)setShowsGroupChats:(BOOL)arg1; +- (void)setShowsOfficialAccounts:(BOOL)arg1; +- (void)setShowsOtherNonhumanChats:(BOOL)arg1; +- (void)setType:(unsigned long long)arg1; + +@end + +@interface AFHTTPResponseSerializer : NSObject +@end + +@interface AFURLSessionManager : NSObject +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + progress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock + destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(void (^)(NSURLResponse *response, NSURL * filePath, NSError * error))completionHandler; +- (id)initWithSessionConfiguration:(id)arg1; +@end + +@interface AFHTTPRequestSerializer : NSObject ++ (id)serializer; +@property(nonatomic) unsigned long long cachePolicy; +@end + +@interface AFHTTPSessionManager : NSObject ++ (AFHTTPSessionManager *)manager; +@property(retain, nonatomic) AFHTTPRequestSerializer *requestSerializer; +@property(retain, nonatomic) AFHTTPResponseSerializer *responseSerializer; +@end + +@interface MMURLHandler : NSObject ++ (id)defaultHandler; +- (void)startGetA8KeyWithURL:(id)arg1; +- (BOOL)openURLWithDefault:(id)arg1; ++ (BOOL)containsHTTPString:(id)arg1; +- (void)openURLWithDefault:(id)arg1 useA8Key:(BOOL)arg2; +- (BOOL)preHandleUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface UserDefaultsService : NSObject +- (void)setString:(id)arg1 forKey:(id)arg2; +- (id)stringForKey:(id)arg1; +@end + +@interface MMLinkInfo : NSObject ++ (NSRange)rangeOfUrlInString:(id)arg1 withRange:(NSRange)arg2; +@end + +@interface MMCDNDownloadMgr : NSObject +- (BOOL)downloadImageWithMessage:(id)arg1 disableHevc:(BOOL)arg2 downloadType:(unsigned long long)arg3; +@end + +@interface MMMessageVideoService : NSObject +- (BOOL)downloadVideoWithMessage:(id)arg1; +@end + +@interface MMVoiceMessagePlayer : NSObject ++ (id)defaultPlayer; +- (void)playWithVoiceMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)playVoiceWithMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)stop; +@end + +@interface MultiPlatformStatusSyncMgr : NSObject +- (void)markVoiceMessageAsRead:(id)arg1; +@end + +@interface EmoticonDownloadMgr : NSObject +- (void)downloadEmoticonWithMessageData:(id)arg1; +@end + +@interface PathUtility : NSObject ++ (id)GetCurUserCachePath; ++ (id)emoticonPath:(id)arg1; ++ (id)getMsgVideoPathWithMessage:(id)arg1; ++ (id)getMsgVideoPathWithUserName:(id)arg1 localId:(unsigned int)arg2; +@end + +@interface MMExtensionCenter : NSObject +- (id)getExtension:(id)arg1; +@end + +@interface MMExtension : NSObject +- (BOOL)registerExtension:(id)arg1; +- (void)unregisterExtension:(id)arg1; +- (id)getExtensionListForSelector:(SEL)arg1; +@end + +@interface EmoticonMsgInfo : NSObject +@property(copy, nonatomic) NSString *cdnUrl; +@property(copy, nonatomic) NSString *m_nsMD5; +@end + +@protocol EmoticonDownloadMgrExt +@optional +- (void)emoticonDownloadFailed:(EmoticonMsgInfo *)arg1; +- (void)emoticonDownloadFinished:(EmoticonMsgInfo *)arg1; +@end + +@protocol IGroupMgrExt + +@end + +@interface MMChatMangerSearchReportMgr : NSObject +@property(retain, nonatomic) NSMutableArray *brandContactSearchResults; +@property(retain, nonatomic) NSMutableArray *chatLogSearchResults; +@property(retain, nonatomic) NSMutableArray *contactSearchResults; +@property(retain, nonatomic) NSMutableArray *groupContactSearchResults; +@end + +@interface MMWebViewHelper : NSObject ++ (BOOL)preHandleWebUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface XMLDictionaryParser : NSObject ++ (id)sharedInstance; +- (id)dictionaryWithString:(id)arg1; +@end + +@interface MMEmoticonData : NSObject +@property(retain, nonatomic) NSString *md5; // @synthesize md5=_md5; +@end + +@interface MMStickerPickerCell : NSView +@property(retain, nonatomic) MMEmoticonData *emoticonData; // @synthesize emoticonData=_emoticonData; +@property(nonatomic) __weak NSScrollView *collectionView; +@end + +@interface MMStickerCollectionViewController : NSViewController +@property(nonatomic) __weak id delegate; +@end + +@interface MMStickerPicker : NSViewController +- (void)hide; +@end + +@interface MMVoiceTranslateMgr : NSObject +- (void)doTranslate:(id)arg1 isAuto:(BOOL)arg2; +- (void)updateTranscribeVoiceMessage:(id)arg1 voiceText:(id)arg2 voiceToTextStatus:(unsigned int)arg3; +@end + +@interface MMAppBrandMessageCellView : NSObject ++ (id)makeAppBrandTableItemWithItem:(id)arg1; +@end + +@interface MMUnsupportedCellView : NSObject ++ (id)makeUnsupportedTableItemWithItem:(id)arg1; +@end + +@interface MMPayTransferCellView : NSObject ++ (id)makePayTransferTableItemWithItem:(id)arg1; +@end + + diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Base.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Base.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..a4d60950 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Base.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Base.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Base.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..ba99cd79 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Base.lproj/TKRemoteControlWindowController.nib differ 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 1953c6c7..baf9b6cc 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Info.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 17C88 + 22D68 CFBundleDevelopmentRegion en CFBundleExecutable @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.7.5 CFBundleSupportedPlatforms MacOSX @@ -27,18 +27,26 @@ DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 9C40b + 14A400 + DTPlatformName + macosx DTPlatformVersion - GM + 12.3 DTSDKBuild - 17C76 + 21E226 DTSDKName - macosx10.13 + macosx12.3 DTXcode - 0920 + 1401 DTXcodeBuild - 9C40b + 14A400 + LSMinimumSystemVersion + 10.12 NSHumanReadableCopyright Copyright © 2017年 tk. All rights reserved. + showUpdateWindow + + versionInfo + v1.7.5(2019-01-13):\n👉🏻 适配微信 Version. 2.3.22\n👉🏼 菜单栏新增是否允许微信启动时检测更新(非AppStore版本)\n👉🏽 优化 XML 解析\n\n\n\nv1.7.3 (2018-10-22):\n👉🏻 适配微信 Version. 2.3.19\n👉🏼 修复安全漏洞(请务必更新,若有安装QQ插件也需要更新)\n👉🏽 菜单栏-关于小助手-新增 alfred 开关(若不使用 aflred 可关闭) \n\nv1.7.1 (2018-07-24):\n👉🏻 适配微信 Version. 2.3.17\n👉🏼 新增 alfred 搜索最近聊天列表\n👉🏽 新增 alfred 查看用户聊天记录\n (需更新wechat-alfred-workflow)\n\nv1.7 (2018-05-12):\n👉🏻 新增不同账户设置不同的自动回复&远程控制\n👉🏼 自动回复新增总开关&指定联系人\n👉🏽 远程控制新增控制小助手配置\n👉🏾 新增一键已读\n👉 新增一键清除空回话\n👉🏻 新增国际化(支持英、简、繁)\n👉🏼 新增关于小助手\n👉🏽 新增在线更新小助手 \n👉🏾 去除微信url转链处理(从此直接打开抖音链接🌝 \n👉🏿 修复无法免认证登录&多开等bug \n diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKAutoReplyWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKAutoReplyWindowController.nib index ae319cd9..702159a1 100644 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKAutoReplyWindowController.nib and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKAutoReplyWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKDownloadWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKDownloadWindowController.nib new file mode 100644 index 00000000..fff221ba Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKDownloadWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlCommands.plist b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlCommands.plist index 4a039a4c..6c0b3bb2 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlCommands.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlCommands.plist @@ -9,9 +9,11 @@ keyword ScreenSave function - 屏幕保护 + Assistant.Directive.ScreenSave enable + type + 1 executeCommand @@ -19,9 +21,11 @@ keyword LockScreen function - 锁屏 + Assistant.Directive.LockScreen enable + type + 1 executeCommand @@ -29,9 +33,11 @@ keyword Sleep function - 休眠 + Assistant.Directive.Sleep enable + type + 2 executeCommand @@ -39,9 +45,11 @@ keyword Shutdown function - 关机 + Assistant.Directive.Shutdown enable + type + 2 executeCommand @@ -49,9 +57,11 @@ keyword Restart function - 重启 + Assistant.Directive.Restart enable + type + 2 executeCommand @@ -59,9 +69,23 @@ keyword EmptyTrash function - 清空废纸篓 + Assistant.Directive.EmptyTrash enable + type + 2 + + + executeCommand + mute + keyword + Mute + function + Assistant.Directive.Mute + enable + + type + 2 @@ -71,19 +95,23 @@ keyword KillQQ function - 退出 QQ + Assistant.Directive.KillQQ enable + type + 2 executeCommand killWeChat keyword - KillWeChat + killWeChat function - 退出 WeChat + Assistant.Directive.KillWeChat enable + type + 2 executeCommand @@ -91,9 +119,11 @@ keyword KillChrome function - 退出 Chrome + Assistant.Directive.KillChrome enable + type + 2 executeCommand @@ -101,9 +131,23 @@ keyword KillSafari function - 退出 Safari + Assistant.Directive.KillSafari enable + type + 2 + + + executeCommand + killFirefox + keyword + killFirefox + function + Assistant.Directive.KillFirefox + enable + + type + 2 executeCommand @@ -111,9 +155,11 @@ keyword KillAll function - 退出所有程序 + Assistant.Directive.KillAll enable + type + 2 @@ -123,9 +169,11 @@ keyword Toggle function - 播放/暂停 + Assistant.Directive.Toggle enable + type + 2 executeCommand @@ -133,9 +181,11 @@ keyword Next function - 下一首 + Assistant.Directive.Next enable + type + 2 executeCommand @@ -143,9 +193,11 @@ keyword Previous function - 上一首 + Assistant.Directive.Previous enable + type + 2 executeCommand @@ -153,9 +205,11 @@ keyword VolumeUp function - 增大音量 + Assistant.Directive.VolumeUp enable + type + 2 executeCommand @@ -163,9 +217,11 @@ keyword VolumeDown function - 减小音量 + Assistant.Directive.VolumeDown enable + type + 2 executeCommand @@ -173,9 +229,61 @@ keyword LikeChange function - 喜欢/取消喜欢 + Assistant.Directive.LikeChange + enable + + type + 2 + + + + + executeCommand + getDirectiveList + keyword + getDirective + function + Assistant.Directive.GetList + enable + + type + 3 + + + executeCommand + PreventRevokeSwitch + keyword + PreventRevokeSwitch + function + Assistant.Directive.PreventRevokeSwitch + enable + + type + 3 + + + executeCommand + AutoReplySwitch + keyword + AutoReplySwitch + function + Assistant.Directive.AutoReplySwitch + enable + + type + 3 + + + executeCommand + AutoAuthSwitch + keyword + AutoAuthSwitch + function + Assistant.Directive.AutoAuthSwitch enable + type + 3 diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlScript.scpt b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlScript.scpt index a2d8dd34..b33ba035 100644 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlScript.scpt and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlScript.scpt differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlWindowController.nib deleted file mode 100644 index d74c58a6..00000000 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/TKRemoteControlWindowController.nib and /dev/null differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/Localizable.strings new file mode 100644 index 00000000..3ce3c06e Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..7beb627a Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..5b00ae8e --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/en.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,53 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset0 HelveticaNeue-Bold; +\f3\fnil\fcharset134 PingFangSC-Regular;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs34 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs34 \cf2 Feature +\fs47\fsmilli23660 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs30 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Message auto reply\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Prevent message recall\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Remote control(support voice control)\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Multiple WeChat\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Auth Login\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session Sticky Bottom\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Windows Sticky Top\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session multiple delete\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Login Switch\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Quick reply to notifications\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Copy or Export Sticker\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Update plugin\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Reply or Open session by Alfred +\f3\fs32 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings new file mode 100644 index 00000000..dac51801 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..caa429c2 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..8411d6cd --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,213 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Regular;\f5\fnil\fcharset0 AppleColorEmoji; +} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;\red255\green255\blue255; +\red52\green110\blue183;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;\cssrgb\c100000\c100000\c100000; +\cssrgb\c25490\c51373\c76863;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2} +{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3} +{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs48 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d3\'ef\'d2\'f4 +\f1 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'bf\'aa +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'c2\'bc\'c3\'e2\'c8\'cf\'d6\'a4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f1 ( +\f4 \strike \strikec2 \'c0\'e0\'cb\'c6\'d6\'c3\'b6\'a5 +\f1 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'b6\'af\'b5\'c7\'c2\'bc\'bf\'aa\'b9\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6 +\f1 & +\f4 \'b4\'e6\'b4\'a2 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f1 \ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0\cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'b4\'b0\'bf\'da\ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1 \cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'d2\'bb\'bc\'fc\'d2\'d1\'b6\'c1 +\f1 \cb1 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls1\ilvl0\cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d2\'bb\'bc\'fc\'c7\'e5\'b3\'fd\'bf\'d5\'bb\'e1\'bb\'b0 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d6\'a7\'b3\'d6\'b9\'fa\'bc\'ca\'bb\'af +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'bb\'bc\'fc\'b8\'fc\'d0\'c2 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c8\'a5\'b3\'fd\'ce\'a2\'d0\'c5 +\f1 url +\f4 \'d7\'aa\'c1\'b4\'a3\'a8\'b4\'d3\'b4\'cb\'d6\'b1\'bd\'d3\'b4\'f2\'bf\'aa\'b6\'b6\'d2\'f4\'c1\'b4\'bd\'d3 +\f5 \uc0\u55356 \u57117 \ +\ls1\ilvl0 +\f1 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'cb\'d1\'cb\'f7\'d7\'ee\'bd\'fc\'c1\'c4\'cc\'ec\'a1\'a2\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc +\f5 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 + +\f1 \cf2 \kerning1\expnd0\expndtw0 \'95 +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'c6\'b3\'fd\'bb\'e1\'bb\'b0(\'b2\'bb\'c9\'be\'b3\'fd\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc)\cb1 \ + +\f1 \cf5 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d6\'be\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls2\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'ca\'ca\'c5\'e4 +\f1 2.3.17 & +\f4 \'bc\'d3\'c7\'bf +\f1 alfred +\f4 \'cb\'d1\'cb\'f7 +\f1 (2018-07-24)}} +\f2\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls3\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'d0\'c2\'d4\'f6\'ba\'c3\'b6\'e0\'b9\'a6\'c4\'dc +\f1 \'85(2018-05-12)}} +\f3\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls4\ilvl0 +\f1\b0\fs32 \cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'d1\'d3\'b3\'d9 +\f1 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'b6\'a5\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f1 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f1 Alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f1 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d3\'ef\'d2\'f4\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 mac & +\f4 \'d3\'c5\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2 +\f1 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6\'b4\'e6\'b4\'a2\'b5\'c8\'b5\'c8 +\f1 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 & +\f4 \'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd\'b5\'c8\'b5\'c8 +\f1 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f1 & +\f4 \'c3\'e2\'c8\'cf\'d6\'a4 +\f1 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'b8\'b4\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc\'cf\'fb\'ca\'a7\'b5\'c4 +\f1 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'b9\'b9\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'a3\'ac\'ca\'b5\'cf\'d6\'b6\'e0\'bb\'d8\'b8\'b4 +\f1 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'cf\'ea\'cf\'b8\'c4\'da\'c8\'dd\'c7\'eb\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f1\b0 \cf5 CHANGELOG}} +\f1\b0 \cf5 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/Localizable.strings new file mode 100644 index 00000000..b3c69032 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..16831867 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..635b6745 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..4739ae65 --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,155 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Light;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d5\'5a\'d2\'f4 +\f0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'e9\'5f +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'e4\'9b\'c3\'e2\'d5\'4a\'d7\'43 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f0 ( +\f4 \strike \strikec2 \'ee\'90\'cb\'c6\'d6\'c3\'ed\'94 +\f0 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'95\'fe\'d4\'92\'b6\'e0\'df\'78\'84\'68\'b3\'fd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'84\'d3\'b5\'c7\'e4\'9b\'e9\'5f\'ea\'50 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6 +\f0 & +\f4 \'b4\'e6\'83\'a6 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'b4\'b0\'bf\'da +\f0 \ +\pard\tx566\pardeftab720\partightenfactor0 + +\fs36\fsmilli18200 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d5\'49 +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls2\ilvl0 +\f0\b0\fs32 \cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'d1\'d3\'df\'74 +\f0 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'ed\'94\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f0 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f0 Alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f0 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d5\'5a\'d2\'f4\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 mac & +\f4 \'83\'9e\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2 +\f0 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6\'b4\'e6\'83\'a6\'b5\'c8\'b5\'c8 +\f0 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 & +\f4 \'b6\'e0\'df\'78\'84\'68\'b3\'fd\'b5\'c8\'b5\'c8 +\f0 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f0 & +\f4 \'c3\'e2\'d5\'4a\'d7\'43 +\f0 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'8f\'cd\'c1\'c4\'cc\'ec\'d3\'9b\'e4\'9b\'cf\'fb\'ca\'a7\'b5\'c4 +\f0 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'98\'8b\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'a3\'ac\'8c\'8d\'ac\'46\'b6\'e0\'bb\'d8\'8f\'cd +\f0 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'d4\'94\'bc\'9a\'83\'c8\'c8\'dd\'d5\'88\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f0\b0 \cf3 CHANGELOG}} +\f0\b0\fs36\fsmilli18200 \cf2 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin b/Other/Products/Debug/WeChatPlugin.framework/Versions/A/WeChatPlugin index 0963c2e4..90ec0092 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 cf445b9d..3429ecc5 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Headers/WeChatPlugin.h +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Headers/WeChatPlugin.h @@ -13,8 +13,28 @@ FOUNDATION_EXPORT double WeChatPluginVersionNumber; FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; +@class WCContactData; + #pragma mark - 微信原始的部分类与方法 +@interface MMSystemLinkInfo : NSObject +@property(retain, nonatomic) NSMutableAttributedString *msgContent; + +@end +@interface MMContactProfileController : NSViewController +@property(copy, nonatomic) NSString *groupName; +@property(nonatomic) struct CGRect relativeToRect; +@property(nonatomic) unsigned long long preferredEdge; +@property(retain, nonatomic) WCContactData *contactData; +- (void)sendGetContactRequest:(id)arg1 withGroupName:(id)arg2; +- (void)showInView:(id)arg1; +@end + + +@interface MMBrandChatsViewController : NSObject +- (void)startChatWithContact:(id)arg1; +@end + @interface MMLoginOneClickViewController : NSViewController @property(nonatomic) NSTextField *descriptionLabel; - (void)onLoginButtonClicked:(id)arg1; @@ -28,25 +48,48 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)AutoAuth; - (void)ManualLogin:(id)arg1 withPassword:(id)arg2; - (void)ManualLogout; +- (void)FFAddSvrMsgImgVCZZ; - (void)QRCodeLoginWithUserName:(id)arg1 password:(id)arg2; +- (void)onAuthOKOfUser:(id)arg1 withSessionKey:(id)arg2 withServerId:(id)arg3 autoAuthKey:(id)arg4 isAutoAuth:(BOOL)arg5; @end @interface MMLoginViewController : NSObject @property(retain, nonatomic) MMLoginOneClickViewController *oneClickViewController; @end +@interface MMHandoffButton : NSView +@end + +@interface MMMainViewController : NSObject +@property(nonatomic) __weak MMHandoffButton *handoffButton; +@end + @interface MMMainWindowController : NSWindowController @property(retain, nonatomic) MMLoginViewController *loginViewController; +@property(retain, nonatomic) MMMainViewController *mainViewController; - (void)onAuthOK; - (void)onLogOut; @end -@interface MessageService : NSObject +@interface MMVoiceTranscribeCGI : NSObject +- (void)transcribeVoiceMessage:(id)arg1 withCompletion:(void (^)(void))arg2; +@end + +@interface FFProcessReqsvrZZ : NSObject - (void)onRevokeMsg:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1 sessionMsgList:(id)arg2; - (void)OnSyncBatchAddMsgs:(NSArray *)arg1 isFirstSync:(BOOL)arg2; -- (id)SendTextMessage:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; +- (void)FFImgToOnFavInfoInfoVCZZ:(id)arg1 isFirstSync:(BOOL)arg2; +- (id)FFProcessTReqZZ:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; - (id)GetMsgData:(id)arg1 svrId:(long)arg2; - (void)AddLocalMsg:(id)arg1 msgData:(id)arg2; +- (void)TranscribeVoiceMessage:(id)arg1 completion:(void (^)(void))arg2; +- (BOOL)ClearUnRead:(id)arg1 FromID:(unsigned int)arg2 ToID:(unsigned int)arg3; +- (BOOL)ClearUnRead:(id)arg1 FromCreateTime:(unsigned int)arg2 ToCreateTime:(unsigned int)arg3; +- (BOOL)HasMsgInChat:(id)arg1; +- (id)GetMsgListWithChatName:(id)arg1 fromCreateTime:(unsigned int)arg2 localId:(NSInteger)arg3 limitCnt:(NSInteger)arg4 hasMore:(char *)arg5 sortAscend:(BOOL)arg6; +- (void)DelMsg:(id)arg1 msgList:(id)arg2 isDelAll:(BOOL)arg3 isManual:(BOOL)arg4; @end @interface MMServiceCenter : NSObject @@ -64,10 +107,27 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic, setter=SetMsgType:) int msgType; // @synthesize msgType; @property(retain, nonatomic, setter=SetToUserName:) SKBuiltinString_t *toUserName; // @synthesize toUserName; @property (nonatomic, assign) unsigned int createTime; +@property(nonatomic, setter=SetNewMsgId:) long long newMsgId; +@end + +@interface MMChatMessageViewController : NSViewController +@property(retain, nonatomic) WCContactData *chatContact; +@property(nonatomic) __weak NSTableView *messageTableView; +- (void)scrollToMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(unsigned int)arg1 needHighLighted:(BOOL)arg2; +- (void)onClickSession; +- (void)reloadTableView; +@end + +@interface MMChatDetailSplitViewController : NSObject +@property(retain, nonatomic) MMChatMessageViewController *chatMessageViewController; @end @interface MMChatsViewController : NSViewController @property(nonatomic) __weak NSTableView *tableView; +@property(retain, nonatomic) MMBrandChatsViewController *brandChatsViewController; +@property(retain, nonatomic) MMChatDetailSplitViewController *chatDetailSplitViewController; @end @interface WeChat : NSObject @@ -75,16 +135,67 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +@property(nonatomic) BOOL hasAuthOK; +- (void)startANewChatWithContact:(id)arg1; +- (void)_clearAllUnreadMessages:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; +- (void)checkForUpdatesInBackground; +- (void)FFAddRecvFavZZ:(BOOL)arg1; @end @interface ContactStorage : NSObject - (id)GetSelfContact; - (id)GetContact:(id)arg1; +- (id)GetAllBrandContacts; +- (id)GetAllFavContacts; +- (id)GetAllFriendContacts; +@end + +@interface GroupStorage : NSObject +{ + NSMutableDictionary *m_dictGroupContacts; +} +- (id)GetAllGroups; +- (id)GetGroupMemberContact:(id)arg1; +- (void)notifyModifyGroupContactsOnMainThread:(id)arg1; +//- (id)GetGroupMemberListWithGroupContact:(id)arg1; +- (id)GetGroupMemberListWithGroupContact:(id)arg1 limit:(unsigned int)arg2 filterSelf:(BOOL)arg3; +@end + +@interface ChatRoomData : NSObject +{ + NSMutableDictionary *m_dicData; +} @end @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; // 头像 +@property(retain, nonatomic) NSString *m_nsHeadHDImgUrl; +@property(retain, nonatomic) NSString *m_nsHeadHDMd5; +@property(retain, nonatomic) NSString *m_nsAliasName; +@property(retain, nonatomic) NSString *avatarCacheKey; +@property(readonly, nonatomic) unsigned long long groupMemberCount; +@property(retain, nonatomic) ChatRoomData *m_chatRoomData; +@property(nonatomic) BOOL m_isShowRedDot; +- (BOOL)isBrandContact; +- (BOOL)isSelf; +- (id)innerGetGroupDisplayName; +- (NSString *)groupChatDisplayNameInGroup:(id)arg1; +- (id)getContactDisplayUsrName; +- (BOOL)isGroupChat; +- (BOOL)isMMChat; +- (BOOL)isMMContact; +- (BOOL)containsMember:(id)arg1; +- (id)displayRegion; +- (BOOL)isStickyFolder; +@end + +@interface WCPayInfoItem : NSObject +@property(retain, nonatomic) NSString *m_nsFeeDesc; @end @interface MessageData : NSObject @@ -93,25 +204,66 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(retain, nonatomic) NSString *toUsrName; @property(retain, nonatomic) NSString *msgContent; @property(retain, nonatomic) NSString *msgPushContent; +@property(retain, nonatomic) NSString *realChatUserName; +@property(retain, nonatomic) WCPayInfoItem *m_oWCPayInfoItem; // @dynamic m_oWCPayInfoItem; +@property(retain, nonatomic) NSString *m_nsAppName; +@property(retain, nonatomic) NSString *m_nsSourceDisplayname; @property(nonatomic) int messageType; @property(nonatomic) int msgStatus; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; +@property(nonatomic) long long mesSvrID; +@property(retain, nonatomic) NSString *msgVoiceText; +@property(copy, nonatomic) NSString *m_nsEmoticonMD5; +- (BOOL)isChatRoomMessage; +- (NSString *)groupChatSenderDisplayName; +- (id)getRealMessageContent; +- (id)getChatRoomUsrName; +- (BOOL)isSendFromSelf; +- (BOOL)isCustomEmojiMsg; +- (BOOL)isImgMsg; +- (BOOL)isVideoMsg; +- (BOOL)isVoiceMsg; +- (BOOL)canForward; +- (BOOL)IsPlayingSound; +- (id)summaryString:(BOOL)arg1; +- (BOOL)isEmojiAppMsg; +- (BOOL)isAppBrandMsg; +- (BOOL)IsUnPlayed; +- (void)SetPlayed; +@property(retain, nonatomic) NSString *m_nsTitle; +- (id)originalImageFilePath; +@property(retain, nonatomic) NSString *m_nsVideoPath; +@property(retain, nonatomic) NSString *m_nsFilePath; +@property(retain, nonatomic) NSString *m_nsAppMediaUrl; +@property(nonatomic) MessageData *m_refMessageData; +@property(nonatomic) unsigned int m_uiDownloadStatus; +- (void)SetPlayingSoundStatus:(BOOL)arg1; @end @interface CUtility : NSObject + (BOOL)HasWechatInstance; ++ (BOOL)FFSvrChatInfoMsgWithImgZZ; + (unsigned long long)getFreeDiskSpace; + (void)ReloadSessionForMsgSync; + (id)GetCurrentUserName; ++ (id)GetContactByUsrName:(id)arg1; ++ (BOOL)IsStickyChatsFolder:(id)arg1; +@end + +@interface MMSessionInfoPackedInfo: NSObject +@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MessageData *m_msgData; @end @interface MMSessionInfo : NSObject @property(nonatomic) BOOL m_bIsTop; // @synthesize m_bIsTop; @property(nonatomic) BOOL m_bShowUnReadAsRedDot; @property(nonatomic) BOOL m_isMentionedUnread; // @synthesize +@property BOOL isInGroupBox; @property(retain, nonatomic) NSString *m_nsUserName; // @synthesize m_nsUserName; -@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MMSessionInfoPackedInfo *m_packedInfo; +@property(nonatomic) unsigned int m_uUnReadCount; @end @protocol MMChatsTableCellViewDelegate @@ -129,21 +281,294 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @end @interface MMSessionMgr : NSObject -@property(retain, nonatomic) NSMutableArray *m_arrSession; -- (id)GetSessionAtIndex:(unsigned long long)arg1; -- (void)MuteSessionByUserName:(id)arg1; +//@property(retain, nonatomic) NSMutableArray *m_arrSession; +- (id)getSessionAtIndex:(unsigned long long)arg1; +- (id)sessionInfoByUserName:(id)arg1; +- (void)muteSessionByUserName:(id)arg1; +- (void)onUnReadCountChange:(id)arg1; //- (void)TopSessionByUserName:(id)arg1; -- (void)UnmuteSessionByUserName:(id)arg1; -- (void)UntopSessionByUserName:(id)arg1; -- (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; +- (void)unmuteSessionByUserName:(id)arg1; +- (void)untopSessionByUserName:(id)arg1; +- (void)changeSessionUnreadCountWithUserName:(id)arg1 to:(unsigned int)arg2; +- (void)removeSessionOfUser:(id)arg1 isDelMsg:(BOOL)arg2; - (void)sortSessions; +- (void)FFDataSvrMgrSvrFavZZ; +- (id)getContact:(id)arg1; +- (id)getSessionContact:(id)arg1; +- (void)onModifyContacts:(id)arg1; +- (NSMutableArray *)getAllSessions; @end @interface LogoutCGI : NSTableCellView - (void)sendLogoutCGIWithCompletion:(id)arg1; +- (void)FFVCRecvDataAddDataToMsgChatMgrRecvZZ:(id)arg1; @end @interface MMNotificationService : NSObject - (id)getNotificationContentWithMsgData:(id)arg1; - (void)userNotificationCenter:(id)arg1 didActivateNotification:(id)arg2; @end + +@interface MMMessageTableItem : NSObject +@property(retain, nonatomic) MessageData *message; +@end + +@interface MMStickerMessageCellView : NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(nonatomic) MMChatMessageViewController *delegate; +- (BOOL)allowCopy; +- (void)contextMenuCopy; +- (id)contextMenu; +@end + +@interface MMImageMessageCellView: NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@end + +@interface MMSystemMessageCellView: NSObject +@property(nonatomic) id delegate; +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(retain, nonatomic) NSTextView *msgTextView; +- (void)populateWithMessage:(id)arg1; +@end +@interface EmoticonMgr : NSObject +@property(retain, nonatomic) MessageData *message; +- (id)getEmotionDataWithMD5:(id)arg1; +- (id)getEmotionImgWithMD5:(id)arg1; +- (void)addFavEmoticon:(id)arg1; +- (void)addEmoticonToUploadQueueWithMD5:(id)arg1; +- (void)setAppStickerToastViewDelegate:(id)arg1; +@end + +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSString *,NSArray *, NSArray *, NSArray *,id))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMBasicSearchResult : NSObject +@end + +@interface MMSearchResultItem : NSObject +@property(retain, nonatomic) MMBasicSearchResult *result; +@end + +@interface MMSearchResultContainer : NSObject +@property(nonatomic) unsigned long long logicSearchResultFlag; // @synthesize +@end + +@interface MMContactSearchLogic : NSObject +{ + unsigned long long _logicSearchResultFlag; // 2.3.19 失效 +} +@property(retain, nonatomic) NSMutableArray *contactResults; +- (void)doSearchWithKeyword:(id)arg1 searchScene:(unsigned long long)arg2 resultIsShownBlock:(id)arg3 completion:(id)arg4; +@property(retain, nonatomic) NSMutableArray *groupResults; +@property(nonatomic) BOOL isBrandContactSearched; +@property(nonatomic) BOOL isChatLogSearched; +@property(nonatomic) BOOL isContactSearched; +@property(nonatomic) BOOL isGroupContactSearched; +@property(retain, nonatomic) NSMutableArray *oaResults; +- (void)clearAllResults; // 2.3.19 失效 +- (void)clearDataWhenSearchEnd; +- (void)reloadSearchResultDataWithKeyword:(id)arg1 completionBlock:(id)arg2; // 2.3.17 +- (void)reloadSearchResultDataWithCompletionBlock:(id)arg1; // 2.3.13 +- (void)reloadSearchResultDataWithKeyword:(id)arg1 resultContainer:(id)arg2 completionBlock:(id)arg3; +@property(retain, nonatomic) MMSearchResultContainer *searchResultContainer; +@end + +@interface MMComplexContactSearchResult : MMBasicSearchResult +@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 : MMBasicSearchResult +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end + +@interface MMComplexGroupContactSearchResult : MMBasicSearchResult +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +- (id)_getImageFromCacheWithMD5Key:(id)arg1; +- (void)avatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +- (void)getAvatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +@end + +@interface NSString (MD5) +- (id)md5String; +@end + +@interface MMSessionPickerLogic : NSObject +@property(nonatomic) NSArray *selectedUserNames; +@end + + +@interface MMSessionListView : NSObject +{ + MMSessionPickerLogic *m_logic; +} +@end + +@interface MMSessionPickerWindow : NSWindowController ++ (id)shareInstance; +- (void)beginSheetForWindow:(id)arg1 completionHandler:(void(^)(id a1))arg2; +@property(retain, nonatomic) id choosenViewController; // @synthesize +@property(retain, nonatomic) id listViewController; // @synthesize +- (void)setShowsGroupChats:(BOOL)arg1; +- (void)setShowsOfficialAccounts:(BOOL)arg1; +- (void)setShowsOtherNonhumanChats:(BOOL)arg1; +- (void)setType:(unsigned long long)arg1; + +@end + +@interface AFHTTPResponseSerializer : NSObject +@end + +@interface AFURLSessionManager : NSObject +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + progress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock + destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(void (^)(NSURLResponse *response, NSURL * filePath, NSError * error))completionHandler; +- (id)initWithSessionConfiguration:(id)arg1; +@end + +@interface AFHTTPRequestSerializer : NSObject ++ (id)serializer; +@property(nonatomic) unsigned long long cachePolicy; +@end + +@interface AFHTTPSessionManager : NSObject ++ (AFHTTPSessionManager *)manager; +@property(retain, nonatomic) AFHTTPRequestSerializer *requestSerializer; +@property(retain, nonatomic) AFHTTPResponseSerializer *responseSerializer; +@end + +@interface MMURLHandler : NSObject ++ (id)defaultHandler; +- (void)startGetA8KeyWithURL:(id)arg1; +- (BOOL)openURLWithDefault:(id)arg1; ++ (BOOL)containsHTTPString:(id)arg1; +- (void)openURLWithDefault:(id)arg1 useA8Key:(BOOL)arg2; +- (BOOL)preHandleUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface UserDefaultsService : NSObject +- (void)setString:(id)arg1 forKey:(id)arg2; +- (id)stringForKey:(id)arg1; +@end + +@interface MMLinkInfo : NSObject ++ (NSRange)rangeOfUrlInString:(id)arg1 withRange:(NSRange)arg2; +@end + +@interface MMCDNDownloadMgr : NSObject +- (BOOL)downloadImageWithMessage:(id)arg1 disableHevc:(BOOL)arg2 downloadType:(unsigned long long)arg3; +@end + +@interface MMMessageVideoService : NSObject +- (BOOL)downloadVideoWithMessage:(id)arg1; +@end + +@interface MMVoiceMessagePlayer : NSObject ++ (id)defaultPlayer; +- (void)playWithVoiceMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)playVoiceWithMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)stop; +@end + +@interface MultiPlatformStatusSyncMgr : NSObject +- (void)markVoiceMessageAsRead:(id)arg1; +@end + +@interface EmoticonDownloadMgr : NSObject +- (void)downloadEmoticonWithMessageData:(id)arg1; +@end + +@interface PathUtility : NSObject ++ (id)GetCurUserCachePath; ++ (id)emoticonPath:(id)arg1; ++ (id)getMsgVideoPathWithMessage:(id)arg1; ++ (id)getMsgVideoPathWithUserName:(id)arg1 localId:(unsigned int)arg2; +@end + +@interface MMExtensionCenter : NSObject +- (id)getExtension:(id)arg1; +@end + +@interface MMExtension : NSObject +- (BOOL)registerExtension:(id)arg1; +- (void)unregisterExtension:(id)arg1; +- (id)getExtensionListForSelector:(SEL)arg1; +@end + +@interface EmoticonMsgInfo : NSObject +@property(copy, nonatomic) NSString *cdnUrl; +@property(copy, nonatomic) NSString *m_nsMD5; +@end + +@protocol EmoticonDownloadMgrExt +@optional +- (void)emoticonDownloadFailed:(EmoticonMsgInfo *)arg1; +- (void)emoticonDownloadFinished:(EmoticonMsgInfo *)arg1; +@end + +@protocol IGroupMgrExt + +@end + +@interface MMChatMangerSearchReportMgr : NSObject +@property(retain, nonatomic) NSMutableArray *brandContactSearchResults; +@property(retain, nonatomic) NSMutableArray *chatLogSearchResults; +@property(retain, nonatomic) NSMutableArray *contactSearchResults; +@property(retain, nonatomic) NSMutableArray *groupContactSearchResults; +@end + +@interface MMWebViewHelper : NSObject ++ (BOOL)preHandleWebUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface XMLDictionaryParser : NSObject ++ (id)sharedInstance; +- (id)dictionaryWithString:(id)arg1; +@end + +@interface MMEmoticonData : NSObject +@property(retain, nonatomic) NSString *md5; // @synthesize md5=_md5; +@end + +@interface MMStickerPickerCell : NSView +@property(retain, nonatomic) MMEmoticonData *emoticonData; // @synthesize emoticonData=_emoticonData; +@property(nonatomic) __weak NSScrollView *collectionView; +@end + +@interface MMStickerCollectionViewController : NSViewController +@property(nonatomic) __weak id delegate; +@end + +@interface MMStickerPicker : NSViewController +- (void)hide; +@end + +@interface MMVoiceTranslateMgr : NSObject +- (void)doTranslate:(id)arg1 isAuto:(BOOL)arg2; +- (void)updateTranscribeVoiceMessage:(id)arg1 voiceText:(id)arg2 voiceToTextStatus:(unsigned int)arg3; +@end + +@interface MMAppBrandMessageCellView : NSObject ++ (id)makeAppBrandTableItemWithItem:(id)arg1; +@end + +@interface MMUnsupportedCellView : NSObject ++ (id)makeUnsupportedTableItemWithItem:(id)arg1; +@end + +@interface MMPayTransferCellView : NSObject ++ (id)makePayTransferTableItemWithItem:(id)arg1; +@end + + diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Base.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Base.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..a4d60950 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Base.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Base.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Base.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..ba99cd79 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Base.lproj/TKRemoteControlWindowController.nib differ 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 1953c6c7..baf9b6cc 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Info.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 17C88 + 22D68 CFBundleDevelopmentRegion en CFBundleExecutable @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.7.5 CFBundleSupportedPlatforms MacOSX @@ -27,18 +27,26 @@ DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 9C40b + 14A400 + DTPlatformName + macosx DTPlatformVersion - GM + 12.3 DTSDKBuild - 17C76 + 21E226 DTSDKName - macosx10.13 + macosx12.3 DTXcode - 0920 + 1401 DTXcodeBuild - 9C40b + 14A400 + LSMinimumSystemVersion + 10.12 NSHumanReadableCopyright Copyright © 2017年 tk. All rights reserved. + showUpdateWindow + + versionInfo + v1.7.5(2019-01-13):\n👉🏻 适配微信 Version. 2.3.22\n👉🏼 菜单栏新增是否允许微信启动时检测更新(非AppStore版本)\n👉🏽 优化 XML 解析\n\n\n\nv1.7.3 (2018-10-22):\n👉🏻 适配微信 Version. 2.3.19\n👉🏼 修复安全漏洞(请务必更新,若有安装QQ插件也需要更新)\n👉🏽 菜单栏-关于小助手-新增 alfred 开关(若不使用 aflred 可关闭) \n\nv1.7.1 (2018-07-24):\n👉🏻 适配微信 Version. 2.3.17\n👉🏼 新增 alfred 搜索最近聊天列表\n👉🏽 新增 alfred 查看用户聊天记录\n (需更新wechat-alfred-workflow)\n\nv1.7 (2018-05-12):\n👉🏻 新增不同账户设置不同的自动回复&远程控制\n👉🏼 自动回复新增总开关&指定联系人\n👉🏽 远程控制新增控制小助手配置\n👉🏾 新增一键已读\n👉 新增一键清除空回话\n👉🏻 新增国际化(支持英、简、繁)\n👉🏼 新增关于小助手\n👉🏽 新增在线更新小助手 \n👉🏾 去除微信url转链处理(从此直接打开抖音链接🌝 \n👉🏿 修复无法免认证登录&多开等bug \n diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKAutoReplyWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKAutoReplyWindowController.nib index ae319cd9..702159a1 100644 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKAutoReplyWindowController.nib and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKAutoReplyWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKDownloadWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKDownloadWindowController.nib new file mode 100644 index 00000000..fff221ba Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKDownloadWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlCommands.plist b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlCommands.plist index 4a039a4c..6c0b3bb2 100644 --- a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlCommands.plist +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlCommands.plist @@ -9,9 +9,11 @@ keyword ScreenSave function - 屏幕保护 + Assistant.Directive.ScreenSave enable + type + 1 executeCommand @@ -19,9 +21,11 @@ keyword LockScreen function - 锁屏 + Assistant.Directive.LockScreen enable + type + 1 executeCommand @@ -29,9 +33,11 @@ keyword Sleep function - 休眠 + Assistant.Directive.Sleep enable + type + 2 executeCommand @@ -39,9 +45,11 @@ keyword Shutdown function - 关机 + Assistant.Directive.Shutdown enable + type + 2 executeCommand @@ -49,9 +57,11 @@ keyword Restart function - 重启 + Assistant.Directive.Restart enable + type + 2 executeCommand @@ -59,9 +69,23 @@ keyword EmptyTrash function - 清空废纸篓 + Assistant.Directive.EmptyTrash enable + type + 2 + + + executeCommand + mute + keyword + Mute + function + Assistant.Directive.Mute + enable + + type + 2 @@ -71,19 +95,23 @@ keyword KillQQ function - 退出 QQ + Assistant.Directive.KillQQ enable + type + 2 executeCommand killWeChat keyword - KillWeChat + killWeChat function - 退出 WeChat + Assistant.Directive.KillWeChat enable + type + 2 executeCommand @@ -91,9 +119,11 @@ keyword KillChrome function - 退出 Chrome + Assistant.Directive.KillChrome enable + type + 2 executeCommand @@ -101,9 +131,23 @@ keyword KillSafari function - 退出 Safari + Assistant.Directive.KillSafari enable + type + 2 + + + executeCommand + killFirefox + keyword + killFirefox + function + Assistant.Directive.KillFirefox + enable + + type + 2 executeCommand @@ -111,9 +155,11 @@ keyword KillAll function - 退出所有程序 + Assistant.Directive.KillAll enable + type + 2 @@ -123,9 +169,11 @@ keyword Toggle function - 播放/暂停 + Assistant.Directive.Toggle enable + type + 2 executeCommand @@ -133,9 +181,11 @@ keyword Next function - 下一首 + Assistant.Directive.Next enable + type + 2 executeCommand @@ -143,9 +193,11 @@ keyword Previous function - 上一首 + Assistant.Directive.Previous enable + type + 2 executeCommand @@ -153,9 +205,11 @@ keyword VolumeUp function - 增大音量 + Assistant.Directive.VolumeUp enable + type + 2 executeCommand @@ -163,9 +217,11 @@ keyword VolumeDown function - 减小音量 + Assistant.Directive.VolumeDown enable + type + 2 executeCommand @@ -173,9 +229,61 @@ keyword LikeChange function - 喜欢/取消喜欢 + Assistant.Directive.LikeChange + enable + + type + 2 + + + + + executeCommand + getDirectiveList + keyword + getDirective + function + Assistant.Directive.GetList + enable + + type + 3 + + + executeCommand + PreventRevokeSwitch + keyword + PreventRevokeSwitch + function + Assistant.Directive.PreventRevokeSwitch + enable + + type + 3 + + + executeCommand + AutoReplySwitch + keyword + AutoReplySwitch + function + Assistant.Directive.AutoReplySwitch + enable + + type + 3 + + + executeCommand + AutoAuthSwitch + keyword + AutoAuthSwitch + function + Assistant.Directive.AutoAuthSwitch enable + type + 3 diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlScript.scpt b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlScript.scpt index a2d8dd34..b33ba035 100644 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlScript.scpt and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlScript.scpt differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlWindowController.nib deleted file mode 100644 index d74c58a6..00000000 Binary files a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/TKRemoteControlWindowController.nib and /dev/null differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/Localizable.strings new file mode 100644 index 00000000..3ce3c06e Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..7beb627a Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..5b00ae8e --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/en.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,53 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset0 HelveticaNeue-Bold; +\f3\fnil\fcharset134 PingFangSC-Regular;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs34 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs34 \cf2 Feature +\fs47\fsmilli23660 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs30 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Message auto reply\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Prevent message recall\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Remote control(support voice control)\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Multiple WeChat\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Auth Login\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session Sticky Bottom\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Windows Sticky Top\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session multiple delete\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Login Switch\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Quick reply to notifications\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Copy or Export Sticker\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Update plugin\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Reply or Open session by Alfred +\f3\fs32 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/Localizable.strings new file mode 100644 index 00000000..dac51801 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..caa429c2 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/TKRemoteControlWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..8411d6cd --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hans.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,213 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Regular;\f5\fnil\fcharset0 AppleColorEmoji; +} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;\red255\green255\blue255; +\red52\green110\blue183;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;\cssrgb\c100000\c100000\c100000; +\cssrgb\c25490\c51373\c76863;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2} +{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3} +{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs48 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d3\'ef\'d2\'f4 +\f1 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'bf\'aa +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'c2\'bc\'c3\'e2\'c8\'cf\'d6\'a4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f1 ( +\f4 \strike \strikec2 \'c0\'e0\'cb\'c6\'d6\'c3\'b6\'a5 +\f1 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'b6\'af\'b5\'c7\'c2\'bc\'bf\'aa\'b9\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6 +\f1 & +\f4 \'b4\'e6\'b4\'a2 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f1 \ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0\cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'b4\'b0\'bf\'da\ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1 \cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'d2\'bb\'bc\'fc\'d2\'d1\'b6\'c1 +\f1 \cb1 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls1\ilvl0\cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d2\'bb\'bc\'fc\'c7\'e5\'b3\'fd\'bf\'d5\'bb\'e1\'bb\'b0 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d6\'a7\'b3\'d6\'b9\'fa\'bc\'ca\'bb\'af +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'bb\'bc\'fc\'b8\'fc\'d0\'c2 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c8\'a5\'b3\'fd\'ce\'a2\'d0\'c5 +\f1 url +\f4 \'d7\'aa\'c1\'b4\'a3\'a8\'b4\'d3\'b4\'cb\'d6\'b1\'bd\'d3\'b4\'f2\'bf\'aa\'b6\'b6\'d2\'f4\'c1\'b4\'bd\'d3 +\f5 \uc0\u55356 \u57117 \ +\ls1\ilvl0 +\f1 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'cb\'d1\'cb\'f7\'d7\'ee\'bd\'fc\'c1\'c4\'cc\'ec\'a1\'a2\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc +\f5 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 + +\f1 \cf2 \kerning1\expnd0\expndtw0 \'95 +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'c6\'b3\'fd\'bb\'e1\'bb\'b0(\'b2\'bb\'c9\'be\'b3\'fd\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc)\cb1 \ + +\f1 \cf5 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d6\'be\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls2\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'ca\'ca\'c5\'e4 +\f1 2.3.17 & +\f4 \'bc\'d3\'c7\'bf +\f1 alfred +\f4 \'cb\'d1\'cb\'f7 +\f1 (2018-07-24)}} +\f2\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls3\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'d0\'c2\'d4\'f6\'ba\'c3\'b6\'e0\'b9\'a6\'c4\'dc +\f1 \'85(2018-05-12)}} +\f3\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls4\ilvl0 +\f1\b0\fs32 \cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'d1\'d3\'b3\'d9 +\f1 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'b6\'a5\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f1 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f1 Alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f1 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d3\'ef\'d2\'f4\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 mac & +\f4 \'d3\'c5\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2 +\f1 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6\'b4\'e6\'b4\'a2\'b5\'c8\'b5\'c8 +\f1 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 & +\f4 \'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd\'b5\'c8\'b5\'c8 +\f1 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f1 & +\f4 \'c3\'e2\'c8\'cf\'d6\'a4 +\f1 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'b8\'b4\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc\'cf\'fb\'ca\'a7\'b5\'c4 +\f1 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'b9\'b9\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'a3\'ac\'ca\'b5\'cf\'d6\'b6\'e0\'bb\'d8\'b8\'b4 +\f1 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'cf\'ea\'cf\'b8\'c4\'da\'c8\'dd\'c7\'eb\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f1\b0 \cf5 CHANGELOG}} +\f1\b0 \cf5 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/Localizable.strings b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/Localizable.strings new file mode 100644 index 00000000..b3c69032 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/Localizable.strings differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/TKAboutWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/TKAboutWindowController.nib new file mode 100644 index 00000000..16831867 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/TKAboutWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib new file mode 100644 index 00000000..635b6745 Binary files /dev/null and b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/TKRemoteControlWindowController.nib differ diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..4739ae65 --- /dev/null +++ b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/Resources/zh-Hant.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,155 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Light;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d5\'5a\'d2\'f4 +\f0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'e9\'5f +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'e4\'9b\'c3\'e2\'d5\'4a\'d7\'43 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f0 ( +\f4 \strike \strikec2 \'ee\'90\'cb\'c6\'d6\'c3\'ed\'94 +\f0 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'95\'fe\'d4\'92\'b6\'e0\'df\'78\'84\'68\'b3\'fd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'84\'d3\'b5\'c7\'e4\'9b\'e9\'5f\'ea\'50 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6 +\f0 & +\f4 \'b4\'e6\'83\'a6 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'b4\'b0\'bf\'da +\f0 \ +\pard\tx566\pardeftab720\partightenfactor0 + +\fs36\fsmilli18200 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d5\'49 +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls2\ilvl0 +\f0\b0\fs32 \cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'d1\'d3\'df\'74 +\f0 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'ed\'94\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f0 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f0 Alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f0 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d5\'5a\'d2\'f4\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 mac & +\f4 \'83\'9e\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2 +\f0 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6\'b4\'e6\'83\'a6\'b5\'c8\'b5\'c8 +\f0 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 & +\f4 \'b6\'e0\'df\'78\'84\'68\'b3\'fd\'b5\'c8\'b5\'c8 +\f0 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f0 & +\f4 \'c3\'e2\'d5\'4a\'d7\'43 +\f0 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'8f\'cd\'c1\'c4\'cc\'ec\'d3\'9b\'e4\'9b\'cf\'fb\'ca\'a7\'b5\'c4 +\f0 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'98\'8b\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'a3\'ac\'8c\'8d\'ac\'46\'b6\'e0\'bb\'d8\'8f\'cd +\f0 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'d4\'94\'bc\'9a\'83\'c8\'c8\'dd\'d5\'88\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f0\b0 \cf3 CHANGELOG}} +\f0\b0\fs36\fsmilli18200 \cf2 \ +} \ No newline at end of file diff --git a/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin b/Other/Products/Debug/WeChatPlugin.framework/Versions/Current/WeChatPlugin index 0963c2e4..90ec0092 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 0963c2e4..90ec0092 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_chat_log.gif b/Other/ScreenShots/alfred_chat_log.gif new file mode 100644 index 00000000..9464cef9 Binary files /dev/null and b/Other/ScreenShots/alfred_chat_log.gif 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/Other/ScreenShots/auto_reply.png b/Other/ScreenShots/auto_reply.png new file mode 100644 index 00000000..5c8fd424 Binary files /dev/null and b/Other/ScreenShots/auto_reply.png differ diff --git a/Other/ScreenShots/emotion_copy_export.png b/Other/ScreenShots/emotion_copy_export.png new file mode 100644 index 00000000..9eecb304 Binary files /dev/null and b/Other/ScreenShots/emotion_copy_export.png differ diff --git a/Other/ScreenShots/en/alfred.gif b/Other/ScreenShots/en/alfred.gif new file mode 100644 index 00000000..32248528 Binary files /dev/null and b/Other/ScreenShots/en/alfred.gif differ diff --git a/Other/ScreenShots/en/auto_auth_and_new.gif b/Other/ScreenShots/en/auto_auth_and_new.gif new file mode 100644 index 00000000..5091f4c4 Binary files /dev/null and b/Other/ScreenShots/en/auto_auth_and_new.gif differ diff --git a/Other/ScreenShots/en/auto_reply.gif b/Other/ScreenShots/en/auto_reply.gif new file mode 100644 index 00000000..a6eb2de2 Binary files /dev/null and b/Other/ScreenShots/en/auto_reply.gif differ diff --git a/Other/ScreenShots/en/emotion_copy_export.png b/Other/ScreenShots/en/emotion_copy_export.png new file mode 100644 index 00000000..f5d76df0 Binary files /dev/null and b/Other/ScreenShots/en/emotion_copy_export.png differ diff --git a/Other/ScreenShots/en/multiselect_and_stick_bottom_and_clear_empty.gif b/Other/ScreenShots/en/multiselect_and_stick_bottom_and_clear_empty.gif new file mode 100644 index 00000000..e375c829 Binary files /dev/null and b/Other/ScreenShots/en/multiselect_and_stick_bottom_and_clear_empty.gif differ diff --git a/Other/ScreenShots/en/prevent_recall.gif b/Other/ScreenShots/en/prevent_recall.gif new file mode 100644 index 00000000..3594453e Binary files /dev/null and b/Other/ScreenShots/en/prevent_recall.gif differ diff --git a/Other/ScreenShots/en/quick_reply_and_make_read.gif b/Other/ScreenShots/en/quick_reply_and_make_read.gif new file mode 100644 index 00000000..0e293741 Binary files /dev/null and b/Other/ScreenShots/en/quick_reply_and_make_read.gif differ diff --git a/Other/ScreenShots/en/remote_control.gif b/Other/ScreenShots/en/remote_control.gif new file mode 100644 index 00000000..268cce3d Binary files /dev/null and b/Other/ScreenShots/en/remote_control.gif differ diff --git a/Other/ScreenShots/en/wechatplugin.png b/Other/ScreenShots/en/wechatplugin.png new file mode 100644 index 00000000..8399ba4f Binary files /dev/null and b/Other/ScreenShots/en/wechatplugin.png differ diff --git a/Other/ScreenShots/install_download.png b/Other/ScreenShots/install_download.png new file mode 100644 index 00000000..2997e053 Binary files /dev/null and b/Other/ScreenShots/install_download.png differ diff --git a/Other/ScreenShots/install_terminal.png b/Other/ScreenShots/install_terminal.png new file mode 100644 index 00000000..e8cb52eb Binary files /dev/null and b/Other/ScreenShots/install_terminal.png differ diff --git a/Other/ScreenShots/notification_quick_reply.gif b/Other/ScreenShots/notification_quick_reply.gif new file mode 100644 index 00000000..b449fabf Binary files /dev/null and b/Other/ScreenShots/notification_quick_reply.gif differ diff --git a/Other/ScreenShots/notification_quick_reply.png b/Other/ScreenShots/notification_quick_reply.png deleted file mode 100644 index a9a120ce..00000000 Binary files a/Other/ScreenShots/notification_quick_reply.png and /dev/null differ diff --git a/Other/ScreenShots/remote_control.png b/Other/ScreenShots/remote_control.png new file mode 100644 index 00000000..99e4df26 Binary files /dev/null and b/Other/ScreenShots/remote_control.png differ diff --git a/Other/ScreenShots/session_empty_and_clean.gif b/Other/ScreenShots/session_empty_and_clean.gif new file mode 100644 index 00000000..4d1d5ff7 Binary files /dev/null and b/Other/ScreenShots/session_empty_and_clean.gif differ diff --git a/Other/ScreenShots/terminal_path.png b/Other/ScreenShots/terminal_path.png new file mode 100644 index 00000000..2f916c47 Binary files /dev/null and b/Other/ScreenShots/terminal_path.png differ diff --git a/Other/ScreenShots/voice_remote_control.gif b/Other/ScreenShots/voice_remote_control.gif new file mode 100644 index 00000000..c5d9fca9 Binary files /dev/null and b/Other/ScreenShots/voice_remote_control.gif differ diff --git a/Other/ScreenShots/wechatplugin.png b/Other/ScreenShots/wechatplugin.png new file mode 100644 index 00000000..f11de350 Binary files /dev/null and b/Other/ScreenShots/wechatplugin.png differ diff --git a/Other/Uninstall.sh b/Other/Uninstall.sh index 825be0b7..571a4d8f 100755 --- a/Other/Uninstall.sh +++ b/Other/Uninstall.sh @@ -1,18 +1,38 @@ # !/bin/bash +wechat_path="/Applications/WeChat.app" + +if [ ! -d "$wechat_path" ] +then +wechat_path="/Applications/微信.app" +if [ ! -d "$wechat_path" ] +then +echo -e "\n\n应用程序文件夹中未发现微信,请检查微信是否有重命名或者移动路径位置" +exit +fi +fi + app_name="WeChat" framework_name="WeChatPlugin" -app_bundle_path="/Applications/${app_name}.app/Contents/MacOS" +app_bundle_path="${wechat_path}/Contents/MacOS" app_executable_path="${app_bundle_path}/${app_name}" app_executable_backup_path="${app_executable_path}_backup" framework_path="${app_bundle_path}/${framework_name}.framework" + # 备份WeChat原始可执行文件 if [ -f "$app_executable_backup_path" ] then rm "$app_executable_path" rm -rf "$framework_path" mv "$app_executable_backup_path" "$app_executable_path" -echo "\n\t卸载成功" + +if [ -f "$app_executable_backup_path" ] +then + echo "卸载失败,请到 /Applications/WeChat.app/Contents/MacOS 路径,删除 WeChatPlugin.framework、WeChat 两个文件文件,并将 WeChat_backup 重命名为 WeChat" +else + echo "\n\t卸载成功" +fi + else echo "\n\t未发现微信小助手" fi diff --git a/Other/Update.sh b/Other/Update.sh new file mode 100755 index 00000000..0d36ef78 --- /dev/null +++ b/Other/Update.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +app_name="WeChat" +shell_path="$(dirname "$0")" +wechat_path="/Applications/WeChat.app" +framework_name="WeChatPlugin" +app_bundle_path="/Applications/${app_name}.app/Contents/MacOS" +app_executable_path="${app_bundle_path}/${app_name}" +app_executable_backup_path="${app_executable_path}_backup" +framework_path="${app_bundle_path}/${framework_name}.framework" + +# 对 WeChat 赋予权限 +if [ ! -w "$wechat_path" ] +then +echo -e "\n\n为了将小助手写入微信, 请输入密码 : " +sudo chown -R $(whoami) "$wechat_path" +fi + +# 备份 WeChat 原始可执行文件 +if [ ! -f "$app_executable_backup_path" ] +then +cp "$app_executable_path" "$app_executable_backup_path" +fi + +cp -r "${shell_path}/Products/Debug/${framework_name}.framework" ${app_bundle_path} +${shell_path}/insert_dylib --all-yes "${framework_path}/${framework_name}" "$app_executable_backup_path" "$app_executable_path" +${shell_path}/UpdateRemoteControlCommandsPlist.py diff --git a/Other/UpdateRemoteControlCommandsPlist.py b/Other/UpdateRemoteControlCommandsPlist.py new file mode 100755 index 00000000..88828b57 --- /dev/null +++ b/Other/UpdateRemoteControlCommandsPlist.py @@ -0,0 +1,57 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +""" +u为老用户自动同步新的plist,不改变已有的entry设置. +""" + +import sys, os +import plistlib + +PLIST_REMOTE_SUB_PATH = 'Products/Debug/WeChatPlugin.framework/Resources/TKRemoteControlCommands.plist' +PLIST_LOCAL_PATH = os.path.expanduser('~') + '/Library/Containers/com.tencent.xinWeChat/Data/Documents/TKWeChatPlugin/' + +def ExportPlistToDict(plist, key): + plist_dic = {} + for l1 in plist: + for l2 in l1: + plist_dic[l2[key]] = l2 + return plist_dic + +def SyncPlistContent(remote_plist, local_plist, key): + local_plist_dic = ExportPlistToDict(local_plist, key) + + new_tmp_plist = [] + for l1 in remote_plist: + new_tmp_plist.append([]) + for l2 in l1: + if l2[key] in local_plist_dic: + new_tmp_plist[-1].append(local_plist_dic[l2[key]]) + else: + new_tmp_plist[-1].append(l2) + + return new_tmp_plist + +def main(): + root_path = os.path.dirname(os.path.abspath(sys.argv[0])) + '/' + PLIST_REMOTE_PATH = root_path + PLIST_REMOTE_SUB_PATH + + if not os.path.isfile(PLIST_REMOTE_PATH) or not os.path.exists(PLIST_LOCAL_PATH): + print('Find plist failed... exit') + return 1 + + remote_plist = plistlib.readPlist(PLIST_REMOTE_PATH) + + for user in os.listdir(PLIST_LOCAL_PATH): + user_plist_dir = os.path.join(PLIST_LOCAL_PATH, user, 'TKRemoteControlCommands.plist') + if not os.path.isfile(user_plist_dir): + continue + + local_plist = plistlib.readPlist(user_plist_dir) + new_plist = SyncPlistContent(remote_plist, local_plist, 'function') + plistlib.writePlist(new_plist, user_plist_dir) + + return 0 + +if __name__ == '__main__': + main() diff --git a/Podfile b/Podfile new file mode 100644 index 00000000..67e89141 --- /dev/null +++ b/Podfile @@ -0,0 +1,6 @@ +platform :osx, '10.12' +inhibit_all_warnings! + +target 'WeChatPlugin' do + pod 'GCDWebServer', '~> 3.4.2' +end diff --git a/Q&A.md b/Q&A.md new file mode 100644 index 00000000..59682664 --- /dev/null +++ b/Q&A.md @@ -0,0 +1,95 @@ +## 常见问题解决方法: + +##### 0. 开场: +由于微信每次更新都会更新一些方法,因此建议可以先备份当前可用的微信.app(~~其实我是不太建议更新的~~),这样避免微信更新之后,小助手部分功能失效或者闪退。 + +--- + +##### 1. 为什么我更新微信之后菜单栏小助手不见了? + +因为微信更新之后,整个 app 都被覆盖,所以小助手也被清空,这时候只要重新安装小助手即可。 + +--- + +##### 2. 为什么更新了微信之后闪退/崩溃? + +因为微信更换了API,导致小助手找不到对应的方法、函数,因此崩溃,解决方法有两种:1. 下载旧版本的微信。2.卸载微信小助手。 + +--- + +##### 3. 有没有微信群或者 QQ群讨论? + +没有,目前没有这个打算。 + +--- + +##### 4. omw 无法安装或者是安装时候不是最新? + +omw 的问题可以去 [oh-my-wechat](https://github.com/lmk123/oh-my-wechat) 提 issue,这样作者能够及时解决。 +如果使用omw更新小助手不是最新的,可以使用其他安装方法试试。 + +--- + +##### 5. 如何卸载小助手? + +在终端执行 Other 文件夹中的 Uninstall.sh,如果无效的话,那么再终端执行以下代码: + +`cd /Applications/WeChat.app/Contents/MacOS && mv WeChat_backup WeChat` + +如果在无效,那么请在Finder中应用程序中,右击微信.app,查看包内容,打开目录`/Contents/MacOS `,将`WeChat_backup`改名为 `WeChat` + +--- + +##### 6. 如何禁止微信更新? + +可以下载小助手1.7.5,如果是从官网下载,点击菜单栏的`微信小助手`-`禁止微信启动时检测更新`,如果是从 App Store,那么请在 App Store 中设置去除自动更新下载。 + +##### 7. 能不能做朋友圈或者微信抢红包? + +* 不能,朋友圈工作量大,细节多,没有那么多的时间。 +* 抢红包是不可能的,这辈子都不可能的,因为也没有人给我发红包。 + +--- + +##### 8. 能不能做群管理或者是自动添加好友? + +不能,目前如果是有点微商性质的功能还是尽量避免,避免打扰到别人。 + +--- + +##### 9. 能不能做群发消息或者定时发送消息? + +不能,目前如果是有点微商性质的功能还是尽量避免,避免打扰到别人。 + +--- + +##### 10. 为什么不支持企业微信? + +企业微信跟普通的微信是两个app,方法也不一样,另外本人没有使用企业微信,因此不打算。 + +--- + +##### 11. 为什么菜单栏的小助手无法点击? + +因为目前小助手的功能是分账号设置的,因为如果用户退出登录的话,那么将无法点击,只有重新登录微信才行。 + +--- + +##### 12. Safari /共享无法分享到微信? + +目前无法解决。 + +--- + +##### 13. 休眠无法自动同步微信消息? + +目前还无法解决。 + +--- + +##### 14. 作者是不是不更新了? + +* 作者的目标是一年两更,现在已达标完成了。 + + + diff --git a/README.md b/README.md index ec5c4292..a6eb7fa2 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,89 @@ -## WeChatPlugin-MacOS -![](https://img.shields.io/badge/platform-osx-lightgrey.svg) ![](https://img.shields.io/badge/support-wechat%202.2.8-green.svg) - -微信小助手 v1.4.0 +![微信小助手.png](./Other/ScreenShots/wechatplugin.png) -![微信小助手.png](http://upload-images.jianshu.io/upload_images/965383-31708af611b55ca4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![platform](https://img.shields.io/badge/platform-macos-lightgrey.svg) [![release](https://img.shields.io/badge/release-v1.7.5-brightgreen.svg)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases) ![support](https://img.shields.io/badge/support-wechat%202.3.22-blue.svg) [![Readme](https://img.shields.io/badge/readme-english-yellow.svg)](./README_EN.md) [![GitHub license](https://img.shields.io/github/license/TKkk-iOSer/WeChatPlugin-MacOS.svg)](./LICENSE) -**iOS版本请戳→_→ [WeChatPlugin-iOS](https://github.com/TKkk-iOSer/WeChatPlugin-iOS)** +# 微信小助手 v2.0 -~~如何制作 mac OS 插件,请参考[我的博客](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/)~~ + **[English](./README_EN.md) | 中文** ---- - -### 更新日志 - -[新增窗口置顶&多选删除等等 (2017-10-11)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0) -[新增置底&免认证 (2017-09-17)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0) +[ [功能](#功能) • [更新日志](#更新日志) • [Demo演示](#demo演示) • [使用](#使用) • [安装](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/Install.md) • [卸载](#卸载) • [TODO](#todo) ] -[修复聊天记录消失的bug (2017-09-11)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0) - -[重构自动回复,实现多回复 (2017-08-23)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0) - -**详细内容请查看**[CHANGELOG](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md) +其他插件: +[ [wechat-alfred-workflow](https://github.com/TKkk-iOSer/wechat-alfred-workflow) • [QQ 版本](https://github.com/TKkk-iOSer/QQPlugin-macOS) ] --- -### 功能 +## 功能 * 消息自动回复 * 消息防撤回 -* 远程控制 +* 远程控制(已支持语音) * 微信多开 * 第二次登录免认证 * 聊天置底功能(~~类似置顶~~) * 微信窗口置顶 * 会话多选删除 * 自动登录开关 -* 通知快捷回复 +* 通知中心快捷回复 +* 聊天窗口表情包复制 & 存储 +* 小助手检测更新提醒 +* alfred 快捷发送消息 & 打开窗口 (需安装:[wechat-alfred-workflow](https://github.com/TKkk-iOSer/wechat-alfred-workflow)) +* 会话一键已读 +* 一键清除空会话 +* 支持国际化 +* 新增一键更新 +* 新增关于小助手 +* 去除微信url转链(从此直接打开抖音链接🌝 +* 史上最强 alfred 扩展🌚 +* 新增移除会话(不删除聊天记录) +* 菜单栏(关于小助手)新增 alfred 开关 +* 新增是否使用微信自带浏览器开关 +* 新增[LaunchBar 扩展](https://github.com/VDeamoV/WeChatHelper) +* 新增禁止微信检测更新开关(非App Store版本) +* ~~新增小助手.app安装方式~~ +* 支持退群监控,撤回消息定位 +* 支持微信 3.7.0 + +**若无使用 alfred,则不必打开 alfred 开关** 远程控制: ->远程控制新增指令发送成功回调、发送`获取指令`获得当前所有远程控制信息。 - - [x] 屏幕保护 - [x] 清空废纸篓 - [x] 锁屏、休眠、关机、重启 - [x] 退出QQ、WeChat、Chrome、Safari、所有程序 - [x] 网易云音乐(播放、暂停、下一首、上一首、喜欢、取消喜欢) +- [x] 小助手(获取指令、防撤回开关、自动回复开关、免认证登录开关) -**若想使用远程控制网易云音乐,请在“系统偏好设置 ==> 安全性与隐私 ==> 隐私 ==> 辅助功能”中添加微信** +**若想使用远程控制网易云音乐,请在“系统偏好设置 ==> 安全性与隐私 ==> 隐私 ==> 辅助功能”中添加微信、脚本编辑器** --- -### TODO -- [ ] 增加`Alfred`搜索 -- [ ] 查看单向好友 -- [ ] 语音(视频转发) -- [ ] 增加 brew 安装方式 -- [ ] 完善自动回复(指定好友回复、图灵机器人、) -- [ ] 完善消息防撤回(显示撤回用户昵称) -- [ ] 清除微信缓存 -- [ ] 优化小助手设置(更新后保留相关设置,更新提醒) -- [ ] 群聊屏蔽某成员 +## 更新日志 + +* [适配3.7.0(2023-03-12)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v2.0) +* [适配2.3.22 & 新增禁止微信检测更新开关(2019-01-13)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.5) +* [适配2.3.19 & 修复安全漏洞(2018-10-23)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.3) +* [适配2.3.17 & 加强 alfred 搜索(2018-07-24)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.1) +* [新增好多功能…(2018-05-12)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7) +* [新增自动回复延迟 & 修改置顶窗口快捷(2018-04-07)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1) +* [新增 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) +* [新增窗口置顶&多选删除等等 (2017-10-11)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0) +* [新增置底&免认证 (2017-09-17)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0) +* [修复聊天记录消失的bug (2017-09-11)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0) +* [重构自动回复,实现多回复 (2017-08-23)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0) + +**详细内容请查看**[CHANGELOG](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md) --- -### Demo 演示 +## Demo演示 -* 消息防撤回 +* 消息防撤回 ![消息防撤回.gif](http://upload-images.jianshu.io/upload_images/965383-30cbea645661e627.gif?imageMogr2/auto-orient/strip) * 自动回复 @@ -83,98 +98,110 @@ * 免认证 & 置底 & 多选删除 ![免认证&置底&多选删除](http://upload-images.jianshu.io/upload_images/965383-170592b03781cbf4.gif?imageMogr2/auto-orient/strip) -* 通知中心快捷回复 - - ---- +* 通知中心快捷回复 +![快捷回复](./Other/ScreenShots/notification_quick_reply.gif) -### 安装 +* 聊天窗口表情复制 & 存储 + -~~第一次安装需要输入密码,仅是为了获取写入微信文件夹的权限~~ +* 语音远程控制 mac +![语音远程控制](./Other/ScreenShots/voice_remote_control.gif) -**0. 懒癌版安装(适合非程序猿)** +* Alfred 快速搜索 [wechat-alfred-workflow](https://github.com/TKkk-iOSer/wechat-alfred-workflow) +![alfred](./Other/ScreenShots/alfred_search.gif) -打开`应用程序-实用工具-Terminal(终端)`,执行以下命令并根据提示输入密码即可。~~(需要git支持)~~ +* Alfred 搜索最近聊天列表 & 查看聊天记录 +![alfred](./Other/ScreenShots/alfred_chat_log.gif) -`cd ~/Downloads && git clone https://github.com/TKkk-iOSer/WeChatPlugin-MacOS.git && ./WeChatPlugin-MacOS/Other/Install.sh` +* 一键已读 & 一键清除空回话 +![基本操作](./Other/ScreenShots/session_empty_and_clean.gif) -**1. 普通安装** +--- -* 点击`clone or download`按钮下载 WeChatPlugin 至`下载`目录并解压,打开Termimal,执行 `~/Downloads/WeChatPlugin-MacOS-master/Other/Install.sh`即可。 +## 使用 +* 消息防撤回:点击`开启消息防撤回`或者快捷键`command + t`,即可开启、关闭。 +* 自动回复:点击`开启自动回复`或者快捷键`conmand + k`,将弹出自动回复设置的窗口,点击红色箭头的按钮设置开关。 -**2. 若想修改源码&重编译** +>若关键字为 `*`,则任何信息都回复; +>若关键字为`x|y`,则 x 和 y 都回复; +>若关键字**或者**自动回复为空,则不开启该条自动回复; +>可设置延迟回复,单位:秒; +>若开启正则,请确认正则表达式书写正确,[在线正则表达式测试](http://tool.oschina.net/regex/) +**若开启特定联系人回复,则原先的群聊&私聊回复无效** -* 先更改微信的 owner 以获取写入微信文件夹的权限,否则会出现类似**Permission denied**的错误。 +![自动回复设置.png](./Other/ScreenShots/auto_reply.png) -`sudo chown -R $(whoami) /Applications/WeChat.app` +* 微信多开:点击`登录新微信`或者快捷键`command + shift + n`,即可多开微信。 -![Permission denied.png](http://upload-images.jianshu.io/upload_images/965383-11e4480553ba086e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +* 远程控制:点击`远程控制 Mac OS`或者快捷键`command + shift + c`,即可打开控制窗口。 -* 下载 WeChatPlugin, 用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/)。 +**注意:仅向自己账号发送指令有效** -**3. 安装完成** +![远程控制设置.png](./Other/ScreenShots/remote_control.png) -* 登录微信,在**菜单栏**中看到**微信小助手**即安装成功。 -![微信小助手.png](http://upload-images.jianshu.io/upload_images/965383-31708af611b55ca4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +* Alfred 使用:请查看 [wechat-alfred-workflow](https://github.com/TKkk-iOSer/wechat-alfred-workflow) ---- +--- -### 使用 +## 安装 -* 消息防撤回:点击`开启消息防撤回`或者快捷键`command + t`,即可开启、关闭。 -* 自动回复:点击`开启自动回复`或者快捷键`conmand + k`,将弹出自动回复设置的窗口,点击红色箭头的按钮设置开关。 +详细安装方法(或者需要重新编译)请查阅 [Install.md](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/Install.md) ->若关键字为 `*`,则任何信息都回复; ->若关键字为`x|y`,则 x 和 y 都回复; ->若关键字**或者**自动回复为空,则不开启该条自动回复。 ->若开启正则,请确认正则表达式书写正确,[在线正则表达式测试](http://tool.oschina.net/regex/) +#### 1. 安装 -![自动回复设置.png](http://upload-images.jianshu.io/upload_images/965383-5aa2fd8fadc545c4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +**若提示无权限:`Permission denied`,执行 `sudo chmod -R 777 /Applications/WeChat.app`** +##### 1.1 需要安装Git -* 微信多开:点击`登录新微信`或者快捷键`command + shift + n`,即可多开微信。 +打开`应用程序-实用工具-Terminal(终端)`,执行下面的命令安装 -* 远程控制:点击`远程控制 Mac OS`或者快捷键`command + shift + c`,即可打开控制窗口。 +`cd ~/Downloads && rm -rf WeChatPlugin-MacOS && git clone https://github.com/TKkk-iOSer/WeChatPlugin-MacOS.git --depth=1 && ./WeChatPlugin-MacOS/Other/Install.sh` -![.png](http://upload-images.jianshu.io/upload_images/965383-9c67894ee7092600.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) -①为选择是否开启远程控制此功能。 +#### 2. 普通安装 -②为能够触发远程控制的消息内容(仅向自己发送账号有效)。 +* 点击`clone or download`按钮下载 WeChatPlugin 并解压,打开Terminal(终端),拖动解压后`Install.sh` 文件(在 Other 文件夹中)到 Terminal 回车即可。 +#### 3. 安装完成 -* 远程控制:发送`获取指令`,手机端可查看所有指令信息。 +* 重启微信,在**菜单栏**中看到**微信小助手**即安装成功。 -![远程控制.png](http://upload-images.jianshu.io/upload_images/965383-7c2a4b17e5a6867f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![微信小助手.png](./Other/ScreenShots/wechatplugin.png) --- -### 卸载 +## 卸载 -在`Terminal`(终端)打开该项目,运行 `./Other/Uninstall.sh` 即可. +打开Terminal(终端),拖动解压后`Uninstall.sh` 文件(在 Other 文件夹中)到 Terminal 回车即可。 +--- -~~或者在 `/Applications/WeChat.app/Contents/MacOS` 目录中,删除 `WeChat` 与 `WeChatPlugin.framework`,将`WeChat_backup` 重命名为 `WeChat` 即可。~~ +## TODO +- [x] 增加`Alfred`搜索 +- [ ] 查看单向好友 +- [ ] 增加 brew 安装方式 +- [x] 完善自动回复(指定好友回复) +- [x] 完善消息防撤回(显示撤回用户昵称) +- [x] ~~清除微信缓存(官方已加)~~ +- [x] 优化小助手设置(更新后保留相关设置,更新提醒) +- [x] 语音远程控制 mac +- [x] 支持中英文 +- [ ] 支持深色模式 --- -### 依赖 -* [XMLReader](https://github.com/amarcadet/XMLReader) +## 依赖 + * [insert_dylib](https://github.com/Tyilo/insert_dylib) * [fishhook](https://github.com/facebook/fishhook) +* [GCDWebServer](https://github.com/swisspol/GCDWebServer) --- -### Other -若有其他好的想法欢迎 Issue me - ---- +### 免责声明 +* 使用插件有风险,使用需谨慎。 +* 本项目旨在提升生活幸福感使用,不可用于商业和个人其他意图。若使用不当,请使用者自行承担。 +* 如有侵权,请联系本人。tkk.ioser@gmail.com -#### 听说你想请我喝下午茶?😏 - -    diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 00000000..c42ed1f5 --- /dev/null +++ b/README_EN.md @@ -0,0 +1,108 @@ + + +![wechat assistant.png](./Other/ScreenShots/en/wechatplugin.png) + +![platform](https://img.shields.io/badge/platform-macos-lightgrey.svg) [![release](https://img.shields.io/badge/release-v1.7-brightgreen.svg)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases) ![support](https://img.shields.io/badge/support-wechat%202.3.10-blue.svg) [![Readme](https://img.shields.io/badge/readme-中文-yellow.svg)](./README.md) [![GitHub license](https://img.shields.io/github/license/TKkk-iOSer/WeChatPlugin-MacOS.svg)](https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/LICENSE) + +# WeChatPlugin-macOS v1.7 + +**English | [中文](./README.md)** + +[ [Feature](#feature) • [Install](#install) • [Uninstall](#uninstall) • [Usage](#usage)] + +Other plugin: +[ [wechat-alfred-workflow](https://github.com/TKkk-iOSer/wechat-alfred-workflow) • [QQPlugin-macOS](https://github.com/TKkk-iOSer/QQPlugin-macOS) • [WeChatPlugin-iOS](https://github.com/TKkk-iOSer/WeChatPlugin-iOS) ] + +--- + +## Feature + +* Message auto reply +* Prevent message recall +* Remote control(support voice control) +* Multiple WeChat +* Auto Auth Login +* Session Sticky Bottom +* Windows Sticky Top +* Session multiple delete +* Auto Login Switch +* Quick reply to notifications +* Copy or Export Sticker +* Update plugin +* Reply or Open session by Alfred (dependency:[wechat-alfred-workflow](https://github.com/TKkk-iOSer/wechat-alfred-workflow)) +* Make all session As Read +* Clear all empty session +* Remove url redirect + +Remote Control: + +- [x] Save Screen +- [x] Empty Trash +- [x] Lock Screen & Sleep & Shut Down & Restart +- [x] Quit some app, include QQ、WeChat、Chrome、Safari。 +- [x] NeteaseMusic(play、pause、next song、previous song、like song、unlike song) +- [x] Assistant(get all directive、prevent recall switch、auto reply switch、auto auth switch) + +**If you want to control NeteaseMusic, please allow WeChat Control in "System Preferences-Security & Privacy-Privacy-Accessibility"** + +--- + +## Install + +**1. If you have installed Git** + +open `/Applications/Utilities/Terminal.app`,run command + +`cd ~/Downloads && rm -rf WeChatPlugin-MacOS && git clone https://github.com/TKkk-iOSer/WeChatPlugin-MacOS.git --depth=1 && ./WeChatPlugin-MacOS/Other/Install.sh`, and enter the mac password. + +**2. Normal install** + +* click `clone or download` button to download project and unzip it,open Terminal.app,Drag the `Install.sh` file(in `Other` Folder) to Terminal. + +--- + +## Uninstall +open `/Applications/Utilities/Terminal.app`,Drag the `Uninstall.sh` file(in `Other` Folder) to Terminal. + +--- + +## Usage + +> A few examples of how to use WeChatPlugin-macOS. + +* Prevent message recall + ![Prevent message recall](./Other/ScreenShots/en/prevent_recall.gif) + +* Message auto reply + ![Message auto reply](./Other/ScreenShots/en/auto_reply.gif) + +* Auto Login & Multiple WeChat + ![Auto Auth & Multiple WeChat](./Other/ScreenShots/en/auto_auth_and_new.gif) + +* Remote control (quit Chrome and Save Screen) + ![remote_control.gif](./Other/ScreenShots/en/remote_control.gif) + +* Session multiple delete & session sticky bottom & delete empty session + ![wechat assistant.png](./Other/ScreenShots/en/multiselect_and_stick_bottom_and_clear_empty.gif) + + +* Quick reply to notifications & make all as Read + ![wechat assistant.png](./Other/ScreenShots/en/quick_reply_and_make_read.gif) + + +* Copy or export sticker + + +* Reply or Open session by Alfred [wechat-alfred-workflow](https://github.com/TKkk-iOSer/wechat-alfred-workflow) + ![Alfred](./Other/ScreenShots/en/alfred.gif) + + +--- + +## Dependency + +* [insert_dylib](https://github.com/Tyilo/insert_dylib) +* [fishhook](https://github.com/facebook/fishhook) +* [GCDWebServer](https://github.com/swisspol/GCDWebServer) + + diff --git a/WeChatPlugin.xcodeproj/project.pbxproj b/WeChatPlugin.xcodeproj/project.pbxproj index 4831f480..a36f1ed8 100644 --- a/WeChatPlugin.xcodeproj/project.pbxproj +++ b/WeChatPlugin.xcodeproj/project.pbxproj @@ -7,6 +7,25 @@ objects = { /* Begin PBXBuildFile section */ + 520AE6E8208E1DA300BADE47 /* TKMessageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 520AE6E6208E1DA300BADE47 /* TKMessageManager.h */; }; + 520AE6E9208E1DA300BADE47 /* TKMessageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 520AE6E7208E1DA300BADE47 /* TKMessageManager.m */; }; + 520AE6F0208E231F00BADE47 /* NotifyConstant.h in Headers */ = {isa = PBXBuildFile; fileRef = 520AE6EF208E231F00BADE47 /* NotifyConstant.h */; }; + 520AE6F3208F62EF00BADE47 /* TKAssistantMenuManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 520AE6F1208F62EF00BADE47 /* TKAssistantMenuManager.h */; }; + 520AE6F4208F62EF00BADE47 /* TKAssistantMenuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 520AE6F2208F62EF00BADE47 /* TKAssistantMenuManager.m */; }; + 520AE6F7208F632700BADE47 /* TKRemoteControlManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 520AE6F5208F632700BADE47 /* TKRemoteControlManager.h */; }; + 520AE6F8208F632700BADE47 /* TKRemoteControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 520AE6F6208F632700BADE47 /* TKRemoteControlManager.m */; }; + 520F2009205E1DF900A36B1E /* TKWebServerManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 520F2007205E1DF900A36B1E /* TKWebServerManager.h */; }; + 520F200A205E1DF900A36B1E /* TKWebServerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 520F2008205E1DF900A36B1E /* TKWebServerManager.m */; }; + 52176DD9209809CE0035FA50 /* NSString+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 52176DD7209809CE0035FA50 /* NSString+Action.h */; }; + 52176DDA209809CE0035FA50 /* NSString+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 52176DD8209809CE0035FA50 /* NSString+Action.m */; }; + 521C49C320820662003902E7 /* TKRemoteControlWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 521C49C520820662003902E7 /* TKRemoteControlWindowController.xib */; }; + 521D75F92080E3670093C820 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 521D75FB2080E3670093C820 /* Localizable.strings */; }; + 52206B6A20836A230010C232 /* NSMenu+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 52206B6820836A230010C232 /* NSMenu+Action.h */; }; + 52206B6B20836A230010C232 /* NSMenu+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 52206B6920836A230010C232 /* NSMenu+Action.m */; }; + 52232710223922610016D3F7 /* TKEmoticonManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5223270E223922610016D3F7 /* TKEmoticonManager.h */; }; + 52232711223922610016D3F7 /* TKEmoticonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5223270F223922610016D3F7 /* TKEmoticonManager.m */; }; + 522327142239258D0016D3F7 /* MMStickerPickerCell+hook.h in Headers */ = {isa = PBXBuildFile; fileRef = 522327122239258D0016D3F7 /* MMStickerPickerCell+hook.h */; }; + 522327152239258D0016D3F7 /* MMStickerPickerCell+hook.m in Sources */ = {isa = PBXBuildFile; fileRef = 522327132239258D0016D3F7 /* MMStickerPickerCell+hook.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 */; }; @@ -14,48 +33,89 @@ 522547E01F4C312A00226A2A /* TKAutoReplyWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 522547D91F4C312A00226A2A /* TKAutoReplyWindowController.xib */; }; 522547E11F4C312A00226A2A /* TKRemoteControlWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 522547DB1F4C312A00226A2A /* TKRemoteControlWindowController.h */; }; 522547E21F4C312A00226A2A /* TKRemoteControlWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 522547DC1F4C312A00226A2A /* TKRemoteControlWindowController.m */; }; - 522547E31F4C312A00226A2A /* TKRemoteControlWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 522547DD1F4C312A00226A2A /* TKRemoteControlWindowController.xib */; }; + 5226D5CA2040FC3E0013C048 /* TKVersionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5226D5C82040FC3E0013C048 /* TKVersionManager.h */; }; + 5226D5CB2040FC3E0013C048 /* TKVersionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5226D5C92040FC3E0013C048 /* TKVersionManager.m */; }; 5228EABA1F70B59500D808CF /* NSButton+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 5228EAB81F70B59500D808CF /* NSButton+Action.h */; }; 5228EABB1F70B59500D808CF /* NSButton+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 5228EAB91F70B59500D808CF /* NSButton+Action.m */; }; 523848AB1F70E73500771BA3 /* NSTextField+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 523848A91F70E73500771BA3 /* NSTextField+Action.h */; }; 523848AC1F70E73500771BA3 /* NSTextField+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 523848AA1F70E73500771BA3 /* NSTextField+Action.m */; }; - 52475C2E1F6B993E00760E3E /* MMChatsTableCellView+hook.h in Headers */ = {isa = PBXBuildFile; fileRef = 52475C2C1F6B993E00760E3E /* MMChatsTableCellView+hook.h */; }; - 52475C2F1F6B993E00760E3E /* MMChatsTableCellView+hook.m in Sources */ = {isa = PBXBuildFile; fileRef = 52475C2D1F6B993E00760E3E /* MMChatsTableCellView+hook.m */; }; 52475C321F6BA43800760E3E /* TKIgnoreSessonModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 52475C301F6BA43800760E3E /* TKIgnoreSessonModel.h */; }; 52475C331F6BA43800760E3E /* TKIgnoreSessonModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 52475C311F6BA43800760E3E /* TKIgnoreSessonModel.m */; }; - 526F4D7D1F4AAADA00E46004 /* Color.h in Headers */ = {isa = PBXBuildFile; fileRef = 526F4D791F4AAADA00E46004 /* Color.h */; }; + 526F4D7D1F4AAADA00E46004 /* ColorConstant.h in Headers */ = {isa = PBXBuildFile; fileRef = 526F4D791F4AAADA00E46004 /* ColorConstant.h */; }; 526F4D801F4AAADA00E46004 /* TKPrefixHeader.pch in Headers */ = {isa = PBXBuildFile; fileRef = 526F4D7C1F4AAADA00E46004 /* TKPrefixHeader.pch */; }; 526F4D831F4AAC1900E46004 /* TKAutoReplyModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 526F4D811F4AAC1900E46004 /* TKAutoReplyModel.h */; }; 526F4D841F4AAC1900E46004 /* TKAutoReplyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 526F4D821F4AAC1900E46004 /* TKAutoReplyModel.m */; }; - 526F4D8B1F4AAC3800E46004 /* TKAutoReplyContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 526F4D861F4AAC3800E46004 /* TKAutoReplyContentView.h */; }; - 526F4D8C1F4AAC3800E46004 /* TKAutoReplyContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 526F4D871F4AAC3800E46004 /* TKAutoReplyContentView.m */; }; - 526F4D8D1F4AAC3800E46004 /* TKRemoteControlCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 526F4D891F4AAC3800E46004 /* TKRemoteControlCell.h */; }; - 526F4D8E1F4AAC3800E46004 /* TKRemoteControlCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 526F4D8A1F4AAC3800E46004 /* TKRemoteControlCell.m */; }; - 526F4D911F4AAE6F00E46004 /* TKAutoReplyCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 526F4D8F1F4AAE6F00E46004 /* TKAutoReplyCell.h */; }; - 526F4D921F4AAE6F00E46004 /* TKAutoReplyCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 526F4D901F4AAE6F00E46004 /* TKAutoReplyCell.m */; }; + 527D017320903C1B007155C9 /* NSMenuItem+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 527D017120903C1B007155C9 /* NSMenuItem+Action.h */; }; + 527D017420903C1B007155C9 /* NSMenuItem+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 527D017220903C1B007155C9 /* NSMenuItem+Action.m */; }; 527E7F622018711800358D26 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = 527E7F602018711800358D26 /* fishhook.c */; }; 527E7F632018711800358D26 /* fishhook.h in Headers */ = {isa = PBXBuildFile; fileRef = 527E7F612018711800358D26 /* fishhook.h */; }; + 52810B6B21E8FCF500861FC3 /* TKUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 52810B6921E8FCF500861FC3 /* TKUtility.h */; }; + 52810B6C21E8FCF500861FC3 /* TKUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 52810B6A21E8FCF500861FC3 /* TKUtility.m */; }; 528B4F971EA7383800BC6A89 /* WeChatPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 528B4F951EA7383800BC6A89 /* WeChatPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 528B4FB41EA7386D00BC6A89 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 528B4FAA1EA7386D00BC6A89 /* main.mm */; }; + 529950622113DAF10008BEE3 /* TKCacheManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 529950602113DAF10008BEE3 /* TKCacheManager.h */; }; + 529950632113DAF10008BEE3 /* TKCacheManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 529950612113DAF10008BEE3 /* TKCacheManager.m */; }; + 5299B2B021087C2B004810D2 /* NSDate+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 5299B2AE21087C2B004810D2 /* NSDate+Action.h */; }; + 5299B2B121087C2B004810D2 /* NSDate+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 5299B2AF21087C2B004810D2 /* NSDate+Action.m */; }; 529CDDFE1F6E6A060056DC1A /* TKBaseModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 529CDDFC1F6E6A060056DC1A /* TKBaseModel.h */; }; 529CDDFF1F6E6A060056DC1A /* TKBaseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 529CDDFD1F6E6A060056DC1A /* TKBaseModel.m */; }; 52B5CEF21F3B4623000D9DD9 /* TKRemoteControlCommands.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52B5CEF01F3B4623000D9DD9 /* TKRemoteControlCommands.plist */; }; 52B5CEF31F3B4623000D9DD9 /* TKRemoteControlScript.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 52B5CEF11F3B4623000D9DD9 /* TKRemoteControlScript.scpt */; }; - 52B5CF121F3B4631000D9DD9 /* WeChat+hook.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5CEF61F3B4631000D9DD9 /* WeChat+hook.h */; }; - 52B5CF131F3B4631000D9DD9 /* WeChat+hook.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B5CEF71F3B4631000D9DD9 /* WeChat+hook.m */; }; 52B5CF141F3B4631000D9DD9 /* TKWeChatPluginConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5CEF91F3B4631000D9DD9 /* TKWeChatPluginConfig.h */; }; 52B5CF151F3B4631000D9DD9 /* TKWeChatPluginConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B5CEFA1F3B4631000D9DD9 /* TKWeChatPluginConfig.m */; }; - 52B5CF161F3B4631000D9DD9 /* TKRemoteControlController.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5CEFC1F3B4631000D9DD9 /* TKRemoteControlController.h */; }; - 52B5CF171F3B4631000D9DD9 /* TKRemoteControlController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B5CEFD1F3B4631000D9DD9 /* TKRemoteControlController.m */; }; 52B5CF181F3B4631000D9DD9 /* TKRemoteControlModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5CEFF1F3B4631000D9DD9 /* TKRemoteControlModel.h */; }; 52B5CF191F3B4631000D9DD9 /* TKRemoteControlModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B5CF001F3B4631000D9DD9 /* TKRemoteControlModel.m */; }; 52B5CF1A1F3B4631000D9DD9 /* TKHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5CF021F3B4631000D9DD9 /* TKHelper.h */; }; 52B5CF1B1F3B4631000D9DD9 /* TKHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B5CF031F3B4631000D9DD9 /* TKHelper.m */; }; - 52B5CF1C1F3B4631000D9DD9 /* XMLReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5CF041F3B4631000D9DD9 /* XMLReader.h */; }; - 52B5CF1D1F3B4631000D9DD9 /* XMLReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B5CF051F3B4631000D9DD9 /* XMLReader.m */; }; + 52CD4C58209C5CA10061A5D6 /* NSWindowController+Action.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C56209C5CA10061A5D6 /* NSWindowController+Action.h */; }; + 52CD4C59209C5CA10061A5D6 /* NSWindowController+Action.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C57209C5CA10061A5D6 /* NSWindowController+Action.m */; }; + 52CD4C5E209CA0510061A5D6 /* TKAboutWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C5B209CA0510061A5D6 /* TKAboutWindowController.h */; }; + 52CD4C5F209CA0510061A5D6 /* TKAboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C5C209CA0510061A5D6 /* TKAboutWindowController.m */; }; + 52CD4C7C209ED2300061A5D6 /* TKAutoReplyCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C78209ED22F0061A5D6 /* TKAutoReplyCell.h */; }; + 52CD4C7D209ED2300061A5D6 /* TKAutoReplyContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C79209ED2300061A5D6 /* TKAutoReplyContentView.h */; }; + 52CD4C7E209ED2300061A5D6 /* TKAutoReplyContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C7A209ED2300061A5D6 /* TKAutoReplyContentView.m */; }; + 52CD4C7F209ED2300061A5D6 /* TKAutoReplyCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C7B209ED2300061A5D6 /* TKAutoReplyCell.m */; }; + 52CD4C82209ED23B0061A5D6 /* TKRemoteControlCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C80209ED23B0061A5D6 /* TKRemoteControlCell.m */; }; + 52CD4C83209ED23B0061A5D6 /* TKRemoteControlCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C81209ED23B0061A5D6 /* TKRemoteControlCell.h */; }; + 52CD4C8420A01CDC0061A5D6 /* TKAboutWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 52CD4C8620A01CDC0061A5D6 /* TKAboutWindowController.xib */; }; + 52CD4C8B20A07D420061A5D6 /* about.rtfd in Resources */ = {isa = PBXBuildFile; fileRef = 52CD4C8D20A07D420061A5D6 /* about.rtfd */; }; + 52CD4C9720A0885A0061A5D6 /* MMChatsTableCellView+hook.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C9120A088590061A5D6 /* MMChatsTableCellView+hook.h */; }; + 52CD4C9820A0885A0061A5D6 /* WeChat+hook.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C9220A088590061A5D6 /* WeChat+hook.h */; }; + 52CD4C9920A0885A0061A5D6 /* MMStickerMessageCellView+hook.h in Headers */ = {isa = PBXBuildFile; fileRef = 52CD4C9320A088590061A5D6 /* MMStickerMessageCellView+hook.h */; }; + 52CD4C9A20A0885A0061A5D6 /* MMStickerMessageCellView+hook.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C9420A088590061A5D6 /* MMStickerMessageCellView+hook.m */; }; + 52CD4C9B20A0885A0061A5D6 /* WeChat+hook.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C9520A088590061A5D6 /* WeChat+hook.m */; }; + 52CD4C9C20A0885A0061A5D6 /* MMChatsTableCellView+hook.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD4C9620A088590061A5D6 /* MMChatsTableCellView+hook.m */; }; + 52DA3E0D2094790900C618BB /* TKDownloadWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 52DA3E0A2094790900C618BB /* TKDownloadWindowController.h */; }; + 52DA3E0E2094790900C618BB /* TKDownloadWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DA3E0B2094790900C618BB /* TKDownloadWindowController.m */; }; + 52DA3E0F2094790900C618BB /* TKDownloadWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 52DA3E0C2094790900C618BB /* TKDownloadWindowController.xib */; }; + 52EA235920862D19008E6329 /* TKHTTPManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 52EA235720862D19008E6329 /* TKHTTPManager.h */; }; + 52EA235A20862D19008E6329 /* TKHTTPManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 52EA235820862D19008E6329 /* TKHTTPManager.m */; }; + 581E98663A5F0E6327516AA8 /* libPods-WeChatPlugin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 17F7A08DC0E3A0626801414D /* libPods-WeChatPlugin.a */; }; /* End PBXBuildFile section */ /* 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; }; + 520AE6E6208E1DA300BADE47 /* TKMessageManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKMessageManager.h; sourceTree = ""; }; + 520AE6E7208E1DA300BADE47 /* TKMessageManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKMessageManager.m; sourceTree = ""; }; + 520AE6EF208E231F00BADE47 /* NotifyConstant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotifyConstant.h; sourceTree = ""; }; + 520AE6F1208F62EF00BADE47 /* TKAssistantMenuManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKAssistantMenuManager.h; sourceTree = ""; }; + 520AE6F2208F62EF00BADE47 /* TKAssistantMenuManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKAssistantMenuManager.m; sourceTree = ""; }; + 520AE6F5208F632700BADE47 /* TKRemoteControlManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKRemoteControlManager.h; sourceTree = ""; }; + 520AE6F6208F632700BADE47 /* TKRemoteControlManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKRemoteControlManager.m; sourceTree = ""; }; + 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 = ""; }; + 52176DD7209809CE0035FA50 /* NSString+Action.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+Action.h"; sourceTree = ""; }; + 52176DD8209809CE0035FA50 /* NSString+Action.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+Action.m"; sourceTree = ""; }; + 521C49C620820663003902E7 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hans"; path = "zh-Hans.lproj/TKRemoteControlWindowController.xib"; sourceTree = ""; }; + 521D75FA2080E3670093C820 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 521D75FC2080E3780093C820 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 52206B6820836A230010C232 /* NSMenu+Action.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSMenu+Action.h"; sourceTree = ""; }; + 52206B6920836A230010C232 /* NSMenu+Action.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMenu+Action.m"; sourceTree = ""; }; + 5223270E223922610016D3F7 /* TKEmoticonManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKEmoticonManager.h; sourceTree = ""; }; + 5223270F223922610016D3F7 /* TKEmoticonManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKEmoticonManager.m; sourceTree = ""; }; + 522327122239258D0016D3F7 /* MMStickerPickerCell+hook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MMStickerPickerCell+hook.h"; sourceTree = ""; }; + 522327132239258D0016D3F7 /* MMStickerPickerCell+hook.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MMStickerPickerCell+hook.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 = ""; }; @@ -63,47 +123,75 @@ 522547D91F4C312A00226A2A /* TKAutoReplyWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TKAutoReplyWindowController.xib; sourceTree = ""; }; 522547DB1F4C312A00226A2A /* TKRemoteControlWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKRemoteControlWindowController.h; sourceTree = ""; }; 522547DC1F4C312A00226A2A /* TKRemoteControlWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKRemoteControlWindowController.m; sourceTree = ""; }; - 522547DD1F4C312A00226A2A /* TKRemoteControlWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TKRemoteControlWindowController.xib; sourceTree = ""; }; + 5226D5C82040FC3E0013C048 /* TKVersionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKVersionManager.h; sourceTree = ""; }; + 5226D5C92040FC3E0013C048 /* TKVersionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKVersionManager.m; sourceTree = ""; }; 5228EAB81F70B59500D808CF /* NSButton+Action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSButton+Action.h"; sourceTree = ""; }; 5228EAB91F70B59500D808CF /* NSButton+Action.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSButton+Action.m"; sourceTree = ""; }; 523848A91F70E73500771BA3 /* NSTextField+Action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTextField+Action.h"; sourceTree = ""; }; 523848AA1F70E73500771BA3 /* NSTextField+Action.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTextField+Action.m"; sourceTree = ""; }; - 52475C2C1F6B993E00760E3E /* MMChatsTableCellView+hook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MMChatsTableCellView+hook.h"; sourceTree = ""; }; - 52475C2D1F6B993E00760E3E /* MMChatsTableCellView+hook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MMChatsTableCellView+hook.m"; sourceTree = ""; }; + 5239B393241CAFDD00A471B4 /* TKConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKConstants.h; sourceTree = ""; }; 52475C301F6BA43800760E3E /* TKIgnoreSessonModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKIgnoreSessonModel.h; sourceTree = ""; }; 52475C311F6BA43800760E3E /* TKIgnoreSessonModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKIgnoreSessonModel.m; sourceTree = ""; }; - 526F4D791F4AAADA00E46004 /* Color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Color.h; sourceTree = ""; }; + 526A26702081AC03005B3E3C /* DefineConstant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DefineConstant.h; sourceTree = ""; }; + 526F4D791F4AAADA00E46004 /* ColorConstant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorConstant.h; sourceTree = ""; }; 526F4D7C1F4AAADA00E46004 /* TKPrefixHeader.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKPrefixHeader.pch; sourceTree = ""; }; 526F4D811F4AAC1900E46004 /* TKAutoReplyModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKAutoReplyModel.h; sourceTree = ""; }; 526F4D821F4AAC1900E46004 /* TKAutoReplyModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKAutoReplyModel.m; sourceTree = ""; }; - 526F4D861F4AAC3800E46004 /* TKAutoReplyContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKAutoReplyContentView.h; sourceTree = ""; }; - 526F4D871F4AAC3800E46004 /* TKAutoReplyContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKAutoReplyContentView.m; sourceTree = ""; }; - 526F4D891F4AAC3800E46004 /* TKRemoteControlCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKRemoteControlCell.h; sourceTree = ""; }; - 526F4D8A1F4AAC3800E46004 /* TKRemoteControlCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKRemoteControlCell.m; sourceTree = ""; }; - 526F4D8F1F4AAE6F00E46004 /* TKAutoReplyCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKAutoReplyCell.h; sourceTree = ""; }; - 526F4D901F4AAE6F00E46004 /* TKAutoReplyCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKAutoReplyCell.m; sourceTree = ""; }; + 527D017120903C1B007155C9 /* NSMenuItem+Action.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSMenuItem+Action.h"; sourceTree = ""; }; + 527D017220903C1B007155C9 /* NSMenuItem+Action.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMenuItem+Action.m"; sourceTree = ""; }; 527E7F602018711800358D26 /* fishhook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fishhook.c; sourceTree = ""; }; 527E7F612018711800358D26 /* fishhook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = ""; }; + 52810B6921E8FCF500861FC3 /* TKUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKUtility.h; sourceTree = ""; }; + 52810B6A21E8FCF500861FC3 /* TKUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKUtility.m; sourceTree = ""; }; + 52810B6D21E90B2400861FC3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TKAboutWindowController.xib; sourceTree = ""; }; + 52810B6E21E90B2500861FC3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TKRemoteControlWindowController.xib; sourceTree = ""; }; 528B4F921EA7383800BC6A89 /* WeChatPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WeChatPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 528B4F951EA7383800BC6A89 /* WeChatPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeChatPlugin.h; sourceTree = ""; }; 528B4F961EA7383800BC6A89 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 528B4FAA1EA7386D00BC6A89 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + 529950602113DAF10008BEE3 /* TKCacheManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKCacheManager.h; sourceTree = ""; }; + 529950612113DAF10008BEE3 /* TKCacheManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKCacheManager.m; sourceTree = ""; }; + 5299B2AE21087C2B004810D2 /* NSDate+Action.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+Action.h"; sourceTree = ""; }; + 5299B2AF21087C2B004810D2 /* NSDate+Action.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+Action.m"; sourceTree = ""; }; 529CDDFC1F6E6A060056DC1A /* TKBaseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKBaseModel.h; sourceTree = ""; }; 529CDDFD1F6E6A060056DC1A /* TKBaseModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKBaseModel.m; sourceTree = ""; }; 52B5CEF01F3B4623000D9DD9 /* TKRemoteControlCommands.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TKRemoteControlCommands.plist; sourceTree = ""; }; 52B5CEF11F3B4623000D9DD9 /* TKRemoteControlScript.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = TKRemoteControlScript.scpt; sourceTree = ""; }; - 52B5CEF61F3B4631000D9DD9 /* WeChat+hook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WeChat+hook.h"; sourceTree = ""; }; - 52B5CEF71F3B4631000D9DD9 /* WeChat+hook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WeChat+hook.m"; sourceTree = ""; }; 52B5CEF91F3B4631000D9DD9 /* TKWeChatPluginConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKWeChatPluginConfig.h; sourceTree = ""; }; 52B5CEFA1F3B4631000D9DD9 /* TKWeChatPluginConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKWeChatPluginConfig.m; sourceTree = ""; }; - 52B5CEFC1F3B4631000D9DD9 /* TKRemoteControlController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKRemoteControlController.h; sourceTree = ""; }; - 52B5CEFD1F3B4631000D9DD9 /* TKRemoteControlController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKRemoteControlController.m; sourceTree = ""; }; 52B5CEFF1F3B4631000D9DD9 /* TKRemoteControlModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKRemoteControlModel.h; sourceTree = ""; }; 52B5CF001F3B4631000D9DD9 /* TKRemoteControlModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKRemoteControlModel.m; sourceTree = ""; }; 52B5CF021F3B4631000D9DD9 /* TKHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKHelper.h; sourceTree = ""; }; 52B5CF031F3B4631000D9DD9 /* TKHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKHelper.m; sourceTree = ""; }; - 52B5CF041F3B4631000D9DD9 /* XMLReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLReader.h; sourceTree = ""; }; - 52B5CF051F3B4631000D9DD9 /* XMLReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMLReader.m; sourceTree = ""; }; + 52CD4C56209C5CA10061A5D6 /* NSWindowController+Action.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSWindowController+Action.h"; sourceTree = ""; }; + 52CD4C57209C5CA10061A5D6 /* NSWindowController+Action.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSWindowController+Action.m"; sourceTree = ""; }; + 52CD4C5B209CA0510061A5D6 /* TKAboutWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKAboutWindowController.h; sourceTree = ""; }; + 52CD4C5C209CA0510061A5D6 /* TKAboutWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKAboutWindowController.m; sourceTree = ""; }; + 52CD4C78209ED22F0061A5D6 /* TKAutoReplyCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKAutoReplyCell.h; sourceTree = ""; }; + 52CD4C79209ED2300061A5D6 /* TKAutoReplyContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKAutoReplyContentView.h; sourceTree = ""; }; + 52CD4C7A209ED2300061A5D6 /* TKAutoReplyContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKAutoReplyContentView.m; sourceTree = ""; }; + 52CD4C7B209ED2300061A5D6 /* TKAutoReplyCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKAutoReplyCell.m; sourceTree = ""; }; + 52CD4C80209ED23B0061A5D6 /* TKRemoteControlCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TKRemoteControlCell.m; sourceTree = ""; }; + 52CD4C81209ED23B0061A5D6 /* TKRemoteControlCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TKRemoteControlCell.h; sourceTree = ""; }; + 52CD4C8520A01CDC0061A5D6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/TKAboutWindowController.xib; sourceTree = ""; }; + 52CD4C8820A07B8E0061A5D6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hant"; path = "zh-Hant.lproj/TKAboutWindowController.xib"; sourceTree = ""; }; + 52CD4C8920A07B8E0061A5D6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "zh-Hant"; path = "zh-Hant.lproj/TKRemoteControlWindowController.xib"; sourceTree = ""; }; + 52CD4C8A20A07B8E0061A5D6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; + 52CD4C8C20A07D420061A5D6 /* en */ = {isa = PBXFileReference; lastKnownFileType = wrapper.rtfd; name = en; path = en.lproj/about.rtfd; sourceTree = ""; }; + 52CD4C8E20A07D450061A5D6 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = wrapper.rtfd; name = "zh-Hans"; path = "zh-Hans.lproj/about.rtfd"; sourceTree = ""; }; + 52CD4C8F20A07D460061A5D6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = wrapper.rtfd; name = "zh-Hant"; path = "zh-Hant.lproj/about.rtfd"; sourceTree = ""; }; + 52CD4C9120A088590061A5D6 /* MMChatsTableCellView+hook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MMChatsTableCellView+hook.h"; sourceTree = ""; }; + 52CD4C9220A088590061A5D6 /* WeChat+hook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WeChat+hook.h"; sourceTree = ""; }; + 52CD4C9320A088590061A5D6 /* MMStickerMessageCellView+hook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MMStickerMessageCellView+hook.h"; sourceTree = ""; }; + 52CD4C9420A088590061A5D6 /* MMStickerMessageCellView+hook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MMStickerMessageCellView+hook.m"; sourceTree = ""; }; + 52CD4C9520A088590061A5D6 /* WeChat+hook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WeChat+hook.m"; sourceTree = ""; }; + 52CD4C9620A088590061A5D6 /* MMChatsTableCellView+hook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MMChatsTableCellView+hook.m"; sourceTree = ""; }; + 52DA3E0A2094790900C618BB /* TKDownloadWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKDownloadWindowController.h; sourceTree = ""; }; + 52DA3E0B2094790900C618BB /* TKDownloadWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKDownloadWindowController.m; sourceTree = ""; }; + 52DA3E0C2094790900C618BB /* TKDownloadWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TKDownloadWindowController.xib; sourceTree = ""; }; + 52EA235720862D19008E6329 /* TKHTTPManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TKHTTPManager.h; sourceTree = ""; }; + 52EA235820862D19008E6329 /* TKHTTPManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TKHTTPManager.m; sourceTree = ""; }; + 888B2791FA0BBCC192BADA47 /* Pods-WeChatPlugin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WeChatPlugin.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WeChatPlugin/Pods-WeChatPlugin.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -111,12 +199,41 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 581E98663A5F0E6327516AA8 /* libPods-WeChatPlugin.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 13EC3A000F46808B50A62C6F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 17F7A08DC0E3A0626801414D /* libPods-WeChatPlugin.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3C138513A2C7760B47317A95 /* Pods */ = { + isa = PBXGroup; + children = ( + 888B2791FA0BBCC192BADA47 /* Pods-WeChatPlugin.debug.xcconfig */, + 13B308B4A92CE38341762A48 /* Pods-WeChatPlugin.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 520AE6F9208F646200BADE47 /* Utils */ = { + isa = PBXGroup; + children = ( + 52B5CF021F3B4631000D9DD9 /* TKHelper.h */, + 52B5CF031F3B4631000D9DD9 /* TKHelper.m */, + 52810B6921E8FCF500861FC3 /* TKUtility.h */, + 52810B6A21E8FCF500861FC3 /* TKUtility.m */, + ); + path = Utils; + sourceTree = ""; + }; 522547CC1F4AE5A700226A2A /* Category */ = { isa = PBXGroup; children = ( @@ -126,6 +243,16 @@ 5228EAB91F70B59500D808CF /* NSButton+Action.m */, 523848A91F70E73500771BA3 /* NSTextField+Action.h */, 523848AA1F70E73500771BA3 /* NSTextField+Action.m */, + 52206B6820836A230010C232 /* NSMenu+Action.h */, + 52206B6920836A230010C232 /* NSMenu+Action.m */, + 527D017120903C1B007155C9 /* NSMenuItem+Action.h */, + 527D017220903C1B007155C9 /* NSMenuItem+Action.m */, + 52176DD7209809CE0035FA50 /* NSString+Action.h */, + 52176DD8209809CE0035FA50 /* NSString+Action.m */, + 52CD4C56209C5CA10061A5D6 /* NSWindowController+Action.h */, + 52CD4C57209C5CA10061A5D6 /* NSWindowController+Action.m */, + 5299B2AE21087C2B004810D2 /* NSDate+Action.h */, + 5299B2AF21087C2B004810D2 /* NSDate+Action.m */, ); path = Category; sourceTree = ""; @@ -152,40 +279,40 @@ children = ( 522547DB1F4C312A00226A2A /* TKRemoteControlWindowController.h */, 522547DC1F4C312A00226A2A /* TKRemoteControlWindowController.m */, - 522547DD1F4C312A00226A2A /* TKRemoteControlWindowController.xib */, + 521C49C520820662003902E7 /* TKRemoteControlWindowController.xib */, ); path = RemoteControl; sourceTree = ""; }; - 526F4D781F4AAADA00E46004 /* Common */ = { + 5268C514209199690090BE40 /* Download */ = { isa = PBXGroup; children = ( - 522547D11F4AE5AE00226A2A /* View */, - 522547CC1F4AE5A700226A2A /* Category */, - 526F4D791F4AAADA00E46004 /* Color.h */, - 526F4D7C1F4AAADA00E46004 /* TKPrefixHeader.pch */, + 52DA3E0A2094790900C618BB /* TKDownloadWindowController.h */, + 52DA3E0B2094790900C618BB /* TKDownloadWindowController.m */, + 52DA3E0C2094790900C618BB /* TKDownloadWindowController.xib */, ); - path = Common; + path = Download; sourceTree = ""; }; - 526F4D851F4AAC3800E46004 /* AutoReply */ = { + 526A266F2081A8DC005B3E3C /* Macro */ = { isa = PBXGroup; children = ( - 526F4D861F4AAC3800E46004 /* TKAutoReplyContentView.h */, - 526F4D871F4AAC3800E46004 /* TKAutoReplyContentView.m */, - 526F4D8F1F4AAE6F00E46004 /* TKAutoReplyCell.h */, - 526F4D901F4AAE6F00E46004 /* TKAutoReplyCell.m */, + 526F4D791F4AAADA00E46004 /* ColorConstant.h */, + 526A26702081AC03005B3E3C /* DefineConstant.h */, + 520AE6EF208E231F00BADE47 /* NotifyConstant.h */, ); - path = AutoReply; + path = Macro; sourceTree = ""; }; - 526F4D881F4AAC3800E46004 /* RemoteControl */ = { + 526F4D781F4AAADA00E46004 /* Common */ = { isa = PBXGroup; children = ( - 526F4D891F4AAC3800E46004 /* TKRemoteControlCell.h */, - 526F4D8A1F4AAC3800E46004 /* TKRemoteControlCell.m */, + 526A266F2081A8DC005B3E3C /* Macro */, + 522547D11F4AE5AE00226A2A /* View */, + 522547CC1F4AE5A700226A2A /* Category */, + 526F4D7C1F4AAADA00E46004 /* TKPrefixHeader.pch */, ); - path = RemoteControl; + path = Common; sourceTree = ""; }; 527E7F5F2018711800358D26 /* Vendor */ = { @@ -202,6 +329,8 @@ children = ( 528B4F941EA7383800BC6A89 /* WeChatPlugin */, 528B4F931EA7383800BC6A89 /* Products */, + 3C138513A2C7760B47317A95 /* Pods */, + 13EC3A000F46808B50A62C6F /* Frameworks */, ); sourceTree = ""; }; @@ -226,10 +355,11 @@ isa = PBXGroup; children = ( 528B4FAA1EA7386D00BC6A89 /* main.mm */, + 52CD4C8D20A07D420061A5D6 /* about.rtfd */, 528B4F951EA7383800BC6A89 /* WeChatPlugin.h */, 528B4F961EA7383800BC6A89 /* Info.plist */, - 52B5CEF01F3B4623000D9DD9 /* TKRemoteControlCommands.plist */, 52B5CEF11F3B4623000D9DD9 /* TKRemoteControlScript.scpt */, + 521D75FB2080E3670093C820 /* Localizable.strings */, ); name = "Supporting Files"; sourceTree = ""; @@ -237,48 +367,29 @@ 52B5CEF41F3B4631000D9DD9 /* Sources */ = { isa = PBXGroup; children = ( + 52CD4C9020A088590061A5D6 /* Hook */, + 52CD4C75209ED2160061A5D6 /* Views */, 527E7F5F2018711800358D26 /* Vendor */, 526F4D781F4AAADA00E46004 /* Common */, - 52B5CEF51F3B4631000D9DD9 /* Category */, 52B5CEF81F3B4631000D9DD9 /* Config */, - 52B5CEFB1F3B4631000D9DD9 /* Controllers */, 52B5CEFE1F3B4631000D9DD9 /* Models */, - 52B5CF011F3B4631000D9DD9 /* Utils */, - 52B5CF061F3B4631000D9DD9 /* Views */, + 520AE6F9208F646200BADE47 /* Utils */, + 52B5CF011F3B4631000D9DD9 /* Managers */, 52B5CF091F3B4631000D9DD9 /* WindowControllers */, ); path = Sources; sourceTree = ""; }; - 52B5CEF51F3B4631000D9DD9 /* Category */ = { - isa = PBXGroup; - children = ( - 52B5CEF61F3B4631000D9DD9 /* WeChat+hook.h */, - 52B5CEF71F3B4631000D9DD9 /* WeChat+hook.m */, - 52475C2C1F6B993E00760E3E /* MMChatsTableCellView+hook.h */, - 52475C2D1F6B993E00760E3E /* MMChatsTableCellView+hook.m */, - ); - path = Category; - sourceTree = ""; - }; 52B5CEF81F3B4631000D9DD9 /* Config */ = { isa = PBXGroup; children = ( 52B5CEF91F3B4631000D9DD9 /* TKWeChatPluginConfig.h */, 52B5CEFA1F3B4631000D9DD9 /* TKWeChatPluginConfig.m */, + 5239B393241CAFDD00A471B4 /* TKConstants.h */, ); path = Config; sourceTree = ""; }; - 52B5CEFB1F3B4631000D9DD9 /* Controllers */ = { - isa = PBXGroup; - children = ( - 52B5CEFC1F3B4631000D9DD9 /* TKRemoteControlController.h */, - 52B5CEFD1F3B4631000D9DD9 /* TKRemoteControlController.m */, - ); - path = Controllers; - sourceTree = ""; - }; 52B5CEFE1F3B4631000D9DD9 /* Models */ = { isa = PBXGroup; children = ( @@ -294,33 +405,93 @@ path = Models; sourceTree = ""; }; - 52B5CF011F3B4631000D9DD9 /* Utils */ = { + 52B5CF011F3B4631000D9DD9 /* Managers */ = { isa = PBXGroup; children = ( - 52B5CF021F3B4631000D9DD9 /* TKHelper.h */, - 52B5CF031F3B4631000D9DD9 /* TKHelper.m */, - 52B5CF041F3B4631000D9DD9 /* XMLReader.h */, - 52B5CF051F3B4631000D9DD9 /* XMLReader.m */, + 5226D5C82040FC3E0013C048 /* TKVersionManager.h */, + 5226D5C92040FC3E0013C048 /* TKVersionManager.m */, + 520F2007205E1DF900A36B1E /* TKWebServerManager.h */, + 520F2008205E1DF900A36B1E /* TKWebServerManager.m */, + 52EA235720862D19008E6329 /* TKHTTPManager.h */, + 52EA235820862D19008E6329 /* TKHTTPManager.m */, + 520AE6E6208E1DA300BADE47 /* TKMessageManager.h */, + 520AE6E7208E1DA300BADE47 /* TKMessageManager.m */, + 520AE6F1208F62EF00BADE47 /* TKAssistantMenuManager.h */, + 520AE6F2208F62EF00BADE47 /* TKAssistantMenuManager.m */, + 520AE6F5208F632700BADE47 /* TKRemoteControlManager.h */, + 520AE6F6208F632700BADE47 /* TKRemoteControlManager.m */, + 52B5CEF01F3B4623000D9DD9 /* TKRemoteControlCommands.plist */, + 529950602113DAF10008BEE3 /* TKCacheManager.h */, + 529950612113DAF10008BEE3 /* TKCacheManager.m */, + 5223270E223922610016D3F7 /* TKEmoticonManager.h */, + 5223270F223922610016D3F7 /* TKEmoticonManager.m */, ); - path = Utils; + path = Managers; + sourceTree = ""; + }; + 52B5CF091F3B4631000D9DD9 /* WindowControllers */ = { + isa = PBXGroup; + children = ( + 52CD4C5A209CA0380061A5D6 /* About */, + 5268C514209199690090BE40 /* Download */, + 522547D61F4C312A00226A2A /* AutoReply */, + 522547DA1F4C312A00226A2A /* RemoteControl */, + ); + path = WindowControllers; sourceTree = ""; }; - 52B5CF061F3B4631000D9DD9 /* Views */ = { + 52CD4C5A209CA0380061A5D6 /* About */ = { isa = PBXGroup; children = ( - 526F4D851F4AAC3800E46004 /* AutoReply */, - 526F4D881F4AAC3800E46004 /* RemoteControl */, + 52CD4C5B209CA0510061A5D6 /* TKAboutWindowController.h */, + 52CD4C5C209CA0510061A5D6 /* TKAboutWindowController.m */, + 52CD4C8620A01CDC0061A5D6 /* TKAboutWindowController.xib */, + ); + path = About; + sourceTree = ""; + }; + 52CD4C75209ED2160061A5D6 /* Views */ = { + isa = PBXGroup; + children = ( + 52CD4C76209ED2160061A5D6 /* AutoReply */, + 52CD4C77209ED2160061A5D6 /* RemoteControl */, ); path = Views; sourceTree = ""; }; - 52B5CF091F3B4631000D9DD9 /* WindowControllers */ = { + 52CD4C76209ED2160061A5D6 /* AutoReply */ = { isa = PBXGroup; children = ( - 522547D61F4C312A00226A2A /* AutoReply */, - 522547DA1F4C312A00226A2A /* RemoteControl */, + 52CD4C78209ED22F0061A5D6 /* TKAutoReplyCell.h */, + 52CD4C7B209ED2300061A5D6 /* TKAutoReplyCell.m */, + 52CD4C79209ED2300061A5D6 /* TKAutoReplyContentView.h */, + 52CD4C7A209ED2300061A5D6 /* TKAutoReplyContentView.m */, ); - path = WindowControllers; + path = AutoReply; + sourceTree = ""; + }; + 52CD4C77209ED2160061A5D6 /* RemoteControl */ = { + isa = PBXGroup; + children = ( + 52CD4C81209ED23B0061A5D6 /* TKRemoteControlCell.h */, + 52CD4C80209ED23B0061A5D6 /* TKRemoteControlCell.m */, + ); + path = RemoteControl; + sourceTree = ""; + }; + 52CD4C9020A088590061A5D6 /* Hook */ = { + isa = PBXGroup; + children = ( + 52CD4C9220A088590061A5D6 /* WeChat+hook.h */, + 52CD4C9520A088590061A5D6 /* WeChat+hook.m */, + 52CD4C9120A088590061A5D6 /* MMChatsTableCellView+hook.h */, + 52CD4C9620A088590061A5D6 /* MMChatsTableCellView+hook.m */, + 52CD4C9320A088590061A5D6 /* MMStickerMessageCellView+hook.h */, + 52CD4C9420A088590061A5D6 /* MMStickerMessageCellView+hook.m */, + 522327122239258D0016D3F7 /* MMStickerPickerCell+hook.h */, + 522327132239258D0016D3F7 /* MMStickerPickerCell+hook.m */, + ); + path = Hook; sourceTree = ""; }; /* End PBXGroup section */ @@ -330,27 +501,44 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 522327142239258D0016D3F7 /* MMStickerPickerCell+hook.h in Headers */, 522547DE1F4C312A00226A2A /* TKAutoReplyWindowController.h in Headers */, 5228EABA1F70B59500D808CF /* NSButton+Action.h in Headers */, - 526F4D7D1F4AAADA00E46004 /* Color.h in Headers */, + 526F4D7D1F4AAADA00E46004 /* ColorConstant.h in Headers */, 527E7F632018711800358D26 /* fishhook.h in Headers */, 528B4F971EA7383800BC6A89 /* WeChatPlugin.h in Headers */, 526F4D801F4AAADA00E46004 /* TKPrefixHeader.pch in Headers */, + 52EA235920862D19008E6329 /* TKHTTPManager.h in Headers */, 529CDDFE1F6E6A060056DC1A /* TKBaseModel.h in Headers */, + 52CD4C58209C5CA10061A5D6 /* NSWindowController+Action.h in Headers */, + 5299B2B021087C2B004810D2 /* NSDate+Action.h in Headers */, 52B5CF1A1F3B4631000D9DD9 /* TKHelper.h in Headers */, - 52B5CF1C1F3B4631000D9DD9 /* XMLReader.h in Headers */, - 52B5CF161F3B4631000D9DD9 /* TKRemoteControlController.h in Headers */, + 52CD4C83209ED23B0061A5D6 /* TKRemoteControlCell.h in Headers */, + 527D017320903C1B007155C9 /* NSMenuItem+Action.h in Headers */, 523848AB1F70E73500771BA3 /* NSTextField+Action.h in Headers */, - 52B5CF121F3B4631000D9DD9 /* WeChat+hook.h in Headers */, + 52CD4C7C209ED2300061A5D6 /* TKAutoReplyCell.h in Headers */, + 52CD4C9820A0885A0061A5D6 /* WeChat+hook.h in Headers */, + 52CD4C9720A0885A0061A5D6 /* MMChatsTableCellView+hook.h in Headers */, + 52DA3E0D2094790900C618BB /* TKDownloadWindowController.h in Headers */, 52475C321F6BA43800760E3E /* TKIgnoreSessonModel.h in Headers */, - 526F4D8D1F4AAC3800E46004 /* TKRemoteControlCell.h in Headers */, + 52810B6B21E8FCF500861FC3 /* TKUtility.h in Headers */, + 52206B6A20836A230010C232 /* NSMenu+Action.h in Headers */, 52B5CF181F3B4631000D9DD9 /* TKRemoteControlModel.h in Headers */, + 52CD4C7D209ED2300061A5D6 /* TKAutoReplyContentView.h in Headers */, + 5226D5CA2040FC3E0013C048 /* TKVersionManager.h in Headers */, + 520F2009205E1DF900A36B1E /* TKWebServerManager.h in Headers */, + 520AE6F7208F632700BADE47 /* TKRemoteControlManager.h in Headers */, 522547CF1F4AE5A700226A2A /* NSView+Action.h in Headers */, - 526F4D911F4AAE6F00E46004 /* TKAutoReplyCell.h in Headers */, - 52475C2E1F6B993E00760E3E /* MMChatsTableCellView+hook.h in Headers */, - 526F4D8B1F4AAC3800E46004 /* TKAutoReplyContentView.h in Headers */, + 52232710223922610016D3F7 /* TKEmoticonManager.h in Headers */, + 520AE6F0208E231F00BADE47 /* NotifyConstant.h in Headers */, + 529950622113DAF10008BEE3 /* TKCacheManager.h in Headers */, + 52CD4C5E209CA0510061A5D6 /* TKAboutWindowController.h in Headers */, 522547E11F4C312A00226A2A /* TKRemoteControlWindowController.h in Headers */, + 520AE6F3208F62EF00BADE47 /* TKAssistantMenuManager.h in Headers */, 526F4D831F4AAC1900E46004 /* TKAutoReplyModel.h in Headers */, + 520AE6E8208E1DA300BADE47 /* TKMessageManager.h in Headers */, + 52CD4C9920A0885A0061A5D6 /* MMStickerMessageCellView+hook.h in Headers */, + 52176DD9209809CE0035FA50 /* NSString+Action.h in Headers */, 52B5CF141F3B4631000D9DD9 /* TKWeChatPluginConfig.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -362,11 +550,13 @@ isa = PBXNativeTarget; buildConfigurationList = 528B4F9A1EA7383800BC6A89 /* Build configuration list for PBXNativeTarget "WeChatPlugin" */; buildPhases = ( + A23204925F0A37A0EBE14B92 /* [CP] Check Pods Manifest.lock */, 528B4F8D1EA7383800BC6A89 /* Sources */, 528B4F8E1EA7383800BC6A89 /* Frameworks */, 528B4F8F1EA7383800BC6A89 /* Headers */, 528B4F901EA7383800BC6A89 /* Resources */, 528B4FB51EA738B100BC6A89 /* ShellScript */, + 165746E0A28B760DEA538E0D /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -383,7 +573,7 @@ 528B4F891EA7383800BC6A89 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0920; + LastUpgradeCheck = 0930; ORGANIZATIONNAME = tk; TargetAttributes = { 528B4F911EA7383800BC6A89 = { @@ -397,7 +587,11 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, + "zh-Hans", + "zh-Hant", + Base, ); mainGroup = 528B4F881EA7383800BC6A89; productRefGroup = 528B4F931EA7383800BC6A89 /* Products */; @@ -414,16 +608,35 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 52DA3E0F2094790900C618BB /* TKDownloadWindowController.xib in Resources */, + 521D75F92080E3670093C820 /* Localizable.strings in Resources */, 522547E01F4C312A00226A2A /* TKAutoReplyWindowController.xib in Resources */, 52B5CEF21F3B4623000D9DD9 /* TKRemoteControlCommands.plist in Resources */, + 52CD4C8420A01CDC0061A5D6 /* TKAboutWindowController.xib in Resources */, 52B5CEF31F3B4623000D9DD9 /* TKRemoteControlScript.scpt in Resources */, - 522547E31F4C312A00226A2A /* TKRemoteControlWindowController.xib in Resources */, + 52CD4C8B20A07D420061A5D6 /* about.rtfd in Resources */, + 521C49C320820662003902E7 /* TKRemoteControlWindowController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 165746E0A28B760DEA538E0D /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeChatPlugin/Pods-WeChatPlugin-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 528B4FB51EA738B100BC6A89 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -435,7 +648,25 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "#!/bin/bash\napp_name=\"WeChat\"\nframework_name=\"WeChatPlugin\"\napp_bundle_path=\"/Applications/${app_name}.app/Contents/MacOS\"\napp_executable_path=\"${app_bundle_path}/${app_name}\"\napp_executable_backup_path=\"${app_executable_path}_backup\"\nframework_path=\"${app_bundle_path}/${framework_name}.framework\"\n# 备份WeChat原始可执行文件\nif [ ! -f \"$app_executable_backup_path\" ]\nthen\ncp \"$app_executable_path\" \"$app_executable_backup_path\"\nfi\n\nrm -rf \"./Other/Products/Debug/${framework_name}.framework\"\ncp -r \"${BUILT_PRODUCTS_DIR}/${framework_name}.framework\" \"./Other/Products/Debug/${framework_name}.framework\"\ncp -r \"${BUILT_PRODUCTS_DIR}/${framework_name}.framework\" ${app_bundle_path}\n./Other/insert_dylib --all-yes \"${framework_path}/${framework_name}\" \"$app_executable_backup_path\" \"$app_executable_path\""; + shellScript = "#!/bin/bash\napp_name=\"WeChat\"\nframework_name=\"WeChatPlugin\"\napp_bundle_path=\"/Applications/${app_name}.app/Contents/MacOS\"\napp_executable_path=\"${app_bundle_path}/${app_name}\"\napp_executable_backup_path=\"${app_executable_path}_backup\"\nframework_path=\"${app_bundle_path}/${framework_name}.framework\"\n# 备份WeChat原始可执行文件\nif [ ! -f \"$app_executable_backup_path\" ]\nthen\ncp \"$app_executable_path\" \"$app_executable_backup_path\"\nfi\n\nrm -rf \"./Other/Products/Debug/${framework_name}.framework\"\ncp -r \"${BUILT_PRODUCTS_DIR}/${framework_name}.framework\" \"./Other/Products/Debug/${framework_name}.framework\"\n\ncp -r \"${BUILT_PRODUCTS_DIR}/${framework_name}.framework\" ${app_bundle_path}\n./Other/insert_dylib --all-yes \"${framework_path}/${framework_name}\" \"$app_executable_backup_path\" \"$app_executable_path\"\n"; + }; + A23204925F0A37A0EBE14B92 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-WeChatPlugin-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -444,36 +675,96 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 52475C2F1F6B993E00760E3E /* MMChatsTableCellView+hook.m in Sources */, - 526F4D921F4AAE6F00E46004 /* TKAutoReplyCell.m in Sources */, + 52CD4C5F209CA0510061A5D6 /* TKAboutWindowController.m in Sources */, + 520F200A205E1DF900A36B1E /* TKWebServerManager.m in Sources */, + 52CD4C9C20A0885A0061A5D6 /* MMChatsTableCellView+hook.m in Sources */, 52B5CF151F3B4631000D9DD9 /* TKWeChatPluginConfig.m in Sources */, + 52CD4C7F209ED2300061A5D6 /* TKAutoReplyCell.m in Sources */, + 52CD4C9B20A0885A0061A5D6 /* WeChat+hook.m in Sources */, 522547E21F4C312A00226A2A /* TKRemoteControlWindowController.m in Sources */, - 52B5CF131F3B4631000D9DD9 /* WeChat+hook.m in Sources */, 529CDDFF1F6E6A060056DC1A /* TKBaseModel.m in Sources */, + 52DA3E0E2094790900C618BB /* TKDownloadWindowController.m in Sources */, 527E7F622018711800358D26 /* fishhook.c in Sources */, + 52176DDA209809CE0035FA50 /* NSString+Action.m in Sources */, + 529950632113DAF10008BEE3 /* TKCacheManager.m in Sources */, + 52EA235A20862D19008E6329 /* TKHTTPManager.m in Sources */, + 52810B6C21E8FCF500861FC3 /* TKUtility.m in Sources */, + 5299B2B121087C2B004810D2 /* NSDate+Action.m in Sources */, + 527D017420903C1B007155C9 /* NSMenuItem+Action.m in Sources */, 52B5CF1B1F3B4631000D9DD9 /* TKHelper.m in Sources */, - 52B5CF171F3B4631000D9DD9 /* TKRemoteControlController.m in Sources */, + 52206B6B20836A230010C232 /* NSMenu+Action.m in Sources */, + 520AE6F8208F632700BADE47 /* TKRemoteControlManager.m in Sources */, + 520AE6F4208F62EF00BADE47 /* TKAssistantMenuManager.m in Sources */, 522547D01F4AE5A700226A2A /* NSView+Action.m in Sources */, 523848AC1F70E73500771BA3 /* NSTextField+Action.m in Sources */, - 526F4D8E1F4AAC3800E46004 /* TKRemoteControlCell.m in Sources */, 526F4D841F4AAC1900E46004 /* TKAutoReplyModel.m in Sources */, - 526F4D8C1F4AAC3800E46004 /* TKAutoReplyContentView.m in Sources */, 522547DF1F4C312A00226A2A /* TKAutoReplyWindowController.m in Sources */, + 5226D5CB2040FC3E0013C048 /* TKVersionManager.m in Sources */, + 522327152239258D0016D3F7 /* MMStickerPickerCell+hook.m in Sources */, + 52CD4C7E209ED2300061A5D6 /* TKAutoReplyContentView.m in Sources */, + 520AE6E9208E1DA300BADE47 /* TKMessageManager.m in Sources */, 52B5CF191F3B4631000D9DD9 /* TKRemoteControlModel.m in Sources */, 5228EABB1F70B59500D808CF /* NSButton+Action.m in Sources */, + 52CD4C59209C5CA10061A5D6 /* NSWindowController+Action.m in Sources */, + 52CD4C82209ED23B0061A5D6 /* TKRemoteControlCell.m in Sources */, + 52232711223922610016D3F7 /* TKEmoticonManager.m in Sources */, 528B4FB41EA7386D00BC6A89 /* main.mm in Sources */, - 52B5CF1D1F3B4631000D9DD9 /* XMLReader.m in Sources */, + 52CD4C9A20A0885A0061A5D6 /* MMStickerMessageCellView+hook.m in Sources */, 52475C331F6BA43800760E3E /* TKIgnoreSessonModel.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXVariantGroup section */ + 521C49C520820662003902E7 /* TKRemoteControlWindowController.xib */ = { + isa = PBXVariantGroup; + children = ( + 521C49C620820663003902E7 /* zh-Hans */, + 52CD4C8920A07B8E0061A5D6 /* zh-Hant */, + 52810B6E21E90B2500861FC3 /* Base */, + ); + name = TKRemoteControlWindowController.xib; + sourceTree = ""; + }; + 521D75FB2080E3670093C820 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 521D75FA2080E3670093C820 /* en */, + 521D75FC2080E3780093C820 /* zh-Hans */, + 52CD4C8A20A07B8E0061A5D6 /* zh-Hant */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + 52CD4C8620A01CDC0061A5D6 /* TKAboutWindowController.xib */ = { + isa = PBXVariantGroup; + children = ( + 52CD4C8520A01CDC0061A5D6 /* en */, + 52CD4C8820A07B8E0061A5D6 /* zh-Hant */, + 52810B6D21E90B2400861FC3 /* Base */, + ); + name = TKAboutWindowController.xib; + sourceTree = ""; + }; + 52CD4C8D20A07D420061A5D6 /* about.rtfd */ = { + isa = PBXVariantGroup; + children = ( + 52CD4C8C20A07D420061A5D6 /* en */, + 52CD4C8E20A07D450061A5D6 /* zh-Hans */, + 52CD4C8F20A07D460061A5D6 /* zh-Hant */, + ); + name = about.rtfd; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ 528B4F981EA7383800BC6A89 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -483,6 +774,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -490,6 +782,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -530,6 +823,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -539,6 +833,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -546,6 +841,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -577,6 +873,7 @@ }; 528B4F9B1EA7383800BC6A89 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 888B2791FA0BBCC192BADA47 /* Pods-WeChatPlugin.debug.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; @@ -590,6 +887,8 @@ INFOPLIST_FILE = WeChatPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 1.7.5; + ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = tk.WeChatPlugin; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -598,6 +897,7 @@ }; 528B4F9C1EA7383800BC6A89 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 13B308B4A92CE38341762A48 /* Pods-WeChatPlugin.release.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; @@ -611,6 +911,8 @@ INFOPLIST_FILE = WeChatPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 1.7.5; + ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = tk.WeChatPlugin; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; diff --git a/WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/TK.xcuserdatad/UserInterfaceState.xcuserstate b/WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/TK.xcuserdatad/UserInterfaceState.xcuserstate index d4a613bf..53118705 100644 Binary files a/WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/TK.xcuserdatad/UserInterfaceState.xcuserstate and b/WeChatPlugin.xcodeproj/project.xcworkspace/xcuserdata/TK.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/WeChatPlugin.xcodeproj/xcuserdata/TK.xcuserdatad/xcschemes/WeChatPlugin.xcscheme b/WeChatPlugin.xcodeproj/xcuserdata/TK.xcuserdatad/xcschemes/WeChatPlugin.xcscheme index dd72f5d7..4bcce771 100644 --- a/WeChatPlugin.xcodeproj/xcuserdata/TK.xcuserdatad/xcschemes/WeChatPlugin.xcscheme +++ b/WeChatPlugin.xcodeproj/xcuserdata/TK.xcuserdatad/xcschemes/WeChatPlugin.xcscheme @@ -1,6 +1,6 @@ @@ -37,7 +36,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/WeChatPlugin.xcworkspace/contents.xcworkspacedata b/WeChatPlugin.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..89bba37f --- /dev/null +++ b/WeChatPlugin.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/WeChatPlugin.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/WeChatPlugin.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/WeChatPlugin.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/WeChatPlugin.xcworkspace/xcuserdata/TK.xcuserdatad/IDEFindNavigatorScopes.plist b/WeChatPlugin.xcworkspace/xcuserdata/TK.xcuserdatad/IDEFindNavigatorScopes.plist new file mode 100644 index 00000000..5dd5da85 --- /dev/null +++ b/WeChatPlugin.xcworkspace/xcuserdata/TK.xcuserdatad/IDEFindNavigatorScopes.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/WeChatPlugin.xcworkspace/xcuserdata/TK.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/WeChatPlugin.xcworkspace/xcuserdata/TK.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 00000000..70a31ee7 --- /dev/null +++ b/WeChatPlugin.xcworkspace/xcuserdata/TK.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatPlugin/Info.plist b/WeChatPlugin/Info.plist index 1ff89961..7a623971 100644 --- a/WeChatPlugin/Info.plist +++ b/WeChatPlugin/Info.plist @@ -15,12 +15,16 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + $(MARKETING_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) NSHumanReadableCopyright Copyright © 2017年 tk. All rights reserved. NSPrincipalClass + showUpdateWindow + + versionInfo + v1.7.5(2019-01-13):\n👉🏻 适配微信 Version. 2.3.22\n👉🏼 菜单栏新增是否允许微信启动时检测更新(非AppStore版本)\n👉🏽 优化 XML 解析\n\n\n\nv1.7.3 (2018-10-22):\n👉🏻 适配微信 Version. 2.3.19\n👉🏼 修复安全漏洞(请务必更新,若有安装QQ插件也需要更新)\n👉🏽 菜单栏-关于小助手-新增 alfred 开关(若不使用 aflred 可关闭) \n\nv1.7.1 (2018-07-24):\n👉🏻 适配微信 Version. 2.3.17\n👉🏼 新增 alfred 搜索最近聊天列表\n👉🏽 新增 alfred 查看用户聊天记录\n (需更新wechat-alfred-workflow)\n\nv1.7 (2018-05-12):\n👉🏻 新增不同账户设置不同的自动回复&远程控制\n👉🏼 自动回复新增总开关&指定联系人\n👉🏽 远程控制新增控制小助手配置\n👉🏾 新增一键已读\n👉 新增一键清除空回话\n👉🏻 新增国际化(支持英、简、繁)\n👉🏼 新增关于小助手\n👉🏽 新增在线更新小助手 \n👉🏾 去除微信url转链处理(从此直接打开抖音链接🌝 \n👉🏿 修复无法免认证登录&多开等bug \n diff --git a/WeChatPlugin/Sources/Category/WeChat+hook.m b/WeChatPlugin/Sources/Category/WeChat+hook.m deleted file mode 100644 index c5ceabd6..00000000 --- a/WeChatPlugin/Sources/Category/WeChat+hook.m +++ /dev/null @@ -1,507 +0,0 @@ -// -// WeChat+hook.m -// WeChatPlugin -// -// Created by TK on 2017/4/19. -// Copyright © 2017年 tk. All rights reserved. -// - -#import "WeChat+hook.h" -#import "WeChatPlugin.h" -#import "XMLReader.h" -#import "TKRemoteControlController.h" -#import "TKAutoReplyWindowController.h" -#import "TKRemoteControlWindowController.h" -#import "TKIgnoreSessonModel.h" -#import "fishhook.h" - -static char tkAutoReplyWindowControllerKey; // 自动回复窗口的关联 key -static char tkRemoteControlWindowControllerKey; // 远程控制窗口的关联 key - -@implementation NSObject (WeChatHook) - -+ (void)hookWeChat { - // 微信撤回消息 - tk_hookMethod(objc_getClass("MessageService"), @selector(onRevokeMsg:), [self class], @selector(hook_onRevokeMsg:)); - // 微信消息同步 - tk_hookMethod(objc_getClass("MessageService"), @selector(OnSyncBatchAddMsgs:isFirstSync:), [self class], @selector(hook_OnSyncBatchAddMsgs:isFirstSync:)); - // 微信多开 - tk_hookClassMethod(objc_getClass("CUtility"), @selector(HasWechatInstance), [self class], @selector(hook_HasWechatInstance)); - // 免认证登录 - tk_hookMethod(objc_getClass("MMLoginOneClickViewController"), @selector(onLoginButtonClicked:), [self class], @selector(hook_onLoginButtonClicked:)); - tk_hookMethod(objc_getClass("LogoutCGI"), @selector(sendLogoutCGIWithCompletion:), [self class], @selector(hook_sendLogoutCGIWithCompletion:)); - // 自动登录 - tk_hookMethod(objc_getClass("MMLoginOneClickViewController"), @selector(viewWillAppear), [self class], @selector(hook_viewWillAppear)); - // 置底 - tk_hookMethod(objc_getClass("MMSessionMgr"), @selector(sortSessions), [self class], @selector(hook_sortSessions)); - // 快捷回复 - tk_hookMethod(objc_getClass("_NSConcreteUserNotificationCenter"), @selector(deliverNotification:), [self class], @selector(hook_deliverNotification:)); - 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:)); - - // 替换沙盒路径 - rebind_symbols((struct rebinding[2]) { - { "NSSearchPathForDirectoriesInDomains", swizzled_NSSearchPathForDirectoriesInDomains, (void *)&original_NSSearchPathForDirectoriesInDomains }, - { "NSHomeDirectory", swizzled_NSHomeDirectory, (void *)&original_NSHomeDirectory } - }, 2); - - [self setup]; -} - -+ (void)setup { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [self addAssistantMenuItem]; - - BOOL onTop = [[TKWeChatPluginConfig sharedConfig] onTop]; - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - wechat.mainWindowController.window.level = onTop == NSControlStateValueOn ? NSStatusWindowLevel : NSNormalWindowLevel; - }); -} - -/** - 菜单栏添加 menuItem - */ -+ (void)addAssistantMenuItem { - // 消息防撤回 - NSMenuItem *preventRevokeItem = [[NSMenuItem alloc] initWithTitle:@"开启消息防撤回" action:@selector(onPreventRevoke:) keyEquivalent:@"t"]; - preventRevokeItem.state = [[TKWeChatPluginConfig sharedConfig] preventRevokeEnable]; - // 自动回复 - NSMenuItem *autoReplyItem = [[NSMenuItem alloc] initWithTitle:@"自动回复设置" action:@selector(onAutoReply:) keyEquivalent:@"k"]; - // 登录新微信 - NSMenuItem *newWeChatItem = [[NSMenuItem alloc] initWithTitle:@"登录新微信" action:@selector(onNewWechatInstance:) keyEquivalent:@"N"]; - // 远程控制 - NSMenuItem *commandItem = [[NSMenuItem alloc] initWithTitle:@"远程控制Mac OS" action:@selector(onRemoteControl:) keyEquivalent:@"C"]; - // 微信窗口置顶 - NSMenuItem *onTopItem = [[NSMenuItem alloc] initWithTitle:@"微信窗口置顶" action:@selector(onWechatOnTopControl:) keyEquivalent:@"d"]; - onTopItem.state = [[TKWeChatPluginConfig sharedConfig] onTop]; - // 免认证登录 - NSMenuItem *autoAuthItem = [[NSMenuItem alloc] initWithTitle:@"免认证登录" action:@selector(onAutoAuthControl:) keyEquivalent:@"M"]; - autoAuthItem.state = [[TKWeChatPluginConfig sharedConfig] autoAuthEnable]; - - NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@"微信小助手"]; - [subMenu addItem:preventRevokeItem]; - [subMenu addItem:autoReplyItem]; - [subMenu addItem:commandItem]; - [subMenu addItem:newWeChatItem]; - [subMenu addItem:onTopItem]; - [subMenu addItem:autoAuthItem]; - - NSMenuItem *menuItem = [[NSMenuItem alloc] init]; - [menuItem setTitle:@"微信小助手"]; - [menuItem setSubmenu:subMenu]; - - [[[NSApplication sharedApplication] mainMenu] addItem:menuItem]; -} - -#pragma mark - menuItem 的点击事件 -/** - 菜单栏-微信小助手-消息防撤回 设置 - - @param item 消息防撤回的item - */ -- (void)onPreventRevoke:(NSMenuItem *)item { - item.state = !item.state; - [[TKWeChatPluginConfig sharedConfig] setPreventRevokeEnable:item.state]; -} - -/** - 菜单栏-微信小助手-自动回复 设置 - - @param item 自动回复设置的item - */ -- (void)onAutoReply:(NSMenuItem *)item { - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - TKAutoReplyWindowController *autoReplyWC = objc_getAssociatedObject(wechat, &tkAutoReplyWindowControllerKey); - - if (!autoReplyWC) { - autoReplyWC = [[TKAutoReplyWindowController alloc] initWithWindowNibName:@"TKAutoReplyWindowController"]; - objc_setAssociatedObject(wechat, &tkAutoReplyWindowControllerKey, autoReplyWC, OBJC_ASSOCIATION_RETAIN); - } - - [autoReplyWC showWindow:autoReplyWC]; - [autoReplyWC.window center]; - [autoReplyWC.window makeKeyWindow]; -} - -/** - 打开新的微信 - - @param item 登录新微信的item - */ -- (void)onNewWechatInstance:(NSMenuItem *)item { - [TKRemoteControlController executeShellCommand:@"open -n /Applications/WeChat.app"]; -} - -/** - 菜单栏-帮助-远程控制 MAC OS 设置 - - @param item 远程控制的item - */ -- (void)onRemoteControl:(NSMenuItem *)item { - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - TKRemoteControlWindowController *remoteControlWC = objc_getAssociatedObject(wechat, &tkRemoteControlWindowControllerKey); - - if (!remoteControlWC) { - remoteControlWC = [[TKRemoteControlWindowController alloc] initWithWindowNibName:@"TKRemoteControlWindowController"]; - objc_setAssociatedObject(wechat, &tkRemoteControlWindowControllerKey, remoteControlWC, OBJC_ASSOCIATION_RETAIN); - } - - [remoteControlWC showWindow:remoteControlWC]; - [remoteControlWC.window center]; - [remoteControlWC.window makeKeyWindow]; -} - -/** - 菜单栏-微信小助手-免认证登录 设置 - - @param item 免认证登录的 item - */ -- (void)onAutoAuthControl:(NSMenuItem *)item { - item.state = !item.state; - [[TKWeChatPluginConfig sharedConfig] setAutoAuthEnable:item.state]; -} - -/** - 菜单栏-微信小助手-微信窗口置顶 - - @param item 免认证登录的 item - */ -- (void)onWechatOnTopControl:(NSMenuItem *)item { - item.state = !item.state; - [[TKWeChatPluginConfig sharedConfig] setOnTop:item.state]; - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - wechat.mainWindowController.window.level = item.state == NSControlStateValueOn ? NSStatusWindowLevel : NSNormalWindowLevel; -} - -/** - 登录界面-自动登录 - - @param btn 自动登录按钮 - */ -- (void)selectAutoLogin:(NSButton *)btn { - [[TKWeChatPluginConfig sharedConfig] setAutoLoginEnable:btn.state]; -} - -#pragma mark - hook 微信方法 -/** - hook 微信是否已启动 - - */ -+ (BOOL)hook_HasWechatInstance { - return NO; -} - -/** - hook 微信撤回消息 - - */ -- (void)hook_onRevokeMsg:(id)msg { - if (![[TKWeChatPluginConfig sharedConfig] preventRevokeEnable]) { - [self hook_onRevokeMsg:msg]; - return; - } - if ([msg rangeOfString:@" 0) { - NSString *content = [revokeMsgData.msgContent substringFromIndex:range.location + range.length]; - newMsgContent = [NSString stringWithFormat:@"TK拦截到一条撤回消息:\n %@",content]; - } - } - } - MessageData *newMsgData = ({ - MessageData *msg = [[objc_getClass("MessageData") alloc] initWithMsgType:0x2710]; - [msg setFromUsrName:revokeMsgData.toUsrName]; - [msg setToUsrName:revokeMsgData.fromUsrName]; - [msg setMsgStatus:4]; - [msg setMsgContent:newMsgContent]; - [msg setMsgCreateTime:[revokeMsgData msgCreateTime]]; - // [msg setMesLocalID:[revokeMsgData mesLocalID]]; - - msg; - }); - - [msgService AddLocalMsg:session msgData:newMsgData]; - } - -} - -/** - hook 微信消息同步 - - */ -- (void)hook_OnSyncBatchAddMsgs:(NSArray *)msgs isFirstSync:(BOOL)arg2 { - [self hook_OnSyncBatchAddMsgs:msgs isFirstSync:arg2]; - - [msgs enumerateObjectsUsingBlock:^(AddMsg *addMsg, NSUInteger idx, BOOL * _Nonnull stop) { - NSDate *now = [NSDate date]; - NSTimeInterval nowSecond = now.timeIntervalSince1970; - if (nowSecond - addMsg.createTime > 180) { // 若是3分钟前的消息,则不进行自动回复与远程控制。 - return; - } - - [self autoReplyWithMsg:addMsg]; - - NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; - if ([addMsg.fromUserName.string isEqualToString:currentUserName] && - [addMsg.toUserName.string isEqualToString:currentUserName]) { - [self remoteControlWithMsg:addMsg]; - [self replySelfWithMsg:addMsg]; - } - }]; -} - -/** - hook 微信通知消息 - - */ - -- (id)hook_getNotificationContentWithMsgData:(MessageData *)arg1 { - [[TKWeChatPluginConfig sharedConfig] setCurrentUserName:arg1.toUsrName]; - return [self hook_getNotificationContentWithMsgData:arg1];; -} - -- (void)hook_deliverNotification:(NSUserNotification *)notification { - NSMutableDictionary *dict = [notification.userInfo mutableCopy]; - dict[@"currnetName"] = [[TKWeChatPluginConfig sharedConfig] currentUserName]; - notification.userInfo = dict; - notification.hasReplyButton = YES; - [self hook_deliverNotification:notification]; -} - -- (void)hook_userNotificationCenter:(id)notificationCenter didActivateNotification:(NSUserNotification *)notification { - NSString *chatName = notification.userInfo[@"ChatName"]; - if (chatName && notification.response.string) { - NSString *instanceUserName = [objc_getClass("CUtility") GetCurrentUserName]; - NSString *currentUserName = notification.userInfo[@"currnetName"]; - if ([instanceUserName isEqualToString:currentUserName]) { - MessageService *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; - [service SendTextMessage:currentUserName toUsrName:chatName msgText:notification.response.string atUserList:nil]; - } - } else { - [self hook_userNotificationCenter:notificationCenter didActivateNotification:notification]; - } -} - -/** - hook 自动登录 - - */ -- (void)hook_onLoginButtonClicked:(NSButton *)btn { - AccountService *accountService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("AccountService")]; - BOOL autoAuthEnable = [[TKWeChatPluginConfig sharedConfig] autoAuthEnable]; - if (autoAuthEnable && [accountService canAutoAuth]) { - [accountService AutoAuth]; - - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - MMLoginOneClickViewController *loginVC = wechat.mainWindowController.loginViewController.oneClickViewController; - loginVC.loginButton.hidden = YES; - //// [wechat.mainWindowController onAuthOK]; - loginVC.descriptionLabel.stringValue = @"TK正在为你免认证登录~"; - loginVC.descriptionLabel.textColor = TK_RGB(0x88, 0x88, 0x88); - loginVC.descriptionLabel.hidden = NO; - } else { - [self hook_onLoginButtonClicked:btn]; - } -} - -- (void)hook_sendLogoutCGIWithCompletion:(id)arg1 { - BOOL autoAuthEnable = [[TKWeChatPluginConfig sharedConfig] autoAuthEnable]; - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - if (autoAuthEnable && wechat.isAppTerminating) return; - - return [self hook_sendLogoutCGIWithCompletion:arg1]; -} - -- (void)hook_viewWillAppear { - [self hook_viewWillAppear]; - - NSButton *autoLoginButton = ({ - NSButton *btn = [NSButton tk_checkboxWithTitle:@"" target:self action:@selector(selectAutoLogin:)]; - btn.frame = NSMakeRect(110, 60, 80, 30); - NSMutableParagraphStyle *pghStyle = [[NSMutableParagraphStyle alloc] init]; - pghStyle.alignment = NSTextAlignmentCenter; - NSDictionary *dicAtt = @{NSForegroundColorAttributeName: kBG4, NSParagraphStyleAttributeName: pghStyle}; - btn.attributedTitle = [[NSAttributedString alloc] initWithString:@"自动登录" attributes:dicAtt]; - - btn; - }); - - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - MMLoginOneClickViewController *loginVC = wechat.mainWindowController.loginViewController.oneClickViewController; - [loginVC.view addSubview:autoLoginButton]; - - BOOL autoLogin = [[TKWeChatPluginConfig sharedConfig] autoLoginEnable]; - autoLoginButton.state = autoLogin; - - NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; - NSArray *instances = [NSRunningApplication runningApplicationsWithBundleIdentifier:bundleIdentifier]; - BOOL wechatHasRun = instances.count == 1; - - if (autoLogin && wechatHasRun) { - [loginVC onLoginButtonClicked:nil]; - } -} - -- (void)hook_sortSessions { - [self hook_sortSessions]; - - MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; - NSMutableArray *arrSession = sessionMgr.m_arrSession; - NSMutableArray *ignoreSessions = [[[TKWeChatPluginConfig sharedConfig] ignoreSessionModels] mutableCopy]; - - NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; - [ignoreSessions enumerateObjectsUsingBlock:^(TKIgnoreSessonModel *model, NSUInteger index, BOOL * _Nonnull stop) { - __block NSInteger ignoreIdx = -1; - [arrSession enumerateObjectsUsingBlock:^(MMSessionInfo *sessionInfo, NSUInteger idx, BOOL * _Nonnull stop) { - if ([model.userName isEqualToString:sessionInfo.m_nsUserName] && [model.selfContact isEqualToString:currentUserName]) { - ignoreIdx = idx; - *stop = YES; - } - }]; - - if (ignoreIdx != -1) { - MMSessionInfo *sessionInfo = arrSession[ignoreIdx]; - [arrSession removeObjectAtIndex:ignoreIdx]; - [arrSession addObject:sessionInfo]; - } - }]; - - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - [wechat.chatsViewController.tableView reloadData]; -} - -#pragma mark - Other -/** - 自动回复 - - @param addMsg 接收的消息 - */ -- (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]; - if (msgContact.m_uiFriendScene == 0 && ![addMsg.fromUserName.string containsString:@"@chatroom"]) { - // 该消息为公众号 - return; - } - MessageService *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; - - NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; - - NSArray *autoReplyModels = [[TKWeChatPluginConfig sharedConfig] autoReplyModels]; - [autoReplyModels enumerateObjectsUsingBlock:^(TKAutoReplyModel *model, NSUInteger idx, BOOL * _Nonnull stop) { - if (!model.enable) return; - if (!model.replyContent || model.replyContent.length == 0) return; - if ([addMsg.fromUserName.string containsString:@"@chatroom"] && !model.enableGroupReply) return; - if (![addMsg.fromUserName.string containsString:@"@chatroom"] && !model.enableSingleReply) return; - - NSString *msgContent = addMsg.content.string; - if ([addMsg.fromUserName.string containsString:@"@chatroom"]) { - NSRange range = [msgContent rangeOfString:@":\n"]; - if (range.length > 0) { - msgContent = [msgContent substringFromIndex:range.location + range.length]; - } - } - - NSArray *replyArray = [model.replyContent componentsSeparatedByString:@"|"]; - int index = arc4random() % replyArray.count; - NSString *randomReplyContent = replyArray[index]; - - if (model.enableRegex) { - NSString *regex = model.keyword; - NSError *error; - NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:&error]; - if (error) return; - NSInteger count = [regular numberOfMatchesInString:msgContent options:NSMatchingReportCompletion range:NSMakeRange(0, msgContent.length)]; - if (count > 0) { - [service SendTextMessage:currentUserName toUsrName:addMsg.fromUserName.string msgText:randomReplyContent atUserList:nil]; - } - } else { - NSArray * keyWordArray = [model.keyword componentsSeparatedByString:@"|"]; - [keyWordArray enumerateObjectsUsingBlock:^(NSString *keyword, NSUInteger idx, BOOL * _Nonnull stop) { - if ([keyword isEqualToString:@"*"] || [msgContent isEqualToString:keyword]) { - [service SendTextMessage:currentUserName toUsrName:addMsg.fromUserName.string msgText:randomReplyContent atUserList:nil]; - } - }]; - } - }]; -} - -/** - 远程控制 - - @param addMsg 接收的消息 - */ -- (void)remoteControlWithMsg:(AddMsg *)addMsg { - if (addMsg.msgType == 1 || addMsg.msgType == 3) { - [TKRemoteControlController executeRemoteControlCommandWithMsg:addMsg.content.string]; - } -} - -- (void)replySelfWithMsg:(AddMsg *)addMsg { - if (addMsg.msgType != 1 && addMsg.msgType != 3) return; - - if ([addMsg.content.string isEqualToString:@"获取指令"]) { - NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; - NSString *callBack = [TKRemoteControlController remoteControlCommandsString]; - MessageService *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; - [service SendTextMessage:currentUserName toUsrName:currentUserName msgText:callBack atUserList:nil]; - } -} - -#pragma mark - 替换 NSSearchPathForDirectoriesInDomains & NSHomeDirectory -static NSArray *(*original_NSSearchPathForDirectoriesInDomains)(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde); - -NSArray *swizzled_NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde) { - NSMutableArray *paths = [original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde) mutableCopy]; - NSString *sandBoxPath = [NSString stringWithFormat:@"%@/Library/Containers/com.tencent.xinWeChat/Data",original_NSHomeDirectory()]; - - [paths enumerateObjectsUsingBlock:^(NSString *filePath, NSUInteger idx, BOOL * _Nonnull stop) { - NSRange range = [filePath rangeOfString:original_NSHomeDirectory()]; - if (range.length > 0) { - NSMutableString *newFilePath = [filePath mutableCopy]; - [newFilePath replaceCharactersInRange:range withString:sandBoxPath]; - paths[idx] = newFilePath; - } - }]; - - return paths; -} - -static NSString *(*original_NSHomeDirectory)(void); - -NSString *swizzled_NSHomeDirectory(void) { - return [NSString stringWithFormat:@"%@/Library/Containers/com.tencent.xinWeChat/Data",original_NSHomeDirectory()]; -} - -@end diff --git a/WeChatPlugin/Sources/Common/Category/NSButton+Action.h b/WeChatPlugin/Sources/Common/Category/NSButton+Action.h index 341b1f11..24242752 100644 --- a/WeChatPlugin/Sources/Common/Category/NSButton+Action.h +++ b/WeChatPlugin/Sources/Common/Category/NSButton+Action.h @@ -9,6 +9,7 @@ #import @interface NSButton (Action) + + (instancetype)tk_buttonWithTitle:(NSString *)title target:(id)target action:(SEL)action; + (instancetype)tk_checkboxWithTitle:(NSString *)title target:(id)target action:(SEL)action; diff --git a/WeChatPlugin/Sources/Common/Category/NSButton+Action.m b/WeChatPlugin/Sources/Common/Category/NSButton+Action.m index c5af3a3e..7c8bf964 100644 --- a/WeChatPlugin/Sources/Common/Category/NSButton+Action.m +++ b/WeChatPlugin/Sources/Common/Category/NSButton+Action.m @@ -11,7 +11,7 @@ @implementation NSButton (Action) + (instancetype)tk_checkboxWithTitle:(NSString *)title target:(id)target action:(SEL)action { - NSButton *btn = [NSButton tk_buttonWithTitle:title target:target action:action]; + NSButton *btn = [self tk_buttonWithTitle:title target:target action:action]; [btn setButtonType:NSButtonTypeSwitch]; return btn; @@ -19,7 +19,7 @@ + (instancetype)tk_checkboxWithTitle:(NSString *)title target:(id)target action: + (instancetype)tk_buttonWithTitle:(NSString *)title target:(id)target action:(SEL)action { NSButton *btn = ({ - NSButton *btn = [[NSButton alloc] init]; + NSButton *btn = [[self alloc] init]; btn.title = title; btn.target = target; btn.action = action; diff --git a/WeChatPlugin/Sources/Common/Category/NSDate+Action.h b/WeChatPlugin/Sources/Common/Category/NSDate+Action.h new file mode 100644 index 00000000..7a31e92b --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSDate+Action.h @@ -0,0 +1,16 @@ +// +// NSDate+Action.h +// WeChatPlugin +// +// Created by TK on 2018/7/25. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface NSDate (Action) + +- (BOOL)isToday; +- (BOOL)isYesterday; + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSDate+Action.m b/WeChatPlugin/Sources/Common/Category/NSDate+Action.m new file mode 100644 index 00000000..99554dc5 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSDate+Action.m @@ -0,0 +1,35 @@ +// +// NSDate+Action.m +// WeChatPlugin +// +// Created by TK on 2018/7/25. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "NSDate+Action.h" + +@implementation NSDate (Action) + +- (BOOL)isToday { + NSCalendar *calendar = [NSCalendar currentCalendar]; + NSInteger unit = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear ; + + NSDateComponents *nowComponents = [calendar components:unit fromDate:[NSDate date]]; + NSDateComponents *selfComponents = [calendar components:unit fromDate:self]; + + return (selfComponents.year == nowComponents.year) && (selfComponents.month == nowComponents.month) && (selfComponents.day == nowComponents.day); +} + +- (BOOL)isYesterday { + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"yyyy-MM-dd"; + + NSDate *nowDate = [formatter dateFromString:[formatter stringFromDate:[NSDate date]]]; + NSDate *selfDate = [formatter dateFromString:[formatter stringFromDate:self]];; + NSCalendar *calendar = [NSCalendar currentCalendar]; + NSDateComponents *cmps = [calendar components:NSCalendarUnitDay fromDate:selfDate toDate:nowDate options:0]; + + return cmps.day == 1; +} + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSMenu+Action.h b/WeChatPlugin/Sources/Common/Category/NSMenu+Action.h new file mode 100644 index 00000000..e9c61377 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSMenu+Action.h @@ -0,0 +1,15 @@ +// +// NSMenu+Action.h +// WeChatPlugin +// +// Created by TK on 2018/4/15. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface NSMenu (Action) + +- (void)addItems:(NSArray *)subItems; + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSMenu+Action.m b/WeChatPlugin/Sources/Common/Category/NSMenu+Action.m new file mode 100644 index 00000000..156d6b09 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSMenu+Action.m @@ -0,0 +1,20 @@ +// +// NSMenu+Action.m +// WeChatPlugin +// +// Created by TK on 2018/4/15. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "NSMenu+Action.h" + +@implementation NSMenu (Action) + +- (void)addItems:(NSArray *)subItems { + for (NSMenuItem *item in subItems) { + NSAssert([item isKindOfClass:[NSMenuItem class]], @"the elements must be a NSMenuItem!"); + [self addItem:item]; + } +} + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSMenuItem+Action.h b/WeChatPlugin/Sources/Common/Category/NSMenuItem+Action.h new file mode 100644 index 00000000..f248c700 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSMenuItem+Action.h @@ -0,0 +1,15 @@ +// +// NSMenuItem+Action.h +// WeChatPlugin +// +// Created by TK on 2018/4/25. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface NSMenuItem (Action) + ++ (NSMenuItem *)menuItemWithTitle:(NSString *)title action:(SEL)selector target:(id)target keyEquivalent:(NSString *)key state:(NSControlStateValue)state; + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSMenuItem+Action.m b/WeChatPlugin/Sources/Common/Category/NSMenuItem+Action.m new file mode 100644 index 00000000..9da500a4 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSMenuItem+Action.m @@ -0,0 +1,21 @@ +// +// NSMenuItem+Action.m +// WeChatPlugin +// +// Created by TK on 2018/4/25. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "NSMenuItem+Action.h" + +@implementation NSMenuItem (Action) + ++ (NSMenuItem *)menuItemWithTitle:(NSString *)title action:(SEL)selector target:(id)target keyEquivalent:(NSString *)key state:(NSControlStateValue)state { + NSMenuItem *item = [[self alloc] initWithTitle:title action:selector keyEquivalent:key]; + item.target = target; + item.state = state; + + return item; +} + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSString+Action.h b/WeChatPlugin/Sources/Common/Category/NSString+Action.h new file mode 100644 index 00000000..9fc006c3 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSString+Action.h @@ -0,0 +1,18 @@ +// +// NSString+Action.h +// WeChatPlugin +// +// Created by TK on 2018/5/1. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface NSString (Action) + +- (CGFloat)widthWithFont:(NSFont *)font; +- (NSRect)rectWithFont:(NSFont *)font; +- (NSString *)substringFromString:(NSString *)fromStr; +- (NSString *)substringToString:(NSString *)fromStr; +- (NSString *)substringFromString:(NSString *)fromStr toString:(NSString *)toString; +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSString+Action.m b/WeChatPlugin/Sources/Common/Category/NSString+Action.m new file mode 100644 index 00000000..4184e38a --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSString+Action.m @@ -0,0 +1,49 @@ +// +// NSString+Action.m +// WeChatPlugin +// +// Created by TK on 2018/5/1. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "NSString+Action.h" + +@implementation NSString (Action) + +- (CGFloat)widthWithFont:(NSFont *)font { + return [self rectWithFont:font].size.width; +} + +- (NSRect)rectWithFont:(NSFont *)font { + return [self boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font}]; +} + +- (NSString *)substringFromString:(NSString *)fromStr { + if (!fromStr || [fromStr isKindOfClass:NSNull.class]) { + return self; + } + NSRange range = [self rangeOfString:fromStr]; + if (range.length > 0) { + return [self substringFromIndex:range.location + range.length]; + } + return nil; +} + +- (NSString *)substringToString:(NSString *)fromStr { + if (!fromStr || [fromStr isKindOfClass:NSNull.class]) { + return self; + } + NSRange range = [self rangeOfString:fromStr]; + if (range.length > 0) { + return [self substringToIndex:range.location]; + } + return nil; +} + +- (NSString *)substringFromString:(NSString *)fromStr toString:(NSString *)toString { + NSString *subString = [self substringFromString:fromStr]; + subString = [subString substringToString:toString]; + + return subString; +} +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSTextField+Action.m b/WeChatPlugin/Sources/Common/Category/NSTextField+Action.m index 5f137bd4..cbca0b5e 100644 --- a/WeChatPlugin/Sources/Common/Category/NSTextField+Action.m +++ b/WeChatPlugin/Sources/Common/Category/NSTextField+Action.m @@ -12,7 +12,7 @@ @implementation NSTextField (Action) + (instancetype)tk_labelWithString:(NSString *)stringValue { NSTextField *textField = ({ - NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 200, 17)]; + NSTextField *textField = [[self alloc] initWithFrame:NSMakeRect(10, 10, 200, 17)]; [textField setStringValue:stringValue]; [textField setBezeled:NO]; [textField setDrawsBackground:NO]; diff --git a/WeChatPlugin/Sources/Common/Category/NSView+Action.h b/WeChatPlugin/Sources/Common/Category/NSView+Action.h index b834deee..68fb7392 100644 --- a/WeChatPlugin/Sources/Common/Category/NSView+Action.h +++ b/WeChatPlugin/Sources/Common/Category/NSView+Action.h @@ -13,3 +13,14 @@ - (void)addSubviews:(NSArray *)subViews; @end + +@interface NSView (Size) + +@property (nonatomic) CGPoint origin; +@property (nonatomic) CGSize size; +@property (nonatomic) CGFloat x; +@property (nonatomic) CGFloat y; +@property (nonatomic) CGFloat width; +@property (nonatomic) CGFloat height; + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSView+Action.m b/WeChatPlugin/Sources/Common/Category/NSView+Action.m index a6c90aa3..1f8bbcdd 100644 --- a/WeChatPlugin/Sources/Common/Category/NSView+Action.m +++ b/WeChatPlugin/Sources/Common/Category/NSView+Action.m @@ -18,3 +18,61 @@ - (void)addSubviews:(NSArray *)subViews { } @end + +@implementation NSView (Size) + +- (CGPoint)origin { + return self.frame.origin; +} + +- (void)setOrigin:(CGPoint)point { + CGRect rect = self.frame; + + rect.origin = point; + self.frame = rect; +} + +- (CGSize)size { + return self.frame.size; +} + +- (void)setSize:(CGSize)size { + CGRect rect = self.frame; + + rect.size = size; + self.frame = rect; +} + +- (CGFloat)x { + return self.frame.origin.x; +} + +- (void)setX:(CGFloat)x { + [self setOrigin:CGPointMake(x, self.y)]; +} + +- (CGFloat)y { + return self.frame.origin.y; +} + +- (void)setY:(CGFloat)y { + [self setOrigin:CGPointMake(self.x, y)]; +} + +- (CGFloat)width { + return self.frame.size.width; +} + +- (void)setWidth:(CGFloat)width { + [self setSize:CGSizeMake(width, self.height)]; +} + +- (CGFloat)height { + return self.frame.size.height; +} + +- (void)setHeight:(CGFloat)height { + [self setSize:CGSizeMake(self.width, height)]; +} + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSWindowController+Action.h b/WeChatPlugin/Sources/Common/Category/NSWindowController+Action.h new file mode 100644 index 00000000..5b81018f --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSWindowController+Action.h @@ -0,0 +1,15 @@ +// +// NSWindowController+Action.h +// WeChatPlugin +// +// Created by TK on 2018/5/4. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface NSWindowController (Action) + +- (void)show; + +@end diff --git a/WeChatPlugin/Sources/Common/Category/NSWindowController+Action.m b/WeChatPlugin/Sources/Common/Category/NSWindowController+Action.m new file mode 100644 index 00000000..18296953 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Category/NSWindowController+Action.m @@ -0,0 +1,19 @@ +// +// NSWindowController+Action.m +// WeChatPlugin +// +// Created by TK on 2018/5/4. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "NSWindowController+Action.h" + +@implementation NSWindowController (Action) + +- (void)show { + [self showWindow:self]; + [self.window center]; + [self.window makeKeyWindow]; +} + +@end diff --git a/WeChatPlugin/Sources/Common/Color.h b/WeChatPlugin/Sources/Common/Macro/ColorConstant.h similarity index 100% rename from WeChatPlugin/Sources/Common/Color.h rename to WeChatPlugin/Sources/Common/Macro/ColorConstant.h diff --git a/WeChatPlugin/Sources/Common/Macro/DefineConstant.h b/WeChatPlugin/Sources/Common/Macro/DefineConstant.h new file mode 100644 index 00000000..c7053235 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Macro/DefineConstant.h @@ -0,0 +1,15 @@ +// +// DefineConstant.h +// WeChatPlugin +// +// Created by TK on 2018/4/14. +// Copyright © 2018年 tk. All rights reserved. +// + +#ifndef DefineConstant_h +#define DefineConstant_h + +#define TKLocalizedString(key) [[NSBundle bundleWithIdentifier:@"tk.WeChatPlugin"] localizedStringForKey:(key) value:@"" table:nil] +#define WXLocalizedString(key) [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil] + +#endif /* DefineConstant_h */ diff --git a/WeChatPlugin/Sources/Common/Macro/NotifyConstant.h b/WeChatPlugin/Sources/Common/Macro/NotifyConstant.h new file mode 100644 index 00000000..14fe27d6 --- /dev/null +++ b/WeChatPlugin/Sources/Common/Macro/NotifyConstant.h @@ -0,0 +1,19 @@ + +// +// NotifyConstant.h.h +// WeChatPlugin +// +// Created by TK on 2018/4/23. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +#ifndef NotifyConstant_h_h +#define NotifyConstant_h_h + +static NSString * const NOTIFY_AUTO_REPLY_CHANGE = @"NOTIFY_AUTO_REPLY_CHANGE"; +static NSString * const NOTIFY_PREVENT_REVOKE_CHANGE = @"NOTIFY_PREVENT_REVOKE_CHANGE"; +static NSString * const NOTIFY_AUTO_AUTH_CHANGE = @"NOTIFY_AUTO_AUTH_CHANGE"; + +#endif /* NotifyConstant_h_h */ diff --git a/WeChatPlugin/Sources/Common/TKPrefixHeader.pch b/WeChatPlugin/Sources/Common/TKPrefixHeader.pch index 1470fdc6..d73f3382 100644 --- a/WeChatPlugin/Sources/Common/TKPrefixHeader.pch +++ b/WeChatPlugin/Sources/Common/TKPrefixHeader.pch @@ -10,10 +10,18 @@ #define TKPrefixHeader_pch #ifdef __OBJC__ -#import "Color.h" +#import "ColorConstant.h" +#import "DefineConstant.h" +#import "NotifyConstant.h" #import "NSView+Action.h" #import "NSButton+Action.h" #import "NSTextField+Action.h" +#import "NSMenu+Action.h" +#import "NSString+Action.h" +#import "NSDate+Action.h" +#import "NSWindowController+Action.h" +#import "WeChatPlugin.h" +#import "TKUtility.h" #endif #endif /* TKPrefixHeader_pch */ diff --git a/WeChatPlugin/Sources/Config/TKConstants.h b/WeChatPlugin/Sources/Config/TKConstants.h new file mode 100644 index 00000000..2cb63334 --- /dev/null +++ b/WeChatPlugin/Sources/Config/TKConstants.h @@ -0,0 +1,17 @@ +// +// TKConstants.h +// WeChatPlugin +// +// Created by TK on 2020/3/14. +// Copyright © 2020 tk. All rights reserved. +// + +#ifndef TKConstants_h +#define TKConstants_h + +static NSString * const kTKScrollToMessageKey = @"click://kTKScrollToMessageKey"; +static NSString * const kTKRevokeLocationKey = @"kTKRevokeLocationKey"; +static NSString * const kTKShowMembeContactProfileKey = @"kTKShowMembeContactProfileKey"; +static NSInteger const kTKMemberQuitDayInterval = 30*2; + +#endif /* TKConstants_h */ diff --git a/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.h b/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.h index 87cb4deb..43f9bc3f 100644 --- a/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.h +++ b/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.h @@ -12,20 +12,34 @@ @interface TKWeChatPluginConfig : NSObject @property (nonatomic, assign) BOOL preventRevokeEnable; /**< 是否开启防撤回 */ +@property (nonatomic, assign) BOOL preventSelfRevokeEnable; /**< 是否防撤回自己 */ +@property (nonatomic, assign) BOOL autoReplyEnable; /**< 是否开启自动回复 */ @property (nonatomic, assign) BOOL autoAuthEnable; /**< 是否免认证登录 */ -@property (nonatomic, assign) BOOL autoLoginEnable; /**< 是否自动登录 */ +@property (nonatomic, assign) BOOL autoLoginEnable; /**< 是否自动登录 */ @property (nonatomic, assign) BOOL onTop; /**< 是否要置顶微信 */ @property (nonatomic, assign) BOOL multipleSelectionEnable; /**< 是否要进行多选 */ -@property (nonatomic, copy) NSMutableArray *autoReplyModels; /**< 自动回复的数组 */ -@property (nonatomic, copy) NSMutableArray *remoteControlModels; /**< 远程控制的数组 */ -@property (nonatomic, copy) NSMutableArray *ignoreSessionModels; /**< 聊天置底的数组 */ -@property (nonatomic, copy) NSMutableArray *selectSessions; /**< 已经选中的会话 */ -@property (nonatomic, copy) NSString *currentUserName; /**< 当前用户的id */ +@property (nonatomic, assign) BOOL forbidCheckVersion; /**< 禁止检测版本 */ +@property (nonatomic, assign) BOOL alfredEnable; /**< 是否开启Alfred */ +@property (nonatomic, assign) BOOL checkUpdateWechatEnable; /**< 是否允许微信启动检测更新 */ +@property (nonatomic, assign) BOOL systemBrowserEnable; /**< 是否使用自身浏览器打开连接 */ +@property (nonatomic, assign) BOOL memberExitMonitoringEnable; /**< 是否使用自身浏览器打开连接 */ +@property (nonatomic, strong) NSMutableArray *autoReplyModels; /**< 自动回复的数组 */ +@property (nonatomic, strong) NSMutableArray *remoteControlModels; /**< 远程控制的数组 */ +@property (nonatomic, strong) NSMutableArray *ignoreSessionModels; /**< 聊天置底的数组 */ +@property (nonatomic, strong) NSMutableArray *selectSessions; /**< 已经选中的会话 */ +@property (nonatomic, strong) NSMutableSet *revokeMsgSet; /**< 撤回的消息集合 */ +@property (nonatomic, strong) NSMutableSet *unreadSessionSet; /**< 标记未读消息集合 */ +@property (nonatomic, copy) NSString *currentUserName; /**< 当前用户的id */ +@property (nonatomic, copy, readonly) NSDictionary *localInfoPlist; +@property (nonatomic, copy, readonly) NSDictionary *romoteInfoPlist; +@property (nonatomic, strong) NSMutableDictionary *quitChatRoomMemberDict; /**< 退群的好友集合 */ - (void)saveAutoReplyModels; - (void)saveRemoteControlModels; - (void)saveIgnoreSessionModels; +- (void)saveQuitChatRoomMemberDict; + (instancetype)sharedConfig; @end + diff --git a/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.m b/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.m index dcbf1f69..67a946a5 100644 --- a/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.m +++ b/WeChatPlugin/Sources/Config/TKWeChatPluginConfig.m @@ -10,14 +10,33 @@ #import "TKRemoteControlModel.h" #import "TKAutoReplyModel.h" #import "TKIgnoreSessonModel.h" +#import "WeChatPlugin.h" static NSString * const kTKPreventRevokeEnableKey = @"kTKPreventRevokeEnableKey"; +static NSString * const kTKPreventSelfRevokeEnableKey = @"kTKPreventSelfRevokeEnableKey"; +static NSString * const kTKAutoReplyEnableKey = @"kTKAutoReplyEnableKey"; static NSString * const kTKAutoAuthEnableKey = @"kTKAutoAuthEnableKey"; static NSString * const kTKAutoLoginEnableKey = @"kTKAutoLoginEnableKey"; static NSString * const kTKOnTopKey = @"kTKOnTopKey"; -static NSString * const kTKAutoReplyModelsFilePath = @"/Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/TKAutoReplyModels.plist"; -static NSString * const kTKRemoteControlModelsFilePath = @"/Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/TKRemoteControlCommands.plist"; -static NSString * const kTKIgnoreSessionModelsFilePath = @"/Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/TKIgnoreSessons.plist"; +static NSString * const kTKForbidCheckVersionKey = @"kTKForbidCheckVersionKey"; +static NSString * const kTKAlfredEnableKey = @"kTKAlfredEnableKey"; +static NSString * const kTKCheckUpdateWechatEnableKey = @"kTKCheckUpdateWechatEnableKey"; +static NSString * const kTKSystemBrowserEnableKey = @"kTKSystemBrowserEnableKey"; +static NSString * const kTKmemberExitMonitoringEnableKey = @"kTKmemberExitMonitoringEnableKey"; +static NSString * const kTKWeChatResourcesPath = @"/Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/"; +static NSString * const kTKWeChatRemotePlistPath = @"https://raw.githubusercontent.com/TKkk-iOSer/WeChatPlugin-MacOS/master/Other/Products/Debug/WeChatPlugin.framework/Resources/Info.plist"; + +@interface TKWeChatPluginConfig () + +@property (nonatomic, copy) NSString *remoteControlPlistFilePath; +@property (nonatomic, copy) NSString *autoReplyPlistFilePath; +@property (nonatomic, copy) NSString *ignoreSessionPlistFilePath; +@property (nonatomic, copy) NSString *quitChatroomMemberPlistFilePath; + +@property (nonatomic, copy) NSDictionary *localInfoPlist; +@property (nonatomic, copy) NSDictionary *romoteInfoPlist; + +@end @implementation TKWeChatPluginConfig @@ -34,9 +53,16 @@ - (instancetype)init { self = [super init]; if (self) { _preventRevokeEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKPreventRevokeEnableKey]; + _preventSelfRevokeEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKPreventSelfRevokeEnableKey]; + _autoReplyEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKAutoReplyEnableKey]; _autoAuthEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKAutoAuthEnableKey]; _autoLoginEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKAutoLoginEnableKey]; _onTop = [[NSUserDefaults standardUserDefaults] boolForKey:kTKOnTopKey]; + _forbidCheckVersion = [[NSUserDefaults standardUserDefaults] boolForKey:kTKForbidCheckVersionKey]; + _alfredEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKAlfredEnableKey]; + _checkUpdateWechatEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKCheckUpdateWechatEnableKey]; + _systemBrowserEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKSystemBrowserEnableKey]; + _memberExitMonitoringEnable = [[NSUserDefaults standardUserDefaults] boolForKey:kTKmemberExitMonitoringEnableKey]; } return self; } @@ -47,6 +73,18 @@ - (void)setPreventRevokeEnable:(BOOL)preventRevokeEnable { [[NSUserDefaults standardUserDefaults] synchronize]; } +- (void)setPreventSelfRevokeEnable:(BOOL)preventSelfRevokeEnable { + _preventSelfRevokeEnable = preventSelfRevokeEnable; + [[NSUserDefaults standardUserDefaults] setBool:preventSelfRevokeEnable forKey:kTKPreventSelfRevokeEnableKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (void)setAutoReplyEnable:(BOOL)autoReplyEnable { + _autoReplyEnable = autoReplyEnable; + [[NSUserDefaults standardUserDefaults] setBool:autoReplyEnable forKey:kTKAutoReplyEnableKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + - (void)setAutoAuthEnable:(BOOL)autoAuthEnable { _autoAuthEnable = autoAuthEnable; [[NSUserDefaults standardUserDefaults] setBool:autoAuthEnable forKey:kTKAutoAuthEnableKey]; @@ -65,10 +103,40 @@ - (void)setOnTop:(BOOL)onTop { [[NSUserDefaults standardUserDefaults] synchronize]; } +- (void)setForbidCheckVersion:(BOOL)forbidCheckVersion { + _forbidCheckVersion = forbidCheckVersion; + [[NSUserDefaults standardUserDefaults] setBool:_forbidCheckVersion forKey:kTKForbidCheckVersionKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (void)setAlfredEnable:(BOOL)alfredEnable { + _alfredEnable = alfredEnable; + [[NSUserDefaults standardUserDefaults] setBool:_alfredEnable forKey:kTKAlfredEnableKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (void)setCheckUpdateWechatEnable:(BOOL)checkUpdateWechatEnable { + _checkUpdateWechatEnable = checkUpdateWechatEnable; + [[NSUserDefaults standardUserDefaults] setBool:_checkUpdateWechatEnable forKey:kTKCheckUpdateWechatEnableKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (void)setSystemBrowserEnable:(BOOL)systemBrowserEnable { + _systemBrowserEnable = systemBrowserEnable; + [[NSUserDefaults standardUserDefaults] setBool:_systemBrowserEnable forKey:kTKSystemBrowserEnableKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (void)setMemberExitMonitoringEnable:(BOOL)memberExitMonitoringEnable { + _memberExitMonitoringEnable = memberExitMonitoringEnable; + [[NSUserDefaults standardUserDefaults] setBool:_memberExitMonitoringEnable forKey:kTKmemberExitMonitoringEnableKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + #pragma mark - 自动回复 - (NSArray *)autoReplyModels { if (!_autoReplyModels) { - _autoReplyModels = [self getArrayClass:[TKAutoReplyModel class] filePath:kTKAutoReplyModelsFilePath]; + _autoReplyModels = [self getModelsWithClass:[TKAutoReplyModel class] filePath:self.autoReplyPlistFilePath]; } return _autoReplyModels; } @@ -84,26 +152,33 @@ - (void)saveAutoReplyModels { model.keyword = model.keyword == nil ? @"" : model.keyword; [needSaveModels addObject:model.dictionary]; }]; - [needSaveModels writeToFile:kTKAutoReplyModelsFilePath atomically:YES]; + [needSaveModels writeToFile:self.autoReplyPlistFilePath atomically:YES]; } #pragma mark - 远程控制 - (NSArray *)remoteControlModels { if (!_remoteControlModels) { + __block BOOL needSaveRemoteControlModels = NO; _remoteControlModels = ({ - NSArray *originModels = [NSArray arrayWithContentsOfFile:kTKRemoteControlModelsFilePath]; + NSArray *originModels = [NSArray arrayWithContentsOfFile:self.remoteControlPlistFilePath]; NSMutableArray *newRemoteControlModels = [NSMutableArray array]; [originModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger idx, BOOL * _Nonnull stop) { NSMutableArray *newSubModels = [NSMutableArray array]; [subModels enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { TKRemoteControlModel *model = [[TKRemoteControlModel alloc] initWithDict:obj]; + if ([model.executeCommand isEqualToString:@"restartWeChat"]) { + model.executeCommand = @"killWeChat"; + needSaveRemoteControlModels = YES; + } [newSubModels addObject:model]; }]; [newRemoteControlModels addObject:newSubModels]; }]; - newRemoteControlModels; }); + if (needSaveRemoteControlModels) { + [self saveRemoteControlModels]; + } } return _remoteControlModels; } @@ -117,49 +192,146 @@ - (void)saveRemoteControlModels { }]; [needSaveModels addObject:newSubModels]; }]; - [needSaveModels writeToFile:kTKRemoteControlModelsFilePath atomically:YES]; + [needSaveModels writeToFile:self.remoteControlPlistFilePath atomically:YES]; } #pragma mark - 置底 - (NSArray *)ignoreSessionModels { if (!_ignoreSessionModels) { - _ignoreSessionModels = [self getArrayClass:[TKIgnoreSessonModel class] filePath:kTKIgnoreSessionModelsFilePath]; - + _ignoreSessionModels = [self getModelsWithClass:[TKIgnoreSessonModel class] filePath:self.ignoreSessionPlistFilePath]; } return _ignoreSessionModels; } - (void)saveIgnoreSessionModels { - [self saveArray:_ignoreSessionModels filePath:kTKIgnoreSessionModelsFilePath]; + NSMutableArray *needSaveArray = [NSMutableArray array]; + [self.ignoreSessionModels enumerateObjectsUsingBlock:^(TKBaseModel *obj, NSUInteger idx, BOOL * _Nonnull stop) { + [needSaveArray addObject:obj.dictionary]; + }]; + + [needSaveArray writeToFile:self.ignoreSessionPlistFilePath atomically:YES]; + +} + +#pragma mark - 选中的会话 +- (NSMutableArray *)selectSessions { + if (!_selectSessions) { + _selectSessions = [NSMutableArray array]; + } + return _selectSessions; +} + +#pragma mark - 撤回的消息集合 +- (NSMutableSet *)revokeMsgSet { + if (!_revokeMsgSet) { + _revokeMsgSet = [NSMutableSet set]; + } + return _revokeMsgSet; +} + +- (NSMutableSet *)unreadSessionSet { + if (!_unreadSessionSet) { + _unreadSessionSet = [NSMutableSet set]; + } + return _unreadSessionSet; +} + +- (NSMutableDictionary *)quitChatRoomMemberDict { + if (!_quitChatRoomMemberDict) { + _quitChatRoomMemberDict = [NSMutableDictionary dictionaryWithContentsOfFile:self.quitChatroomMemberPlistFilePath]; + if (!_quitChatRoomMemberDict) { + _quitChatRoomMemberDict = [NSMutableDictionary dictionary]; + } + } + return _quitChatRoomMemberDict; +} + +- (void)saveQuitChatRoomMemberDict { + [self.quitChatRoomMemberDict writeToFile:self.quitChatroomMemberPlistFilePath atomically:YES]; +} +#pragma mark - 获取沙盒上的 plist 文件,包括:远程控制,自动回复,置底列表。 +- (NSString *)remoteControlPlistFilePath { + if (!_remoteControlPlistFilePath) { + _remoteControlPlistFilePath = [self getSandboxFilePathWithPlistName:@"TKRemoteControlCommands.plist"]; + } + return _remoteControlPlistFilePath; +} + +- (NSString *)autoReplyPlistFilePath { + if (!_autoReplyPlistFilePath) { + _autoReplyPlistFilePath = [self getSandboxFilePathWithPlistName:@"TKAutoReplyModels.plist"]; + } + return _autoReplyPlistFilePath; +} + +- (NSString *)ignoreSessionPlistFilePath { + if (!_ignoreSessionPlistFilePath) { + _ignoreSessionPlistFilePath = [self getSandboxFilePathWithPlistName:@"TKIgnoreSessons.plist"]; + } + return _ignoreSessionPlistFilePath; +} + +- (NSString *)quitChatroomMemberPlistFilePath { + if (!_quitChatroomMemberPlistFilePath) { + _quitChatroomMemberPlistFilePath = [self getSandboxFilePathWithPlistName:@"TKQuitChatRoomMember.plist"]; + } + return _quitChatroomMemberPlistFilePath; +} + +#pragma mark - 获取本地 & github 上的小助手 info 信息 +- (NSDictionary *)localInfoPlist { + if (!_localInfoPlist) { + NSString *localInfoPath = [kTKWeChatResourcesPath stringByAppendingString:@"info.plist"]; + _localInfoPlist = [NSDictionary dictionaryWithContentsOfFile:localInfoPath]; + } + return _localInfoPlist; +} + +- (NSDictionary *)romoteInfoPlist { + if (!_romoteInfoPlist) { + NSURL *url = [NSURL URLWithString:kTKWeChatRemotePlistPath]; + _romoteInfoPlist = [NSDictionary dictionaryWithContentsOfURL:url]; + } + return _romoteInfoPlist; } #pragma mark - common -- (NSMutableArray *)getArrayClass:(Class)class filePath:(NSString *)filePath { +- (NSMutableArray *)getModelsWithClass:(Class)class filePath:(NSString *)filePath { NSArray *originModels = [NSArray arrayWithContentsOfFile:filePath]; NSMutableArray *newModels = [NSMutableArray array]; - + __weak Class weakClass = class; [originModels enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL * _Nonnull stop) { TKIgnoreSessonModel *model = [[weakClass alloc] initWithDict:obj]; [newModels addObject:model]; }]; - return newModels; -} - -- (void)saveArray:(NSMutableArray *)array filePath:(NSString *)filePath { - NSMutableArray *needSaveArray = [NSMutableArray array]; - [array enumerateObjectsUsingBlock:^(TKBaseModel *obj, NSUInteger idx, BOOL * _Nonnull stop) { - [needSaveArray addObject:obj.dictionary]; - }]; - - [needSaveArray writeToFile:filePath atomically:YES]; + return newModels; } -- (NSMutableArray *)selectSessions { - if (!_selectSessions) { - _selectSessions = [NSMutableArray array]; +- (NSString *)getSandboxFilePathWithPlistName:(NSString *)plistName { + NSFileManager *manager = [NSFileManager defaultManager]; + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + + NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; + NSString *wechatPluginDirectory = [documentDirectory stringByAppendingFormat:@"/TKWeChatPlugin/%@/",currentUserName]; + NSString *plistFilePath = [wechatPluginDirectory stringByAppendingPathComponent:plistName]; + if ([manager fileExistsAtPath:plistFilePath]) { + return plistFilePath; } - return _selectSessions; + + [manager createDirectoryAtPath:wechatPluginDirectory withIntermediateDirectories:YES attributes:nil error:nil]; + NSString *resourcesFilePath = [kTKWeChatResourcesPath stringByAppendingString:plistName]; + if (![manager fileExistsAtPath:resourcesFilePath]) { + return plistFilePath; + } + + NSError *error = nil; + [manager copyItemAtPath:resourcesFilePath toPath:plistFilePath error:&error]; + if (!error) { + return plistFilePath; + } + return resourcesFilePath; } @end + diff --git a/WeChatPlugin/Sources/Controllers/TKRemoteControlController.h b/WeChatPlugin/Sources/Controllers/TKRemoteControlController.h deleted file mode 100644 index 29ad7d03..00000000 --- a/WeChatPlugin/Sources/Controllers/TKRemoteControlController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// TKRemoteControlController.h -// WeChatPlugin -// -// Created by TK on 2017/8/8. -// Copyright © 2017年 tk. All rights reserved. -// - -#import - -@interface TKRemoteControlController : NSObject - -+ (void)executeRemoteControlCommandWithMsg:(NSString *)msg; -+ (void)executeShellCommand:(NSString *)msg; -+ (NSString *)remoteControlCommandsString; - -@end diff --git a/WeChatPlugin/Sources/Controllers/TKRemoteControlController.m b/WeChatPlugin/Sources/Controllers/TKRemoteControlController.m deleted file mode 100644 index 2334092b..00000000 --- a/WeChatPlugin/Sources/Controllers/TKRemoteControlController.m +++ /dev/null @@ -1,86 +0,0 @@ -// -// TKRemoteControlController.m -// WeChatPlugin -// -// Created by TK on 2017/8/8. -// Copyright © 2017年 tk. All rights reserved. -// - -#import "TKRemoteControlController.h" -#import "TKWeChatPluginConfig.h" -#import "TKRemoteControlModel.h" -#import "WeChatPlugin.h" - -// 执行 AppleScript -static NSString * const kRemoteControlAppleScript = @"osascript /Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt"; - -@implementation TKRemoteControlController - -+ (void)executeRemoteControlCommandWithMsg:(NSString *)msg { - NSArray *remoteControlModels = [TKWeChatPluginConfig sharedConfig].remoteControlModels; - [remoteControlModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger index, BOOL * _Nonnull stop) { - [subModels enumerateObjectsUsingBlock:^(TKRemoteControlModel *model, NSUInteger idx, BOOL * _Nonnull stop) { - if (model.enable && ![model.keyword isEqualToString:@""] && [msg isEqualToString:model.keyword]) { - if ([model.function isEqualToString:@"屏幕保护"] || [model.function isEqualToString:@"锁屏"]) { - // 屏幕保护 & 锁屏 通过 Shell 命令来执行即可 - [self executeShellCommand:model.executeCommand]; - } else { - // 拼接相关参数,执行 AppleScript - NSString *command = [NSString stringWithFormat:@"%@ %@",kRemoteControlAppleScript, model.executeCommand]; - [self executeShellCommand:command]; - // bug: 有些程序在第一次时会无法关闭,需要再次关闭 - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - if ([model.function isEqualToString:@"退出所有程序"]) { - NSString *command = [NSString stringWithFormat:@"%@ %@",kRemoteControlAppleScript, model.executeCommand]; - [self executeShellCommand:command]; - } - }); - } - NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; - NSString *callBack = [NSString stringWithFormat:@"小助手收到一条指令:%@",model.function]; - MessageService *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; - [service SendTextMessage:currentUserName toUsrName:currentUserName msgText:callBack atUserList:nil]; - } - }]; - }]; -} - -/** - 通过 NSTask 执行 Shell 命令 - - @param cmd Terminal命令 - */ -+ (void)executeShellCommand:(NSString *)cmd { - NSTask *task = [[NSTask alloc] init]; - [task setLaunchPath:@"/bin/bash"]; - [task setArguments:@[@"-c", cmd]]; - [task launch]; -} - -+ (NSString *)remoteControlCommandsString { - NSMutableString *replyContent = [NSMutableString stringWithFormat:@"远程控制指令:\n(功能-指令-是否开启)\n\n"]; - - NSArray *remoteControlModels = [TKWeChatPluginConfig sharedConfig].remoteControlModels; - [remoteControlModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger index, BOOL * _Nonnull stop) { - switch (index) { - case 0: - [replyContent appendString:@"macbook控制:\n"]; - break; - case 1: - [replyContent appendString:@"app控制:\n"]; - break; - case 2: - [replyContent appendString:@"网易云音乐控制:\n"]; - break; - default: - break; - } - [subModels enumerateObjectsUsingBlock:^(TKRemoteControlModel *model, NSUInteger idx, BOOL * _Nonnull stop) { - [replyContent appendFormat:@"%@-%@-%@\n", model.function, model.keyword, model.enable ? @"开启":@"关闭"]; - }]; - [replyContent appendString:@"\n"]; - }]; - return replyContent; -} - -@end diff --git a/WeChatPlugin/Sources/Category/MMChatsTableCellView+hook.h b/WeChatPlugin/Sources/Hook/MMChatsTableCellView+hook.h similarity index 100% rename from WeChatPlugin/Sources/Category/MMChatsTableCellView+hook.h rename to WeChatPlugin/Sources/Hook/MMChatsTableCellView+hook.h diff --git a/WeChatPlugin/Sources/Category/MMChatsTableCellView+hook.m b/WeChatPlugin/Sources/Hook/MMChatsTableCellView+hook.m similarity index 57% rename from WeChatPlugin/Sources/Category/MMChatsTableCellView+hook.m rename to WeChatPlugin/Sources/Hook/MMChatsTableCellView+hook.m index fda8bca0..cb60b146 100644 --- a/WeChatPlugin/Sources/Category/MMChatsTableCellView+hook.m +++ b/WeChatPlugin/Sources/Hook/MMChatsTableCellView+hook.m @@ -9,6 +9,8 @@ #import "MMChatsTableCellView+hook.h" #import "WeChatPlugin.h" #import "TKIgnoreSessonModel.h" +#import "TKMessageManager.h" +#import "TKEmoticonManager.h" @implementation NSObject (MMChatsTableCellViewHook) @@ -17,16 +19,16 @@ + (void)hookMMChatsTableCellView { tk_hookMethod(objc_getClass("MMChatsTableCellView"), @selector(setSessionInfo:), [self class], @selector(hook_setSessionInfo:)); tk_hookMethod(objc_getClass("MMChatsTableCellView"), @selector(contextMenuSticky:), [self class], @selector(hook_contextMenuSticky:)); tk_hookMethod(objc_getClass("MMChatsTableCellView"), @selector(contextMenuDelete:), [self class], @selector(hook_contextMenuDelete:)); - tk_hookMethod(objc_getClass("MMChatsViewController"), @selector(tableView:rowGotMouseDown:), [self class], @selector(hooktableView:rowGotMouseDown:)); + tk_hookMethod(objc_getClass("MMChatsViewController"), @selector(tableView:rowGotMouseDown:), [self class], @selector(hook_tableView:rowGotMouseDown:)); } -- (void)hooktableView:(NSTableView *)arg1 rowGotMouseDown:(long long)arg2 { - [self hooktableView:arg1 rowGotMouseDown:arg2]; +- (void)hook_tableView:(NSTableView *)arg1 rowGotMouseDown:(long long)arg2 { + [self hook_tableView:arg1 rowGotMouseDown:arg2]; if ([[TKWeChatPluginConfig sharedConfig] multipleSelectionEnable]) { NSMutableArray *selectSessions = [[TKWeChatPluginConfig sharedConfig] selectSessions]; MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; - MMSessionInfo *sessionInfo = [sessionMgr GetSessionAtIndex:arg2]; + MMSessionInfo *sessionInfo = [sessionMgr getSessionAtIndex:arg2]; if ([selectSessions containsObject:sessionInfo]) { [selectSessions removeObject:sessionInfo]; } else { @@ -62,8 +64,7 @@ - (void)hook_setSessionInfo:(MMSessionInfo *)sessionInfo { } - (void)hook_menuWillOpen:(NSMenu *)arg1 { - MMChatsTableCellView *cellView = (MMChatsTableCellView *)self; - MMSessionInfo *sessionInfo = [cellView sessionInfo]; + MMSessionInfo *sessionInfo = [(MMChatsTableCellView *)self sessionInfo]; NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; __block BOOL isIgnore = false; @@ -74,73 +75,73 @@ - (void)hook_menuWillOpen:(NSMenu *)arg1 { *stop = YES; } }]; + + NSMenuItem *clearUnReadItem = [[NSMenuItem alloc] initWithTitle:TKLocalizedString(@"assistant.chat.readAll") action:@selector(contextMenuClearUnRead) keyEquivalent:@""]; - NSString *itemString = isIgnore ? @"取消置底" : @"置底"; - NSMenuItem *preventRevokeItem = [[NSMenuItem alloc] initWithTitle:itemString action:@selector(contextMenuStickyBottom) keyEquivalent:@""]; - - BOOL multipleSelectionEnable = [[TKWeChatPluginConfig sharedConfig] multipleSelectionEnable]; - NSString *multipleSelectionString = multipleSelectionEnable ? @"取消多选" : @"多选"; - NSMenuItem *multipleSelectionItem = [[NSMenuItem alloc] initWithTitle:multipleSelectionString action:@selector(contextMenuMutipleSelection) keyEquivalent:@""]; - - [arg1 insertItem:preventRevokeItem atIndex:1]; - [arg1 addItem:multipleSelectionItem]; + NSMenuItem *clearEmptySessionItem = [[NSMenuItem alloc] initWithTitle:TKLocalizedString(@"assistant.chat.clearEmpty") action:@selector(contextMenuClearEmptySession) keyEquivalent:@""]; + + [arg1 addItems:@[[NSMenuItem separatorItem], + clearUnReadItem, + clearEmptySessionItem + ]]; [self hook_menuWillOpen:arg1]; } -- (void)contextMenuStickyBottom { - MMChatsTableCellView *cellView = (MMChatsTableCellView *)self; - MMSessionInfo *sessionInfo = [cellView sessionInfo]; - NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; - - NSMutableArray *ignoreSessions = [[TKWeChatPluginConfig sharedConfig] ignoreSessionModels]; - __block NSInteger index = -1; - [ignoreSessions enumerateObjectsUsingBlock:^(TKIgnoreSessonModel *model, NSUInteger idx, BOOL * _Nonnull stop) { - if ([model.userName isEqualToString:sessionInfo.m_nsUserName] && [model.selfContact isEqualToString:currentUserName]) { - index = idx; - *stop = YES; - } +- (void)contextMenuClearUnRead { + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + NSMutableArray *arrSession = [sessionMgr getAllSessions]; + + [arrSession enumerateObjectsUsingBlock:^(MMSessionInfo *obj, NSUInteger idx, BOOL * _Nonnull stop) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [[TKMessageManager shareManager] clearUnRead:obj.m_nsUserName]; + }); }]; - +} + +- (void)contextMenuClearEmptySession { MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + FFProcessReqsvrZZ *msgService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; - if (index == -1) { - TKIgnoreSessonModel *model = [[TKIgnoreSessonModel alloc] init]; - model.userName = sessionInfo.m_nsUserName; - model.selfContact = currentUserName; - model.ignore = true; - [ignoreSessions addObject:model]; - if (!sessionInfo.m_bShowUnReadAsRedDot) { - [sessionMgr MuteSessionByUserName:sessionInfo.m_nsUserName]; - } - if (sessionInfo.m_bIsTop) { - [sessionMgr UntopSessionByUserName:sessionInfo.m_nsUserName]; - } - } else { - [ignoreSessions removeObjectAtIndex:index]; - if (sessionInfo.m_bShowUnReadAsRedDot) { - [sessionMgr UnmuteSessionByUserName:sessionInfo.m_nsUserName]; + if (msgService == nil || sessionMgr == nil) { + return; + + } + + NSMutableArray *arrSession = [sessionMgr getAllSessions]; + NSMutableArray *emptyArrSession = [NSMutableArray array]; + + [arrSession enumerateObjectsUsingBlock:^(MMSessionInfo *sessionInfo, NSUInteger idx, BOOL * _Nonnull stop) { + BOOL hasEmplyMsgSession = ![msgService HasMsgInChat:sessionInfo.m_nsUserName]; + WCContactData *contact = sessionInfo.m_packedInfo.m_contact; + if (![sessionInfo.m_nsUserName isEqualToString:@"brandsessionholder"] && ![contact isSelf] && hasEmplyMsgSession) { + [emptyArrSession addObject:sessionInfo]; } + }]; + + while (emptyArrSession.count > 0) { + [emptyArrSession enumerateObjectsUsingBlock:^(MMSessionInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [sessionMgr removeSessionOfUser:obj.m_nsUserName isDelMsg:NO]; + [emptyArrSession removeObject:obj]; + }]; } - [sessionMgr sortSessions]; - [[TKWeChatPluginConfig sharedConfig] saveIgnoreSessionModels]; } -- (void)contextMenuMutipleSelection { - BOOL multipleSelectionEnable = [[TKWeChatPluginConfig sharedConfig] multipleSelectionEnable]; - if (multipleSelectionEnable) { - [[[TKWeChatPluginConfig sharedConfig] selectSessions] removeAllObjects]; - WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; - [wechat.chatsViewController.tableView reloadData]; - } +- (void)contextMenuUnreadSession { + MMSessionInfo *sessionInfo = [(MMChatsTableCellView *)self sessionInfo]; + if (sessionInfo.m_uUnReadCount > 0) return; + + NSMutableSet *unreadSessionSet = [[TKWeChatPluginConfig sharedConfig] unreadSessionSet]; + if ([unreadSessionSet containsObject:sessionInfo.m_nsUserName]) return; - [[TKWeChatPluginConfig sharedConfig] setMultipleSelectionEnable:!multipleSelectionEnable]; + [unreadSessionSet addObject:sessionInfo.m_nsUserName]; + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + [sessionMgr changeSessionUnreadCountWithUserName:sessionInfo.m_nsUserName to:sessionInfo.m_uUnReadCount + 1]; } - (void)hook_contextMenuSticky:(id)arg1 { [self hook_contextMenuSticky:arg1]; - MMChatsTableCellView *cellView = (MMChatsTableCellView *)self; - MMSessionInfo *sessionInfo = [cellView sessionInfo]; + MMSessionInfo *sessionInfo = [(MMChatsTableCellView *)self sessionInfo]; if (!sessionInfo.m_bIsTop) return; NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; @@ -157,10 +158,14 @@ - (void)hook_contextMenuSticky:(id)arg1 { [ignoreSessions removeObjectAtIndex:index]; MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; - if (sessionInfo.m_bShowUnReadAsRedDot) { - [sessionMgr UnmuteSessionByUserName:sessionInfo.m_nsUserName]; + if (sessionInfo.m_bShowUnReadAsRedDot && sessionInfo.m_nsUserName) { + [sessionMgr unmuteSessionByUserName:sessionInfo.m_nsUserName]; + } + if ([sessionMgr respondsToSelector:@selector(FFDataSvrMgrSvrFavZZ)]) { + [sessionMgr FFDataSvrMgrSvrFavZZ]; + } else if ([sessionMgr respondsToSelector:@selector(sortSessions)]){ + [sessionMgr sortSessions]; } - [sessionMgr sortSessions]; [[TKWeChatPluginConfig sharedConfig] saveIgnoreSessionModels]; } } @@ -175,10 +180,10 @@ - (void)hook_contextMenuDelete:(id)arg1 { [selectSessions enumerateObjectsUsingBlock:^(MMSessionInfo *sessionInfo, NSUInteger idx, BOOL * _Nonnull stop) { NSString *sessionUserName = sessionInfo.m_nsUserName; if (sessionUserName.length != 0) { - [sessionMgr deleteSessionWithoutSyncToServerWithUserName:sessionUserName]; + [sessionMgr removeSessionOfUser:sessionUserName isDelMsg:NO]; } }]; - + [[TKWeChatPluginConfig sharedConfig] setMultipleSelectionEnable:NO]; WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; [wechat.chatsViewController.tableView reloadData]; } else { diff --git a/WeChatPlugin/Sources/Hook/MMStickerMessageCellView+hook.h b/WeChatPlugin/Sources/Hook/MMStickerMessageCellView+hook.h new file mode 100644 index 00000000..34ec8198 --- /dev/null +++ b/WeChatPlugin/Sources/Hook/MMStickerMessageCellView+hook.h @@ -0,0 +1,15 @@ +// +// MMStickerMessageCellView+hook.m +// WeChatPlugin +// +// Created by TK on 2018/2/23. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface NSObject (MMStickerMessageCellView) + ++ (void)hookMMStickerMessageCellView; + +@end diff --git a/WeChatPlugin/Sources/Hook/MMStickerMessageCellView+hook.m b/WeChatPlugin/Sources/Hook/MMStickerMessageCellView+hook.m new file mode 100644 index 00000000..6c755a7f --- /dev/null +++ b/WeChatPlugin/Sources/Hook/MMStickerMessageCellView+hook.m @@ -0,0 +1,65 @@ +// +// MMStickerMessageCellView+hook.m +// WeChatPlugin +// +// Created by TK on 2018/2/23. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "MMStickerMessageCellView+hook.h" +#import "WeChatPlugin.h" +#import "TKEmoticonManager.h" + +@implementation NSObject (MMStickerMessageCellView) + ++ (void)hookMMStickerMessageCellView { + tk_hookMethod(objc_getClass("MMStickerMessageCellView"), @selector(contextMenu), [self class], @selector(hook_contextMenu)); + if (LargerOrEqualVersion(@"2.3.22")) { + tk_hookMethod(objc_getClass("MMStickerMessageCellView"), @selector(contextMenuExport), [self class], @selector(hook_contextMenuExport)); + } +} + +- (id)hook_contextMenu { + NSMenu *menu = [self hook_contextMenu]; + if ([self.className isEqualToString:@"MMStickerMessageCellView"]) { + NSMenuItem *copyItem = [[NSMenuItem alloc] initWithTitle:WXLocalizedString(@"Message.Menu.Copy") action:@selector(contextMenuCopyEmoji) keyEquivalent:@""]; + NSMenuItem *exportItem = [[NSMenuItem alloc] initWithTitle:WXLocalizedString(@"Message.Menu.Export") action:@selector(contextMenuExport) keyEquivalent:@""]; + [menu addItem:[NSMenuItem separatorItem]]; + [menu addItem:copyItem]; + [menu addItem:exportItem]; + } + return menu; +} + +- (void)contextMenuExport { + [self exportEmoji]; +} + +- (void)hook_contextMenuExport { + if (![self.className isEqualToString:@"MMStickerMessageCellView"]) { + [self hook_contextMenu]; + return; + } + [self exportEmoji]; +} + +- (void)exportEmoji { + MMStickerMessageCellView *currentCellView = (MMStickerMessageCellView *)self; + MMMessageTableItem *item = currentCellView.messageTableItem; + if (!item.message || !item.message.m_nsEmoticonMD5) { + return; + } + [[TKEmoticonManager shareManager] exportEmoticonWithMd5:item.message.m_nsEmoticonMD5 window:currentCellView.delegate.view.window]; +} + +- (void)contextMenuCopyEmoji { + if ([self.className isEqualToString:@"MMStickerMessageCellView"]) { + MMMessageTableItem *item = [self valueForKey:@"messageTableItem"]; + if (!item.message || !item.message.m_nsEmoticonMD5) { + return; + } + [[TKEmoticonManager shareManager] copyEmoticonWithMd5:item.message.m_nsEmoticonMD5]; + } +} + +@end diff --git a/WeChatPlugin/Sources/Hook/MMStickerPickerCell+hook.h b/WeChatPlugin/Sources/Hook/MMStickerPickerCell+hook.h new file mode 100644 index 00000000..d1e63ed7 --- /dev/null +++ b/WeChatPlugin/Sources/Hook/MMStickerPickerCell+hook.h @@ -0,0 +1,17 @@ +// +// NSObject+MMStickerPickerCell.h +// WeChatPlugin +// +// Created by TK on 2019/3/13. +// Copyright © 2019 tk. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (MMStickerPickerCell) ++ (void)hookMMStickerPickerCell; +@end + +NS_ASSUME_NONNULL_END diff --git a/WeChatPlugin/Sources/Hook/MMStickerPickerCell+hook.m b/WeChatPlugin/Sources/Hook/MMStickerPickerCell+hook.m new file mode 100644 index 00000000..11e6a6f7 --- /dev/null +++ b/WeChatPlugin/Sources/Hook/MMStickerPickerCell+hook.m @@ -0,0 +1,62 @@ +// +// NSObject+MMStickerPickerCell.m +// WeChatPlugin +// +// Created by TK on 2019/3/13. +// Copyright © 2019 tk. All rights reserved. +// + +#import "MMStickerPickerCell+hook.h" +#import "TKEmoticonManager.h" + +@implementation NSObject (MMStickerPickerCell) + ++ (void)hookMMStickerPickerCell { + tk_hookMethod(objc_getClass("MMStickerPickerCell"), @selector(rightMouseDown:), [self class], @selector(hook_rightMouseDown:)); +} + +- (void)hook_rightMouseDown:(id)theEvent { + [self hook_rightMouseDown:theEvent]; + if ([self.className isEqualToString:@"MMStickerPickerCell"]) { + MMStickerPickerCell *pickerCell = (MMStickerPickerCell *)self; + NSMenu *popupMenu = [[NSMenu alloc] init]; + popupMenu.delegate = pickerCell; + + NSMenuItem *preventRevokeItem = [[NSMenuItem alloc] initWithTitle:@"存储" action:@selector(pickerExportEmoji) keyEquivalent:@""]; + + NSMenuItem *copyItem = [[NSMenuItem alloc] initWithTitle:@"复制" action:@selector(pickerCopyEmoji) keyEquivalent:@""]; + [popupMenu addItems:@[preventRevokeItem,copyItem]]; + [NSMenu popUpContextMenu:popupMenu withEvent:theEvent forView:pickerCell]; + } +} + +- (void)pickerExportEmoji { + if (![self.className isEqualToString:@"MMStickerPickerCell"]) return; + + MMStickerPickerCell *currentCellView = (MMStickerPickerCell *)self; + MMEmoticonData *emotionData = currentCellView.emoticonData; + if (!emotionData.md5) { + return; + } + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + MMMainWindowController *mainWC = wechat.mainWindowController; + [[TKEmoticonManager shareManager] exportEmoticonWithMd5:emotionData.md5 window:mainWC.window]; +} + +- (void)pickerCopyEmoji { + if (![self.className isEqualToString:@"MMStickerPickerCell"]) return; + + MMStickerPickerCell *currentCellView = (MMStickerPickerCell *)self; + MMEmoticonData *emotionData = currentCellView.emoticonData; + if (!emotionData.md5) { + return; + } + [[TKEmoticonManager shareManager] copyEmoticonWithMd5:emotionData.md5]; + if([currentCellView.collectionView respondsToSelector:@selector(delegate)]) { + MMStickerCollectionViewController *stickerVC = [currentCellView.collectionView performSelector:@selector(delegate)]; + MMStickerPicker *picker = stickerVC.delegate; + [picker hide]; + } +} + +@end diff --git a/WeChatPlugin/Sources/Category/WeChat+hook.h b/WeChatPlugin/Sources/Hook/WeChat+hook.h similarity index 100% rename from WeChatPlugin/Sources/Category/WeChat+hook.h rename to WeChatPlugin/Sources/Hook/WeChat+hook.h diff --git a/WeChatPlugin/Sources/Hook/WeChat+hook.m b/WeChatPlugin/Sources/Hook/WeChat+hook.m new file mode 100644 index 00000000..b99dee5b --- /dev/null +++ b/WeChatPlugin/Sources/Hook/WeChat+hook.m @@ -0,0 +1,699 @@ +// +// WeChat+hook.m +// WeChatPlugin +// +// Created by TK on 2017/4/19. +// Copyright © 2017年 tk. All rights reserved. +// + +#import "WeChat+hook.h" +#import "WeChatPlugin.h" +#import "fishhook.h" +#import "TKIgnoreSessonModel.h" +#import "TKWebServerManager.h" +#import "TKMessageManager.h" +#import "TKAssistantMenuManager.h" +#import "TKAutoReplyModel.h" +#import "TKVersionManager.h" +#import "TKRemoteControlManager.h" +#import "TKDownloadWindowController.h" +#import "TKConstants.h" + +@implementation NSObject (WeChatHook) + ++ (void)hookWeChat { + // 微信撤回消息 + tk_hookMethod(objc_getClass("FFProcessReqsvrZZ"), @selector(FFToNameFavChatZZ:sessionMsgList:), [self class], @selector(hook_FFToNameFavChatZZ:sessionMsgList:)); + // 微信消息同步 + SEL syncBatchAddMsgsMethod = LargerOrEqualVersion(@"2.3.22") ? @selector(FFImgToOnFavInfoInfoVCZZ:isFirstSync:) : @selector(OnSyncBatchAddMsgs:isFirstSync:); + tk_hookMethod(objc_getClass("FFProcessReqsvrZZ"), syncBatchAddMsgsMethod, [self class], @selector(hook_OnSyncBatchAddMsgs:isFirstSync:)); + // 微信多开 + SEL hasWechatInstanceMethod = LargerOrEqualVersion(@"2.3.22") ? @selector(FFSvrChatInfoMsgWithImgZZ) : @selector(HasWechatInstance); + tk_hookClassMethod(objc_getClass("CUtility"), hasWechatInstanceMethod, [self class], @selector(hook_HasWechatInstance)); + // 窗口置顶 + tk_hookMethod(objc_getClass("NSWindow"), @selector(makeKeyAndOrderFront:), [self class], @selector(hook_makeKeyAndOrderFront:)); + // 登录逻辑 + tk_hookMethod(objc_getClass("AccountService"), @selector(onAuthOKOfUser:withSessionKey:withServerId:autoAuthKey:isAutoAuth:), [self class], @selector(hook_onAuthOKOfUser:withSessionKey:withServerId:autoAuthKey:isAutoAuth:)); + + // 自带浏览器打开链接 + tk_hookMethod(objc_getClass("MMURLHandler"), @selector(preHandleUrlStr:withMessage:), [self class], @selector(hook_preHandleUrlStr:withMessage:)); + + tk_hookMethod(objc_getClass("MMURLHandler"), @selector(startGetA8KeyWithURL:), [self class], @selector(hook_startGetA8KeyWithURL:)); + tk_hookMethod(objc_getClass("WeChat"), @selector(applicationDidFinishLaunching:), [self class], @selector(hook_applicationDidFinishLaunching:)); + + tk_hookMethod(objc_getClass("UserDefaultsService"), @selector(stringForKey:), [self class], @selector(hook_stringForKey:)); + + // 设置标记未读 + tk_hookMethod(objc_getClass("MMChatMessageViewController"), @selector(onClickSession), [self class], @selector(hook_onClickSession)); + tk_hookMethod(objc_getClass("MMSessionMgr"), @selector(onUnReadCountChange:), [self class], @selector(hook_onUnReadCountChange:)); + + // 远程语音控制 + tk_hookMethod(objc_getClass("MMVoiceTranslateMgr"), @selector(updateTranscribeVoiceMessage:voiceText:voiceToTextStatus:), [self class], @selector(hook_updateTranscribeVoiceMessage:voiceText:voiceToTextStatus:)); + + // 不支持的消息提示(小程序、转账等 + tk_hookClassMethod(objc_getClass("MMAppBrandMessageCellView"), @selector(makeAppBrandTableItemWithItem:), [self class], @selector(hook_makeAppBrandTableItemWithItem:)); + tk_hookClassMethod(objc_getClass("MMUnsupportedCellView"), @selector(makeUnsupportedTableItemWithItem:), [self class], @selector(hook_makeUnsupportedTableItemWithItem:)); + tk_hookClassMethod(objc_getClass("MMPayTransferCellView"), @selector(makePayTransferTableItemWithItem:), [self class], @selector(hook_makePayTransferTableItemWithItem:)); + + // 退群提示 + tk_hookMethod(objc_getClass("GroupStorage"), @selector(notifyModifyGroupContactsOnMainThread:), [self class], @selector(hook_notifyModifyGroupContactsOnMainThread:)); + tk_hookMethod(objc_getClass("MMSystemMessageCellView"), @selector(textView:clickedOnLink:atIndex:), [self class], @selector(hook_textView:clickedOnLink:atIndex:)); + tk_hookMethod(objc_getClass("MMSystemMessageCellView"), @selector(populateWithMessage:), [self class], @selector(hook_populateWithMessage:)); + // 替换沙盒路径 + rebind_symbols((struct rebinding[2]) { + { "NSSearchPathForDirectoriesInDomains", swizzled_NSSearchPathForDirectoriesInDomains, (void *)&original_NSSearchPathForDirectoriesInDomains }, + { "NSHomeDirectory", swizzled_NSHomeDirectory, (void *)&original_NSHomeDirectory } + }, 2); + + [self setup]; +} + ++ (void)setup { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + // 窗口置顶初始化 + [self setupWindowSticky]; + }); + [self checkPluginVersion]; + // 监听 NSWindow 最小化通知 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowsWillMiniaturize:) name:NSWindowWillMiniaturizeNotification object:nil]; +} + ++ (void)setupWindowSticky { + BOOL onTop = [[TKWeChatPluginConfig sharedConfig] onTop]; + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + wechat.mainWindowController.window.level = onTop == NSControlStateValueOn ? NSNormalWindowLevel+2 : NSNormalWindowLevel; +} + ++ (void)checkPluginVersion { + if ([[TKWeChatPluginConfig sharedConfig] forbidCheckVersion]) return; + + [[TKVersionManager shareManager] checkVersionFinish:^(TKVersionStatus status, NSString *message) { + if (status == TKVersionStatusNew) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert addButtonWithTitle:TKLocalizedString(@"assistant.update.alret.confirm")]; + [alert addButtonWithTitle:TKLocalizedString(@"assistant.update.alret.forbid")]; + [alert addButtonWithTitle:TKLocalizedString(@"assistant.update.alret.cancle")]; + [alert setMessageText:TKLocalizedString(@"assistant.update.alret.title")]; + [alert setInformativeText:message]; + NSModalResponse respose = [alert runModal]; + if (respose == NSAlertFirstButtonReturn) { + [[TKDownloadWindowController downloadWindowController] show]; + } else if (respose == NSAlertSecondButtonReturn) { + [[TKWeChatPluginConfig sharedConfig] setForbidCheckVersion:YES]; + } + }); + } + }]; +} + +/** + 登录界面-自动登录 + + @param btn 自动登录按钮 + */ +- (void)selectAutoLogin:(NSButton *)btn { + [[TKWeChatPluginConfig sharedConfig] setAutoLoginEnable:btn.state]; +} + +#pragma mark - hook 微信方法 +/** + hook 微信是否已启动 + + */ ++ (BOOL)hook_HasWechatInstance { + return NO; +} + +/** + hook 微信撤回消息 + + */ +- (void)hook_FFToNameFavChatZZ:(id)msgData sessionMsgList:(id)arg2 { + if (![[TKWeChatPluginConfig sharedConfig] preventRevokeEnable]) { + [self hook_FFToNameFavChatZZ:msgData sessionMsgList:arg2]; + return; + } + id msg = msgData; + if ([msgData isKindOfClass:objc_getClass("MessageData")]) { + msg = [msgData valueForKey:@"msgContent"]; + } + if ([msg rangeOfString:@" 180) { // 若是3分钟前的消息,则不进行自动回复与远程控制。 + return; + } + + [self autoReplyWithMsg:addMsg]; + + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + if ([addMsg.fromUserName.string isEqualToString:currentUserName] && + [addMsg.toUserName.string isEqualToString:currentUserName]) { + [self remoteControlWithMsg:addMsg]; + [self replySelfWithMsg:addMsg]; + } + }]; +} + +/** + hook 微信通知消息 + + */ +//- (id)hook_getNotificationContentWithMsgData:(MessageData *)arg1 { +// [[TKWeChatPluginConfig sharedConfig] setCurrentUserName:arg1.toUsrName]; +// return [self hook_getNotificationContentWithMsgData:arg1];; +//} +// +//- (void)hook_deliverNotification:(NSUserNotification *)notification { +// NSMutableDictionary *dict = [notification.userInfo mutableCopy]; +// dict[@"currnetName"] = [[TKWeChatPluginConfig sharedConfig] currentUserName]; +// notification.userInfo = dict; +// notification.hasReplyButton = YES; +// [self hook_deliverNotification:notification]; +//} +// +//- (void)hook_userNotificationCenter:(id)notificationCenter didActivateNotification:(NSUserNotification *)notification { +// NSString *chatName = notification.userInfo[@"ChatName"]; +// if (chatName && notification.response.string) { +// NSString *instanceUserName = [objc_getClass("CUtility") GetCurrentUserName]; +// NSString *currentUserName = notification.userInfo[@"currnetName"]; +// if ([instanceUserName isEqualToString:currentUserName]) { +// MessageService *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MessageService")]; +// [service SendTextMessage:currentUserName toUsrName:chatName msgText:notification.response.string atUserList:nil]; +// [[TKMessageManager shareManager] clearUnRead:chatName]; +// } +// } else { +// [self hook_userNotificationCenter:notificationCenter didActivateNotification:notification]; +// } +//} + +- (void)hook_onAuthOKOfUser:(id)arg1 withSessionKey:(id)arg2 withServerId:(id)arg3 autoAuthKey:(id)arg4 isAutoAuth:(BOOL)arg5 { + [self hook_onAuthOKOfUser:arg1 withSessionKey:arg2 withServerId:arg3 autoAuthKey:arg4 isAutoAuth:arg5]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if ([[TKWeChatPluginConfig sharedConfig] alfredEnable]) { + [[TKWebServerManager shareManager] startServer]; + } + NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu]; + NSMenuItem *pluginMenu = mainMenu.itemArray.lastObject; + pluginMenu.enabled = YES; + NSMenuItem *preventMenu = pluginMenu.submenu.itemArray.firstObject; + preventMenu.enabled = YES; + }); +} + +- (void)hook_startGetA8KeyWithURL:(id)arg1 { + MMURLHandler *urlHandler = (MMURLHandler *)self; + [urlHandler openURLWithDefault:arg1]; +} + +- (void)hook_applicationDidFinishLaunching:(id)arg1 { + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + if ([NSObject hook_HasWechatInstance]) { + wechat.hasAuthOK = YES; + } + if ([wechat respondsToSelector:@selector(checkForUpdatesInBackground)]) { + // 去除刚启动微信更新弹窗提醒 + tk_hookMethod(objc_getClass("WeChat"), @selector(checkForUpdatesInBackground), [self class], @selector(hook_checkForUpdatesInBackground)); + } + + [[TKAssistantMenuManager shareManager] initAssistantMenuItems]; + [self hook_applicationDidFinishLaunching:arg1]; +} + +// 强制用户退出时保存聊天记录 +- (id)hook_stringForKey:(NSString *)key { + if ([key isEqualToString:@"kMMUserDefaultsKey_SaveChatHistory"]) { + return @"1"; + } + return [self hook_stringForKey:key]; +} + +// 微信检测更新 +- (void)hook_checkForUpdatesInBackground { + if ([[TKWeChatPluginConfig sharedConfig] checkUpdateWechatEnable]) { + [self hook_checkForUpdatesInBackground]; + } +} + +// 是否使用微信浏览器 +- (BOOL)hook_preHandleUrlStr:(id)arg1 withMessage:(id)arg2 { + if ([[TKWeChatPluginConfig sharedConfig] systemBrowserEnable]) { + MMURLHandler *urlHander = [objc_getClass("MMURLHandler") defaultHandler]; + if ([urlHander respondsToSelector:@selector(openURLWithDefault:)]) { // 2.3.22 + [urlHander openURLWithDefault:arg1]; + return YES; + } else if ([urlHander respondsToSelector:@selector(openURLWithDefault:useA8Key:)]) { // 2.3.30 + [urlHander openURLWithDefault:arg1 useA8Key:YES]; + return YES; + } + } + return [self hook_preHandleUrlStr:arg1 withMessage:arg2]; +} + +// 设置标记未读 +- (void)hook_onClickSession { + [self hook_onClickSession]; + MMChatMessageViewController *chatMessageVC = (MMChatMessageViewController *)self; + NSMutableSet *unreadSessionSet = [[TKWeChatPluginConfig sharedConfig] unreadSessionSet]; + if ([unreadSessionSet containsObject:chatMessageVC.chatContact.m_nsUsrName]) { + [unreadSessionSet removeObject:chatMessageVC.chatContact.m_nsUsrName]; + [[TKMessageManager shareManager] clearUnRead:chatMessageVC.chatContact.m_nsUsrName]; + } +} + +- (void)hook_onUnReadCountChange:(id)arg1 { + NSMutableSet *unreadSessionSet = [[TKWeChatPluginConfig sharedConfig] unreadSessionSet]; + if ([unreadSessionSet containsObject:arg1]) { + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + MMSessionInfo *sessionInfo = [sessionMgr sessionInfoByUserName:arg1]; + sessionInfo.m_uUnReadCount++; + } + [self hook_onUnReadCountChange:arg1]; +} + +// 拦截微信语音转换,用于语音远程控制 +- (void)hook_updateTranscribeVoiceMessage:(MessageData *)arg1 voiceText:(id)arg2 voiceToTextStatus:(unsigned int)arg3 { + [self hook_updateTranscribeVoiceMessage:arg1 voiceText:arg2 voiceToTextStatus:arg3]; + dispatch_async(dispatch_get_main_queue(), ^{ + if ([arg1 isSendFromSelf]) { + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + if ([arg1.toUsrName isEqualToString:currentUserName]) { + [TKRemoteControlManager executeRemoteControlCommandWithVoiceMsg:arg2]; + } + } + }); +} + +#pragma mark - hook 系统方法 +- (void)hook_makeKeyAndOrderFront:(nullable id)sender { + BOOL top = [[TKWeChatPluginConfig sharedConfig] onTop]; + ((NSWindow *)self).level = top == NSControlStateValueOn ? NSNormalWindowLevel+2 : NSNormalWindowLevel; + + [self hook_makeKeyAndOrderFront:sender]; +} + +#pragma mark - Other +/** + 自动回复 + + @param addMsg 接收的消息 + */ +- (void)autoReplyWithMsg:(AddMsg *)addMsg { + // addMsg.msgType != 49 + if (![[TKWeChatPluginConfig sharedConfig] autoReplyEnable]) return; + if (addMsg.msgType != 1 && addMsg.msgType != 3) return; + + NSString *userName = addMsg.fromUserName.string; + + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + WCContactData *msgContact = [sessionMgr getSessionContact:userName]; + if ([msgContact isBrandContact] || [msgContact isSelf]) { + // 该消息为公众号或者本人发送的消息 + return; + } + NSArray *autoReplyModels = [[TKWeChatPluginConfig sharedConfig] autoReplyModels]; + [autoReplyModels enumerateObjectsUsingBlock:^(TKAutoReplyModel *model, NSUInteger idx, BOOL * _Nonnull stop) { + if (!model.enable) return; + if (!model.replyContent || model.replyContent.length == 0) return; + + if (model.enableSpecificReply) { + if ([model.specificContacts containsObject:userName]) { + [self replyWithMsg:addMsg model:model]; + } + return; + } + if ([addMsg.fromUserName.string containsString:@"@chatroom"] && !model.enableGroupReply) return; + if (![addMsg.fromUserName.string containsString:@"@chatroom"] && !model.enableSingleReply) return; + + [self replyWithMsg:addMsg model:model]; + }]; +} + +- (void)replyWithMsg:(AddMsg *)addMsg model:(TKAutoReplyModel *)model { + NSString *msgContent = addMsg.content.string; + if ([addMsg.fromUserName.string containsString:@"@chatroom"]) { + msgContent = [msgContent substringFromString:@":\n"]; + } + + NSArray *replyArray = [model.replyContent componentsSeparatedByString:@"|"]; + int index = arc4random() % replyArray.count; + NSString *randomReplyContent = replyArray[index]; + NSInteger delayTime = model.enableDelay ? model.delayTime : 0; + + if (model.enableRegex) { + NSString *regex = model.keyword; + NSError *error; + NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:&error]; + if (error) return; + NSInteger count = [regular numberOfMatchesInString:msgContent options:NSMatchingReportCompletion range:NSMakeRange(0, msgContent.length)]; + if (count > 0) { + [[TKMessageManager shareManager] sendTextMessage:randomReplyContent toUsrName:addMsg.fromUserName.string delay:delayTime]; + } + } else { + NSArray * keyWordArray = [model.keyword componentsSeparatedByString:@"|"]; + [keyWordArray enumerateObjectsUsingBlock:^(NSString *keyword, NSUInteger idx, BOOL * _Nonnull stop) { + if ([keyword isEqualToString:@"*"] || [msgContent isEqualToString:keyword]) { + [[TKMessageManager shareManager] sendTextMessage:randomReplyContent toUsrName:addMsg.fromUserName.string delay:delayTime]; + *stop = YES; + } + }]; + } +} + +/** + 远程控制 + + @param addMsg 接收的消息 + */ +- (void)remoteControlWithMsg:(AddMsg *)addMsg { + NSDate *now = [NSDate date]; + NSTimeInterval nowSecond = now.timeIntervalSince1970; + if (nowSecond - addMsg.createTime > 10) { // 若是10秒前的消息,则不进行远程控制。 + return; + } + if (addMsg.msgType == 1 || addMsg.msgType == 3) { + [TKRemoteControlManager executeRemoteControlCommandWithMsg:addMsg.content.string]; + } else if (addMsg.msgType == 34) { + // 此为语音消息 + FFProcessReqsvrZZ *msgService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + MessageData *msgData = [msgService GetMsgData:addMsg.fromUserName.string svrId:addMsg.newMsgId]; + dispatch_async(dispatch_get_main_queue(), ^{ + MMVoiceTranslateMgr *voiceMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMVoiceTranslateMgr")]; + [voiceMgr doTranslate:msgData isAuto:YES]; + }); + } +} + +- (void)replySelfWithMsg:(AddMsg *)addMsg { + if (addMsg.msgType != 1 && addMsg.msgType != 3) return; + + if ([addMsg.content.string isEqualToString:TKLocalizedString(@"assistant.remoteControl.getList")]) { + NSString *callBack = [TKRemoteControlManager remoteControlCommandsString]; + [[TKMessageManager shareManager] sendTextMessageToSelf:callBack]; + } +} + +- (void)windowsWillMiniaturize:(NSNotification *)notification { + NSObject *window = notification.object; + ((NSWindow *)window).level =NSNormalWindowLevel; +} + +#pragma mark - 不支持的消息展示 ++ (id)hook_makePayTransferTableItemWithItem:(MMMessageTableItem *)arg1 { + MMMessageTableItem *tableItem = [self hook_makePayTransferTableItemWithItem:arg1]; + + NSString *feeDesc = tableItem.message.m_oWCPayInfoItem.m_nsFeeDesc; + if (feeDesc.length > 0) { + tableItem.message.msgContent = [NSString stringWithFormat:@"%@\n金额:%@元",tableItem.message.msgContent,feeDesc]; + } + return tableItem; + +} ++ (id)hook_makeAppBrandTableItemWithItem:(MMMessageTableItem *)arg1 { + MMMessageTableItem *tableItem = [self hook_makeAppBrandTableItemWithItem:arg1]; + tableItem.message = [self resetMsgContent:tableItem.message]; + return tableItem; +} + ++ (id)hook_makeUnsupportedTableItemWithItem:(MMMessageTableItem *)arg1 { + MMMessageTableItem *tableItem = [self hook_makeUnsupportedTableItemWithItem:arg1]; + tableItem.message = [self resetMsgContent:tableItem.message]; + return tableItem; +} + ++ (MessageData *)resetMsgContent:(MessageData *)msgData { + if (msgData.m_nsTitle.length > 0) { + NSString *from = @"内容"; + if (msgData.m_nsSourceDisplayname.length > 0) { + from = msgData.m_nsSourceDisplayname; + } else if (msgData.m_nsAppName.length > 0) { + from = msgData.m_nsAppName; + } + msgData.msgContent = [msgData.msgContent stringByAppendingFormat:@"\n%@:%@", from, msgData.m_nsTitle]; + } + + return msgData; +} + +#pragma mark - 退群处理 +- (void)hook_notifyModifyGroupContactsOnMainThread:(NSArray *)arg1 { + [self hook_notifyModifyGroupContactsOnMainThread:arg1]; + if (![TKWeChatPluginConfig sharedConfig].memberExitMonitoringEnable) { + return; + } + GroupStorage *contactStorage = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("GroupStorage")]; + [arg1 enumerateObjectsUsingBlock:^(WCContactData * obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSDictionary *m_dicData = [obj.m_chatRoomData valueForKey:@"m_dicData"]; + [m_dicData.allKeys enumerateObjectsUsingBlock:^(NSString *userName, NSUInteger idx, BOOL * _Nonnull stop) { + if (![obj containsMember:userName]) { + NSString *localKey = [NSString stringWithFormat:@"%@-%@",obj.m_nsUsrName, userName]; + NSMutableDictionary *quitChatRoomMemberDict = [TKWeChatPluginConfig sharedConfig].quitChatRoomMemberDict; + NSString *saveDateKey = quitChatRoomMemberDict[localKey]; + BOOL canShowQuitTip = NO; + if (saveDateKey) { + NSDate *currentDate = [NSDate date]; + NSDate *lastSaveDate = [[TKUtility getDateFormater] dateFromString:saveDateKey]; + NSTimeInterval days = [currentDate timeIntervalSinceDate:lastSaveDate] / (3600.0 * 24); + canShowQuitTip = days > kTKMemberQuitDayInterval; + } else { + canShowQuitTip = YES; + } + if (canShowQuitTip) { + [TKWeChatPluginConfig sharedConfig].quitChatRoomMemberDict[localKey] = [TKUtility getOnlyDateString]; + [[TKWeChatPluginConfig sharedConfig] saveQuitChatRoomMemberDict]; + WCContactData *quitChatroomUser = [contactStorage GetGroupMemberContact:userName]; + NSString *msgContent = [NSString stringWithFormat:@"%@ %@ \n %@%@",quitChatroomUser.m_nsNickName, WXLocalizedString(@"ChatInspector.LeaveChat"),WXLocalizedString(@"Contacts.UserNameKeyLabel"),userName]; + FFProcessReqsvrZZ *msgService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + MessageData *newMsgData = ({ + MessageData *msg = [[objc_getClass("MessageData") alloc] initWithMsgType:0x2710]; + [msg setFromUsrName:userName]; + [msg setToUsrName:obj.m_nsUsrName]; + [msg setM_nsAppName:userName]; + [msg setMsgStatus:4]; + [msg setMsgContent:msgContent]; + [msg setMsgCreateTime:[[NSDate date] timeIntervalSince1970]]; + + msg; + }); + [msgService AddLocalMsg:obj.m_nsUsrName msgData:newMsgData]; + } + } + }]; + }]; +} + +- (BOOL)hook_textView:(NSTextView *)arg1 clickedOnLink:(NSString *)arg2 atIndex:(unsigned long long)arg3 { + if ([arg2 containsString:kTKScrollToMessageKey]) { + MMSystemMessageCellView *currentCellView = (MMSystemMessageCellView *)self; + NSString *localIDStr = [arg2 substringFromString:kTKScrollToMessageKey]; + NSUInteger localId = [localIDStr integerValue]; + if (localId > 0) { + if ([currentCellView.delegate isKindOfClass:objc_getClass("MMChatMessageViewController")]) { + MMChatMessageViewController *vc = currentCellView.delegate; + if ([vc respondsToSelector:@selector(showLocatedMessage:)]) { + [vc showLocatedMessage:localId]; + } else if ([vc respondsToSelector:@selector(showLocatedMessage:needHighLighted:)]) { + [vc showLocatedMessage:localId needHighLighted:YES]; + } + } + } + return YES; + } else if ([arg2 containsString:kTKShowMembeContactProfileKey]) { + NSString *usrName = [arg2 substringFromString:kTKShowMembeContactProfileKey]; + if (usrName.length) { + MMSystemMessageCellView *currentCellView = (MMSystemMessageCellView *)self; + MMMessageTableItem *item = currentCellView.messageTableItem; + MessageData *msgData = item.message; + GroupStorage *contactStorage = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("GroupStorage")]; + WCContactData *contactData = [objc_getClass("CUtility") GetContactByUsrName:usrName]; + if (!contactData) { + contactData = [contactStorage GetGroupMemberContact:usrName]; + } + if (contactData) { + MMContactProfileController *vc = [[objc_getClass("MMContactProfileController") alloc] initWithNibName:@"MMContactProfileController" bundle:0]; + vc.groupName = msgData.fromUsrName; + vc.relativeToRect = CGRectMake(150, 11, 200, 50); + vc.preferredEdge = 2; + vc.contactData = contactData; + [vc showInView:self]; + return YES; + } + } + } + + return [self hook_textView:arg1 clickedOnLink:arg2 atIndex:arg3]; +} + +- (void)hook_populateWithMessage:(id)arg1 { + [self hook_populateWithMessage:arg1]; + + MMSystemMessageCellView *currentCellView = (MMSystemMessageCellView *)self; + MMMessageTableItem *item = currentCellView.messageTableItem; + MessageData *msgData = item.message; + NSString *msgContent = msgData.msgContent; + if ([msgContent containsString:WXLocalizedString(@"ChatInspector.LeaveChat")] && + [msgContent containsString:WXLocalizedString(@"Contacts.UserNameKeyLabel")]) { + NSMutableAttributedString *attStr = [currentCellView.msgTextView.attributedString mutableCopy]; + NSString *displayMsgContent = attStr.string; + NSString *userName = [displayMsgContent substringToString:WXLocalizedString(@"ChatInspector.LeaveChat")]; + NSString *userId = [displayMsgContent substringFromString:WXLocalizedString(@"Contacts.UserNameKeyLabel")]; + + if (userName && userId) { + // 将用户昵称标记超链接 + NSRange userRange = [displayMsgContent rangeOfString:userName]; + if (userRange.length > 0 && userId) { + NSString *linkValue = [kTKShowMembeContactProfileKey stringByAppendingString:userId]; + [attStr addAttribute:NSLinkAttributeName value:linkValue range:userRange]; + } + // 删除其他信息,不显示微信号 + NSString *otherMsg = [displayMsgContent substringFromString:WXLocalizedString(@"ChatInspector.LeaveChat")]; + if (otherMsg) { + NSRange otherMsgRange = [displayMsgContent rangeOfString:otherMsg]; + [attStr deleteCharactersInRange:otherMsgRange]; + } + currentCellView.msgTextView.textStorage.attributedString = attStr; + } + } else if ([msgContent containsString:kTKRevokeLocationKey]) { + NSMutableAttributedString *attStr = [currentCellView.msgTextView.attributedString mutableCopy]; + NSString *displayMsgContent = attStr.string; + NSString *originMsg = [displayMsgContent substringFromString:TKLocalizedString(@"assistant.revoke.otherMessage.tip")]; + if (originMsg) { + // 将撤回内容标记超链接 + NSRange msgRange = [displayMsgContent rangeOfString:originMsg]; + if (msgRange.length > 0) { + NSString *localID = [displayMsgContent substringFromString:kTKRevokeLocationKey]; + if (localID) { + NSString *linkValue = [kTKScrollToMessageKey stringByAppendingString:localID]; + [attStr addAttribute:NSLinkAttributeName value:linkValue range:msgRange]; + } + } + } + // 删除其他信息,不显示微信号 + NSRange tipRange = [attStr.string rangeOfString:kTKRevokeLocationKey]; + if (tipRange.length > 0) { + NSString *tipAndLocalId = [attStr.string substringFromIndex:tipRange.location]; + NSRange localIdrange = [attStr.string rangeOfString:tipAndLocalId]; + if (localIdrange.length > 0) { + if (localIdrange.length + localIdrange.location > attStr.length) { + localIdrange.length = attStr.length - localIdrange.location; + } + [attStr deleteCharactersInRange:localIdrange]; + } + currentCellView.msgTextView.textStorage.attributedString = attStr; + } + } + NSMutableArray *names = [TKUtility getMemberNameWithMsgContent:msgContent]; + if (names.count > 0) { + NSMutableAttributedString *attStr = [currentCellView.msgTextView.attributedString mutableCopy]; + NSString *displayMsgContent = attStr.string; + GroupStorage *contactStorage = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("GroupStorage")]; + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + WCContactData *group = [sessionMgr getSessionContact:msgData.fromUsrName]; + NSArray *memberList = [contactStorage GetGroupMemberListWithGroupContact:group limit:500 filterSelf:YES]; + + [memberList enumerateObjectsUsingBlock:^(WCContactData *obj, NSUInteger idx, BOOL * _Nonnull stop) { + __block NSString *needRemoveName = nil; + [names enumerateObjectsUsingBlock:^(NSString *name, NSUInteger idx, BOOL * _Nonnull subStop) { + if ( [[obj groupChatDisplayNameInGroup:msgData.fromUsrName] isEqualToString:name] || + [obj.m_nsNickName isEqualToString:name] || + [obj.m_nsRemark isEqual:name]) { + NSRange nameRange = [displayMsgContent rangeOfString:name]; + NSString *value = [NSString stringWithFormat:@"%@%@",kTKShowMembeContactProfileKey,obj.m_nsUsrName]; + [attStr addAttribute:NSLinkAttributeName value:value range:nameRange]; + needRemoveName = name; + *subStop = YES; + } + }]; + if (needRemoveName) { + [names removeObject:needRemoveName]; + } + if (names.count == 0) { + *stop = YES; + } + }]; + currentCellView.msgTextView.textStorage.attributedString = attStr; + } +} + +#pragma mark - 替换 NSSearchPathForDirectoriesInDomains & NSHomeDirectory +static NSArray *(*original_NSSearchPathForDirectoriesInDomains)(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde); + +NSArray *swizzled_NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde) { + NSMutableArray *paths = [original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde) mutableCopy]; + NSString *sandBoxPath = [NSString stringWithFormat:@"%@/Library/Containers/com.tencent.xinWeChat/Data",original_NSHomeDirectory()]; + + [paths enumerateObjectsUsingBlock:^(NSString *filePath, NSUInteger idx, BOOL * _Nonnull stop) { + NSRange range = [filePath rangeOfString:original_NSHomeDirectory()]; + if (range.length > 0) { + NSMutableString *newFilePath = [filePath mutableCopy]; + [newFilePath replaceCharactersInRange:range withString:sandBoxPath]; + paths[idx] = newFilePath; + } + }]; + + return paths; +} + +static NSString *(*original_NSHomeDirectory)(void); + +NSString *swizzled_NSHomeDirectory(void) { + return [NSString stringWithFormat:@"%@/Library/Containers/com.tencent.xinWeChat/Data",original_NSHomeDirectory()]; +} + +@end diff --git a/WeChatPlugin/Sources/Managers/TKAssistantMenuManager.h b/WeChatPlugin/Sources/Managers/TKAssistantMenuManager.h new file mode 100644 index 00000000..9b347788 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKAssistantMenuManager.h @@ -0,0 +1,16 @@ +// +// TKAssistantMenuManager.h +// WeChatPlugin +// +// Created by TK on 2018/4/24. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface TKAssistantMenuManager : NSObject + ++ (instancetype)shareManager; +- (void)initAssistantMenuItems; + +@end diff --git a/WeChatPlugin/Sources/Managers/TKAssistantMenuManager.m b/WeChatPlugin/Sources/Managers/TKAssistantMenuManager.m new file mode 100644 index 00000000..a48bc1b6 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKAssistantMenuManager.m @@ -0,0 +1,332 @@ +// +// TKAssistantMenuManager.m +// WeChatPlugin +// +// Created by TK on 2018/4/24. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKAssistantMenuManager.h" +#import "TKRemoteControlManager.h" +#import "TKAutoReplyWindowController.h" +#import "TKRemoteControlWindowController.h" +#import "TKVersionManager.h" +#import "NSMenuItem+Action.h" +#import "TKDownloadWindowController.h" +#import "TKAboutWindowController.h" +#import "TKWebServerManager.h" + +static char tkAutoReplyWindowControllerKey; // 自动回复窗口的关联 key +static char tkRemoteControlWindowControllerKey; // 远程控制窗口的关联 key +static char tkAboutWindowControllerKey; // 关于窗口的关联 key + +@implementation TKAssistantMenuManager + ++ (instancetype)shareManager { + static id manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[self alloc] init]; + }); + return manager; +} + +- (void)initAssistantMenuItems { + // 消息防撤回 + NSMenuItem *preventRevokeItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.revoke") + action:@selector(onPreventRevoke:) + target:self + keyEquivalent:@"t" + state:[[TKWeChatPluginConfig sharedConfig] preventRevokeEnable]]; + if ([[TKWeChatPluginConfig sharedConfig] preventRevokeEnable]) { + // 防撤回自己 + NSMenuItem *preventSelfRevokeItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.revokeSelf") + action:@selector(onPreventSelfRevoke:) + target:self + keyEquivalent:@"" + state:[[TKWeChatPluginConfig sharedConfig] preventSelfRevokeEnable]]; + + NSMenu *subPreventMenu = [[NSMenu alloc] initWithTitle:TKLocalizedString(@"assistant.menu.revoke")]; + [subPreventMenu addItems:@[preventSelfRevokeItem]]; + preventRevokeItem.submenu = subPreventMenu; + } + + // 自动回复 + NSMenuItem *autoReplyItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.autoReply") + action:@selector(onAutoReply:) + target:self + keyEquivalent:@"k" + state:[[TKWeChatPluginConfig sharedConfig] autoReplyEnable]]; + // 远程控制 + NSMenuItem *commandItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.remoteControl") + action:@selector(onRemoteControl:) + target:self + keyEquivalent:@"C" + state:0]; + // 微信窗口置顶 + NSMenuItem *onTopItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.windowSticky") + action:@selector(onWechatOnTopControl:) + target:self + keyEquivalent:@"D" + state:[[TKWeChatPluginConfig sharedConfig] onTop]]; + + // 使用自带浏览器 + NSMenuItem *enableSystemBrowserItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.systemBrowser") + action:@selector(onEnableSystemBrowser:) + target:self + keyEquivalent:@"B" + state:[[TKWeChatPluginConfig sharedConfig] systemBrowserEnable]]; + + // 退群监控 + NSMenuItem *memberExitMonitoringItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.memberExitMonitoring") + action:@selector(onEnablememberExitMonitoring:) + target:self + keyEquivalent:@"" + state:[[TKWeChatPluginConfig sharedConfig] memberExitMonitoringEnable]]; + + // 是否禁止微信开启时检测新版本 + NSMenuItem *forbidCheckUpdateItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.forbidCheck") + action:@selector(onForbidWeChatCheckUpdate:) + target:self + keyEquivalent:@"" + state:![[TKWeChatPluginConfig sharedConfig] checkUpdateWechatEnable]]; + + // 开启 Alfred + NSMenuItem *enableAlfredItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.enableAlfred") + action:@selector(onEnableaAlfred:) + target:self + keyEquivalent:@"" + state:[[TKWeChatPluginConfig sharedConfig] alfredEnable]]; + + // 更新小助手 + NSMenuItem *updatePluginItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.updateAssistant") + action:@selector(onUpdatePluginControl:) + target:self + keyEquivalent:@"" + state:0]; + // 关于小助手 + NSMenuItem *abountPluginItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.aboutAssistant") + action:@selector(onAboutPluginControl:) + target:self + keyEquivalent:@"" + state:0]; + + // 关于小助手 + NSMenuItem *pluginItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.other") + action:@selector(onAboutPluginControl:) + target:self + keyEquivalent:@"" + state:0]; + NSMenu *subPluginMenu = [[NSMenu alloc] initWithTitle:TKLocalizedString(@"assistant.menu.other")]; + [subPluginMenu addItems:@[enableAlfredItem, + updatePluginItem, + abountPluginItem]]; + + NSMenu *subMenu = [[NSMenu alloc] initWithTitle:TKLocalizedString(@"assistant.menu.title")]; + + [subMenu addItems:@[preventRevokeItem, + autoReplyItem, + commandItem, + onTopItem, + enableSystemBrowserItem, + memberExitMonitoringItem, + pluginItem + ]]; + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + if ([wechat respondsToSelector:@selector(checkForUpdatesInBackground)]) { + [subMenu insertItem:forbidCheckUpdateItem atIndex:6]; + } + [subMenu setSubmenu:subPluginMenu forItem:pluginItem]; + NSMenuItem *menuItem = [[NSMenuItem alloc] init]; + [menuItem setTitle:TKLocalizedString(@"assistant.menu.title")]; + [menuItem setSubmenu:subMenu]; + menuItem.target = self; + [[[NSApplication sharedApplication] mainMenu] addItem:menuItem]; + menuItem.enabled = NO; + + [self addObserverWeChatConfig]; +} + +#pragma mark - 监听 WeChatPluginConfig + +- (void)addObserverWeChatConfig { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(weChatPluginConfigAutoReplyChange) name:NOTIFY_AUTO_REPLY_CHANGE object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(weChatPluginConfigPreventRevokeChange) name:NOTIFY_PREVENT_REVOKE_CHANGE object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(weChatPluginConfigAutoAuthChange) name:NOTIFY_AUTO_AUTH_CHANGE object:nil]; +} + +- (void)weChatPluginConfigAutoReplyChange { + TKWeChatPluginConfig *shareConfig = [TKWeChatPluginConfig sharedConfig]; + shareConfig.autoReplyEnable = !shareConfig.autoReplyEnable; + [self changePluginMenuItemWithIndex:1 state:shareConfig.autoReplyEnable]; +} + +- (void)weChatPluginConfigPreventRevokeChange { + TKWeChatPluginConfig *shareConfig = [TKWeChatPluginConfig sharedConfig]; + shareConfig.preventRevokeEnable = !shareConfig.preventRevokeEnable; + [self changePluginMenuItemWithIndex:0 state:shareConfig.preventRevokeEnable]; +} + +- (void)weChatPluginConfigAutoAuthChange { + TKWeChatPluginConfig *shareConfig = [TKWeChatPluginConfig sharedConfig]; + shareConfig.autoAuthEnable = !shareConfig.autoAuthEnable; + [self changePluginMenuItemWithIndex:5 state:shareConfig.autoAuthEnable]; +} + +- (void)changePluginMenuItemWithIndex:(NSInteger)index state:(NSControlStateValue)state { + NSMenuItem *pluginMenuItem = [[[[NSApplication sharedApplication] mainMenu] itemArray] lastObject]; + NSMenuItem *item = pluginMenuItem.submenu.itemArray[index]; + item.state = state; +} + +#pragma mark - menuItem 的点击事件 +/** + 菜单栏-微信小助手-消息防撤回 设置 + + @param item 消息防撤回的item + */ +- (void)onPreventRevoke:(NSMenuItem *)item { + item.state = !item.state; + [[TKWeChatPluginConfig sharedConfig] setPreventRevokeEnable:item.state]; + if (item.state) { + // 防撤回自己 + NSMenuItem *preventSelfRevokeItem = [NSMenuItem menuItemWithTitle:TKLocalizedString(@"assistant.menu.revokeSelf") + action:@selector(onPreventSelfRevoke:) + target:self + keyEquivalent:@"" + state:[[TKWeChatPluginConfig sharedConfig] preventSelfRevokeEnable]]; + + NSMenu *subPreventMenu = [[NSMenu alloc] initWithTitle:TKLocalizedString(@"assistant.menu.revoke")]; + [subPreventMenu addItems:@[preventSelfRevokeItem]]; + item.submenu = subPreventMenu; + } else { + item.submenu = nil; + } + +} + +/** + 菜单栏-微信小助手-消息防撤回-拦截自己消息 设置 + + @param item 消息防撤回的item + */ +- (void)onPreventSelfRevoke:(NSMenuItem *)item { + item.state = !item.state; + [[TKWeChatPluginConfig sharedConfig] setPreventSelfRevokeEnable:item.state]; +} + +/** + 菜单栏-微信小助手-自动回复 设置 + + @param item 自动回复设置的item + */ +- (void)onAutoReply:(NSMenuItem *)item { + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + TKAutoReplyWindowController *autoReplyWC = objc_getAssociatedObject(wechat, &tkAutoReplyWindowControllerKey); + + if (!autoReplyWC) { + autoReplyWC = [[TKAutoReplyWindowController alloc] initWithWindowNibName:@"TKAutoReplyWindowController"]; + objc_setAssociatedObject(wechat, &tkAutoReplyWindowControllerKey, autoReplyWC, OBJC_ASSOCIATION_RETAIN); + } + [autoReplyWC show]; +} + +/** + 菜单栏-帮助-远程控制 MAC OS 设置 + + @param item 远程控制的item + */ +- (void)onRemoteControl:(NSMenuItem *)item { + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + TKRemoteControlWindowController *remoteControlWC = objc_getAssociatedObject(wechat, &tkRemoteControlWindowControllerKey); + + if (!remoteControlWC) { + remoteControlWC = [[TKRemoteControlWindowController alloc] initWithWindowNibName:@"TKRemoteControlWindowController"]; + objc_setAssociatedObject(wechat, &tkRemoteControlWindowControllerKey, remoteControlWC, OBJC_ASSOCIATION_RETAIN); + } + + [remoteControlWC show]; +} + +/** + 菜单栏-微信小助手-微信窗口置顶 + + @param item 窗口置顶的 item + */ +- (void)onWechatOnTopControl:(NSMenuItem *)item { + item.state = !item.state; + [[TKWeChatPluginConfig sharedConfig] setOnTop:item.state]; + + NSArray *windows = [[NSApplication sharedApplication] windows]; + [windows enumerateObjectsUsingBlock:^(NSWindow *window, NSUInteger idx, BOOL * _Nonnull stop) { + if (![window.className isEqualToString:@"NSStatusBarWindow"]) { + window.level = item.state == NSControlStateValueOn ? NSNormalWindowLevel+2 : NSNormalWindowLevel; + } + }]; +} + +/** + 菜单栏-微信小助手-更新小助手 + + @param item 更新小助手的 item + */ +- (void)onUpdatePluginControl:(NSMenuItem *)item { + [[TKWeChatPluginConfig sharedConfig] setForbidCheckVersion:NO]; + [[TKVersionManager shareManager] checkVersionFinish:^(TKVersionStatus status, NSString *message) { + if (status == TKVersionStatusNew) { + NSAlert *alert = [[NSAlert alloc] init]; + [alert addButtonWithTitle:TKLocalizedString(@"assistant.update.alret.confirm")]; + [alert addButtonWithTitle:TKLocalizedString(@"assistant.update.alret.cancle")]; + [alert setMessageText:TKLocalizedString(@"assistant.update.alret.title")]; + [alert setInformativeText:message]; + NSModalResponse respose = [alert runModal]; + if (respose == NSAlertFirstButtonReturn) { + [[TKDownloadWindowController downloadWindowController] show]; + } + } else { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:TKLocalizedString(@"assistant.update.alret.latest")]; + [alert setInformativeText:message]; + [alert runModal]; + } + }]; +} + +- (void)onEnableaAlfred:(NSMenuItem *)item { + item.state = !item.state; + if (item.state) { + [[TKWebServerManager shareManager] startServer]; + } else { + [[TKWebServerManager shareManager] endServer]; + } + [[TKWeChatPluginConfig sharedConfig] setAlfredEnable:item.state]; +} + +- (void)onEnableSystemBrowser:(NSMenuItem *)item { + item.state = !item.state; + [[TKWeChatPluginConfig sharedConfig] setSystemBrowserEnable:item.state]; +} + +- (void)onEnablememberExitMonitoring:(NSMenuItem *)item { + item.state = !item.state; + [[TKWeChatPluginConfig sharedConfig] setMemberExitMonitoringEnable:item.state]; +} + +- (void)onForbidWeChatCheckUpdate:(NSMenuItem *)item { + item.state = !item.state; + [[TKWeChatPluginConfig sharedConfig] setCheckUpdateWechatEnable:!item.state]; +} + +- (void)onAboutPluginControl:(NSMenuItem *)item { + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + TKAboutWindowController *remoteControlWC = objc_getAssociatedObject(wechat, &tkAboutWindowControllerKey); + + if (!remoteControlWC) { + remoteControlWC = [[TKAboutWindowController alloc] initWithWindowNibName:@"TKAboutWindowController"]; + objc_setAssociatedObject(wechat, &tkAboutWindowControllerKey, remoteControlWC, OBJC_ASSOCIATION_RETAIN); + } + + [remoteControlWC show]; +} + +@end diff --git a/WeChatPlugin/Sources/Managers/TKCacheManager.h b/WeChatPlugin/Sources/Managers/TKCacheManager.h new file mode 100644 index 00000000..000f9176 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKCacheManager.h @@ -0,0 +1,20 @@ +// +// TKCacheManager.h +// WeChatPlugin +// +// Created by TK on 2018/8/3. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface TKCacheManager : NSObject + ++ (instancetype)shareManager; + +- (BOOL)fileExistsWithName:(NSString *)fileName; +- (NSString *)filePathWithName:(NSString *)fileName; +- (NSString *)cacheEmotionMessage:(MessageData *)emotionMsg; +- (NSString *)cacheAvatarWithContact:(WCContactData *)contact; + +@end diff --git a/WeChatPlugin/Sources/Managers/TKCacheManager.m b/WeChatPlugin/Sources/Managers/TKCacheManager.m new file mode 100644 index 00000000..efc40c20 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKCacheManager.m @@ -0,0 +1,156 @@ +// +// TKCacheManager.m +// WeChatPlugin +// +// Created by TK on 2018/8/3. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKCacheManager.h" + +@interface TKCacheManager () + +@property (nonatomic, copy) NSString *cacheDirectory; +@property (nonatomic, strong) NSMutableSet *emotionSet; +@property (nonatomic, strong) NSMutableSet *avatarSet; +@end + +@implementation TKCacheManager + ++ (instancetype)shareManager { + static TKCacheManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[TKCacheManager alloc] init]; + }); + return manager; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.cacheDirectory = [NSTemporaryDirectory() stringByAppendingString:@"TKWeChatPlugin/"]; + NSFileManager *manager = [NSFileManager defaultManager]; + if (![manager fileExistsAtPath:self.cacheDirectory]) { + [manager createDirectoryAtPath:self.cacheDirectory withIntermediateDirectories:YES attributes:nil error:nil]; + } + + MMExtensionCenter *extensionCenter = [[objc_getClass("MMServiceCenter") defaultCenter] getService:[objc_getClass("MMExtensionCenter") class]]; + MMExtension *extension = [extensionCenter getExtension:@protocol(EmoticonDownloadMgrExt)]; + if (extension) { + [extension registerExtension:self]; + } + + self.emotionSet = [NSMutableSet set]; + self.avatarSet = [NSMutableSet set]; + } + return self; +} + +- (void)dealloc { + MMExtensionCenter *extensionCenter = [[objc_getClass("MMServiceCenter") defaultCenter] getService:[objc_getClass("MMExtensionCenter") class]]; + MMExtension *extension = [extensionCenter getExtension:@protocol(EmoticonDownloadMgrExt)]; + if (extension) { + [extension unregisterExtension:self]; + } +} + +- (BOOL)fileExistsWithName:(NSString *)fileName { + fileName = [fileName stringByAppendingString:@".gif"]; + NSString *filePath = [self.cacheDirectory stringByAppendingString:fileName]; + NSFileManager *manager = [NSFileManager defaultManager]; + return [manager fileExistsAtPath:filePath]; +} + +- (NSString *)filePathWithName:(NSString *)fileName { + if (![self fileExistsWithName:fileName]) return nil; + + fileName = [fileName stringByAppendingString:@".gif"]; + return [self.cacheDirectory stringByAppendingString:fileName]; +} + +- (NSString *)cacheImageData:(NSData *)imageData withFileName:(NSString *)fileName completion:(void (^)(BOOL))completion { + BOOL result = NO; + if (!imageData) { + if (completion) { + completion(result); + } + } + NSString *imageName = [NSString stringWithFormat:@"%@.gif", fileName]; + NSString *tempImageFilePath = [self.cacheDirectory stringByAppendingString:imageName]; + if (imageData) { + NSURL *imageUrl = [NSURL fileURLWithPath:tempImageFilePath]; + result = [imageData writeToURL:imageUrl atomically:YES]; + } + + if (completion) { + completion(result); + } + return tempImageFilePath; +} + +- (NSString *)cacheEmotionMessage:(MessageData *)emotionMsg { + EmoticonMgr *emoticonMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("EmoticonMgr")]; + NSData *imageData = [emoticonMgr getEmotionDataWithMD5:emotionMsg.m_nsEmoticonMD5]; + if (!imageData && ![self.emotionSet containsObject:emotionMsg.m_nsEmoticonMD5]) { + EmoticonDownloadMgr *emotionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("EmoticonDownloadMgr")]; + [emotionMgr downloadEmoticonWithMessageData:emotionMsg]; + [self.emotionSet addObject:emotionMsg.m_nsEmoticonMD5]; + } + NSString *tempImageFilePath = [self cacheImageData:imageData withFileName:emotionMsg.m_nsEmoticonMD5 completion:nil]; + + return tempImageFilePath; +} + +- (void)emoticonDownloadFinished:(EmoticonMsgInfo *)msgInfo { + if (![self.emotionSet containsObject:msgInfo.m_nsMD5]) return; + + EmoticonMgr *emoticonMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("EmoticonMgr")]; + NSData *imageData = [emoticonMgr getEmotionDataWithMD5:msgInfo.m_nsMD5]; + [self cacheImageData:imageData withFileName:msgInfo.m_nsMD5 completion:^(BOOL result) { + if(result) { + [self.emotionSet removeObject:msgInfo.m_nsMD5]; + } + }]; +} + +- (NSString *)cacheAvatarWithContact:(WCContactData *)contact { + NSString *headImgUrl = contact.m_nsHeadImgUrl; + if (headImgUrl.length == 0) return @""; + + NSString *imgPath = @""; + if ([headImgUrl respondsToSelector:@selector(md5String)]) { + NSString *imgMd5Str = [headImgUrl performSelector:@selector(md5String)]; + MMAvatarService *avatarService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMAvatarService")]; + + NSString *userCache = [objc_getClass("PathUtility") GetCurUserCachePath]; + NSString *avatarPath = [userCache stringByAppendingString:@"/avatar"]; + + NSFileManager *fileMgr = [NSFileManager defaultManager]; + if (![fileMgr fileExistsAtPath:avatarPath]) { + [fileMgr createDirectoryAtPath:avatarPath withIntermediateDirectories:YES attributes:nil error:nil]; + } + + imgPath = [NSString stringWithFormat:@"%@/%@", avatarPath, imgMd5Str]; + if (imgPath && ![fileMgr fileExistsAtPath:imgPath] && ![self.avatarSet containsObject:imgPath]) { + [self.avatarSet addObject:imgPath]; + + void (^cacheImage)(NSImage *img) = ^(NSImage *img) { + NSData *imageData = [img TIFFRepresentation]; + [imageData writeToFile:imgPath atomically:YES]; + [self.avatarSet removeObject:imgPath]; + }; + + if ([avatarService respondsToSelector:@selector(avatarImageWithContact:completion:)]) { + [avatarService avatarImageWithContact:contact completion:cacheImage]; + } else { + [avatarService getAvatarImageWithContact:contact completion:cacheImage]; + } + } + + } + return imgPath ?: @""; + +} +@end diff --git a/WeChatPlugin/Sources/Managers/TKEmoticonManager.h b/WeChatPlugin/Sources/Managers/TKEmoticonManager.h new file mode 100644 index 00000000..0973794d --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKEmoticonManager.h @@ -0,0 +1,21 @@ +// +// TKEmoticonManager.h +// WeChatPlugin +// +// Created by TK on 2019/3/13. +// Copyright © 2019 tk. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TKEmoticonManager : NSObject + ++ (instancetype)shareManager; + +- (void)copyEmoticonWithMd5:(NSString *)md5Str; +- (void)exportEmoticonWithMd5:(NSString *)md5Str window:(NSWindow *)window; +@end + +NS_ASSUME_NONNULL_END diff --git a/WeChatPlugin/Sources/Managers/TKEmoticonManager.m b/WeChatPlugin/Sources/Managers/TKEmoticonManager.m new file mode 100644 index 00000000..9b89f8db --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKEmoticonManager.m @@ -0,0 +1,99 @@ +// +// TKEmoticonManager.m +// WeChatPlugin +// +// Created by TK on 2019/3/13. +// Copyright © 2019 tk. All rights reserved. +// + +#import "TKEmoticonManager.h" +#import "WeChatPlugin.h" + +@implementation TKEmoticonManager + ++ (instancetype)shareManager { + static TKEmoticonManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[TKEmoticonManager alloc] init]; + }); + return manager; +} + +- (void)copyEmoticonWithMd5:(NSString *)md5Str { + if (!md5Str) { + return; + } + + EmoticonMgr *emoticonMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("EmoticonMgr")]; + NSData *imageData = [emoticonMgr getEmotionDataWithMD5:md5Str]; + if (!imageData) return; + + NSString *imageType = [TKUtility getTypeForImageData:imageData]; + if (![imageType isEqualToString:@"gif"]) { + NSImage *image = [emoticonMgr getEmotionImgWithMD5:md5Str]; + image = [self resizeImage:image forSize:CGSizeMake(60, 60)]; + imageData = [image TIFFRepresentation]; + } + NSString *imageName = [NSString stringWithFormat:@"temp_paste_image_%@.%@", md5Str, imageType]; + NSString *tempImageFilePath = [NSTemporaryDirectory() stringByAppendingString:imageName]; + NSURL *imageUrl = [NSURL fileURLWithPath:tempImageFilePath]; + [imageData writeToURL:imageUrl atomically:YES]; + + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard clearContents]; + [pasteboard declareTypes:@[NSFilenamesPboardType] owner:nil]; + [pasteboard writeObjects:@[imageUrl]]; +} + +- (NSImage *)resizeImage:(NSImage *)sourceImage forSize:(NSSize)size { + NSRect targetFrame = NSMakeRect(0, 0, size.width, size.height); + NSSize imageSize = sourceImage.size; + if (imageSize.height * 0.5 < size.height && imageSize.width * 0.5 < size.width) { + targetFrame = NSMakeRect(0, 0, imageSize.width * 0.5, imageSize.height * 0.5); + } else { + if (imageSize.height > imageSize.width) { + targetFrame = NSMakeRect(0, 0, imageSize.width / imageSize.height * size.width, size.height); + } else { + targetFrame = NSMakeRect(0, 0, size.width, size.height * imageSize.height / imageSize.width); + } + } + NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame context:nil hints:nil]; + NSImage *targetImage = [[NSImage alloc] initWithSize:targetFrame.size]; + + [targetImage lockFocus]; + [sourceImageRep drawInRect: targetFrame]; + [targetImage unlockFocus]; + + return targetImage; +} + +- (void)exportEmoticonWithMd5:(NSString *)md5Str window:(NSWindow *)window { + if (!md5Str || !window) { + return; + } + + EmoticonMgr *emoticonMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("EmoticonMgr")]; + NSData *imageData = [emoticonMgr getEmotionDataWithMD5:md5Str]; + if (!imageData) return; + + NSSavePanel *savePanel = ({ + NSSavePanel *panel = [NSSavePanel savePanel]; + [panel setDirectoryURL:[NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Pictures"]]]; + [panel setNameFieldStringValue:md5Str]; + [panel setAllowedFileTypes:@[[TKUtility getTypeForImageData:imageData]]]; + [panel setAllowsOtherFileTypes:YES]; + [panel setExtensionHidden:NO]; + [panel setCanCreateDirectories:YES]; + + panel; + }); + + [savePanel beginSheetModalForWindow:window completionHandler:^(NSInteger result) { + if (result == NSModalResponseOK) { + [imageData writeToFile:[[savePanel URL] path] atomically:YES]; + } + }]; +} + +@end diff --git a/WeChatPlugin/Sources/Managers/TKHTTPManager.h b/WeChatPlugin/Sources/Managers/TKHTTPManager.h new file mode 100644 index 00000000..0d2e9ec5 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKHTTPManager.h @@ -0,0 +1,22 @@ +// +// TKHTTPManager.h +// WeChatPlugin +// +// Created by TK on 2018/4/17. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface TKHTTPManager : NSObject + ++ (instancetype)shareManager; + +- (void)downloadWithUrlString:(NSString *)urlString + toDirectoryPah:(NSString *)directory + progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock + completionHandler:(nullable void (^)(NSString * filePath, NSError * _Nullable error))completionHandler; + +- (void)cancelDownload; + +@end diff --git a/WeChatPlugin/Sources/Managers/TKHTTPManager.m b/WeChatPlugin/Sources/Managers/TKHTTPManager.m new file mode 100644 index 00000000..050f4997 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKHTTPManager.m @@ -0,0 +1,74 @@ +// +// TKHTTPManager.m +// WeChatPlugin +// +// Created by TK on 2018/4/17. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKHTTPManager.h" +#import "TKRemoteControlManager.h" + +@interface TKHTTPManager () + +@property (nonatomic, strong) AFHTTPSessionManager *session; +@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask; +@property (nonatomic, strong) AFURLSessionManager *sessionManager; +@property (nonatomic, copy) NSString *zipPath; + +@end + +@implementation TKHTTPManager + +- (instancetype) init +{ + self = [super init]; + if (self) { + self.session = ({ + AFHTTPSessionManager *session = [objc_getClass("AFHTTPSessionManager") manager]; + session.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringCacheData; + + session; + }); + } + return self; +} + ++ (instancetype)shareManager { + static TKHTTPManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[TKHTTPManager alloc] init]; + }); + return manager; +} + +- (void)downloadWithUrlString:(NSString *)urlString + toDirectoryPah:(NSString *)directory + progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock + completionHandler:(nullable void (^)(NSString * filePath, NSError * _Nullable error))completionHandler { + + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]; + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + self.sessionManager = [[objc_getClass("AFURLSessionManager") alloc] initWithSessionConfiguration:configuration]; + + self.downloadTask = [self.sessionManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { + if (downloadProgressBlock) downloadProgressBlock(downloadProgress); + + } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { + NSString *path = [directory stringByAppendingPathComponent:response.suggestedFilename]; + return [NSURL fileURLWithPath:path]; + } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable urlPath, NSError * _Nullable error) { + NSString *filePath = [[urlPath absoluteString] substringFromIndex:7]; + if (completionHandler) completionHandler(filePath, error); + }]; + [self.downloadTask resume]; +} + +- (void)cancelDownload { + if (!self.downloadTask) return; + [self.downloadTask cancel]; + self.downloadTask = nil; +} + +@end diff --git a/WeChatPlugin/Sources/Managers/TKMessageManager.h b/WeChatPlugin/Sources/Managers/TKMessageManager.h new file mode 100644 index 00000000..2b13a7a6 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKMessageManager.h @@ -0,0 +1,22 @@ +// +// TKMessageManager.h +// WeChatPlugin +// +// Created by TK on 2018/4/23. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface TKMessageManager : NSObject + ++ (instancetype)shareManager; + +- (void)sendTextMessageToSelf:(id)msgContent; +- (void)sendTextMessage:(id)msgContent toUsrName:(id)toUser delay:(NSInteger)delayTime; +- (void)clearUnRead:(id)arg1; +- (NSString *)getMessageContentWithData:(MessageData *)msgData; +- (NSArray *)getMsgListWithChatName:(id)arg1 minMesLocalId:(unsigned int)arg2 limitCnt:(NSInteger)arg3; +- (void)playVoiceWithMessageData:(MessageData *)msgData; + +@end diff --git a/WeChatPlugin/Sources/Managers/TKMessageManager.m b/WeChatPlugin/Sources/Managers/TKMessageManager.m new file mode 100644 index 00000000..a82830ee --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKMessageManager.m @@ -0,0 +1,121 @@ +// +// TKMessageManager.m +// WeChatPlugin +// +// Created by TK on 2018/4/23. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKMessageManager.h" + +@implementation TKMessageManager + ++ (instancetype)shareManager { + static id manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[self alloc] init]; + }); + return manager; +} + +- (void)sendTextMessageToSelf:(id)msgContent { + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + [self sendTextMessage:msgContent toUsrName:currentUserName delay:0]; +} + +- (void)sendTextMessage:(id)msgContent toUsrName:(id)toUser delay:(NSInteger)delayTime { + FFProcessReqsvrZZ *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + + if (delayTime == 0) { + [service FFProcessTReqZZ:currentUserName toUsrName:toUser msgText:msgContent atUserList:nil]; + return; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + [service FFProcessTReqZZ:currentUserName toUsrName:toUser msgText:msgContent atUserList:nil]; + }); + }); +} + +- (void)clearUnRead:(id)arg1 { + FFProcessReqsvrZZ *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + if ([service respondsToSelector:@selector(ClearUnRead:FromCreateTime:ToCreateTime:)]) { + [service ClearUnRead:arg1 FromCreateTime:0 ToCreateTime:0]; + } else if ([service respondsToSelector:@selector(ClearUnRead:FromID:ToID:)]) { + [service ClearUnRead:arg1 FromID:0 ToID:0]; + } +} + +- (NSString *)getMessageContentWithData:(MessageData *)msgData { + if (!msgData) return @""; + + NSString *msgContent = [msgData summaryString:NO] ?: @""; + if (msgData.m_nsTitle && (msgData.isAppBrandMsg || [msgContent isEqualToString:WXLocalizedString(@"Message_type_unsupport")])){ + NSString *content = msgData.m_nsTitle ?:@""; + if (msgContent) { + if (msgData.m_nsSourceDisplayname.length > 0) { + msgContent = [msgContent stringByAppendingFormat:@"%@:", msgData.m_nsSourceDisplayname]; + } else if (msgData.m_nsAppName.length > 0) { + msgContent = [msgContent stringByAppendingFormat:@"%@:", msgData.m_nsAppName]; + } + msgContent = [msgContent stringByAppendingString:content]; + } + } + + if ([msgData respondsToSelector:@selector(isChatRoomMessage)] && msgData.isChatRoomMessage && msgData.groupChatSenderDisplayName) { + if (msgData.groupChatSenderDisplayName.length > 0 && msgContent) { + msgContent = [NSString stringWithFormat:@"%@:%@",msgData.groupChatSenderDisplayName, msgContent]; + } + } + + if (msgData.messageType == 49) { + if (msgData.m_oWCPayInfoItem.m_nsFeeDesc.length > 0) { + msgContent = [msgContent stringByAppendingFormat:@" [金额:%@元]",msgData.m_oWCPayInfoItem.m_nsFeeDesc]; + } + } + return msgContent; +} + +- (NSArray *)getMsgListWithChatName:(id)arg1 minMesLocalId:(unsigned int)arg2 limitCnt:(NSInteger)arg3 { + FFProcessReqsvrZZ *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + char hasMore = '1'; + NSArray *array = @[]; + if ([service respondsToSelector:@selector(GetMsgListWithChatName:fromCreateTime:localId:limitCnt:hasMore:sortAscend:)]) { + array = [service GetMsgListWithChatName:arg1 fromCreateTime:arg2 localId:arg2 limitCnt:arg3 hasMore:&hasMore sortAscend:YES]; + } + + return [[array reverseObjectEnumerator] allObjects]; +} + +- (void)playVoiceWithMessageData:(MessageData *)msgData { + if (!msgData.isVoiceMsg) return; + + if (msgData.IsUnPlayed) { + msgData.msgStatus = 4; + MultiPlatformStatusSyncMgr *syncMgr = [[objc_getClass("MMServiceCenter") defaultCenter] + getService:objc_getClass("MultiPlatformStatusSyncMgr")]; + if ([syncMgr respondsToSelector:@selector(markVoiceMessageAsRead:)]) { + [syncMgr markVoiceMessageAsRead:msgData]; + } + } + MMVoiceMessagePlayer *voicePlayer = [objc_getClass("MMVoiceMessagePlayer") defaultPlayer]; + + if (msgData.IsPlayingSound) { + [msgData SetPlayingSoundStatus:NO]; + [voicePlayer stop]; + } else { + [msgData SetPlayed]; + MessageData *refMsgData = [msgData m_refMessageData]; + [refMsgData setM_uiDownloadStatus:refMsgData.m_uiDownloadStatus|0x4]; + [msgData SetPlayingSoundStatus:1]; + if ([voicePlayer respondsToSelector:@selector(playWithVoiceMessage:isUnplayedBeforePlay:)]) { + [voicePlayer playWithVoiceMessage:msgData isUnplayedBeforePlay:msgData.IsUnPlayed]; + } else if ([voicePlayer respondsToSelector:@selector(playVoiceWithMessage:isUnplayedBeforePlay:)]) { + [voicePlayer playVoiceWithMessage:msgData isUnplayedBeforePlay:msgData.IsUnPlayed]; + } + } +} + +@end diff --git a/WeChatPlugin/TKRemoteControlCommands.plist b/WeChatPlugin/Sources/Managers/TKRemoteControlCommands.plist similarity index 51% rename from WeChatPlugin/TKRemoteControlCommands.plist rename to WeChatPlugin/Sources/Managers/TKRemoteControlCommands.plist index 4a039a4c..6c0b3bb2 100644 --- a/WeChatPlugin/TKRemoteControlCommands.plist +++ b/WeChatPlugin/Sources/Managers/TKRemoteControlCommands.plist @@ -9,9 +9,11 @@ keyword ScreenSave function - 屏幕保护 + Assistant.Directive.ScreenSave enable + type + 1 executeCommand @@ -19,9 +21,11 @@ keyword LockScreen function - 锁屏 + Assistant.Directive.LockScreen enable + type + 1 executeCommand @@ -29,9 +33,11 @@ keyword Sleep function - 休眠 + Assistant.Directive.Sleep enable + type + 2 executeCommand @@ -39,9 +45,11 @@ keyword Shutdown function - 关机 + Assistant.Directive.Shutdown enable + type + 2 executeCommand @@ -49,9 +57,11 @@ keyword Restart function - 重启 + Assistant.Directive.Restart enable + type + 2 executeCommand @@ -59,9 +69,23 @@ keyword EmptyTrash function - 清空废纸篓 + Assistant.Directive.EmptyTrash enable + type + 2 + + + executeCommand + mute + keyword + Mute + function + Assistant.Directive.Mute + enable + + type + 2 @@ -71,19 +95,23 @@ keyword KillQQ function - 退出 QQ + Assistant.Directive.KillQQ enable + type + 2 executeCommand killWeChat keyword - KillWeChat + killWeChat function - 退出 WeChat + Assistant.Directive.KillWeChat enable + type + 2 executeCommand @@ -91,9 +119,11 @@ keyword KillChrome function - 退出 Chrome + Assistant.Directive.KillChrome enable + type + 2 executeCommand @@ -101,9 +131,23 @@ keyword KillSafari function - 退出 Safari + Assistant.Directive.KillSafari enable + type + 2 + + + executeCommand + killFirefox + keyword + killFirefox + function + Assistant.Directive.KillFirefox + enable + + type + 2 executeCommand @@ -111,9 +155,11 @@ keyword KillAll function - 退出所有程序 + Assistant.Directive.KillAll enable + type + 2 @@ -123,9 +169,11 @@ keyword Toggle function - 播放/暂停 + Assistant.Directive.Toggle enable + type + 2 executeCommand @@ -133,9 +181,11 @@ keyword Next function - 下一首 + Assistant.Directive.Next enable + type + 2 executeCommand @@ -143,9 +193,11 @@ keyword Previous function - 上一首 + Assistant.Directive.Previous enable + type + 2 executeCommand @@ -153,9 +205,11 @@ keyword VolumeUp function - 增大音量 + Assistant.Directive.VolumeUp enable + type + 2 executeCommand @@ -163,9 +217,11 @@ keyword VolumeDown function - 减小音量 + Assistant.Directive.VolumeDown enable + type + 2 executeCommand @@ -173,9 +229,61 @@ keyword LikeChange function - 喜欢/取消喜欢 + Assistant.Directive.LikeChange + enable + + type + 2 + + + + + executeCommand + getDirectiveList + keyword + getDirective + function + Assistant.Directive.GetList + enable + + type + 3 + + + executeCommand + PreventRevokeSwitch + keyword + PreventRevokeSwitch + function + Assistant.Directive.PreventRevokeSwitch + enable + + type + 3 + + + executeCommand + AutoReplySwitch + keyword + AutoReplySwitch + function + Assistant.Directive.AutoReplySwitch + enable + + type + 3 + + + executeCommand + AutoAuthSwitch + keyword + AutoAuthSwitch + function + Assistant.Directive.AutoAuthSwitch enable + type + 3 diff --git a/WeChatPlugin/Sources/Managers/TKRemoteControlManager.h b/WeChatPlugin/Sources/Managers/TKRemoteControlManager.h new file mode 100644 index 00000000..e85dca33 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKRemoteControlManager.h @@ -0,0 +1,19 @@ +// +// TKRemoteControlManager.h +// WeChatPlugin +// +// Created by TK on 2018/4/24. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface TKRemoteControlManager : NSObject + ++ (void)executeRemoteControlCommandWithVoiceMsg:(NSString *)msg; ++ (void)executeRemoteControlCommandWithMsg:(NSString *)msg; ++ (NSString *)executeShellCommand:(NSString *)msg; ++ (NSString *)executeAppleScriptCommand:(NSString *)cmd; ++ (NSString *)remoteControlCommandsString; + +@end diff --git a/WeChatPlugin/Sources/Managers/TKRemoteControlManager.m b/WeChatPlugin/Sources/Managers/TKRemoteControlManager.m new file mode 100644 index 00000000..5ed5aad7 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKRemoteControlManager.m @@ -0,0 +1,170 @@ +// +// TKRemoteControlManager.m +// WeChatPlugin +// +// Created by TK on 2018/4/24. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKRemoteControlManager.h" +#import "TKWeChatPluginConfig.h" +#import "TKRemoteControlModel.h" +#import "TKMessageManager.h" + +typedef NS_ENUM(NSUInteger, MessageDataType) { + MessageDataTypeText, + MessageDataTypeVoice +}; + +// 执行 AppleScript +static NSString * const kRemoteControlAppleScript = @"osascript /Applications/WeChat.app/Contents/MacOS/WeChatPlugin.framework/Resources/TKRemoteControlScript.scpt"; + +@implementation TKRemoteControlManager + ++ (void)executeRemoteControlCommandWithVoiceMsg:(NSString *)msg { + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + NSString *callBack = [NSString stringWithFormat:@"%@\n\n\n%@", TKLocalizedString(@"assistant.remoteControl.voiceRecall"), msg]; + FFProcessReqsvrZZ *service = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + [service FFProcessTReqZZ:currentUserName toUsrName:currentUserName msgText:callBack atUserList:nil]; + + [self executeRemoteControlCommandWithMsg:msg msgType:MessageDataTypeVoice]; +} + ++ (void)executeRemoteControlCommandWithMsg:(NSString *)msg { + [self executeRemoteControlCommandWithMsg:msg msgType:MessageDataTypeText]; +} + ++ (void)executeRemoteControlCommandWithMsg:(NSString *)msg msgType:(MessageDataType)type { + NSArray *remoteControlModels = [TKWeChatPluginConfig sharedConfig].remoteControlModels; + [remoteControlModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger index, BOOL * _Nonnull stop) { + [subModels enumerateObjectsUsingBlock:^(TKRemoteControlModel *model, NSUInteger idx, BOOL * _Nonnull subStop) { + if ([self shouldExecuteRemoteControlWithModel:model msg:msg msgType:type]) { + switch (model.type) { + case TKRemoteControlTypeShell: { + // 屏幕保护 & 锁屏 通过 Shell 命令来执行即可 + [self executeShellCommand:model.executeCommand]; + break; + } + case TKRemoteControlTypeScript: { + NSString *errorMsg = [self executeAppleScriptCommand:model.executeCommand]; + if ([errorMsg containsString:@"TKRemoteControlScript.scpt:"]) { + NSString *result = [errorMsg substringFromString:@"TKRemoteControlScript.scpt:"]; + [[TKMessageManager shareManager] sendTextMessageToSelf:result]; + } + // bug: 有些程序在第一次时会无法关闭,需要再次关闭 + if ([model.function isEqualToString:@"Assistant.Directive.KillAll"]) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self executeAppleScriptCommand:model.executeCommand]; + }); + } + break; + } + case TKRemoteControlTypePlugin: { + [self executePluginCommand:model.executeCommand]; + break; + } + default: + break; + } + + if (model.type != TKRemoteControlTypePlugin) { + NSString *callBack = [NSString stringWithFormat:@"%@%@", TKLocalizedString(@"assistant.remoteControl.recall"), TKLocalizedString(model.function)]; + [[TKMessageManager shareManager] sendTextMessageToSelf:callBack]; + [[TKMessageManager shareManager] clearUnRead:[objc_getClass("CUtility") GetCurrentUserName]]; + } + *stop = YES; + *subStop = YES; + } + }]; + }]; +} + ++ (BOOL)shouldExecuteRemoteControlWithModel:(TKRemoteControlModel *)model msg:(NSString *)msg msgType:(MessageDataType)type { + if (model.enable && ![model.keyword isEqualToString:@""]) { + if ((type == MessageDataTypeText && [msg isEqualToString:model.keyword]) || (type == MessageDataTypeVoice && ([msg containsString:model.keyword] || [msg containsString:TKLocalizedString(model.function)]))) { + return YES; + } else { + return NO; + } + } else { + return NO; + } +} + ++ (NSString *)executeAppleScriptCommand:(NSString *)cmd { + NSString *command = [NSString stringWithFormat:@"%@ %@",kRemoteControlAppleScript, cmd]; + return [self executeShellCommand:command]; +} + +/** + 通过 NSTask 执行 Shell 命令 + + @param cmd Terminal命令 + */ ++ (NSString *)executeShellCommand:(NSString *)cmd { + NSTask *task = [[NSTask alloc] init]; + [task setLaunchPath:@"/bin/bash"]; + [task setArguments:@[@"-c", cmd]]; + // 新建输出管道作为Task的错误输出 + NSPipe *errorPipe = [NSPipe pipe]; + [task setStandardError:errorPipe]; + NSFileHandle *file = [errorPipe fileHandleForReading]; + // 获取运行结果 + [task launch]; + NSData *data = [file readDataToEndOfFile]; + + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; +} + ++ (void)executePluginCommand:(NSString *)cmd { + NSString *callBack = @""; + TKWeChatPluginConfig *config = [TKWeChatPluginConfig sharedConfig]; + if ([cmd isEqualToString:@"getDirectiveList"]) { + callBack = [TKRemoteControlManager remoteControlCommandsString]; + } else if ([cmd isEqualToString:@"AutoReplySwitch"]) { + NSString *status = config.autoReplyEnable ? TKLocalizedString(@"Assistant.Directive.SwitchOff") : TKLocalizedString(@"Assistant.Directive.SwitchOn"); + callBack = [NSString stringWithFormat:@"%@-%@",TKLocalizedString(@"Assistant.Directive.AutoReplySwitch"),status]; + [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFY_AUTO_REPLY_CHANGE object:nil]; + } else if ([cmd isEqualToString:@"PreventRevokeSwitch"]) { + NSString *status = config.preventRevokeEnable ? TKLocalizedString(@"Assistant.Directive.SwitchOff") : TKLocalizedString(@"Assistant.Directive.SwitchOn"); + callBack = [NSString stringWithFormat:@"%@-%@",TKLocalizedString(@"Assistant.Directive.PreventRevokeSwitch"),status]; + [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFY_PREVENT_REVOKE_CHANGE object:nil]; + } else if ([cmd isEqualToString:@"AutoAuthSwitch"]) { + NSString *status = config.autoAuthEnable ? TKLocalizedString(@"Assistant.Directive.SwitchOff") : TKLocalizedString(@"Assistant.Directive.SwitchOn"); + callBack = [NSString stringWithFormat:@"%@-%@",TKLocalizedString(@"Assistant.Directive.AutoAuthSwitch"),status]; + [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFY_AUTO_AUTH_CHANGE object:nil]; + } + + [[TKMessageManager shareManager] sendTextMessageToSelf:callBack]; +} + ++ (NSString *)remoteControlCommandsString { + NSMutableString *replyContent = [NSMutableString stringWithString:TKLocalizedString(@"assistant.remoteControl.listTip")]; + + NSArray *remoteControlModels = [TKWeChatPluginConfig sharedConfig].remoteControlModels; + [remoteControlModels enumerateObjectsUsingBlock:^(NSArray *subModels, NSUInteger index, BOOL * _Nonnull stop) { + switch (index) { + case 0: + [replyContent appendFormat:@"%@\n",TKLocalizedString(@"assistant.remoteControl.mac")]; + break; + case 1: + [replyContent appendFormat:@"%@\n",TKLocalizedString(@"assistant.remoteControl.app")]; + break; + case 2: + [replyContent appendFormat:@"%@\n",TKLocalizedString(@"assistant.remoteControl.neteaseMusic")]; + break; + case 3: + [replyContent appendFormat:@"%@\n",TKLocalizedString(@"assistant.remoteControl.assistant")]; + break; + default: + break; + } + [subModels enumerateObjectsUsingBlock:^(TKRemoteControlModel *model, NSUInteger idx, BOOL * _Nonnull stop) { + [replyContent appendFormat:@"%@-%@-%@\n", TKLocalizedString(model.function), model.keyword, model.enable ? TKLocalizedString(@"assistant.remoteControl.open") : TKLocalizedString(@"assistant.remoteControl.close")]; + }]; + [replyContent appendString:@"\n"]; + }]; + return replyContent; +} + +@end diff --git a/WeChatPlugin/Sources/Managers/TKVersionManager.h b/WeChatPlugin/Sources/Managers/TKVersionManager.h new file mode 100644 index 00000000..30de8918 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKVersionManager.h @@ -0,0 +1,23 @@ +// +// TKVersionManager.h +// WeChatPlugin +// +// Created by TK on 2018/2/24. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +typedef NS_ENUM(NSUInteger, TKVersionStatus) { + TKVersionStatusOld, + TKVersionStatusNew, +}; + +@interface TKVersionManager : NSObject + ++ (instancetype)shareManager; +- (void)checkVersionFinish:(void (^)(TKVersionStatus, NSString *))finish; +- (void)downloadPluginProgress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock completionHandler:(void (^)(NSString *filePath, NSError * _Nullable error))completionHandler; +- (void)cancelDownload; + +@end diff --git a/WeChatPlugin/Sources/Managers/TKVersionManager.m b/WeChatPlugin/Sources/Managers/TKVersionManager.m new file mode 100644 index 00000000..0bf6400f --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKVersionManager.m @@ -0,0 +1,67 @@ +// +// TKVersionManager.m +// WeChatPlugin +// +// Created by TK on 2018/2/24. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKVersionManager.h" +#import "TKWeChatPluginConfig.h" +#import "TKHTTPManager.h" +#import "TKRemoteControlManager.h" + +@implementation TKVersionManager + ++ (instancetype)shareManager { + static TKVersionManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[TKVersionManager alloc] init]; + }); + return manager; +} + +- (void)checkVersionFinish:(void (^)(TKVersionStatus, NSString *))finish { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSDictionary *localInfo = [[TKWeChatPluginConfig sharedConfig] localInfoPlist]; + NSDictionary *romoteInfo = [[TKWeChatPluginConfig sharedConfig] romoteInfoPlist]; + NSString *localBundle = localInfo[@"CFBundleShortVersionString"]; + NSString *romoteBundle = romoteInfo[@"CFBundleShortVersionString"]; + + dispatch_async(dispatch_get_main_queue(), ^{ + if ([localBundle isEqualToString:romoteBundle]) { + NSString *versionMsg = [localInfo[@"versionInfo"] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"]; + finish(TKVersionStatusOld, versionMsg); + } else if (romoteInfo[@"versionInfo"]) { + if (![romoteInfo[@"showUpdateWindow"] boolValue]) return; + NSString *versionMsg = [romoteInfo[@"versionInfo"] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"]; + finish(TKVersionStatusNew, versionMsg); + } + }); + }); +} + +- (void)downloadPluginProgress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock completionHandler:(void (^)(NSString *filePath, NSError * _Nullable error))completionHandler { + NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; + + NSString *pluginName = @"WeChatPlugin-MacOS-master"; + NSString *pluginPath = [NSString stringWithFormat:@"%@/%@",cachesPath,pluginName]; + NSString *pluginZipPath = [NSString stringWithFormat:@"%@.zip",pluginPath]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + [fileManager removeItemAtPath:pluginPath error:nil]; + [fileManager removeItemAtPath:pluginZipPath error:nil]; + + NSString *urlString = @"https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/archive/master.zip"; + [[TKHTTPManager shareManager] downloadWithUrlString:urlString toDirectoryPah:cachesPath progress:^(NSProgress *downloadProgress) { + if (downloadProgressBlock) downloadProgressBlock(downloadProgress); + } completionHandler:^(NSString *filePath, NSError * _Nullable error) { + if (completionHandler) completionHandler(filePath,error); + }]; +} + +- (void)cancelDownload { + [[TKHTTPManager shareManager] cancelDownload]; +} +@end diff --git a/WeChatPlugin/Sources/Managers/TKWebServerManager.h b/WeChatPlugin/Sources/Managers/TKWebServerManager.h new file mode 100644 index 00000000..0d136e7e --- /dev/null +++ b/WeChatPlugin/Sources/Managers/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/Managers/TKWebServerManager.m b/WeChatPlugin/Sources/Managers/TKWebServerManager.m new file mode 100644 index 00000000..5a531186 --- /dev/null +++ b/WeChatPlugin/Sources/Managers/TKWebServerManager.m @@ -0,0 +1,548 @@ +// +// 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 +#import "TKMessageManager.h" +#import "TKCacheManager.h" + +@interface TKWebServerManager () + +@property (nonatomic, strong) GCDWebServer *webServer; +@property (nonatomic, strong) MMContactSearchLogic *searchLogic; +@property (nonatomic, strong) dispatch_semaphore_t semaphore; +@end + +@implementation TKWebServerManager + +static int port=57270; + ++ (instancetype)shareManager { + static TKWebServerManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[TKWebServerManager alloc] init]; + }); + return manager; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.searchLogic = [[objc_getClass("MMContactSearchLogic") alloc] init]; + self.semaphore = dispatch_semaphore_create(0); + } + return self; +} + +- (void)startServer { + if (self.webServer) { + return; + } + NSDictionary *options = @{GCDWebServerOption_Port: [NSNumber numberWithInt:port], + GCDWebServerOption_BindToLocalhost: @YES, + GCDWebServerOption_ConnectedStateCoalescingInterval: @2, + }; + + self.webServer = [[GCDWebServer alloc] init]; + [self addHandleForSearchUser]; + [self addHandleForOpenSession]; + [self addHandleForSendMsg]; + [self addHandleForSearchUserChatLog]; + [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) { + + if (![weakSelf isLocalhost:request.headers[@"Host"]]) { + return [GCDWebServerResponse responseWithStatusCode:404]; + } + + NSString *keyword = request.query ? request.query[@"keyword"] ? request.query[@"keyword"] : @"" : @""; + __block NSMutableArray *sessionList = [NSMutableArray array]; + + // 返回最近聊天列表 + if ([keyword isEqualToString:@""]) { + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + NSMutableArray *arrSession = [sessionMgr getAllSessions]; + [arrSession enumerateObjectsUsingBlock:^(MMSessionInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj.m_packedInfo.m_contact.m_nsUsrName isEqualToString:@"brandsessionholder"]) { + return ; + } + if (obj.isInGroupBox) { + return; + } + [sessionList addObject:[weakSelf dictFromSessionInfo:obj]]; + }]; + return [GCDWebServerDataResponse responseWithJSONObject:sessionList]; + } + + __block NSInteger count = 2; + MMContactSearchLogic *logic = weakSelf.searchLogic; + [logic doSearchWithKeyword:keyword searchScene:31 resultIsShownBlock:nil completion:^ { + if ([logic respondsToSelector:@selector(reloadSearchResultDataWithKeyword:resultContainer:completionBlock:)]) { + [logic reloadSearchResultDataWithKeyword:keyword resultContainer:nil completionBlock:^ { + NSLog(@"TKKK ---- %d", logic.searchResultContainer.logicSearchResultFlag); + if (logic.searchResultContainer.logicSearchResultFlag == 55) { + count -= 1; + if (count <= 0) { + dispatch_semaphore_signal(weakSelf.semaphore); + } + } + }]; + } + }]; + dispatch_semaphore_wait(weakSelf.semaphore, DISPATCH_TIME_FOREVER); + + MMChatMangerSearchReportMgr *reportMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMChatMangerSearchReportMgr")]; + + [reportMgr.contactSearchResults enumerateObjectsUsingBlock:^(id contact, NSUInteger idx, BOOL * _Nonnull stop) { + if ([contact isKindOfClass:objc_getClass("MMComplexContactSearchResult")]) { + [sessionList addObject:[weakSelf dictFromContactSearchResult:(MMComplexContactSearchResult *)contact]]; + } else if([contact isKindOfClass:objc_getClass("MMComplexGroupContactSearchResult")]) { + [sessionList addObject:[weakSelf dictFromGroupSearchResult:(MMComplexGroupContactSearchResult *)contact]]; + } + }]; + [reportMgr.groupContactSearchResults enumerateObjectsUsingBlock:^(MMComplexGroupContactSearchResult *group, NSUInteger idx, BOOL * _Nonnull stop) { + [sessionList addObject:[weakSelf dictFromGroupSearchResult:group]]; + }]; + [reportMgr.brandContactSearchResults enumerateObjectsUsingBlock:^(MMComplexContactSearchResult *contact, NSUInteger idx, BOOL * _Nonnull stop) { + [sessionList addObject:[weakSelf dictFromContactSearchResult:contact]]; + }]; + + if ([logic respondsToSelector:@selector(clearAllResults)]) { + [logic clearAllResults]; + } else if ([logic respondsToSelector:@selector(clearDataWhenSearchEnd)]) { + [logic clearDataWhenSearchEnd]; + } + + return [GCDWebServerDataResponse responseWithJSONObject:sessionList]; + + }]; +} + +- (void)addHandleForSearchUserChatLog { + __weak typeof(self) weakSelf = self; + [self.webServer addHandlerForMethod:@"GET" path:@"/wechat-plugin/chatlog" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerRequest * _Nonnull request) { + + if (![weakSelf isLocalhost:request.headers[@"Host"]]) { + return [GCDWebServerResponse responseWithStatusCode:404]; + } + + NSString *userId = request.query ? request.query[@"userId"] ? request.query[@"userId"] : nil : nil; + NSInteger count = request.query ? request.query[@"count"] ? [request.query[@"count"] integerValue] : 30 : 30; + + if (userId) { + NSMutableArray *chatLogList = [NSMutableArray array]; + + NSArray *msgDataList = [[TKMessageManager shareManager] getMsgListWithChatName:userId minMesLocalId:0 limitCnt:count]; + [msgDataList enumerateObjectsUsingBlock:^(MessageData * _Nonnull msgData, NSUInteger idx, BOOL * _Nonnull stop) { + [chatLogList addObject:[weakSelf dictFromMessageData:msgData]]; + }]; + + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + WCContactData *toUserContact = [sessionMgr getSessionContact:userId]; + NSString *wechatId = [toUserContact getContactDisplayUsrName]; + NSString *title = [weakSelf getUserNameWithContactData:toUserContact showOriginName:YES]; + NSString *imgPath = [[TKCacheManager shareManager] cacheAvatarWithContact:toUserContact]; + NSDictionary *toUserContactDict = @{@"title": [NSString stringWithFormat:@"To: %@", title], + @"subTitle": chatLogList.count > 0 ? TKLocalizedString(@"assistant.search.chatlog") : @"", + @"icon": imgPath ?: @"", + @"userId": userId, + @"url": @"", + @"copyText": wechatId ?: @"", + @"srvId": @(0) + }; + [chatLogList insertObject:toUserContactDict atIndex:0]; + + return [GCDWebServerDataResponse responseWithJSONObject:chatLogList]; + } + + return [GCDWebServerResponse responseWithStatusCode:404]; + }]; +} + +- (void)addHandleForOpenSession { + __weak typeof(self) weakSelf = self; + + [self.webServer addHandlerForMethod:@"POST" path:@"/wechat-plugin/open-session" requestClass:[GCDWebServerURLEncodedFormRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerURLEncodedFormRequest * _Nonnull request) { + + if (![weakSelf isLocalhost:request.headers[@"Host"]]) { + return [GCDWebServerResponse responseWithStatusCode:404]; + } + + NSDictionary *requestBody = [request arguments]; + + if (requestBody && requestBody[@"userId"]) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *userId = requestBody[@"userId"]; + NSInteger srvId = [requestBody[@"srvId"] integerValue]; + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + WCContactData *selectContact = [sessionMgr getSessionContact:userId]; + + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + if ([selectContact isBrandContact]) { + WCContactData *brandsessionholder = [sessionMgr getSessionContact:@"brandsessionholder"]; + if (brandsessionholder) { + [wechat startANewChatWithContact:brandsessionholder]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + MMBrandChatsViewController *brandChats = wechat.chatsViewController.brandChatsViewController; + [brandChats startChatWithContact:selectContact]; + }); + } + } else { + [wechat startANewChatWithContact:selectContact]; + if (srvId > 0) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + FFProcessReqsvrZZ *msgService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + MessageData *msgData = [msgService GetMsgData:userId svrId:srvId]; + if (msgData) { + MMChatMessageViewController *vc = wechat.chatsViewController.chatDetailSplitViewController.chatMessageViewController; + [vc scrollToMessage:msgData]; + } + + }); + } + } + [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; + }); + return [GCDWebServerResponse responseWithStatusCode:200]; + } + + return [GCDWebServerResponse responseWithStatusCode:404]; + }]; +} + +- (void)addHandleForSendMsg { + __weak typeof(self) weakSelf = self; + + [self.webServer addHandlerForMethod:@"POST" path:@"/wechat-plugin/send-message" requestClass:[GCDWebServerURLEncodedFormRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerURLEncodedFormRequest * _Nonnull request) { + + if (![weakSelf isLocalhost:request.headers[@"Host"]]) { + return [GCDWebServerResponse responseWithStatusCode:404]; + } + + NSDictionary *requestBody = [request arguments]; + NSString *userId = requestBody[@"userId"]; + + if (requestBody && userId.length > 0) { + NSString *content = requestBody[@"content"]; + + FFProcessReqsvrZZ *messageService = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("FFProcessReqsvrZZ")]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (content.length > 0) { + NSString *currentUserName = [objc_getClass("CUtility") GetCurrentUserName]; + [messageService FFProcessTReqZZ:currentUserName + toUsrName:requestBody[@"userId"] + msgText:requestBody[@"content"] + atUserList:nil]; + [[TKMessageManager shareManager] clearUnRead:requestBody[@"userId"]]; + + } else if (content.length == 0 && requestBody[@"srvId"]) { + if (requestBody[@"srvId"]) { + NSInteger srvId = [requestBody[@"srvId"] integerValue]; + if (srvId != 0) { + MessageData *msgData = [messageService GetMsgData:userId svrId:srvId]; + [[TKMessageManager shareManager] playVoiceWithMessageData:msgData]; + } + } + [[TKMessageManager shareManager] clearUnRead:userId]; + } + }); + return [GCDWebServerResponse responseWithStatusCode:200]; + } + + return [GCDWebServerResponse responseWithStatusCode:404]; + }]; +} + +- (NSDictionary *)dictFromGroupSearchResult:(MMComplexGroupContactSearchResult *)result { + if (![result isKindOfClass:objc_getClass("MMComplexGroupContactSearchResult")]) { + return [self dictWithErrorMsg:result.className]; + } + WCContactData *groupContact = result.groupContact; + if (!groupContact) { + return [self dictWithErrorMsg:@"搜索群组有误"]; + } + NSMutableArray *subTitleArray = [NSMutableArray array]; + if (result.searchType == 2) { + [result.groupMembersResult.membersSearchReults enumerateObjectsUsingBlock:^(MMComplexContactSearchResult * _Nonnull contact, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *matchStr =[self matchWithContactResult:contact]; + NSString *contactName; + if(contact.contact.m_nsRemark && ![contact.contact.m_nsRemark isEqualToString:@""]) { + contactName = contact.contact.m_nsRemark; + if (contact.fieldType != 1) { + contactName = [NSString stringWithFormat:@"%@(%@)", contactName, matchStr]; + } + } else { + contactName = contact.contact.m_nsNickName; + if (contact.fieldType != 3) { + contactName = [NSString stringWithFormat:@"%@(%@)", contactName, matchStr]; + } + } + [subTitleArray addObject:contactName]; + }]; + } + NSString *title = [NSString stringWithFormat:@"%@%@", TKLocalizedString(@"assistant.search.group"), groupContact.innerGetGroupDisplayName]; + if ([groupContact isGroupChat]) { + title = [title stringByAppendingFormat:@" (%@)",@(groupContact.groupMemberCount)]; + } + NSString *subTitle = @""; + if (subTitleArray.count > 0) { + subTitle = [NSString stringWithFormat:@"%@%@",TKLocalizedString(@"assistant.search.member"),[subTitleArray componentsJoinedByString:@", "]]; + } + NSString *imgPath = [[TKCacheManager shareManager] cacheAvatarWithContact:groupContact]; + NSString *wechatId = [groupContact getContactDisplayUsrName]; + + return @{@"title": title, + @"subTitle": subTitle, + @"icon": imgPath, + @"userId": groupContact.m_nsUsrName, + @"copyText": wechatId ?: @"", + @"url": groupContact.m_nsHeadHDImgUrl ?: @"" + }; +} + +- (NSString *)matchWithContactResult:(MMComplexContactSearchResult *)result { + NSString *matchStr = @""; + NSInteger type = result.fieldType; + + switch (type) { // 1:备注 3:昵称 4:微信号 7:市 8:省份 9:国家 + case 1: + matchStr = WXLocalizedString(@"Search.Remark"); + break; + case 3: + matchStr = WXLocalizedString(@"Search.Nickname"); + break; + case 4: + matchStr = WXLocalizedString(@"Search.Username"); + break; + case 7: + matchStr = WXLocalizedString(@"Search.City"); + break; + case 8: + matchStr = WXLocalizedString(@"Search.Province"); + break; + case 9: + matchStr = WXLocalizedString(@"Search.Country"); + break; + default: + matchStr = WXLocalizedString(@"Search.Include"); + break; + } + matchStr = [matchStr stringByAppendingString:result.fieldValue ?: @""]; + return matchStr; +} + +- (NSDictionary *)dictFromContactSearchResult:(MMComplexContactSearchResult *)result { + if (![result isKindOfClass:objc_getClass("MMComplexContactSearchResult")]) { + return [self dictWithErrorMsg:result.className]; + } + WCContactData *contact = result.contact; + if (!contact) { + return [self dictWithErrorMsg:@"搜索用户有误"]; + } + if (contact.m_nsNickName.length == 0) { + return [self dictWithErrorMsg:@"用户:找不到 m_nsNickName"]; + } + NSString *title = [contact isBrandContact] ? [NSString stringWithFormat:@"%@%@",TKLocalizedString(@"assistant.search.official"), contact.m_nsNickName] : 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 = [[TKCacheManager shareManager] cacheAvatarWithContact:contact]; + + NSString *wechatId = [contact getContactDisplayUsrName]; + return @{@"title": title, + @"subTitle": subTitle, + @"icon": imgPath, + @"userId": contact.m_nsUsrName, + @"copyText": wechatId ?: @"", + @"url": contact.m_nsHeadHDImgUrl ?: @"" + }; +} + +- (NSDictionary *)dictFromSessionInfo:(MMSessionInfo *)sessionInfo { + if (!sessionInfo) return [self dictWithErrorMsg:@"最近聊天列表有误"]; + + WCContactData *contact = sessionInfo.m_packedInfo.m_contact; + MessageData *msgData = sessionInfo.m_packedInfo.m_msgData; + + NSString *title = [self getUserNameWithContactData:contact showOriginName:YES]; + if ([contact isGroupChat]) { + title = [title stringByAppendingFormat:@" (%@)",@(contact.groupMemberCount)]; + } + NSString *msgContent = [[TKMessageManager shareManager] getMessageContentWithData:msgData]; + NSString *imgPath = [[TKCacheManager shareManager] cacheAvatarWithContact:contact]; + + NSString *wechatId = [contact getContactDisplayUsrName]; + return @{@"title": title, + @"subTitle": msgContent, + @"icon": imgPath, + @"userId": contact.m_nsUsrName, + @"copyText": wechatId ?: @"", + @"unReadCount": @(sessionInfo.m_bShowUnReadAsRedDot ? 0 : sessionInfo.m_uUnReadCount), + @"url": contact.m_nsHeadHDImgUrl ?: @"" + }; +} + + +- (NSDictionary *)dictWithErrorMsg:(NSString *)msg { + return @{@"title": msg, + @"subTitle": @"", + @"icon": @"", + @"userId": @"", + @"copyText": @"", + @"url": @"" + }; +} + +- (NSDictionary *)dictFromMessageData:(MessageData *)msgData { + if (!msgData) { + return [self dictWithErrorMsg:@"消息不存在"]; + } + MMSessionMgr *sessionMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMSessionMgr")]; + WCContactData *msgContact = [sessionMgr getSessionContact:msgData.fromUsrName]; + NSString *title = [[TKMessageManager shareManager] getMessageContentWithData:msgData]; + + NSString *url; + long long svrId = msgData.mesSvrID; + if (msgData.messageType == 1) { + // 文本消息,如果有链接,传到 copyText 复制 + NSRange range = [objc_getClass("MMLinkInfo") rangeOfUrlInString:title withRange:NSMakeRange(0, title.length)]; + if (range.length > 0) { + url = [title substringWithRange:range]; + if(![objc_getClass("MMURLHandler") containsHTTPString:url]) { + url = [NSString stringWithFormat:@"http://%@",url]; + } + } + } else if (msgData.isVideoMsg) { + url = msgData.m_nsVideoPath; + NSFileManager *manager = [NSFileManager defaultManager]; + if (![manager fileExistsAtPath:url]) { + MMMessageVideoService *videoMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMMessageVideoService")]; + [videoMgr downloadVideoWithMessage:msgData]; + } + } else if (msgData.isImgMsg) { + url = [msgData originalImageFilePath]; + NSFileManager *manager = [NSFileManager defaultManager]; + if (![manager fileExistsAtPath:url]) { + MMCDNDownloadMgr *imgMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("MMCDNDownloadMgr")]; + [imgMgr downloadImageWithMessage:msgData disableHevc:NO downloadType:1]; + } + } else if (msgData.isCustomEmojiMsg || msgData.isEmojiAppMsg) { + if ([[TKCacheManager shareManager] fileExistsWithName:msgData.m_nsEmoticonMD5]) { + url = [[TKCacheManager shareManager] filePathWithName:msgData.m_nsEmoticonMD5]; + } else { + url = [[TKCacheManager shareManager] cacheEmotionMessage:msgData]; + } + // } + + } else if(msgData.isVoiceMsg) { + if (msgData.msgVoiceText.length > 0) { + title = [title stringByAppendingString:msgData.msgVoiceText]; + } +// if (msgData.IsUnPlayed) { +// title = [NSString stringWithFormat:@"%@(%@)",title,TKLocalizedString(@"assistant.search.message.unread")]; +// } + } else if (msgData.messageType == 49) { + NSString *msgContact = [msgData summaryString:NO]; + if (!msgData.isAppBrandMsg && ![msgContact isEqualToString:WXLocalizedString(@"Message_type_unsupport")]) { + url = [msgData m_nsAppMediaUrl]; + } + if (url.length == 0 && msgData.m_nsFilePath.length > 0) { + url = msgData.m_nsFilePath; + } + } + + NSString *subTitle = [self getDateStringWithTimeStr:msgData.msgCreateTime]; + + NSString *imgPath; + if ([msgContact isGroupChat]) { + GroupStorage *contactStorage = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("GroupStorage")]; + WCContactData *fromContact = [contactStorage GetGroupMemberContact:[msgData getChatRoomUsrName]]; + imgPath = [[TKCacheManager shareManager] cacheAvatarWithContact:fromContact]; + } else { + imgPath = [[TKCacheManager shareManager] cacheAvatarWithContact:msgContact]; + } + + if (!msgContact.isGroupChat) { + subTitle = [NSString stringWithFormat:@"from: %@ %@",[self getUserNameWithContactData:msgContact showOriginName:NO], subTitle]; + } + return @{@"title": title, + @"subTitle": subTitle, + @"icon": imgPath, + @"userId": msgContact.m_nsUsrName, + @"url": url ?: @"", + @"copyText": url ?: title, + @"srvId": @(svrId) + }; +} + +- (NSString *)getDateStringWithTimeStr:(NSTimeInterval)time { + NSDate *date = [NSDate dateWithTimeIntervalSince1970:time]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + if ([date isToday]) { + formatter.dateFormat = @"HH:mm:ss"; + return [formatter stringFromDate:date]; + } else { + //昨天 + if ([date isYesterday]) { + formatter.dateFormat = [NSString stringWithFormat:@"%@ HH:mm:ss", TKLocalizedString(@"assistant.search.yesterday")]; + return [formatter stringFromDate:date]; + } else { + formatter.dateFormat = @"yy-MM-dd HH:mm:ss"; + return [formatter stringFromDate:date]; + } + } + return @""; +} + +- (NSString *)getUserNameWithContactData:(WCContactData *)contact showOriginName:(BOOL)showOriginName { + if (!contact) return @""; + + NSString *userName; + if (contact.isGroupChat) { + userName = [NSString stringWithFormat:@"%@%@", TKLocalizedString(@"assistant.search.group"), contact.innerGetGroupDisplayName]; + } else if ([contact respondsToSelector:@selector(isBrandContact)]){ + userName = contact.isBrandContact ? [NSString stringWithFormat:@"%@%@",TKLocalizedString(@"assistant.search.official"), contact.m_nsNickName] : contact.m_nsNickName; + if(contact.m_nsRemark && ![contact.m_nsRemark isEqualToString:@""]) { + if (showOriginName) { + userName = [NSString stringWithFormat:@"%@(%@)",contact.m_nsRemark, contact.m_nsNickName]; + } else { + userName = contact.m_nsRemark; + } + + } + } + return userName ?: @""; +} + +- (BOOL)isLocalhost:(NSString *)host { + NSArray *localhostUrls = @[[NSString stringWithFormat:@"127.0.0.1:%d", port], + [NSString stringWithFormat:@"localhost:%d", port] + ]; + return [localhostUrls containsObject:host]; +} + +@end diff --git a/WeChatPlugin/Sources/Models/TKAutoReplyModel.h b/WeChatPlugin/Sources/Models/TKAutoReplyModel.h index 3da7c5db..7d93b4ec 100644 --- a/WeChatPlugin/Sources/Models/TKAutoReplyModel.h +++ b/WeChatPlugin/Sources/Models/TKAutoReplyModel.h @@ -16,6 +16,10 @@ @property (nonatomic, assign) BOOL enableGroupReply; /**< 是否开启群聊自动回复 */ @property (nonatomic, assign) BOOL enableSingleReply; /**< 是否开启私聊自动回复 */ @property (nonatomic, assign) BOOL enableRegex; /**< 是否开启正则匹配 */ +@property (nonatomic, assign) BOOL enableDelay; /**< 是否开启延迟回复 */ +@property (nonatomic, assign) NSInteger delayTime; /**< 延迟时间 */ +@property (nonatomic, assign) BOOL enableSpecificReply; /**< 是否开启特定回复 */ +@property (nonatomic, strong) NSArray *specificContacts; /**< 特定回复的联系人 */ - (BOOL)hasEmptyKeywordOrReplyContent; diff --git a/WeChatPlugin/Sources/Models/TKAutoReplyModel.m b/WeChatPlugin/Sources/Models/TKAutoReplyModel.m index afc4677e..ebb3c8d6 100644 --- a/WeChatPlugin/Sources/Models/TKAutoReplyModel.m +++ b/WeChatPlugin/Sources/Models/TKAutoReplyModel.m @@ -19,6 +19,10 @@ - (instancetype)initWithDict:(NSDictionary *)dict { self.enableGroupReply = [dict[@"enableGroupReply"] boolValue]; self.enableSingleReply = [dict[@"enableSingleReply"] boolValue]; self.enableRegex = [dict[@"enableRegex"] boolValue]; + self.enableDelay = [dict[@"enableDelay"] boolValue]; + self.delayTime = [dict[@"delayTime"] floatValue]; + self.enableSpecificReply = [dict[@"enableSpecificReply"] boolValue]; + self.specificContacts = dict[@"specificContacts"] ? : [NSArray array]; } return self; } @@ -29,11 +33,22 @@ - (NSDictionary *)dictionary { @"replyContent": self.replyContent, @"enableGroupReply": @(self.enableGroupReply), @"enableSingleReply": @(self.enableSingleReply), - @"enableRegex": @(self.enableRegex)}; + @"enableRegex": @(self.enableRegex), + @"enableDelay": @(self.enableDelay), + @"delayTime": @(self.delayTime), + @"enableSpecificReply": @(self.enableSpecificReply), + @"specificContacts": self.specificContacts + }; } - (BOOL)hasEmptyKeywordOrReplyContent { return (self.keyword == nil || self.replyContent == nil || [self.keyword isEqualToString:@""] || [self.replyContent isEqualToString:@""]); } +- (NSArray *)specificContacts { + if (!_specificContacts) { + _specificContacts = [NSArray array]; + } + return _specificContacts; +} @end diff --git a/WeChatPlugin/Sources/Models/TKRemoteControlModel.h b/WeChatPlugin/Sources/Models/TKRemoteControlModel.h index 1f611919..6870f7d3 100644 --- a/WeChatPlugin/Sources/Models/TKRemoteControlModel.h +++ b/WeChatPlugin/Sources/Models/TKRemoteControlModel.h @@ -8,11 +8,18 @@ #import "TKBaseModel.h" +typedef NS_ENUM(NSUInteger, TKRemoteControlType) { + TKRemoteControlTypeShell = 1, + TKRemoteControlTypeScript, + TKRemoteControlTypePlugin, +}; + @interface TKRemoteControlModel : TKBaseModel @property (nonatomic, assign) BOOL enable; @property (nonatomic, copy) NSString *keyword; @property (nonatomic, copy) NSString *function; @property (nonatomic, copy) NSString *executeCommand; +@property (nonatomic, assign) TKRemoteControlType type; @end diff --git a/WeChatPlugin/Sources/Models/TKRemoteControlModel.m b/WeChatPlugin/Sources/Models/TKRemoteControlModel.m index 27d1943c..47da252e 100644 --- a/WeChatPlugin/Sources/Models/TKRemoteControlModel.m +++ b/WeChatPlugin/Sources/Models/TKRemoteControlModel.m @@ -17,6 +17,7 @@ - (instancetype)initWithDict:(NSDictionary *)dict { self.keyword = dict[@"keyword"]; self.function = dict[@"function"]; self.executeCommand = dict[@"executeCommand"]; + self.type = [dict[@"type"] integerValue]; } return self; } @@ -25,7 +26,8 @@ - (NSDictionary *)dictionary { return @{@"enable": @(self.enable), @"keyword": self.keyword, @"function": self.function, - @"executeCommand": self.executeCommand}; + @"executeCommand": self.executeCommand, + @"type": @(self.type)}; } @end diff --git a/WeChatPlugin/Sources/Utils/TKUtility.h b/WeChatPlugin/Sources/Utils/TKUtility.h new file mode 100644 index 00000000..b4d698b0 --- /dev/null +++ b/WeChatPlugin/Sources/Utils/TKUtility.h @@ -0,0 +1,24 @@ +// +// TKUtility.h +// WeChatPlugin +// +// Created by TK on 2019/1/12. +// Copyright © 2019 tk. All rights reserved. +// + +#import + +#define LargerOrEqualVersion(version) [TKUtility isLargerOrEqualVersion:version] +NS_ASSUME_NONNULL_BEGIN + +@interface TKUtility : NSObject + ++ (BOOL)isLargerOrEqualVersion:(NSString *)version; ++ (NSString *)getTypeForImageData:(NSData *)data; ++ (NSDateFormatter *)getDateFormater; ++ (NSString *)getOnlyDateString; ++ (NSMutableArray *)getMemberNameWithMsgContent:(NSString *)msgContent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WeChatPlugin/Sources/Utils/TKUtility.m b/WeChatPlugin/Sources/Utils/TKUtility.m new file mode 100644 index 00000000..1eec63ba --- /dev/null +++ b/WeChatPlugin/Sources/Utils/TKUtility.m @@ -0,0 +1,95 @@ +// +// TKUtility.m +// WeChatPlugin +// +// Created by TK on 2019/1/12. +// Copyright © 2019 tk. All rights reserved. +// + +#import "TKUtility.h" + +@implementation TKUtility + ++ (BOOL)isLargerOrEqualVersion:(NSString *)version { + NSDictionary *dict = [NSBundle mainBundle].infoDictionary; + if ([dict[@"CFBundleShortVersionString"] compare:version options:NSNumericSearch] == NSOrderedAscending) { + return NO; + } else { + return YES; + } +} + ++ (NSString *)getTypeForImageData:(NSData *)data { + uint8_t c; + [data getBytes:&c length:1]; + switch (c) { + case 0x89: + return @"png"; + case 0x47: + return @"gif"; + default: + return @"jpg"; + } + return nil; +} + +///yyyy-MM-dd ++ (NSDateFormatter *)getDateFormater { + static NSDateFormatter *formatter; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd"]; + }); + return formatter; +} + ++ (NSString *)getOnlyDateString { + return [[self getDateFormater] stringFromDate:[NSDate date]]; +} + ++ (NSMutableArray *)getMemberNameWithMsgContent:(NSString *)msgContent { + NSArray *keywords = [self getMemberSplitKeywords]; + __block BOOL hasContain = YES; + __block NSArray *keyword = nil; + [keywords enumerateObjectsUsingBlock:^(NSArray *obj, NSUInteger idx, BOOL * _Nonnull stop) { + [obj enumerateObjectsUsingBlock:^(NSString *string, NSUInteger idx, BOOL * _Nonnull subStop) { + if (![string isKindOfClass:NSNull.class] && ![msgContent containsString:string]) { + hasContain = NO; + *subStop = YES; + } + }]; + if (hasContain) { + keyword = obj; + *stop = YES; + } + hasContain = YES; + }]; + + NSMutableArray *nameArray = [NSMutableArray array]; + if (keyword) { + for (NSInteger index = 0; index < keyword.count - 1; index++) { + NSString *name = [msgContent substringFromString:keyword[index] toString:keyword[index + 1]]; + if (name) { + if ([name containsString:@"、"] && ![name isEqualToString:@"、"]) { + NSArray *tempArray = [name componentsSeparatedByString:@"、"]; + [nameArray addObjectsFromArray:tempArray]; + } else { + [nameArray addObject:name]; + } + } + } + } + + return nameArray; +} + ++ (NSArray *)getMemberSplitKeywords { + return @[ @[@"\"", @"\"邀请\"", @"\"加入了群聊"], + @[@"\" ", @"\"通过扫描\"", @"\"分享的二维码加入群聊"], + @[@"\"", @"\"与群里其他人都不是微信朋友关系,请注意隐私安全"], + @[@"你通过扫描二维码加入群聊,群聊参与人还有:", [NSNull null]], + @[@"\"", @"\"邀请你和\"", @"\"加入了群聊"] + ]; +} +@end diff --git a/WeChatPlugin/Sources/Utils/XMLReader.h b/WeChatPlugin/Sources/Utils/XMLReader.h deleted file mode 100755 index aeca0b80..00000000 --- a/WeChatPlugin/Sources/Utils/XMLReader.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// XMLReader.h -// -// Created by Troy Brant on 9/18/10. -// Updated by Antoine Marcadet on 9/23/11. -// Updated by Divan Visagie on 2012-08-26 -// - -#import - -enum { - XMLReaderOptionsProcessNamespaces = 1 << 0, // Specifies whether the receiver reports the namespace and the qualified name of an element. - XMLReaderOptionsReportNamespacePrefixes = 1 << 1, // Specifies whether the receiver reports the scope of namespace declarations. - XMLReaderOptionsResolveExternalEntities = 1 << 2, // Specifies whether the receiver reports declarations of external entities. -}; -typedef NSUInteger XMLReaderOptions; - -@interface XMLReader : NSObject - -+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)errorPointer; -+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)errorPointer; -+ (NSDictionary *)dictionaryForXMLData:(NSData *)data options:(XMLReaderOptions)options error:(NSError **)errorPointer; -+ (NSDictionary *)dictionaryForXMLString:(NSString *)string options:(XMLReaderOptions)options error:(NSError **)errorPointer; - -@end diff --git a/WeChatPlugin/Sources/Utils/XMLReader.m b/WeChatPlugin/Sources/Utils/XMLReader.m deleted file mode 100755 index 754c95a4..00000000 --- a/WeChatPlugin/Sources/Utils/XMLReader.m +++ /dev/null @@ -1,176 +0,0 @@ -// -// XMLReader.m -// -// Created by Troy Brant on 9/18/10. -// Updated by Antoine Marcadet on 9/23/11. -// Updated by Divan Visagie on 2012-08-26 -// - -#import "XMLReader.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "XMLReader requires ARC support." -#endif - -NSString *const kXMLReaderTextNodeKey = @"text"; -NSString *const kXMLReaderAttributePrefix = @"@"; - -@interface XMLReader () - -@property (nonatomic, strong) NSMutableArray *dictionaryStack; -@property (nonatomic, strong) NSMutableString *textInProgress; -@property (nonatomic, strong) NSError *errorPointer; - -@end - - -@implementation XMLReader - -#pragma mark - Public methods - -+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)error -{ - XMLReader *reader = [[XMLReader alloc] initWithError:error]; - NSDictionary *rootDictionary = [reader objectWithData:data options:0]; - return rootDictionary; -} - -+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)error -{ - NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; - return [XMLReader dictionaryForXMLData:data error:error]; -} - -+ (NSDictionary *)dictionaryForXMLData:(NSData *)data options:(XMLReaderOptions)options error:(NSError **)error -{ - XMLReader *reader = [[XMLReader alloc] initWithError:error]; - NSDictionary *rootDictionary = [reader objectWithData:data options:options]; - return rootDictionary; -} - -+ (NSDictionary *)dictionaryForXMLString:(NSString *)string options:(XMLReaderOptions)options error:(NSError **)error -{ - NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; - return [XMLReader dictionaryForXMLData:data options:options error:error]; -} - - -#pragma mark - Parsing - -- (id)initWithError:(NSError **)error -{ - self = [super init]; - if (self) - { - self.errorPointer = *error; - } - return self; -} - -- (NSDictionary *)objectWithData:(NSData *)data options:(XMLReaderOptions)options -{ - // Clear out any old data - self.dictionaryStack = [[NSMutableArray alloc] init]; - self.textInProgress = [[NSMutableString alloc] init]; - - // Initialize the stack with a fresh dictionary - [self.dictionaryStack addObject:[NSMutableDictionary dictionary]]; - - // Parse the XML - NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; - - [parser setShouldProcessNamespaces:(options & XMLReaderOptionsProcessNamespaces)]; - [parser setShouldReportNamespacePrefixes:(options & XMLReaderOptionsReportNamespacePrefixes)]; - [parser setShouldResolveExternalEntities:(options & XMLReaderOptionsResolveExternalEntities)]; - - parser.delegate = self; - BOOL success = [parser parse]; - - // Return the stack's root dictionary on success - if (success) - { - NSDictionary *resultDict = [self.dictionaryStack objectAtIndex:0]; - return resultDict; - } - - return nil; -} - - -#pragma mark - NSXMLParserDelegate methods - -- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict -{ - // Get the dictionary for the current level in the stack - NSMutableDictionary *parentDict = [self.dictionaryStack lastObject]; - - // Create the child dictionary for the new element, and initilaize it with the attributes - NSMutableDictionary *childDict = [NSMutableDictionary dictionary]; - [childDict addEntriesFromDictionary:attributeDict]; - - // If there's already an item for this key, it means we need to create an array - id existingValue = [parentDict objectForKey:elementName]; - if (existingValue) - { - NSMutableArray *array = nil; - if ([existingValue isKindOfClass:[NSMutableArray class]]) - { - // The array exists, so use it - array = (NSMutableArray *) existingValue; - } - else - { - // Create an array if it doesn't exist - array = [NSMutableArray array]; - [array addObject:existingValue]; - - // Replace the child dictionary with an array of children dictionaries - [parentDict setObject:array forKey:elementName]; - } - - // Add the new child dictionary to the array - [array addObject:childDict]; - } - else - { - // No existing value, so update the dictionary - [parentDict setObject:childDict forKey:elementName]; - } - - // Update the stack - [self.dictionaryStack addObject:childDict]; -} - -- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName -{ - // Update the parent dict with text info - NSMutableDictionary *dictInProgress = [self.dictionaryStack lastObject]; - - // Set the text property - if ([self.textInProgress length] > 0) - { - // trim after concatenating - NSString *trimmedString = [self.textInProgress stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - [dictInProgress setObject:[trimmedString mutableCopy] forKey:kXMLReaderTextNodeKey]; - - // Reset the text - self.textInProgress = [[NSMutableString alloc] init]; - } - - // Pop the current dict - [self.dictionaryStack removeLastObject]; -} - -- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string -{ - // Build the text value - [self.textInProgress appendString:string]; -} - -- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError -{ - // Set the error pointer to the parser's error object - self.errorPointer = parseError; -} - -@end diff --git a/WeChatPlugin/Sources/Vendor/fishhook.c b/WeChatPlugin/Sources/Vendor/fishhook.c index 205ee82b..fb41e8ec 100755 --- a/WeChatPlugin/Sources/Vendor/fishhook.c +++ b/WeChatPlugin/Sources/Vendor/fishhook.c @@ -21,15 +21,20 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#import "fishhook.h" +#include "fishhook.h" -#import -#import -#import -#import -#import -#import -#import +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef __LP64__ typedef struct mach_header_64 mach_header_t; @@ -76,6 +81,36 @@ static int prepend_rebindings(struct rebindings_entry **rebindings_head, return 0; } +#if 0 +static int get_protection(void *addr, vm_prot_t *prot, vm_prot_t *max_prot) { + mach_port_t task = mach_task_self(); + vm_size_t size = 0; + vm_address_t address = (vm_address_t)addr; + memory_object_name_t object; +#ifdef __LP64__ + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; + vm_region_basic_info_data_64_t info; + kern_return_t info_ret = vm_region_64( + task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_64_t)&info, &count, &object); +#else + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; + vm_region_basic_info_data_t info; + kern_return_t info_ret = vm_region(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info, &count, &object); +#endif + if (info_ret == KERN_SUCCESS) { + if (prot != NULL) + *prot = info.protection; + + if (max_prot != NULL) + *max_prot = info.max_protection; + + return 0; + } + + return -1; +} +#endif + static void perform_rebinding_with_section(struct rebindings_entry *rebindings, section_t *section, intptr_t slide, @@ -84,6 +119,7 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, uint32_t *indirect_symtab) { uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); + for (uint i = 0; i < section->size / sizeof(void *); i++) { uint32_t symtab_index = indirect_symbol_indices[i]; if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || @@ -92,18 +128,33 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings, } uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; char *symbol_name = strtab + strtab_offset; - if (strnlen(symbol_name, 2) < 2) { - continue; - } + bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1]; struct rebindings_entry *cur = rebindings; while (cur) { for (uint j = 0; j < cur->rebindings_nel; j++) { - if (strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { - if (cur->rebindings[j].replaced != NULL && - indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { + if (symbol_name_longer_than_1 && strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { + kern_return_t err; + + if (cur->rebindings[j].replaced != NULL && indirect_symbol_bindings[i] != cur->rebindings[j].replacement) *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; + + /** + * 1. Moved the vm protection modifying codes to here to reduce the + * changing scope. + * 2. Adding VM_PROT_WRITE mode unconditionally because vm_region + * API on some iOS/Mac reports mismatch vm protection attributes. + * -- Lianfu Hao Jun 16th, 2021 + **/ + err = vm_protect (mach_task_self (), (uintptr_t)indirect_symbol_bindings, section->size, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY); + if (err == KERN_SUCCESS) { + /** + * Once we failed to change the vm protection, we + * MUST NOT continue the following write actions! + * iOS 15 has corrected the const segments prot. + * -- Lionfore Hao Jun 11th, 2021 + **/ + indirect_symbol_bindings[i] = cur->rebindings[j].replacement; } - indirect_symbol_bindings[i] = cur->rebindings[j].replacement; goto symbol_loop; } } @@ -187,6 +238,9 @@ int rebind_symbols_image(void *header, struct rebindings_entry *rebindings_head = NULL; int retval = prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide); + if (rebindings_head) { + free(rebindings_head->rebindings); + } free(rebindings_head); return retval; } diff --git a/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyCell.m b/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyCell.m index d22d5c72..39c12c93 100644 --- a/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyCell.m +++ b/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyCell.m @@ -34,10 +34,10 @@ - (void)initSubviews { btn; }); - + self.keywordLabel = ({ NSTextField *label = [NSTextField tk_labelWithString:@""]; - label.placeholderString = @"关键字"; + label.placeholderString = TKLocalizedString(@"assistant.autoReply.keyword"); [[label cell] setLineBreakMode:NSLineBreakByCharWrapping]; [[label cell] setTruncatesLastVisibleLine:YES]; label.font = [NSFont systemFontOfSize:10]; @@ -48,7 +48,7 @@ - (void)initSubviews { self.replyContentLabel = ({ NSTextField *label = [NSTextField tk_labelWithString:@""]; - label.placeholderString = @"回复内容"; + label.placeholderString = TKLocalizedString(@"assistant.autoReply.content"); [[label cell] setLineBreakMode:NSLineBreakByCharWrapping]; [[label cell] setTruncatesLastVisibleLine:YES]; label.frame = NSMakeRect(30, 10, 160, 15); diff --git a/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyContentView.m b/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyContentView.m index 03a1a240..5eac1e83 100644 --- a/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyContentView.m +++ b/WeChatPlugin/Sources/Views/AutoReply/TKAutoReplyContentView.m @@ -7,6 +7,7 @@ // #import "TKAutoReplyContentView.h" +#import "WeChatPlugin.h" @interface TKAutoReplyContentView () @@ -17,6 +18,10 @@ @interface TKAutoReplyContentView () @property (nonatomic, strong) NSButton *enableGroupReplyBtn; @property (nonatomic, strong) NSButton *enableSingleReplyBtn; @property (nonatomic, strong) NSButton *enableRegexBtn; +@property (nonatomic, strong) NSTextField *delayField; +@property (nonatomic, strong) NSButton *enableDelayBtn; +@property (nonatomic, strong) NSButton *enableSpecificReplyBtn; +@property (nonatomic, strong) NSButton *selectSessionButton; @end @@ -31,55 +36,94 @@ - (instancetype)init { } - (void)initSubviews { + self.enableSpecificReplyBtn = ({ + NSButton *btn = [NSButton tk_checkboxWithTitle:TKLocalizedString(@"assistant.autoReply.enableSpecific") target:self action:@selector(clickEnableSpecificReplyBtn:)]; + btn.frame = NSMakeRect(20, 0, 400, 20); + + btn; + }); + + self.selectSessionButton = ({ + NSButton *btn = [NSButton tk_buttonWithTitle:TKLocalizedString(@"assistant.autoReply.selectSpecific") target:self action:@selector(clickSelectSessionButton:)]; + btn.frame = NSMakeRect(200, 0, 150, 20); + btn.bezelStyle = NSBezelStyleTexturedRounded; + + btn; + }); + self.enableRegexBtn = ({ - NSButton *btn = [NSButton tk_checkboxWithTitle:@"开启正则匹配" target:self action:@selector(clickEnableRegexBtn:)]; - btn.frame = NSMakeRect(20, 15, 400, 20); + NSButton *btn = [NSButton tk_checkboxWithTitle:TKLocalizedString(@"assistant.autoReply.enableRegEx") target:self action:@selector(clickEnableRegexBtn:)]; + btn.frame = NSMakeRect(20, 25, 400, 20); btn; }); self.enableGroupReplyBtn = ({ - NSButton *btn = [NSButton tk_checkboxWithTitle:@"开启群聊自动回复" target:self action:@selector(clickEnableGroupBtn:)]; - btn.frame = NSMakeRect(20, 40, 400, 20); + NSButton *btn = [NSButton tk_checkboxWithTitle:TKLocalizedString(@"assistant.autoReply.enableGroup") target:self action:@selector(clickEnableGroupBtn:)]; + btn.frame = NSMakeRect(20, 50, 400, 20); btn; }); self.enableSingleReplyBtn = ({ - NSButton *btn = [NSButton tk_checkboxWithTitle:@"开启私聊自动回复" target:self action:@selector(clickEnableSingleBtn:)]; - btn.frame = NSMakeRect(200, 40, 400, 20); + NSButton *btn = [NSButton tk_checkboxWithTitle:TKLocalizedString(@"assistant.autoReply.enableSingle") target:self action:@selector(clickEnableSingleBtn:)]; + btn.frame = NSMakeRect(200, 50, 400, 20); btn; }); + self.enableDelayBtn = ({ + NSButton *btn = [NSButton tk_checkboxWithTitle:TKLocalizedString(@"assistant.autoReply.delay") target:self action:@selector(clickEnableDelayBtn:)]; + btn.frame = NSMakeRect(200, 25, 85, 20); + + btn; + }); + + self.delayField = ({ + NSTextField *textField = [[NSTextField alloc] init]; + textField.frame = NSMakeRect(CGRectGetMaxX(self.enableDelayBtn.frame), 25, 60, 20); + textField.placeholderString = TKLocalizedString(@"assistant.autoReply.timeUnit"); + textField.delegate = self; + textField.alignment = NSTextAlignmentRight; + NSNumberFormatter * formater = [[NSNumberFormatter alloc] init]; + formater.numberStyle = NSNumberFormatterDecimalStyle; + formater.minimum = @(0); + formater.maximum = @(999); + textField.cell.formatter = formater; + + textField; + }); + self.autoReplyContentField = ({ NSTextField *textField = [[NSTextField alloc] init]; - textField.frame = NSMakeRect(20, 70, 350, 175); - textField.placeholderString = @"请输入自动回复的内容(‘|’ 为随机回复其中任一内容)"; + textField.frame = NSMakeRect(20, 80, 350, 175); + textField.placeholderString = TKLocalizedString(@"assistant.autoReply.contentPlaceholder"); textField.delegate = self; textField; }); self.autoReplyLabel = ({ - NSTextField *label = [NSTextField tk_labelWithString:@"自动回复:"]; - label.frame = NSMakeRect(20, 250, 350, 20); + NSString *text = [NSString stringWithFormat:@"%@: ",TKLocalizedString(@"assistant.autoReply.content")]; + NSTextField *label = [NSTextField tk_labelWithString:text]; + label.frame = NSMakeRect(20, 260, 350, 20); label; }); self.keywordTextField = ({ NSTextField *textField = [[NSTextField alloc] init]; - textField.frame = NSMakeRect(20, 290, 350, 50); - textField.placeholderString = @"请输入关键字( ‘*’ 为任何消息都回复,‘|’ 为匹配多个关键字)"; + textField.frame = NSMakeRect(20, 300, 350, 50); + textField.placeholderString = TKLocalizedString(@"assistant.autoReply.keywordPlaceholder"); textField.delegate = self; textField; }); self.keywordLabel = ({ - NSTextField *label = [NSTextField tk_labelWithString:@"关键字:"]; - label.frame = NSMakeRect(20, 345, 350, 20); + NSString *text = [NSString stringWithFormat:@"%@: ",TKLocalizedString(@"assistant.autoReply.keyword")]; + NSTextField *label = [NSTextField tk_labelWithString:text]; + label.frame = NSMakeRect(20, 355, 350, 20); label; }); @@ -90,7 +134,25 @@ - (void)initSubviews { self.autoReplyContentField, self.autoReplyLabel, self.keywordTextField, - self.keywordLabel]]; + self.keywordLabel, + self.delayField, + self.enableDelayBtn, + self.enableSpecificReplyBtn, + self.selectSessionButton]]; +} + +- (void)clickEnableSpecificReplyBtn:(NSButton *)btn { + self.selectSessionButton.hidden = !btn.state; + self.enableGroupReplyBtn.hidden = btn.state; + self.enableSingleReplyBtn.hidden = btn.state; + if (btn.state) { + [self selectSessionAction]; + } + self.model.enableSpecificReply = btn.state; +} + +- (void)clickSelectSessionButton:(NSButton *)btn { + [self selectSessionAction]; } - (void)clickEnableRegexBtn:(NSButton *)btn { @@ -118,6 +180,10 @@ - (void)clickEnableSingleBtn:(NSButton *)btn { if (self.endEdit) self.endEdit(); } +- (void)clickEnableDelayBtn:(NSButton *)btn { + self.model.enableDelay = btn.state; +} + - (void)viewDidMoveToSuperview { [super viewDidMoveToSuperview]; self.layer.backgroundColor = [kBG2 CGColor]; @@ -135,6 +201,33 @@ - (void)setModel:(TKAutoReplyModel *)model { self.enableGroupReplyBtn.state = model.enableGroupReply; self.enableSingleReplyBtn.state = model.enableSingleReply; self.enableRegexBtn.state = model.enableRegex; + self.enableDelayBtn.state = model.enableDelay; + self.delayField.stringValue = [NSString stringWithFormat:@"%ld",model.delayTime]; + self.enableSpecificReplyBtn.state = model.enableSpecificReply; + + self.selectSessionButton.hidden = !model.enableSpecificReply; + self.enableGroupReplyBtn.hidden = model.enableSpecificReply; + self.enableSingleReplyBtn.hidden = model.enableSpecificReply; +} + +- (void)selectSessionAction { + MMSessionPickerWindow *picker = [objc_getClass("MMSessionPickerWindow") shareInstance]; + [picker setType:1]; + [picker setShowsGroupChats:0x1]; + [picker setShowsOtherNonhumanChats:0]; + [picker setShowsOfficialAccounts:0]; + MMSessionPickerLogic *logic = [picker.listViewController valueForKey:@"m_logic"]; + NSMutableOrderedSet *orderSet = [logic valueForKey:@"_selectedUserNamesSet"]; + + [orderSet addObjectsFromArray:self.model.specificContacts]; + [picker.choosenViewController setValue:self.model.specificContacts forKey:@"selectedUserNames"]; + [picker beginSheetForWindow:self.window completionHandler:^(NSOrderedSet *a1) { + NSMutableArray *array = [NSMutableArray array]; + [a1 enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [array addObject:obj]; + }]; + self.model.specificContacts = [array copy]; + }]; } - (void)controlTextDidEndEditing:(NSNotification *)notification { @@ -147,6 +240,8 @@ - (void)controlTextDidChange:(NSNotification *)notification { self.model.keyword = self.keywordTextField.stringValue; } else if (control == self.autoReplyContentField) { self.model.replyContent = self.autoReplyContentField.stringValue; + } else if (control == self.delayField) { + self.model.delayTime = [self.delayField.stringValue integerValue]; } } diff --git a/WeChatPlugin/Sources/Views/RemoteControl/TKRemoteControlCell.m b/WeChatPlugin/Sources/Views/RemoteControl/TKRemoteControlCell.m index 6c321519..dd71656d 100644 --- a/WeChatPlugin/Sources/Views/RemoteControl/TKRemoteControlCell.m +++ b/WeChatPlugin/Sources/Views/RemoteControl/TKRemoteControlCell.m @@ -38,7 +38,7 @@ - (void)initSubviews { self.textField = ({ NSTextField *v = [[NSTextField alloc] init]; v.frame = NSMakeRect(200, 10, 250, 30); - v.placeholderString = @"请输入匹配的关键词"; + v.placeholderString = TKLocalizedString(@"assistant.remoteControl.contentPlaceHodler"); v.layer.cornerRadius = 10; v.layer.masksToBounds = YES; [v.layer setNeedsDisplay]; @@ -58,7 +58,7 @@ - (void)clickSelectBtn:(NSButton *)btn { - (void)setupWithData:(id)data { TKRemoteControlModel *model = data; self.model = model; - self.selectBtn.title = model.function; + self.selectBtn.title = TKLocalizedString(model.function); self.selectBtn.state = model.enable; self.textField.stringValue = model.keyword; } diff --git a/WeChatPlugin/Sources/WindowControllers/About/Base.lproj/TKAboutWindowController.xib b/WeChatPlugin/Sources/WindowControllers/About/Base.lproj/TKAboutWindowController.xib new file mode 100644 index 00000000..1c07d8cb --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/About/Base.lproj/TKAboutWindowController.xib @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatPlugin/Sources/WindowControllers/About/TKAboutWindowController.h b/WeChatPlugin/Sources/WindowControllers/About/TKAboutWindowController.h new file mode 100644 index 00000000..13974da8 --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/About/TKAboutWindowController.h @@ -0,0 +1,13 @@ +// +// TKAboutWindowController.h +// WeChatPlugin +// +// Created by TK on 2018/5/4. +// Copyright © 2018年 tk. All rights reserved. +// + +#import + +@interface TKAboutWindowController : NSWindowController + +@end diff --git a/WeChatPlugin/Sources/WindowControllers/About/TKAboutWindowController.m b/WeChatPlugin/Sources/WindowControllers/About/TKAboutWindowController.m new file mode 100644 index 00000000..e51f7394 --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/About/TKAboutWindowController.m @@ -0,0 +1,32 @@ +// +// TKAboutWindowController.m +// WeChatPlugin +// +// Created by TK on 2018/5/4. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKAboutWindowController.h" + +@interface TKAboutWindowController () + +@property (unsafe_unretained) IBOutlet NSTextView *textView; +@property (weak) IBOutlet NSTextField *versionLabel; + +@end + +@implementation TKAboutWindowController + +- (void)windowDidLoad { + [super windowDidLoad]; + self.window.backgroundColor = [NSColor whiteColor]; + NSDictionary *localInfo = [[TKWeChatPluginConfig sharedConfig] localInfoPlist]; + NSString *localBundle = localInfo[@"CFBundleShortVersionString"]; + self.versionLabel.stringValue = localBundle; + + NSString *path = [[NSBundle bundleWithIdentifier:@"tk.WeChatPlugin"] pathForResource:@"about" ofType:@"rtfd"]; + [self.textView readRTFDFromFile:path]; + self.textView.selectable = YES; +} + +@end diff --git a/WeChatPlugin/Sources/WindowControllers/About/en.lproj/TKAboutWindowController.xib b/WeChatPlugin/Sources/WindowControllers/About/en.lproj/TKAboutWindowController.xib new file mode 100644 index 00000000..b94e5726 --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/About/en.lproj/TKAboutWindowController.xib @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatPlugin/Sources/WindowControllers/About/zh-Hant.lproj/TKAboutWindowController.xib b/WeChatPlugin/Sources/WindowControllers/About/zh-Hant.lproj/TKAboutWindowController.xib new file mode 100644 index 00000000..b9a552d8 --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/About/zh-Hant.lproj/TKAboutWindowController.xib @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatPlugin/Sources/WindowControllers/AutoReply/TKAutoReplyWindowController.m b/WeChatPlugin/Sources/WindowControllers/AutoReply/TKAutoReplyWindowController.m index 190b50aa..e62c6629 100644 --- a/WeChatPlugin/Sources/WindowControllers/AutoReply/TKAutoReplyWindowController.m +++ b/WeChatPlugin/Sources/WindowControllers/AutoReply/TKAutoReplyWindowController.m @@ -8,7 +8,6 @@ #import "TKAutoReplyWindowController.h" #import "TKAutoReplyContentView.h" -#import "WeChatPlugin.h" #import "TKAutoReplyCell.h" @interface TKAutoReplyWindowController () @@ -17,6 +16,7 @@ @interface TKAutoReplyWindowController () + +@interface TKDownloadWindowController : NSWindowController + ++ (instancetype)downloadWindowController; + +@end diff --git a/WeChatPlugin/Sources/WindowControllers/Download/TKDownloadWindowController.m b/WeChatPlugin/Sources/WindowControllers/Download/TKDownloadWindowController.m new file mode 100644 index 00000000..808c807f --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/Download/TKDownloadWindowController.m @@ -0,0 +1,119 @@ +// +// TKDownloadWindowController.m +// WeChatPlugin +// +// Created by TK on 2018/4/28. +// Copyright © 2018年 tk. All rights reserved. +// + +#import "TKDownloadWindowController.h" +#import "TKVersionManager.h" +#import "TKRemoteControlManager.h" + +typedef NS_ENUM(NSUInteger, TKDownloadState) { + TKDownloadStateProgress, + TKDownloadStateFinish, + TKDownloadStateError, +}; + +@interface TKDownloadWindowController () + +@property (weak) IBOutlet NSTextField *titleLabel; +@property (weak) IBOutlet NSButton *installButton; +@property (weak) IBOutlet NSProgressIndicator *progressView; +@property (weak) IBOutlet NSTextField *progressLabel; +@property (nonatomic, assign) TKDownloadState downloadState; +@property (nonatomic, copy) NSString *filePath; + +@end + +@implementation TKDownloadWindowController + ++ (instancetype)downloadWindowController { + static TKDownloadWindowController *windowController = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + windowController = [[TKDownloadWindowController alloc] initWithWindowNibName:@"TKDownloadWindowController"]; + }); + return windowController; +} + +- (void)windowDidLoad { + [super windowDidLoad]; + + [self setup]; +} + +- (void)setup { + [self downloadPlugin]; +} + +- (void)setupInstallBtnTitle:(NSString *)text { + self.installButton.title = text; + + CGFloat stringWidth = [text widthWithFont:self.installButton.font]; + self.installButton.width = stringWidth + 40; + self.installButton.x = 430 - stringWidth - 40; +} + +- (void)downloadPlugin { + self.downloadState = TKDownloadStateProgress; + self.window.title = TKLocalizedString(@"assistant.download.title"); + self.titleLabel.stringValue = TKLocalizedString(@"assistant.download.update"); + self.progressView.doubleValue = 0; + [self setupInstallBtnTitle:TKLocalizedString(@"assistant.download.cancel")]; + + [[TKVersionManager shareManager] downloadPluginProgress:^(NSProgress *downloadProgress) { + dispatch_async(dispatch_get_main_queue(), ^{ + self.progressView.minValue = 0; + self.progressView.maxValue = downloadProgress.totalUnitCount / 1024.0; + self.progressView.doubleValue = downloadProgress.completedUnitCount / 1024.0; + CGFloat currentCount = downloadProgress.completedUnitCount / 1024.0 / 1024.0; + CGFloat totalCount = downloadProgress.totalUnitCount / 1024.0 / 1024.0; + self.progressLabel.stringValue = [NSString stringWithFormat:@"%.2lf MB / %.2lf MB", currentCount, totalCount]; + }); + } completionHandler:^(NSString *filePath, NSError * _Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + self.downloadState = TKDownloadStateError; + if (error.code == NSURLErrorCancelled) { + self.titleLabel.stringValue = TKLocalizedString(@"assistant.download.cancelTitle"); + [self setupInstallBtnTitle:TKLocalizedString(@"assistant.download.reDownload")]; + self.progressLabel.stringValue = @""; + } else { + self.titleLabel.stringValue = TKLocalizedString(@"assistant.download.error"); + [self setupInstallBtnTitle:TKLocalizedString(@"assistant.download.reInstall")]; + } + return; + } + self.downloadState = TKDownloadStateFinish; + [self setupInstallBtnTitle:TKLocalizedString(@"assistant.download.relaunch")]; + self.titleLabel.stringValue = TKLocalizedString(@"assistant.download.install"); + self.filePath = filePath; + }); + }]; +} + +- (IBAction)clickInstallButton:(NSButton *)sender { + switch (self.downloadState) { + case TKDownloadStateProgress: { + [[TKVersionManager shareManager] cancelDownload]; + break; + } + case TKDownloadStateFinish: { + NSString *directoryName = [self.filePath stringByDeletingLastPathComponent]; + NSString *fileName = [[self.filePath lastPathComponent] stringByDeletingPathExtension]; + NSString *cmdString = [NSString stringWithFormat:@"cd %@ && unzip -n %@.zip && ./%@/Other/Update.sh && killall WeChat && sleep 2s && open /Applications/WeChat.app",directoryName, fileName, fileName]; + [TKRemoteControlManager executeShellCommand:cmdString]; + break; + } + case TKDownloadStateError: { + [self downloadPlugin]; + break; + } + default: + break; + } +} + +@end diff --git a/WeChatPlugin/Sources/WindowControllers/Download/TKDownloadWindowController.xib b/WeChatPlugin/Sources/WindowControllers/Download/TKDownloadWindowController.xib new file mode 100644 index 00000000..e338d033 --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/Download/TKDownloadWindowController.xib @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatPlugin/Sources/WindowControllers/RemoteControl/Base.lproj/TKRemoteControlWindowController.xib b/WeChatPlugin/Sources/WindowControllers/RemoteControl/Base.lproj/TKRemoteControlWindowController.xib new file mode 100644 index 00000000..d3ce9d0b --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/RemoteControl/Base.lproj/TKRemoteControlWindowController.xib @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.m b/WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.m index b0ab7430..e5b9e730 100644 --- a/WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.m +++ b/WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.m @@ -29,29 +29,39 @@ - (void)windowDidLoad { } - (void)initSubviews { - - CGFloat tabViewWidth = self.tabView.frame.size.width; - CGFloat tabViewHeight = self.tabView.frame.size.height; - + CGFloat scrollViewWidth = self.tabView.frame.size.width -100; + CGFloat scrollViewHeight = self.tabView.frame.size.height -110; + self.tableView = ({ NSTableView *tableView = [[NSTableView alloc] init]; - tableView.frame = NSMakeRect(50, 50, tabViewWidth, tabViewHeight); + tableView.frame = NSMakeRect(0, 0, scrollViewWidth, scrollViewHeight); + tableView.headerView = nil; tableView.delegate = self; tableView.dataSource = self; NSTableColumn *column = [[NSTableColumn alloc] init]; - column.width = tabViewWidth - 100; + column.width = scrollViewWidth - 50; [tableView addTableColumn:column]; tableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleNone; tableView.backgroundColor = [NSColor clearColor]; tableView; }); + + NSScrollView *scrollView = ({ + NSScrollView *view = [[NSScrollView alloc] initWithFrame:NSMakeRect(50, 50, scrollViewWidth, scrollViewHeight)]; + view.documentView = self.tableView; + view.hasVerticalScroller = YES; + view.autohidesScrollers = YES; + view.drawsBackground = NO; + + view; + }); - [self.tabView addSubview:self.tableView]; + [self.tabView addSubview:scrollView]; } - (void)setup { - self.window.contentView.layer.backgroundColor = [NSColor whiteColor].CGColor; + self.window.contentView.layer.backgroundColor = [NSColor windowBackgroundColor].CGColor; [self.window.contentView.layer setNeedsDisplay]; self.remoteControlModels = [[TKWeChatPluginConfig sharedConfig] remoteControlModels][0]; } diff --git a/WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.xib b/WeChatPlugin/Sources/WindowControllers/RemoteControl/zh-Hans.lproj/TKRemoteControlWindowController.xib similarity index 92% rename from WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.xib rename to WeChatPlugin/Sources/WindowControllers/RemoteControl/zh-Hans.lproj/TKRemoteControlWindowController.xib index 8ad75ba6..f3d2a20f 100644 --- a/WeChatPlugin/Sources/WindowControllers/RemoteControl/TKRemoteControlWindowController.xib +++ b/WeChatPlugin/Sources/WindowControllers/RemoteControl/zh-Hans.lproj/TKRemoteControlWindowController.xib @@ -1,8 +1,8 @@ - + - + @@ -29,14 +29,14 @@ - + - + - + @@ -68,6 +68,12 @@ + + + + + + diff --git a/WeChatPlugin/Sources/WindowControllers/RemoteControl/zh-Hant.lproj/TKRemoteControlWindowController.xib b/WeChatPlugin/Sources/WindowControllers/RemoteControl/zh-Hant.lproj/TKRemoteControlWindowController.xib new file mode 100644 index 00000000..94234ab5 --- /dev/null +++ b/WeChatPlugin/Sources/WindowControllers/RemoteControl/zh-Hant.lproj/TKRemoteControlWindowController.xib @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatPlugin/TKRemoteControlScript.scpt b/WeChatPlugin/TKRemoteControlScript.scpt index a2d8dd34..b33ba035 100644 Binary files a/WeChatPlugin/TKRemoteControlScript.scpt and b/WeChatPlugin/TKRemoteControlScript.scpt differ diff --git a/WeChatPlugin/WeChatPlugin.h b/WeChatPlugin/WeChatPlugin.h index cf445b9d..3429ecc5 100644 --- a/WeChatPlugin/WeChatPlugin.h +++ b/WeChatPlugin/WeChatPlugin.h @@ -13,8 +13,28 @@ FOUNDATION_EXPORT double WeChatPluginVersionNumber; FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; +@class WCContactData; + #pragma mark - 微信原始的部分类与方法 +@interface MMSystemLinkInfo : NSObject +@property(retain, nonatomic) NSMutableAttributedString *msgContent; + +@end +@interface MMContactProfileController : NSViewController +@property(copy, nonatomic) NSString *groupName; +@property(nonatomic) struct CGRect relativeToRect; +@property(nonatomic) unsigned long long preferredEdge; +@property(retain, nonatomic) WCContactData *contactData; +- (void)sendGetContactRequest:(id)arg1 withGroupName:(id)arg2; +- (void)showInView:(id)arg1; +@end + + +@interface MMBrandChatsViewController : NSObject +- (void)startChatWithContact:(id)arg1; +@end + @interface MMLoginOneClickViewController : NSViewController @property(nonatomic) NSTextField *descriptionLabel; - (void)onLoginButtonClicked:(id)arg1; @@ -28,25 +48,48 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; - (void)AutoAuth; - (void)ManualLogin:(id)arg1 withPassword:(id)arg2; - (void)ManualLogout; +- (void)FFAddSvrMsgImgVCZZ; - (void)QRCodeLoginWithUserName:(id)arg1 password:(id)arg2; +- (void)onAuthOKOfUser:(id)arg1 withSessionKey:(id)arg2 withServerId:(id)arg3 autoAuthKey:(id)arg4 isAutoAuth:(BOOL)arg5; @end @interface MMLoginViewController : NSObject @property(retain, nonatomic) MMLoginOneClickViewController *oneClickViewController; @end +@interface MMHandoffButton : NSView +@end + +@interface MMMainViewController : NSObject +@property(nonatomic) __weak MMHandoffButton *handoffButton; +@end + @interface MMMainWindowController : NSWindowController @property(retain, nonatomic) MMLoginViewController *loginViewController; +@property(retain, nonatomic) MMMainViewController *mainViewController; - (void)onAuthOK; - (void)onLogOut; @end -@interface MessageService : NSObject +@interface MMVoiceTranscribeCGI : NSObject +- (void)transcribeVoiceMessage:(id)arg1 withCompletion:(void (^)(void))arg2; +@end + +@interface FFProcessReqsvrZZ : NSObject - (void)onRevokeMsg:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1; +- (void)FFToNameFavChatZZ:(id)arg1 sessionMsgList:(id)arg2; - (void)OnSyncBatchAddMsgs:(NSArray *)arg1 isFirstSync:(BOOL)arg2; -- (id)SendTextMessage:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; +- (void)FFImgToOnFavInfoInfoVCZZ:(id)arg1 isFirstSync:(BOOL)arg2; +- (id)FFProcessTReqZZ:(id)arg1 toUsrName:(id)arg2 msgText:(id)arg3 atUserList:(id)arg4; - (id)GetMsgData:(id)arg1 svrId:(long)arg2; - (void)AddLocalMsg:(id)arg1 msgData:(id)arg2; +- (void)TranscribeVoiceMessage:(id)arg1 completion:(void (^)(void))arg2; +- (BOOL)ClearUnRead:(id)arg1 FromID:(unsigned int)arg2 ToID:(unsigned int)arg3; +- (BOOL)ClearUnRead:(id)arg1 FromCreateTime:(unsigned int)arg2 ToCreateTime:(unsigned int)arg3; +- (BOOL)HasMsgInChat:(id)arg1; +- (id)GetMsgListWithChatName:(id)arg1 fromCreateTime:(unsigned int)arg2 localId:(NSInteger)arg3 limitCnt:(NSInteger)arg4 hasMore:(char *)arg5 sortAscend:(BOOL)arg6; +- (void)DelMsg:(id)arg1 msgList:(id)arg2 isDelAll:(BOOL)arg3 isManual:(BOOL)arg4; @end @interface MMServiceCenter : NSObject @@ -64,10 +107,27 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic, setter=SetMsgType:) int msgType; // @synthesize msgType; @property(retain, nonatomic, setter=SetToUserName:) SKBuiltinString_t *toUserName; // @synthesize toUserName; @property (nonatomic, assign) unsigned int createTime; +@property(nonatomic, setter=SetNewMsgId:) long long newMsgId; +@end + +@interface MMChatMessageViewController : NSViewController +@property(retain, nonatomic) WCContactData *chatContact; +@property(nonatomic) __weak NSTableView *messageTableView; +- (void)scrollToMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(NSUInteger)arg1; +- (BOOL)showLocatedMessage:(unsigned int)arg1 needHighLighted:(BOOL)arg2; +- (void)onClickSession; +- (void)reloadTableView; +@end + +@interface MMChatDetailSplitViewController : NSObject +@property(retain, nonatomic) MMChatMessageViewController *chatMessageViewController; @end @interface MMChatsViewController : NSViewController @property(nonatomic) __weak NSTableView *tableView; +@property(retain, nonatomic) MMBrandChatsViewController *brandChatsViewController; +@property(retain, nonatomic) MMChatDetailSplitViewController *chatDetailSplitViewController; @end @interface WeChat : NSObject @@ -75,16 +135,67 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(nonatomic) MMChatsViewController *chatsViewController; @property(retain, nonatomic) MMMainWindowController *mainWindowController; @property(nonatomic) BOOL isAppTerminating; +@property(nonatomic) BOOL hasAuthOK; +- (void)startANewChatWithContact:(id)arg1; +- (void)_clearAllUnreadMessages:(id)arg1; +- (void)onAuthOK:(BOOL)arg1; +- (void)checkForUpdatesInBackground; +- (void)FFAddRecvFavZZ:(BOOL)arg1; @end @interface ContactStorage : NSObject - (id)GetSelfContact; - (id)GetContact:(id)arg1; +- (id)GetAllBrandContacts; +- (id)GetAllFavContacts; +- (id)GetAllFriendContacts; +@end + +@interface GroupStorage : NSObject +{ + NSMutableDictionary *m_dictGroupContacts; +} +- (id)GetAllGroups; +- (id)GetGroupMemberContact:(id)arg1; +- (void)notifyModifyGroupContactsOnMainThread:(id)arg1; +//- (id)GetGroupMemberListWithGroupContact:(id)arg1; +- (id)GetGroupMemberListWithGroupContact:(id)arg1 limit:(unsigned int)arg2 filterSelf:(BOOL)arg3; +@end + +@interface ChatRoomData : NSObject +{ + NSMutableDictionary *m_dicData; +} @end @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; // 头像 +@property(retain, nonatomic) NSString *m_nsHeadHDImgUrl; +@property(retain, nonatomic) NSString *m_nsHeadHDMd5; +@property(retain, nonatomic) NSString *m_nsAliasName; +@property(retain, nonatomic) NSString *avatarCacheKey; +@property(readonly, nonatomic) unsigned long long groupMemberCount; +@property(retain, nonatomic) ChatRoomData *m_chatRoomData; +@property(nonatomic) BOOL m_isShowRedDot; +- (BOOL)isBrandContact; +- (BOOL)isSelf; +- (id)innerGetGroupDisplayName; +- (NSString *)groupChatDisplayNameInGroup:(id)arg1; +- (id)getContactDisplayUsrName; +- (BOOL)isGroupChat; +- (BOOL)isMMChat; +- (BOOL)isMMContact; +- (BOOL)containsMember:(id)arg1; +- (id)displayRegion; +- (BOOL)isStickyFolder; +@end + +@interface WCPayInfoItem : NSObject +@property(retain, nonatomic) NSString *m_nsFeeDesc; @end @interface MessageData : NSObject @@ -93,25 +204,66 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @property(retain, nonatomic) NSString *toUsrName; @property(retain, nonatomic) NSString *msgContent; @property(retain, nonatomic) NSString *msgPushContent; +@property(retain, nonatomic) NSString *realChatUserName; +@property(retain, nonatomic) WCPayInfoItem *m_oWCPayInfoItem; // @dynamic m_oWCPayInfoItem; +@property(retain, nonatomic) NSString *m_nsAppName; +@property(retain, nonatomic) NSString *m_nsSourceDisplayname; @property(nonatomic) int messageType; @property(nonatomic) int msgStatus; @property(nonatomic) int msgCreateTime; @property(nonatomic) int mesLocalID; +@property(nonatomic) long long mesSvrID; +@property(retain, nonatomic) NSString *msgVoiceText; +@property(copy, nonatomic) NSString *m_nsEmoticonMD5; +- (BOOL)isChatRoomMessage; +- (NSString *)groupChatSenderDisplayName; +- (id)getRealMessageContent; +- (id)getChatRoomUsrName; +- (BOOL)isSendFromSelf; +- (BOOL)isCustomEmojiMsg; +- (BOOL)isImgMsg; +- (BOOL)isVideoMsg; +- (BOOL)isVoiceMsg; +- (BOOL)canForward; +- (BOOL)IsPlayingSound; +- (id)summaryString:(BOOL)arg1; +- (BOOL)isEmojiAppMsg; +- (BOOL)isAppBrandMsg; +- (BOOL)IsUnPlayed; +- (void)SetPlayed; +@property(retain, nonatomic) NSString *m_nsTitle; +- (id)originalImageFilePath; +@property(retain, nonatomic) NSString *m_nsVideoPath; +@property(retain, nonatomic) NSString *m_nsFilePath; +@property(retain, nonatomic) NSString *m_nsAppMediaUrl; +@property(nonatomic) MessageData *m_refMessageData; +@property(nonatomic) unsigned int m_uiDownloadStatus; +- (void)SetPlayingSoundStatus:(BOOL)arg1; @end @interface CUtility : NSObject + (BOOL)HasWechatInstance; ++ (BOOL)FFSvrChatInfoMsgWithImgZZ; + (unsigned long long)getFreeDiskSpace; + (void)ReloadSessionForMsgSync; + (id)GetCurrentUserName; ++ (id)GetContactByUsrName:(id)arg1; ++ (BOOL)IsStickyChatsFolder:(id)arg1; +@end + +@interface MMSessionInfoPackedInfo: NSObject +@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MessageData *m_msgData; @end @interface MMSessionInfo : NSObject @property(nonatomic) BOOL m_bIsTop; // @synthesize m_bIsTop; @property(nonatomic) BOOL m_bShowUnReadAsRedDot; @property(nonatomic) BOOL m_isMentionedUnread; // @synthesize +@property BOOL isInGroupBox; @property(retain, nonatomic) NSString *m_nsUserName; // @synthesize m_nsUserName; -@property(retain, nonatomic) WCContactData *m_contact; +@property(retain, nonatomic) MMSessionInfoPackedInfo *m_packedInfo; +@property(nonatomic) unsigned int m_uUnReadCount; @end @protocol MMChatsTableCellViewDelegate @@ -129,21 +281,294 @@ FOUNDATION_EXPORT const unsigned char WeChatPluginVersionString[]; @end @interface MMSessionMgr : NSObject -@property(retain, nonatomic) NSMutableArray *m_arrSession; -- (id)GetSessionAtIndex:(unsigned long long)arg1; -- (void)MuteSessionByUserName:(id)arg1; +//@property(retain, nonatomic) NSMutableArray *m_arrSession; +- (id)getSessionAtIndex:(unsigned long long)arg1; +- (id)sessionInfoByUserName:(id)arg1; +- (void)muteSessionByUserName:(id)arg1; +- (void)onUnReadCountChange:(id)arg1; //- (void)TopSessionByUserName:(id)arg1; -- (void)UnmuteSessionByUserName:(id)arg1; -- (void)UntopSessionByUserName:(id)arg1; -- (void)deleteSessionWithoutSyncToServerWithUserName:(id)arg1; +- (void)unmuteSessionByUserName:(id)arg1; +- (void)untopSessionByUserName:(id)arg1; +- (void)changeSessionUnreadCountWithUserName:(id)arg1 to:(unsigned int)arg2; +- (void)removeSessionOfUser:(id)arg1 isDelMsg:(BOOL)arg2; - (void)sortSessions; +- (void)FFDataSvrMgrSvrFavZZ; +- (id)getContact:(id)arg1; +- (id)getSessionContact:(id)arg1; +- (void)onModifyContacts:(id)arg1; +- (NSMutableArray *)getAllSessions; @end @interface LogoutCGI : NSTableCellView - (void)sendLogoutCGIWithCompletion:(id)arg1; +- (void)FFVCRecvDataAddDataToMsgChatMgrRecvZZ:(id)arg1; @end @interface MMNotificationService : NSObject - (id)getNotificationContentWithMsgData:(id)arg1; - (void)userNotificationCenter:(id)arg1 didActivateNotification:(id)arg2; @end + +@interface MMMessageTableItem : NSObject +@property(retain, nonatomic) MessageData *message; +@end + +@interface MMStickerMessageCellView : NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(nonatomic) MMChatMessageViewController *delegate; +- (BOOL)allowCopy; +- (void)contextMenuCopy; +- (id)contextMenu; +@end + +@interface MMImageMessageCellView: NSObject +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@end + +@interface MMSystemMessageCellView: NSObject +@property(nonatomic) id delegate; +@property(retain, nonatomic) MMMessageTableItem *messageTableItem; +@property(retain, nonatomic) NSTextView *msgTextView; +- (void)populateWithMessage:(id)arg1; +@end +@interface EmoticonMgr : NSObject +@property(retain, nonatomic) MessageData *message; +- (id)getEmotionDataWithMD5:(id)arg1; +- (id)getEmotionImgWithMD5:(id)arg1; +- (void)addFavEmoticon:(id)arg1; +- (void)addEmoticonToUploadQueueWithMD5:(id)arg1; +- (void)setAppStickerToastViewDelegate:(id)arg1; +@end + +@interface MMComplexContactSearchTaskMgr : NSObject ++ (id)sharedInstance; +- (void)doComplexContactSearch:(id)arg1 searchScene:(unsigned long long)arg2 complete:(void (^)(NSString *,NSArray *, NSArray *, NSArray *,id))arg3 cancelable:(BOOL)arg4; +@end + +@interface MMBasicSearchResult : NSObject +@end + +@interface MMSearchResultItem : NSObject +@property(retain, nonatomic) MMBasicSearchResult *result; +@end + +@interface MMSearchResultContainer : NSObject +@property(nonatomic) unsigned long long logicSearchResultFlag; // @synthesize +@end + +@interface MMContactSearchLogic : NSObject +{ + unsigned long long _logicSearchResultFlag; // 2.3.19 失效 +} +@property(retain, nonatomic) NSMutableArray *contactResults; +- (void)doSearchWithKeyword:(id)arg1 searchScene:(unsigned long long)arg2 resultIsShownBlock:(id)arg3 completion:(id)arg4; +@property(retain, nonatomic) NSMutableArray *groupResults; +@property(nonatomic) BOOL isBrandContactSearched; +@property(nonatomic) BOOL isChatLogSearched; +@property(nonatomic) BOOL isContactSearched; +@property(nonatomic) BOOL isGroupContactSearched; +@property(retain, nonatomic) NSMutableArray *oaResults; +- (void)clearAllResults; // 2.3.19 失效 +- (void)clearDataWhenSearchEnd; +- (void)reloadSearchResultDataWithKeyword:(id)arg1 completionBlock:(id)arg2; // 2.3.17 +- (void)reloadSearchResultDataWithCompletionBlock:(id)arg1; // 2.3.13 +- (void)reloadSearchResultDataWithKeyword:(id)arg1 resultContainer:(id)arg2 completionBlock:(id)arg3; +@property(retain, nonatomic) MMSearchResultContainer *searchResultContainer; +@end + +@interface MMComplexContactSearchResult : MMBasicSearchResult +@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 : MMBasicSearchResult +@property(retain, nonatomic) NSMutableArray *membersSearchReults; +@end + +@interface MMComplexGroupContactSearchResult : MMBasicSearchResult +@property(nonatomic) unsigned long long searchType; // 1 名称 2 群成员名称 +@property(retain) WCContactData *groupContact; +@property(retain, nonatomic) MMComplexGroupContactMembersSearchResult *groupMembersResult; +@end + +@interface MMAvatarService : NSObject +- (NSString *)avatarCachePath; +- (id)_getImageFromCacheWithMD5Key:(id)arg1; +- (void)avatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +- (void)getAvatarImageWithContact:(id)arg1 completion:(void (^)(NSImage *image))arg2; +@end + +@interface NSString (MD5) +- (id)md5String; +@end + +@interface MMSessionPickerLogic : NSObject +@property(nonatomic) NSArray *selectedUserNames; +@end + + +@interface MMSessionListView : NSObject +{ + MMSessionPickerLogic *m_logic; +} +@end + +@interface MMSessionPickerWindow : NSWindowController ++ (id)shareInstance; +- (void)beginSheetForWindow:(id)arg1 completionHandler:(void(^)(id a1))arg2; +@property(retain, nonatomic) id choosenViewController; // @synthesize +@property(retain, nonatomic) id listViewController; // @synthesize +- (void)setShowsGroupChats:(BOOL)arg1; +- (void)setShowsOfficialAccounts:(BOOL)arg1; +- (void)setShowsOtherNonhumanChats:(BOOL)arg1; +- (void)setType:(unsigned long long)arg1; + +@end + +@interface AFHTTPResponseSerializer : NSObject +@end + +@interface AFURLSessionManager : NSObject +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + progress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock + destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(void (^)(NSURLResponse *response, NSURL * filePath, NSError * error))completionHandler; +- (id)initWithSessionConfiguration:(id)arg1; +@end + +@interface AFHTTPRequestSerializer : NSObject ++ (id)serializer; +@property(nonatomic) unsigned long long cachePolicy; +@end + +@interface AFHTTPSessionManager : NSObject ++ (AFHTTPSessionManager *)manager; +@property(retain, nonatomic) AFHTTPRequestSerializer *requestSerializer; +@property(retain, nonatomic) AFHTTPResponseSerializer *responseSerializer; +@end + +@interface MMURLHandler : NSObject ++ (id)defaultHandler; +- (void)startGetA8KeyWithURL:(id)arg1; +- (BOOL)openURLWithDefault:(id)arg1; ++ (BOOL)containsHTTPString:(id)arg1; +- (void)openURLWithDefault:(id)arg1 useA8Key:(BOOL)arg2; +- (BOOL)preHandleUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface UserDefaultsService : NSObject +- (void)setString:(id)arg1 forKey:(id)arg2; +- (id)stringForKey:(id)arg1; +@end + +@interface MMLinkInfo : NSObject ++ (NSRange)rangeOfUrlInString:(id)arg1 withRange:(NSRange)arg2; +@end + +@interface MMCDNDownloadMgr : NSObject +- (BOOL)downloadImageWithMessage:(id)arg1 disableHevc:(BOOL)arg2 downloadType:(unsigned long long)arg3; +@end + +@interface MMMessageVideoService : NSObject +- (BOOL)downloadVideoWithMessage:(id)arg1; +@end + +@interface MMVoiceMessagePlayer : NSObject ++ (id)defaultPlayer; +- (void)playWithVoiceMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)playVoiceWithMessage:(id)arg1 isUnplayedBeforePlay:(BOOL)arg2; +- (void)stop; +@end + +@interface MultiPlatformStatusSyncMgr : NSObject +- (void)markVoiceMessageAsRead:(id)arg1; +@end + +@interface EmoticonDownloadMgr : NSObject +- (void)downloadEmoticonWithMessageData:(id)arg1; +@end + +@interface PathUtility : NSObject ++ (id)GetCurUserCachePath; ++ (id)emoticonPath:(id)arg1; ++ (id)getMsgVideoPathWithMessage:(id)arg1; ++ (id)getMsgVideoPathWithUserName:(id)arg1 localId:(unsigned int)arg2; +@end + +@interface MMExtensionCenter : NSObject +- (id)getExtension:(id)arg1; +@end + +@interface MMExtension : NSObject +- (BOOL)registerExtension:(id)arg1; +- (void)unregisterExtension:(id)arg1; +- (id)getExtensionListForSelector:(SEL)arg1; +@end + +@interface EmoticonMsgInfo : NSObject +@property(copy, nonatomic) NSString *cdnUrl; +@property(copy, nonatomic) NSString *m_nsMD5; +@end + +@protocol EmoticonDownloadMgrExt +@optional +- (void)emoticonDownloadFailed:(EmoticonMsgInfo *)arg1; +- (void)emoticonDownloadFinished:(EmoticonMsgInfo *)arg1; +@end + +@protocol IGroupMgrExt + +@end + +@interface MMChatMangerSearchReportMgr : NSObject +@property(retain, nonatomic) NSMutableArray *brandContactSearchResults; +@property(retain, nonatomic) NSMutableArray *chatLogSearchResults; +@property(retain, nonatomic) NSMutableArray *contactSearchResults; +@property(retain, nonatomic) NSMutableArray *groupContactSearchResults; +@end + +@interface MMWebViewHelper : NSObject ++ (BOOL)preHandleWebUrlStr:(id)arg1 withMessage:(id)arg2; +@end + +@interface XMLDictionaryParser : NSObject ++ (id)sharedInstance; +- (id)dictionaryWithString:(id)arg1; +@end + +@interface MMEmoticonData : NSObject +@property(retain, nonatomic) NSString *md5; // @synthesize md5=_md5; +@end + +@interface MMStickerPickerCell : NSView +@property(retain, nonatomic) MMEmoticonData *emoticonData; // @synthesize emoticonData=_emoticonData; +@property(nonatomic) __weak NSScrollView *collectionView; +@end + +@interface MMStickerCollectionViewController : NSViewController +@property(nonatomic) __weak id delegate; +@end + +@interface MMStickerPicker : NSViewController +- (void)hide; +@end + +@interface MMVoiceTranslateMgr : NSObject +- (void)doTranslate:(id)arg1 isAuto:(BOOL)arg2; +- (void)updateTranscribeVoiceMessage:(id)arg1 voiceText:(id)arg2 voiceToTextStatus:(unsigned int)arg3; +@end + +@interface MMAppBrandMessageCellView : NSObject ++ (id)makeAppBrandTableItemWithItem:(id)arg1; +@end + +@interface MMUnsupportedCellView : NSObject ++ (id)makeUnsupportedTableItemWithItem:(id)arg1; +@end + +@interface MMPayTransferCellView : NSObject ++ (id)makePayTransferTableItemWithItem:(id)arg1; +@end + + diff --git a/WeChatPlugin/en.lproj/Localizable.strings b/WeChatPlugin/en.lproj/Localizable.strings new file mode 100644 index 00000000..d8e54e09 --- /dev/null +++ b/WeChatPlugin/en.lproj/Localizable.strings @@ -0,0 +1,134 @@ +/* + Localizable.strings + WeChatPlugin + + Created by TK on 2018/4/14. + Copyright © 2018年 tk. All rights reserved. + */ + + +// MainMenu +"assistant.menu.title" = "Assistant"; +"assistant.menu.revoke" = "Prevent Revoke"; +"assistant.menu.revokeSelf" = "Prevent Self Message"; +"assistant.menu.autoReply" = "Auto Reply"; +"assistant.menu.newWeChat" = "New WeChat"; +"assistant.menu.remoteControl" = "Remote Control"; +"assistant.menu.windowSticky" = "Sticky on Top"; +"assistant.menu.freeLogin" = "AutoAuth Login"; +"assistant.menu.systemBrowser" = "Use System Browser"; +"assistant.menu.forbidCheck" = "Forbid WeChat Check Update"; +"assistant.menu.other" = "Others"; +"assistant.menu.enableAlfred" = "Enable Alfred"; +"assistant.menu.updateAssistant" = "Update Assistant…"; +"assistant.menu.aboutAssistant" = "About Assistant"; +"assistant.menu.memberExitMonitoring" = "Member Exit Monitoring"; +// Prevent Revoke +"assistant.revokeType.emoji" = "[Sticker]"; +"assistant.revokeType.image" = "[Photo]"; +"assistant.revokeType.video" = "[Video]"; +"assistant.revokeType.voice" = "[Voice]"; +"assistant.revokeType.other" = "[Unknown Message]"; +"assistant.revoke.otherMessage.tip" = "TK prevent a message recalled: "; +"assistant.revoke.selfMessage.tip" = "You've recalled a message: "; + +// AutoAuth +"assistant.autoAuth.tip" = "AutoAuth Logging in…"; +"assistant.autoLogin.text" = "Auto Login"; + + +// Context Menu +"assistant.chat.stickyBottom" = "Sticky on Bottom"; +"assistant.chat.unStickyBottom" = "Unsticky on Bottom"; +"assistant.chat.multiSelect" = "Multiselect"; +"assistant.chat.unMultiSelect" = "Unmultiselect"; +"assistant.chat.readAll" = "Mark All As Read"; +"assistant.chat.clearEmpty" = "Clear All Empty Session"; +"assistant.chat.remove" = "remove"; +"assistant.chat.unread" = "Unread"; + +// Remote Control +"assistant.remoteControl.getList" = "Directive"; +"assistant.remoteControl.listTip" = "remote Control Directives: \n(function-directive-Switch)\n\n"; +"assistant.remoteControl.recall" = "Assistant got a directive: "; +"assistant.remoteControl.voiceRecall" = "Assistant got a audio message, Convert to Text👇👇👇:"; +"assistant.remoteControl.mac" = "Macbook:"; +"assistant.remoteControl.app" = "APP:"; +"assistant.remoteControl.neteaseMusic" = "NeteaseMusic:"; +"assistant.remoteControl.assistant" = "Assistant:"; +"assistant.remoteControl.open" = "On"; +"assistant.remoteControl.close" = "Off"; +"assistant.remoteControl.contentPlaceHodler" = "Please enter the keyword"; + +// Remote Control Directive +"Assistant.Directive.ScreenSave" = "Screen Save"; +"Assistant.Directive.LockScreen" = "Lock Screen"; +"Assistant.Directive.Sleep" = "Sleep"; +"Assistant.Directive.Shutdown" = "Shut Down"; +"Assistant.Directive.Restart" = "Restart"; +"Assistant.Directive.EmptyTrash" = "Empty Trash"; +"Assistant.Directive.Mute" = "Mute"; +"Assistant.Directive.KillQQ" = "Kill QQ"; +"Assistant.Directive.KillWeChat" = "Kill WeChat"; +"Assistant.Directive.KillChrome" = "Kill Chrome"; +"Assistant.Directive.KillSafari" = "Kill Safari"; +"Assistant.Directive.KillFirefox" = "Kill Firefox"; +"Assistant.Directive.KillAll" = "Kill All App"; +"Assistant.Directive.Toggle" = "Play/Pause"; +"Assistant.Directive.Next" = "Next"; +"Assistant.Directive.Previous" = "Previous"; +"Assistant.Directive.VolumeUp" = "Increase Volume"; +"Assistant.Directive.VolumeDown" = "Decrease Volume"; +"Assistant.Directive.LikeChange" = "Like/Unlike"; +"Assistant.Directive.GetList" = "Get Directive"; +"Assistant.Directive.AutoReplySwitch" = "AutoReply Switch"; +"Assistant.Directive.PreventRevokeSwitch" = "PreventRecall Switch"; +"Assistant.Directive.AutoAuthSwitch" = "AutoAuth Switch"; +"Assistant.Directive.SwitchOn" = "On"; +"Assistant.Directive.SwitchOff" = "Off"; + +// AutoAuth Setting +"assistant.autoReply.title" = "Auto Reply Setting"; +"assistant.autoReply.enable" = "Enable Auto Reply"; +"assistant.autoReply.enableSpecific" = "Enable Some Session Reply"; +"assistant.autoReply.selectSpecific" = "View Or Edit Session"; +"assistant.autoReply.enableRegEx" = "Enable RegEx"; +"assistant.autoReply.enableGroup" = "Enable Group Reply"; +"assistant.autoReply.enableSingle" = "Enable Single Reply"; +"assistant.autoReply.delay" = "Delay Send"; +"assistant.autoReply.timeUnit" = "Second"; +"assistant.autoReply.contentPlaceholder" = "Reply Content(‘|’ is random reply a content)"; +"assistant.autoReply.keywordPlaceholder" = "Keyword (‘*’ is All message can Reply,‘|’ is match multiple keyword)"; +"assistant.autoReply.keyword" = "Keyword"; +"assistant.autoReply.content" = "Reply Content"; +"assistant.autoReply.list" = "Auto Reply List"; +"assistant.autoReply.alert.confirm" = "OK"; +"assistant.autoReply.alert.title" = "Attention"; // +"assistant.autoReply.alert.content" = "Please fill in keyword and reply content"; + +// Version Update +"assistant.update.alret.cancle" = "Cancel"; +"assistant.update.alret.confirm" = "Update"; +"assistant.update.alret.title" = "Found a New Version!Main Contents:👇"; +"assistant.update.alret.latest" = "This is Latest Version!Main Contents:👇"; +"assistant.update.alret.forbid" = "Ignore"; + +// Download +"assistant.download.title" = "Update Assistant"; +"assistant.download.cancelTitle" = "Cancelled"; +"assistant.download.install" = "Ready to Install"; +"assistant.download.error" = "Update Error!"; +"assistant.download.update" = "Downloading update..."; +"assistant.download.relaunch" = "Install and Relaunch"; +"assistant.download.cancel" = "Cancel"; +"assistant.download.reInstall" = "Try Again"; +"assistant.download.reDownload" = "Redownload"; + +// Alfred +"assistant.search.member" = "Member: "; +"assistant.search.friend" = "[Friend]"; +"assistant.search.group" = "[Group]"; +"assistant.search.official" = "[Official]"; +"assistant.search.chatlog" = "this is chat log👇🏻"; +"assistant.search.message.unread" = "unread"; +"assistant.search.yesterday" = "yesterday"; diff --git a/WeChatPlugin/en.lproj/about.rtfd/TXT.rtf b/WeChatPlugin/en.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..5b00ae8e --- /dev/null +++ b/WeChatPlugin/en.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,53 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset0 HelveticaNeue-Bold; +\f3\fnil\fcharset134 PingFangSC-Regular;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs34 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs34 \cf2 Feature +\fs47\fsmilli23660 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs30 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Message auto reply\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Prevent message recall\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Remote control(support voice control)\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Multiple WeChat\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Auth Login\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session Sticky Bottom\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Windows Sticky Top\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Session multiple delete\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Auto Login Switch\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Quick reply to notifications\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Copy or Export Sticker\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Update plugin\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +Reply or Open session by Alfred +\f3\fs32 \ +} \ No newline at end of file diff --git a/WeChatPlugin/main.mm b/WeChatPlugin/main.mm index 4da9953b..827fe8f8 100644 --- a/WeChatPlugin/main.mm +++ b/WeChatPlugin/main.mm @@ -9,9 +9,14 @@ #import #import "WeChat+hook.h" #import "MMChatsTableCellView+hook.h" +#import "MMStickerMessageCellView+hook.h" +#import "MMStickerPickerCell+hook.h" static void __attribute__((constructor)) initialize(void) { NSLog(@"++++++++ WeChatPlugin loaded ++++++++"); [NSObject hookWeChat]; [NSObject hookMMChatsTableCellView]; + [NSObject hookMMStickerMessageCellView]; + [NSObject hookMMStickerPickerCell]; + } diff --git a/WeChatPlugin/zh-Hans.lproj/Localizable.strings b/WeChatPlugin/zh-Hans.lproj/Localizable.strings new file mode 100644 index 00000000..09c79c1d --- /dev/null +++ b/WeChatPlugin/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,136 @@ +/* + Localizable.strings + WeChatPlugin + + Created by TK on 2018/4/14. + Copyright © 2018年 tk. All rights reserved. +*/ + + +// 菜单栏 +"assistant.menu.title" = "微信小助手"; +"assistant.menu.revoke" = "开启消息防撤回"; +"assistant.menu.revokeSelf" = "拦截自己撤回消息"; +"assistant.menu.autoReply" = "自动回复设置"; +"assistant.menu.newWeChat" = "登录新微信"; +"assistant.menu.remoteControl" = "远程控制mac"; +"assistant.menu.windowSticky" = "微信窗口置顶"; +"assistant.menu.freeLogin" = "免认证登录"; +"assistant.menu.systemBrowser" = "使用系统浏览器"; +"assistant.menu.forbidCheck" = "禁止微信启动时检测更新"; +"assistant.menu.memberExitMonitoring" = "退群监控"; +"assistant.menu.other" = "小助手🌚"; +"assistant.menu.enableAlfred" = "开启 Alfred 功能"; +"assistant.menu.updateAssistant" = "更新小助手…"; +"assistant.menu.aboutAssistant" = "关于小助手"; + +// 撤回相关 +"assistant.revokeType.emoji" = "[表情]"; +"assistant.revokeType.image" = "[图片]"; +"assistant.revokeType.video" = "[视频]"; +"assistant.revokeType.voice" = "[语音]"; +"assistant.revokeType.other" = "[非文本]"; +"assistant.revoke.otherMessage.tip" = "TK拦截到一条撤回消息: "; +"assistant.revoke.selfMessage.tip" = "你撤回了一条消息: "; + +// 免认证相关 +"assistant.autoAuth.tip" = "TK正在为你免认证登录~"; +"assistant.autoLogin.text" = "自动登录"; + + +// 回话选择 +"assistant.chat.stickyBottom" = "置底"; +"assistant.chat.unStickyBottom" = "取消置底"; +"assistant.chat.multiSelect" = "多选"; +"assistant.chat.unMultiSelect" = "取消多选"; +"assistant.chat.readAll" = "一键已读"; +"assistant.chat.clearEmpty" = "清除空会话"; +"assistant.chat.remove" = "移除"; +"assistant.chat.unread" = "标记未读"; + +// 远程控制相关 +"assistant.remoteControl.getList" = "获取指令"; +"assistant.remoteControl.listTip" = "远程控制指令:\n(功能-指令-是否开启)\n\n"; +"assistant.remoteControl.recall" = "小助手收到一条指令:"; +"assistant.remoteControl.voiceRecall" = "小助手收到一条语音消息,转文字后👇👇👇:"; +"assistant.remoteControl.mac" = "macbook控制:"; +"assistant.remoteControl.app" = "app控制:"; +"assistant.remoteControl.neteaseMusic" = "网易云音乐控制:"; +"assistant.remoteControl.assistant" = "小助手控制:"; +"assistant.remoteControl.open" = "开启"; +"assistant.remoteControl.close" = "关闭"; +"assistant.remoteControl.contentPlaceHodler" = "请输入匹配的关键词"; + +// 远程控制指令 +"Assistant.Directive.ScreenSave" = "屏幕保护"; +"Assistant.Directive.LockScreen" = "锁屏"; +"Assistant.Directive.Sleep" = "休眠"; +"Assistant.Directive.Shutdown" = "关机"; +"Assistant.Directive.Restart" = "重启"; +"Assistant.Directive.EmptyTrash" = "清空废纸篓"; +"Assistant.Directive.Mute" = "静音"; +"Assistant.Directive.KillQQ" = "退出 QQ"; +"Assistant.Directive.KillWeChat" = "退出 WeChat"; +"Assistant.Directive.KillChrome" = "退出 Chrome"; +"Assistant.Directive.KillSafari" = "退出 Safari"; +"Assistant.Directive.KillFirefox" = "退出 Firefox"; +"Assistant.Directive.KillAll" = "退出所有程序"; +"Assistant.Directive.Toggle" = "播放/暂停"; +"Assistant.Directive.Next" = "下一首"; +"Assistant.Directive.Previous" = "上一首"; +"Assistant.Directive.VolumeUp" = "增大音量"; +"Assistant.Directive.VolumeDown" = "VolumeDown"; +"Assistant.Directive.LikeChange" = "喜欢/取消喜欢"; +"Assistant.Directive.GetList" = "获取指令"; +"Assistant.Directive.AutoReplySwitch" = "自动回复开关"; +"Assistant.Directive.PreventRevokeSwitch" = "防撤回开关"; +"Assistant.Directive.AutoAuthSwitch" = "免认证登录开关"; +"Assistant.Directive.SwitchOn" = "开启"; +"Assistant.Directive.SwitchOff" = "关闭"; + +// 自动回复 +"assistant.autoReply.title" = "自动回复设置"; +"assistant.autoReply.enable" = "开启自动回复"; +"assistant.autoReply.enableSpecific" = "开启特定回复"; +"assistant.autoReply.selectSpecific" = "查看(修改)选中联系人"; +"assistant.autoReply.enableRegEx" = "开启正则匹配"; +"assistant.autoReply.enableGroup" = "开启群聊自动回复"; +"assistant.autoReply.enableSingle" = "开启私聊自动回复"; +"assistant.autoReply.delay" = "延迟发送"; +"assistant.autoReply.timeUnit" = "秒"; +"assistant.autoReply.contentPlaceholder" = "请输入自动回复的内容(‘|’ 为随机回复其中任一内容)"; +"assistant.autoReply.keywordPlaceholder" = "请输入关键字( ‘*’ 为任何消息都回复,‘|’ 为匹配多个关键字)"; +"assistant.autoReply.keyword" = "关键字"; +"assistant.autoReply.content" = "回复内容"; +"assistant.autoReply.list" = "自动回复列表"; +"assistant.autoReply.alert.confirm" = "确定"; +"assistant.autoReply.alert.title" = "您还有一条自动回复设置未完成"; +"assistant.autoReply.alert.content" = "请完善未完成的自动回复设置"; + +// 版本更新 +"assistant.update.alret.cancle" = "取消"; +"assistant.update.alret.confirm" = "安装更新"; +"assistant.update.alret.title" = "检测到新版本!主要内容:👇"; +"assistant.update.alret.latest" = "当前为最新版本!主要内容:👇"; +"assistant.update.alret.forbid" = "不再提示"; + +// 下载 +"assistant.download.title" = "更新小助手"; +"assistant.download.cancelTitle" = "已取消"; +"assistant.download.install" = "可以开始安装了"; +"assistant.download.error" = "更新错误!"; +"assistant.download.update" = "正在下载更新…"; +"assistant.download.relaunch" = "安装并重启应用"; +"assistant.download.cancel" = "取消"; +"assistant.download.reInstall" = "重试"; +"assistant.download.reDownload" = "重新下载"; + + +// alfred 搜索 +"assistant.search.member" = "成员:"; +"assistant.search.friend" = "[好友]"; +"assistant.search.group" = "[群聊]"; +"assistant.search.official" = "[公众号]"; +"assistant.search.chatlog" = "以下为聊天记录👇🏻"; +"assistant.search.message.unread" = "未读"; +"assistant.search.yesterday" = "昨天"; diff --git a/WeChatPlugin/zh-Hans.lproj/about.rtfd/TXT.rtf b/WeChatPlugin/zh-Hans.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..8411d6cd --- /dev/null +++ b/WeChatPlugin/zh-Hans.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,213 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Regular;\f5\fnil\fcharset0 AppleColorEmoji; +} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;\red255\green255\blue255; +\red52\green110\blue183;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;\cssrgb\c100000\c100000\c100000; +\cssrgb\c25490\c51373\c76863;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2} +{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3} +{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs48 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d3\'ef\'d2\'f4 +\f1 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'bf\'aa +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'c2\'bc\'c3\'e2\'c8\'cf\'d6\'a4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f1 ( +\f4 \strike \strikec2 \'c0\'e0\'cb\'c6\'d6\'c3\'b6\'a5 +\f1 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'b6\'af\'b5\'c7\'c2\'bc\'bf\'aa\'b9\'d8 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6 +\f1 & +\f4 \'b4\'e6\'b4\'a2 +\f1 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f1 \ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0\cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'b4\'b0\'bf\'da\ +\pard\tx0\tx220\pardeftab720\fi-1\sl216\slmult1\partightenfactor0 +\ls1\ilvl0 +\f1 \cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'bb\'e1\'bb\'b0\'d2\'bb\'bc\'fc\'d2\'d1\'b6\'c1 +\f1 \cb1 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls1\ilvl0\cf2 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d2\'bb\'bc\'fc\'c7\'e5\'b3\'fd\'bf\'d5\'bb\'e1\'bb\'b0 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d6\'a7\'b3\'d6\'b9\'fa\'bc\'ca\'bb\'af +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'bb\'bc\'fc\'b8\'fc\'d0\'c2 +\f1 \cb1 \ +\ls1\ilvl0\cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c8\'a5\'b3\'fd\'ce\'a2\'d0\'c5 +\f1 url +\f4 \'d7\'aa\'c1\'b4\'a3\'a8\'b4\'d3\'b4\'cb\'d6\'b1\'bd\'d3\'b4\'f2\'bf\'aa\'b6\'b6\'d2\'f4\'c1\'b4\'bd\'d3 +\f5 \uc0\u55356 \u57117 \ +\ls1\ilvl0 +\f1 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'cb\'d1\'cb\'f7\'d7\'ee\'bd\'fc\'c1\'c4\'cc\'ec\'a1\'a2\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc +\f5 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 + +\f1 \cf2 \kerning1\expnd0\expndtw0 \'95 +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d2\'c6\'b3\'fd\'bb\'e1\'bb\'b0(\'b2\'bb\'c9\'be\'b3\'fd\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc)\cb1 \ + +\f1 \cf5 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d6\'be\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls2\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'ca\'ca\'c5\'e4 +\f1 2.3.17 & +\f4 \'bc\'d3\'c7\'bf +\f1 alfred +\f4 \'cb\'d1\'cb\'f7 +\f1 (2018-07-24)}} +\f2\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl360\partightenfactor0 +\ls3\ilvl0 +\f1\b0\fs32 \cf5 \cb4 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.7"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\ul \'d0\'c2\'d4\'f6\'ba\'c3\'b6\'e0\'b9\'a6\'c4\'dc +\f1 \'85(2018-05-12)}} +\f3\b\fs36 \cf2 \cb1 \expnd0\expndtw0\kerning0 +\ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls4\ilvl0 +\f1\b0\fs32 \cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'d1\'d3\'b3\'d9 +\f1 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'b6\'a5\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f1 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f1 Alfred +\f4 \'bf\'ec\'bd\'dd\'b7\'a2\'cb\'cd\'cf\'fb\'cf\'a2 +\f1 & +\f4 \'b4\'f2\'bf\'aa\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f1 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d3\'ef\'d2\'f4\'d4\'b6\'b3\'cc\'bf\'d8\'d6\'c6 +\f1 mac & +\f4 \'d3\'c5\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'b8\'b4 +\f1 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'bc\'ec\'b2\'e2\'b8\'fc\'d0\'c2 +\f1 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'b8\'b4\'d6\'c6\'b4\'e6\'b4\'a2\'b5\'c8\'b5\'c8 +\f1 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'b6\'a5 +\f1 & +\f4 \'b6\'e0\'d1\'a1\'c9\'be\'b3\'fd\'b5\'c8\'b5\'c8 +\f1 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f1 & +\f4 \'c3\'e2\'c8\'cf\'d6\'a4 +\f1 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'b8\'b4\'c1\'c4\'cc\'ec\'bc\'c7\'c2\'bc\'cf\'fb\'ca\'a7\'b5\'c4 +\f1 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls4\ilvl0\cf5 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'b9\'b9\'d7\'d4\'b6\'af\'bb\'d8\'b8\'b4\'a3\'ac\'ca\'b5\'cf\'d6\'b6\'e0\'bb\'d8\'b8\'b4 +\f1 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'cf\'ea\'cf\'b8\'c4\'da\'c8\'dd\'c7\'eb\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f1\b0 \cf5 CHANGELOG}} +\f1\b0 \cf5 \ +} \ No newline at end of file diff --git a/WeChatPlugin/zh-Hant.lproj/Localizable.strings b/WeChatPlugin/zh-Hant.lproj/Localizable.strings new file mode 100644 index 00000000..c937d96f --- /dev/null +++ b/WeChatPlugin/zh-Hant.lproj/Localizable.strings @@ -0,0 +1,136 @@ +/* + Localizable.strings + WeChatPlugin + + Created by TK on 2018/4/14. + Copyright © 2018年 tk. All rights reserved. + */ + + +// 菜單欄 +"assistant.menu.title" = "微信小助手"; +"assistant.menu.revoke" = "開啟消息防撤回"; +"assistant.menu.revokeSelf" = "攔截自己撤回消息"; +"assistant.menu.autoReply" = "自動回復設置"; +"assistant.menu.newWeChat" = "登錄新微信"; +"assistant.menu.remoteControl" = "遠程控制mac"; +"assistant.menu.windowSticky" = "微信窗口置頂"; +"assistant.menu.freeLogin" = "免認證登錄"; +"assistant.menu.systemBrowser" = "使用系統瀏覽器"; +"assistant.menu.memberExitMonitoring" = "退群監控"; +"assistant.menu.forbidCheck" = "禁止微信啟動時檢測更新"; +"assistant.menu.other" = "小助手🌚"; +"assistant.menu.enableAlfred" = "開啟 Alfred 功能"; +"assistant.menu.updateAssistant" = "更新小助手…"; +"assistant.menu.aboutAssistant" = "關於小助手"; + +// 撤回相關 +"assistant.revokeType.emoji" = "[表情]"; +"assistant.revokeType.image" = "[圖片]"; +"assistant.revokeType.video" = "[視頻]"; +"assistant.revokeType.voice" = "[語音]"; +"assistant.revokeType.other" = "[非文本]"; +"assistant.revoke.otherMessage.tip" = "TK攔截到一條撤回消息: "; +"assistant.revoke.selfMessage.tip" = "你撤回了一條消息: "; + +// 免認證相關 +"assistant.autoAuth.tip" = "TK正在為你免認證登錄~"; +"assistant.autoLogin.text" = "自動登錄"; + + +// 回話選擇 +"assistant.chat.stickyBottom" = "置底"; +"assistant.chat.unStickyBottom" = "取消置底"; +"assistant.chat.multiSelect" = "多選"; +"assistant.chat.unMultiSelect" = "取消多選"; +"assistant.chat.readAll" = "一鍵已讀"; +"assistant.chat.clearEmpty" = "清除空會話"; +"assistant.chat.remove" = "移除"; +"assistant.chat.unread" = "标记未读"; + +// 遠程控制相關 +"assistant.remoteControl.getList" = "獲取指令"; +"assistant.remoteControl.listTip" = "遠程控制指令:\n(功能-指令-是否開啟)\n\n"; +"assistant.remoteControl.recall" = "小助手收到一條指令:"; +"assistant.remoteControl.voiceRecall" = "小助手收到一條語音消息,轉文字後👇👇👇:"; +"assistant.remoteControl.mac" = "macbook控制:"; +"assistant.remoteControl.app" = "app控制:"; +"assistant.remoteControl.neteaseMusic" = "網易雲音樂控制:"; +"assistant.remoteControl.assistant" = "小助手控制:"; +"assistant.remoteControl.open" = "開啟"; +"assistant.remoteControl.close" = "關閉"; +"assistant.remoteControl.contentPlaceHodler" = "請輸入匹配的關鍵詞"; + +// 遠程控制指令 +"Assistant.Directive.ScreenSave" = "屏幕保護"; +"Assistant.Directive.LockScreen" = "鎖屏"; +"Assistant.Directive.Sleep" = "休眠"; +"Assistant.Directive.Shutdown" = "關機"; +"Assistant.Directive.Restart" = "重啟"; +"Assistant.Directive.EmptyTrash" = "清空廢紙簍"; +"Assistant.Directive.Mute" = "靜音"; +"Assistant.Directive.KillQQ" = "退出 QQ"; +"Assistant.Directive.KillWeChat" = "退出 WeChat"; +"Assistant.Directive.KillChrome" = "退出 Chrome"; +"Assistant.Directive.KillSafari" = "退出 Safari"; +"Assistant.Directive.KillFirefox" = "退出 Firefox"; +"Assistant.Directive.KillAll" = "退出所有程序"; +"Assistant.Directive.Toggle" = "播放/暫停"; +"Assistant.Directive.Next" = "下一首"; +"Assistant.Directive.Previous" = "上一首"; +"Assistant.Directive.VolumeUp" = "增大音量"; +"Assistant.Directive.VolumeDown" = "VolumeDown"; +"Assistant.Directive.LikeChange" = "喜歡/取消喜歡"; +"Assistant.Directive.GetList" = "獲取指令"; +"Assistant.Directive.AutoReplySwitch" = "自動回復開關"; +"Assistant.Directive.PreventRevokeSwitch" = "防撤回開關"; +"Assistant.Directive.AutoAuthSwitch" = "免認證登錄開關"; +"Assistant.Directive.SwitchOn" = "開啟"; +"Assistant.Directive.SwitchOff" = "關閉"; + +// 自動回復 +"assistant.autoReply.title" = "自動回復設置"; +"assistant.autoReply.enable" = "開啟自動回復"; +"assistant.autoReply.enableSpecific" = "開啟特定回復"; +"assistant.autoReply.selectSpecific" = "查看(修改)選中聯系人"; +"assistant.autoReply.enableRegEx" = "開啟正則匹配"; +"assistant.autoReply.enableGroup" = "開啟群聊自動回復"; +"assistant.autoReply.enableSingle" = "開啟私聊自動回復"; +"assistant.autoReply.delay" = "延遲發送"; +"assistant.autoReply.timeUnit" = "秒"; +"assistant.autoReply.contentPlaceholder" = "請輸入自動回復的內容(‘|’ 為隨機回復其中任一內容)"; +"assistant.autoReply.keywordPlaceholder" = "請輸入關鍵字( ‘*’ 為任何消息都回復,‘|’ 為匹配多個關鍵字)"; +"assistant.autoReply.keyword" = "關鍵字"; +"assistant.autoReply.content" = "回復內容"; +"assistant.autoReply.list" = "自動回復列表"; +"assistant.autoReply.alert.confirm" = "確定"; +"assistant.autoReply.alert.title" = "您還有一條自動回復設置未完成"; +"assistant.autoReply.alert.content" = "請完善未完成的自動回復設置"; + +// 版本更新 +"assistant.update.alret.cancle" = "取消"; +"assistant.update.alret.confirm" = "安裝更新"; +"assistant.update.alret.title" = "檢測到新版本!主要內容:👇"; +"assistant.update.alret.latest" = "當前為最新版本!主要內容:👇"; +"assistant.update.alret.forbid" = "不再提示"; + +// 下載 +"assistant.download.title" = "更新小助手"; +"assistant.download.cancelTitle" = "已取消"; +"assistant.download.install" = "可以開始安裝了"; +"assistant.download.error" = "更新錯誤!"; +"assistant.download.update" = "正在下載更新…"; +"assistant.download.relaunch" = "安裝並重啟應用"; +"assistant.download.cancel" = "取消"; +"assistant.download.reInstall" = "重試"; +"assistant.download.reDownload" = "重新下載"; + + +// alfred 搜索 +"assistant.search.member" = "成員:"; +"assistant.search.friend" = "[好友]"; +"assistant.search.group" = "[群聊]"; +"assistant.search.official" = "[公衆號]"; +"assistant.search.chatlog" = "以下為聊天記錄👇🏻"; +"assistant.search.message.unread" = "未读"; +"assistant.search.yesterday" = "昨天"; diff --git a/WeChatPlugin/zh-Hant.lproj/about.rtfd/TXT.rtf b/WeChatPlugin/zh-Hant.lproj/about.rtfd/TXT.rtf new file mode 100644 index 00000000..4739ae65 --- /dev/null +++ b/WeChatPlugin/zh-Hant.lproj/about.rtfd/TXT.rtf @@ -0,0 +1,155 @@ +{\rtf1\ansi\ansicpg936\cocoartf1671 +{\fonttbl\f0\fnil\fcharset0 HelveticaNeue-Light;\f1\fnil\fcharset0 HelveticaNeue;\f2\fnil\fcharset134 PingFangSC-Semibold; +\f3\fnil\fcharset0 HelveticaNeue-Bold;\f4\fnil\fcharset134 PingFangSC-Light;} +{\colortbl;\red255\green255\blue255;\red38\green38\blue38;\red32\green124\blue169;} +{\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;\cssrgb\c14510\c56078\c72157;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}} +\margl1440\margr1440\vieww13760\viewh11300\viewkind0 +\hyphauto1\hyphfactor90 +\deftab720 +\pard\pardeftab720\qc\partightenfactor0 + +\f0\fs36\fsmilli18200 \cf2 \expnd0\expndtw0\kerning0 +Github: {\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS"}}{\fldrslt \cf3 WeChatPlugin-MacOS}}\ +Email: {\field{\*\fldinst{HYPERLINK "mailto:tkk.ioser@gmail.com"}}{\fldrslt \cf3 tkk.ioser@gmail.com}} +\f1\fs32 \ +\pard\pardeftab720\sl288\slmult1\qc\partightenfactor0 + +\fs28 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b9\'a6\'c4\'dc +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\partightenfactor0 +\ls1\ilvl0 +\f0\b0\fs32 \cf2 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cf\'fb\'cf\'a2\'b7\'c0\'b3\'b7\'bb\'d8 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 ( +\f4 \'d2\'d1\'d6\'a7\'b3\'d6\'d5\'5a\'d2\'f4 +\f0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b6\'e0\'e9\'5f +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'b5\'da\'b6\'fe\'b4\'ce\'b5\'c7\'e4\'9b\'c3\'e2\'d5\'4a\'d7\'43 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'d6\'c3\'b5\'d7\'b9\'a6\'c4\'dc +\f0 ( +\f4 \strike \strikec2 \'ee\'90\'cb\'c6\'d6\'c3\'ed\'94 +\f0 \strike0\striked0 )\ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'ce\'a2\'d0\'c5\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'95\'fe\'d4\'92\'b6\'e0\'df\'78\'84\'68\'b3\'fd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d7\'d4\'84\'d3\'b5\'c7\'e4\'9b\'e9\'5f\'ea\'50 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'cd\'a8\'d6\'aa\'d6\'d0\'d0\'c4\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da\'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6 +\f0 & +\f4 \'b4\'e6\'83\'a6 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 } +\f4 \expnd0\expndtw0\kerning0 +\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2\'cc\'e1\'d0\'d1 +\f0 \ +\ls1\ilvl0\kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }\expnd0\expndtw0\kerning0 +alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'b4\'b0\'bf\'da +\f0 \ +\pard\tx566\pardeftab720\partightenfactor0 + +\fs36\fsmilli18200 \cf2 \ +\pard\pardeftab720\partightenfactor0 + +\f2\b\fs36 \cf2 \'b8\'fc\'d0\'c2\'c8\'d5\'d5\'49 +\f3\fs47\fsmilli23660 \cf2 \ +\pard\tx220\tx720\pardeftab720\li720\fi-720\sl264\slmult1\partightenfactor0 +\ls2\ilvl0 +\f0\b0\fs32 \cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'d1\'d3\'df\'74 +\f0 & +\f4 \'d0\'de\'b8\'c4\'d6\'c3\'ed\'94\'b4\'b0\'bf\'da\'bf\'ec\'bd\'dd +\f0 (2018-04-07)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.6"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6 +\f0 Alfred +\f4 \'bf\'ec\'bd\'dd\'b0\'6c\'cb\'cd\'cf\'fb\'cf\'a2 +\f0 & +\f4 \'b4\'f2\'e9\'5f\'c1\'c4\'cc\'ec\'b4\'b0\'bf\'da +\f0 (2018-03-18)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.1"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d5\'5a\'d2\'f4\'df\'68\'b3\'cc\'bf\'d8\'d6\'c6 +\f0 mac & +\f4 \'83\'9e\'bb\'af\'b3\'b7\'bb\'d8\'cf\'fb\'cf\'a2\'a1\'a2\'bf\'ec\'bd\'dd\'bb\'d8\'8f\'cd +\f0 (2018-03-03)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.5.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d0\'a1\'d6\'fa\'ca\'d6\'99\'7a\'9c\'79\'b8\'fc\'d0\'c2 +\f0 & +\f4 \'b1\'ed\'c7\'e9\'b0\'fc\'8f\'cd\'d6\'c6\'b4\'e6\'83\'a6\'b5\'c8\'b5\'c8 +\f0 (2018-02-24)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.4.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'b4\'b0\'bf\'da\'d6\'c3\'ed\'94 +\f0 & +\f4 \'b6\'e0\'df\'78\'84\'68\'b3\'fd\'b5\'c8\'b5\'c8 +\f0 (2017-10-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.3.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'c2\'d4\'f6\'d6\'c3\'b5\'d7 +\f0 & +\f4 \'c3\'e2\'d5\'4a\'d7\'43 +\f0 (2017-09-17)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.2.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d0\'de\'8f\'cd\'c1\'c4\'cc\'ec\'d3\'9b\'e4\'9b\'cf\'fb\'ca\'a7\'b5\'c4 +\f0 bug (2017-09-11)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\ls2\ilvl0\cf3 \kerning1\expnd0\expndtw0 {\listtext \uc0\u8226 }{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/releases/tag/v1.1.0"}}{\fldrslt +\f4 \expnd0\expndtw0\kerning0 +\'d6\'d8\'98\'8b\'d7\'d4\'84\'d3\'bb\'d8\'8f\'cd\'a3\'ac\'8c\'8d\'ac\'46\'b6\'e0\'bb\'d8\'8f\'cd +\f0 (2017-08-23)}}\cf2 \expnd0\expndtw0\kerning0 +\ +\pard\pardeftab720\sl264\slmult1\partightenfactor0 + +\f2\b \cf2 \'d4\'94\'bc\'9a\'83\'c8\'c8\'dd\'d5\'88\'b2\'e9\'bf\'b4{\field{\*\fldinst{HYPERLINK "https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/blob/master/CHANGELOG.md"}}{\fldrslt +\f0\b0 \cf3 CHANGELOG}} +\f0\b0\fs36\fsmilli18200 \cf2 \ +} \ No newline at end of file