hyperf-chat/app/Controller/Api/V1/Talk/MessageController.php

477 lines
16 KiB
PHP
Raw Normal View History

2021-07-05 21:52:44 +08:00
<?php
2021-07-29 23:30:42 +08:00
declare(strict_types=1);
2021-07-05 21:52:44 +08:00
2022-01-17 21:06:27 +08:00
namespace App\Controller\Api\V1\Talk;
2021-07-05 21:52:44 +08:00
2021-07-21 23:31:41 +08:00
use App\Cache\UnreadTalkCache;
2022-01-22 20:08:19 +08:00
use App\Constant\MediaTypeConstant;
use App\Constant\TalkEventConstant;
use App\Constant\TalkModeConstant;
2022-01-17 21:06:27 +08:00
use App\Controller\Api\V1\CController;
2021-07-20 23:12:18 +08:00
use App\Event\TalkEvent;
2022-01-21 21:46:17 +08:00
use App\Model\Emoticon\EmoticonItem;
2022-01-19 22:02:00 +08:00
use App\Model\SplitUpload;
2021-08-14 17:31:21 +08:00
use App\Service\TalkForwardService;
2021-07-08 23:44:43 +08:00
use App\Service\TalkMessageService;
2021-07-06 23:32:14 +08:00
use App\Support\UserRelation;
2021-07-05 21:52:44 +08:00
use App\Service\EmoticonService;
use App\Service\TalkService;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use App\Middleware\JWTAuthMiddleware;
use League\Flysystem\Filesystem;
2021-09-11 12:41:28 +08:00
use Psr\Http\Message\ResponseInterface;
2021-07-05 21:52:44 +08:00
/**
* Class TalkController
2022-01-22 21:02:53 +08:00
*
2021-07-05 21:52:44 +08:00
* @Controller(prefix="/api/v1/talk/message")
* @Middleware(JWTAuthMiddleware::class)
*
* @package App\Controller\Api\V1
*/
2022-01-17 21:06:27 +08:00
class MessageController extends CController
2021-07-05 21:52:44 +08:00
{
/**
* @var TalkService
*/
public $talkService;
2021-07-08 23:44:43 +08:00
/**
* @var TalkMessageService
*/
public $talkMessageService;
2022-01-22 21:02:53 +08:00
public function __construct(TalkService $talkService, TalkMessageService $talkMessageService)
{
parent::__construct();
$this->talkService = $talkService;
$this->talkMessageService = $talkMessageService;
}
2021-08-09 20:58:13 +08:00
/**
* 发送文本消息
2021-09-11 12:41:28 +08:00
*
2021-08-09 20:58:13 +08:00
* @RequestMapping(path="text", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function text(): ResponseInterface
2021-08-09 20:58:13 +08:00
{
2021-08-09 21:58:36 +08:00
$params = $this->request->inputs(['talk_type', 'receiver_id', 'text']);
$this->validate($params, [
'talk_type' => 'required|in:1,2',
'receiver_id' => 'required|integer|min:1',
'text' => 'required|max:65535',
]);
2021-09-11 15:53:23 +08:00
$this->talkMessageService->insertText([
2021-08-09 21:58:36 +08:00
'talk_type' => $params['talk_type'],
'user_id' => $this->uid(),
'receiver_id' => $params['receiver_id'],
'content' => $params['text'],
]);
return $this->response->success();
2021-08-09 20:58:13 +08:00
}
2021-07-05 21:52:44 +08:00
/**
* 发送代码块消息
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="code", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function code(): ResponseInterface
2021-07-05 21:52:44 +08:00
{
$params = $this->request->inputs(['talk_type', 'receiver_id', 'lang', 'code']);
2022-01-17 21:06:27 +08:00
2021-07-05 21:52:44 +08:00
$this->validate($params, [
'talk_type' => 'required|in:1,2',
'receiver_id' => 'required|integer|min:1',
'lang' => 'required',
'code' => 'required'
]);
$user_id = $this->uid();
2022-01-17 21:06:27 +08:00
2021-07-29 23:30:42 +08:00
if (!UserRelation::isFriendOrGroupMember($user_id, (int)$params['receiver_id'], (int)$params['talk_type'])) {
2021-07-05 21:52:44 +08:00
return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!');
}
2021-09-11 12:41:28 +08:00
$isTrue = $this->talkMessageService->insertCode([
2021-07-05 21:52:44 +08:00
'talk_type' => $params['talk_type'],
'user_id' => $user_id,
'receiver_id' => $params['receiver_id'],
], [
2022-01-17 21:06:27 +08:00
'user_id' => $user_id,
'lang' => $params['lang'],
'code' => $params['code']
2021-07-05 21:52:44 +08:00
]);
2021-07-13 22:53:13 +08:00
if (!$isTrue) return $this->response->fail('消息发送失败!');
2021-07-05 21:52:44 +08:00
return $this->response->success();
}
/**
* 发送图片消息
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="image", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function image(Filesystem $filesystem): ResponseInterface
2021-07-05 21:52:44 +08:00
{
$params = $this->request->inputs(['talk_type', 'receiver_id']);
2022-01-17 21:06:27 +08:00
2021-07-05 21:52:44 +08:00
$this->validate($params, [
'talk_type' => 'required|in:1,2',
'receiver_id' => 'required|integer|min:1'
]);
$user_id = $this->uid();
2022-01-17 21:06:27 +08:00
2021-07-29 23:30:42 +08:00
if (!UserRelation::isFriendOrGroupMember($user_id, (int)$params['receiver_id'], (int)$params['talk_type'])) {
2021-07-05 21:52:44 +08:00
return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!');
}
$file = $this->request->file('image');
if (!$file || !$file->isValid()) {
return $this->response->fail();
}
$ext = $file->getExtension();
if (!in_array($ext, ['jpg', 'png', 'jpeg', 'gif', 'webp'])) {
return $this->response->fail('图片格式错误目前仅支持jpg、png、jpeg、gif和webp');
}
try {
2022-01-22 12:48:28 +08:00
$path = 'public/media/images/talks/' . date('Ymd') . '/' . create_image_name($ext, getimagesize($file->getRealPath()));
2021-07-05 21:52:44 +08:00
$filesystem->write($path, file_get_contents($file->getRealPath()));
} catch (\Exception $e) {
return $this->response->fail();
}
// 创建图片消息记录
2021-09-11 12:41:28 +08:00
$isTrue = $this->talkMessageService->insertFile([
2021-07-05 21:52:44 +08:00
'talk_type' => $params['talk_type'],
'user_id' => $user_id,
'receiver_id' => $params['receiver_id'],
], [
'user_id' => $user_id,
2022-01-19 22:02:00 +08:00
'suffix' => $ext,
'size' => $file->getSize(),
'path' => $path,
2022-01-22 12:48:28 +08:00
'url' => get_media_url($path),
2021-07-05 21:52:44 +08:00
'original_name' => $file->getClientFilename(),
]);
2021-07-13 22:53:13 +08:00
if (!$isTrue) return $this->response->fail('图片上传失败!');
2021-07-05 21:52:44 +08:00
return $this->response->success();
}
/**
* 发送文件消息
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="file", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function file(Filesystem $filesystem): ResponseInterface
2021-07-05 21:52:44 +08:00
{
$params = $this->request->inputs(['talk_type', 'receiver_id', 'hash_name']);
2022-01-17 21:06:27 +08:00
2021-07-05 21:52:44 +08:00
$this->validate($params, [
'talk_type' => 'required|in:1,2',
'receiver_id' => 'required|integer|min:1',
'hash_name' => 'required',
]);
$user_id = $this->uid();
2021-07-29 23:30:42 +08:00
if (!UserRelation::isFriendOrGroupMember($user_id, (int)$params['receiver_id'], (int)$params['talk_type'])) {
2021-07-05 21:52:44 +08:00
return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!');
}
2022-01-19 22:02:00 +08:00
$file = SplitUpload::where('user_id', $user_id)->where('upload_id', $params['hash_name'])->where('type', 1)->first();
if (!$file || empty($file->path)) {
2021-07-05 21:52:44 +08:00
return $this->response->fail('文件不存在...');
}
2022-01-19 22:02:00 +08:00
$save_dir = "private/files/talks/" . date('Ymd') . '/' . create_random_filename($file->file_ext);
2022-01-22 16:51:55 +08:00
$url = "";
if (MediaTypeConstant::getMediaType($file->file_ext) <= 3) {
$save_dir = "public/media/" . date('Ymd') . '/' . create_random_filename($file->file_ext);
$url = get_media_url($save_dir);
}
2021-07-05 21:52:44 +08:00
try {
2022-01-19 22:02:00 +08:00
$filesystem->copy($file->path, $save_dir);
2021-07-05 21:52:44 +08:00
} catch (\Exception $e) {
return $this->response->fail('文件不存在...');
}
2021-09-11 12:41:28 +08:00
$isTrue = $this->talkMessageService->insertFile([
2021-07-05 21:52:44 +08:00
'talk_type' => $params['talk_type'],
'user_id' => $user_id,
'receiver_id' => $params['receiver_id']
], [
'user_id' => $user_id,
2022-01-19 22:02:00 +08:00
'source' => 1,
2021-07-05 21:52:44 +08:00
'original_name' => $file->original_name,
2022-01-19 22:02:00 +08:00
'suffix' => $file->file_ext,
'size' => $file->file_size,
'path' => $save_dir,
2022-01-22 16:51:55 +08:00
'url' => $url,
2021-07-05 21:52:44 +08:00
]);
2022-01-19 22:02:00 +08:00
if (!$isTrue) return $this->response->fail('文件发送失败!');
2021-07-05 21:52:44 +08:00
return $this->response->success();
}
/**
* 发送投票消息
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="vote", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function vote(): ResponseInterface
2021-07-05 21:52:44 +08:00
{
2021-07-12 23:19:58 +08:00
$params = $this->request->all();
$this->validate($params, [
'receiver_id' => 'required|integer|min:1',
'mode' => 'required|integer|in:0,1',
'title' => 'required',
2021-07-17 21:27:48 +08:00
'options' => 'required|array',
2021-07-12 23:19:58 +08:00
]);
2021-07-05 21:52:44 +08:00
2021-07-12 23:19:58 +08:00
$user_id = $this->uid();
2021-07-29 23:30:42 +08:00
if (!UserRelation::isFriendOrGroupMember($user_id, (int)$params['receiver_id'], TalkModeConstant::GROUP_CHAT)) {
2021-07-17 00:07:24 +08:00
return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!');
}
2021-07-12 23:19:58 +08:00
2021-09-11 12:41:28 +08:00
$isTrue = $this->talkMessageService->insertVote([
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-12 23:19:58 +08:00
'user_id' => $user_id,
'receiver_id' => $params['receiver_id'],
], [
2021-07-17 21:27:48 +08:00
'user_id' => $user_id,
'title' => $params['title'],
'answer_mode' => $params['mode'],
'answer_option' => $params['options'],
2021-07-12 23:19:58 +08:00
]);
2021-07-13 22:53:13 +08:00
if (!$isTrue) return $this->response->fail('发起投票失败!');
return $this->response->success();
2021-07-05 21:52:44 +08:00
}
/**
* 发送表情包消息
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="emoticon", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function emoticon(): ResponseInterface
2021-07-05 21:52:44 +08:00
{
$params = $this->request->inputs(['talk_type', 'receiver_id', 'emoticon_id']);
2022-01-22 12:48:28 +08:00
2021-07-05 21:52:44 +08:00
$this->validate($params, [
'talk_type' => 'required|in:1,2',
'receiver_id' => 'required|integer|min:1',
'emoticon_id' => 'required|integer|min:1',
]);
$user_id = $this->uid();
2021-07-29 23:30:42 +08:00
if (!UserRelation::isFriendOrGroupMember($user_id, (int)$params['receiver_id'], (int)$params['talk_type'])) {
2021-07-05 21:52:44 +08:00
return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!');
}
2021-07-09 19:40:43 +08:00
$emoticon = EmoticonItem::where('id', $params['emoticon_id'])->where('user_id', $user_id)->first();
2021-07-05 21:52:44 +08:00
2021-07-06 23:32:14 +08:00
if (!$emoticon) return $this->response->fail('表情不存在!');
2021-07-05 21:52:44 +08:00
2021-09-11 12:41:28 +08:00
$isTrue = $this->talkMessageService->insertFile([
2021-07-05 21:52:44 +08:00
'talk_type' => $params['talk_type'],
'user_id' => $user_id,
'receiver_id' => $params['receiver_id'],
], [
'user_id' => $user_id,
2022-01-19 22:02:00 +08:00
'suffix' => $emoticon->file_suffix,
'size' => $emoticon->file_size,
'url' => $emoticon->url,
2021-07-05 21:52:44 +08:00
'original_name' => '图片表情',
]);
2021-07-13 22:53:13 +08:00
if (!$isTrue) return $this->response->fail('表情发送失败!');
2021-07-05 21:52:44 +08:00
return $this->response->success();
}
/**
2021-09-11 22:50:57 +08:00
* 发送转发消息
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="forward", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function forward(TalkForwardService $forwardService): ResponseInterface
2021-07-05 21:52:44 +08:00
{
2021-09-11 12:41:28 +08:00
$params = $this->request->inputs([
'talk_type', 'receiver_id', 'records_ids', 'forward_mode', 'receive_user_ids', 'receive_group_ids'
]);
2021-07-05 21:52:44 +08:00
$this->validate($params, [
'talk_type' => 'required|in:1,2',
'receiver_id' => 'required|integer|min:1',
'records_ids' => 'required', // 聊天记录ID多个逗号拼接
'forward_mode' => 'required|in:1,2',// 转发方方式[1:逐条转发;2:合并转发;]
]);
2021-08-14 17:31:21 +08:00
$user_id = $this->uid();
// 判断好友或者群关系
if (!UserRelation::isFriendOrGroupMember($user_id, (int)$params['receiver_id'], (int)$params['talk_type'])) {
return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!');
}
2021-07-05 21:52:44 +08:00
$receive_user_ids = $receive_group_ids = [];
2021-08-14 17:31:21 +08:00
$func = function (array $ids, int $talk_type) {
return array_map(function ($id) use ($talk_type) {
return ['talk_type' => $talk_type, 'id' => (int)$id];
}, $ids);
};
2021-07-05 21:52:44 +08:00
if (isset($params['receive_user_ids']) && !empty($params['receive_user_ids'])) {
2022-01-17 21:06:27 +08:00
$receive_user_ids = $func(parse_ids($params['receive_user_ids']), TalkModeConstant::PRIVATE_CHAT);
2021-07-05 21:52:44 +08:00
}
if (isset($params['receive_group_ids']) && !empty($params['receive_group_ids'])) {
2022-01-17 21:06:27 +08:00
$receive_group_ids = $func(parse_ids($params['receive_group_ids']), TalkModeConstant::GROUP_CHAT);
2021-07-05 21:52:44 +08:00
}
2021-08-14 17:31:21 +08:00
// 需要转发的好友或者群组
2021-07-05 21:52:44 +08:00
$items = array_merge($receive_user_ids, $receive_group_ids);
2021-09-11 22:50:57 +08:00
$method = $params['forward_mode'] == 1 ? "multiSplitForward" : "multiMergeForward";
2022-01-17 21:06:27 +08:00
$ids = $forwardService->{$method}($user_id, (int)$params['receiver_id'], (int)$params['talk_type'], parse_ids($params['records_ids']), $items);
2021-07-05 21:52:44 +08:00
2021-07-06 23:32:14 +08:00
if (!$ids) return $this->response->fail('转发失败!');
2021-07-05 21:52:44 +08:00
if ($receive_user_ids) {
foreach ($receive_user_ids as $v) {
2021-07-21 23:31:41 +08:00
UnreadTalkCache::getInstance()->increment($user_id, $v['id']);
2021-07-05 21:52:44 +08:00
}
}
// 消息推送队列
foreach ($ids as $value) {
2021-07-20 23:12:18 +08:00
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_TALK, [
2021-07-12 23:19:58 +08:00
'sender_id' => $user_id,
'receiver_id' => $value['receiver_id'],
'talk_type' => $value['talk_type'],
'record_id' => $value['record_id'],
]));
2021-07-05 21:52:44 +08:00
}
return $this->response->success([], '转发成功...');
}
2021-09-11 22:50:57 +08:00
/**
* 发送用户名片消息
*
* @RequestMapping(path="card", methods="post")
*/
public function card(): ResponseInterface
{
// todo 待开发
}
2021-07-05 21:52:44 +08:00
/**
* 收藏聊天图片
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="collect", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function collect(EmoticonService $service): ResponseInterface
2021-07-05 21:52:44 +08:00
{
$params = $this->request->inputs(['record_id']);
$this->validate($params, [
'record_id' => 'required|integer'
]);
2021-08-14 17:31:21 +08:00
[$isTrue, $data] = $service->collect($this->uid(), (int)$params['record_id']);
2021-07-05 21:52:44 +08:00
if (!$isTrue) return $this->response->fail('添加表情失败!');
return $this->response->success([
'emoticon' => $data
]);
}
/**
* 撤销聊天记录
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="revoke", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function revoke(): ResponseInterface
2021-07-05 21:52:44 +08:00
{
$params = $this->request->inputs(['record_id']);
$this->validate($params, [
2021-07-09 19:40:43 +08:00
'record_id' => 'required|integer|min:1'
2021-07-05 21:52:44 +08:00
]);
2021-08-14 17:31:21 +08:00
[$isTrue, $message,] = $this->talkService->revokeRecord($this->uid(), (int)$params['record_id']);
2021-07-06 23:32:14 +08:00
if (!$isTrue) return $this->response->fail($message);
2021-07-05 21:52:44 +08:00
2021-07-06 23:32:14 +08:00
return $this->response->success([], $message);
2021-07-05 21:52:44 +08:00
}
/**
* 删除聊天记录
2021-09-11 12:41:28 +08:00
*
2021-07-05 21:52:44 +08:00
* @RequestMapping(path="delete", methods="post")
*/
2021-09-11 12:41:28 +08:00
public function delete(): ResponseInterface
2021-07-05 21:52:44 +08:00
{
$params = $this->request->inputs(['talk_type', 'receiver_id', 'record_id']);
$this->validate($params, [
'talk_type' => 'required|in:1,2',
'receiver_id' => 'required|integer|min:1',
'record_id' => 'required|ids',
]);
$isTrue = $this->talkService->removeRecords(
$this->uid(),
2021-08-14 17:31:21 +08:00
(int)$params['talk_type'],
(int)$params['receiver_id'],
2021-07-05 21:52:44 +08:00
parse_ids($params['record_id'])
);
2021-09-11 22:50:57 +08:00
if (!$isTrue) {
return $this->response->fail('删除失败!');
}
return $this->response->success([], '删除成功...');
}
/**
* 投票处理
*
* @RequestMapping(path="vote/handle", methods="post")
*/
public function handleVote(): ResponseInterface
{
$params = $this->request->inputs(['record_id', 'options']);
2022-01-17 21:06:27 +08:00
2021-09-11 22:50:57 +08:00
$this->validate($params, [
'record_id' => 'required|integer|min:1',
'options' => 'required',
]);
$params['options'] = array_filter(explode(',', $params['options']));
if (!$params['options']) {
return $this->response->fail('投票失败,请稍后再试!');
}
[$isTrue, $cache] = $this->talkMessageService->handleVote($this->uid(), $params);
if (!$isTrue) return $this->response->fail('投票失败,请稍后再试!');
return $this->response->success($cache);
2021-07-05 21:52:44 +08:00
}
}