Compare commits

...

2 Commits

Author SHA1 Message Date
kuaifan
2fad6394ee no message 2025-11-06 14:03:58 +00:00
kuaifan
4bfe33a37f feat: 优化打开会话事件接口,优化机器人webhook逻辑
- 新增 `open__event` 方法用于处理打开会话事件
- 移除旧的 `open__webhook` 方法
- 更新前端调用逻辑,使用新的事件接口
- 优化 webhook 事件推送逻辑,简化参数传递
2025-11-06 13:59:10 +00:00
24 changed files with 507 additions and 725 deletions

View File

@ -448,6 +448,39 @@ class DialogController extends AbstractController
return Base::retSuccess('success', $data);
}
/**
* @api {get} api/dialog/open/event 打开会话事件
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName open__event
*
* @apiParam {Number} dialog_id 对话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function open__event()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
if (empty($dialog)) {
return Base::retError('打开会话失败');
}
//
Cache::remember("webhook_dialog_open_{$dialog->id}_{$user->userid}", Carbon::now()->addMinute(), function () use ($dialog, $user) {
$dialog->dispatchMemberWebhook(UserBot::WEBHOOK_EVENT_DIALOG_OPEN, $user->userid, $user->userid);
return true;
});
//
return Base::retSuccess('success');
}
/**
* @api {get} api/dialog/msg/list 获取消息列表
*
@ -1258,9 +1291,6 @@ 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);
}
}
@ -3688,61 +3718,4 @@ class DialogController extends AbstractController
//
return Base::retSuccess('重命名成功', $session);
}
/**
* @api {get} api/dialog/open/webhook 打开机器人会话推送 webhook
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName open__webhook
*
* @apiParam {Number} dialog_id 对话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function open__webhook()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
if (empty($dialog_id)) {
return Base::retError('错误的会话');
}
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
if (empty($dialog)) {
return Base::retError('打开会话失败');
}
$data = WebSocketDialog::synthesizeData($dialog->id, $user->userid);
if ($data['bot'] == 1) {
$botTarget = User::whereUserid($data['dialog_user']['userid'])->whereBot(1)->first();
if ($botTarget) {
$userBot = UserBot::whereBotId($botTarget->userid)->first();
if ($userBot) {
// 每个机器人1分钟只触发一次 webhook
Cache::remember('webhook_dialog_open_' . $botTarget->userid, 60, function () use ($userBot, $dialog, $user) {
$userBot->dispatchWebhook(UserBot::WEBHOOK_EVENT_DIALOG_OPEN, [
'dialog_id' => $dialog->id,
'dialog_type' => $dialog->type,
'session_id' => $dialog->session_id,
'dialog_name' => $dialog->getGroupName(),
'user' => [
'userid' => $user->userid,
'email' => $user->email,
'nickname' => $user->nickname,
],
], 10, [
'dialog' => $dialog->id,
'operator' => $user->userid,
]);
return true;
});
}
}
}
return Base::retSuccess('success');
}
}

View File

@ -4,7 +4,6 @@ namespace App\Models;
use App\Module\Base;
use App\Module\Doo;
use App\Module\Extranet;
use App\Module\Ihttp;
use App\Module\Timer;
use App\Tasks\JokeSoupTask;
@ -56,43 +55,6 @@ class UserBot extends AbstractModel
'webhook_events' => 'array',
];
/**
* 获取可选的 webhook 事件
*
* @return string[]
*/
public static function webhookEventOptions(): array
{
return [
self::WEBHOOK_EVENT_MESSAGE,
self::WEBHOOK_EVENT_DIALOG_OPEN,
self::WEBHOOK_EVENT_MEMBER_JOIN,
self::WEBHOOK_EVENT_MEMBER_LEAVE,
];
}
/**
* 标准化 webhook 事件配置
*
* @param mixed $events
* @return array
*/
public static function normalizeWebhookEvents(mixed $events, bool $useFallback = true): array
{
if (is_string($events)) {
$events = Base::json2array($events);
}
if ($events === null) {
$events = [];
}
if (!is_array($events)) {
$events = [$events];
}
$events = array_filter(array_map('strval', $events));
$events = array_values(array_intersect($events, self::webhookEventOptions()));
return $events ?: ($useFallback ? [self::WEBHOOK_EVENT_MESSAGE] : []);
}
/**
* 获取 webhook 事件配置
*
@ -140,35 +102,27 @@ class UserBot extends AbstractModel
* 发送 webhook
*
* @param string $event
* @param array $payload
* @param array $data
* @param int $timeout
* @param array $context
* @return array|null
*/
public function dispatchWebhook(string $event, array $payload, int $timeout = 30, array $context = []): ?array
public function dispatchWebhook(string $event, array $data, int $timeout = 30): ?array
{
if (!$this->shouldDispatchWebhook($event)) {
return null;
}
$payload = array_merge([
'event' => $event,
'timestamp' => time(),
'bot_uid' => $this->bot_id,
'owner_uid' => $this->userid,
], $payload);
try {
$result = Ihttp::ihttp_post($this->webhook_url, $payload, $timeout);
$data['event'] = $event;
$result = Ihttp::ihttp_post($this->webhook_url, $data, $timeout);
$this->increment('webhook_num');
return $result;
} catch (Throwable $th) {
info(Base::array2json(array_merge($context, [
'bot_userid' => $this->bot_id,
'event' => $event,
info(Base::array2json([
'webhook_url' => $this->webhook_url,
'data' => $data,
'error' => $th->getMessage(),
])));
]));
return null;
}
}
@ -607,4 +561,42 @@ class UserBot extends AbstractModel
}
return Base::retSuccess("创建成功。", $data);
}
/**
* 获取可选的 webhook 事件
*
* @return string[]
*/
public static function webhookEventOptions(): array
{
return [
self::WEBHOOK_EVENT_MESSAGE,
self::WEBHOOK_EVENT_DIALOG_OPEN,
self::WEBHOOK_EVENT_MEMBER_JOIN,
self::WEBHOOK_EVENT_MEMBER_LEAVE,
];
}
/**
* 标准化 webhook 事件配置
*
* @param mixed $events
* @param bool $useFallback
* @return array
*/
public static function normalizeWebhookEvents(mixed $events, bool $useFallback = true): array
{
if (is_string($events)) {
$events = Base::json2array($events);
}
if ($events === null) {
$events = [];
}
if (!is_array($events)) {
$events = [$events];
}
$events = array_filter(array_map('strval', $events));
$events = array_values(array_intersect($events, self::webhookEventOptions()));
return $events ?: ($useFallback ? [self::WEBHOOK_EVENT_MESSAGE] : []);
}
}

