فهرست منبع

支持通过 Bark 送信

luolongfei 4 سال پیش
والد
کامیت
c6afa5a66b
5فایلهای تغییر یافته به همراه329 افزوده شده و 1 حذف شده
  1. 18 0
      .env.example
  2. 27 0
      config.php
  3. 3 1
      libs/Message.php
  4. 279 0
      libs/MessageServices/Bark.php
  5. 2 0
      libs/MessageServices/ServerChan.php

+ 18 - 0
.env.example

@@ -90,6 +90,24 @@ SCT_SEND_KEY=''
 SCT_ENABLE=0
 ######################  end Server 酱  #########################
 
+######################  Bark 送信  #########################
+# Bark key 打开 Bark App,注册设备后看到的 key Open the Bark App, register the device and see the key
+BARK_KEY=''
+
+# Bark 域名 默认是 Bark 作者提供的服务,建议自建 The Bark URL defaults to the server provided by the Bark author, and it is recommended to build your own
+BARK_URL='https://api.day.app'
+
+# Bark 其它相关参数(保持默认即可)
+BARK_IS_ARCHIVE=''
+BARK_GROUP='FreeNom'
+BARK_LEVEL='active'
+BARK_ICON=''
+BARK_JUMP_URL=''
+
+# 是否启用 Bark 推送消息 1:启用 0:不启用 Whether to enable Bark push messaging 1: Enable 0: Do not enable
+BARK_ENABLE=0
+######################  end Bark 送信  #########################
+
 # 通知频率 0:仅当有续期操作的时候 1:每次执行 Notification frequency 0: Only when there is a renewal operation 1: Each execution
 NOTICE_FREQ=1
 

+ 27 - 0
config.php

