From 98e4668969593f0b6e7d7fa8a59a4e3741f46060 Mon Sep 17 00:00:00 2001 From: nightcp Date: Tue, 21 Oct 2025 13:53:16 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=9C=BA=E5=99=A8=E4=BA=BA=20webhook=20=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 3 +++ app/Tasks/BotReceiveMsgTask.php | 8 ++++++-- app/Tasks/WebSocketDialogMsgTask.php | 10 +++++----- .../js/pages/manage/components/DialogWrapper.vue | 10 ++++++---- resources/assets/js/store/actions.js | 2 +- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index a653f34b6..16f704c47 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -1280,6 +1280,9 @@ class DialogController extends AbstractController if ($model_name) { $msgData['model_name'] = $model_name; } + if (User::isBot($user->userid)) { + $msgData['force_webhook'] = true; // 强制使用webhook发送 + } $result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'text', $msgData, $user->userid, false, false, $silence, $key); } } diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php index 68dc7917a..b6193d4b6 100644 --- a/app/Tasks/BotReceiveMsgTask.php +++ b/app/Tasks/BotReceiveMsgTask.php @@ -66,7 +66,7 @@ class BotReceiveMsgTask extends AbstractTask } // 判断消息是否存在 - $msg = WebSocketDialogMsg::with(['user'])->find($this->msgId); + $msg = WebSocketDialogMsg::with(['user', 'webSocketDialog'])->find($this->msgId); if (empty($msg)) { return; } @@ -75,7 +75,11 @@ class BotReceiveMsgTask extends AbstractTask $msg->readSuccess($botUser->userid); // 判断消息是否是机器人发送的则不处理,避免循环 - if (!$msg->user || $msg->user->bot) { + if ((!$msg->user || $msg->user->bot)) { + $msgData = Base::json2array($msg->msg); + if (Base::val($msgData, 'force_webhook') && $msg->webSocketDialog) { + $this->handleWebhookRequest($msgData['text'], null, $msg, $msg->webSocketDialog, $botUser); + } return; } diff --git a/app/Tasks/WebSocketDialogMsgTask.php b/app/Tasks/WebSocketDialogMsgTask.php index 4dcf271b6..fd3507aa3 100644 --- a/app/Tasks/WebSocketDialogMsgTask.php +++ b/app/Tasks/WebSocketDialogMsgTask.php @@ -138,11 +138,11 @@ class WebSocketDialogMsgTask extends AbstractTask 'dot' => $dot, 'updated' => $updated, ]; - // 机器人收到消处理 - $botUser = User::whereUserid($userid)->whereBot(1)->first(); - if ($botUser) { - $this->endArray[] = new BotReceiveMsgTask($botUser->userid, $msg->id, $mentions, $this->client); - } + } + // 机器人收到消处理 + $botUser = User::whereUserid($userid)->whereBot(1)->first(); + if ($botUser) { // 避免机器人处理自己发送的消息 + $this->endArray[] = new BotReceiveMsgTask($botUser->userid, $msg->id, $mentions, $this->client); } } // 更新已发送数量 diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 719af23b1..bea6d7913 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -463,7 +463,7 @@ - + {{$L(option.label)}} @@ -781,6 +781,7 @@ export default { {value: 'member_join', label: '成员加入'}, {value: 'member_leave', label: '成员退出'}, ], + webhookEvents: [], openId: 0, errorId: 0, @@ -2762,8 +2763,9 @@ export default { clear_day: 0, webhook_url: '', system_name: '', - webhook_events: this.prepareWebhookEvents([], true), + webhook_events: [], }) + this.webhookEvents = this.prepareWebhookEvents([], true) this.modifyLoad++; this.$store.dispatch("call", { url: 'users/bot/info', @@ -2774,7 +2776,7 @@ export default { this.modifyData.clear_day = data.clear_day this.modifyData.webhook_url = data.webhook_url this.modifyData.system_name = data.system_name - this.modifyData.webhook_events = this.prepareWebhookEvents(data.webhook_events, true) + this.webhookEvents = this.prepareWebhookEvents(data.webhook_events, true) }).finally(() => { this.modifyLoad--; }) @@ -2929,7 +2931,7 @@ export default { name: this.modifyData.name, clear_day: this.modifyData.clear_day, webhook_url: this.modifyData.webhook_url, - webhook_events: this.normalizeWebhookEvents(this.modifyData.webhook_events, false), + webhook_events: this.normalizeWebhookEvents(this.webhookEvents), dialog_id: this.modifyData.dialog_id }).then(({msg}) => { $A.messageSuccess(msg); diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 5d64def7d..67e3f2073 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -3399,7 +3399,7 @@ export default { } return item.dialog_user.userid === userid }); - if (dialog) { + if (dialog && dialog.bot !== 1) { return dispatch("openDialog", dialog.id).then(resolve).catch(reject) } dispatch("call", { From bdfc8bdd0c990d7e7db71297fb41a32053f3d219 Mon Sep 17 00:00:00 2001 From: nightcp Date: Wed, 22 Oct 2025 17:29:32 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=9C=BA?= =?UTF-8?q?=E5=99=A8=E4=BA=BA=E6=B6=88=E6=81=AF=E6=8E=A8=E9=80=81=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=96=87=E6=A1=A3=EF=BC=8C=E5=A2=9E=E5=BC=BA=20webhoo?= =?UTF-8?q?k=20=E4=BA=8B=E4=BB=B6=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DialogView/template/bot-api.vue | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/pages/manage/components/DialogView/template/bot-api.vue b/resources/assets/js/pages/manage/components/DialogView/template/bot-api.vue index 5d9b16d69..dbbc3d1f2 100644 --- a/resources/assets/js/pages/manage/components/DialogView/template/bot-api.vue +++ b/resources/assets/js/pages/manage/components/DialogView/template/bot-api.vue @@ -69,9 +69,72 @@ export default { "| `mention` | {{是否被@到}} | boolean |", "| `bot_uid` | {{机器人ID}} | string |", "| `version` | {{系统版本}} | string |", + "### 3. {{打开会话 消息推送}}", + "", + "{{打开机器人会话后会自动POST推送到配置的Webhook地址,请求超时为30秒。}}", + "", + "#### {{推送参数}}", + "", + "| {{参数名}} | {{说明}} | {{类型}} |", + "|--------|------|------|", + "| `event` | {{推送事件}} | string |", + "| `timestamp` | {{推送时间戳}} | string |", + "| `dialog_id` | {{对话ID}} | string |", + "| `dialog_type` | {{对话类型}} | string |", + "| `bot_uid` | {{机器人ID}} | string |", + "| `owner_uid` | {{机器人所属用户ID}} | string |", + "| `user` | {{机器人所属用户信息}} | object |", + "| `user.userid` | {{用户ID}} | string |", + "| `user.email` | {{用户邮箱}} | string |", + "| `user.nickname` | {{用户昵称}} | string |", + "### 4. {{成员加入 消息推送}}", + "", + "{{成员加入群组后会自动POST推送到配置的Webhook地址,请求超时为30秒。}}", + "", + "#### {{推送参数}}", + "", + "| {{参数名}} | {{说明}} | {{类型}} |", + "|--------|------|------|", + "| `event` | {{推送事件}} | string |", + "| `timestamp` | {{推送时间戳}} | string |", + "| `dialog_id` | {{对话ID}} | string |", + "| `dialog_type` | {{对话类型}} | string |", + "| `bot_uid` | {{机器人ID}} | string |", + "| `owner_uid` | {{机器人所属用户ID}} | string |", + "| `user` | {{机器人所属用户信息}} | object |", + "| `user.userid` | {{用户ID}} | string |", + "| `user.email` | {{用户邮箱}} | string |", + "| `user.nickname` | {{用户昵称}} | string |", + "### 5. {{成员退出 消息推送}}", + "", + "{{成员退出群组后会自动POST推送到配置的Webhook地址,请求超时为30秒。}}", + "", + "#### {{推送参数}}", + "", + "| {{参数名}} | {{说明}} | {{类型}} |", + "|--------|------|------|", + "| `event` | {{推送事件}} | string |", + "| `timestamp` | {{推送时间戳}} | string |", + "| `dialog_id` | {{对话ID}} | string |", + "| `dialog_type` | {{对话类型}} | string |", + "| `dialog_name` | {{对话名称}} | string |", + "| `group_type` | {{群组类型}} | string |", + "| `bot_uid` | {{机器人ID}} | string |", + "| `owner_uid` | {{机器人所属用户ID}} | string |", + "| `action` | {{动作}} | string |", + "| `actor` | {{操作人信息}} | object |", + "| `actor.userid` | {{用户ID}} | string |", + "| `actor.email` | {{用户邮箱}} | string |", + "| `actor.nickname` | {{用户昵称}} | string |", + "| `actor.is_bot` | {{是否机器人}} | boolean |", + "| `members` | {{成员信息}} | array |", + "| `members.userid` | {{用户ID}} | string |", + "| `members.email` | {{用户邮箱}} | string |", + "| `members.nickname` | {{用户昵称}} | string |", + "| `members.is_bot` | {{是否机器人}} | boolean |", ].map(item => item.replace(/\{\{([^}]+)\}\}/g, (_, v1) => this.$L(v1))).join("\n"); }, }, methods: {}, } - + \ No newline at end of file