diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..d049b5d --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +tweaks.app \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e1dcff9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,5 @@ +# Contributing + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + +[![Contributors](https://opencollective.com/WeChatTweak-macOS/contributors.svg?width=890&button=false)](https://github.com/Sunnyyoung/WeChatTweak-macOS/graphs/contributors) diff --git a/LICENSE b/LICENSE index 4f780b4..f49a4e1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Copyright (c) 2016 Sunnyyoung + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 1. Definitions. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/Podfile.lock b/Podfile.lock index 695a91d..19de125 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,7 +1,7 @@ PODS: - - GCDWebServer (3.4.1): - - GCDWebServer/Core (= 3.4.1) - - GCDWebServer/Core (3.4.1) + - GCDWebServer (3.4.2): + - GCDWebServer/Core (= 3.4.2) + - GCDWebServer/Core (3.4.2) - JRSwizzle (1.0) - YYModel (1.0.4) @@ -10,11 +10,17 @@ DEPENDENCIES: - JRSwizzle - YYModel +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - GCDWebServer + - JRSwizzle + - YYModel + SPEC CHECKSUMS: - GCDWebServer: 1db60034fe0e78a4a8524bd6c7cd97cd3c589870 + GCDWebServer: 8d67ee9f634b4bb91eb4b8aee440318a5fc6debd JRSwizzle: dd5ead5d913a0f29e7f558200165849f006bb1e3 YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30 PODFILE CHECKSUM: af44d62b300e2c55cb63386ec4be3227b93c7761 -COCOAPODS: 1.3.1 +COCOAPODS: 1.5.3 diff --git a/README-Chinese.md b/README-Chinese.md index f52c77f..9fb0091 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -1,9 +1,11 @@ # WeChatTweak-macOS -[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) +[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE) [![README](https://img.shields.io/badge/README-English-blue.svg)](README.md) [![README](https://img.shields.io/badge/README-中文-blue.svg)](README-Chinese.md) [![README](https://img.shields.io/badge/Telegram-WeChatTweak-brightgreen.svg)](https://t.me/joinchat/B0vW8kPU5OrwdC1qRbaqRA) +[![Backers on Open Collective](https://opencollective.com/WeChatTweak-macOS/backers/badge.svg)](#backers) +[![Sponsors on Open Collective](https://opencollective.com/WeChatTweak-macOS/sponsors/badge.svg)](#sponsors) 微信 macOS 客户端 Tweak 动态库。 @@ -11,24 +13,29 @@ ### 整体预览 -![](Screenshot/0x01.png) +![Overview](Screenshot/0x01.png) ### Alfred workflow -![](Screenshot/0x02.png) +![Alfred](Screenshot/0x02.png) + +### LaunchBar action + +![LaunchBar](Screenshot/0x03.png) ## 功能 - 阻止消息撤回 - - 消息列表通知 - - 系统通知 - - 正常撤回自己发出的消息 + - 消息列表通知 + - 系统通知 + - 正常撤回自己发出的消息 - 客户端无限多开 - - 右键 dock icon 登录新的微信账号 - - 命令行执行:`open -n /Applications/WeChat.app` + - 右键 dock icon 登录新的微信账号 + - 命令行执行:`open -n /Applications/WeChat.app` - 重新打开应用无需手机认证 - UI界面设置面板 - 支持 Alfred workflow +- 支持 Launchbar action ## 使用 @@ -51,6 +58,33 @@ - [微信 macOS 客户端拦截撤回功能实践](https://blog.sunnyyoung.net/wei-xin-macos-ke-hu-duan-lan-jie-che-hui-gong-neng-shi-jian/) - [让微信 macOS 客户端支持 Alfred](https://blog.sunnyyoung.net/rang-wei-xin-macos-ke-hu-duan-zhi-chi-alfred/) +## 贡献者 + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + +[![Contributors](https://opencollective.com/WeChatTweak-macOS/contributors.svg?width=890&button=false)](/graphs/contributors) + +## 支持者 + +Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/WeChatTweak-macOS#backer)] + +[![Backers](https://opencollective.com/WeChatTweak-macOS/backers.svg?width=890)](https://opencollective.com/WeChatTweak-macOS#backers) + +## 赞助者 + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/WeChatTweak-macOS#sponsor)] + +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/0/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/0/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/1/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/1/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/2/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/2/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/3/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/3/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/4/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/4/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/5/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/5/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/6/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/6/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/7/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/7/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/8/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/8/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/9/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/9/website) + ## License -The [MIT License](LICENSE). +The [Apache License 2.0](LICENSE). diff --git a/README.md b/README.md index 962f71c..f15ac40 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # WeChatTweak-macOS -[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) +[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE) [![README](https://img.shields.io/badge/README-English-blue.svg)](README.md) [![README](https://img.shields.io/badge/README-中文-blue.svg)](README-Chinese.md) [![README](https://img.shields.io/badge/Telegram-WeChatTweak-brightgreen.svg)](https://t.me/joinchat/B0vW8kPU5OrwdC1qRbaqRA) +[![Backers on Open Collective](https://opencollective.com/WeChatTweak-macOS/backers/badge.svg)](#backers) +[![Sponsors on Open Collective](https://opencollective.com/WeChatTweak-macOS/sponsors/badge.svg)](#sponsors) A dynamic library tweak for WeChat macOS. @@ -11,24 +13,29 @@ A dynamic library tweak for WeChat macOS. ### Overview -![](Screenshot/0x01.png) +![Overview](Screenshot/0x01.png) ### Alfred workflow -![](Screenshot/0x02.png) +![Alfred](Screenshot/0x02.png) + +### LaunchBar action + +![LaunchBar](Screenshot/0x03.png) ## Feature - Prevent message revoked - - Message list notification - - System notification - - Revoke message you sent + - Message list notification + - System notification + - Revoke message you sent - Multiple WeChat Instance - - Right click on the dock icon to login another WeChat account - - Run command: `open -n /Applications/WeChat.app` + - Right click on the dock icon to login another WeChat account + - Run command: `open -n /Applications/WeChat.app` - Auto login without authentication - UI Interface settings panel - Alfred workflow support +- Launchbar action support ## Quick Start @@ -51,6 +58,33 @@ For more informations, please go to the [Wiki](https://github.com/Sunnyyoung/WeC - [微信 macOS 客户端拦截撤回功能实践](https://blog.sunnyyoung.net/wei-xin-macos-ke-hu-duan-lan-jie-che-hui-gong-neng-shi-jian/) - [让微信 macOS 客户端支持 Alfred](https://blog.sunnyyoung.net/rang-wei-xin-macos-ke-hu-duan-zhi-chi-alfred/) +## Contributors + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + +[![Contributors](https://opencollective.com/WeChatTweak-macOS/contributors.svg?width=890&button=false)](https://github.com/Sunnyyoung/WeChatTweak-macOS/graphs/contributors) + +## Backers + +Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/WeChatTweak-macOS#backer)] + +[![Backers](https://opencollective.com/WeChatTweak-macOS/backers.svg?width=890)](https://opencollective.com/WeChatTweak-macOS#backers) + +## Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/WeChatTweak-macOS#sponsor)] + +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/0/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/0/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/1/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/1/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/2/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/2/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/3/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/3/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/4/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/4/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/5/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/5/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/6/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/6/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/7/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/7/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/8/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/8/website) +[![Sponsor](https://opencollective.com/WeChatTweak-macOS/sponsor/9/avatar.svg)](https://opencollective.com/WeChatTweak-macOS/sponsor/9/website) + ## License -The [MIT License](LICENSE). +The [Apache License 2.0](LICENSE). diff --git a/Screenshot/0x03.png b/Screenshot/0x03.png new file mode 100644 index 0000000..0f1a10b Binary files /dev/null and b/Screenshot/0x03.png differ diff --git a/WeChat.alfredworkflow b/WeChat.alfredworkflow index 34f42e8..49acdd3 100644 Binary files a/WeChat.alfredworkflow and b/WeChat.alfredworkflow differ diff --git a/WeChatTweak.framework/Headers b/WeChatTweak.framework/Headers new file mode 120000 index 0000000..a177d2a --- /dev/null +++ b/WeChatTweak.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/WeChatTweak.framework/Modules b/WeChatTweak.framework/Modules new file mode 120000 index 0000000..5736f31 --- /dev/null +++ b/WeChatTweak.framework/Modules @@ -0,0 +1 @@ +Versions/Current/Modules \ No newline at end of file diff --git a/WeChatTweak.framework/Versions/A/Headers/WeChatTweak.h b/WeChatTweak.framework/Versions/A/Headers/WeChatTweak.h new file mode 100644 index 0000000..17df520 --- /dev/null +++ b/WeChatTweak.framework/Versions/A/Headers/WeChatTweak.h @@ -0,0 +1,15 @@ +// +// WeChatTweak.h +// WeChatTweak +// +// Created by Sunnyyoung on 2017/8/11. +// Copyright © 2017年 Sunnyyoung. All rights reserved. +// + +#import +#import +#import +#import + +FOUNDATION_EXPORT double WeChatTweakVersionNumber; +FOUNDATION_EXPORT const unsigned char WeChatTweakVersionString[]; diff --git a/WeChatTweak.framework/Versions/A/Modules/module.modulemap b/WeChatTweak.framework/Versions/A/Modules/module.modulemap new file mode 100644 index 0000000..15f312c --- /dev/null +++ b/WeChatTweak.framework/Versions/A/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module WeChatTweak { + umbrella header "WeChatTweak.h" + + export * + module * { export * } +} diff --git a/WeChatTweak.framework/Versions/A/Resources/Base.lproj/TweakPreferecesController.nib b/WeChatTweak.framework/Versions/A/Resources/Base.lproj/TweakPreferecesController.nib new file mode 100644 index 0000000..f084ba9 Binary files /dev/null and b/WeChatTweak.framework/Versions/A/Resources/Base.lproj/TweakPreferecesController.nib differ diff --git a/WeChatTweak.framework/Versions/A/Resources/Info.plist b/WeChatTweak.framework/Versions/A/Resources/Info.plist index c16dca1..2bc7c7f 100644 --- a/WeChatTweak.framework/Versions/A/Resources/Info.plist +++ b/WeChatTweak.framework/Versions/A/Resources/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 16G29 + 18A391 CFBundleDevelopmentRegion en CFBundleExecutable @@ -27,17 +27,17 @@ DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 8E3004b + 10A255 DTPlatformVersion GM DTSDKBuild - 16E185 + 18A384 DTSDKName - macosx10.12 + macosx10.14 DTXcode - 0833 + 1000 DTXcodeBuild - 8E3004b + 10A255 NSHumanReadableCopyright Copyright © 2017年 Sunnyyoung. All rights reserved. diff --git a/WeChatTweak.framework/Versions/A/Resources/TweakPreferecesController.nib b/WeChatTweak.framework/Versions/A/Resources/TweakPreferecesController.nib deleted file mode 100644 index 399b569..0000000 Binary files a/WeChatTweak.framework/Versions/A/Resources/TweakPreferecesController.nib and /dev/null differ diff --git a/WeChatTweak.framework/Versions/A/Resources/en.lproj/Localizable.strings b/WeChatTweak.framework/Versions/A/Resources/en.lproj/Localizable.strings new file mode 100644 index 0000000..a452625 Binary files /dev/null and b/WeChatTweak.framework/Versions/A/Resources/en.lproj/Localizable.strings differ diff --git a/WeChatTweak.framework/Versions/A/Resources/en.lproj/TweakPreferecesController.strings b/WeChatTweak.framework/Versions/A/Resources/en.lproj/TweakPreferecesController.strings new file mode 100644 index 0000000..2cd2dbb --- /dev/null +++ b/WeChatTweak.framework/Versions/A/Resources/en.lproj/TweakPreferecesController.strings @@ -0,0 +1,33 @@ + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "10G-t9-s4T"; */ +"10G-t9-s4T.title" = "Enabled"; + +/* Class = "NSTextFieldCell"; title = "Need to restart"; ObjectID = "2vl-mc-m3L"; */ +"2vl-mc-m3L.title" = "Need to restart"; + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "KQg-jN-y9a"; */ +"KQg-jN-y9a.title" = "Enabled"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "MEN-Kg-wfj"; */ +"MEN-Kg-wfj.title" = "Disabled"; + +/* Class = "NSTextFieldCell"; title = "Message recall notification:"; ObjectID = "UKv-CM-nGt"; */ +"UKv-CM-nGt.title" = "Message recall notification:"; + +/* Class = "NSTextFieldCell"; title = "Auto login:"; ObjectID = "UiV-zj-l6I"; */ +"UiV-zj-l6I.title" = "Auto login:"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Uk9-Oc-Jtv"; */ +"Uk9-Oc-Jtv.title" = "Disabled"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Vcv-eD-OM9"; */ +"Vcv-eD-OM9.title" = "Disabled"; + +/* Class = "NSMenuItem"; title = "All"; ObjectID = "da4-aJ-lEy"; */ +"da4-aJ-lEy.title" = "All"; + +/* Class = "NSMenuItem"; title = "Inherited"; ObjectID = "gec-CY-E1x"; */ +"gec-CY-E1x.title" = "Inherited"; + +/* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ +"jHw-2a-B2t.title" = "Alfred JSON compressing:"; diff --git a/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings b/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..e9b609d Binary files /dev/null and b/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/Localizable.strings differ diff --git a/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/TweakPreferecesController.strings b/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/TweakPreferecesController.strings new file mode 100644 index 0000000..8bcc94a --- /dev/null +++ b/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/TweakPreferecesController.strings @@ -0,0 +1,33 @@ + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "10G-t9-s4T"; */ +"10G-t9-s4T.title" = "开启"; + +/* Class = "NSTextFieldCell"; title = "Need to restart"; ObjectID = "2vl-mc-m3L"; */ +"2vl-mc-m3L.title" = "需重启客户端"; + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "KQg-jN-y9a"; */ +"KQg-jN-y9a.title" = "开启"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "MEN-Kg-wfj"; */ +"MEN-Kg-wfj.title" = "关闭"; + +/* Class = "NSTextFieldCell"; title = "Message recall notification:"; ObjectID = "UKv-CM-nGt"; */ +"UKv-CM-nGt.title" = "消息撤回通知:"; + +/* Class = "NSTextFieldCell"; title = "Auto login:"; ObjectID = "UiV-zj-l6I"; */ +"UiV-zj-l6I.title" = "免认证登录:"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Uk9-Oc-Jtv"; */ +"Uk9-Oc-Jtv.title" = "关闭"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Vcv-eD-OM9"; */ +"Vcv-eD-OM9.title" = "关闭"; + +/* Class = "NSMenuItem"; title = "All"; ObjectID = "da4-aJ-lEy"; */ +"da4-aJ-lEy.title" = "全部接收"; + +/* Class = "NSMenuItem"; title = "Inherited"; ObjectID = "gec-CY-E1x"; */ +"gec-CY-E1x.title" = "跟随聊天设置"; + +/* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ +"jHw-2a-B2t.title" = "Alfred JSON 压缩:"; diff --git a/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/Localizable.strings b/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/Localizable.strings new file mode 100644 index 0000000..bcb6bfb Binary files /dev/null and b/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/Localizable.strings differ diff --git a/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/TweakPreferecesController.strings b/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/TweakPreferecesController.strings new file mode 100644 index 0000000..e6a4bd1 --- /dev/null +++ b/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/TweakPreferecesController.strings @@ -0,0 +1,33 @@ + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "10G-t9-s4T"; */ +"10G-t9-s4T.title" = "開啟"; + +/* Class = "NSTextFieldCell"; title = "Need to restart"; ObjectID = "2vl-mc-m3L"; */ +"2vl-mc-m3L.title" = "需重啟客戶端"; + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "KQg-jN-y9a"; */ +"KQg-jN-y9a.title" = "開啟"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "MEN-Kg-wfj"; */ +"MEN-Kg-wfj.title" = "關閉"; + +/* Class = "NSTextFieldCell"; title = "Message recall notification:"; ObjectID = "UKv-CM-nGt"; */ +"UKv-CM-nGt.title" = "消息撤回通知:"; + +/* Class = "NSTextFieldCell"; title = "Auto login:"; ObjectID = "UiV-zj-l6I"; */ +"UiV-zj-l6I.title" = "免認證登錄:"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Uk9-Oc-Jtv"; */ +"Uk9-Oc-Jtv.title" = "關閉"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Vcv-eD-OM9"; */ +"Vcv-eD-OM9.title" = "關閉"; + +/* Class = "NSMenuItem"; title = "All"; ObjectID = "da4-aJ-lEy"; */ +"da4-aJ-lEy.title" = "全部接收"; + +/* Class = "NSMenuItem"; title = "Inherited"; ObjectID = "gec-CY-E1x"; */ +"gec-CY-E1x.title" = "跟隨聊天設置"; + +/* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ +"jHw-2a-B2t.title" = "Alfred JSON 壓縮:"; diff --git a/WeChatTweak.framework/Versions/A/WeChatTweak b/WeChatTweak.framework/Versions/A/WeChatTweak index c81310c..651ae34 100755 Binary files a/WeChatTweak.framework/Versions/A/WeChatTweak and b/WeChatTweak.framework/Versions/A/WeChatTweak differ diff --git a/WeChatTweak.lbaction/Contents/Info.plist b/WeChatTweak.lbaction/Contents/Info.plist new file mode 100644 index 0000000..f40600f --- /dev/null +++ b/WeChatTweak.lbaction/Contents/Info.plist @@ -0,0 +1,53 @@ + + + + + CFBundleIconFile + icon.png + CFBundleIdentifier + com.viko16.LaunchBar.action.WeChatTweak + CFBundleName + WeChatTweak + CFBundleVersion + 1.0 + LBAbbreviation + wc + LBDescription + + LBAuthor + viko16 + LBEmail + + LBSummary + A LaunchBar action for WeChatTweak. + LBTwitter + + LBWebsiteURL + https://github.com/viko16 + + LBScripts + + LBDefaultScript + + LBAcceptedArgumentTypes + + string + + LBKeepWindowActive + + LBLiveFeedbackEnabled + + LBRequiresArgument + + LBResultType + unknown + LBReturnsResult + + LBScriptName + default.js + + + LBTextInputTitle + Search your friend... + + diff --git a/WeChatTweak.lbaction/Contents/Resources/icon.png b/WeChatTweak.lbaction/Contents/Resources/icon.png new file mode 100644 index 0000000..5e457bd Binary files /dev/null and b/WeChatTweak.lbaction/Contents/Resources/icon.png differ diff --git a/WeChatTweak.lbaction/Contents/Scripts/default.js b/WeChatTweak.lbaction/Contents/Scripts/default.js new file mode 100644 index 0000000..4227c3d --- /dev/null +++ b/WeChatTweak.lbaction/Contents/Scripts/default.js @@ -0,0 +1,32 @@ +// LaunchBar Action Script + +function run(string) { + if (!string) return []; + + var url = 'http://localhost:48065/wechat/search?keyword='; + var result = HTTP.getJSON(url + encodeURIComponent(string.trim())); + + if (result == undefined) { + LaunchBar.alert('HTTP.getJSON() returned undefined'); + return []; + } + + if (result.error != undefined) { + LaunchBar.log('Error in HTTP request: ' + result.error); + return []; + } + + return result.data.map(function (i) { + return { + title: i.m_nsRemark || i.m_nsNickName, + subtitle: i.m_nsNickName, + icon: i.wt_avatarPath || 'icon.png', + action: "open", + actionArgument: i.m_nsUsrName + } + }); +} + +function open(id) { + HTTP.get('http://localhost:48065/wechat/start?session=' + id); +} \ No newline at end of file diff --git a/WeChatTweak.xcodeproj/project.pbxproj b/WeChatTweak.xcodeproj/project.pbxproj index f120c7b..018ccbd 100644 --- a/WeChatTweak.xcodeproj/project.pbxproj +++ b/WeChatTweak.xcodeproj/project.pbxproj @@ -9,50 +9,50 @@ /* Begin PBXBuildFile section */ 7D14E5A41F6447DB00D75132 /* AlfredManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D14E5A21F6447DB00D75132 /* AlfredManager.h */; }; 7D14E5A51F6447DB00D75132 /* AlfredManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D14E5A31F6447DB00D75132 /* AlfredManager.m */; }; + 7D54A05C20E74D9400CB5306 /* TweakPreferecesController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D54A05E20E74D9400CB5306 /* TweakPreferecesController.xib */; }; + 7D54A06A20E74FE500CB5306 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D54A06C20E74FE500CB5306 /* Localizable.strings */; }; + 7D9049F51F82A41A004E6370 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = 7D9049F31F82A415004E6370 /* fishhook.c */; }; + 7D9049F61F82A41A004E6370 /* fishhook.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9049F41F82A415004E6370 /* fishhook.h */; }; + 7D9049F91F82B6FB004E6370 /* NSString+WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9049F81F82B6FB004E6370 /* NSString+WeChatTweak.m */; }; + 7D9049FA1F82B708004E6370 /* NSString+WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9049F71F82B6FB004E6370 /* NSString+WeChatTweak.h */; }; + 7DB8AFBE206211D900E683AE /* WTConfigManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DB8AFBC206211D900E683AE /* WTConfigManager.h */; }; + 7DB8AFBF206211D900E683AE /* WTConfigManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB8AFBD206211D900E683AE /* WTConfigManager.m */; }; 7DF8422C1F40583F00D42D79 /* WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF8422A1F40583F00D42D79 /* WeChatTweak.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7DF842341F4058AB00D42D79 /* WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF842331F4058AB00D42D79 /* WeChatTweak.m */; }; 7DF842521F4058C600D42D79 /* TweakPreferecesController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF8424F1F4058C600D42D79 /* TweakPreferecesController.h */; }; 7DF842531F4058C600D42D79 /* TweakPreferecesController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF842501F4058C600D42D79 /* TweakPreferecesController.m */; }; - 7DF842541F4058C600D42D79 /* TweakPreferecesController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7DF842511F4058C600D42D79 /* TweakPreferecesController.xib */; }; 7DF8425B1F4058DD00D42D79 /* NSBundle+WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF842571F4058DD00D42D79 /* NSBundle+WeChatTweak.h */; }; 7DF8425C1F4058DD00D42D79 /* NSBundle+WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF842581F4058DD00D42D79 /* NSBundle+WeChatTweak.m */; }; - 7DF8425D1F4058DD00D42D79 /* NSString+WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF842591F4058DD00D42D79 /* NSString+WeChatTweak.h */; }; - 7DF8425E1F4058DD00D42D79 /* NSString+WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF8425A1F4058DD00D42D79 /* NSString+WeChatTweak.m */; }; 7DF842601F40590500D42D79 /* WeChatTweakHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF8425F1F40590500D42D79 /* WeChatTweakHeaders.h */; }; - 7DF842621F40592800D42D79 /* WeChatTweak.framework in Export Framework */ = {isa = PBXBuildFile; fileRef = 7DF842271F40583F00D42D79 /* WeChatTweak.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 7DF842651F40594400D42D79 /* Prefs-Tweak.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 7DF842641F40594400D42D79 /* Prefs-Tweak.tiff */; }; D84599A16A2504BCF95DB436 /* libPods-WeChatTweak.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 153504EC5C9196C0D85213CF /* libPods-WeChatTweak.a */; }; /* End PBXBuildFile section */ -/* Begin PBXCopyFilesBuildPhase section */ - 7DF842611F40592100D42D79 /* Export Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "${SRCROOT}"; - dstSubfolderSpec = 0; - files = ( - 7DF842621F40592800D42D79 /* WeChatTweak.framework in Export Framework */, - ); - name = "Export Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ 153504EC5C9196C0D85213CF /* libPods-WeChatTweak.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-WeChatTweak.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7D14E5A21F6447DB00D75132 /* AlfredManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlfredManager.h; sourceTree = ""; }; 7D14E5A31F6447DB00D75132 /* AlfredManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlfredManager.m; sourceTree = ""; }; + 7D54A05F20E74E4600CB5306 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TweakPreferecesController.xib; sourceTree = ""; }; + 7D54A06320E74E5A00CB5306 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/TweakPreferecesController.strings; sourceTree = ""; }; + 7D54A06520E74E8200CB5306 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/TweakPreferecesController.strings"; sourceTree = ""; }; + 7D54A06720E74E8E00CB5306 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/TweakPreferecesController.strings"; sourceTree = ""; }; + 7D54A07020E74FFD00CB5306 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 7D54A07120E7535F00CB5306 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 7D54A07220E7536300CB5306 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; + 7D9049F31F82A415004E6370 /* fishhook.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fishhook.c; sourceTree = ""; }; + 7D9049F41F82A415004E6370 /* fishhook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = ""; }; + 7D9049F71F82B6FB004E6370 /* NSString+WeChatTweak.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+WeChatTweak.h"; sourceTree = ""; }; + 7D9049F81F82B6FB004E6370 /* NSString+WeChatTweak.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+WeChatTweak.m"; sourceTree = ""; }; + 7DB8AFBC206211D900E683AE /* WTConfigManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WTConfigManager.h; sourceTree = ""; }; + 7DB8AFBD206211D900E683AE /* WTConfigManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WTConfigManager.m; sourceTree = ""; }; 7DF842271F40583F00D42D79 /* WeChatTweak.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WeChatTweak.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7DF8422A1F40583F00D42D79 /* WeChatTweak.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeChatTweak.h; sourceTree = ""; }; 7DF8422B1F40583F00D42D79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7DF842331F4058AB00D42D79 /* WeChatTweak.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WeChatTweak.m; sourceTree = ""; }; 7DF8424F1F4058C600D42D79 /* TweakPreferecesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TweakPreferecesController.h; sourceTree = ""; }; 7DF842501F4058C600D42D79 /* TweakPreferecesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TweakPreferecesController.m; sourceTree = ""; }; - 7DF842511F4058C600D42D79 /* TweakPreferecesController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TweakPreferecesController.xib; sourceTree = ""; }; 7DF842571F4058DD00D42D79 /* NSBundle+WeChatTweak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+WeChatTweak.h"; sourceTree = ""; }; 7DF842581F4058DD00D42D79 /* NSBundle+WeChatTweak.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+WeChatTweak.m"; sourceTree = ""; }; - 7DF842591F4058DD00D42D79 /* NSString+WeChatTweak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+WeChatTweak.h"; sourceTree = ""; }; - 7DF8425A1F4058DD00D42D79 /* NSString+WeChatTweak.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+WeChatTweak.m"; sourceTree = ""; }; 7DF8425F1F40590500D42D79 /* WeChatTweakHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeChatTweakHeaders.h; sourceTree = ""; }; 7DF842641F40594400D42D79 /* Prefs-Tweak.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "Prefs-Tweak.tiff"; sourceTree = ""; }; A82E6F61C63DBD47219BB308 /* Pods-WeChatTweak.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WeChatTweak.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WeChatTweak/Pods-WeChatTweak.debug.xcconfig"; sourceTree = ""; }; @@ -79,13 +79,55 @@ name = Frameworks; sourceTree = ""; }; - 7D14E5A11F6447B900D75132 /* Manager */ = { + 7D5AAF3320DF4B7B00860EEE /* Manager */ = { isa = PBXGroup; children = ( 7D14E5A21F6447DB00D75132 /* AlfredManager.h */, 7D14E5A31F6447DB00D75132 /* AlfredManager.m */, + 7DB8AFBC206211D900E683AE /* WTConfigManager.h */, + 7DB8AFBD206211D900E683AE /* WTConfigManager.m */, ); - name = Manager; + path = Manager; + sourceTree = ""; + }; + 7D5AAF3520DF4B9700860EEE /* Controller */ = { + isa = PBXGroup; + children = ( + 7DF8424F1F4058C600D42D79 /* TweakPreferecesController.h */, + 7DF842501F4058C600D42D79 /* TweakPreferecesController.m */, + 7D54A05E20E74D9400CB5306 /* TweakPreferecesController.xib */, + ); + path = Controller; + sourceTree = ""; + }; + 7D5AAF3620DF4BA400860EEE /* Category */ = { + isa = PBXGroup; + children = ( + 7DF842571F4058DD00D42D79 /* NSBundle+WeChatTweak.h */, + 7DF842581F4058DD00D42D79 /* NSBundle+WeChatTweak.m */, + 7D9049F71F82B6FB004E6370 /* NSString+WeChatTweak.h */, + 7D9049F81F82B6FB004E6370 /* NSString+WeChatTweak.m */, + ); + path = Category; + sourceTree = ""; + }; + 7D5AAF3720DF4BB300860EEE /* Vendor */ = { + isa = PBXGroup; + children = ( + 7D9049F41F82A415004E6370 /* fishhook.h */, + 7D9049F31F82A415004E6370 /* fishhook.c */, + ); + path = Vendor; + sourceTree = ""; + }; + 7D5AAF3820DF4BC400860EEE /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 7DF8425F1F40590500D42D79 /* WeChatTweakHeaders.h */, + 7DF8422B1F40583F00D42D79 /* Info.plist */, + 7D54A06C20E74FE500CB5306 /* Localizable.strings */, + ); + path = "Supporting Files"; sourceTree = ""; }; 7DF8421D1F40583F00D42D79 = { @@ -111,45 +153,16 @@ children = ( 7DF8422A1F40583F00D42D79 /* WeChatTweak.h */, 7DF842331F4058AB00D42D79 /* WeChatTweak.m */, - 7D14E5A11F6447B900D75132 /* Manager */, - 7DF842551F4058C900D42D79 /* Controller */, - 7DF842561F4058D300D42D79 /* Category */, + 7D5AAF3720DF4BB300860EEE /* Vendor */, + 7D5AAF3620DF4BA400860EEE /* Category */, + 7D5AAF3520DF4B9700860EEE /* Controller */, + 7D5AAF3320DF4B7B00860EEE /* Manager */, 7DF842631F40594400D42D79 /* Resources */, - 7DF842321F40584700D42D79 /* Supporting Files */, + 7D5AAF3820DF4BC400860EEE /* Supporting Files */, ); path = WeChatTweak; sourceTree = ""; }; - 7DF842321F40584700D42D79 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 7DF8425F1F40590500D42D79 /* WeChatTweakHeaders.h */, - 7DF8422B1F40583F00D42D79 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 7DF842551F4058C900D42D79 /* Controller */ = { - isa = PBXGroup; - children = ( - 7DF8424F1F4058C600D42D79 /* TweakPreferecesController.h */, - 7DF842501F4058C600D42D79 /* TweakPreferecesController.m */, - 7DF842511F4058C600D42D79 /* TweakPreferecesController.xib */, - ); - name = Controller; - sourceTree = ""; - }; - 7DF842561F4058D300D42D79 /* Category */ = { - isa = PBXGroup; - children = ( - 7DF842571F4058DD00D42D79 /* NSBundle+WeChatTweak.h */, - 7DF842581F4058DD00D42D79 /* NSBundle+WeChatTweak.m */, - 7DF842591F4058DD00D42D79 /* NSString+WeChatTweak.h */, - 7DF8425A1F4058DD00D42D79 /* NSString+WeChatTweak.m */, - ); - name = Category; - sourceTree = ""; - }; 7DF842631F40594400D42D79 /* Resources */ = { isa = PBXGroup; children = ( @@ -174,12 +187,14 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 7D9049FA1F82B708004E6370 /* NSString+WeChatTweak.h in Headers */, 7DF8422C1F40583F00D42D79 /* WeChatTweak.h in Headers */, 7DF8425B1F4058DD00D42D79 /* NSBundle+WeChatTweak.h in Headers */, + 7DB8AFBE206211D900E683AE /* WTConfigManager.h in Headers */, + 7D9049F61F82A41A004E6370 /* fishhook.h in Headers */, 7D14E5A41F6447DB00D75132 /* AlfredManager.h in Headers */, 7DF842601F40590500D42D79 /* WeChatTweakHeaders.h in Headers */, 7DF842521F4058C600D42D79 /* TweakPreferecesController.h in Headers */, - 7DF8425D1F4058DD00D42D79 /* NSString+WeChatTweak.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -195,8 +210,7 @@ 7DF842231F40583F00D42D79 /* Frameworks */, 7DF842241F40583F00D42D79 /* Headers */, 7DF842251F40583F00D42D79 /* Resources */, - B75BB08B5F9B62E8FF4DEE05 /* [CP] Copy Pods Resources */, - 7DF842611F40592100D42D79 /* Export Framework */, + 7DE5D07F218319DF00ABCE56 /* Export Framework */, ); buildRules = ( ); @@ -213,7 +227,7 @@ 7DF8421E1F40583F00D42D79 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0830; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = Sunnyyoung; TargetAttributes = { 7DF842261F40583F00D42D79 = { @@ -228,6 +242,9 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, + "zh-Hans", + "zh-Hant", ); mainGroup = 7DF8421D1F40583F00D42D79; productRefGroup = 7DF842281F40583F00D42D79 /* Products */; @@ -245,27 +262,31 @@ buildActionMask = 2147483647; files = ( 7DF842651F40594400D42D79 /* Prefs-Tweak.tiff in Resources */, - 7DF842541F4058C600D42D79 /* TweakPreferecesController.xib in Resources */, + 7D54A06A20E74FE500CB5306 /* Localizable.strings in Resources */, + 7D54A05C20E74D9400CB5306 /* TweakPreferecesController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - B75BB08B5F9B62E8FF4DEE05 /* [CP] Copy Pods Resources */ = { + 7DE5D07F218319DF00ABCE56 /* Export Framework */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( ); - name = "[CP] Copy Pods Resources"; + name = "Export Framework"; + outputFileListPaths = ( + ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeChatTweak/Pods-WeChatTweak-resources.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "FRAMEWORK=\"${TARGET_NAME}.framework\"\nrm -r \"${SRCROOT}/${FRAMEWORK}\"\ncp -R \"${BUILT_PRODUCTS_DIR}/${FRAMEWORK}\" \"${SRCROOT}\"\n"; }; CB198514792C1F69F3B65026 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -293,35 +314,70 @@ buildActionMask = 2147483647; files = ( 7D14E5A51F6447DB00D75132 /* AlfredManager.m in Sources */, - 7DF8425E1F4058DD00D42D79 /* NSString+WeChatTweak.m in Sources */, 7DF842531F4058C600D42D79 /* TweakPreferecesController.m in Sources */, + 7D9049F91F82B6FB004E6370 /* NSString+WeChatTweak.m in Sources */, 7DF842341F4058AB00D42D79 /* WeChatTweak.m in Sources */, + 7DB8AFBF206211D900E683AE /* WTConfigManager.m in Sources */, + 7D9049F51F82A41A004E6370 /* fishhook.c in Sources */, 7DF8425C1F4058DD00D42D79 /* NSBundle+WeChatTweak.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXVariantGroup section */ + 7D54A05E20E74D9400CB5306 /* TweakPreferecesController.xib */ = { + isa = PBXVariantGroup; + children = ( + 7D54A05F20E74E4600CB5306 /* Base */, + 7D54A06320E74E5A00CB5306 /* en */, + 7D54A06520E74E8200CB5306 /* zh-Hans */, + 7D54A06720E74E8E00CB5306 /* zh-Hant */, + ); + name = TweakPreferecesController.xib; + sourceTree = ""; + }; + 7D54A06C20E74FE500CB5306 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 7D54A07020E74FFD00CB5306 /* en */, + 7D54A07120E7535F00CB5306 /* zh-Hans */, + 7D54A07220E7536300CB5306 /* zh-Hant */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ 7DF8422D1F40583F00D42D79 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 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; CLANG_WARN_ENUM_CONVERSION = YES; 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; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -345,7 +401,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.12; + MACOSX_DEPLOYMENT_TARGET = 10.13; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -358,21 +414,30 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 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; CLANG_WARN_ENUM_CONVERSION = YES; 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; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -390,7 +455,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.12; + MACOSX_DEPLOYMENT_TARGET = 10.13; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; @@ -409,9 +474,10 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; - INFOPLIST_FILE = WeChatTweak/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/WeChatTweak/Supporting Files/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_BUNDLE_IDENTIFIER = net.sunnyyoung.WeChatTweak; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -429,9 +495,10 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; - INFOPLIST_FILE = WeChatTweak/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/WeChatTweak/Supporting Files/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_BUNDLE_IDENTIFIER = net.sunnyyoung.WeChatTweak; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; diff --git a/WeChatTweak.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/WeChatTweak.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/WeChatTweak.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/WeChatTweak/NSBundle+WeChatTweak.h b/WeChatTweak/Category/NSBundle+WeChatTweak.h similarity index 82% rename from WeChatTweak/NSBundle+WeChatTweak.h rename to WeChatTweak/Category/NSBundle+WeChatTweak.h index 788bc3e..6995c53 100644 --- a/WeChatTweak/NSBundle+WeChatTweak.h +++ b/WeChatTweak/Category/NSBundle+WeChatTweak.h @@ -11,5 +11,6 @@ @interface NSBundle (WeChatTweak) + (instancetype)tweakBundle; +- (NSString *)localizedStringForKey:(NSString *)key; @end diff --git a/WeChatTweak/NSBundle+WeChatTweak.m b/WeChatTweak/Category/NSBundle+WeChatTweak.m similarity index 73% rename from WeChatTweak/NSBundle+WeChatTweak.m rename to WeChatTweak/Category/NSBundle+WeChatTweak.m index f44c6e3..69f6694 100644 --- a/WeChatTweak/NSBundle+WeChatTweak.m +++ b/WeChatTweak/Category/NSBundle+WeChatTweak.m @@ -14,4 +14,8 @@ return [NSBundle bundleWithIdentifier:@"net.sunnyyoung.WeChatTweak"]; } +- (NSString *)localizedStringForKey:(NSString *)key { + return [self localizedStringForKey:key value:nil table:nil]; +} + @end diff --git a/WeChatTweak/NSString+WeChatTweak.h b/WeChatTweak/Category/NSString+WeChatTweak.h similarity index 100% rename from WeChatTweak/NSString+WeChatTweak.h rename to WeChatTweak/Category/NSString+WeChatTweak.h diff --git a/WeChatTweak/NSString+WeChatTweak.m b/WeChatTweak/Category/NSString+WeChatTweak.m similarity index 100% rename from WeChatTweak/NSString+WeChatTweak.m rename to WeChatTweak/Category/NSString+WeChatTweak.m diff --git a/WeChatTweak/Controller/Base.lproj/TweakPreferecesController.xib b/WeChatTweak/Controller/Base.lproj/TweakPreferecesController.xib new file mode 100644 index 0000000..dcb1ac2 --- /dev/null +++ b/WeChatTweak/Controller/Base.lproj/TweakPreferecesController.xib @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WeChatTweak/TweakPreferecesController.h b/WeChatTweak/Controller/TweakPreferecesController.h similarity index 100% rename from WeChatTweak/TweakPreferecesController.h rename to WeChatTweak/Controller/TweakPreferecesController.h diff --git a/WeChatTweak/TweakPreferecesController.m b/WeChatTweak/Controller/TweakPreferecesController.m similarity index 80% rename from WeChatTweak/TweakPreferecesController.m rename to WeChatTweak/Controller/TweakPreferecesController.m index f052357..9877876 100644 --- a/WeChatTweak/TweakPreferecesController.m +++ b/WeChatTweak/Controller/TweakPreferecesController.m @@ -8,11 +8,13 @@ #import "TweakPreferecesController.h" #import "NSBundle+WeChatTweak.h" +#import "WTConfigManager.h" @interface TweakPreferecesController () @property (weak) IBOutlet NSPopUpButton *autoAuthButton; @property (weak) IBOutlet NSPopUpButton *notificationTypeButton; +@property (weak) IBOutlet NSPopUpButton *compressedJSONEnabledButton; @end @@ -28,11 +30,13 @@ } - (void)reloadData { + WTConfigManager *configManager = WTConfigManager.sharedInstance; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; BOOL enabledAutoAuth = [userDefaults boolForKey:WeChatTweakPreferenceAutoAuthKey]; RevokeNotificationType notificationType = [userDefaults integerForKey:WeChatTweakPreferenceRevokeNotificationTypeKey]; [self.autoAuthButton selectItemAtIndex:enabledAutoAuth ? 1 : 0]; [self.notificationTypeButton selectItemAtIndex:notificationType]; + [self.compressedJSONEnabledButton selectItemAtIndex:configManager.compressedJSONEnabled ? 0 : 1]; } #pragma mark - Event method @@ -48,6 +52,11 @@ [[NSUserDefaults standardUserDefaults] setInteger:type forKey:WeChatTweakPreferenceRevokeNotificationTypeKey]; } +- (IBAction)switchCompressedJSONEnabledAction:(NSPopUpButton *)sender { + BOOL enabled = sender.indexOfSelectedItem == 0; + WTConfigManager.sharedInstance.compressedJSONEnabled = enabled; +} + #pragma mark - MASPreferencesViewController - (NSString *)identifier { diff --git a/WeChatTweak/Controller/en.lproj/TweakPreferecesController.strings b/WeChatTweak/Controller/en.lproj/TweakPreferecesController.strings new file mode 100644 index 0000000..2cd2dbb --- /dev/null +++ b/WeChatTweak/Controller/en.lproj/TweakPreferecesController.strings @@ -0,0 +1,33 @@ + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "10G-t9-s4T"; */ +"10G-t9-s4T.title" = "Enabled"; + +/* Class = "NSTextFieldCell"; title = "Need to restart"; ObjectID = "2vl-mc-m3L"; */ +"2vl-mc-m3L.title" = "Need to restart"; + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "KQg-jN-y9a"; */ +"KQg-jN-y9a.title" = "Enabled"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "MEN-Kg-wfj"; */ +"MEN-Kg-wfj.title" = "Disabled"; + +/* Class = "NSTextFieldCell"; title = "Message recall notification:"; ObjectID = "UKv-CM-nGt"; */ +"UKv-CM-nGt.title" = "Message recall notification:"; + +/* Class = "NSTextFieldCell"; title = "Auto login:"; ObjectID = "UiV-zj-l6I"; */ +"UiV-zj-l6I.title" = "Auto login:"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Uk9-Oc-Jtv"; */ +"Uk9-Oc-Jtv.title" = "Disabled"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Vcv-eD-OM9"; */ +"Vcv-eD-OM9.title" = "Disabled"; + +/* Class = "NSMenuItem"; title = "All"; ObjectID = "da4-aJ-lEy"; */ +"da4-aJ-lEy.title" = "All"; + +/* Class = "NSMenuItem"; title = "Inherited"; ObjectID = "gec-CY-E1x"; */ +"gec-CY-E1x.title" = "Inherited"; + +/* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ +"jHw-2a-B2t.title" = "Alfred JSON compressing:"; diff --git a/WeChatTweak/Controller/zh-Hans.lproj/TweakPreferecesController.strings b/WeChatTweak/Controller/zh-Hans.lproj/TweakPreferecesController.strings new file mode 100644 index 0000000..8bcc94a --- /dev/null +++ b/WeChatTweak/Controller/zh-Hans.lproj/TweakPreferecesController.strings @@ -0,0 +1,33 @@ + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "10G-t9-s4T"; */ +"10G-t9-s4T.title" = "开启"; + +/* Class = "NSTextFieldCell"; title = "Need to restart"; ObjectID = "2vl-mc-m3L"; */ +"2vl-mc-m3L.title" = "需重启客户端"; + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "KQg-jN-y9a"; */ +"KQg-jN-y9a.title" = "开启"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "MEN-Kg-wfj"; */ +"MEN-Kg-wfj.title" = "关闭"; + +/* Class = "NSTextFieldCell"; title = "Message recall notification:"; ObjectID = "UKv-CM-nGt"; */ +"UKv-CM-nGt.title" = "消息撤回通知:"; + +/* Class = "NSTextFieldCell"; title = "Auto login:"; ObjectID = "UiV-zj-l6I"; */ +"UiV-zj-l6I.title" = "免认证登录:"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Uk9-Oc-Jtv"; */ +"Uk9-Oc-Jtv.title" = "关闭"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Vcv-eD-OM9"; */ +"Vcv-eD-OM9.title" = "关闭"; + +/* Class = "NSMenuItem"; title = "All"; ObjectID = "da4-aJ-lEy"; */ +"da4-aJ-lEy.title" = "全部接收"; + +/* Class = "NSMenuItem"; title = "Inherited"; ObjectID = "gec-CY-E1x"; */ +"gec-CY-E1x.title" = "跟随聊天设置"; + +/* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ +"jHw-2a-B2t.title" = "Alfred JSON 压缩:"; diff --git a/WeChatTweak/Controller/zh-Hant.lproj/TweakPreferecesController.strings b/WeChatTweak/Controller/zh-Hant.lproj/TweakPreferecesController.strings new file mode 100644 index 0000000..e6a4bd1 --- /dev/null +++ b/WeChatTweak/Controller/zh-Hant.lproj/TweakPreferecesController.strings @@ -0,0 +1,33 @@ + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "10G-t9-s4T"; */ +"10G-t9-s4T.title" = "開啟"; + +/* Class = "NSTextFieldCell"; title = "Need to restart"; ObjectID = "2vl-mc-m3L"; */ +"2vl-mc-m3L.title" = "需重啟客戶端"; + +/* Class = "NSMenuItem"; title = "Enabled"; ObjectID = "KQg-jN-y9a"; */ +"KQg-jN-y9a.title" = "開啟"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "MEN-Kg-wfj"; */ +"MEN-Kg-wfj.title" = "關閉"; + +/* Class = "NSTextFieldCell"; title = "Message recall notification:"; ObjectID = "UKv-CM-nGt"; */ +"UKv-CM-nGt.title" = "消息撤回通知:"; + +/* Class = "NSTextFieldCell"; title = "Auto login:"; ObjectID = "UiV-zj-l6I"; */ +"UiV-zj-l6I.title" = "免認證登錄:"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Uk9-Oc-Jtv"; */ +"Uk9-Oc-Jtv.title" = "關閉"; + +/* Class = "NSMenuItem"; title = "Disabled"; ObjectID = "Vcv-eD-OM9"; */ +"Vcv-eD-OM9.title" = "關閉"; + +/* Class = "NSMenuItem"; title = "All"; ObjectID = "da4-aJ-lEy"; */ +"da4-aJ-lEy.title" = "全部接收"; + +/* Class = "NSMenuItem"; title = "Inherited"; ObjectID = "gec-CY-E1x"; */ +"gec-CY-E1x.title" = "跟隨聊天設置"; + +/* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ +"jHw-2a-B2t.title" = "Alfred JSON 壓縮:"; diff --git a/WeChatTweak/AlfredManager.h b/WeChatTweak/Manager/AlfredManager.h similarity index 100% rename from WeChatTweak/AlfredManager.h rename to WeChatTweak/Manager/AlfredManager.h diff --git a/WeChatTweak/AlfredManager.m b/WeChatTweak/Manager/AlfredManager.m similarity index 77% rename from WeChatTweak/AlfredManager.m rename to WeChatTweak/Manager/AlfredManager.m index 10ace71..ef8e905 100644 --- a/WeChatTweak/AlfredManager.m +++ b/WeChatTweak/Manager/AlfredManager.m @@ -17,6 +17,8 @@ @implementation AlfredManager +static int port = 48065; + + (instancetype)sharedInstance { static dispatch_once_t onceToken; static AlfredManager *shared; @@ -34,19 +36,27 @@ // Search contancts [self.server addHandlerForMethod:@"GET" path:@"/wechat/search" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerRequest * _Nonnull request) { NSString *keyword = [request.query[@"keyword"] lowercaseString] ? : @""; + + NSString *hostname = request.headers[@"Host"]; + NSString *url1 = [NSString stringWithFormat:@"127.0.0.1:%d", port]; + NSString *url2 = [NSString stringWithFormat:@"localhost:%d", port]; + if(!([hostname isEqualToString:url1] | [hostname isEqualToString:url2])){ + return [GCDWebServerResponse responseWithStatusCode:404]; + } + NSArray *contacts = ({ MMServiceCenter *serviceCenter = [objc_getClass("MMServiceCenter") defaultCenter]; ContactStorage *contactStorage = [serviceCenter getService:objc_getClass("ContactStorage")]; GroupStorage *groupStorage = [serviceCenter getService:objc_getClass("GroupStorage")]; NSMutableArray *array = [NSMutableArray array]; [array addObjectsFromArray:[contactStorage GetAllFriendContacts]]; - [array addObjectsFromArray:[groupStorage GetAllGroups]]; + [array addObjectsFromArray:[groupStorage GetGroupContactList:2 ContactType:0]]; array; }); NSArray *results = ({ NSMutableArray *results = [NSMutableArray array]; for (WCContactData *contact in contacts) { - BOOL isFriend = contact.m_uiBrandSubscriptionSettings == 0; + BOOL isOfficialAccount = (contact.m_uiCertificationFlag >> 0x3 & 0x1) == 1; BOOL containsNickName = [contact.m_nsNickName.lowercaseString containsString:keyword]; BOOL containsUsername = [contact.m_nsUsrName.lowercaseString containsString:keyword]; BOOL containsAliasName = [contact.m_nsAliasName.lowercaseString containsString:keyword]; @@ -54,7 +64,7 @@ BOOL containsNickNamePinyin = [contact.m_nsFullPY.lowercaseString containsString:keyword]; BOOL containsRemarkPinyin = [contact.m_nsRemarkPYFull.lowercaseString containsString:keyword]; BOOL matchRemarkShortPinyin = [contact.m_nsRemarkPYShort.lowercaseString isEqualToString:keyword]; - if (isFriend && (containsNickName || containsUsername || containsAliasName || containsRemark || containsNickNamePinyin || containsRemarkPinyin || matchRemarkShortPinyin)) { + if (!isOfficialAccount && (containsNickName || containsUsername || containsAliasName || containsRemark || containsNickNamePinyin || containsRemarkPinyin || matchRemarkShortPinyin)) { [results addObject:contact]; } } @@ -64,6 +74,14 @@ }]; // Start chat [self.server addHandlerForMethod:@"GET" path:@"/wechat/start" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse * _Nullable(__kindof GCDWebServerRequest * _Nonnull request) { + + NSString *hostname = request.headers[@"Host"]; + NSString *url1 = [NSString stringWithFormat:@"127.0.0.1:%d", port]; + NSString *url2 = [NSString stringWithFormat:@"localhost:%d", port]; + if(!([hostname isEqualToString:url1] | [hostname isEqualToString:url2])){ + return [GCDWebServerResponse responseWithStatusCode:404]; + } + WCContactData *contact = ({ NSString *session = request.query[@"session"]; WCContactData *contact = nil; @@ -86,7 +104,7 @@ }); return [GCDWebServerResponse responseWithStatusCode:200]; }]; - [self.server startWithOptions:@{GCDWebServerOption_Port: @(48065), + [self.server startWithOptions:@{GCDWebServerOption_Port: [NSNumber numberWithInt:port], GCDWebServerOption_BindToLocalhost: @(YES)} error:nil]; } diff --git a/WeChatTweak/Manager/WTConfigManager.h b/WeChatTweak/Manager/WTConfigManager.h new file mode 100644 index 0000000..2d21970 --- /dev/null +++ b/WeChatTweak/Manager/WTConfigManager.h @@ -0,0 +1,19 @@ +// +// WTConfigManager.h +// WeChatTweak +// +// Created by Sunny Young on 21/03/2018. +// Copyright © 2018 Sunnyyoung. All rights reserved. +// + +#import +#import +#import + +@interface WTConfigManager : NSObject + +@property (nonatomic, assign) BOOL compressedJSONEnabled; + ++ (instancetype)sharedInstance; + +@end diff --git a/WeChatTweak/Manager/WTConfigManager.m b/WeChatTweak/Manager/WTConfigManager.m new file mode 100644 index 0000000..9529c81 --- /dev/null +++ b/WeChatTweak/Manager/WTConfigManager.m @@ -0,0 +1,49 @@ +// +// WTConfigManager.m +// WeChatTweak +// +// Created by Sunny Young on 21/03/2018. +// Copyright © 2018 Sunnyyoung. All rights reserved. +// + +#import "WTConfigManager.h" + +static NSString * const WeChatTweakCompressedJSONEnabledKey = @"WeChatTweakCompressedJSONEnabledKey"; + +@interface WTConfigManager() + +@end + +@implementation WTConfigManager + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static WTConfigManager *shared; + dispatch_once(&onceToken, ^{ + shared = [[WTConfigManager alloc] init]; + }); + return shared; +} + +- (instancetype)init { + self = [super init]; + if (self) { + NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults; + if ([userDefaults objectForKey:WeChatTweakCompressedJSONEnabledKey]) { + _compressedJSONEnabled = [userDefaults boolForKey:WeChatTweakCompressedJSONEnabledKey]; + } else { + _compressedJSONEnabled = YES; + } + } + return self; +} + +#pragma mark - Property method + +- (void)setCompressedJSONEnabled:(BOOL)compressedJSONEnabled { + _compressedJSONEnabled = compressedJSONEnabled; + [NSUserDefaults.standardUserDefaults setBool:compressedJSONEnabled forKey:WeChatTweakCompressedJSONEnabledKey]; + [NSUserDefaults.standardUserDefaults synchronize]; +} + +@end diff --git a/WeChatTweak/Info.plist b/WeChatTweak/Supporting Files/Info.plist similarity index 100% rename from WeChatTweak/Info.plist rename to WeChatTweak/Supporting Files/Info.plist diff --git a/WeChatTweak/WeChatTweakHeaders.h b/WeChatTweak/Supporting Files/WeChatTweakHeaders.h similarity index 73% rename from WeChatTweak/WeChatTweakHeaders.h rename to WeChatTweak/Supporting Files/WeChatTweakHeaders.h index c8efe3c..4906121 100644 --- a/WeChatTweak/WeChatTweakHeaders.h +++ b/WeChatTweak/Supporting Files/WeChatTweakHeaders.h @@ -8,9 +8,19 @@ #import #import +#import +#import + +@interface NSString (MD5) + +- (NSString *)md5String; + +@end @interface WeChat : NSObject +@property(nonatomic) BOOL isAppTerminating; + + (instancetype)sharedInstance; - (void)lock:(id)block; - (void)showMainWindow; @@ -18,6 +28,12 @@ @end +@interface PathUtility : NSObject + ++ (NSString *)GetCurUserDocumentPath; + +@end + @interface MMSearchResultItem : NSObject @property(nonatomic) unsigned long long type; // 0 is single chat, 1 is group chat @@ -29,19 +45,22 @@ @property(nonatomic) unsigned int messageType; @property(nonatomic) unsigned int msgStatus; +@property(nonatomic) long long mesSvrID; @property(retain, nonatomic) NSString *toUsrName; @property(retain, nonatomic) NSString *fromUsrName; @property(retain, nonatomic) NSString *msgContent; @property(nonatomic) unsigned int msgCreateTime; @property(nonatomic) unsigned int mesLocalID; +- (instancetype)initWithMsgType:(long long)arg1; - (BOOL)isSendFromSelf; @end @interface WCContactData : NSObject -@property(nonatomic) unsigned int m_uiBrandSubscriptionSettings; +@property(nonatomic) unsigned int m_uiCertificationFlag; +@property(retain, nonatomic) NSString *m_nsHeadImgUrl; @property(retain, nonatomic) NSString *m_nsNickName; @property(retain, nonatomic) NSString *m_nsUsrName; @property(retain, nonatomic) NSString *m_nsAliasName; @@ -49,6 +68,7 @@ @property(retain, nonatomic) NSString *m_nsFullPY; @property(retain, nonatomic) NSString *m_nsRemarkPYShort; @property(retain, nonatomic) NSString *m_nsRemarkPYFull; +@property(retain, nonatomic) NSString *wt_avatarPath; - (BOOL)isChatStatusNotifyOpen; @@ -65,6 +85,7 @@ - (WCContactData *)GetGroupContact:(NSString *)session; - (NSArray *)GetAllGroups; +- (NSArray *)GetGroupContactList:(NSInteger)arg1 ContactType:(NSInteger)arg2; @end @@ -88,6 +109,19 @@ - (BOOL)canAutoAuth; - (void)AutoAuth; +- (void)onAuthOKOfUser:(id)arg1 withSessionKey:(id)arg2 withServerId:(id)arg3 autoAuthKey:(id)arg4 isAutoAuth:(BOOL)arg5; + +@end + +@interface LogoutCGI: NSObject + +- (void)sendLogoutCGIWithCompletion:(id)arg1; + +@end + +@interface MMAvatarService: NSObject + +- (NSString *)avatarCachePath; @end @@ -103,7 +137,7 @@ @end -@interface MASPreferencesWindowController : NSWindowController +@interface MASPreferencesWindowController: NSWindowController - (id)initWithViewControllers:(NSArray *)arg1; diff --git a/WeChatTweak/Supporting Files/en.lproj/Localizable.strings b/WeChatTweak/Supporting Files/en.lproj/Localizable.strings new file mode 100644 index 0000000..cd7e590 --- /dev/null +++ b/WeChatTweak/Supporting Files/en.lproj/Localizable.strings @@ -0,0 +1,11 @@ +/* + Localizable.strings + WeChatTweak + + Created by Sunny Young on 2018/6/30. + Copyright © 2018 Sunnyyoung. All rights reserved. +*/ + +"Tweak.Title.LoginAnotherAccount" = "Login new account"; +"Tweak.Title.Group" = "Group"; +"Tweak.Message.CatchARecalledMessage" = "[Catched]\n%@"; diff --git a/WeChatTweak/Supporting Files/zh-Hans.lproj/Localizable.strings b/WeChatTweak/Supporting Files/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..586059d --- /dev/null +++ b/WeChatTweak/Supporting Files/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,11 @@ +/* + Localizable.strings + WeChatTweak + + Created by Sunny Young on 2018/6/30. + Copyright © 2018 Sunnyyoung. All rights reserved. +*/ + +"Tweak.Title.LoginAnotherAccount" = "登录新的账号"; +"Tweak.Title.Group" = "群组"; +"Tweak.Message.CatchARecalledMessage" = "[已拦截]\n%@"; diff --git a/WeChatTweak/Supporting Files/zh-Hant.lproj/Localizable.strings b/WeChatTweak/Supporting Files/zh-Hant.lproj/Localizable.strings new file mode 100644 index 0000000..5c1f297 --- /dev/null +++ b/WeChatTweak/Supporting Files/zh-Hant.lproj/Localizable.strings @@ -0,0 +1,11 @@ +/* + Localizable.strings + WeChatTweak + + Created by Sunny Young on 2018/6/30. + Copyright © 2018 Sunnyyoung. All rights reserved. +*/ + +"Tweak.Title.LoginAnotherAccount" = "登錄新的賬號"; +"Tweak.Title.Group" = "群組"; +"Tweak.Message.CatchARecalledMessage" = "[已攔截]\n%@"; diff --git a/WeChatTweak/TweakPreferecesController.xib b/WeChatTweak/TweakPreferecesController.xib deleted file mode 100644 index 35701ef..0000000 --- a/WeChatTweak/TweakPreferecesController.xib +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WeChatTweak/Vendor/fishhook.c b/WeChatTweak/Vendor/fishhook.c new file mode 100644 index 0000000..205ee82 --- /dev/null +++ b/WeChatTweak/Vendor/fishhook.c @@ -0,0 +1,210 @@ +// Copyright (c) 2013, Facebook, Inc. +// All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name Facebook nor the names of its contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// 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" + +#import +#import +#import +#import +#import +#import +#import + +#ifdef __LP64__ +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +typedef struct nlist_64 nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +typedef struct nlist nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT +#endif + +#ifndef SEG_DATA_CONST +#define SEG_DATA_CONST "__DATA_CONST" +#endif + +struct rebindings_entry { + struct rebinding *rebindings; + size_t rebindings_nel; + struct rebindings_entry *next; +}; + +static struct rebindings_entry *_rebindings_head; + +static int prepend_rebindings(struct rebindings_entry **rebindings_head, + struct rebinding rebindings[], + size_t nel) { + struct rebindings_entry *new_entry = (struct rebindings_entry *) malloc(sizeof(struct rebindings_entry)); + if (!new_entry) { + return -1; + } + new_entry->rebindings = (struct rebinding *) malloc(sizeof(struct rebinding) * nel); + if (!new_entry->rebindings) { + free(new_entry); + return -1; + } + memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel); + new_entry->rebindings_nel = nel; + new_entry->next = *rebindings_head; + *rebindings_head = new_entry; + return 0; +} + +static void perform_rebinding_with_section(struct rebindings_entry *rebindings, + section_t *section, + intptr_t slide, + nlist_t *symtab, + char *strtab, + 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 || + symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { + continue; + } + uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; + char *symbol_name = strtab + strtab_offset; + if (strnlen(symbol_name, 2) < 2) { + continue; + } + 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) { + *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; + } + indirect_symbol_bindings[i] = cur->rebindings[j].replacement; + goto symbol_loop; + } + } + cur = cur->next; + } + symbol_loop:; + } +} + +static void rebind_symbols_for_image(struct rebindings_entry *rebindings, + const struct mach_header *header, + intptr_t slide) { + Dl_info info; + if (dladdr(header, &info) == 0) { + return; + } + + segment_command_t *cur_seg_cmd; + segment_command_t *linkedit_segment = NULL; + struct symtab_command* symtab_cmd = NULL; + struct dysymtab_command* dysymtab_cmd = NULL; + + uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); + for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { + cur_seg_cmd = (segment_command_t *)cur; + if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { + linkedit_segment = cur_seg_cmd; + } + } else if (cur_seg_cmd->cmd == LC_SYMTAB) { + symtab_cmd = (struct symtab_command*)cur_seg_cmd; + } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { + dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; + } + } + + if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || + !dysymtab_cmd->nindirectsyms) { + return; + } + + // Find base symbol/string table addresses + uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; + nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); + char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); + + // Get indirect symbol table (array of uint32_t indices into symbol table) + uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); + + cur = (uintptr_t)header + sizeof(mach_header_t); + for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { + cur_seg_cmd = (segment_command_t *)cur; + if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && + strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { + continue; + } + for (uint j = 0; j < cur_seg_cmd->nsects; j++) { + section_t *sect = + (section_t *)(cur + sizeof(segment_command_t)) + j; + if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { + perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); + } + if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { + perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); + } + } + } + } +} + +static void _rebind_symbols_for_image(const struct mach_header *header, + intptr_t slide) { + rebind_symbols_for_image(_rebindings_head, header, slide); +} + +int rebind_symbols_image(void *header, + intptr_t slide, + struct rebinding rebindings[], + size_t rebindings_nel) { + 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); + free(rebindings_head); + return retval; +} + +int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { + int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); + if (retval < 0) { + return retval; + } + // If this was the first call, register callback for image additions (which is also invoked for + // existing images, otherwise, just run on existing images + if (!_rebindings_head->next) { + _dyld_register_func_for_add_image(_rebind_symbols_for_image); + } else { + uint32_t c = _dyld_image_count(); + for (uint32_t i = 0; i < c; i++) { + _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); + } + } + return retval; +} diff --git a/WeChatTweak/Vendor/fishhook.h b/WeChatTweak/Vendor/fishhook.h new file mode 100644 index 0000000..0d8e36a --- /dev/null +++ b/WeChatTweak/Vendor/fishhook.h @@ -0,0 +1,76 @@ +// Copyright (c) 2013, Facebook, Inc. +// All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name Facebook nor the names of its contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// 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. + +#ifndef fishhook_h +#define fishhook_h + +#include +#include + +#if !defined(FISHHOOK_EXPORT) +#define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) +#else +#define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +/* + * A structure representing a particular intended rebinding from a symbol + * name to its replacement + */ +struct rebinding { + const char *name; + void *replacement; + void **replaced; +}; + +/* + * For each rebinding in rebindings, rebinds references to external, indirect + * symbols with the specified name to instead point at replacement for each + * image in the calling process as well as for all future images that are loaded + * by the process. If rebind_functions is called more than once, the symbols to + * rebind are added to the existing list of rebindings, and if a given symbol + * is rebound more than once, the later rebinding will take precedence. + */ +FISHHOOK_VISIBILITY +int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); + +/* + * Rebinds as above, but only in the specified image. The header should point + * to the mach-o header, the slide should be the slide offset. Others as above. + */ +FISHHOOK_VISIBILITY +int rebind_symbols_image(void *header, + intptr_t slide, + struct rebinding rebindings[], + size_t rebindings_nel); + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //fishhook_h + diff --git a/WeChatTweak/WeChatTweak.m b/WeChatTweak/WeChatTweak.m index 429708a..41f4dfa 100755 --- a/WeChatTweak/WeChatTweak.m +++ b/WeChatTweak/WeChatTweak.m @@ -8,50 +8,93 @@ #import "WeChatTweak.h" #import "WeChatTweakHeaders.h" +#import "fishhook.h" #import "NSBundle+WeChatTweak.h" #import "NSString+WeChatTweak.h" #import "TweakPreferecesController.h" #import "AlfredManager.h" +#import "WTConfigManager.h" + +// Global Function +static NSString *(*original_NSHomeDirectory)(void); +static NSArray *(*original_NSSearchPathForDirectoriesInDomains)(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde); +NSString *tweak_NSHomeDirectory() { + return [original_NSHomeDirectory() stringByAppendingPathComponent:@"/Library/Containers/com.tencent.xinWeChat/Data/"]; +} +NSArray *tweak_NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde) { + if (domainMask == NSUserDomainMask) { + NSMutableArray *directories = [original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde) mutableCopy]; + [directories enumerateObjectsUsingBlock:^(NSString * _Nonnull object, NSUInteger index, BOOL * _Nonnull stop) { + switch (directory) { + case NSDocumentDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; break; + case NSLibraryDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library"]; break; + case NSApplicationSupportDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support"]; break; + case NSCachesDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; break; + default: break; + } + }]; + return directories; + } else { + return original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde); + } +} @implementation NSObject (WeChatTweak) #pragma mark - Constructor static void __attribute__((constructor)) tweak(void) { + // Global Function Hook + rebind_symbols((struct rebinding[2]) { + { "NSHomeDirectory", tweak_NSHomeDirectory, (void *)&original_NSHomeDirectory }, + { "NSSearchPathForDirectoriesInDomains", tweak_NSSearchPathForDirectoriesInDomains, (void *)&original_NSSearchPathForDirectoriesInDomains } + }, 2); + // Method Swizzling class_addMethod(objc_getClass("AppDelegate"), @selector(applicationDockMenu:), method_getImplementation(class_getInstanceMethod(objc_getClass("AppDelegate"), @selector(tweak_applicationDockMenu:))), "@:@"); [objc_getClass("AppDelegate") jr_swizzleMethod:NSSelectorFromString(@"applicationDidFinishLaunching:") withMethod:@selector(tweak_applicationDidFinishLaunching:) error:nil]; - [objc_getClass("AppDelegate") jr_swizzleMethod:NSSelectorFromString(@"applicationShouldTerminate:") withMethod:@selector(tweak_applicationShouldTerminate:) error:nil]; + [objc_getClass("LogoutCGI") jr_swizzleMethod:NSSelectorFromString(@"sendLogoutCGIWithCompletion:") withMethod:@selector(tweak_sendLogoutCGIWithCompletion:) error:nil]; + [objc_getClass("AccountService") jr_swizzleMethod:NSSelectorFromString(@"onAuthOKOfUser:withSessionKey:withServerId:autoAuthKey:isAutoAuth:") withMethod:@selector(tweak_onAuthOKOfUser:withSessionKey:withServerId:autoAuthKey:isAutoAuth:) error:nil]; + [objc_getClass("AccountService") jr_swizzleMethod:NSSelectorFromString(@"ManualLogout") withMethod:@selector(tweak_ManualLogout) error:nil]; [objc_getClass("MessageService") jr_swizzleMethod:NSSelectorFromString(@"onRevokeMsg:") withMethod:@selector(tweak_onRevokeMsg:) error:nil]; [objc_getClass("CUtility") jr_swizzleClassMethod:NSSelectorFromString(@"HasWechatInstance") withClassMethod:@selector(tweak_HasWechatInstance) error:nil]; [objc_getClass("MASPreferencesWindowController") jr_swizzleMethod:NSSelectorFromString(@"initWithViewControllers:") withMethod:@selector(tweak_initWithViewControllers:) error:nil]; + + objc_property_attribute_t type = { "T", "@\"NSString\"" }; // NSString + objc_property_attribute_t atom = { "N", "" }; // nonatomic + objc_property_attribute_t ownership = { "&", "" }; // C = copy & = strong + objc_property_attribute_t backingivar = { "V", "_m_nsHeadImgUrl" }; // ivar name + objc_property_attribute_t attrs[] = { type, atom, ownership, backingivar }; + class_addProperty(objc_getClass("WCContactData"), "wt_avatarPath", attrs, 4); + class_addMethod(objc_getClass("WCContactData"), @selector(wt_avatarPath), method_getImplementation(class_getInstanceMethod(objc_getClass("WCContactData"), @selector(wt_avatarPath))), "@@:"); + class_addMethod(objc_getClass("WCContactData"), @selector(setWt_avatarPath:), method_getImplementation(class_getInstanceMethod(objc_getClass("WCContactData"), @selector(setWt_avatarPath:))), "v@:@"); + class_addMethod(objc_getClass("WCContactData"), @selector(modelPropertyWhitelist), method_getImplementation(class_getClassMethod(objc_getClass("WCContactData"), @selector(modelPropertyWhitelist))), "v@:"); } #pragma mark - No Revoke Message -- (void)tweak_onRevokeMsg:(NSString *)message { +- (void)tweak_onRevokeMsg:(MessageData *)message { // Decode message - NSString *session = [message tweak_subStringFrom:@"" to:@""]; - NSUInteger newMessageID = [message tweak_subStringFrom:@"" to:@""].longLongValue; - NSString *replaceMessage = [message tweak_subStringFrom:@""]; - + NSString *session = [message.msgContent tweak_subStringFrom:@"" to:@""]; + NSUInteger newMessageID = [message.msgContent tweak_subStringFrom:@"" to:@""].longLongValue; + NSString *replaceMessage = [message.msgContent tweak_subStringFrom:@""]; // Prepare message data MessageData *localMessageData = [((MessageService *)self) GetMsgData:session svrId:newMessageID]; MessageData *promptMessageData = ({ - MessageData *data = [[objc_getClass("MessageData") alloc] init]; - data.messageType = 10000; + MessageData *data = [[objc_getClass("MessageData") alloc] initWithMsgType:10000]; data.msgStatus = 4; data.toUsrName = localMessageData.toUsrName; data.fromUsrName = localMessageData.fromUsrName; + data.mesSvrID = localMessageData.mesSvrID; data.mesLocalID = localMessageData.mesLocalID; data.msgCreateTime = localMessageData.msgCreateTime; if ([localMessageData isSendFromSelf]) { data.msgContent = replaceMessage; } else { - data.msgContent = [NSString stringWithFormat:@"[已拦截]\n%@", replaceMessage]; + data.msgContent = [NSString stringWithFormat:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.CatchARecalledMessage"], replaceMessage]; } data; }); - + // Prepare notification information MMServiceCenter *serviceCenter = [objc_getClass("MMServiceCenter") defaultCenter]; NSUserNotification *userNotification = [[NSUserNotification alloc] init]; @@ -65,19 +108,20 @@ static void __attribute__((constructor)) tweak(void) { GroupStorage *groupStorage = [serviceCenter getService:objc_getClass("GroupStorage")]; WCContactData *groupContact = [groupStorage GetGroupContact:session]; isChatStatusNotifyOpen = [groupContact isChatStatusNotifyOpen]; - NSString *groupName = groupContact.m_nsNickName.length ? groupContact.m_nsNickName : @"群组"; + NSString *groupName = groupContact.m_nsNickName.length ? groupContact.m_nsNickName : [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Title.Group"]; userNotification.informativeText = [NSString stringWithFormat:@"%@: %@", groupName, replaceMessage]; } - + + // Delete message if it is revoke from myself + if ([localMessageData isSendFromSelf]) { + [((MessageService *)self) DelMsg:session msgList:@[localMessageData] isDelAll:NO isManual:YES]; + [((MessageService *)self) AddLocalMsg:session msgData:promptMessageData]; + } else { + [((MessageService *)self) AddLocalMsg:session msgData:promptMessageData]; + } + // Dispatch notification dispatch_async(dispatch_get_main_queue(), ^{ - // Delete message if it is revoke from myself - if ([localMessageData isSendFromSelf]) { - [((MessageService *)self) DelMsg:session msgList:@[localMessageData] isDelAll:NO isManual:YES]; - [((MessageService *)self) AddLocalMsg:session msgData:promptMessageData]; - } else { - [((MessageService *)self) AddLocalMsg:session msgData:promptMessageData]; - } // Deliver notification if (![localMessageData isSendFromSelf]) { RevokeNotificationType notificationType = [[NSUserDefaults standardUserDefaults] integerForKey:WeChatTweakPreferenceRevokeNotificationTypeKey]; @@ -96,7 +140,9 @@ static void __attribute__((constructor)) tweak(void) { - (NSMenu *)tweak_applicationDockMenu:(NSApplication *)sender { NSMenu *menu = [[NSMenu alloc] init]; - NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@"登录新的微信账号" action:@selector(openNewWeChatInstace:) keyEquivalent:@""]; + NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.Title.LoginAnotherAccount"] + action:@selector(openNewWeChatInstace:) + keyEquivalent:@""]; [menu insertItem:menuItem atIndex:0]; return menu; } @@ -124,15 +170,26 @@ static void __attribute__((constructor)) tweak(void) { [accountService AutoAuth]; } } - [[AlfredManager sharedInstance] startListener]; } -- (NSApplicationTerminateReply)tweak_applicationShouldTerminate:(NSApplication *)sender { +- (void)tweak_onAuthOKOfUser:(id)arg1 withSessionKey:(id)arg2 withServerId:(id)arg3 autoAuthKey:(id)arg4 isAutoAuth:(BOOL)arg5 { + [[AlfredManager sharedInstance] startListener]; + [self tweak_onAuthOKOfUser:arg1 withSessionKey:arg2 withServerId:arg3 autoAuthKey:arg4 isAutoAuth:arg5]; +} + +- (void)tweak_sendLogoutCGIWithCompletion:(id)completion { BOOL enabledAutoAuth = [[NSUserDefaults standardUserDefaults] boolForKey:WeChatTweakPreferenceAutoAuthKey]; - if (enabledAutoAuth) { - return NSTerminateNow; - } else { - return [self tweak_applicationShouldTerminate:sender]; + WeChat *wechat = [objc_getClass("WeChat") sharedInstance]; + if (enabledAutoAuth && wechat.isAppTerminating) { + return; + } + [self tweak_sendLogoutCGIWithCompletion:completion]; +} + +- (void)tweak_ManualLogout { + BOOL enabledAutoAuth = [[NSUserDefaults standardUserDefaults] boolForKey:WeChatTweakPreferenceAutoAuthKey]; + if (!enabledAutoAuth) { + [self tweak_ManualLogout]; } } @@ -145,4 +202,27 @@ static void __attribute__((constructor)) tweak(void) { return [self tweak_initWithViewControllers:viewControllers]; } +#pragma mark - WCContact Data + +- (NSString *)wt_avatarPath { + if (![objc_getClass("PathUtility") respondsToSelector:@selector(GetCurUserDocumentPath)]) { + return @""; + } + NSString *pathString = [NSString stringWithFormat:@"%@/Avatar/%@.jpg", [objc_getClass("PathUtility") GetCurUserDocumentPath], [((WCContactData *)self).m_nsUsrName md5String]]; + return [NSFileManager.defaultManager fileExistsAtPath:pathString] ? pathString : @""; +} + +- (void)setWt_avatarPath:(NSString *)avatarPath { + // For readonly + return; +} + ++ (NSArray *)modelPropertyWhitelist { + NSArray *list =@[@"wt_avatarPath", + @"m_nsRemark", + @"m_nsNickName", + @"m_nsUsrName"]; + return WTConfigManager.sharedInstance.compressedJSONEnabled ? list : nil; +} + @end diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c419263 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file