@@ -23,6 +23,8 @@ return [
             'password' => env('MAIL_PASSWORD'), // 机器人邮箱密码或授权码
             'enable' => (int)env('MAIL_ENABLE'), // 是否启用,默认启用
 
+            'not_enabled_tips' => env('MAIL_USERNAME') && env('MAIL_PASSWORD'), // 提醒未启用
+
             // 'reply_to' => '[email protected]', // 接收回复的邮箱
             // 'reply_to_name' => '作者', // 接收回复的人名
 
@@ -42,6 +44,8 @@ return [
             'token' => env('TELEGRAM_BOT_TOKEN'), // Telegram Bot 的 token
             'enable' => (int)env('TELEGRAM_BOT_ENABLE'), // 是否启用,默认不启用
 
+            'not_enabled_tips' => env('TELEGRAM_CHAT_ID') && env('TELEGRAM_BOT_TOKEN'), // 提醒未启用
+
             'class' => \Luolongfei\Libs\MessageServices\TelegramBot::class,
             'name' => 'Telegram Bot',
 
@@ -57,6 +61,8 @@ return [
             'agent_id' => (int)env('WECHAT_AGENT_ID'), // 企业微信应用 ID
             'enable' => (int)env('WECHAT_ENABLE'), // 是否启用,默认不启用
 
+            'not_enabled_tips' => env('WECHAT_CORP_ID') && env('WECHAT_CORP_SECRET') && env('WECHAT_AGENT_ID'), // 提醒未启用
+
             'class' => \Luolongfei\Libs\MessageServices\WeChat::class,
             'name' => '企业微信',
         ],
@@ -68,9 +74,30 @@ return [
             'sct_send_key' => env('SCT_SEND_KEY'), // SendKey
             'enable' => (int)env('SCT_ENABLE'), // 是否启用,默认不启用
 
+            'not_enabled_tips' => (bool)env('SCT_SEND_KEY'), // 提醒未启用
+
             'class' => \Luolongfei\Libs\MessageServices\ServerChan::class,
             'name' => 'Server 酱',
         ],
+
+        /**
+         * Bark 送信
+         */
+        'bark' => [
+            'bark_key' => env('BARK_KEY'), // 打开 Bark App,注册设备后看到的 Key
+            'bark_url' => (string)env('BARK_URL'), // Bark 域名
+            'bark_is_archive' => env('BARK_IS_ARCHIVE') === '' ? null : (int)env('BARK_IS_ARCHIVE'),
+            'bark_group' => env('BARK_GROUP') === '' ? null : env('BARK_GROUP'),
+            'bark_level' => env('BARK_LEVEL'),
+            'bark_icon' => env('BARK_ICON') === '' ? null : env('BARK_ICON'),
+            'bark_jump_url' => env('BARK_JUMP_URL') === '' ? null : env('BARK_JUMP_URL'),
+            'enable' => (int)env('BARK_ENABLE'), // 是否启用,默认不启用
+
+            'not_enabled_tips' => env('BARK_KEY') && env('BARK_URL'), // 提醒未启用
+
+            'class' => \Luolongfei\Libs\MessageServices\Bark::class,
+            'name' => 'Bark',
+        ],
     ],
 
     'locale' => 'zh', // 指定语言包,位于resources/lang/目录下

+ 3 - 1
libs/Message.php

@@ -26,7 +26,9 @@ abstract class Message extends Base
     {
         foreach (config('message') as $conf) {
             if ($conf['enable'] !== 1) {
-                system_log(sprintf('由于没有启用「%s」功能,故本次不通过「%s」送信。', $conf['name'], $conf['name']));
+                if ($conf['not_enabled_tips']) { // 仅在存在配置的送信项未启用的情况下提醒
+                    system_log(sprintf('由于没有启用「%s」功能,故本次不通过「%s」送信,尽管检测到相关配置。', $conf['name'], $conf['name']));
+                }
 
                 continue;
             }

+ 279 - 0
libs/MessageServices/Bark.php

@@ -0,0 +1,279 @@
+<?php
+/**
+ * Bark 推送
+ *
+ * @author mybsdc <[email protected]>
+ * @date 2021/11/3
+ * @time 11:18
+ */
+
+namespace Luolongfei\Libs\MessageServices;
+
+use GuzzleHttp\Client;
+use Luolongfei\Libs\Connector\MessageGateway;
+
+class Bark extends MessageGateway
+{
+    const TIMEOUT = 33;
+
+    /**
+     * @var string Bark Key
+     */
+    protected $barkKey;
+
+    /**
+     * @var string Bark 域名
+     */
+    protected $barkUrl;
+
+    /**
+     * @var integer|string 指定是否需要保存推送信息到历史记录,1 为保存,其他值为不保存。如果值为空字符串,则推送信息将按照 APP 内设置来决定是否保存
+     */
+    protected $isArchive;
+
+    /**
+     * @var string 指定推送消息分组,可在历史记录中按分组查看推送
+     */
+    protected $group;
+
+    /**
+     * 可选参数值
+     * active:不设置时的默认值,系统会立即亮屏显示通知
+     * timeSensitive:时效性通知,可在专注状态下显示通知
+     * passive:仅将通知添加到通知列表,不会亮屏提醒
+     *
+     * @var string 时效性通知
+     */
+    protected $level;
+
+    /**
+     * @var string 指定推送消息图标 (仅 iOS15 或以上支持)http://day.app/assets/images/avatar.jpg
+     */
+    protected $icon;
+
+    /**
+     * @var string 点击推送将跳转到url的地址(发送时,URL参数需要编码),GuzzleHttp 库会自动编码
+     */
+    protected $jumpUrl;
+
+    /**
+     * @var integer 携带参数 automaticallyCopy=1, 收到推送时,推送内容会自动复制到粘贴板(如发现不能自动复制,可尝试重启一下手机)
+     */
+    protected $automaticallyCopy = 1;
+
+    /**
+     * @var string 携带 copy 参数, 则上面两种复制操作,将只复制 copy 参数的值
+     */
+    protected $copy = 'https://my.freenom.com/domains.php?a=renewals';
+
+    /**
+     * @var Client
+     */
+    protected $client;
+
+    public function __construct()
+    {
+        $this->barkKey = config('message.bark.bark_key');
+        $this->barkUrl = rtrim(config('message.bark.bark_url'), '/');
+
+        $this->isArchive = config('message.bark.bark_is_archive');
+        $this->group = config('message.bark.bark_group');
+        $this->level = config('message.bark.bark_level');
+        $this->icon = config('message.bark.bark_icon');
+        $this->jumpUrl = config('message.bark.bark_jump_url');
+
+        $this->client = new Client([
+            'cookies' => false,
+            'timeout' => self::TIMEOUT,
+            'verify' => config('verify_ssl'),
+            'debug' => config('debug'),
+        ]);
+    }
+
+    /**
+     * 生成域名文本
+     *
+     * @param array $domains
+     *
+     * @return string
+     */
+    public function genDomainsText(array $domains)
+    {
+        $domainsText = '';
+
+        foreach ($domains as $domain) {
+            $domainsText .= sprintf('%s ', $domain);
+        }
+
+        $domainsText = trim($domainsText, ' ') . "\n";
+
+        return $domainsText;
+    }
+
+    /**
+     * 获取页脚
+     *
+     * @return string
+     */
+    public function getFooter()
+    {
+        $footer = '';
+
+        $footer .= "\n更多信息可以参考:https://my.freenom.com/domains.php?a=renewals(点击“复制内容”即可复制此网址)";
+        $footer .= "\n\n(如果你不想每次执行都收到推送,请将 .env 中 NOTICE_FREQ 的值设为 0,使程序只在有续期操作时才推送)";
+
+        return $footer;
+    }
+
+    /**
+     * 生成域名状态文本
+     *
+     * @param array $domainStatus
+     *
+     * @return string
+     */
+    public function genDomainStatusText(array $domainStatus)
+    {
+        if (empty($domainStatus)) {
+            return "无数据。\n";
+        }
+
+        $domainStatusText = '';
+
+        foreach ($domainStatus as $domain => $daysLeft) {
+            $domainStatusText .= sprintf('%s 还有 %d 天到期,', $domain, $daysLeft);
+        }
+
+        $domainStatusText = rtrim($domainStatusText, ',') . "。\n";
+
+        return $domainStatusText;
+    }
+
+    /**
+     * 生成域名续期结果文本
+     *
+     * @param string $username
+     * @param array $renewalSuccessArr
+     * @param array $renewalFailuresArr
+     * @param array $domainStatus
+     *
+     * @return string
+     */
+    public function genDomainRenewalResultsText(string $username, array $renewalSuccessArr, array $renewalFailuresArr, array $domainStatus)
+    {
+        $text = sprintf("账户 %s 这次续期的结果如下\n\n", $username);
+
+        if ($renewalSuccessArr) {
+            $text .= '续期成功:';
+            $text .= $this->genDomainsText($renewalSuccessArr);
+        }
+
+        if ($renewalFailuresArr) {
+            $text .= '续期出错:';
+            $text .= $this->genDomainsText($renewalFailuresArr);
+        }
+
+        $text .= "\n今次无需续期的域名及其剩余天数如下所示:\n\n";
+        $text .= $this->genDomainStatusText($domainStatus);
+
+        $text .= $this->getFooter();
+
+        return $text;
+    }
+
+    /**
+     * 生成域名状态完整文本
+     *
+     * @param string $username
+     * @param array $domainStatus
+     *
+     * @return string
+     */
+    public function genDomainStatusFullText(string $username, array $domainStatus)
+    {
+        $markDownText = sprintf("我刚刚帮小主看了一下,账户 %s 今天并没有需要续期的域名。所有域名情况如下:\n\n", $username);
+
+        $markDownText .= $this->genDomainStatusText($domainStatus);
+
+        $markDownText .= $this->getFooter();
+
+        return $markDownText;
+    }
+
+    /**
+     * 送信
+     *
+     * @param string $content
+     * @param string $subject
+     * @param int $type
+     * @param array $data
+     * @param string|null $recipient
+     * @param mixed ...$params
+     *
+     * @return bool|mixed
+     * @throws \Exception
+     */
+    public function send(string $content, string $subject = '', int $type = 1, array $data = [], ?string $recipient = null, ...$params)
+    {
+        $this->check($content, $data);
+
+        if ($type === 1) {
+            // Do nothing
+        } else if ($type === 2) {
+            $content = $this->genDomainRenewalResultsText($data['username'], $data['renewalSuccessArr'], $data['renewalFailuresArr'], $data['domainStatusArr']);
+        } else if ($type === 3) {
+            $content = $this->genDomainStatusFullText($data['username'], $data['domainStatusArr']);
+        } else {
+            throw new \Exception(lang('error_msg.100003'));
+        }
+
+        $query = [
+            'level' => $this->level,
+            'automaticallyCopy' => $this->automaticallyCopy, // 携带参数 automaticallyCopy=1, 收到推送时,推送内容会自动复制到粘贴板(如发现不能自动复制,可尝试重启一下手机)
+            'copy' => $this->copy, // 携带 copy 参数,则上面的复制操作,将只复制 copy 参数的值
+        ];
+
+        if ($this->isArchive !== null) {
+            $query['isArchive'] = $this->isArchive;
+        }
+        if ($this->group !== null) {
+            $query['group'] = $this->group;
+        }
+        if ($this->icon !== null) {
+            $query['icon'] = $this->icon;
+        }
+        if ($this->jumpUrl !== null) {
+            $query['url'] = $this->jumpUrl;
+        }
+
+        $formParams = [
+            'body' => $content, // 推送内容 换行请使用换行符 \n
+        ];
+
+        if ($subject !== '') {
+            $formParams['title'] = $subject; // 推送标题 比 body 字号粗一点
+        }
+
+        try {
+            $resp = $this->client->post(
+                sprintf('%s/%s/', $this->barkUrl, $this->barkKey),
+                [
+                    'query' => $query,
+                    'form_params' => $formParams,
+                ]
+            );
+
+            $resp = json_decode($resp->getBody()->getContents(), true);
+
+            if (isset($resp['code']) && $resp['code'] === 200) {
+                return true;
+            }
+
+            throw new \Exception($resp['message'] ?? '未知原因');
+        } catch (\Exception $e) {
+            system_log('Bark 送信失败:<red>' . $e->getMessage() . '</red>');
+
+            return false;
+        }
+    }
+}

+ 2 - 0
libs/MessageServices/ServerChan.php

@@ -175,6 +175,8 @@ class ServerChan extends MessageGateway
             throw new \Exception(lang('error_msg.100003'));
         }
 
+        $subject = $subject === '' ? mb_substr($content, 0, 12) . '...' : $subject;
+
         try {
             $resp = $this->client->post(
                 sprintf('https://sctapi.ftqq.com/%s.send', $this->sendKey),