View File

@ -461,8 +461,7 @@ class WebSocketDialog extends AbstractModel
*/
public function joinGroup($userid, $inviter, $important = null)
{
$addedUserIds = [];
AbstractModel::transaction(function () use ($important, $inviter, $userid, &$addedUserIds) {
AbstractModel::transaction(function () use ($important, $inviter, $userid) {
foreach (is_array($userid) ? $userid : [$userid] as $value) {
if ($value > 0) {
$updateData = [
@ -481,7 +480,6 @@ class WebSocketDialog extends AbstractModel
]);
}, $isInsert);
if ($isInsert) {
$addedUserIds[] = $value;
WebSocketDialogMsg::sendMsg(null, $this->id, 'notice', [
'notice' => User::userid2nickname($value) . " 已加入群组"
], $inviter, true, true);
@ -492,16 +490,6 @@ class WebSocketDialog extends AbstractModel
$data = WebSocketDialog::generatePeople($this->id);
$data['id'] = $this->id;
$this->pushMsg("groupUpdate", $data);
if ($addedUserIds) {
$meta = ['action' => 'join'];
if ($inviter > 0) {
$actor = $this->getUserSnapshots([$inviter]);
if (!empty($actor)) {
$meta['actor'] = $actor[0];
}
}
$this->dispatchMemberWebhook(UserBot::WEBHOOK_EVENT_MEMBER_JOIN, $addedUserIds, $meta);
}
return true;
}
@ -515,15 +503,14 @@ class WebSocketDialog extends AbstractModel
public function exitGroup($userid, $type = 'exit', $checkDelete = true, $pushMsg = true)
{
$typeDesc = $type === 'remove' ? '移出' : '退出';
$removedUserIds = [];
AbstractModel::transaction(function () use ($pushMsg, $checkDelete, $typeDesc, $type, $userid, &$removedUserIds) {
AbstractModel::transaction(function () use ($pushMsg, $checkDelete, $typeDesc, $type, $userid) {
$builder = WebSocketDialogUser::whereDialogId($this->id);
if (is_array($userid)) {
$builder->whereIn('userid', $userid);
} else {
$builder->whereUserid($userid);
}
$builder->chunkById(100, function($list) use ($pushMsg, $checkDelete, $typeDesc, $type, &$removedUserIds) {
$builder->chunkById(100, function($list) use ($pushMsg, $checkDelete, $typeDesc, $type) {
/** @var WebSocketDialogUser $item */
foreach ($list as $item) {
if ($checkDelete) {
@ -543,8 +530,8 @@ class WebSocketDialog extends AbstractModel
}
}
//
$item->operator_id = User::userid();
$item->delete();
$removedUserIds[] = $item->userid;
//
if ($pushMsg) {
if ($type === 'remove') {
@ -563,58 +550,17 @@ class WebSocketDialog extends AbstractModel
$data = WebSocketDialog::generatePeople($this->id);
$data['id'] = $this->id;
$this->pushMsg("groupUpdate", $data);
if ($removedUserIds) {
$meta = ['action' => $type];
$operatorId = User::userid();
if ($operatorId > 0) {
$actor = $this->getUserSnapshots([$operatorId]);
if (!empty($actor)) {
$meta['actor'] = $actor[0];
}
}
$this->dispatchMemberWebhook(UserBot::WEBHOOK_EVENT_MEMBER_LEAVE, $removedUserIds, $meta);
}
}
/**
* 获取用户快照
* @param array $userIds
* @return array
*/
protected function getUserSnapshots(array $userIds): array
{
$userIds = array_values(array_unique(array_filter($userIds)));
if (empty($userIds)) {
return [];
}
return User::whereIn('userid', $userIds)
->get(['userid', 'nickname', 'email', 'bot'])
->map(function (User $user) {
return [
'userid' => $user->userid,
'nickname' => $user->nickname,
'email' => $user->email,
'is_bot' => (bool)$user->bot,
];
})
->values()
->all();
}
/**
* 推送成员事件到机器人 webhook
* @param string $event
* @param array $memberIds
* @param array $meta
* @param int $memberId
* @param int $operatorId
* @return void
*/
protected function dispatchMemberWebhook(string $event, array $memberIds, array $meta = []): void
public function dispatchMemberWebhook(string $event, int $memberId, int $operatorId): void
{
$memberIds = array_values(array_unique(array_filter($memberIds)));
if (empty($memberIds)) {
return;
}
$botIds = $this->dialogUser()->where('bot', 1)->pluck('userid')->toArray();
if (empty($botIds)) {
return;
@ -625,24 +571,20 @@ class WebSocketDialog extends AbstractModel
return;
}
$members = $this->getUserSnapshots($memberIds);
if (empty($members)) {
return;
}
$member = User::find($memberId, ['userid', 'nickname', 'email', 'bot'])?->toArray();
$operator = $operatorId === $memberId ? $member : User::find($operatorId, ['userid', 'nickname', 'email', 'bot'])?->toArray();
$payload = array_merge([
$payload = [
'dialog_id' => $this->id,
'dialog_type' => $this->type,
'group_type' => $this->group_type,
'dialog_name' => $this->getGroupName(),
'members' => $members,
], array_filter($meta, fn ($value) => $value !== null));
'member' => $member,
'operator' => $operator,
];
foreach ($userBots as $userBot) {
$userBot->dispatchWebhook($event, $payload, 10, [
'dialog' => $this->id,
'event_members' => $memberIds,
]);
$userBot->dispatchWebhook($event, $payload, 10);
}
}

View File

@ -3,6 +3,7 @@
namespace App\Observers;
use App\Models\Deleted;
use App\Models\UserBot;
use App\Models\WebSocketDialogUser;
use App\Tasks\ZincSearchSyncTask;
use Carbon\Carbon;
@ -31,6 +32,11 @@ class WebSocketDialogUserObserver extends AbstractObserver
}
Deleted::forget('dialog', $webSocketDialogUser->dialog_id, $webSocketDialogUser->userid);
self::taskDeliver(new ZincSearchSyncTask('userSync', $webSocketDialogUser->toArray()));
//
$dialog = $webSocketDialogUser->webSocketDialog;
if ($dialog) {
$dialog->dispatchMemberWebhook(UserBot::WEBHOOK_EVENT_MEMBER_JOIN, $webSocketDialogUser->userid, intval($webSocketDialogUser->inviter));
}
}
/**
@ -54,6 +60,12 @@ class WebSocketDialogUserObserver extends AbstractObserver
{
Deleted::record('dialog', $webSocketDialogUser->dialog_id, $webSocketDialogUser->userid);
self::taskDeliver(new ZincSearchSyncTask('deleteUser', $webSocketDialogUser->toArray()));
//
$dialog = $webSocketDialogUser->webSocketDialog;
if ($dialog) {
$operatorId = $webSocketDialogUser->operator_id ?? 0;
$dialog->dispatchMemberWebhook(UserBot::WEBHOOK_EVENT_MEMBER_LEAVE, $webSocketDialogUser->userid, intval($operatorId));
}
}
/**

View File

@ -75,11 +75,7 @@ class BotReceiveMsgTask extends AbstractTask
$msg->readSuccess($botUser->userid);
// 判断消息是否是机器人发送的则不处理,避免循环
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);
}
if (!$msg->user || $msg->user->bot) {
return;
}
@ -539,9 +535,6 @@ class BotReceiveMsgTask extends AbstractTask
return;
}
}
if (!$userBot && !preg_match("/^https?:\/\//", $webhookUrl)) {
return;
}
} catch (\Exception $e) {
WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'template', [
'type' => 'content',
@ -549,8 +542,10 @@ class BotReceiveMsgTask extends AbstractTask
], $botUser->userid, false, false, true); // todo 未能在任务end事件来发送任务
return;
}
//
// 基本请求数据
$data = [
'event' => UserBot::WEBHOOK_EVENT_MESSAGE,
'text' => $sendText,
'reply_text' => $replyText,
'token' => User::generateToken($botUser),
@ -561,8 +556,9 @@ class BotReceiveMsgTask extends AbstractTask
'msg_uid' => $msg->userid,
'mention' => $this->mention ? 1 : 0,
'bot_uid' => $botUser->userid,
'extras' => Base::array2json($extras),
'version' => Base::getVersion(),
'extras' => Base::array2json($extras)
'timestamp' => time(),
];
// 添加用户信息
$userInfo = User::find($msg->userid);
@ -579,19 +575,14 @@ class BotReceiveMsgTask extends AbstractTask
$result = null;
if ($userBot) {
$result = $userBot->dispatchWebhook(UserBot::WEBHOOK_EVENT_MESSAGE, $data, 30, [
'dialog' => $dialog->id,
'msg' => $msg->id,
]);
$result = $userBot->dispatchWebhook(UserBot::WEBHOOK_EVENT_MESSAGE, $data);
} else {
try {
$result = Ihttp::ihttp_post($webhookUrl, $data, 30);
} catch (\Throwable $th) {
info(Base::array2json([
'bot_userid' => $botUser->userid,
'dialog' => $dialog->id,
'msg' => $msg->id,
'webhook_url' => $webhookUrl,
'data' => $data,
'error' => $th->getMessage(),
]));
}
@ -599,7 +590,7 @@ class BotReceiveMsgTask extends AbstractTask
if ($result && isset($result['data'])) {
$responseData = Base::json2array($result['data']);
if (($responseData['code'] ?? 0) != 200 && !empty($responseData['message'])) {
if (($responseData['code'] ?? 0) === 200 && !empty($responseData['message'])) {
WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', [
'text' => $responseData['message']
], $botUser->userid, false, false, true);
@ -722,7 +713,7 @@ class BotReceiveMsgTask extends AbstractTask
</role_setting>
EOF;
}
// 上下文信息(项目、任务、部门等)+ 操作指令
switch ($dialog->type) {
// 用户对话
@ -757,7 +748,7 @@ class BotReceiveMsgTask extends AbstractTask
项目状态:{$projectStatus}
</context_info>
EOF;
$sections[] = <<<EOF
<instructions>
如果你判断我想要或需要添加任务,请按照以下格式回复:
@ -787,7 +778,7 @@ class BotReceiveMsgTask extends AbstractTask
{$taskContext}
</context_info>
EOF;
$sections[] = <<<EOF
<instructions>
如果你判断我想要或需要添加子任务,请按照以下格式回复:
@ -822,7 +813,7 @@ class BotReceiveMsgTask extends AbstractTask
EOF;
break;
}
// 聊天历史
if ($dialog->type === 'group') {
$chatHistory = $this->getRecentChatHistory($dialog, 15);
@ -836,7 +827,7 @@ class BotReceiveMsgTask extends AbstractTask
}
break;
}
// 更新系统提示词
if (!empty($sections)) {
$extras['system_message'] = implode("\n\n", $sections);

View File

@ -1563,17 +1563,10 @@ API接口文档
搜索关键词
查看会话ID
查看接口列表
发送文本消息
对话ID
消息内容
回复指定消息ID
对话类型
消息ID
消息发送人ID
消息发送人信息
是否被@到
机器人ID
系统版本
机器人详情
保留消息时间
最后一次清理时间
@ -2094,37 +2087,17 @@ OKR群组
已加入
邀请地址不存在或已被删除!
API 使用说明
Webhook 消息推送
html 或 md
yes 或 no
会话名称
结果
参数名
名称
命令
回复/引用的消息文本
开发者可以通过此接口调用机器人向指定对话发送文本消息。
必填
接口信息
接口地址
推送参数
搜索词
文本类型
机器人收到消息后会自动POST推送到配置的Webhook地址请求超时为10秒。
消息文本内容
清理时间
留空自动生成
示例值
类型
该机器人不支持
说明
请求参数
请求头
请求方式
通过机器人向指定对话发送文本消息
静默模式
属性
会话ID

View File

@ -18431,18 +18431,6 @@
"id": "Lihat Daftar Antarmuka",
"ru": "Просмотр списка интерфейсов"
},
{
"key": "发送文本消息",
"zh": "",
"zh-CHT": "發送文本消息",
"en": "Send Text Message",
"ko": "텍스트 메시지 보내기",
"ja": "テキストメッセージを送信",
"de": "Textnachricht senden",
"fr": "Envoyer un message texte",
"id": "Kirim Pesan Teks",
"ru": "Отправить текстовое сообщение"
},
{
"key": "对话ID",
"zh": "",
@ -18467,30 +18455,6 @@
"id": "Konten Pesan",
"ru": "Содержание сообщения"
},
{
"key": "回复指定消息ID",
"zh": "",
"zh-CHT": "回覆指定消息ID",
"en": "Reply to Specific Message ID",
"ko": "특정 메시지 ID에 답장",
"ja": "特定のメッセージIDに返信",
"de": "Auf bestimmte Nachrichten-ID antworten",
"fr": "Répondre à un ID de message spécifique",
"id": "Balas ke ID Pesan Tertentu",
"ru": "Ответить на конкретный ID сообщения"
},
{
"key": "对话类型",
"zh": "",
"zh-CHT": "對話類型",
"en": "Conversation Type",
"ko": "대화 유형",
"ja": "会話タイプ",
"de": "Gesprächstyp",
"fr": "Type de conversation",
"id": "Jenis Percakapan",
"ru": "Тип разговора"
},
{
"key": "消息ID",
"zh": "",
@ -18503,30 +18467,6 @@
"id": "ID Pesan",
"ru": "ID сообщения"
},
{
"key": "消息发送人ID",
"zh": "",
"zh-CHT": "消息發送人ID",
"en": "Message Sender ID",
"ko": "메시지 발신자 ID",
"ja": "メッセージ送信者ID",
"de": "Absender-ID der Nachricht",
"fr": "ID de l'expéditeur du message",
"id": "ID Pengirim Pesan",
"ru": "ID отправителя сообщения"
},
{
"key": "是否被@到",
"zh": "",
"zh-CHT": "是否被@到",
"en": "Is Mentioned",
"ko": "멘션 여부",
"ja": "メンション有無",
"de": "Wurde erwähnt",
"fr": "Est mentionné",
"id": "Apakah Disebutkan",
"ru": "Упомянут ли"
},
{
"key": "机器人ID",
"zh": "",
@ -18539,18 +18479,6 @@
"id": "ID Bot",
"ru": "ID бота"
},
{
"key": "系统版本",
"zh": "",
"zh-CHT": "系統版本",
"en": "System Version",
"ko": "시스템 버전",
"ja": "システムバージョン",
"de": "Systemversion",
"fr": "Version du système",
"id": "Versi Sistem",
"ru": "Версия системы"
},
{
"key": "机器人详情",
"zh": "",
@ -30023,66 +29951,6 @@
"id": "Jenis robot harus terdiri dari 6-20 karakter.",
"ru": "Тип робота должен состоять из 6-20 символов."
},
{
"key": "消息发送人信息",
"zh": "",
"zh-CHT": "消息發送人資訊",
"en": "Sender Information",
"ko": "발신자 정보",
"ja": "送信者情報",
"de": "Absenderinformationen",
"fr": "Informations sur l'expéditeur",
"id": "Informasi Pengirim",
"ru": "Информация об отправителе"
},
{
"key": "API 使用说明",
"zh": "",
"zh-CHT": "API 使用說明",
"en": "API Documentation",
"ko": "API 사용 설명서",
"ja": "API 使用説明",
"de": "API-Anleitung",
"fr": "Documentation API",
"id": "Dokumentasi API",
"ru": "Документация по API"
},
{
"key": "Webhook 消息推送",
"zh": "",
"zh-CHT": "Webhook 消息推送",
"en": "Webhook Message Push",
"ko": "Webhook 메시지 푸시",
"ja": "Webhook メッセージプッシュ",
"de": "Webhook-Nachricht pushen",
"fr": "Push de message Webhook",
"id": "Push Pesan Webhook",
"ru": "Пуш-сообщения Webhook"
},
{
"key": "html 或 md",
"zh": "",
"zh-CHT": "html 或 md",
"en": "html or md",
"ko": "html 또는 md",
"ja": "html または md",
"de": "html oder md",
"fr": "html ou md",
"id": "html atau md",
"ru": "html или md"
},
{
"key": "yes 或 no",
"zh": "",
"zh-CHT": "yes 或 no",
"en": "yes or no",
"ko": "예 또는 아니오",
"ja": "はい または いいえ",
"de": "ja oder nein",
"fr": "oui ou non",
"id": "ya atau tidak",
"ru": "да или нет"
},
{
"key": "会话名称",
"zh": "",
@ -30119,18 +29987,6 @@
"id": "Hasil",
"ru": "Результат"
},
{
"key": "参数名",
"zh": "",
"zh-CHT": "參數名",
"en": "Parameter Name",
"ko": "매개변수 이름",
"ja": "パラメータ名",
"de": "Parametername",
"fr": "Nom du paramètre",
"id": "Nama Parameter",
"ru": "Имя параметра"
},
{
"key": "命令",
"zh": "",
@ -30143,42 +29999,6 @@
"id": "Perintah",
"ru": "Команда"
},
{
"key": "回复\/引用的消息文本",
"zh": "",
"zh-CHT": "回覆\/引用的消息文本",
"en": "Reply\/quoted message text",
"ko": "답장\/인용된 메시지 텍스트",
"ja": "返信\/引用されたメッセージのテキスト",
"de": "Antwort\/zitierter Nachrichtentext",
"fr": "Texte du message de réponse\/citation",
"id": "Balasan\/kutipan teks pesan",
"ru": "Текст ответа\/цитируемого сообщения"
},
{
"key": "开发者可以通过此接口调用机器人向指定对话发送文本消息。",
"zh": "",
"zh-CHT": "開發者可以通過此介面調用機器人向指定對話發送文本消息。",
"en": "Developers can use this interface to call the bot to send text messages to a specified conversation.",
"ko": "개발자는 이 인터페이스를 통해 지정된 대화에 텍스트 메시지를 보내도록 봇을 호출할 수 있습니다.",
"ja": "開発者は、このインターフェースを使用して、指定された会話にテキストメッセージを送信するためにボットを呼び出すことができます。",
"de": "Entwickler können diese Schnittstelle verwenden, um den Bot aufzurufen und Textnachrichten an ein angegebenes Gespräch zu senden.",
"fr": "Les développeurs peuvent utiliser cette interface pour appeler le bot afin d'envoyer des messages texte à une conversation spécifiée.",
"id": "Pengembang dapat menggunakan antarmuka ini untuk menghubungi bot untuk mengirim pesan teks ke percakapan yang ditentukan.",
"ru": "Разработчики могут использовать этот интерфейс для вызова бота для отправки текстовых сообщений в указанную беседу."
},
{
"key": "接口信息",
"zh": "",
"zh-CHT": "介面信息",
"en": "Interface information",
"ko": "인터페이스 정보",
"ja": "インターフェース情報",
"de": "Schnittstelleninformation",
"fr": "Informations d'interface",
"id": "Informasi antarmuka",
"ru": "Информация об интерфейсе"
},
{
"key": "接口地址",
"zh": "",
@ -30191,90 +30011,6 @@
"id": "Alamat antarmuka",
"ru": "Адрес интерфейса"
},
{
"key": "推送参数",
"zh": "",
"zh-CHT": "推送參數",
"en": "Push parameters",
"ko": "푸시 매개변수",
"ja": "プッシュパラメータ",
"de": "Push-Parameter",
"fr": "Paramètres de poussée",
"id": "Parameter dorong",
"ru": "Параметры пуша"
},
{
"key": "搜索词",
"zh": "",
"zh-CHT": "搜索詞",
"en": "Search term",
"ko": "검색어",
"ja": "検索用語",
"de": "Suchbegriff",
"fr": "Terme de recherche",
"id": "Istilah pencarian",
"ru": "Поисковый запрос"
},
{
"key": "文本类型",
"zh": "",
"zh-CHT": "文本類型",
"en": "Text type",
"ko": "텍스트 유형",
"ja": "テキストタイプ",
"de": "Texttyp",
"fr": "Type de texte",
"id": "Jenis teks",
"ru": "Тип текста"
},
{
"key": "机器人收到消息后会自动POST推送到配置的Webhook地址请求超时为10秒。",
"zh": "",
"zh-CHT": "機器人收到消息後會自動POST推送到配置的Webhook地址請求超時為10秒。",
"en": "Once the bot receives the message, it will automatically POST to the configured Webhook address, with a request timeout of 10 seconds.",
"ko": "봇이 메시지를 수신하면 구성된 웹훅 주소로 자동으로 POST를 전송하며, 요청 시간 초과는 10초입니다.",
"ja": "ボットがメッセージを受信すると、自動的に設定されたWebhookアドレスにPOSTし、要求のタイムアウトは10秒です。",
"de": "Sobald der Bot die Nachricht erhält, wird automatisch ein POST an die konfigurierte Webhook-Adresse gesendet, mit einer Anforderungszeitüberschreitung von 10 Sekunden.",
"fr": "Une fois que le bot reçoit le message, il enverra automatiquement un POST à l'adresse Webhook configurée, avec une expiration de requête de 10 secondes.",
"id": "Setelah bot menerima pesan tersebut, bot akan secara otomatis mengirimkan POST ke alamat Webhook yang dikonfigurasi, dengan waktu habis permintaan 10 detik.",
"ru": "Как только бот получает сообщение, он автоматически отправляет POST на сконфигурированный адрес Webhook, с временем ожидания запроса 10 секунд."
},
{
"key": "消息文本内容",
"zh": "",
"zh-CHT": "消息文本內容",
"en": "Message text content",
"ko": "메시지 텍스트 내용",
"ja": "メッセージテキスト内容",
"de": "Nachrichtentextinhalt",
"fr": "Contenu du texte du message",
"id": "Konten teks pesan",
"ru": "Содержимое текста сообщения"
},
{
"key": "留空自动生成",
"zh": "",
"zh-CHT": "留空自動生成",
"en": "Leave blank to auto-generate",
"ko": "자동 생성하려면 비워 두세요",
"ja": "空白にして自動生成",
"de": "Leer lassen, um automatisch zu generieren",
"fr": "Laisser vide pour générer automatiquement",
"id": "Biarkan kosong untuk menghasilkan otomatis",
"ru": "Оставьте пустым для автоматической генерации"
},
{
"key": "示例值",
"zh": "",
"zh-CHT": "示例值",
"en": "Example Value",
"ko": "예시 값",
"ja": "サンプル値",
"de": "Beispielwert",
"fr": "Valeur d'exemple",
"id": "Nilai contoh",
"ru": "Пример значения"
},
{
"key": "该机器人不支持",
"zh": "",
@ -30299,66 +30035,6 @@
"id": "Deskripsi",
"ru": "Описание"
},
{
"key": "请求参数",
"zh": "",
"zh-CHT": "請求參數",
"en": "Request Parameters",
"ko": "요청 매개변수",
"ja": "リクエストパラメータ",
"de": "Anforderungsparameter",
"fr": "Paramètres de requête",
"id": "Parameter permintaan",
"ru": "Параметры запроса"
},
{
"key": "请求头",
"zh": "",
"zh-CHT": "請求頭",
"en": "Request Headers",
"ko": "요청 헤더",
"ja": "リクエストヘッダー",
"de": "Anforderungsheader",
"fr": "En-têtes de requête",
"id": "Header permintaan",
"ru": "Заголовки запроса"
},
{
"key": "请求方式",
"zh": "",
"zh-CHT": "請求方式",
"en": "Request Method",
"ko": "요청 방법",
"ja": "リクエスト方法",
"de": "Anforderungsmethode",
"fr": "Méthode de requête",
"id": "Metode permintaan",
"ru": "Метод запроса"
},
{
"key": "通过机器人向指定对话发送文本消息",
"zh": "",
"zh-CHT": "通過機器人向指定對話發送文本消息",
"en": "Send a text message to a specific conversation through the bot",
"ko": "봇을 통해 특정 대화에 텍스트 메시지 보내기",
"ja": "ボットを通じて指定された会話にテキストメッセージを送信",
"de": "Senden Sie eine Textnachricht an ein bestimmtes Gespräch über den Bot",
"fr": "Envoyer un message texte à une conversation spécifique via le bot",
"id": "Kirim pesan teks ke percakapan tertentu melalui bot",
"ru": "Отправить текстовое сообщение в определенный разговор через бота"
},
{
"key": "静默模式",
"zh": "",
"zh-CHT": "靜默模式",
"en": "Silent Mode",
"ko": "무음 모드",
"ja": "サイレントモード",
"de": "Lautlos-Modus",
"fr": "Mode silencieux",
"id": "Mode senyap",
"ru": "Тихий режим"
},
{
"key": "属性",
"zh": "",
@ -32831,4 +32507,4 @@
"id": "Kelola",
"ru": "Управление"
}
]
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -81,7 +81,7 @@ import {languageName} from "../../../language";
import zhCN from '@kangc/v-md-editor/lib/lang/zh-CN';
import enUS from '@kangc/v-md-editor/lib/lang/en-US';
if (languageName === "zh" || languageName === "zh-CHT") {
if (/^zh/.test(languageName)) {
VMdEditor.lang.use('zh-CN', zhCN);
} else {
VMdEditor.lang.use('en-US', enUS);

View File

@ -24,7 +24,7 @@ import {languageName} from "../../../language";
import zhCN from '@kangc/v-md-editor/lib/lang/zh-CN';
import enUS from '@kangc/v-md-editor/lib/lang/en-US';
if (languageName === "zh" || languageName === "zh-CHT") {
if (/^zh/.test(languageName)) {
VMdPreview.lang.use('zh-CN', zhCN);
} else {
VMdPreview.lang.use('en-US', enUS);

View File

@ -1175,7 +1175,7 @@ export default {
// Load recorder
if (!this.disabledRecord) {
const i18nLang = languageName === "zh" || languageName === "zh-CHT" ? "zh-CN" : "en-US";
const i18nLang = /^zh/.test(languageName) ? "zh-CN" : "en-US";
$A.loadScriptS([
'js/recorder/recorder.mp3.min.js',
'js/recorder/lib.fft.js',

View File

@ -4,6 +4,7 @@
<script>
import DialogMarkdown from "../../DialogMarkdown.vue";
import {languageName} from "../../../../../language";
export default {
components: {DialogMarkdown},
@ -11,130 +12,357 @@ export default {
msg: Object,
},
data() {
return {};
return {
isChinese: /^zh/.test(languageName),
chineseTemplate: `
## API 使用说明
---
## 机器人主动发送消息
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">发送文本消息接口</span>
</summary>
<br>
**功能说明**开发者可以通过调用此API接口让机器人主动向指定的对话群组或私聊发送文本消息这是一个主动推送接口适用于机器人需要定时通知告警提醒等主动发送消息的场景
#### 接口信息
| 属性 | 结果 |
|------|------|
| **请求方式** | POST |
| **接口地址** | \`{{sendApiUrl}}\` |
| **认证方式** | 通过请求头中的 version token 进行认证 |
| **超时时间** | 30 |
#### 请求头
| 参数名 | | 必填 | 说明 |
|--------|-----|------|------|
| \`version\` | \`{{version}}\` | √ | 系统版本号 |
| \`token\` | 机器人Token | √ | 机器人的访问令牌,可在机器人设置中获取 |
#### 请求参数
| 参数名 | 说明 | 类型 | 必填 | 示例值 |
|--------|------|------|------|--------|
| \`dialog_id\` | 对话ID | string | √ | |
| \`text\` | 消息内容 | string | √ | |
| \`text_type\` | 文本类型 | string | | html 或 md |
| \`key\` | 消息唯一标识 | string | | 留空则自动生成 |
| \`silence\` | 静默模式 | string | | yes 或 no |
| \`reply_id\` | 回复消息ID | string | | |
</details>
---
## Webhook 事件推送
**功能说明**当特定事件发生时系统会自动向机器人配置的 Webhook 地址发送 POST 请求推送事件数据这是一个被动接收机制适用于机器人需要响应用户消息监听群组事件等场景
**重要提示**
- 请确保 Webhook 地址可正常访问且能在超时时间内响应
- 建议对推送的数据进行签名验证确保数据来源可信
- Webhook 接口应尽快返回响应200 OK复杂业务逻辑建议异步处理
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">接收消息事件<code>message</code></span>
</summary>
<br>
**触发时机**当机器人在对话中收到新消息时包括被@提及或私聊消息系统会自动推送到配置的 Webhook 地址
**超时时间**30
**使用场景**智能问答关键词回复消息记录自动客服等
#### 推送参数
| 参数名 | 说明 | 类型 |
|--------|------|------|
| \`event\` | 事件类型,固定值 \`message\` | string |
| \`text\` | 消息的文本内容 | string |
| \`reply_text\` | 如果是回复消息,则包含被回复消息的文本内容 | string |
| \`token\` | 机器人Token | string |
| \`session_id\` | 会话ID {{sessionDesc}} | string |
| \`dialog_id\` | 对话ID | string |
| \`dialog_type\` | 对话类型 | string |
| \`msg_id\` | 消息ID | string |
| \`msg_uid\` | 消息发送人的用户ID | string |
| \`msg_user\` | 消息发送人的详细信息(昵称、头像等) | object |
| \`mention\` | 机器人是否被@提及 | boolean |
| \`bot_uid\` | 机器人ID | string |
| \`version\` | 系统版本 | string |
</details>
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">打开会话事件<code>dialog_open</code></span>
</summary>
<br>
**触发时机**当用户打开与机器人的会话窗口时首次打开或重新进入系统会推送此事件
**超时时间**10
**使用场景**欢迎语菜单展示会话初始化用户行为统计等
#### 推送参数
| 参数名 | 说明 | 类型 |
|--------|------|------|
| \`event\` | 事件类型,固定值 \`dialog_open\` | string |
| \`dialog_id\` | 对话ID | number |
| \`dialog_type\` | 对话类型 | string |
| \`group_type\` | 群组类型(仅群组对话时有值) | string |
| \`dialog_name\` | 对话名称(群组名称或用户昵称) | string |
| \`member\` | 打开会话的成员信息 | object |
| \`operator\` | 操作人信息(通常与 member 相同) | object |
</details>
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">成员加入事件<code>member_join</code></span>
</summary>
<br>
**触发时机**当新成员加入机器人所在的群组时系统会推送此事件
**超时时间**10
**使用场景**新成员欢迎语群规则提醒自动分配权限成员统计等
#### 推送参数
| 参数名 | 说明 | 类型 |
|--------|------|------|
| \`event\` | 事件类型,固定值 \`member_join\` | string |
| \`dialog_id\` | 群组对话ID | number |
| \`dialog_type\` | 对话类型,此处固定为 \`group\` | string |
| \`group_type\` | 群组类型 | string |
| \`dialog_name\` | 群组名称 | string |
| \`member\` | 加入的成员信息昵称、ID等 | object |
| \`operator\` | 操作人信息(邀请人,如果是自己加入则与 member 相同) | object |
</details>
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">成员退出事件<code>member_leave</code></span>
</summary>
<br>
**触发时机**当成员退出或被移出机器人所在的群组时系统会推送此事件
**超时时间**10
**使用场景**成员变动记录权限清理离职提醒成员统计等
#### 推送参数
| 参数名 | 说明 | 类型 |
|--------|------|------|
| \`event\` | 事件类型,固定值 \`member_leave\` | string |
| \`dialog_id\` | 群组对话ID | number |
| \`dialog_type\` | 对话类型,此处固定为 \`group\` | string |
| \`group_type\` | 群组类型 | string |
| \`dialog_name\` | 群组名称 | string |
| \`member\` | 退出的成员信息昵称、ID等 | object |
| \`operator\` | 操作人信息(踢出者,如果是自己退出则与 member 相同) | object |
</details>
---
**提示**请妥善保管机器人 Token确保 Webhook 接口稳定可用并及时响应更多帮助请发送 <span class="mark-color mark-set">/help</span> 命令查看
`,
englishTemplate: `
## API Documentation
---
## 1. Bot Proactive Message Sending
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">Send Text Message API</span>
</summary>
<br>
**Description**: Developers can call this API to allow the bot to proactively send text messages to specified conversations (groups or private chats). This is a proactive push interface, suitable for scenarios where the bot needs to send scheduled notifications, alerts, and other proactive messages.
#### API Information
| Property | Value |
|------|------|
| **Request Method** | POST |
| **API Endpoint** | \`{{sendApiUrl}}\` |
| **Authentication** | Authenticate via version and token in request headers |
| **Timeout** | 30 seconds |
#### Request Headers
| Parameter | Value | Required | Description |
|--------|-----|------|------|
| \`version\` | \`{{version}}\` | √ | System version number |
| \`token\` | Bot Token | √ | Bot access token, available in bot settings |
#### Request Parameters
| Parameter | Description | Type | Required | Example |
|--------|------|------|------|--------|
| \`dialog_id\` | Dialog ID | string | √ | |
| \`text\` | Message content | string | √ | |
| \`text_type\` | Text type | string | | html or md |
| \`key\` | Unique message identifier | string | | Auto-generated if left empty |
| \`silence\` | Silent mode | string | | yes or no |
| \`reply_id\` | Reply message ID | string | | |
</details>
---
## 2. Webhook Event Push
**Description**: When specific events occur, the system will automatically send POST requests to the Webhook URL configured for the bot, pushing event data. This is a passive receiving mechanism, suitable for scenarios where the bot needs to respond to user messages, monitor group events, etc.
**Important Notes**:
- Ensure the Webhook URL is accessible and can respond within the timeout period
- Recommend verifying the signature of pushed data to ensure the source is trustworthy
- Webhook interface should return a response (200 OK) as quickly as possible; complex business logic should be handled asynchronously
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">Message Received Event (<code>message</code>)</span>
</summary>
<br>
**Trigger Timing**: When the bot receives a new message in a conversation (including being @mentioned or private messages), the system will automatically push to the configured Webhook URL.
**Timeout**: 30 seconds
**Use Cases**: Intelligent Q&A, keyword replies, message logging, automatic customer service, etc.
#### Push Parameters
| Parameter | Description | Type |
|--------|------|------|
| \`event\` | Event type, fixed value \`message\` | string |
| \`text\` | Text content of the message | string |
| \`reply_text\` | If it's a reply message, contains the text content of the replied message | string |
| \`token\` | Bot Token | string |
| \`session_id\` | Session ID {{sessionDesc}} | string |
| \`dialog_id\` | Dialog ID | string |
| \`dialog_type\` | Dialog type | string |
| \`msg_id\` | Message ID | string |
| \`msg_uid\` | User ID of message sender | string |
| \`msg_user\` | Detailed information of message sender (nickname, avatar, etc.) | object |
| \`mention\` | Whether the bot was @mentioned | boolean |
| \`bot_uid\` | Bot ID | string |
| \`version\` | System version | string |
</details>
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">Dialog Open Event (<code>dialog_open</code>)</span>
</summary>
<br>
**Trigger Timing**: When a user opens a conversation window with the bot (first time or re-entry), the system will push this event.
**Timeout**: 10 seconds
**Use Cases**: Welcome messages, menu display, session initialization, user behavior statistics, etc.
#### Push Parameters
| Parameter | Description | Type |
|--------|------|------|
| \`event\` | Event type, fixed value \`dialog_open\` | string |
| \`dialog_id\` | Dialog ID | number |
| \`dialog_type\` | Dialog type | string |
| \`group_type\` | Group type (only for group conversations) | string |
| \`dialog_name\` | Dialog name (group name or user nickname) | string |
| \`member\` | Information of member opening the session | object |
| \`operator\` | Operator information (usually same as member) | object |
</details>
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">Member Join Event (<code>member_join</code>)</span>
</summary>
<br>
**Trigger Timing**: When a new member joins a group where the bot is present, the system will push this event.
**Timeout**: 10 seconds
**Use Cases**: New member welcome messages, group rules reminders, automatic permission assignment, member statistics, etc.
#### Push Parameters
| Parameter | Description | Type |
|--------|------|------|
| \`event\` | Event type, fixed value \`member_join\` | string |
| \`dialog_id\` | Group dialog ID | number |
| \`dialog_type\` | Dialog type, fixed as \`group\` | string |
| \`group_type\` | Group type | string |
| \`dialog_name\` | Group name | string |
| \`member\` | Information of joining member (nickname, ID, etc.) | object |
| \`operator\` | Operator information (inviter, same as member if self-joined) | object |
</details>
<details>
<summary>
<span style="font-size:1.25em;font-weight:bold;padding-left:8px">Member Leave Event (<code>member_leave</code>)</span>
</summary>
<br>
**Trigger Timing**: When a member leaves or is removed from a group where the bot is present, the system will push this event.
**Timeout**: 10 seconds
**Use Cases**: Member change records, permission cleanup, departure reminders, member statistics, etc.
#### Push Parameters
| Parameter | Description | Type |
|--------|------|------|
| \`event\` | Event type, fixed value \`member_leave\` | string |
| \`dialog_id\` | Group dialog ID | number |
| \`dialog_type\` | Dialog type, fixed as \`group\` | string |
| \`group_type\` | Group type | string |
| \`dialog_name\` | Group name | string |
| \`member\` | Information of leaving member (nickname, ID, etc.) | object |
| \`operator\` | Operator information (remover, same as member if self-left) | object |
</details>
---
**Tip**: Please keep the bot Token secure, ensure the Webhook interface is stable and responds promptly. For more help, send the <span class="mark-color mark-set">/help</span> command.
`,
};
},
computed: {
content() {
const sessionDesc = !/^(ai-|user-session-)/.test(this.msg.email) ? " <span style='color:#999;padding-left:4px;'>({{该机器人不支持}})</span>" : "";
return [
"## {{API 使用说明}}",
"",
"### 1. {{发送文本消息}}",
"",
"{{开发者可以通过此接口调用机器人向指定对话发送文本消息。}}",
"",
"#### {{接口信息}}",
"",
"| {{属性}} | {{结果}} |",
"|------|------|",
"| **{{请求方式}}** | POST |",
"| **{{接口地址}}** | `" + $A.apiUrl('dialog/msg/sendtext') + "` |",
"| **{{说明}}** | {{通过机器人向指定对话发送文本消息}} |",
"",
"#### {{请求头}}",
"",
"| {{参数名}} | {{值}} | {{必填}} |",
"|--------|-----|------|",
"| `version` | `" + this.msg.version + "` | √ |",
"| `token` | {{机器人Token}} | √ |",
"",
"#### {{请求参数}}",
"",
"| {{参数名}} | {{说明}} | {{类型}} | {{必填}} | {{示例值}} |",
"|--------|------|------|------|--------|",
"| `dialog_id` | {{对话ID}} | string | √ | |",
"| `text` | {{消息内容}} | string | √ | |",
"| `text_type` | {{文本类型}} | string | | {{html 或 md}} |",
"| `key` | {{搜索词}} | string | | {{留空自动生成}} |",
"| `silence` | {{静默模式}} | string | | {{yes 或 no}} |",
"| `reply_id` | {{回复指定消息ID}} | string | | |",
"",
"### 2. {{Webhook 消息推送}}",
"",
"{{机器人收到消息后会自动POST推送到配置的Webhook地址请求超时为10秒。}}",
"",
"#### {{推送参数}}",
"",
"| {{参数名}} | {{说明}} | {{类型}} |",
"|--------|------|------|",
"| `text` | {{消息文本内容}} | string |",
"| `reply_text` | {{回复/引用的消息文本}} | string |",
"| `token` | {{机器人Token}} | string |",
"| `session_id` | {{会话ID}}" + sessionDesc + " | string |",
"| `dialog_id` | {{对话ID}} | string |",
"| `dialog_type` | {{对话类型}} | string |",
"| `msg_id` | {{消息ID}} | string |",
"| `msg_uid` | {{消息发送人ID}} | string |",
"| `msg_user` | {{消息发送人信息}} | object |",
"| `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");
const variables = {
sendApiUrl: $A.apiUrl('dialog/msg/sendtext'),
version: this.msg.version,
sessionDesc: !/^(ai-|user-session-)/.test(this.msg.email) ? ` <span style='color:#999;padding-left:4px;'>(${this.$L('该机器人不支持')})</span>` : ``,
};
const template = this.isChinese ? this.chineseTemplate : this.englishTemplate;
return template.replace(/\{\{([^}]+)\}\}/g, (_, v1) => variables[v1] || v1).trim();
},
},
methods: {},
}
</script>
</script>

View File

@ -1241,8 +1241,7 @@ export default {
this.getDialogBase(dialog_id)
this.generateUnreadData(old_id)
//
this.$store.dispatch('openDialogWebhook', dialog_id)
//
this.$store.dispatch('openDialogEvent', dialog_id)
this.$store.dispatch('closeDialog', {id: old_id})
//
window.localStorage.removeItem('__cache:vote__')

View File

@ -6,7 +6,7 @@ import {languageName} from "../language";
export default {
mounted() {
if (languageName === "zh" || languageName === "zh-CHT") {
if (/^zh/.test(languageName)) {
window.location.href = $A.mainUrl("site/zh/price.html")
} else {
window.location.href = $A.mainUrl("site/en/price.html")

View File

@ -3514,35 +3514,6 @@ export default {
})
},
/**
* 打开会话打开机器人会话推送 webhook
* @param state
* @param dispatch
* @param dialogId
* @returns {Promise<unknown>}
*/
openDialogWebhook({state, dispatch}, dialogId) {
return new Promise((resolve, reject) => {
const dialog = state.cacheDialogs.find(item => {
if (item.type !== 'user') {
return false
}
return item.id === dialogId
});
if (dialog && dialog.bot === 1) {
dispatch("call", {
url: 'dialog/open/webhook',
data: {
dialog_id: dialogId,
},
}).catch(e => {
console.warn(e);
reject(e);
})
}
});
},
/**
* 打开会话通过会员ID打开个人会话
* @param state
@ -3576,6 +3547,31 @@ export default {
});
},
/**
* 打开会话事件
* @param state
* @param dispatch
* @param dialogId
* @returns {Promise<unknown>}
*/
openDialogEvent({state, dispatch}, dialogId) {
return new Promise((resolve, reject) => {
if (!dialogId) {
reject({msg: 'Parameter error'});
return;
}
dispatch("call", {
url: 'dialog/open/event',
data: {
dialog_id: dialogId,
},
}).catch(e => {
console.warn(e);
reject(e);
})
});
},
/**
* 打开会话客户端新窗口
* @param state