dootask/app/Http/Controllers/Api/DialogController.php
2022-09-18 21:26:16 +08:00

1379 lines
48 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers\Api;
use App\Models\File;
use App\Models\FileContent;
use App\Models\ProjectTask;
use App\Models\ProjectTaskFile;
use App\Models\User;
use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogMsg;
use App\Models\WebSocketDialogMsgRead;
use App\Models\WebSocketDialogMsgTodo;
use App\Models\WebSocketDialogUser;
use App\Module\Base;
use Carbon\Carbon;
use DB;
use Redirect;
use Request;
use Response;
/**
* @apiDefine dialog
*
* 对话
*/
class DialogController extends AbstractController
{
/**
* @api {get} api/dialog/lists 01. 对话列表
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName lists
*
* @apiParam {String} [at_after] 只读取在这个时间之后更新的对话
* @apiParam {Number} [page] 当前页,默认:1
* @apiParam {Number} [pagesize] 每页显示数量,默认:100最大:200
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function lists()
{
$user = User::auth();
//
$builder = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('u.userid', $user->userid);
if (Request::exists('at_after')) {
$builder->where('web_socket_dialogs.last_at', '>', Carbon::parse(Request::input('at_after')));
}
$list = $builder
->orderByDesc('u.top_at')
->orderByDesc('web_socket_dialogs.last_at')
->paginate(Base::getPaginate(200, 100));
$list->transform(function (WebSocketDialog $item) use ($user) {
return $item->formatData($user->userid);
});
//
return Base::retSuccess('success', $list);
}
/**
* @api {get} api/dialog/search 02. 搜索会话
*
* @apiDescription 根据消息关键词搜索相关会话需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName search
*
* @apiParam {String} key 消息关键词
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function search()
{
$user = User::auth();
//
$key = trim(Request::input('key'));
if (empty($key)) {
return Base::retError('请输入搜索关键词');
}
//
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('web_socket_dialogs.name', 'LIKE', "%{$key}%")
->where('u.userid', $user->userid)
->orderByDesc('u.top_at')
->orderByDesc('web_socket_dialogs.last_at')
->take(20)
->get();
$list->transform(function (WebSocketDialog $item) use ($user) {
return $item->formatData($user->userid);
});
if (count($list) < 20) {
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'm.id as search_msg_id'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id')
->where('u.userid', $user->userid)
->where('m.key', 'LIKE', "%{$key}%")
->orderByDesc('m.id')
->take(20 - count($list))
->get();
$msgs->transform(function (WebSocketDialog $item) use ($user) {
return $item->formatData($user->userid);
});
$list = array_merge($list->toArray(), $msgs->toArray());
}
//
return Base::retSuccess('success', $list);
}
/**
* @api {get} api/dialog/one 03. 获取单个会话信息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName one
*
* @apiParam {Number} dialog_id 对话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function one()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
//
$item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('web_socket_dialogs.id', $dialog_id)
->where('u.userid', $user->userid)
->first();
if (empty($item)) {
return Base::retError('会话不存在或已被删除', ['dialog_id' => $dialog_id], -4003);
}
return Base::retSuccess('success', $item->formatData($user->userid));
}
/**
* @api {get} api/dialog/user 04. 获取会话成员
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName user
*
* @apiParam {Number} dialog_id 会话ID
* @apiParam {Number} [getuser] 获取会员详情1: 返回会员昵称、邮箱等基本信息0: 默认不返回)
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function user()
{
User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$getuser = intval(Request::input('getuser', 0));
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
//
$data = $dialog->dialogUser->toArray();
if ($getuser === 1) {
$array = [];
foreach ($data as $item) {
$res = User::userid2basic($item['userid']);
if ($res) {
$array[] = array_merge($item, $res->toArray());
}
}
$data = $array;
}
//
$array = [];
foreach ($data as $item) {
if ($item['userid'] > 0) {
$array[] = $item;
}
}
return Base::retSuccess('success', $array);
}
/**
* @api {get} api/dialog/todo 05. 获取会话待办
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName todo
*
* @apiParam {Number} dialog_id 会话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function todo()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
//
WebSocketDialog::checkDialog($dialog_id);
//
$list = WebSocketDialogMsgTodo::whereDialogId($dialog_id)->whereUserid($user->userid)->whereDoneAt(null)->orderByDesc('id')->take(50)->get();
return Base::retSuccess("success", $list);
}
/**
* @api {get} api/dialog/top 06. 会话置顶
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName top
*
* @apiParam {Number} dialog_id 会话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function top()
{
$user = User::auth();
$dialogId = intval(Request::input('dialog_id'));
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
if (!$dialogUser) {
return Base::retError("会话不存在");
}
$dialogUser->top_at = $dialogUser->top_at ? null : Carbon::now();
$dialogUser->save();
return Base::retSuccess("success", [
'id' => $dialogUser->dialog_id,
'top_at' => $dialogUser->top_at?->toDateTimeString(),
]);
}
/**
* @api {get} api/dialog/tel 07. 获取对方联系电话
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName tel
*
* @apiParam {Number} dialog_id 会话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function tel()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
if ($dialog->type !== 'user') {
return Base::retError("会话类型错误");
}
$dialogUser = $dialog->dialogUser->where('userid', '!=', $user->userid)->first();
if (empty($dialogUser)) {
return Base::retError("会话对象不存在");
}
$callUser = User::find($dialogUser->userid);
if (empty($callUser) || empty($callUser->tel)) {
return Base::retError("对方未设置联系电话");
}
//
$add = null;
$res = WebSocketDialogMsg::sendMsg(null, $dialog->id, 'notice', [
'notice' => $user->nickname . " 查看了 " . $callUser->nickname . " 的联系电话"
]);
if (Base::isSuccess($res)) {
$add = $res['data'];
}
//
return Base::retSuccess("success", [
'tel' => $callUser->tel,
'add' => $add ?: null
]);
}
/**
* @api {get} api/dialog/open/user 08. 打开会话
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName open__user
*
* @apiParam {Number} userid 对话会员ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function open__user()
{
$user = User::auth();
//
$userid = intval(Request::input('userid'));
if (empty($userid)) {
return Base::retError('错误的会话');
}
//
$dialog = WebSocketDialog::checkUserDialog($user->userid, $userid);
if (empty($dialog)) {
return Base::retError('打开会话失败');
}
$data = WebSocketDialog::find($dialog->id)?->formatData($user->userid);
return Base::retSuccess('success', $data);
}
/**
* @api {get} api/dialog/msg/list 09. 获取消息列表
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__list
*
* @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} msg_id 消息ID
* @apiParam {Number} [position_id] 此消息ID前后的数据
* @apiParam {Number} [prev_id] 此消息ID之前的数据
* @apiParam {Number} [next_id] 此消息ID之后的数据
* - position_id、prev_id、next_id 只有一个有效优先循序为position_id > prev_id > next_id
* @apiParam {String} [msg_type] 消息类型
* - tag: 标记
* - link: 链接
* - text: 文本
* - image: 图片
* - file: 文件
* - record: 录音
* - meeting: 会议
*
* @apiParam {Number} [take] 获取条数,默认:50最大:100
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__list()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$msg_id = intval(Request::input('msg_id'));
$position_id = intval(Request::input('position_id'));
$prev_id = intval(Request::input('prev_id'));
$next_id = intval(Request::input('next_id'));
$msg_type = trim(Request::input('msg_type'));
$take = Base::getPaginate(100, 50, 'take');
$data = [];
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
$reDialog = true;
//
$builder = WebSocketDialogMsg::select([
'web_socket_dialog_msgs.*',
'read.mention',
'read.read_at',
])->leftJoin('web_socket_dialog_msg_reads as read', function ($leftJoin) use ($user) {
$leftJoin
->on('read.userid', '=', DB::raw($user->userid))
->on('read.msg_id', '=', 'web_socket_dialog_msgs.id');
})->where('web_socket_dialog_msgs.dialog_id', $dialog_id);
//
if ($msg_type) {
if ($msg_type === 'tag') {
$builder->where('tag', '>', 0);
} elseif ($msg_type === 'link') {
$builder->whereLink(1);
} elseif (in_array($msg_type, ['text', 'image', 'file', 'record', 'meeting'])) {
$builder->whereMtype($msg_type);
} else {
return Base::retError('参数错误');
}
$reDialog = false;
}
if ($msg_id > 0) {
$builder->whereReplyId($msg_id);
$reDialog = false;
}
//
if ($position_id > 0) {
$array = $builder->clone()
->where('web_socket_dialog_msgs.id', '>=', $position_id)
->orderBy('web_socket_dialog_msgs.id')
->take(intval($take / 2))
->get();
$prev_id = intval($array->last()?->id);
}
//
$cloner = $builder->clone();
if ($prev_id > 0) {
$cloner->where('web_socket_dialog_msgs.id', '<=', $prev_id)->orderByDesc('web_socket_dialog_msgs.id');
$reDialog = false;
} elseif ($next_id > 0) {
$cloner->where('web_socket_dialog_msgs.id', '>=', $next_id)->orderBy('web_socket_dialog_msgs.id');
$reDialog = false;
} else {
$cloner->orderByDesc('web_socket_dialog_msgs.id');
}
$list = $cloner->take($take)->get()->sortByDesc('id', SORT_NUMERIC)->values();
//
if ($list->isNotEmpty()) {
$list->transform(function (WebSocketDialogMsg $item) {
$item->next_id = 0;
$item->prev_id = 0;
return $item;
});
$first = $list->first();
$first->next_id = intval($builder->clone()
->where('web_socket_dialog_msgs.id', '>', $first->id)
->orderBy('web_socket_dialog_msgs.id')
->value('id'));
$last = $list->last();
$last->prev_id = intval($builder->clone()
->where('web_socket_dialog_msgs.id', '<', $last->id)
->orderByDesc('web_socket_dialog_msgs.id')
->value('id'));
}
$data['list'] = $list;
// 记录当前打开的任务对话
if ($dialog->type == 'group' && $dialog->group_type == 'task') {
$user->task_dialog_id = $dialog->id;
$user->save();
}
// 去掉标记未读
$isMarkDialogUser = WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($user->userid)->whereMarkUnread(1)->first();
if ($isMarkDialogUser) {
$isMarkDialogUser->mark_unread = 0;
$isMarkDialogUser->save();
}
//
if ($reDialog) {
$data['dialog'] = $dialog->formatData($user->userid, true);
$data['todo'] = $data['dialog']->todo_num > 0 ? WebSocketDialogMsgTodo::whereDialogId($dialog->id)->whereUserid($user->userid)->whereDoneAt(null)->orderByDesc('id')->take(50)->get() : [];
}
return Base::retSuccess('success', $data);
}
/**
* @api {get} api/dialog/msg/one 10. 获取单条消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__one
*
* @apiParam {Number} msg_id 消息ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__one()
{
User::auth();
//
$msg_id = intval(Request::input('msg_id'));
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
WebSocketDialog::checkDialog($msg->dialog_id);
//
return Base::retSuccess('success', $msg);
}
/**
* @api {get} api/dialog/msg/read 11. 标记已读
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__read
*
* @apiParam {Number} id 消息ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__read()
{
$user = User::auth();
//
$id = Request::input('id');
$ids = Base::arrayRetainInt(is_array($id) ? $id : Base::explodeInt($id));
//
WebSocketDialogMsg::whereIn('id', $ids)->chunkById(20, function($list) use ($user) {
/** @var WebSocketDialogMsg $item */
foreach ($list as $item) {
$item->readSuccess($user->userid);
}
});
return Base::retSuccess('success');
}
/**
* @api {get} api/dialog/msg/unread 12. 获取未读消息数量
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__unread
*
* @apiParam {Number} [dialog_id] 对话ID留空获取总未读消息数量
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
* @apiSuccessExample {json} data:
{
"unread": 43, // 未读消息数
"last_umid": 308 // 最新的一条未读消息ID用于判断是否更新前端的未读数量
}
*/
public function msg__unread()
{
$dialog_id = intval(Request::input('dialog_id'));
//
$builder = WebSocketDialogMsgRead::whereUserid(User::userid())->whereReadAt(null);
if ($dialog_id > 0) {
$builder->whereDialogId($dialog_id);
}
return Base::retSuccess('success', [
'unread' => $builder->count(),
'last_umid' => intval($builder->orderByDesc('msg_id')->value('msg_id')),
]);
}
/**
* @api {post} api/dialog/msg/sendtext 13. 发送消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__sendtext
*
* @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} [update_id] 更新消息ID优先大于reply_id
* @apiParam {Number} [reply_id] 回复ID
* @apiParam {String} text 消息内容
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__sendtext()
{
Base::checkClientVersion('0.19.0');
$user = User::auth();
//
$chat_information = Base::settingFind('system', 'chat_information');
if ($chat_information == 'required') {
if (empty($user->getRawOriginal('nickname'))) {
return Base::retError('请设置昵称', [], -2);
}
if (empty($user->getRawOriginal('tel'))) {
return Base::retError('请设置联系电话', [], -3);
}
}
//
$dialog_id = Base::getPostInt('dialog_id');
$update_id = Base::getPostInt('update_id');
$reply_id = Base::getPostInt('reply_id');
$text = trim(Base::getPostValue('text'));
//
WebSocketDialog::checkDialog($dialog_id);
//
if ($update_id > 0) {
$action = "update-$update_id";
} elseif ($reply_id > 0) {
$action = "reply-$reply_id";
} else {
$action = "";
}
//
$text = WebSocketDialogMsg::formatMsg($text, $dialog_id);
$strlen = mb_strlen($text);
if ($strlen < 1) {
return Base::retError('消息内容不能为空');
} elseif ($strlen > 200000) {
return Base::retError('消息内容最大不能超过200000字');
}
if ($strlen > 2000) {
// 内容过长转成文件发送
$path = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/";
Base::makeDir(public_path($path));
$path = $path . md5($text) . ".htm";
$file = public_path($path);
file_put_contents($file, $text);
$size = filesize(public_path($path));
if (empty($size)) {
return Base::retError('消息发送保存失败');
}
$fileData = [
'name' => "LongText-{$strlen}.htm",
'size' => $size,
'file' => $file,
'path' => $path,
'url' => Base::fillUrl($path),
'thumb' => '',
'width' => -1,
'height' => -1,
'ext' => 'htm',
];
return WebSocketDialogMsg::sendMsg($action, $dialog_id, 'file', $fileData, $user->userid);
}
//
return WebSocketDialogMsg::sendMsg($action, $dialog_id, 'text', ['text' => $text], $user->userid);
}
/**
* @api {post} api/dialog/msg/sendrecord 14. 发送语音
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__sendrecord
*
* @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} [reply_id] 回复ID
* @apiParam {String} base64 语音base64
* @apiParam {Number} duration 语音时长(毫秒)
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__sendrecord()
{
$user = User::auth();
//
$dialog_id = Base::getPostInt('dialog_id');
$reply_id = Base::getPostInt('reply_id');
//
WebSocketDialog::checkDialog($dialog_id);
//
$action = $reply_id > 0 ? "reply-$reply_id" : "";
$path = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/";
$base64 = Base::getPostValue('base64');
$duration = Base::getPostInt('duration');
if ($duration < 600) {
return Base::retError('说话时间太短');
}
$data = Base::record64save([
"base64" => $base64,
"path" => $path,
]);
if (Base::isError($data)) {
return Base::retError($data['msg']);
} else {
$recordData = $data['data'];
$recordData['size'] *= 1024;
$recordData['duration'] = $duration;
return WebSocketDialogMsg::sendMsg($action, $dialog_id, 'record', $recordData, $user->userid);
}
}
/**
* @api {post} api/dialog/msg/sendfile 15. 文件上传
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__sendfile
*
* @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} [reply_id] 回复ID
* @apiParam {Number} [image_attachment] 图片是否也存到附件
* @apiParam {String} [filename] post-文件名称
* @apiParam {String} [image64] post-base64图片二选一
* @apiParam {File} [files] post-文件对象(二选一)
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__sendfile()
{
$user = User::auth();
//
$dialog_id = Base::getPostInt('dialog_id');
$reply_id = Base::getPostInt('reply_id');
$image_attachment = Base::getPostInt('image_attachment');
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
//
$action = $reply_id > 0 ? "reply-$reply_id" : "";
$path = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/";
$image64 = Base::getPostValue('image64');
$fileName = Base::getPostValue('filename');
if ($image64) {
$data = Base::image64save([
"image64" => $image64,
"path" => $path,
"fileName" => $fileName,
]);
} else {
$data = Base::upload([
"file" => Request::file('files'),
"type" => 'more',
"path" => $path,
"fileName" => $fileName,
]);
}
//
if (Base::isError($data)) {
return Base::retError($data['msg']);
} else {
$fileData = $data['data'];
$fileData['thumb'] = Base::unFillUrl($fileData['thumb']);
$fileData['size'] *= 1024;
//
if ($dialog->type === 'group' && $dialog->group_type === 'task') { // 任务群组保存文件
if ($image_attachment || !in_array($fileData['ext'], File::imageExt)) { // 如果是图片不保存
$task = ProjectTask::whereDialogId($dialog->id)->first();
if ($task) {
$file = ProjectTaskFile::createInstance([
'project_id' => $task->project_id,
'task_id' => $task->id,
'name' => $fileData['name'],
'size' => $fileData['size'],
'ext' => $fileData['ext'],
'path' => $fileData['path'],
'thumb' => $fileData['thumb'],
'userid' => $user->userid,
]);
$file->save();
}
}
}
//
$result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'file', $fileData, $user->userid);
if (Base::isSuccess($result)) {
if (isset($task)) {
$result['data']['task_id'] = $task->id;
}
}
return $result;
}
}
/**
* @api {get} api/dialog/msg/readlist 16. 获取消息阅读情况
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__readlist
*
* @apiParam {Number} msg_id 消息ID需要是消息的发送人
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__readlist()
{
$user = User::auth();
//
$msg_id = intval(Request::input('msg_id'));
//
$msg = WebSocketDialogMsg::whereId($msg_id)->whereUserid($user->userid)->first();
if (empty($msg)) {
return Base::retError('不是发送人');
}
//
$read = WebSocketDialogMsgRead::whereMsgId($msg_id)->get();
return Base::retSuccess('success', $read ?: []);
}
/**
* @api {get} api/dialog/msg/detail 17. 消息详情
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__detail
*
* @apiParam {Number} msg_id 消息ID
* @apiParam {String} only_update_at 仅获取update_at字段
* - no (默认)
* - yes
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__detail()
{
User::auth();
//
$msg_id = intval(Request::input('msg_id'));
$only_update_at = Request::input('only_update_at', 'no');
//
$dialogMsg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($dialogMsg)) {
return Base::retError("文件不存在");
}
//
if ($only_update_at == 'yes') {
return Base::retSuccess('success', [
'id' => $dialogMsg->id,
'update_at' => Carbon::parse($dialogMsg->updated_at)->toDateTimeString()
]);
}
//
$data = $dialogMsg->toArray();
//
if ($data['type'] == 'file') {
$msg = Base::json2array($dialogMsg->getRawOriginal('msg'));
$msg = File::formatFileData($msg);
$data['content'] = $msg['content'];
$data['file_mode'] = $msg['file_mode'];
}
//
return Base::retSuccess('success', $data);
}
/**
* @api {get} api/dialog/msg/download 18. 文件下载
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__download
*
* @apiParam {Number} msg_id 消息ID
* @apiParam {String} down 直接下载
* - yes: 下载(默认)
* - preview: 转预览地址
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__download()
{
User::auth();
//
$msg_id = intval(Request::input('msg_id'));
$down = Request::input('down', 'yes');
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
abort(403, "This file not exist.");
}
if ($msg->type != 'file') {
abort(403, "This file not support download.");
}
$array = Base::json2array($msg->getRawOriginal('msg'));
//
if ($down === 'preview') {
return Redirect::to(FileContent::toPreviewUrl($array));
}
//
return Response::download(public_path($array['path']), $array['name']);
}
/**
* @api {get} api/dialog/msg/withdraw 19. 聊天消息撤回
*
* @apiDescription 消息撤回限制24小时内需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__withdraw
*
* @apiParam {Number} msg_id 消息ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__withdraw()
{
$user = User::auth();
$msg_id = intval(Request::input("msg_id"));
$msg = WebSocketDialogMsg::whereId($msg_id)->whereUserid($user->userid)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
$msg->deleteMsg();
return Base::retSuccess("success");
}
/**
* @api {get} api/dialog/msg/mark 20. 消息标记操作
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__mark
*
* @apiParam {Number} dialog_id 会话ID
* @apiParam {String} type 类型
* - read
* - unread
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__mark()
{
$user = User::auth();
$dialogId = intval(Request::input('dialog_id'));
$type = Request::input('type');
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
if (!$dialogUser) {
return Base::retError("会话不存在");
}
switch ($type) {
case 'read':
WebSocketDialogMsgRead::whereUserid($user->userid)
->whereReadAt(null)
->whereDialogId($dialogId)
->chunkById(100, function ($list) {
WebSocketDialogMsgRead::onlyMarkRead($list);
});
$dialogUser->mark_unread = 0;
$dialogUser->save();
break;
case 'unread':
$dialogUser->mark_unread = 1;
$dialogUser->save();
break;
default:
return Base::retError("参数错误");
}
return Base::retSuccess("success", [
'id' => $dialogId,
'mark_unread' => $dialogUser->mark_unread,
]);
}
/**
* @api {get} api/dialog/msg/forward 21. 转发消息给
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__forward
*
* @apiParam {Number} msg_id 消息ID
* @apiParam {Array} dialogids 转发给的对话ID
* @apiParam {Array} userids 转发给的成员ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__forward()
{
$user = User::auth();
//
$msg_id = intval(Request::input("msg_id"));
$dialogids = Request::input('dialogids');
$userids = Request::input('userids');
//
if (empty($dialogids) && empty($userids)) {
return Base::retError("请选择转发对话或成员");
}
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
WebSocketDialog::checkDialog($msg->dialog_id);
//
return $msg->forwardMsg($dialogids, $userids, $user->userid);
}
/**
* @api {get} api/dialog/msg/emoji 22. emoji回复
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__emoji
*
* @apiParam {Number} msg_id 消息ID
* @apiParam {String} symbol 回复或取消的emoji表情
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__emoji()
{
$user = User::auth();
//
$msg_id = intval(Request::input("msg_id"));
$symbol = Request::input("symbol");
//
if (!preg_match("/^[\u{d800}-\u{dbff}]|[\u{dc00}-\u{dfff}]$/", $symbol)) {
return Base::retError("参数错误");
}
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
WebSocketDialog::checkDialog($msg->dialog_id);
//
return $msg->emojiMsg($symbol, $user->userid);
}
/**
* @api {get} api/dialog/msg/tag 23. 标注/取消标注
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__tag
*
* @apiParam {Number} msg_id 消息ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__tag()
{
$user = User::auth();
//
$msg_id = intval(Request::input("msg_id"));
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
WebSocketDialog::checkDialog($msg->dialog_id);
//
return $msg->toggleTagMsg($user->userid);
}
/**
* @api {get} api/dialog/msg/todo 24. 设待办/取消待办
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__todo
*
* @apiParam {Number} msg_id 消息ID
* @apiParam {String} type 设待办对象
* - all: 会话全部成员(默认)
* - user: 会话指定成员
* @apiParam {Array} userids 会员ID组type=user有效格式: [userid1, userid2, userid3]
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__todo()
{
$user = User::auth();
//
$msg_id = intval(Request::input("msg_id"));
$type = trim(Request::input("type", "all"));
$userids = Request::input('userids');
//
if ($type === 'user') {
if (empty($userids)) {
return Base::retError("选择指定成员");
}
} else {
$userids = [];
}
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
WebSocketDialog::checkDialog($msg->dialog_id);
//
return $msg->toggleTodoMsg($user->userid, $userids);
}
/**
* @api {get} api/dialog/msg/todolist 25. 获取消息待办情况
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__todolist
*
* @apiParam {Number} msg_id 消息ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__todolist()
{
User::auth();
//
$msg_id = intval(Request::input('msg_id'));
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
WebSocketDialog::checkDialog($msg->dialog_id);
//
$todo = WebSocketDialogMsgTodo::whereMsgId($msg_id)->get();
return Base::retSuccess('success', $todo ?: []);
}
/**
* @api {get} api/dialog/msg/done 26. 完成待办
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__done
*
* @apiParam {Number} id 待办数据ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__done()
{
$user = User::auth();
//
$id = intval(Request::input("id"));
//
$add = [];
$todo = WebSocketDialogMsgTodo::whereId($id)->whereUserid($user->userid)->first();
if ($todo && empty($todo->done_at)) {
$todo->done_at = Carbon::now();
$todo->save();
//
$msg = WebSocketDialogMsg::find($todo->msg_id);
if ($msg) {
$res = WebSocketDialogMsg::sendMsg(null, $todo->dialog_id, 'todo', [
'action' => 'done',
'data' => [
'id' => $msg->id,
'type' => $msg->type,
'msg' => $msg->quoteTextMsg(),
]
]);
if (Base::isSuccess($res)) {
$add = $res['data'];
}
}
}
//
return Base::retSuccess("待办已完成", [
'add' => $add ?: null
]);
}
/**
* @api {get} api/dialog/group/add 27. 新增群组
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName group__add
*
* @apiParam {Array} userids 群成员,格式: [userid1, userid2, userid3]
* @apiParam {String} chat_name 群名称
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function group__add()
{
$user = User::auth();
//
$userids = Request::input('userids');
$chatName = trim(Request::input('chat_name'));
//
if (!is_array($userids)) {
return Base::retError('请选择群成员');
}
$userids = array_merge([$user->userid], $userids);
$userids = array_values(array_filter(array_unique($userids)));
if (count($userids) < 2) {
return Base::retError('群成员至少2人');
}
//
if (empty($chatName)) {
$array = [];
foreach ($userids as $userid) {
$array[] = User::userid2nickname($userid);
if (count($array) >= 8 || strlen(implode(", ", $array)) > 100) {
$array[] = "...";
break;
}
}
$chatName = implode(", ", $array);
}
$dialog = WebSocketDialog::createGroup($chatName, $userids, 'user', $user->userid);
if (empty($dialog)) {
return Base::retError('创建群组失败');
}
$data = WebSocketDialog::find($dialog->id)?->formatData($user->userid);
$userids = array_values(array_diff($userids, [$user->userid]));
$dialog->pushMsg("groupAdd", null, $userids);
return Base::retSuccess('创建成功', $data);
}
/**
* @api {get} api/dialog/group/edit 28. 修改群组
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName group__edit
*
* @apiParam {Number} dialog_id 会话ID
* @apiParam {String} chat_name 群名称
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function group__edit()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$chatName = trim(Request::input('chat_name'));
//
if (mb_strlen($chatName) < 2) {
return Base::retError('群名称至少2个字');
}
if (mb_strlen($chatName) > 100) {
return Base::retError('群名称最长限制100个字');
}
//
$dialog = WebSocketDialog::checkDialog($dialog_id, true);
//
$dialog->name = $chatName;
$dialog->save();
return Base::retSuccess('修改成功', [
'id' => $dialog->id,
'name' => $dialog->name,
]);
}
/**
* @api {get} api/dialog/group/adduser 29. 添加群成员
*
* @apiDescription 需要token身份
* - 有群主时:只有群主可以邀请
* - 没有群主时:群内成员都可以邀请
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName group__adduser
*
* @apiParam {Number} dialog_id 会话ID
* @apiParam {Array} userids 新增的群成员,格式: [userid1, userid2, userid3]
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function group__adduser()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$userids = Request::input('userids');
//
if (!is_array($userids)) {
return Base::retError('请选择群成员');
}
//
$dialog = WebSocketDialog::checkDialog($dialog_id, "auto");
//
$dialog->checkGroup();
$dialog->joinGroup($userids, $user->userid);
$dialog->pushMsg("groupJoin", null, $userids);
return Base::retSuccess('添加成功');
}
/**
* @api {get} api/dialog/group/deluser 30. 移出(退出)群成员
*
* @apiDescription 需要token身份
* - 只有群主、邀请人可以踢人
* - 群主、任务人员、项目人员不可被踢或退出
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName group__adduser
*
* @apiParam {Number} dialog_id 会话ID
* @apiParam {Array} userids 移出的群成员,格式: [userid1, userid2, userid3]
* - 留空表示自己退出
* - 有值表示移出,仅限群主操作
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function group__deluser()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$userids = Request::input('userids');
//
$type = 'remove';
if (empty($userids)) {
$type = 'exit';
$userids = [$user->userid];
}
//
if (!is_array($userids)) {
return Base::retError('请选择群成员');
}
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
//
$dialog->checkGroup();
$dialog->exitGroup($userids, $type);
$dialog->pushMsg("groupExit", null, $userids);
return Base::retSuccess($type === 'remove' ? '移出成功' : '退出成功');
}
/**
* @api {get} api/dialog/group/disband 31. 解散群组
*
* @apiDescription 需要token身份
* - 只有群主且是个人类型群可以解散
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName group__disband
*
* @apiParam {Number} dialog_id 会话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function group__disband()
{
User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
//
$dialog = WebSocketDialog::checkDialog($dialog_id, true);
//
$dialog->checkGroup('user');
$dialog->deleteDialog();
$dialog->pushMsg("groupDelete");
return Base::retSuccess('解散成功');
}
}