From 8201318bd7dd007d948943ca66ee4031edc07ac9 Mon Sep 17 00:00:00 2001 From: net909 Date: Wed, 25 Dec 2024 20:08:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81MW=E9=9D=A2=E6=9D=BF=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=EF=BC=8C=E5=A2=9E=E5=8A=A0=E7=BE=A4=E6=9C=BA=E5=99=A8?= =?UTF-8?q?=E4=BA=BAwebhook=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common.php | 1 + app/controller/System.php | 14 ++++ app/lib/DeployHelper.php | 57 ++++++++++++++ app/lib/deploy/lecdn.php | 6 +- app/lib/deploy/mwpanel.php | 127 +++++++++++++++++++++++++++++++ app/service/CertTaskService.php | 8 +- app/utils/MsgNotice.php | 109 ++++++++++++++++++-------- app/view/cert/certset.html | 4 + app/view/dmonitor/overview.html | 4 + app/view/system/noticeset.html | 42 +++++++++- public/static/images/mwpanel.ico | Bin 0 -> 9662 bytes route/app.php | 1 + 12 files changed, 332 insertions(+), 41 deletions(-) create mode 100644 app/lib/deploy/mwpanel.php create mode 100644 public/static/images/mwpanel.ico diff --git a/app/common.php b/app/common.php index eec1643..f334612 100644 --- a/app/common.php +++ b/app/common.php @@ -7,6 +7,7 @@ function get_curl($url, $post = 0, $referer = 0, $cookie = 0, $header = 0, $ua = { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $httpheader[] = "Accept: */*"; diff --git a/app/controller/System.php b/app/controller/System.php index 9411a14..f5d126e 100644 --- a/app/controller/System.php +++ b/app/controller/System.php @@ -76,6 +76,20 @@ class System extends BaseController } } + public function webhooktest() + { + if (!checkPermission(2)) return $this->alert('error', '无权限'); + $webhook_url = config_get('webhook_url'); + if (empty($webhook_url)) return json(['code' => -1, 'msg' => '请先保存设置']); + $content = "这是一封测试消息!\n来自:" . $this->request->root(true); + $result = \app\utils\MsgNotice::send_webhook('消息发送测试', $content); + if ($result === true) { + return json(['code' => 0, 'msg' => '消息发送成功!']); + } else { + return json(['code' => -1, 'msg' => '消息发送失败!' . $result]); + } + } + public function proxytest() { if (!checkPermission(2)) return $this->alert('error', '无权限'); diff --git a/app/lib/DeployHelper.php b/app/lib/DeployHelper.php index 72e4cd2..b81c697 100644 --- a/app/lib/DeployHelper.php +++ b/app/lib/DeployHelper.php @@ -342,6 +342,63 @@ class DeployHelper ], 'taskinputs' => [], ], + 'mwpanel' => [ + 'name' => 'mdserver-web', + 'class' => 1, + 'icon' => 'mwpanel.ico', + 'note' => null, + 'tasknote' => '', + 'inputs' => [ + 'url' => [ + 'name' => '面板地址', + 'type' => 'input', + 'placeholder' => 'MW面板地址', + 'note' => '填写规则如:http://192.168.1.100:8888 ,不要带其他后缀', + 'required' => true, + ], + 'appid' => [ + 'name' => '应用ID', + 'type' => 'input', + 'placeholder' => 'MW面板设置->API接口', + 'required' => true, + ], + 'appsecret' => [ + 'name' => '应用密钥', + 'type' => 'input', + 'placeholder' => '面板设置->API接口', + 'required' => true, + ], + 'proxy' => [ + 'name' => '使用代理服务器', + 'type' => 'radio', + 'options' => [ + '0' => '否', + '1' => '是', + ], + 'value' => '0' + ], + ], + 'taskinputs' => [ + 'type' => [ + 'name' => '部署类型', + 'type' => 'radio', + 'options' => [ + '0' => 'MW面板站点的证书', + '1' => 'MW面板本身的证书', + ], + 'value' => '0', + 'required' => true, + ], + 'sites' => [ + 'name' => '网站名称列表', + 'type' => 'textarea', + 'placeholder' => '填写要部署证书的网站名称,每行一个', + 'note' => '网站名称,即为网站创建时绑定的第一个域名', + 'show' => 'type==0', + 'required' => true, + ], + ], + ], 'aliyun' => [ 'name' => '阿里云', 'class' => 2, diff --git a/app/lib/deploy/lecdn.php b/app/lib/deploy/lecdn.php index 2e64c99..83b545b 100644 --- a/app/lib/deploy/lecdn.php +++ b/app/lib/deploy/lecdn.php @@ -62,8 +62,8 @@ class lecdn implements DeployInterface 'password' => $this->password, ]; $result = $this->request($path, $params); - if (isset($result['access_token'])) { - $this->accessToken = $result['access_token']; + if (isset($result['token'])) { + $this->accessToken = $result['token']; } else { throw new Exception('登录成功,获取access_token失败'); } @@ -83,7 +83,7 @@ class lecdn implements DeployInterface } $response = curl_client($url, $body, null, null, $headers, $this->proxy, $method); $result = json_decode($response['body'], true); - if (isset($result['code']) && $result['code'] == 0) { + if (isset($result['code']) && $result['code'] == 200) { return isset($result['data']) ? $result['data'] : null; } elseif (isset($result['message'])) { throw new Exception($result['message']); diff --git a/app/lib/deploy/mwpanel.php b/app/lib/deploy/mwpanel.php new file mode 100644 index 0000000..f3fdc6a --- /dev/null +++ b/app/lib/deploy/mwpanel.php @@ -0,0 +1,127 @@ +url = rtrim($config['url'], '/'); + $this->appid = $config['appid']; + $this->appsecret = $config['appsecret']; + $this->proxy = $config['proxy'] == 1; + } + + public function check() + { + if (empty($this->url) || empty($this->appid) || empty($this->appsecret)) throw new Exception('请填写面板地址和接口密钥'); + + $path = '/task/count'; + $response = $this->request($path); + $result = json_decode($response, true); + if (isset($result['status']) && $result['status'] == true) { + return true; + } else { + throw new Exception(isset($result['msg']) ? $result['msg'] : '面板地址无法连接'); + } + } + + public function deploy($fullchain, $privatekey, $config, &$info) + { + if ($config['type'] == '1') { + $this->deployPanel($fullchain, $privatekey); + $this->log("面板证书部署成功"); + return; + } + $sites = explode("\n", $config['sites']); + $success = 0; + $errmsg = null; + foreach ($sites as $site) { + $siteName = trim($site); + if (empty($siteName)) continue; + try { + $this->deploySite($siteName, $fullchain, $privatekey); + $this->log("网站 {$siteName} 证书部署成功"); + $success++; + } catch (Exception $e) { + $errmsg = $e->getMessage(); + $this->log("网站 {$siteName} 证书部署失败:" . $errmsg); + } + } + if ($success == 0) { + throw new Exception($errmsg ? $errmsg : '要部署的网站不存在'); + } + } + + private function deployPanel($fullchain, $privatekey) + { + $path = '/setting/save_panel_ssl'; + $data = [ + 'privateKey' => $privatekey, + 'certPem' => $fullchain, + 'choose' => 'local', + ]; + $response = $this->request($path, $data); + $result = json_decode($response, true); + if (isset($result['status']) && $result['status']) { + return true; + } elseif (isset($result['msg'])) { + throw new Exception($result['msg']); + } else { + throw new Exception($response ? $response : '返回数据解析失败'); + } + } + + private function deploySite($siteName, $fullchain, $privatekey) + { + $path = '/site/set_ssl'; + $data = [ + 'type' => '1', + 'siteName' => $siteName, + 'key' => $privatekey, + 'csr' => $fullchain, + ]; + $response = $this->request($path, $data); + $result = json_decode($response, true); + if (isset($result['status']) && $result['status']) { + return true; + } elseif (isset($result['msg'])) { + throw new Exception($result['msg']); + } else { + throw new Exception($response ? $response : '返回数据解析失败'); + } + } + + public function setLogger($func) + { + $this->logger = $func; + } + + private function log($txt) + { + if ($this->logger) { + call_user_func($this->logger, $txt); + } + } + + private function request($path, $params = null) + { + $url = $this->url . $path; + + $headers = [ + 'app-id: '.$this->appid, + 'app-secret: '.$this->appsecret, + ]; + $response = curl_client($url, $params ? http_build_query($params) : null, null, null, $headers, $this->proxy); + return $response['body']; + } +} diff --git a/app/service/CertTaskService.php b/app/service/CertTaskService.php index c953ce8..64f38ce 100644 --- a/app/service/CertTaskService.php +++ b/app/service/CertTaskService.php @@ -31,7 +31,7 @@ class CertTaskService $retcode = $service->process(); if ($retcode == 3) { echo 'ID:'.$row['id'].' 证书已签发成功!'.PHP_EOL; - if($row['issend'] == 0) MsgNotice::cert_send($row['id'], true); + if($row['issend'] == 0) MsgNotice::cert_order_send($row['id'], true); } elseif ($retcode == 1) { echo 'ID:'.$row['id'].' 添加DNS记录成功!'.PHP_EOL; } @@ -41,7 +41,7 @@ class CertTaskService if ($e->getCode() == 102) { break; } elseif ($e->getCode() == 103) { - if($row['issend'] == 0) MsgNotice::cert_send($row['id'], false); + if($row['issend'] == 0) MsgNotice::cert_order_send($row['id'], false); } else { $failcount++; } @@ -74,14 +74,14 @@ class CertTaskService $service = new CertDeployService($row['id']); $service->process(); echo 'ID:'.$row['id'].' 部署任务执行成功!'.PHP_EOL; - if($row['issend'] == 0) MsgNotice::deploy_send($row['id'], true); + if($row['issend'] == 0) MsgNotice::cert_deploy_send($row['id'], true); $count++; } catch (Exception $e) { echo 'ID:'.$row['id'].' '.$e->getMessage().PHP_EOL; if ($e->getCode() == 102) { break; } elseif ($e->getCode() == 103) { - if($row['issend'] == 0) MsgNotice::deploy_send($row['id'], false); + if($row['issend'] == 0) MsgNotice::cert_deploy_send($row['id'], false); } else { $count++; } diff --git a/app/utils/MsgNotice.php b/app/utils/MsgNotice.php index 5fb8e6c..9c1fd66 100644 --- a/app/utils/MsgNotice.php +++ b/app/utils/MsgNotice.php @@ -13,7 +13,7 @@ class MsgNotice { if ($action == 1) { $mail_title = 'DNS容灾切换-发生告警通知'; - $mail_content = '尊敬的系统管理员,您好:
您的域名 '.$task['domain'].''.$task['main_value'].' 记录发生了异常'; + $mail_content = '尊敬的用户,您好:
您的域名 '.$task['domain'].''.$task['main_value'].' 记录发生了异常'; if ($task['type'] == 2) { $mail_content .= ',已自动切换为备用解析记录 '.$task['backup_value'].' '; } elseif ($task['type'] == 1) { @@ -22,11 +22,11 @@ class MsgNotice $mail_content .= ',请及时处理'; } if (!empty($result['errmsg'])) { - $mail_content .= '。
异常信息:'.$result['errmsg']; + $mail_content .= '。
异常信息:'.$result['errmsg'].''; } } else { $mail_title = 'DNS容灾切换-恢复正常通知'; - $mail_content = '尊敬的系统管理员,您好:
您的域名 '.$task['domain'].''.$task['main_value'].' 记录已恢复正常'; + $mail_content = '尊敬的用户,您好:
您的域名 '.$task['domain'].''.$task['main_value'].' 记录已恢复正常'; if ($task['type'] == 2) { $mail_content .= ',已自动切换回当前解析记录'; } elseif ($task['type'] == 1) { @@ -41,7 +41,7 @@ class MsgNotice if (!empty($task['remark'])) { $mail_content .= '
备注:'.$task['remark']; } - $mail_content .= '
'.self::$sitename.'
'.date('Y-m-d H:i:s'); + $mail_content .= '
'.self::$sitename.'
'.date('Y-m-d H:i:s').''; if (config_get('notice_mail') == 1) { $mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name'); @@ -49,16 +49,20 @@ class MsgNotice } if (config_get('notice_wxtpl') == 1) { $content = str_replace(['
', '', ''], ["\n\n", '**', '**'], $mail_content); - self::send_wechat_tplmsg($mail_title, $content); + self::send_wechat_tplmsg($mail_title, strip_tags($content)); } if (config_get('notice_tgbot') == 1) { $content = str_replace('
', "\n", $mail_content); - $content = "".$mail_title."\n".$content; + $content = "".$mail_title."\n".strip_tags($content); self::send_telegram_bot($content); } + if (config_get('notice_webhook') == 1) { + $content = str_replace(['
', '', ''], ["\n", '**', '**'], $mail_content); + self::send_webhook($mail_title, $content); + } } - public static function cert_send($id, $result) + public static function cert_order_send($id, $result) { $row = Db::name('cert_order')->field('id,aid,issuetime,expiretime,issuer,status,error')->where('id', $id)->find(); if (!$row) return; @@ -71,7 +75,7 @@ class MsgNotice } else { $mail_title = $domainList[0] . '域名SSL证书签发成功通知'; } - $mail_content = '尊敬的用户,您好:您的SSL证书已签发成功!
证书账户:'.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')
证书域名:'.implode('、', $domainList).'
签发时间:'.$row['issuetime'].'
到期时间:'.$row['expiretime'].'
颁发机构:'.$row['issuer']; + $mail_content = '尊敬的用户,您好:您的SSL证书已签发成功!
证书账户: '.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')
证书域名: '.implode('、', $domainList).'
签发时间: '.$row['issuetime'].'
到期时间: '.$row['expiretime'].'
颁发机构: '.$row['issuer']; } else { $status_arr = [0 => '失败', -1 => '购买证书失败', -2 => '创建订单失败', -3 => '添加DNS失败', -4 => '验证DNS失败', -5 => '验证订单失败', -6 => '订单验证未通过', -7 => '签发证书失败']; if(count($domainList) > 1){ @@ -79,27 +83,15 @@ class MsgNotice }else{ $mail_title = $domainList[0].'域名SSL证书'.$status_arr[$row['status']].'通知'; } - $mail_content = '尊敬的用户,您好:您的SSL证书'.$status_arr[$row['status']].'!
证书账户:'.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')
证书域名:'.implode('、', $domainList).'
失败时间:'.date('Y-m-d H:i:s').'
失败原因:'.$row['error']; + $mail_content = '尊敬的用户,您好:您的SSL证书'.$status_arr[$row['status']].'!
证书账户: '.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')
证书域名: '.implode('、', $domainList).'
失败时间: '.date('Y-m-d H:i:s').'
失败原因: '.$row['error'].''; } - $mail_content .= '
'.self::$sitename.'
'.date('Y-m-d H:i:s'); + $mail_content .= '
'.self::$sitename.'
'.date('Y-m-d H:i:s').''; - if (config_get('cert_notice_mail') == 1 || config_get('cert_notice_mail') == 2 && !$result) { - $mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name'); - self::send_mail($mail_name, $mail_title, $mail_content); - } - if (config_get('cert_notice_wxtpl') == 1 || config_get('cert_notice_wxtpl') == 2 && !$result) { - $content = str_replace(['
', '', ''], ["\n\n", '**', '**'], $mail_content); - self::send_wechat_tplmsg($mail_title, $content); - } - if (config_get('cert_notice_tgbot') == 1 || config_get('cert_notice_tgbot') == 2 && !$result) { - $content = str_replace('
', "\n", $mail_content); - $content = "" . $mail_title . "\n" . $content; - self::send_telegram_bot($content); - } + self::cert_send($mail_title, $mail_content, $result); Db::name('cert_order')->where('id', $id)->update(['issend' => 1]); } - public static function deploy_send($id, $result) + public static function cert_deploy_send($id, $result) { $row = Db::name('cert_deploy')->field('id,aid,oid,remark,status,error')->where('id', $id)->find(); if (!$row) return; @@ -108,28 +100,37 @@ class MsgNotice $typename = DeployHelper::$deploy_config[$account['type']]['name']; $mail_title = $typename; if(!empty($row['remark'])) $mail_title .= '('.$row['remark'].')'; - $mail_title .= '证书部署'.($result?'成功':'失败').'通知'; + $mail_title .= 'SSL证书部署'.($result?'成功':'失败').'通知'; if ($result) { - $mail_content = '尊敬的用户,您好:您的SSL证书已成功部署到'.$typename.'!
自动部署账户:['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')
关联SSL证书:['.$row['oid'].']'.implode('、', $domainList).'
任务备注:'.($row['remark']?$row['remark']:'无'); + $mail_content = '尊敬的用户,您好:您的SSL证书已成功部署到'.$typename.'!
自动部署账户: ['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')
关联SSL证书: ['.$row['oid'].']'.implode('、', $domainList).'
任务备注: '.($row['remark']?$row['remark']:'无'); } else { - $mail_content = '尊敬的用户,您好:您的SSL证书部署失败!
失败原因:'.$row['error'].'
自动部署账户:['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')
关联SSL证书:['.$row['oid'].']'.implode('、', $domainList).'
任务备注:'.($row['remark']?$row['remark']:'无'); + $mail_content = '尊敬的用户,您好:您的SSL证书部署失败!
失败原因: '.$row['error'].'
自动部署账户: ['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')
关联SSL证书: ['.$row['oid'].']'.implode('、', $domainList).'
任务备注: '.($row['remark']?$row['remark']:'无'); } - $mail_content .= '
'.self::$sitename.'
'.date('Y-m-d H:i:s'); + $mail_content .= '
'.self::$sitename.'
'.date('Y-m-d H:i:s').''; + self::cert_send($mail_title, $mail_content, $result); + Db::name('cert_deploy')->where('id', $id)->update(['issend' => 1]); + } + + private static function cert_send($mail_title, $mail_content, $result) + { if (config_get('cert_notice_mail') == 1 || config_get('cert_notice_mail') == 2 && !$result) { $mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name'); self::send_mail($mail_name, $mail_title, $mail_content); } if (config_get('cert_notice_wxtpl') == 1 || config_get('cert_notice_wxtpl') == 2 && !$result) { $content = str_replace(['
', '', ''], ["\n\n", '**', '**'], $mail_content); - self::send_wechat_tplmsg($mail_title, $content); + self::send_wechat_tplmsg($mail_title, strip_tags($content)); } if (config_get('cert_notice_tgbot') == 1 || config_get('cert_notice_tgbot') == 2 && !$result) { $content = str_replace('
', "\n", $mail_content); - $content = "" . $mail_title . "\n" . $content; + $content = "".$mail_title."\n".strip_tags($content); self::send_telegram_bot($content); } - Db::name('cert_deploy')->where('id', $id)->update(['issend' => 1]); + if (config_get('cert_notice_webhook') == 1) { + $content = str_replace(['*', '
', '', ''], ['\*', "\n", '**', '**'], $mail_content); + self::send_webhook($mail_title, $content); + } } public static function send_mail($to, $sub, $msg) @@ -187,7 +188,7 @@ class MsgNotice if (isset($arr['success']) && $arr['success'] == true) { return true; } else { - return $arr['msg']; + return isset($arr['msg']) ? $arr['msg'] : '请求失败'; } } @@ -203,7 +204,48 @@ class MsgNotice if (isset($arr['ok']) && $arr['ok'] == true) { return true; } else { - return $arr['description']; + return isset($arr['description']) ? $arr['description'] : '请求失败'; + } + } + + public static function send_webhook($title, $content) + { + $url = config_get('webhook_url'); + if (!$url || !parse_url($url)) return false; + if (strpos($url, 'oapi.dingtalk.com')) { + $content = '### '.$title." \n ".str_replace("\n", " \n ", $content); + $post = [ + 'msgtype' => 'markdown', + 'markdown' => [ + 'title' => $title, + 'text' => $content, + ], + ]; + } elseif (strpos($url, 'qyapi.weixin.qq.com')) { + $content = '## '.$title."\n".$content; + $post = [ + 'msgtype' => 'markdown', + 'markdown' => [ + 'content' => $content, + ], + ]; + } elseif (strpos($url, 'open.feishu.cn')) { + $content = str_replace(['\*', '**'], ['*', ''], strip_tags($content)); + $post = [ + 'msg_type' => 'text', + 'content' => [ + 'text' => $content, + ], + ]; + } else { + return '不支持的Webhook地址'; + } + $result = get_curl($url, json_encode($post), 0, 0, 0, 0, 0, ['Content-Type: application/json; charset=UTF-8']); + $arr = json_decode($result, true); + if (isset($arr['errcode']) && $arr['errcode'] == 0 || isset($arr['code']) && $arr['code'] == 0) { + return true; + } else { + return isset($arr['errmsg']) ? $arr['errmsg'] : (isset($arr['msg']) ? $arr['msg'] : '请求失败'); } } @@ -233,6 +275,7 @@ class MsgNotice curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type); } curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $httpheader[] = "Accept: */*"; diff --git a/app/view/cert/certset.html b/app/view/cert/certset.html index a7fa391..26af945 100644 --- a/app/view/cert/certset.html +++ b/app/view/cert/certset.html @@ -64,6 +64,10 @@
+
+ +
+
diff --git a/app/view/dmonitor/overview.html b/app/view/dmonitor/overview.html index da86afc..f15d9a1 100644 --- a/app/view/dmonitor/overview.html +++ b/app/view/dmonitor/overview.html @@ -56,6 +56,10 @@
+
+ +
+
+
+

群机器人Webhook

+
+
+
+ +
+
+
+ +
+
+
+ +
{/block} @@ -139,7 +159,7 @@ function saveSetting(obj){ success : function(data) { layer.close(ii); if(data.code == 0){ - layer.alert('设置保存成功!
重启检测进程或容器后生效', { + layer.alert('设置保存成功!
如有使用容灾切换,重启检测进程后生效', { icon: 1, closeBtn: false }, function(){ @@ -196,5 +216,25 @@ function tgbottest(){ } }); } +function webhooktest(){ + var ii = layer.load(2, {shade:[0.1,'#fff']}); + $.ajax({ + type : 'GET', + url : '/system/webhooktest', + dataType : 'json', + success : function(data) { + layer.close(ii); + if(data.code == 0){ + layer.alert(data.msg, {icon: 1}); + }else{ + layer.alert(data.msg, {icon: 2}) + } + }, + error:function(data){ + layer.close(ii); + layer.msg('服务器错误'); + } + }); +} {/block} \ No newline at end of file diff --git a/public/static/images/mwpanel.ico b/public/static/images/mwpanel.ico new file mode 100644 index 0000000000000000000000000000000000000000..17e918a805f4f1f16613716ef3238518435197cc GIT binary patch literal 9662 zcmd5?-Ahzk6yN5QWj0P`_DNbPL_zdYlv!4Ym6U;54;3O36+{okK_Pt4SI`i zT;viVVMh4S7t}*Ngav(QHce&^S%_BZzQ5n8HFwXRea0Detkd1Dz4uvruiyGOYp-+W zDwTnMt5zxeEmD7%C{>`8T84%xRgcDb?<)R5#{2J%9Xs;p&!1m8efspX+1c6GX3w4- zo;h=-4g>;T%gxQz`T6->)22;p%E`$&HE-U$%9@&*(0JoWWxw+B@|;j8R38imZ%m#% z`3u(SR2p>ag)TSH4wROb=A1+_UexuITA>OCDnT+B_&1ha|^JK+14)H z<{WK?7q2k z=hh^P*W_EUU_mWx(C6BBBIib<17n7EPuFvrs{Yg=*;rb-bZHUdJ(8-7bo29hC@wBu z1UbIf@#Dt>I74rMA?qarFjjf|GtY;Wv%AifgFH;^GX?n#Nfd!^<%n@7XfAhwz(n*tdCQj9Tzd z^rKfrMMaL^8AX|oA3xTSNJRJa^yv5R-+Q#XyIbG9c{5JN>eZ|DhYugTMjkd_wJp?M_#TarA)tA2G-7v8#iW)0;nMy(2v<$#>D^n^=myiIH-i48tGAo$U5 z5xh2~4Y(I^%l?At{{8!Lc!;08!Y?{=yl&mPIR1P0?#1X!KCVdue>3s#+O;bWxz)FR zxAB|UXggcqva+%$9$N?Av-yc%d`q8+ALw(x_~9PF+`D)0-VkcyZT6n#nDHa_7u(Q2 zl;dar;o)Hq6LE|Fp62 z*lYakFLn|8lfHWOYDE0ViH&I2Y|Q4E__>$(n6jijc<>-D9{7w>zF;@0-}5UxVtF@9Nd`%hc?d=-hQDWBPT#v?q_==R+P$S0h(l!qt zK8&%y*oHEB-?q6q&dbZwh@p0K&h8UGeJQa+KTrl~Z*Q+&ym)bpjQ#ufM`On1rT&eL zjWN8e+vr>F$0o7H{>zsy<9usl<99yf&wuQBb8OpR{2=l!U%srF1IWi3_13Lh9uDeD zJf;qei4`kWcy=X!eSLitvtTD>bLD0e7yHcp$f1q)yg3&9+*7biJcz7k&z|Y#=4So$ z>C>nk1wVOt9#dcH^6}$G-P+o!Z{NPH`}+E#{N&?)q-+;2UX1aTiAnnK-)Ww~GImkH z&pnArbRgxJxMW_a_(tw?EwKxgwZzMLQsHHv>uYOkN5qeBB-`*kGsIfRg`IQ6Z=S!D zBf5}^JdrQ=MF+VrdUM{?MaHDE_Q{hc8g)%V{H!@qd*%b9f*)9mI{8ie6R+T6-s8F8 z(nV}4*cn@wE?x3;73`v~@XGk}=g)f6rcF*PCPqAStogkQ&%r))oNI`m`G;62gOr#n zD=YQ#<;%V2%*?4K9`aqeaz!)G@jdbU`SV`Pi=D|U_NRaN?zMC0&Jpttu>ya+2OfVm zY}k+ue{^x))tD0x9XjN-!-o&+y1F`z_h^ro`G3!zJ-Vr>NxyjU!h08d{`|SVdiAQ_ zzJ0sLM;mZo(v>S$>I)Yx=tqwp>9=p+>To!$SwoyVcTVFskfgBV+zJD8%sV`OFX20} z6MwSv)P?WeiOzJ7K(Mh#4m`Oetgp}8wt00f6kma)yR=wi2YaMCwAo3S`%Bc zed>VqQ9oeagxa6j@w|=-yXeSRf**X(wsh%)Gm5`gq!crP*`|esg$r40!yZG#o6dOR z-u#}K?6YcP^&9gyWz^aS;EQzre%*t2s)G#;4GD9kAI4rYvv{{ei&Y%u@; literal 0 HcmV?d00001 diff --git a/route/app.php b/route/app.php index 374d87c..82eaf28 100644 --- a/route/app.php +++ b/route/app.php @@ -110,6 +110,7 @@ Route::group(function () { Route::any('/system/proxyset', 'system/proxyset'); Route::get('/system/mailtest', 'system/mailtest'); Route::get('/system/tgbottest', 'system/tgbottest'); + Route::get('/system/webhooktest', 'system/webhooktest'); Route::post('/system/proxytest', 'system/proxytest'); })->middleware(CheckLogin::class)