perf: 支持通过接口发送通知和模板消息

This commit is contained in:
kuaifan 2024-12-03 13:53:34 +08:00
parent 96c64fbb91
commit 76bf46c152
5 changed files with 146 additions and 14 deletions

View File

@ -960,10 +960,10 @@ class DialogController extends AbstractController
* @apiGroup dialog
* @apiName msg__stream
*
* @apiParam {String} [source] 消息来源
* - ai: 默认
* @apiParam {Number} userid 通知会员ID
* @apiParam {String} stream_url 流动消息地址
* @apiParam {String} [source] 消息来源
* - api: 默认
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
@ -973,12 +973,15 @@ class DialogController extends AbstractController
{
$userid = intval(Request::input('userid'));
$stream_url = trim(Request::input('stream_url'));
$source = trim(Request::input('source', 'api'));
//
if ($userid <= 0) {
return Base::retError('参数错误');
}
//
if ($source === 'ai') {
$stream_url = '/ai' . preg_replace('/^\/ai\/?/', '/', $stream_url);
}
//
$params = [
'userid' => $userid,
@ -1001,7 +1004,8 @@ class DialogController extends AbstractController
* @apiGroup dialog
* @apiName msg__sendtext
*
* @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} dialog_id 对话ID存在dialog_ids时无效
* @apiParam {String} [dialog_ids] 对话ID列表多个对话ID用逗号分隔
* @apiParam {String} text 消息内容
* @apiParam {String} [key] 搜索关键词 (不设置根据内容自动生成)
* @apiParam {String} [text_type] 消息类型
@ -1099,6 +1103,128 @@ class DialogController extends AbstractController
return $result;
}
/**
* @api {post} api/dialog/msg/sendnotice 21. 发送通知
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__sendnotice
*
* @apiParam {Number} dialog_id 对话ID存在dialog_ids时无效
* @apiParam {String} [dialog_ids] 对话ID列表多个对话ID用逗号分隔
* @apiParam {String} notice 通知内容最长500字
* @apiParam {String} [silence] 是否静默发送
* - no: 正常发送(默认)
* - yes: 静默发送
* @apiParam {String} [source] 消息来源
* - api: 默认
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__sendnotice()
{
$user = User::auth();
$user->checkChatInformation();
//
$dialog_id = intval(Request::input('dialog_id'));
$dialog_ids = trim(Request::input('dialog_ids'));
$notice = trim(Request::input('notice'));
$silence = in_array(strtolower(trim(Request::input('silence'))), ['yes', 'true', '1']);
$source = trim(Request::input('source', 'api'));
//
$strlen = mb_strlen($notice);
if ($strlen < 1) {
return Base::retError('通知内容不能为空');
}
if ($strlen > 500) {
return Base::retError('通知内容最大不能超过500字');
}
//
$result = [];
$dialogIds = $dialog_ids ? explode(',', $dialog_ids) : [$dialog_id ?: 0];
foreach ($dialogIds as $dialog_id) {
WebSocketDialog::checkDialog($dialog_id);
//
$result = WebSocketDialogMsg::sendMsg(null, $dialog_id, 'notice', [
'notice' => $notice,
'source' => $source
], $user->userid, false, false, $silence);
}
return $result;
}
/**
* @api {post} api/dialog/msg/sendtemplate 21. 发送模板消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__sendtemplate
*
* @apiParam {Number} dialog_id 对话ID存在dialog_ids时无效
* @apiParam {String} [dialog_ids] 对话ID列表多个对话ID用逗号分隔
* @apiParam {String} content 模板消息JSON格式
* - 格式:[{content:内容(最长300个字), style:样式(最长300个字)}, ...]
* @apiParam {String} [title] 模板标题(留空从模板消息第一个内容提取)
* @apiParam {String} [silence] 是否静默发送
* - no: 正常发送(默认)
* - yes: 静默发送
* @apiParam {String} [source] 消息来源
* - api: 默认
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__sendtemplate()
{
$user = User::auth();
$user->checkChatInformation();
//
$dialog_id = intval(Request::input('dialog_id'));
$dialog_ids = trim(Request::input('dialog_ids'));
$content = Base::json2array(Request::input('content'));
$title = trim(Request::input('title'));
$silence = in_array(strtolower(trim(Request::input('silence'))), ['yes', 'true', '1']);
$source = trim(Request::input('source', 'api'));
//
if (empty($content)) {
return Base::retError('模板内容不能为空');
}
foreach ($content as $item) {
$contentLength = mb_strlen($item['content']);
if ($contentLength < 1) {
return Base::retError('模板消息内容至少需要1个字');
}
if ($contentLength > 300) {
return Base::retError('模板消息内容最多不能超过300个字');
}
if (mb_strlen($item['style']) > 300) {
return Base::retError('模板消息样式过长');
}
if (empty($title)) {
$title = Base::cutStr($item['content'], 50);
}
}
//
$result = [];
$dialogIds = $dialog_ids ? explode(',', $dialog_ids) : [$dialog_id ?: 0];
foreach ($dialogIds as $dialog_id) {
WebSocketDialog::checkDialog($dialog_id);
//
$result = WebSocketDialogMsg::sendMsg(null, $dialog_id, 'template', [
'type' => 'content',
'title' => $title,
'content' => $content,
'source' => $source
], $user->userid, false, false, $silence);
}
return $result;
}
/**
* @api {post} api/dialog/msg/sendrecord 22. 发送语音
*

View File

@ -610,7 +610,8 @@ class WebSocketDialogMsg extends AbstractModel
return "[{$action}] " . self::previewMsg($data['msg']['data']);
case 'notice':
return Base::cutStr(Doo::translate($data['msg']['notice']), 50);
$notice = $data['msg']['source'] === 'api' ? $data['msg']['notice'] : Doo::translate($data['msg']['notice']);
return Base::cutStr($notice, 50);
case 'template':
return self::previewTemplateMsg($data['msg']);
@ -679,13 +680,15 @@ class WebSocketDialogMsg extends AbstractModel
return $msg['title_raw'];
}
if ($msg['type'] === 'task_list' && count($msg['list']) === 1) {
return Doo::translate($msg['title']) . ": " . Base::cutStr($msg['list'][0]['name'], 50);
$title = $msg['source'] === 'api' ? $msg['title'] : Doo::translate($msg['title']);
return $title . ": " . Base::cutStr($msg['list'][0]['name'], 50);
}
if (!empty($msg['title'])) {
return Doo::translate($msg['title']);
return $msg['source'] === 'api' ? $msg['title'] : Doo::translate($msg['title']);
}
if ($msg['type'] === 'content' && is_string($msg['content']) && $msg['content'] !== '') {
return Base::cutStr(Doo::translate($msg['content']), 50);
$content = $msg['source'] === 'api' ? $msg['content'] : Doo::translate($msg['content']);
return Base::cutStr($content, 50);
}
return Doo::translate('未知的消息');
}

View File

@ -420,7 +420,8 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
case 'todo':
return `[${$A.L(data.msg.action === 'remove' ? '取消待办' : (data.msg.action === 'done' ? '完成' : '设待办'))}] ${$A.getMsgSimpleDesc(data.msg.data)}`
case 'notice':
return $A.cutString($A.L(data.msg.notice), 50)
const notice = data.msg.source === 'api' ? data.msg.notice : $A.L(data.msg.notice);
return $A.cutString(notice, 50)
case 'template':
return $A.templateMsgSimpleDesc(data.msg)
case 'preview':
@ -466,13 +467,15 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
return msg.title_raw
}
if (msg.type === 'task_list' && $A.arrayLength(msg.list) === 1) {
return $A.L(msg.title) + ": " + $A.cutString(msg.list[0].name, 50)
const title = msg.source === 'api' ? msg.title : $A.L(msg.title)
return title + ": " + $A.cutString(msg.list[0].name, 50)
}
if (msg.title) {
return $A.L(msg.title)
return msg.source === 'api' ? msg.title : $A.L(msg.title)
}
if (msg.type === 'content' && typeof msg.content === 'string' && msg.content !== '') {
return $A.cutString($A.L(msg.content), 50)
const content = msg.source === 'api' ? msg.content : $A.L(msg.content)
return $A.cutString(content, 50)
}
return $A.L('未知的消息')
},

View File

@ -26,7 +26,7 @@
</div>
</div>
<div v-else-if="source.type === 'notice'" class="dialog-notice">
{{$L(source.msg.notice)}}
{{source.msg.source === 'api' ? source.msg.notice : $L(source.msg.notice)}}
</div>
<template v-else>
<div class="dialog-avatar">

View File

@ -25,7 +25,7 @@ export default {
formatContent(item) {
if ($A.isJson(item)) {
return {
content: item.language === false ? item.content : this.$L(item.content),
content: item.language === false || this.msg.source === 'api' ? item.content : this.$L(item.content),
style: item.style || {},
};
}