├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── .php-cs-fixer.php ├── .phplint.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── pre_build.sh └── src ├── Channel.php ├── Channel ├── Bark.php ├── Chanify.php ├── Dingtalk.php ├── Feishu.php ├── Mailer.php ├── PushBack.php ├── PushDeer.php ├── PushPlus.php ├── Pushbullet.php ├── Pushover.php ├── Pushsafer.php ├── QQBot.php ├── ServerChan.php ├── Showdoc.php ├── Techulus.php ├── Telegram.php ├── WeCom.php ├── Webhook.php ├── WxPusher.php ├── Xizhi.php └── Zulip.php ├── ChannelInterface.php ├── Message.php ├── Message ├── BarkMessage.php ├── ChanifyMessage.php ├── DingtalkMessage.php ├── FeishuMessage.php ├── MailerMessage.php ├── PushBackMessage.php ├── PushDeerMessage.php ├── PushPlusMessage.php ├── PushbulletMessage.php ├── PushoverMessage.php ├── PushsaferMessage.php ├── QQBotMessage.php ├── ServerChanMessage.php ├── ShowdocMessage.php ├── TechulusMessage.php ├── TelegramMessage.php ├── WeComMessage.php ├── WebhookMessage.php ├── WxPusherMessage.php ├── XizhiMessage.php └── ZulipMessage.php ├── MessageInterface.php ├── Pusher.php └── Utils.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.yml] 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # source ./.env.example && source ./.env && vendor/bin/phpunit tests 4 | 5 | ## Bark 6 | export BarkToken= 7 | export BarkCustomURL= 8 | 9 | ## Chanify 10 | export ChanifyToken= 11 | export ChanifyCustomURL= 12 | 13 | ## Dingtalk 14 | export DingtalkToken= 15 | export DingtalkSecret= 16 | 17 | ## Feishu 18 | export FeishuToken= 19 | export FeishuSecret= 20 | 21 | ## Mailer 22 | export SMTPHostPort= 23 | export SMTPUser= 24 | export SMTPFrom= 25 | export SMTPTo= 26 | 27 | ## PushBack (100 messages) 28 | export PushBackToken= 29 | 30 | ## Pushbullet (每月必须登录一次) 31 | export PushbulletToken= 32 | 33 | ## PushDeer 34 | export PushDeerToken= 35 | export PushDeerCustomURL= 36 | 37 | ## Pushover (付费,试用期 30 天) 38 | export PushoverToken= 39 | export PushoverUserKey= 40 | export PushoverGroupKey= 41 | 42 | ## PushPlus 43 | export PushPlusToken= 44 | 45 | ## Pushsafer 46 | export PushsaferToken= 47 | 48 | ## QQ Channel Bot 49 | export QQBotToken= 50 | export QQBotAppId= 51 | export QQBotChannelId= 52 | 53 | ## ServerChan 54 | export ServerChanToken= 55 | 56 | ## Showdoc 57 | export ShowdocToken= 58 | 59 | ## Techulus 60 | export TechulusToken= 61 | 62 | ## Telegram 63 | export TelegramToken= 64 | export TelegramChatId="" 65 | 66 | ## Webhook 67 | export WebhookTokenGet= 68 | export WebhookTokenPost= 69 | export WebhookTokenPostJSON= 70 | 71 | ## WeCom(企业微信群机器人) 72 | export WeComToken= 73 | 74 | ## WxPusher 75 | export WxPusherToken= 76 | 77 | ## Xizhi 78 | export XizhiToken= 79 | export XizhiChannelToken= 80 | 81 | ## Zulip 82 | export ZulipEmail= 83 | export ZulipApiKey= 84 | export ZulipCustomURL= 85 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto-detect text files, ensure they use LF. 2 | * text=auto eol=lf 3 | 4 | # These files are always considered text and should use LF. 5 | # See core.whitespace @ https://git-scm.com/docs/git-config for whitespace flags. 6 | *.php text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4 diff=php 7 | *.json text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4 8 | *.test text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4 9 | *.yml text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=2 10 | 11 | # Exclude non-essential files from dist 12 | /tests export-ignore 13 | .github export-ignore 14 | .php_cs export-ignore 15 | .travis.yml export-ignore 16 | appveyor.yml export-ignore 17 | phpunit.xml.dist export-ignore 18 | /phpstan/ export-ignore 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .phpunit.cache 4 | .phpunit.result.cache 5 | .php-cs-fixer.cache 6 | 7 | /vendor/ 8 | 9 | .env 10 | .env.dev -------------------------------------------------------------------------------- /.php-cs-fixer.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | For the full copyright and license information, please view the LICENSE 9 | file that was distributed with this source code. 10 | EOF; 11 | 12 | $finder = PhpCsFixer\Finder::create() 13 | ->files() 14 | ->in(__DIR__.'/src') 15 | ->in(__DIR__.'/tests') 16 | ->name('*.php') 17 | ->exclude([ 18 | __DIR__.'/vendor', 19 | ]) 20 | ->ignoreDotFiles(true); 21 | ; 22 | 23 | $config = new PhpCsFixer\Config(); 24 | return $config->setRules([ 25 | '@PSR2' => true, 26 | 'binary_operator_spaces' => true, 27 | 'blank_line_before_statement' => array('statements' => array('declare', 'return')), 28 | 'cast_spaces' => array('space' => 'single'), 29 | 'header_comment' => array('header' => $header), 30 | 'include' => true, 31 | 32 | 'class_attributes_separation' => array('elements' => array('method' => 'one', 'trait_import' => 'none')), 33 | 'no_blank_lines_after_class_opening' => true, 34 | 'no_blank_lines_after_phpdoc' => true, 35 | 'no_empty_statement' => true, 36 | 'no_extra_blank_lines' => true, 37 | 'no_leading_namespace_whitespace' => true, 38 | 'no_trailing_comma_in_singleline_array' => true, 39 | 'no_whitespace_in_blank_line' => true, 40 | 'object_operator_without_whitespace' => true, 41 | //'phpdoc_align' => true, 42 | 'phpdoc_indent' => true, 43 | 'phpdoc_no_access' => true, 44 | 'phpdoc_no_package' => true, 45 | //'phpdoc_order' => true, 46 | 'phpdoc_scalar' => true, 47 | 'phpdoc_trim' => true, 48 | 'phpdoc_types' => true, 49 | 'psr_autoloading' => true, 50 | 'single_blank_line_before_namespace' => true, 51 | 'standardize_not_equals' => true, 52 | 'ternary_operator_spaces' => true, 53 | 'trailing_comma_in_multiline' => ['elements' => ['arrays']], 54 | 'unary_operator_spaces' => true, 55 | 56 | // imports 57 | 'no_unused_imports' => true, 58 | 'fully_qualified_strict_types' => true, 59 | 'single_line_after_imports' => true, 60 | //'global_namespace_import' => ['import_classes' => true], 61 | 'no_leading_import_slash' => true, 62 | 'single_import_per_statement' => true, 63 | 64 | // PHP 7.2 migration 65 | // TODO later once 2.2 is more stable 66 | // 'array_syntax' => true, 67 | // 'list_syntax' => true, 68 | 'visibility_required' => ['elements' => ['property', 'method', 'const']], 69 | 'non_printable_character' => true, 70 | 'combine_nested_dirname' => true, 71 | 'random_api_migration' => true, 72 | 'ternary_to_null_coalescing' => true, 73 | 'phpdoc_to_param_type' => true, 74 | 'declare_strict_types' => true, 75 | 76 | // TODO php 7.4 migration (one day..) 77 | // 'phpdoc_to_property_type' => true, 78 | ]) 79 | ->setUsingCache(true) 80 | ->setRiskyAllowed(true) 81 | ->setFinder($finder) 82 | ; 83 | -------------------------------------------------------------------------------- /.phplint.yml: -------------------------------------------------------------------------------- 1 | path: ./ 2 | jobs: 10 3 | extensions: 4 | - php 5 | exclude: 6 | - vendor 7 | warning: true 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2022 Jetsung Chan 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pusher 2 | 3 | APP 推送通知 4 | 5 | ## 支持平台 6 | 7 | | 状态 | **国内**平台 | 官网 | 文档 | 案例 | 备注 | 8 | | :------- | :------------------- | :--------------------------------------------------------------------------------------------------------------- | :--- | :----------------------------------------- | :--------------------------------------------------------------------- | 9 | | ✔ **荐** | **Bark** | [https://day.app/2021/06/barkfaq/](https://day.app/2021/06/barkfaq/) | - | [cases](tests/Channels/BarkTest.php) | 仅支持 `iOS` | 10 | | ✔ **荐** | **Chanify** | [https://www.chanify.net/](https://www.chanify.net/) | - | [cases](tests/Channels/ChanifyTest.php) | 仅支持 `iOS` | 11 | | ✔ **荐** | **钉钉群机器人** | [https://open.dingtalk.com/](https://open.dingtalk.com/document/robots/customize-robot-security-settings) | - | [cases](tests/Channels/DingtalkTest.php) | 12 | | ✔ **荐** | **飞书群机器人** | [https://open.feishu.cn/](https://www.feishu.cn/hc/zh-CN/articles/360024984973) | - | [cases](tests/Channels/FeishuTest.php) | 13 | | ✔ **荐** | **电子邮件** | [https://github.com/phpmailer/phpmailer](https://github.com/phpmailer/phpmailer) | - | [cases](tests/Channels/MailerTest.php) | 14 | | ✔ **荐** | **PushDeer** | http://pushdeer.com/ | - | [cases](tests/Channels/PushDeerTest.php) | 15 | | ✔ | **PushPlus** | [https://www.pushplus.plus/doc](https://www.pushplus.plus/) | - | [cases](tests/Channels/PushPlusTest.php) | 16 | | ✔ | **QQ 频道机器人** | [https://bot.q.qq.com/wiki/](https://bot.q.qq.com/wiki/develop/api/openapi/message/post_messages.html) | - | [cases](tests/Channels/QQBotTest.php) | 17 | | ✔ | **Server 酱** | [https://sct.ftqq.com/](https://sct.ftqq.com/) | - | [cases](tests/Channels/ServerChanTest.php) | 18 | | ✔ | **Showdoc** | [https://push.showdoc.com.cn/](https://push.showdoc.com.cn/) | - | [cases](tests/Channels/ShowdocTest.php) | 19 | | ✔ | **Webhook** | - | - | [cases](tests/Channels/WebhookTest.php) | 20 | | ✔ **荐** | **企业微信群机器人** | [https://developer.work.weixin.qq.com](https://developer.work.weixin.qq.com/document/path/91770?notreplace=true) | - | [cases](tests/Channels/WeComTest.php) | 21 | | ✔ | **WxPusher** | [https://wxpusher.zjiecode.com/](https://wxpusher.zjiecode.com/) | - | [cases](tests/Channels/WxPusherTest.php) | 22 | | ✔ | **息知** | [https://xz.qqoq.net/](https://xz.qqoq.net/) | - | [cases](tests/Channels/XizhiTest.php) | 23 | 24 | | 状态 | **国外**平台 | 官网 | 文档 | 案例 | 备注 | 25 | | :------- | :------------- | :-------------------------------------------------------------------------------------- | :--- | :----------------------------------------- | :------------------------------------------------------------------------------------- | 26 | | ✔ | **Pushsafer** | [https://www.pushsafer.com/](https://www.pushsafer.com/en/pushapi#api-message) | - | [cases](tests/Channels/PushsaferTest.php) | 27 | | ✔ | **Techulus** | [https://push.techulus.com/](https://docs.push.techulus.com/api-documentation) | - | [cases](tests/Channels/TechulusTest.php) | (付费) 28 | | ✔ **荐** | **Telegram** | [https://core.telegram.org/bots/](https://core.telegram.org/bots/api#sendmessage) | - | [cases](tests/Channels/TelegramTest.php) |创建[Bot](https://t.me/BotFather)后,将Bot添加至群组或频道,再添加[获取ChatId的机器人进群组](https://t.me/getmyid_bot)(可移除),即可获得`ChatId`| 29 | | ✔ | **PushBack** | [https://pushback.io/](https://pushback.io/docs/getting-started) | - | [cases](tests/Channels/PushBackTest.php) | (100条信息) 30 | | ✔ | **Pushover** | [https://pushover.net/](https://pushover.net/api#messages) | - | [cases](tests/Channels/PushoverTest.php) | (付费,试用期 30 天) | 31 | | ✔ | **Pushbullet** | [https://www.pushbullet.com/](https://docs.pushbullet.com/#create-push) | - | [cases](tests/Channels/PushbulletTest.php) | 不支持 `iOS`。小米手机无法正常接收,但 Chrome 插件可用,长时间不登录账号,功能会失效。 | 32 | | ✔ | **Zulip Chat** | [https://zulip.com/](https://zulip.com/api/send-message) | - | [cases](tests/Channels/ZulipTest.php) | **可[自建](https://zulip.readthedocs.io/en/stable/production/install.html)** | 33 | 34 | **TODO:** 35 | > 36 | 37 | ## 环境 38 | 39 | - **PHP**: `"^8.2"` 40 | 41 | ## 使用 42 | 43 | - https://packagist.org/packages/jetsung/pusher 44 | 45 | ```bash 46 | # 主线版 47 | composer require jetsung/pusher:dev-main 48 | ``` 49 | 50 | ## 仓库镜像 51 | 52 | - https://git.jetsung.com/idev/pusher 53 | - https://framagit.org/idev/pusher 54 | - https://gitcode.com/idev/pusher 55 | - https://github.com/idevsig/pusher 56 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jetsung/pusher", 3 | "description": "A message push extension.", 4 | "keywords": [ 5 | "pusher", 6 | "push message" 7 | ], 8 | "homepage": "https://github.com/idevsig/pusher", 9 | "require": { 10 | "php": "^8.2 || ^8.3 || ^8.4", 11 | "guzzlehttp/guzzle": "^7.9.2", 12 | "phpmailer/phpmailer": "^6.9.3", 13 | "textalk/websocket": "^1.5" 14 | }, 15 | "license": "Apache-2.0", 16 | "autoload": { 17 | "psr-4": { 18 | "Pusher\\": "src/" 19 | } 20 | }, 21 | "authors": [ 22 | { 23 | "name": "Jetsung Chan", 24 | "email": "i@jetsung.com" 25 | } 26 | ], 27 | "require-dev": { 28 | "phpunit/phpunit": "^11.5.3", 29 | "friendsofphp/php-cs-fixer": "^3.68", 30 | "phpstan/phpstan": "^2.1.2" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pre_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -f ".env" ]; then 4 | cp .env .env.example 5 | sed -i '3d' .env.example 6 | sed -i "s@\=.*@\=@" .env.example 7 | fi 8 | 9 | ## 校验 composer.json 10 | composer validate --strict 11 | 12 | ## 修复错误 13 | vendor/bin/phpstan analyse src tests 14 | 15 | ## 修正语法 16 | vendor/bin/php-cs-fixer fix --verbose 17 | 18 | if [ -f "./.env" ]; then 19 | # shellcheck disable=SC1091 20 | . ./.env 21 | 22 | vendor/bin/phpunit tests --verbose 23 | fi 24 | -------------------------------------------------------------------------------- /src/Channel.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher; 13 | 14 | use Exception; 15 | use GuzzleHttp\Psr7\Response; 16 | 17 | class Channel implements ChannelInterface 18 | { 19 | protected array $config = []; // 配置 20 | 21 | protected string $default_url = ''; // 默认 URL 22 | protected string $request_url = ''; // 请求 URL (已拼接的最终 URL) 23 | protected string $custom_url = ''; // 定制请求 URL 24 | protected string $token = ''; // Token 25 | 26 | protected string $method = Pusher::METHOD_GET; // 请求方式:GET,POST,JSON (POST) 27 | protected array $params = []; // 请求数据 28 | protected array $options = []; // 选项,比如 proxy,headers,cookies 29 | 30 | protected Response $response; // 返回数据 31 | protected string $content = ''; // 请求结果正文 32 | 33 | protected bool $status = false; // 请求状态 34 | protected string $error_message = ''; // 错误信息 35 | 36 | public function configureDefaults(array $config): void 37 | { 38 | $default = [ 39 | 'url' => $this->default_url, 40 | ]; 41 | 42 | // 存在 token 参数,设置 token 值 43 | if (isset($config['token'])) { 44 | $this->setToken($config['token']); 45 | unset($config['token']); 46 | } 47 | 48 | // 存在 URL 参数,但判断不正确 49 | if (isset($config['url']) && filter_var($config['url'], FILTER_VALIDATE_URL) === false) { 50 | unset($config['url']); 51 | } 52 | 53 | $this->config = $default + $config; 54 | $this->setURL($this->config['url']); 55 | } 56 | 57 | public function setURL(string $base_url): self 58 | { 59 | if (filter_var($base_url, FILTER_VALIDATE_URL) === false) { 60 | return $this; 61 | } 62 | 63 | $this->config['url'] = rtrim($base_url, '/'); 64 | 65 | return $this; 66 | } 67 | 68 | public function getURL(): string 69 | { 70 | return $this->config['url']; 71 | } 72 | 73 | public function setReqURL(string $url): self 74 | { 75 | $this->custom_url = $url; 76 | 77 | return $this; 78 | } 79 | 80 | public function setToken(string $token): self 81 | { 82 | $this->token = $token; 83 | 84 | return $this; 85 | } 86 | 87 | public function getToken(): string 88 | { 89 | return $this->token; 90 | } 91 | 92 | public function setMethod(string $method = 'GET'): self 93 | { 94 | $method = strtoupper($method); 95 | if (!in_array($method, [ Pusher::METHOD_GET, Pusher::METHOD_POST, Pusher::METHOD_JSON])) { 96 | $method = Pusher::METHOD_GET; 97 | } 98 | $this->method = $method; 99 | 100 | return $this; 101 | } 102 | 103 | public function setOptions(array $options): self 104 | { 105 | $this->options = $options; 106 | 107 | return $this; 108 | } 109 | 110 | public function getResponse(): Response 111 | { 112 | return $this->response; 113 | } 114 | 115 | public function getContents(): string 116 | { 117 | return $this->content; 118 | } 119 | 120 | public function getStatus(): bool 121 | { 122 | return $this->status; 123 | } 124 | 125 | public function getErrMessage(): string 126 | { 127 | return $this->error_message; 128 | } 129 | 130 | // 需要定制(数据请求前需要拼接请求 URL、Token、请求头等等) 131 | public function doCheck(Message $message): self 132 | { 133 | $this->params = $message->getParams(); 134 | 135 | return $this; 136 | } 137 | 138 | // 需要定制(数据需要解析,并且判断请求是否成功) 139 | public function doAfter(): self 140 | { 141 | return $this; 142 | } 143 | 144 | public function send(string $method = Pusher::METHOD_GET, string $uri = '', array $data = [], array $options = []): Response 145 | { 146 | $method = strtoupper($method); 147 | if ($method === Pusher::METHOD_JSON) { 148 | $method = Pusher::METHOD_POST; 149 | $options['json'] = $data; 150 | } elseif ($method === Pusher::METHOD_POST) { 151 | $options['form_params'] = $data; 152 | } else { 153 | $method = Pusher::METHOD_GET; 154 | } 155 | 156 | // var_dump($method, $uri, $options); 157 | $client = new \GuzzleHttp\Client(); 158 | try { 159 | $response = $client->request($method, $uri, $options); 160 | } catch (Exception $e) { 161 | $status_code = $e->getCode(); 162 | if ($status_code === 0) { 163 | $status_code = 408; // 请求超时 (比如 proxy 错误) 164 | } 165 | $this->error_message = $e->getMessage(); 166 | $response = new Response($status_code); 167 | } 168 | 169 | return $response; 170 | } 171 | 172 | public function request(Message $message): string 173 | { 174 | $this->doCheck($message); 175 | $this->response = $this->send($this->method, $this->request_url, $this->params, $this->options); 176 | // var_dump($this->request_url, $this->params); 177 | $status_code = $this->response->getStatusCode(); 178 | if ($status_code >= 200 && 179 | $status_code <= 299) { 180 | $this->content = $this->response->getBody()->getContents(); 181 | $this->doAfter(); 182 | } 183 | 184 | return $this->content; 185 | } 186 | 187 | public function requestArray(Message $message): array 188 | { 189 | return Utils::strToArray($this->request($message)); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/Channel/Bark.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Bark extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/push'; 22 | 23 | protected string $default_url = 'https://api.day.app'; 24 | protected string $method = Pusher::METHOD_JSON; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->params['device_key'] = $this->token; 35 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 36 | 37 | return $this; 38 | } 39 | 40 | public function doAfter(): self 41 | { 42 | try { 43 | $resp = Utils::strToArray($this->content); 44 | $this->status = $resp['code'] === 200; 45 | } catch (Exception $e) { 46 | $this->error_message = $e->getMessage(); 47 | $this->status = false; 48 | } 49 | 50 | return $this; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Channel/Chanify.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Chanify extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/v1/sender/%s'; 22 | 23 | protected string $default_url = 'https://api.chanify.net'; 24 | protected string $method = Pusher::METHOD_JSON; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token); 35 | 36 | return $this; 37 | } 38 | 39 | public function doAfter(): self 40 | { 41 | try { 42 | $resp = Utils::strToArray($this->content); 43 | $this->status = isset($resp['request-uid']) ? true : false; 44 | } catch (Exception $e) { 45 | $this->error_message = $e->getMessage(); 46 | $this->status = false; 47 | } 48 | 49 | return $this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Channel/Dingtalk.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Dingtalk extends \Pusher\Channel 20 | { 21 | private string $secret = ''; 22 | private string $uri_template = '%s/robot/send?access_token=%s'; 23 | 24 | protected string $default_url = 'https://oapi.dingtalk.com'; 25 | protected string $method = Pusher::METHOD_JSON; 26 | 27 | public function __construct(array $config = []) 28 | { 29 | parent::configureDefaults($config); 30 | } 31 | 32 | public function setSecret(string $secret): self 33 | { 34 | $this->secret = $secret; 35 | 36 | return $this; 37 | } 38 | 39 | public function doCheck(Message $message): self 40 | { 41 | $this->params = $message->getParams(); 42 | 43 | $uri = ''; 44 | if ($this->secret !== '') { 45 | $timestamp = time() * 1000; 46 | $sign = Utils::generateSign($this->secret, $timestamp); 47 | $uri = sprintf('×tamp=%d&sign=%s', $timestamp, $sign); 48 | } 49 | 50 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token) . $uri; 51 | 52 | return $this; 53 | } 54 | 55 | public function doAfter(): self 56 | { 57 | try { 58 | $resp = Utils::strToArray($this->content); 59 | $this->status = $resp['errcode'] === 0; 60 | } catch (Exception $e) { 61 | $this->error_message = $e->getMessage(); 62 | $this->status = false; 63 | } 64 | 65 | return $this; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Channel/Feishu.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Feishu extends \Pusher\Channel 20 | { 21 | private string $secret = ''; 22 | private string $uri_template = '%s/open-apis/bot/v2/hook/%s'; 23 | 24 | protected string $default_url = 'https://open.feishu.cn'; 25 | protected string $method = Pusher::METHOD_JSON; 26 | 27 | public function __construct(array $config = []) 28 | { 29 | parent::configureDefaults($config); 30 | } 31 | 32 | public function setSecret(string $secret): self 33 | { 34 | $this->secret = $secret; 35 | 36 | return $this; 37 | } 38 | 39 | public function doCheck(Message $message): self 40 | { 41 | $this->params = $message->getParams(); 42 | if ($this->secret !== '') { 43 | $timestamp = time(); 44 | $this->params['timestamp'] = $timestamp; 45 | $this->params['sign'] = Utils::generateSign2($this->secret, $timestamp); 46 | } 47 | 48 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token); 49 | 50 | return $this; 51 | } 52 | 53 | public function doAfter(): self 54 | { 55 | try { 56 | $resp = Utils::strToArray($this->content); 57 | $this->status = $resp['StatusCode'] === 0; 58 | } catch (Exception $e) { 59 | $this->error_message = $e->getMessage(); 60 | $this->status = false; 61 | } 62 | 63 | return $this; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Channel/Mailer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use PHPMailer\PHPMailer\PHPMailer; 17 | use PHPMailer\PHPMailer\SMTP; 18 | 19 | class Mailer extends \Pusher\Channel 20 | { 21 | public PHPMailer $mail; 22 | 23 | public function __construct(array $config = []) 24 | { 25 | parent::configureDefaults($config); 26 | $this->mail = new PHPMailer(); 27 | $this->mail->isSMTP(); // Send using SMTP 28 | $this->setCharSet(); 29 | } 30 | 31 | // Enable verbose debug output 32 | public function setSMTPDebug(bool $debug): self 33 | { 34 | $this->mail->SMTPDebug = $debug ? SMTP::DEBUG_SERVER : SMTP::DEBUG_OFF; 35 | 36 | return $this; 37 | } 38 | 39 | // Enable SMTP authentication 40 | public function setSMTPAuth(bool $auth): self 41 | { 42 | $this->mail->SMTPAuth = $auth; 43 | 44 | return $this; 45 | } 46 | 47 | // The character set of the message 48 | public function setCharSet(string $charset = PHPMailer::CHARSET_UTF8): self 49 | { 50 | $this->mail->CharSet = $charset; 51 | 52 | return $this; 53 | } 54 | 55 | // Set the SMTP server and port to send through 56 | public function setSMTPHostPort(string $host, int $port): self 57 | { 58 | $this->mail->Host = $host; 59 | $this->mail->Port = $port; 60 | 61 | return $this; 62 | } 63 | 64 | // Set the SMTP server to send through 65 | public function setSMTPHost(string $host): self 66 | { 67 | $this->mail->Host = $host; 68 | 69 | return $this; 70 | } 71 | 72 | // TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` 73 | public function setSMTPPort(int $port = 465): self 74 | { 75 | $this->mail->Port = $port; 76 | 77 | return $this; 78 | } 79 | 80 | // SMTP username, password 81 | public function setSMTPUser(string $username, string $password): self 82 | { 83 | $this->mail->Username = $username; 84 | $this->mail->Password = $password; 85 | 86 | return $this; 87 | } 88 | 89 | // SMTP username 90 | public function setSMTPUsername(string $username): self 91 | { 92 | $this->mail->Username = $username; 93 | 94 | return $this; 95 | } 96 | 97 | // SMTP password 98 | public function setSMTPPassword(string $password): self 99 | { 100 | $this->mail->Password = $password; 101 | 102 | return $this; 103 | } 104 | 105 | // Enable implicit TLS encryption: ssl, tls 106 | public function setSMTPSecure(string $secure = PHPMailer::ENCRYPTION_SMTPS): self 107 | { 108 | $this->mail->SMTPSecure = $secure; 109 | 110 | return $this; 111 | } 112 | 113 | public function setFrom(string $address, string $name = '', bool $auto = true): self 114 | { 115 | $this->mail->setFrom($address, $name, $auto); 116 | 117 | return $this; 118 | } 119 | 120 | // Add a recipient 121 | public function addAddress(string $address, string $name = ''): self 122 | { 123 | $this->mail->addAddress($address, $name); 124 | 125 | return $this; 126 | } 127 | 128 | public function addReplyTo(string $address, string $name = ''): self 129 | { 130 | $this->mail->addReplyTo($address, $name); 131 | 132 | return $this; 133 | } 134 | 135 | public function addCC(string $address, string $name = ''): self 136 | { 137 | $this->mail->addCC($address, $name); 138 | 139 | return $this; 140 | } 141 | 142 | public function addBCC(string $address, string $name = ''): self 143 | { 144 | $this->mail->addBCC($address, $name); 145 | 146 | return $this; 147 | } 148 | 149 | public function isHTML(bool $html = true): self 150 | { 151 | $this->mail->isHTML($html); 152 | 153 | return $this; 154 | } 155 | 156 | public function sendTo(Message $message): bool 157 | { 158 | $postData = $message->getParams(); 159 | $this->mail->Subject = $postData['subject']; 160 | $this->mail->Body = $postData['body']; 161 | $this->mail->AltBody = $postData['altBody']; 162 | 163 | $this->status = $this->mail->send(); 164 | 165 | return $this->status; 166 | } 167 | 168 | public function request(Message $message): string 169 | { 170 | try { 171 | $this->content = $this->sendTo($message) ? 'success' : 'fail'; 172 | } catch (Exception $e) { 173 | $this->error_message = $this->mail->ErrorInfo; 174 | $this->content = 'fail'; 175 | } 176 | 177 | return $this->content; 178 | } 179 | 180 | public function requestArray(Message $message): array 181 | { 182 | $resp = []; 183 | $this->request($message); 184 | if ($this->status) { 185 | $resp = [ 186 | 'code' => 0, 187 | 'message' => 'success', 188 | ]; 189 | } else { 190 | $resp = [ 191 | 'code' => 1, 192 | 'message' => $this->mail->ErrorInfo, 193 | ]; 194 | } 195 | 196 | return $resp; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/Channel/PushBack.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | 18 | class PushBack extends \Pusher\Channel 19 | { 20 | private string $uri_template = '%s/v1/send'; 21 | 22 | protected string $default_url = 'https://api.pushback.io'; 23 | protected string $method = Pusher::METHOD_JSON; 24 | 25 | public function __construct(array $config = []) 26 | { 27 | parent::configureDefaults($config); 28 | } 29 | 30 | public function doCheck(Message $message): self 31 | { 32 | $this->params = $message->getParams(); 33 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 34 | 35 | $this->options['headers'] = [ 36 | 'Authorization' => sprintf('Bearer %s', $this->token), 37 | ]; 38 | 39 | return $this; 40 | } 41 | 42 | public function doAfter(): self 43 | { 44 | try { 45 | $this->status = $this->content === '0'; 46 | } catch (Exception $e) { 47 | $this->error_message = $e->getMessage(); 48 | $this->status = false; 49 | } 50 | 51 | return $this; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Channel/PushDeer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class PushDeer extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/message/push'; 22 | 23 | protected string $default_url = 'https://api2.pushdeer.com'; 24 | protected string $method = Pusher::METHOD_POST; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->params['pushkey'] = $this->token; 35 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 36 | 37 | return $this; 38 | } 39 | 40 | public function doAfter(): self 41 | { 42 | try { 43 | $resp = Utils::strToArray($this->content); 44 | $count = count($resp['content']['result']); 45 | $this->status = $count !== 0; 46 | } catch (Exception $e) { 47 | $this->error_message = $e->getMessage(); 48 | $this->status = false; 49 | } 50 | 51 | return $this; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Channel/PushPlus.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | 18 | class PushPlus extends \Pusher\Channel 19 | { 20 | private string $uri_template = '%s/send'; 21 | 22 | protected string $default_url = 'https://www.pushplus.plus'; 23 | protected string $method = Pusher::METHOD_JSON; 24 | 25 | public function __construct(array $config = []) 26 | { 27 | parent::configureDefaults($config); 28 | } 29 | 30 | public function doCheck(Message $message): self 31 | { 32 | $this->params = $message->getParams(); 33 | $this->params['token'] = $this->token; 34 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 35 | 36 | return $this; 37 | } 38 | 39 | public function doAfter(): self 40 | { 41 | try { 42 | $resp = json_decode($this->content, true); 43 | $this->status = $resp['code'] === 200; 44 | 45 | if (!$this->status) { 46 | $this->error_message = $resp['msg']; 47 | } 48 | } catch (Exception $e) { 49 | $this->error_message = $e->getMessage(); 50 | $this->status = false; 51 | } 52 | 53 | return $this; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Channel/Pushbullet.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Pushbullet extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/v2/pushes'; 22 | 23 | protected string $default_url = 'https://api.pushbullet.com'; 24 | protected string $method = Pusher::METHOD_POST; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 35 | 36 | $this->options['headers'] = [ 37 | 'Access-Token' => $this->token, 38 | ]; 39 | 40 | return $this; 41 | } 42 | 43 | public function doAfter(): self 44 | { 45 | try { 46 | $resp = Utils::strToArray($this->content); 47 | $this->status = $resp['active']; 48 | } catch (Exception $e) { 49 | $this->error_message = $e->getMessage(); 50 | $this->status = false; 51 | } 52 | 53 | return $this; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Channel/Pushover.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Pushover extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/1/messages.json'; 22 | 23 | protected string $default_url = 'https://api.pushover.net'; 24 | protected string $method = Pusher::METHOD_JSON; 25 | 26 | private string $user = ''; // UserKey, GroupKey 27 | 28 | public function __construct(array $config = []) 29 | { 30 | parent::configureDefaults($config); 31 | } 32 | 33 | public function setUser(string $user): self 34 | { 35 | $this->user = $user; 36 | 37 | return $this; 38 | } 39 | 40 | public function doCheck(Message $message): self 41 | { 42 | $this->params = $message->getParams(); 43 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 44 | $this->params['token'] = $this->token; 45 | $this->params['user'] = $this->user; 46 | 47 | return $this; 48 | } 49 | 50 | public function doAfter(): self 51 | { 52 | try { 53 | $resp = Utils::strToArray($this->content); 54 | $this->status = $resp['status'] === 1; 55 | } catch (Exception $e) { 56 | $this->error_message = $e->getMessage(); 57 | $this->status = false; 58 | } 59 | 60 | return $this; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Channel/Pushsafer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Pushsafer extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/api'; 22 | 23 | protected string $default_url = 'https://www.pushsafer.com'; 24 | protected string $method = Pusher::METHOD_POST; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 35 | $this->params['k'] = $this->token; 36 | 37 | return $this; 38 | } 39 | 40 | public function doAfter(): self 41 | { 42 | try { 43 | $resp = Utils::strToArray($this->content); 44 | $this->status = $resp['status'] === 1; 45 | } catch (Exception $e) { 46 | $this->error_message = $e->getMessage(); 47 | $this->status = false; 48 | } 49 | 50 | return $this; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Channel/QQBot.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | use WebSocket\Client; 19 | 20 | class QQBot extends \Pusher\Channel 21 | { 22 | private string $uri_template = '%s/channels/%s/messages'; 23 | 24 | protected string $default_url = 'https://api.sgroup.qq.com'; 25 | protected string $method = Pusher::METHOD_JSON; 26 | 27 | private Client $wsClient; 28 | 29 | private string $appID = ''; // APP ID 30 | private string $channelID = ''; // 子频道 ID 31 | private string $wss_url = 'wss://api.sgroup.qq.com/websocket'; 32 | 33 | // 沙盒模式 34 | private bool $sandbox = false; 35 | private string $req_sandbox_url = 'https://sandbox.api.sgroup.qq.com'; 36 | private string $wss_sandbox_url = 'wss://sandbox.api.sgroup.qq.com/websocket'; 37 | 38 | public function __construct(array $config = []) 39 | { 40 | parent::configureDefaults($config); 41 | } 42 | 43 | public function Sandbox(bool $sandbox = false): self 44 | { 45 | $this->sandbox = $sandbox; 46 | $url = $this->sandbox ? $this->req_sandbox_url : $this->default_url; 47 | $this->setURL($url); 48 | 49 | return $this; 50 | } 51 | 52 | public function setAppID(string $appID): self 53 | { 54 | $this->appID = $appID; 55 | 56 | return $this; 57 | } 58 | 59 | public function setChannelID(string $channelID): self 60 | { 61 | $this->channelID = $channelID; 62 | 63 | return $this; 64 | } 65 | 66 | public function doCheck(Message $message): self 67 | { 68 | if ($this->custom_url !== '') { 69 | $this->request_url = sprintf('%s%s', $this->config['url'], $this->custom_url); 70 | $this->custom_url = ''; 71 | } else { 72 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->channelID); 73 | } 74 | 75 | // 非 GET 请求,需要连接 WS 76 | if ($this->method !== 'GET') { 77 | $wssURL = $this->sandbox ? $this->wss_sandbox_url : $this->wss_url; 78 | $this->wsClient = new Client($wssURL); 79 | // $client->text("Hello WebSocket.org!"); 80 | $this->wsClient->text(json_encode([ 81 | 'op' => 2, 82 | 'd' => [ 83 | 'token' => sprintf('Bot %s.%s', $this->appID, $this->token), 84 | 'intents' => 0 | 1 << 9, 85 | ], 86 | ])); 87 | // echo $client->receive(); 88 | 89 | $this->params = $message->getParams(); 90 | } 91 | 92 | $this->options = [ 93 | 'headers' => [ 94 | 'Authorization' => sprintf('Bot %s.%s', $this->appID, $this->token), 95 | ], 96 | ]; 97 | 98 | return $this; 99 | } 100 | 101 | public function doAfter(): self 102 | { 103 | if (isset($this->wsClient) && $this->wsClient->isConnected()) { 104 | $this->wsClient->close(); 105 | } 106 | 107 | try { 108 | $resp = Utils::strToArray($this->content); 109 | 110 | // 非 GET 请求 111 | if ($this->method !== Pusher::METHOD_GET) { 112 | // 通用的 JSON 格式 113 | if (isset($resp['code']) && !in_array($resp['code'], [ 200, 304023 ])) { 114 | new Exception($resp['message'], 401); 115 | } 116 | } 117 | 118 | $this->status = true; 119 | } catch (Exception $e) { 120 | $this->error_message = $e->getMessage(); 121 | $this->status = false; 122 | } 123 | 124 | return $this; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/Channel/ServerChan.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class ServerChan extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/%s.send'; 22 | 23 | protected string $default_url = 'https://sctapi.ftqq.com'; 24 | protected string $method = Pusher::METHOD_POST; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token); 35 | 36 | return $this; 37 | } 38 | 39 | public function doAfter(): self 40 | { 41 | try { 42 | $resp = Utils::strToArray($this->content); 43 | $this->status = $resp['data']['errno'] === 0; 44 | } catch (Exception $e) { 45 | $this->error_message = $e->getMessage(); 46 | $this->status = false; 47 | } 48 | 49 | return $this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Channel/Showdoc.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Showdoc extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/server/api/push/%s'; 22 | 23 | protected string $default_url = 'https://push.showdoc.com.cn'; 24 | protected string $method = Pusher::METHOD_POST; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token); 35 | 36 | return $this; 37 | } 38 | 39 | public function doAfter(): self 40 | { 41 | try { 42 | $resp = Utils::strToArray($this->content); 43 | $this->status = $resp['error_code'] === 0; 44 | } catch (Exception $e) { 45 | $this->error_message = $e->getMessage(); 46 | $this->status = false; 47 | } 48 | 49 | return $this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Channel/Techulus.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Techulus extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/api/v1/notify/%s'; 22 | 23 | protected string $default_url = 'https://push.techulus.com'; 24 | protected string $method = Pusher::METHOD_JSON; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token); 35 | 36 | return $this; 37 | } 38 | 39 | public function doAfter(): self 40 | { 41 | try { 42 | $resp = Utils::strToArray($this->content); 43 | $this->status = $resp['success'] ? true : false; 44 | } catch (Exception $e) { 45 | $this->error_message = $e->getMessage(); 46 | $this->status = false; 47 | } 48 | 49 | return $this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Channel/Telegram.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Telegram extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/bot%s/sendMessage'; 22 | 23 | protected string $default_url = 'https://api.telegram.org'; 24 | protected string $method = Pusher::METHOD_JSON; 25 | 26 | private string $chat_id = ''; // 频道的用户名或唯一标识符 27 | 28 | public function __construct(array $config = []) 29 | { 30 | parent::configureDefaults($config); 31 | } 32 | 33 | public function setChatID(string $id): self 34 | { 35 | $this->chat_id = $id; 36 | 37 | return $this; 38 | } 39 | 40 | public function getChatID(): string 41 | { 42 | return $this->chat_id; 43 | } 44 | 45 | public function doCheck(Message $message): self 46 | { 47 | $this->params = $message->getParams(); 48 | 49 | if ($this->custom_url !== '') { 50 | $this->request_url = sprintf('%s/bot%s%s', $this->config['url'], $this->token, $this->custom_url); 51 | $this->custom_url = ''; 52 | } else { 53 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token); 54 | } 55 | $this->params['chat_id'] = $this->chat_id; 56 | 57 | return $this; 58 | } 59 | 60 | public function doAfter(): self 61 | { 62 | try { 63 | $resp = Utils::strToArray($this->content); 64 | $this->status = $resp['ok']; 65 | } catch (Exception $e) { 66 | $this->error_message = $e->getMessage(); 67 | $this->status = false; 68 | } 69 | 70 | return $this; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Channel/WeCom.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class WeCom extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/cgi-bin/webhook/send?key=%s'; 22 | 23 | protected string $default_url = 'https://qyapi.weixin.qq.com'; 24 | protected string $method = Pusher::METHOD_JSON; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token); 35 | 36 | return $this; 37 | } 38 | 39 | public function doAfter(): self 40 | { 41 | try { 42 | $resp = Utils::strToArray($this->content); 43 | $this->status = $resp['errcode'] === 0; 44 | } catch (Exception $e) { 45 | $this->error_message = $e->getMessage(); 46 | $this->status = false; 47 | } 48 | 49 | return $this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Channel/Webhook.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | class Webhook extends \Pusher\Channel 15 | { 16 | public function __construct(array $config = []) 17 | { 18 | parent::configureDefaults($config); 19 | } 20 | 21 | public function setReqURL(string $url): self 22 | { 23 | $this->request_url = $url; 24 | 25 | return $this; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Channel/WxPusher.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class WxPusher extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/api/send/message'; 22 | 23 | protected string $default_url = 'http://wxpusher.zjiecode.com'; 24 | protected string $method = Pusher::METHOD_JSON; 25 | 26 | public function __construct(array $config = []) 27 | { 28 | parent::configureDefaults($config); 29 | } 30 | 31 | public function doCheck(Message $message): self 32 | { 33 | $this->params = $message->getParams(); 34 | $this->params['appToken'] = $this->token; 35 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 36 | 37 | return $this; 38 | } 39 | 40 | public function doAfter(): self 41 | { 42 | try { 43 | $resp = Utils::strToArray($this->content); 44 | $this->status = $resp['code'] === 1000; 45 | } catch (Exception $e) { 46 | $this->error_message = $e->getMessage(); 47 | $this->status = false; 48 | } 49 | 50 | return $this; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Channel/Xizhi.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Xizhi extends \Pusher\Channel 20 | { 21 | private string $type = 'send'; // 推送类型:单点.send,频道.channel 22 | private string $uri_template = '%s/%s.%s'; 23 | 24 | protected string $default_url = 'https://xizhi.qqoq.net'; 25 | protected string $method = Pusher::METHOD_POST; 26 | 27 | public const TYPE_SEND = 'send'; 28 | public const TYPE_CHANNEL = 'channel'; 29 | 30 | public function __construct(array $config = []) 31 | { 32 | parent::configureDefaults($config); 33 | } 34 | 35 | public function setType(string $type = self::TYPE_SEND): self 36 | { 37 | $this->type = ($type === self::TYPE_CHANNEL) ? self::TYPE_CHANNEL : self::TYPE_SEND; 38 | 39 | return $this; 40 | } 41 | 42 | public function getType(): string 43 | { 44 | return $this->type; 45 | } 46 | 47 | public function doCheck(Message $message): self 48 | { 49 | $this->params = $message->getParams(); 50 | $this->request_url = sprintf($this->uri_template, $this->config['url'], $this->token, $this->type); 51 | 52 | return $this; 53 | } 54 | 55 | public function doAfter(): self 56 | { 57 | try { 58 | $resp = Utils::strToArray($this->content); 59 | $this->status = $resp['code'] === 200; 60 | } catch (Exception $e) { 61 | $this->error_message = $e->getMessage(); 62 | $this->status = false; 63 | } 64 | 65 | return $this; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Channel/Zulip.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Channel; 13 | 14 | use Exception; 15 | use Pusher\Message; 16 | use Pusher\Pusher; 17 | use Pusher\Utils; 18 | 19 | class Zulip extends \Pusher\Channel 20 | { 21 | private string $uri_template = '%s/api/v1/messages'; 22 | 23 | protected string $default_url = ''; 24 | protected string $method = Pusher::METHOD_POST; 25 | 26 | private string $email = ''; 27 | private string $api_key = ''; 28 | 29 | public function __construct(array $config = []) 30 | { 31 | parent::configureDefaults($config); 32 | } 33 | 34 | public function setEmail(string $email): self 35 | { 36 | $this->email = $email; 37 | 38 | return $this; 39 | } 40 | 41 | public function getEmail(): string 42 | { 43 | return $this->email; 44 | } 45 | 46 | public function setApiKey(string $key): self 47 | { 48 | $this->api_key = $key; 49 | 50 | return $this; 51 | } 52 | 53 | public function getApiKey(): string 54 | { 55 | return $this->api_key; 56 | } 57 | 58 | public function doCheck(Message $message): self 59 | { 60 | $this->params = $message->getParams(); 61 | 62 | if ($this->custom_url !== '') { 63 | $this->request_url = $this->config['url'] . $this->custom_url; 64 | $this->custom_url = ''; 65 | } else { 66 | $this->request_url = sprintf($this->uri_template, $this->config['url']); 67 | } 68 | 69 | if ($this->token !== '') { 70 | $this->options['headers'] = [ 71 | 'Authorization' => sprintf('Basic %s', $this->token), 72 | ]; 73 | } elseif ($this->email !== '' && $this->api_key !== '') { 74 | $this->options['auth'] = [ $this->email, $this->api_key ]; 75 | } 76 | 77 | return $this; 78 | } 79 | 80 | public function doAfter(): self 81 | { 82 | try { 83 | $resp = Utils::strToArray($this->content); 84 | $this->status = $resp['result'] === 'success'; 85 | } catch (Exception $e) { 86 | $this->error_message = $e->getMessage(); 87 | $this->status = false; 88 | } 89 | 90 | return $this; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/ChannelInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher; 13 | 14 | use GuzzleHttp\Psr7\Response; 15 | 16 | interface ChannelInterface 17 | { 18 | public function configureDefaults(array $config): void; 19 | 20 | public function setURL(string $base_url): self; 21 | 22 | public function getURL(): string; 23 | 24 | public function setReqURL(string $url): self; 25 | 26 | public function setToken(string $token): self; 27 | 28 | public function getToken(): string; 29 | 30 | public function setMethod(string $method): self; 31 | 32 | public function setOptions(array $options): self; 33 | 34 | public function getResponse(): Response; 35 | 36 | public function getContents(): string; 37 | 38 | public function getStatus(): bool; 39 | 40 | public function getErrMessage(): string; 41 | 42 | public function doCheck(Message $message): self; 43 | 44 | public function doAfter(): self; 45 | 46 | public function send(string $method, string $uri, array $data, array $options): Response; 47 | 48 | public function request(Message $message): string; 49 | 50 | public function requestArray(Message $message): array; 51 | } 52 | -------------------------------------------------------------------------------- /src/Message.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher; 13 | 14 | class Message implements MessageInterface 15 | { 16 | protected array $params; 17 | 18 | public function Data(array $data): self 19 | { 20 | $this->params = $data; 21 | 22 | return $this; 23 | } 24 | 25 | public function generateParams(): self 26 | { 27 | return $this; 28 | } 29 | 30 | public function getParams(): array 31 | { 32 | if (empty($this->params)) { 33 | $this->generateParams(); 34 | } 35 | 36 | return $this->params; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Message/BarkMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class BarkMessage extends Message 17 | { 18 | private string $title = ''; // 通知标题 19 | private string $body = ''; // 通知内容 20 | private int $badge = 1; // 图标旁边显示数字 21 | private string $copy = ''; // 复制文本 22 | private string $sound = ''; // 通知提示音 23 | private string $icon = ''; // 图标的 URL 24 | private string $group = ''; // 通知组 25 | private string $url = ''; // 跳转 URL 26 | 27 | public function __construct(string $body = '', string $title = '') 28 | { 29 | $this->body = $body; 30 | $this->title = $title; 31 | } 32 | 33 | public function setBody(string $body): self 34 | { 35 | $this->body = $body; 36 | 37 | return $this; 38 | } 39 | 40 | public function getBody(): string 41 | { 42 | return $this->body; 43 | } 44 | 45 | public function setTitle(string $title): self 46 | { 47 | $this->title = $title; 48 | 49 | return $this; 50 | } 51 | 52 | public function getTitle(): string 53 | { 54 | return $this->title; 55 | } 56 | 57 | public function setBadge(int $badge): self 58 | { 59 | $this->badge = $badge; 60 | 61 | return $this; 62 | } 63 | 64 | public function getBadge(): int 65 | { 66 | return $this->badge; 67 | } 68 | 69 | public function setCopy(string $copy): self 70 | { 71 | $this->copy = $copy; 72 | 73 | return $this; 74 | } 75 | 76 | public function getCopy(): string 77 | { 78 | return $this->copy; 79 | } 80 | 81 | public function setSound(string $sound): self 82 | { 83 | $this->sound = $sound; 84 | 85 | return $this; 86 | } 87 | 88 | public function getSound(): string 89 | { 90 | return $this->sound; 91 | } 92 | 93 | public function setIcon(string $icon): self 94 | { 95 | $this->icon = $icon; 96 | 97 | return $this; 98 | } 99 | 100 | public function getIcon(): string 101 | { 102 | return $this->icon; 103 | } 104 | 105 | public function setGroup(string $group): self 106 | { 107 | $this->group = $group; 108 | 109 | return $this; 110 | } 111 | 112 | public function getGroup(): string 113 | { 114 | return $this->group; 115 | } 116 | 117 | public function setURL(string $url): self 118 | { 119 | $this->url = $url; 120 | 121 | return $this; 122 | } 123 | 124 | public function getURL(): string 125 | { 126 | return $this->url; 127 | } 128 | 129 | public function generateParams(): self 130 | { 131 | $this->params = [ 132 | 'body' => $this->body, 133 | 'title' => $this->title, 134 | 'badge' => $this->badge, 135 | 'sound' => $this->sound, 136 | 'icon' => $this->icon, 137 | 'group' => $this->group, 138 | 'url' => $this->url, 139 | ]; 140 | 141 | return $this; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/Message/ChanifyMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class ChanifyMessage extends Message 17 | { 18 | private string $title = ''; // 通知标题 19 | private string $text = ''; // 通知内容 20 | private string $copy = ''; // 复制文本 21 | private int $autocopy = 1; // 自动复制 22 | private int $sound = 1; // 启用声音 23 | private int $priority = 10; // 优先级 24 | // active: 点亮屏幕并可能播放声音。 25 | // passive: 不点亮屏幕或播放声音。 26 | // time-sensitive: 点亮屏幕并可能播放声音; 可能会在“请勿打扰”期间展示。 27 | private string $interruptionLevel = 'active'; // 通知时间的中断级别 28 | private array $actions = []; // 动作列表 29 | private array $timeline = []; // Timeline 对象 30 | 31 | // 发送链接 32 | private string $link = ''; 33 | 34 | public function __construct(string $text = '', string $title = '') 35 | { 36 | $this->text = $text; 37 | $this->title = $title; 38 | } 39 | 40 | public function setText(string $text): self 41 | { 42 | $this->text = $text; 43 | 44 | return $this; 45 | } 46 | 47 | public function getText(): string 48 | { 49 | return $this->text; 50 | } 51 | 52 | public function setTitle(string $title): self 53 | { 54 | $this->title = $title; 55 | 56 | return $this; 57 | } 58 | 59 | public function getTitle(): string 60 | { 61 | return $this->title; 62 | } 63 | 64 | public function setCopy(string $copy): self 65 | { 66 | $this->copy = $copy; 67 | 68 | return $this; 69 | } 70 | 71 | public function getCopy(): string 72 | { 73 | return $this->copy; 74 | } 75 | 76 | public function setSound(int $sound): self 77 | { 78 | $this->sound = $sound; 79 | 80 | return $this; 81 | } 82 | 83 | public function getSound(): int 84 | { 85 | return $this->sound; 86 | } 87 | 88 | public function setPriority(int $priority): self 89 | { 90 | $this->priority = $priority; 91 | 92 | return $this; 93 | } 94 | 95 | public function getPriority(): int 96 | { 97 | return $this->priority; 98 | } 99 | 100 | public function setInterruptionLevel(string $interruptionLevel): self 101 | { 102 | $this->interruptionLevel = $interruptionLevel; 103 | 104 | return $this; 105 | } 106 | 107 | public function getInterruptionLevel(): string 108 | { 109 | return $this->interruptionLevel; 110 | } 111 | 112 | public function setActions(array $actions): self 113 | { 114 | $this->actions = $actions; 115 | 116 | return $this; 117 | } 118 | 119 | public function getActions(): array 120 | { 121 | return $this->actions; 122 | } 123 | 124 | public function addAction(string $action): self 125 | { 126 | $this->actions[] = $action; 127 | 128 | return $this; 129 | } 130 | 131 | public function setTimeline(array $timeline): self 132 | { 133 | $this->timeline = $timeline; 134 | 135 | return $this; 136 | } 137 | 138 | public function getTimeline(): array 139 | { 140 | return $this->timeline; 141 | } 142 | 143 | public function setLink(string $link): self 144 | { 145 | $this->link = $link; 146 | 147 | return $this; 148 | } 149 | 150 | public function getLink(): string 151 | { 152 | return $this->link; 153 | } 154 | 155 | public function generateParams(): self 156 | { 157 | if ($this->link !== '') { 158 | $this->params = [ 159 | 'sound' => $this->sound, 160 | 'priority' => $this->priority, 161 | 'link' => $this->link, 162 | ]; 163 | } else { 164 | $this->params = [ 165 | 'title' => $this->title, 166 | 'text' => $this->text, 167 | 'copy' => $this->copy, 168 | 'autocopy' => $this->autocopy, 169 | 'sound' => $this->sound, 170 | 'priority' => $this->priority, 171 | 'interruption-level' => $this->interruptionLevel, 172 | 'actions' => $this->actions, 173 | 'timeline' => $this->timeline, 174 | ]; 175 | 176 | if (!empty($this->timeline)) { 177 | unset($this->params['actions']); 178 | } else { 179 | unset($this->params['timeline']); 180 | } 181 | } 182 | 183 | return $this; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/Message/DingtalkMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class DingtalkMessage extends Message 17 | { 18 | public const TYPE_TEXT = 'text'; 19 | public const TYPE_LINK = 'link'; 20 | public const TYPE_MARKDOWN = 'markdown'; 21 | public const TYPE_ACTION_CARD = 'actionCard'; 22 | public const TYPE_FEED_CARD = 'feedCard'; 23 | 24 | private string $msgtype = ''; // 消息类型 text,link,markdown,actionCard,feedCard 25 | private string $content = ''; // 通知内容 26 | private string $title = ''; // 消息标题 27 | 28 | // text,markdown 类型 29 | private array $atMobiles = []; // 被@人的手机号 30 | private array $atUserIds = []; // 被@人的用户userid 31 | private bool $isAtAll = false; // 是否@所有人 32 | 33 | // link 类型 34 | private string $messageUrl = ''; // M, 点击消息跳转的URL 35 | private string $picUrl = ''; // 图片URL 36 | 37 | // ActionCard 类型 38 | private string $btnOrientation = '0'; // 排列方向 0:按钮竖直排列,1:按钮横向排列 39 | 40 | ///(整体跳转) 41 | private string $singleTitle = ''; // M, 单个按钮的标题 42 | private string $singleURL = ''; // M, 点击消息跳转的URL 43 | 44 | ///(独立跳转) 45 | private array $btns = []; // M, 按钮列表 [{'title', 'actionURL'}, {'title', 'actionURL'}] 46 | 47 | // FeedCard 类型 48 | private array $links = []; // M, 链接列表 [{'title', 'messageURL', 'picURL'}, {'title', 'messageURL', 'picURL'}] 49 | 50 | public function __construct( 51 | string $msgtype = '', 52 | string $content = '', 53 | string $title = '', 54 | ) { 55 | $this->msgtype = $this->filter_message_type($msgtype); 56 | $this->content = $content; 57 | $this->title = $title; 58 | } 59 | 60 | public function setMsgType(string $type): self 61 | { 62 | $this->msgtype = $this->filter_message_type($type); 63 | 64 | return $this; 65 | } 66 | 67 | public function getMsgType(): string 68 | { 69 | return $this->msgtype; 70 | } 71 | 72 | public function setContent(string $content): self 73 | { 74 | $this->content = $content; 75 | 76 | return $this; 77 | } 78 | 79 | public function getContent(): string 80 | { 81 | return $this->content; 82 | } 83 | 84 | public function setTitle(string $title): self 85 | { 86 | $this->title = $title; 87 | 88 | return $this; 89 | } 90 | 91 | public function getTitle(): string 92 | { 93 | return $this->title; 94 | } 95 | 96 | public function setAtMobiles(array $mobile): self 97 | { 98 | $this->atMobiles = $mobile; 99 | 100 | return $this; 101 | } 102 | 103 | public function getAtMobiles(): array 104 | { 105 | return $this->atMobiles; 106 | } 107 | 108 | public function setAtUserIds(array $users): self 109 | { 110 | $this->atUserIds = $users; 111 | 112 | return $this; 113 | } 114 | 115 | public function getAtUserIds(): array 116 | { 117 | return $this->atUserIds; 118 | } 119 | 120 | public function setIsAll(bool $all): self 121 | { 122 | $this->isAtAll = $all; 123 | 124 | return $this; 125 | } 126 | 127 | public function getIsAll(): bool 128 | { 129 | return $this->isAtAll; 130 | } 131 | 132 | public function setMessageUrl(string $messageUrl): self 133 | { 134 | $this->messageUrl = $messageUrl; 135 | 136 | return $this; 137 | } 138 | 139 | public function getMessageUrl(): string 140 | { 141 | return $this->messageUrl; 142 | } 143 | 144 | public function setPicUrl(string $picUrl): self 145 | { 146 | $this->picUrl = $picUrl; 147 | 148 | return $this; 149 | } 150 | 151 | public function getPicUrl(): string 152 | { 153 | return $this->picUrl; 154 | } 155 | 156 | public function setBtnOrientation(string $btnOrientation): self 157 | { 158 | $this->btnOrientation = $btnOrientation; 159 | 160 | return $this; 161 | } 162 | 163 | public function getBtnOrientation(): string 164 | { 165 | return $this->btnOrientation; 166 | } 167 | 168 | public function setSingleTitle(string $singleTitle): self 169 | { 170 | $this->singleTitle = $singleTitle; 171 | 172 | return $this; 173 | } 174 | 175 | public function getSingleTitle(): string 176 | { 177 | return $this->singleTitle; 178 | } 179 | 180 | public function setSingleURL(string $singleURL): self 181 | { 182 | $this->singleURL = $singleURL; 183 | 184 | return $this; 185 | } 186 | 187 | public function getSingleURL(): string 188 | { 189 | return $this->singleURL; 190 | } 191 | 192 | public function setBtns(array $btns): self 193 | { 194 | $this->btns = $btns; 195 | 196 | return $this; 197 | } 198 | 199 | public function getBtns(): array 200 | { 201 | return $this->btns; 202 | } 203 | 204 | public function addBtn(string $title, string $actionURL): self 205 | { 206 | $this->btns[] = [ 207 | 'title' => $title, 208 | 'actionURL' => $actionURL, 209 | ]; 210 | 211 | return $this; 212 | } 213 | 214 | public function setLinks(array $links): self 215 | { 216 | $this->links = $links; 217 | 218 | return $this; 219 | } 220 | 221 | public function getLinks(): array 222 | { 223 | return $this->links; 224 | } 225 | 226 | public function addLink(string $title, string $messageURL, string $picURL): self 227 | { 228 | $this->links[] = [ 229 | 'title' => $title, 230 | 'messageURL' => $messageURL, 231 | 'picURL' => $picURL, 232 | ]; 233 | 234 | return $this; 235 | } 236 | 237 | public function generateParams(): self 238 | { 239 | $this->params = [ 240 | 'msgtype' => $this->msgtype, 241 | ]; 242 | 243 | $params = []; 244 | 245 | switch ($this->msgtype) { 246 | case self::TYPE_LINK: 247 | $params = [ 248 | 'link' => [ 249 | 'title' => $this->title, 250 | 'text' => $this->content, 251 | 'picUrl' => $this->picUrl, 252 | 'messageUrl' => $this->messageUrl, 253 | ], 254 | ]; 255 | break; 256 | 257 | case self::TYPE_MARKDOWN: 258 | $params = [ 259 | 'markdown' => [ 260 | 'title' => $this->title, 261 | 'text' => $this->content, 262 | ], 263 | 'at' => [ 264 | 'atMobiles' => $this->atMobiles, 265 | 'atUserIds' => $this->atUserIds, 266 | 'isAtAll' => $this->isAtAll, 267 | ], 268 | ]; 269 | break; 270 | 271 | case self::TYPE_ACTION_CARD: 272 | $params = [ 273 | 'actionCard' => [ 274 | 'title' => $this->title, 275 | 'text' => $this->content, 276 | 'btnOrientation' => $this->btnOrientation, 277 | ], 278 | ]; 279 | 280 | if (count($this->btns) > 0) { 281 | $params['actionCard']['btns'] = $this->btns; 282 | } else { 283 | $params['actionCard']['singleTitle'] = $this->singleTitle; 284 | $params['actionCard']['singleURL'] = $this->singleURL; 285 | } 286 | break; 287 | 288 | case self::TYPE_FEED_CARD: 289 | $params = [ 290 | 'feedCard' => [ 291 | 'links' => $this->links, 292 | ], 293 | ]; 294 | break; 295 | 296 | case self::TYPE_TEXT: 297 | default: 298 | $params = [ 299 | 'text' => [ 300 | 'content' => $this->content, 301 | ], 302 | 'at' => [ 303 | 'atMobiles' => $this->atMobiles, 304 | 'atUserIds' => $this->atUserIds, 305 | 'isAtAll' => $this->isAtAll, 306 | ], 307 | ]; 308 | } 309 | 310 | $this->params += $params; 311 | 312 | return $this; 313 | } 314 | 315 | private function filter_message_type(string $type): string 316 | { 317 | return in_array($type, [ 318 | self::TYPE_TEXT, 319 | self::TYPE_LINK, 320 | self::TYPE_MARKDOWN, 321 | self::TYPE_ACTION_CARD, 322 | self::TYPE_FEED_CARD, 323 | ]) ? $type : self::TYPE_TEXT; 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /src/Message/FeishuMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class FeishuMessage extends Message 17 | { 18 | public const TYPE_TEXT = 'text'; 19 | public const TYPE_POST = 'post'; 20 | public const TYPE_IMAGE = 'image'; 21 | public const TYPE_SHARE_CHAT = 'share_chat'; 22 | public const TYPE_INTERACTIVE = 'interactive'; 23 | 24 | private string $msgType = ''; // 消息类型 text,post,image,share_chat,interactive 25 | private string $title = ''; // 消息标题 26 | 27 | // text 文本类型 28 | private string $text = ''; 29 | 30 | // post 富文本类型 31 | private array $contents = []; // 段落. 一个富文本可分多个段落 32 | 33 | // image 图片类型 34 | private string $imageKey = ''; // 图片的唯一标识 35 | 36 | // share_chat "分享群名片"类型 37 | private string $shareChatID = ''; // 群名片 ID 38 | 39 | // interactive "消息卡片"类型 40 | private array $interactiveElements = []; // 用于定义卡片正文内容 41 | private array $interactiveI18nElements = []; // 为卡片的正文部分定义多语言内容 42 | private array $interactiveConfig = []; // 卡片属性 43 | private array $interactiveHeader = []; // 卡片标题 44 | 45 | public function __construct( 46 | string $msg_type = '', 47 | string $title = '', 48 | ) { 49 | $this->msgType = $this->filter_message_type($msg_type); 50 | $this->title = $title; 51 | } 52 | 53 | public function setMsgType(string $type): self 54 | { 55 | $this->msgType = $this->filter_message_type($type); 56 | 57 | return $this; 58 | } 59 | 60 | public function getMsgType(): string 61 | { 62 | return $this->msgType; 63 | } 64 | 65 | public function setTitle(string $title): self 66 | { 67 | $this->title = $title; 68 | 69 | return $this; 70 | } 71 | 72 | public function getTitle(): string 73 | { 74 | return $this->title; 75 | } 76 | 77 | public function setText(string $text): self 78 | { 79 | $this->text = $text; 80 | 81 | return $this; 82 | } 83 | 84 | public function getText(): string 85 | { 86 | return $this->text; 87 | } 88 | 89 | public function setContents(array $contents): self 90 | { 91 | $this->contents = $contents; 92 | 93 | return $this; 94 | } 95 | 96 | public function getContents(): array 97 | { 98 | return $this->contents; 99 | } 100 | 101 | public function addContent(array $content): self 102 | { 103 | $this->contents[] = $content; 104 | 105 | return $this; 106 | } 107 | 108 | public function setImageKey(string $key): self 109 | { 110 | $this->imageKey = $key; 111 | 112 | return $this; 113 | } 114 | 115 | public function getImageKey(): string 116 | { 117 | return $this->imageKey; 118 | } 119 | 120 | public function setShareChatID(string $shareChatID): self 121 | { 122 | $this->shareChatID = $shareChatID; 123 | 124 | return $this; 125 | } 126 | 127 | public function getShareChatID(): string 128 | { 129 | return $this->shareChatID; 130 | } 131 | 132 | public function setInteractiveElements(array $elements): self 133 | { 134 | $this->interactiveElements = $elements; 135 | 136 | return $this; 137 | } 138 | 139 | public function getInteractiveElements(): array 140 | { 141 | return $this->interactiveElements; 142 | } 143 | 144 | public function setInteractiveI18nElements(array $elements): self 145 | { 146 | $this->interactiveI18nElements = $elements; 147 | 148 | return $this; 149 | } 150 | 151 | public function getInteractiveI18nElements(): array 152 | { 153 | return $this->interactiveI18nElements; 154 | } 155 | 156 | public function setInteractiveHeader(array $header): self 157 | { 158 | $this->interactiveHeader = $header; 159 | 160 | return $this; 161 | } 162 | 163 | public function getInteractiveHeader(): array 164 | { 165 | return $this->interactiveHeader; 166 | } 167 | 168 | public function setInteractiveConfig(array $config): self 169 | { 170 | $this->interactiveConfig = $config; 171 | 172 | return $this; 173 | } 174 | 175 | public function getInteractiveConfig(): array 176 | { 177 | return $this->interactiveConfig; 178 | } 179 | 180 | public function generateParams(): self 181 | { 182 | $this->params = [ 183 | 'msg_type' => $this->msgType, 184 | ]; 185 | 186 | $params = []; 187 | 188 | switch ($this->msgType) { 189 | case self::TYPE_POST: 190 | $params = [ 191 | 'content' => [ 192 | 'post' => [ 193 | 'zh_cn' => [ 194 | 'title' => $this->title, 195 | 'content' => $this->contents, 196 | ], 197 | ], 198 | ], 199 | ]; 200 | break; 201 | 202 | case self::TYPE_IMAGE: 203 | $params = [ 204 | 'content' => [ 205 | 'image_key' => $this->imageKey, 206 | ], 207 | ]; 208 | break; 209 | 210 | case self::TYPE_SHARE_CHAT: 211 | $params = [ 212 | 'content' => [ 213 | 'share_chat_id' => $this->shareChatID, 214 | ], 215 | ]; 216 | break; 217 | 218 | case self::TYPE_INTERACTIVE: 219 | $params = [ 220 | 'card' => [ 221 | 'config' => $this->interactiveConfig, 222 | 'header' => $this->interactiveHeader, 223 | // 'elements' => $this->interactiveElements, 224 | // 'i18n_elements' => $this->interactiveI18nElements, 225 | ], 226 | ]; 227 | empty($this->interactiveElements) || $params['card']['elements'] = $this->interactiveElements; 228 | empty($this->interactiveI18nElements) || $params['card']['i18n_elements'] = $this->interactiveI18nElements; 229 | 230 | break; 231 | 232 | case self::TYPE_TEXT: 233 | default: 234 | $params = [ 235 | 'content' => [ 236 | 'text' => $this->text, 237 | ], 238 | ]; 239 | } 240 | 241 | $this->params += $params; 242 | 243 | // echo json_encode($this->params); 244 | return $this; 245 | } 246 | 247 | public function filter_message_type(string $type): string 248 | { 249 | return in_array($type, [ 250 | self::TYPE_TEXT, 251 | self::TYPE_POST, 252 | self::TYPE_IMAGE, 253 | self::TYPE_SHARE_CHAT, 254 | self::TYPE_INTERACTIVE, 255 | ]) ? $type : self::TYPE_TEXT; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/Message/MailerMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class MailerMessage extends Message 17 | { 18 | private string $subject = ''; // 主题 19 | private string $body = ''; // 内容 20 | private string $altBody = ''; // 非 HTML 邮件客户端的纯文本正文 21 | 22 | public function __construct(string $body = '', string $subject = '', string $altBody = '') 23 | { 24 | $this->body = $body; 25 | $this->subject = $subject; 26 | $this->altBody = $altBody; 27 | } 28 | 29 | public function setSubject(string $subject): self 30 | { 31 | $this->subject = $subject; 32 | 33 | return $this; 34 | } 35 | 36 | public function getSubject(): string 37 | { 38 | return $this->subject; 39 | } 40 | 41 | public function setBody(string $body): self 42 | { 43 | $this->body = $body; 44 | 45 | return $this; 46 | } 47 | 48 | public function getBody(): string 49 | { 50 | return $this->body; 51 | } 52 | 53 | public function setAltBody(string $altBody): self 54 | { 55 | $this->altBody = $altBody; 56 | 57 | return $this; 58 | } 59 | 60 | public function getAltBody(): string 61 | { 62 | return $this->altBody; 63 | } 64 | 65 | public function generateParams(): self 66 | { 67 | $this->params = [ 68 | 'subject' => $this->subject, 69 | 'body' => $this->body, 70 | 'altBody' => $this->altBody, 71 | ]; 72 | 73 | return $this; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Message/PushBackMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class PushBackMessage extends Message 17 | { 18 | private string $body = ''; // 通知内容 19 | private string $title = ''; // 通知标题 20 | private string $id = ''; // id 21 | private string $action1 = ''; 22 | private string $action2 = ''; 23 | private string $reply = ''; 24 | 25 | public function __construct(string $body = '', string $title = '') 26 | { 27 | $this->body = $body; 28 | $this->title = $title; 29 | } 30 | 31 | public function setTitle(string $title): self 32 | { 33 | $this->title = $title; 34 | 35 | return $this; 36 | } 37 | 38 | public function getTitle(): string 39 | { 40 | return $this->title; 41 | } 42 | 43 | public function setBody(string $body): self 44 | { 45 | $this->body = $body; 46 | 47 | return $this; 48 | } 49 | 50 | public function getBody(): string 51 | { 52 | return $this->body; 53 | } 54 | 55 | public function setID(string $id): self 56 | { 57 | $this->id = $id; 58 | 59 | return $this; 60 | } 61 | 62 | public function getID(): string 63 | { 64 | return $this->id; 65 | } 66 | 67 | public function setAction1(string $action): self 68 | { 69 | $this->action1 = $action; 70 | 71 | return $this; 72 | } 73 | 74 | public function getAction1(): string 75 | { 76 | return $this->action1; 77 | } 78 | 79 | public function setAction2(string $action): self 80 | { 81 | $this->action2 = $action; 82 | 83 | return $this; 84 | } 85 | 86 | public function getAction2(): string 87 | { 88 | return $this->action2; 89 | } 90 | 91 | public function setReply(string $reply): self 92 | { 93 | $this->reply = $reply; 94 | 95 | return $this; 96 | } 97 | 98 | public function getReply(): string 99 | { 100 | return $this->reply; 101 | } 102 | 103 | public function generateParams(): self 104 | { 105 | $this->params = [ 106 | 'title' => $this->title, 107 | 'body' => $this->body, 108 | 'id' => $this->id, 109 | 'action1' => $this->action1, 110 | 'action2' => $this->action2, 111 | 'reply' => $this->reply, 112 | ]; 113 | 114 | return $this; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Message/PushDeerMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class PushDeerMessage extends Message 17 | { 18 | public const TYPE_TEXT = 'text'; 19 | public const TYPE_MARKDOWN = 'markdown'; 20 | public const TYPE_IMAGE = 'image'; 21 | 22 | private string $type = ''; // 通知类型 text,markdown,image 23 | private string $desp = ''; // 通知内容 24 | private string $text = ''; // 通知标题 25 | 26 | public function __construct(string $type = '', string $desp = '', string $text = '') 27 | { 28 | $this->type = $this->filter_message_type($type); 29 | $this->desp = $desp; 30 | $this->text = $text; 31 | } 32 | 33 | public function setType(string $type): self 34 | { 35 | $this->type = $this->filter_message_type($type); 36 | 37 | return $this; 38 | } 39 | 40 | public function getType(): string 41 | { 42 | return $this->type; 43 | } 44 | 45 | public function setDesp(string $desp): self 46 | { 47 | $this->desp = $desp; 48 | 49 | return $this; 50 | } 51 | 52 | public function getDesp(): string 53 | { 54 | return $this->desp; 55 | } 56 | 57 | public function setText(string $text): self 58 | { 59 | $this->text = $text; 60 | 61 | return $this; 62 | } 63 | 64 | public function getText(): string 65 | { 66 | return $this->text; 67 | } 68 | 69 | public function generateParams(): self 70 | { 71 | $this->params = [ 72 | 'text' => $this->text, 73 | 'desp' => $this->desp, 74 | 'type' => $this->type, 75 | ]; 76 | 77 | return $this; 78 | } 79 | 80 | private function filter_message_type(string $type): string 81 | { 82 | $type = strtolower($type); 83 | 84 | return in_array($type, [ self::TYPE_TEXT, self::TYPE_MARKDOWN, self::TYPE_IMAGE ]) ? $type : self::TYPE_TEXT; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Message/PushPlusMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class PushPlusMessage extends Message 17 | { 18 | private string $content = ''; // 通知内容 19 | private string $title = ''; // 通知标题 20 | 21 | private string $template = ''; // 发送消息模板, html,json,cloudMonitor 阿里云监控报警定制模板 (该平台不支持) 22 | private string $topic = ''; // 群组编码 23 | 24 | public function __construct(string $content = '', string $title = '') 25 | { 26 | $this->content = $content; 27 | $this->title = $title; 28 | } 29 | 30 | public function setContent(string $content): self 31 | { 32 | $this->content = $content; 33 | 34 | return $this; 35 | } 36 | 37 | public function getContent(): string 38 | { 39 | return $this->content; 40 | } 41 | 42 | public function setTitle(string $title): self 43 | { 44 | $this->title = $title; 45 | 46 | return $this; 47 | } 48 | 49 | public function getTitle(): string 50 | { 51 | return $this->title; 52 | } 53 | 54 | public function setTemplate(string $template): self 55 | { 56 | $this->template = $template; 57 | 58 | return $this; 59 | } 60 | 61 | public function getTemplate(): string 62 | { 63 | return $this->template; 64 | } 65 | 66 | public function setTopic(string $topic): self 67 | { 68 | $this->topic = $topic; 69 | 70 | return $this; 71 | } 72 | 73 | public function getTopic(): string 74 | { 75 | return $this->topic; 76 | } 77 | 78 | public function generateParams(): self 79 | { 80 | $this->params = [ 81 | 'title' => $this->title, 82 | 'content' => $this->content, 83 | 'template' => $this->template, 84 | 'topic' => $this->topic, 85 | ]; 86 | 87 | return $this; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Message/PushbulletMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class PushbulletMessage extends Message 17 | { 18 | public const TYPE_NOTE = 'note'; 19 | public const TYPE_FILE = 'file'; 20 | public const TYPE_LINK = 'link'; 21 | 22 | private string $type = ''; // 类型: note,file,link 23 | private string $body = ''; // 通知内容 24 | private string $title = ''; // 通知标题 25 | 26 | // link 类型 27 | private string $url = ''; 28 | 29 | // file 类型 30 | private string $file_name = ''; 31 | private string $file_type = ''; 32 | private string $file_url = ''; 33 | 34 | private string $email = ''; //接收者 35 | private string $device_iden = ''; // 接收者设备 ID 36 | private string $client_iden = ''; // 客户端 ID 37 | private string $channel_tag = ''; // 通道 38 | 39 | public function __construct(string $type = '', string $body = '', string $title = '') 40 | { 41 | $this->type = $this->filter_message_type($type); 42 | $this->body = $body; 43 | $this->title = $title; 44 | } 45 | 46 | public function setType(string $type): self 47 | { 48 | $this->type = $this->filter_message_type($type); 49 | 50 | return $this; 51 | } 52 | 53 | public function getType(): string 54 | { 55 | return $this->type; 56 | } 57 | 58 | public function setBody(string $body): self 59 | { 60 | $this->body = $body; 61 | 62 | return $this; 63 | } 64 | 65 | public function getBody(): string 66 | { 67 | return $this->body; 68 | } 69 | 70 | public function setTitle(string $title): self 71 | { 72 | $this->title = $title; 73 | 74 | return $this; 75 | } 76 | 77 | public function getTitle(): string 78 | { 79 | return $this->title; 80 | } 81 | 82 | public function setURL(string $url): self 83 | { 84 | $this->url = $url; 85 | 86 | return $this; 87 | } 88 | 89 | public function getURL(): string 90 | { 91 | return $this->url; 92 | } 93 | 94 | public function setFileName(string $name): self 95 | { 96 | $this->file_name = $name; 97 | 98 | return $this; 99 | } 100 | 101 | public function getFileName(): string 102 | { 103 | return $this->file_name; 104 | } 105 | 106 | public function setFileType(string $type): self 107 | { 108 | $this->file_type = $type; 109 | 110 | return $this; 111 | } 112 | 113 | public function getFileType(): string 114 | { 115 | return $this->file_type; 116 | } 117 | 118 | public function setFileURL(string $url): self 119 | { 120 | $this->file_url = $url; 121 | 122 | return $this; 123 | } 124 | 125 | public function getFileURL(): string 126 | { 127 | return $this->file_url; 128 | } 129 | 130 | public function setEmail(string $email): self 131 | { 132 | $this->email = $email; 133 | 134 | return $this; 135 | } 136 | 137 | public function getEmail(): string 138 | { 139 | return $this->email; 140 | } 141 | 142 | public function setDeviceIden(string $iden): self 143 | { 144 | $this->device_iden = $iden; 145 | 146 | return $this; 147 | } 148 | 149 | public function getDeviceIden(): string 150 | { 151 | return $this->device_iden; 152 | } 153 | 154 | public function setClientIden(string $iden): self 155 | { 156 | $this->client_iden = $iden; 157 | 158 | return $this; 159 | } 160 | 161 | public function getClientIden(): string 162 | { 163 | return $this->client_iden; 164 | } 165 | 166 | public function setChannelTag(string $tag): self 167 | { 168 | $this->channel_tag = $tag; 169 | 170 | return $this; 171 | } 172 | 173 | public function getChannelTag(): string 174 | { 175 | return $this->channel_tag; 176 | } 177 | 178 | public function generateParams(): self 179 | { 180 | $this->params = [ 181 | 'type' => $this->type, 182 | 'title' => $this->title, 183 | 'body' => $this->body, 184 | 'url' => $this->url, 185 | 'file_name' => $this->file_name, 186 | 'file_type' => $this->file_type, 187 | 'file_url' => $this->file_url, 188 | ]; 189 | 190 | if ($this->email !== '') { 191 | $this->params['email'] = $this->email; 192 | } 193 | 194 | if ($this->device_iden !== '') { 195 | $this->params['device_iden'] = $this->device_iden; 196 | } 197 | 198 | if ($this->client_iden !== '') { 199 | $this->params['client_iden'] = $this->client_iden; 200 | } 201 | 202 | if ($this->channel_tag !== '') { 203 | $this->params['channel_tag'] = $this->channel_tag; 204 | } 205 | 206 | return $this; 207 | } 208 | 209 | private function filter_message_type(string $type): string 210 | { 211 | $type = strtolower($type); 212 | 213 | return in_array($type, [ self::TYPE_NOTE, self::TYPE_LINK, self::TYPE_FILE ]) ? $type : self::TYPE_NOTE; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /src/Message/PushoverMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class PushoverMessage extends Message 17 | { 18 | private string $message = ''; // 通知内容 19 | private string $title = ''; // 通知标题 20 | 21 | private string $device = ''; // 设备名称 22 | 23 | private bool $html = false; // 是否支持 HTML 24 | private string $url = ''; // 链接 25 | 26 | public function __construct(string $message = '', string $title = '') 27 | { 28 | $this->message = $message; 29 | $this->title = $title; 30 | } 31 | 32 | public function setMessage(string $message): self 33 | { 34 | $this->message = $message; 35 | 36 | return $this; 37 | } 38 | 39 | public function getMessage(): string 40 | { 41 | return $this->message; 42 | } 43 | 44 | public function setTitle(string $title): self 45 | { 46 | $this->title = $title; 47 | 48 | return $this; 49 | } 50 | 51 | public function getTitle(): string 52 | { 53 | return $this->title; 54 | } 55 | 56 | public function setHtml(bool $enable): self 57 | { 58 | $this->html = $enable; 59 | 60 | return $this; 61 | } 62 | 63 | public function getHtml(): bool 64 | { 65 | return $this->html; 66 | } 67 | 68 | public function setURL(string $url): self 69 | { 70 | $this->url = $url; 71 | 72 | return $this; 73 | } 74 | 75 | public function getURL(): string 76 | { 77 | return $this->url; 78 | } 79 | 80 | public function setDevice(string $device): self 81 | { 82 | $this->device = $device; 83 | 84 | return $this; 85 | } 86 | 87 | public function getDevice(): string 88 | { 89 | return $this->device; 90 | } 91 | 92 | public function generateParams(): self 93 | { 94 | $this->params = [ 95 | 'title' => $this->title, 96 | 'message' => $this->message, 97 | 'device' => $this->device, 98 | 'html' => $this->html ? 1 : 0, 99 | 'url' => $this->url, 100 | ]; 101 | 102 | return $this; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Message/PushsaferMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class PushsaferMessage extends Message 17 | { 18 | private string $message = ''; 19 | private string $title = ''; 20 | 21 | private int $sound = 0; // 声音 22 | private int $vibration = 1; // 振动 23 | private int $icon = 1; 24 | private string $icon_color = ''; 25 | private string $device = 'a'; 26 | private string $url = ''; 27 | private string $url_title = ''; 28 | private string $picture = ''; 29 | 30 | public function __construct(string $message = '', string $title = '') 31 | { 32 | $this->message = $message; 33 | $this->title = $title; 34 | } 35 | 36 | public function setMessage(string $message): self 37 | { 38 | $this->message = $message; 39 | 40 | return $this; 41 | } 42 | 43 | public function getMessage(): string 44 | { 45 | return $this->message; 46 | } 47 | 48 | public function setTitle(string $title): self 49 | { 50 | $this->title = $title; 51 | 52 | return $this; 53 | } 54 | 55 | public function getTitle(): string 56 | { 57 | return $this->title; 58 | } 59 | 60 | public function setSound(int $sound): self 61 | { 62 | $this->sound = $sound; 63 | 64 | return $this; 65 | } 66 | 67 | public function getSound(): int 68 | { 69 | return $this->sound; 70 | } 71 | 72 | public function setVibration(int $vibration): self 73 | { 74 | $this->vibration = $vibration; 75 | 76 | return $this; 77 | } 78 | 79 | public function getVibration(): int 80 | { 81 | return $this->vibration; 82 | } 83 | 84 | public function setIcon(int $icon): self 85 | { 86 | $this->icon = $icon; 87 | 88 | return $this; 89 | } 90 | 91 | public function getIcon(): int 92 | { 93 | return $this->icon; 94 | } 95 | 96 | public function setIconColor(string $color): self 97 | { 98 | $this->icon_color = $color; 99 | 100 | return $this; 101 | } 102 | 103 | public function getIconColor(): string 104 | { 105 | return $this->icon_color; 106 | } 107 | 108 | public function setDevice(string $device): self 109 | { 110 | $this->device = $device; 111 | 112 | return $this; 113 | } 114 | 115 | public function getDevice(): string 116 | { 117 | return $this->device; 118 | } 119 | 120 | public function setURL(string $url): self 121 | { 122 | $this->url = $url; 123 | 124 | return $this; 125 | } 126 | 127 | public function getURL(): string 128 | { 129 | return $this->url; 130 | } 131 | 132 | public function setUrlTitle(string $title): self 133 | { 134 | $this->url_title = $title; 135 | 136 | return $this; 137 | } 138 | 139 | public function getUrlTitle(): string 140 | { 141 | return $this->url_title; 142 | } 143 | 144 | public function setPicture(string $picture): self 145 | { 146 | $this->picture = $picture; 147 | 148 | return $this; 149 | } 150 | 151 | public function getPicture(): string 152 | { 153 | return $this->picture; 154 | } 155 | 156 | public function generateParams(): self 157 | { 158 | $this->params = [ 159 | 't' => $this->title, 160 | 'm' => $this->message, 161 | 's' => $this->sound, 162 | 'v' => $this->vibration, 163 | 'i' => $this->icon, 164 | 'c' => $this->icon_color, 165 | 'd' => $this->device, 166 | 'u' => $this->url, 167 | 'ut' => $this->url_title, 168 | 'p' => $this->picture, 169 | ]; 170 | 171 | return $this; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Message/QQBotMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class QQBotMessage extends Message 17 | { 18 | private string $content = ''; // 通知内容 19 | 20 | private array $embed = []; // embed 消息 21 | private array $ark = []; // ark 消息 22 | private string $image = ''; // 图片 url 地址,平台会转存该图片,用于下发图片消息 23 | private array $markdown = []; // markdown 消息对象 24 | 25 | private array $messageReference = []; // 引用消息 26 | private string $msgID = ''; // 要回复的消息 ID 27 | 28 | public function __construct(string $content = '') 29 | { 30 | $this->content = $content; 31 | } 32 | 33 | public function setContent(string $content): self 34 | { 35 | $this->content = $content; 36 | 37 | return $this; 38 | } 39 | 40 | public function getContent(): string 41 | { 42 | return $this->content; 43 | } 44 | 45 | public function setEmbed(array $embed): self 46 | { 47 | $this->embed = $embed; 48 | 49 | return $this; 50 | } 51 | 52 | public function getEmbed(): array 53 | { 54 | return $this->embed; 55 | } 56 | 57 | public function setArk(array $ark): self 58 | { 59 | $this->ark = $ark; 60 | 61 | return $this; 62 | } 63 | 64 | public function getArk(): array 65 | { 66 | return $this->ark; 67 | } 68 | 69 | public function setImage(string $image): self 70 | { 71 | $this->image = $image; 72 | 73 | return $this; 74 | } 75 | 76 | public function getImage(): string 77 | { 78 | return $this->image; 79 | } 80 | 81 | public function setMarkdown(array $markdown): self 82 | { 83 | $this->markdown = $markdown; 84 | 85 | return $this; 86 | } 87 | 88 | public function getMarkdown(): array 89 | { 90 | return $this->markdown; 91 | } 92 | 93 | public function setMessageReference(array $message): self 94 | { 95 | $this->messageReference = $message; 96 | 97 | return $this; 98 | } 99 | 100 | public function getMessageReference(): array 101 | { 102 | return $this->messageReference; 103 | } 104 | 105 | public function setMsgID(string $msgID): self 106 | { 107 | $this->msgID = $msgID; 108 | 109 | return $this; 110 | } 111 | 112 | public function getMsgID(): string 113 | { 114 | return $this->msgID; 115 | } 116 | 117 | public function generateParams(): self 118 | { 119 | $this->params = [ 120 | 'msg_id' => $this->msgID, 121 | 'content' => $this->content, 122 | 123 | ]; 124 | 125 | if (!empty($this->markdown)) { 126 | $this->params['markdown'] = $this->markdown; 127 | } elseif (!empty($this->image)) { 128 | $this->params['image'] = $this->image; 129 | } elseif (!empty($this->embed)) { 130 | $this->params['embed'] = $this->embed; 131 | } elseif (!empty($this->ark)) { 132 | $this->params['ark'] = $this->ark; 133 | } elseif (!empty($this->messageReference)) { 134 | $this->params['message_reference'] = $this->messageReference; 135 | } 136 | 137 | return $this; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/Message/ServerChanMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class ServerChanMessage extends Message 17 | { 18 | private string $desp = ''; // 通知内容 19 | private string $title = ''; // 通知标题 20 | 21 | public function __construct(string $desp = '', string $title = '') 22 | { 23 | $this->desp = $desp; 24 | $this->title = $title; 25 | } 26 | 27 | public function setDesp(string $desp): self 28 | { 29 | $this->desp = $desp; 30 | 31 | return $this; 32 | } 33 | 34 | public function getDesp(): string 35 | { 36 | return $this->desp; 37 | } 38 | 39 | public function setTitle(string $title): self 40 | { 41 | $this->title = $title; 42 | 43 | return $this; 44 | } 45 | 46 | public function getTitle(): string 47 | { 48 | return $this->title; 49 | } 50 | 51 | public function generateParams(): self 52 | { 53 | $this->params = [ 54 | 'title' => $this->title, 55 | 'desp' => $this->desp, 56 | ]; 57 | 58 | return $this; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Message/ShowdocMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class ShowdocMessage extends Message 17 | { 18 | private string $content = ''; // 通知内容 19 | private string $title = ''; // 通知标题 20 | 21 | public function __construct(string $content = '', string $title = '') 22 | { 23 | $this->content = $content; 24 | $this->title = $title; 25 | } 26 | 27 | public function setContent(string $content): self 28 | { 29 | $this->content = $content; 30 | 31 | return $this; 32 | } 33 | 34 | public function getContent(): string 35 | { 36 | return $this->content; 37 | } 38 | 39 | public function setTitle(string $title): self 40 | { 41 | $this->title = $title; 42 | 43 | return $this; 44 | } 45 | 46 | public function getTitle(): string 47 | { 48 | return $this->title; 49 | } 50 | 51 | public function generateParams(): self 52 | { 53 | $this->params = [ 54 | 'title' => $this->title, 55 | 'content' => $this->content, 56 | ]; 57 | 58 | return $this; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Message/TechulusMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class TechulusMessage extends Message 17 | { 18 | private string $body = ''; // 通知内容 19 | private string $title = ''; // 通知标题 20 | 21 | private string $link = ''; // 通知链接 22 | private string $image = ''; // 通知图片 23 | 24 | public function __construct(string $body = '', string $title = '') 25 | { 26 | $this->body = $body; 27 | $this->title = $title; 28 | } 29 | 30 | public function setBody(string $body): self 31 | { 32 | $this->body = $body; 33 | 34 | return $this; 35 | } 36 | 37 | public function getBody(): string 38 | { 39 | return $this->body; 40 | } 41 | 42 | public function setTitle(string $title): self 43 | { 44 | $this->title = $title; 45 | 46 | return $this; 47 | } 48 | 49 | public function getTitle(): string 50 | { 51 | return $this->title; 52 | } 53 | 54 | public function setLink(string $link): self 55 | { 56 | $this->link = $link; 57 | 58 | return $this; 59 | } 60 | 61 | public function getLink(): string 62 | { 63 | return $this->link; 64 | } 65 | 66 | public function setImage(string $image): self 67 | { 68 | $this->image = $image; 69 | 70 | return $this; 71 | } 72 | 73 | public function getImage(): string 74 | { 75 | return $this->image; 76 | } 77 | 78 | public function generateParams(): self 79 | { 80 | $this->params = [ 81 | 'title' => $this->title, 82 | 'body' => $this->body, 83 | 'link' => $this->link, 84 | 'image' => $this->image, 85 | ]; 86 | 87 | return $this; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Message/TelegramMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class TelegramMessage extends Message 17 | { 18 | private string $text = ''; // 通知内容 19 | private bool $sound = false; // 通知声音 20 | 21 | public function __construct(string $text = '') 22 | { 23 | $this->text = $text; 24 | } 25 | 26 | public function setText(string $text): self 27 | { 28 | $this->text = $text; 29 | 30 | return $this; 31 | } 32 | 33 | public function getText(): string 34 | { 35 | return $this->text; 36 | } 37 | 38 | public function setSound(bool $enable): self 39 | { 40 | $this->sound = $enable; 41 | 42 | return $this; 43 | } 44 | 45 | public function getSound(): bool 46 | { 47 | return $this->sound; 48 | } 49 | 50 | public function generateParams(): self 51 | { 52 | $this->params = [ 53 | 'text' => $this->text, 54 | 'disable_notification' => !$this->sound, 55 | ]; 56 | 57 | return $this; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Message/WeComMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class WeComMessage extends Message 17 | { 18 | public const TYPE_TEXT = 'text'; 19 | public const TYPE_MARKDOWN = 'markdown'; 20 | public const TYPE_IMAGE = 'image'; 21 | public const TYPE_NEWS = 'news'; 22 | 23 | private string $msgtype = ''; // 消息类型 text,markdown,image,news 24 | private string $content = ''; // 通知内容 25 | 26 | // text 类型 27 | private array $mentionedList = []; // userid 的列表,提醒群中的指定成员(@某个成员),@all表示提醒所有人 28 | private array $mentionedMobileList = []; // 手机号列表,提醒手机号对应的群成员(@某个成员),@all表示提醒所有人 29 | 30 | // image 类型 31 | private string $imageBase64 = ''; // 图片内容的 base64 编码(不可换行,不带图片识别头):base64 -w 0 pic.jpg > encode.log 32 | private string $imageMd5 = ''; // 图片内容(base64编码前)的md5值:md5sum pic.jpg 33 | 34 | // news 类型 35 | private array $articles = []; // 图文消息,一个图文消息支持1到8条图文 36 | 37 | public function __construct( 38 | string $msgtype = '', 39 | string $content = '', 40 | ) { 41 | $this->msgtype = $this->filter_message_type($msgtype); 42 | $this->content = $content; 43 | } 44 | 45 | public function setMsgType(string $msgtype): self 46 | { 47 | $this->msgtype = $this->filter_message_type($msgtype); 48 | 49 | return $this; 50 | } 51 | 52 | public function getMsgType(): string 53 | { 54 | return $this->msgtype; 55 | } 56 | 57 | public function setContent(string $content): self 58 | { 59 | $this->content = $content; 60 | 61 | return $this; 62 | } 63 | 64 | public function getContent(): string 65 | { 66 | return $this->content; 67 | } 68 | 69 | public function setMentionedList(array $list): self 70 | { 71 | $this->mentionedList = $list; 72 | 73 | return $this; 74 | } 75 | 76 | public function getMentionedList(): array 77 | { 78 | return $this->mentionedList; 79 | } 80 | 81 | public function setMentionedMobileList(array $list): self 82 | { 83 | $this->mentionedMobileList = $list; 84 | 85 | return $this; 86 | } 87 | 88 | public function getMetMentionedMobileList(): array 89 | { 90 | return $this->mentionedMobileList; 91 | } 92 | 93 | public function setImageBase64(string $base64): self 94 | { 95 | $this->imageBase64 = $base64; 96 | 97 | return $this; 98 | } 99 | 100 | public function getImageBase64(): string 101 | { 102 | return $this->imageBase64; 103 | } 104 | 105 | public function setImageMd5(string $md5): self 106 | { 107 | $this->imageMd5 = $md5; 108 | 109 | return $this; 110 | } 111 | 112 | public function getImageMd5(): string 113 | { 114 | return $this->imageMd5; 115 | } 116 | 117 | public function setArticles(array $articles): self 118 | { 119 | $this->articles = $articles; 120 | 121 | return $this; 122 | } 123 | 124 | public function getArticles(): array 125 | { 126 | return $this->articles; 127 | } 128 | 129 | public function addArticle(string $title, string $url, string $description = '', string $picurl = ''): self 130 | { 131 | $this->articles[] = [ 132 | 'title' => $title, 133 | 'url' => $url, 134 | 'description' => $description, 135 | 'picurl' => $picurl, 136 | ]; 137 | 138 | return $this; 139 | } 140 | 141 | public function generateParams(): self 142 | { 143 | $this->params = [ 144 | 'msgtype' => $this->msgtype, 145 | ]; 146 | 147 | $params = []; 148 | 149 | switch ($this->msgtype) { 150 | case 'markdown': 151 | $params = [ 152 | 'markdown' => [ 153 | 'content' => $this->content, 154 | ], 155 | ]; 156 | break; 157 | 158 | case 'image': 159 | $params = [ 160 | 'image' => [ 161 | 'base64' => $this->imageBase64, 162 | 'md5' => $this->imageMd5, 163 | ], 164 | ]; 165 | break; 166 | 167 | case 'news': 168 | $params = [ 169 | 'news' => [ 170 | 'articles' => $this->articles, 171 | ], 172 | ]; 173 | break; 174 | 175 | case 'text': 176 | default: 177 | $params = [ 178 | 'text' => [ 179 | 'content' => $this->content, 180 | 'mentioned_list' => $this->mentionedList, 181 | 'mentioned_mobile_list' => $this->mentionedMobileList, 182 | ], 183 | ]; 184 | } 185 | 186 | $this->params += $params; 187 | 188 | return $this; 189 | } 190 | 191 | private function filter_message_type(string $type): string 192 | { 193 | $type = strtolower($type); 194 | 195 | return in_array($type, [ self::TYPE_TEXT, self::TYPE_MARKDOWN, self::TYPE_IMAGE, self::TYPE_NEWS ]) ? $type : self::TYPE_TEXT; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/Message/WebhookMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class WebhookMessage extends Message 17 | { 18 | public function __construct(array $data = []) 19 | { 20 | $this->params = $data; 21 | } 22 | 23 | public function setParams(array $params): self 24 | { 25 | $this->params = $params; 26 | 27 | return $this; 28 | } 29 | 30 | public function getParams(): array 31 | { 32 | return $this->params; 33 | } 34 | 35 | public function generateParams(): self 36 | { 37 | return $this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Message/WxPusherMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class WxPusherMessage extends Message 17 | { 18 | private string $content = ''; // 通知内容 19 | 20 | private string $summary = ''; // 消息摘要 不传默认截取content前面的内容 21 | private int $contentType = 1; // 内容类型 1表示文字 2表示html(只发送body标签内部的数据即可,不包括body标签) 3表示markdown 22 | private array $topicIds = []; // 发送目标的topicId,是一个数组!!!,也就是群发,使用uids单发的时候, 可以不传。 23 | private array $uids = []; // 发送目标的UID,是一个数组。注意uids和topicIds可以同时填写,也可以只填写一个。 24 | private string $url = ''; // 原文链接,可选参数 25 | 26 | public function __construct(string $content = '') 27 | { 28 | $this->content = $content; 29 | } 30 | 31 | public function setContent(string $content): self 32 | { 33 | $this->content = $content; 34 | 35 | return $this; 36 | } 37 | 38 | public function getContent(): string 39 | { 40 | return $this->content; 41 | } 42 | 43 | public function setSummary(string $summary): self 44 | { 45 | $this->summary = $summary; 46 | 47 | return $this; 48 | } 49 | 50 | public function getSummary(): string 51 | { 52 | return $this->summary; 53 | } 54 | 55 | public function setContentType(int $contentType): self 56 | { 57 | $this->contentType = $contentType; 58 | 59 | return $this; 60 | } 61 | 62 | public function getContentType(): int 63 | { 64 | return $this->contentType; 65 | } 66 | 67 | public function setTopicIds(array $topicIds): self 68 | { 69 | $this->topicIds = $topicIds; 70 | 71 | return $this; 72 | } 73 | 74 | public function getTopicIds(): array 75 | { 76 | return $this->topicIds; 77 | } 78 | 79 | public function setUids(array $uids): self 80 | { 81 | $this->uids = $uids; 82 | 83 | return $this; 84 | } 85 | 86 | public function getUids(): array 87 | { 88 | return $this->uids; 89 | } 90 | 91 | public function setURL(string $url): self 92 | { 93 | $this->url = $url; 94 | 95 | return $this; 96 | } 97 | 98 | public function getURL(): string 99 | { 100 | return $this->url; 101 | } 102 | 103 | public function generateParams(): self 104 | { 105 | $this->params = [ 106 | 'content' => $this->content, 107 | 'summary' => $this->summary, 108 | 'contentType' => $this->contentType, 109 | 'topicIds' => $this->topicIds, 110 | 'uids' => $this->uids, 111 | 'url' => $this->url, 112 | ]; 113 | 114 | return $this; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Message/XizhiMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class XizhiMessage extends Message 17 | { 18 | private string $content = ''; // 通知内容 19 | private string $title = ''; // 通知标题 20 | 21 | public function __construct(string $content = '', string $title = '') 22 | { 23 | $this->content = $content; 24 | $this->title = $title; 25 | } 26 | 27 | public function setContent(string $content): self 28 | { 29 | $this->content = $content; 30 | 31 | return $this; 32 | } 33 | 34 | public function getContent(): string 35 | { 36 | return $this->content; 37 | } 38 | 39 | public function setTitle(string $title): self 40 | { 41 | $this->title = $title; 42 | 43 | return $this; 44 | } 45 | 46 | public function getTitle(): string 47 | { 48 | return $this->title; 49 | } 50 | 51 | public function generateParams(): self 52 | { 53 | $this->params = [ 54 | 'title' => $this->title, 55 | 'content' => $this->content, 56 | ]; 57 | 58 | return $this; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Message/ZulipMessage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher\Message; 13 | 14 | use Pusher\Message; 15 | 16 | class ZulipMessage extends Message 17 | { 18 | public const TYPE_PRIVATE = 'private'; // 私人 19 | public const TYPE_STREAM = 'stream'; // 流 20 | 21 | private string $type = ''; // 通知类型 ['private', 'stream'] 22 | private string|int $to = ''; // 对于流消息,流的名称或整数ID。对于私人消息,包含包含整数用户ID的列表或包含字符串电子邮件地址的列表。 23 | private string $content = ''; // 消息内容 24 | private string $topic = ''; // 主题 25 | 26 | public function __construct(string $type = '', string $content = '') 27 | { 28 | $this->type = $this->filter_message_type($type); 29 | $this->content = $content; 30 | } 31 | 32 | public function setType(string $type): self 33 | { 34 | $this->type = $this->filter_message_type($type); 35 | 36 | return $this; 37 | } 38 | 39 | public function getType(): string 40 | { 41 | return $this->type; 42 | } 43 | 44 | public function setTo(string|int $to): self 45 | { 46 | $this->to = $to; 47 | 48 | return $this; 49 | } 50 | 51 | public function getTo(): string|int 52 | { 53 | return $this->to; 54 | } 55 | 56 | public function setContent(string $content): self 57 | { 58 | $this->content = $content; 59 | 60 | return $this; 61 | } 62 | 63 | public function getContent(): string 64 | { 65 | return $this->content; 66 | } 67 | 68 | public function setTopic(string $topic): self 69 | { 70 | $this->topic = $topic; 71 | 72 | return $this; 73 | } 74 | 75 | public function getTopic(): string 76 | { 77 | return $this->topic; 78 | } 79 | 80 | public function generateParams(): self 81 | { 82 | $this->params = [ 83 | 'type' => $this->type, 84 | 'to' => $this->to, 85 | 'content' => $this->content, 86 | ]; 87 | 88 | if ($this->type === self::TYPE_STREAM) { 89 | $this->params['topic'] = $this->topic; 90 | } 91 | 92 | return $this; 93 | } 94 | 95 | private function filter_message_type(string $type): string 96 | { 97 | $type = strtolower($type); 98 | 99 | return in_array($type, [ self::TYPE_PRIVATE, self::TYPE_STREAM ]) ? $type : self::TYPE_PRIVATE; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/MessageInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher; 13 | 14 | interface MessageInterface 15 | { 16 | public function Data(array $data): self; 17 | 18 | public function generateParams(): self; 19 | 20 | public function getParams(): array; 21 | } 22 | -------------------------------------------------------------------------------- /src/Pusher.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher; 13 | 14 | class Pusher 15 | { 16 | public const METHOD_GET = 'GET'; 17 | public const METHOD_POST = 'POST'; 18 | public const METHOD_JSON = 'JSON'; 19 | } 20 | -------------------------------------------------------------------------------- /src/Utils.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Pusher; 13 | 14 | class Utils 15 | { 16 | /** 17 | * 钉钉 签名 18 | */ 19 | public static function generateSign(string $secret, int $timestamp): string 20 | { 21 | $stringToSign = sprintf("%s\n%s", $timestamp, $secret); 22 | $signData = hash_hmac('sha256', $stringToSign, $secret, true); 23 | 24 | return urlencode(base64_encode($signData)); 25 | } 26 | 27 | /** 28 | * 飞书 Lark 签名 29 | */ 30 | public static function generateSign2(string $secret, int $timestamp): string 31 | { 32 | $stringToSign = sprintf("%s\n%s", $timestamp, $secret); 33 | $signData = hash_hmac('sha256', '', $stringToSign, true); 34 | 35 | return base64_encode($signData); 36 | } 37 | 38 | public static function strToArray(string $message): array 39 | { 40 | return json_decode($message, true); 41 | } 42 | 43 | public static function xmlToArray(string $message): array 44 | { 45 | $xmlObj = simplexml_load_string($message); 46 | 47 | return json_decode(json_encode($xmlObj), true); 48 | } 49 | } 50 | --------------------------------------------------------------------------------