hyperf-chat/app/Service/TalkMessageService.php

319 lines
9.7 KiB
PHP
Raw Normal View History

2021-07-05 21:52:44 +08:00
<?php
2021-09-05 21:13:48 +08:00
declare(strict_types=1);
2021-07-05 21:52:44 +08:00
namespace App\Service;
2021-07-13 22:53:13 +08:00
use App\Cache\LastMessage;
2021-08-09 21:29:52 +08:00
use App\Cache\UnreadTalkCache;
2021-07-18 23:41:25 +08:00
use App\Cache\VoteCache;
2021-07-19 23:58:14 +08:00
use App\Cache\VoteStatisticsCache;
2021-07-25 22:57:41 +08:00
use App\Constants\RobotConstant;
2021-07-20 23:12:18 +08:00
use App\Constants\TalkEventConstant;
2021-07-08 23:44:43 +08:00
use App\Constants\TalkMessageType;
2021-07-25 22:57:41 +08:00
use App\Constants\TalkModeConstant;
2021-07-20 23:12:18 +08:00
use App\Event\TalkEvent;
2021-07-17 00:07:24 +08:00
use App\Model\Group\GroupMember;
2021-07-09 22:57:19 +08:00
use App\Model\Talk\TalkRecordsCode;
2021-07-25 22:57:41 +08:00
use App\Model\Talk\TalkRecordsLogin;
2021-07-12 23:19:58 +08:00
use App\Model\Talk\TalkRecordsVote;
2021-07-17 00:07:24 +08:00
use App\Model\Talk\TalkRecordsVoteAnswer;
2021-09-12 21:15:38 +08:00
use App\Repository\RobotRepository;
2021-07-17 00:07:24 +08:00
use App\Support\UserRelation;
2021-07-08 23:44:43 +08:00
use Exception;
2021-07-20 23:12:18 +08:00
use App\Constants\MediaTypeConstant;
2021-07-09 22:57:19 +08:00
use App\Model\Talk\TalkRecords;
use App\Model\Talk\TalkRecordsFile;
2021-07-08 23:44:43 +08:00
use Hyperf\DbConnection\Db;
2021-07-05 21:52:44 +08:00
class TalkMessageService
{
2021-08-09 21:29:52 +08:00
/**
* 创建文本消息
*
* @param array $message
* @return bool
*/
2021-09-11 12:41:28 +08:00
public function insertText(array $message): bool
2021-08-09 21:29:52 +08:00
{
2021-09-05 21:13:48 +08:00
$message['msg_type'] = TalkMessageType::TEXT_MESSAGE;
$message['content'] = htmlspecialchars($message['content']);
2021-08-09 21:29:52 +08:00
$message['created_at'] = date('Y-m-d H:i:s');
$message['updated_at'] = date('Y-m-d H:i:s');
$result = TalkRecords::create($message);
2021-09-12 21:15:38 +08:00
$this->handle($result, ['text' => mb_substr($result->content, 0, 30)]);
2021-08-09 21:29:52 +08:00
return true;
}
2021-07-08 23:44:43 +08:00
/**
* 创建代码块消息
*
* @param array $message
* @param array $code
2021-07-13 22:53:13 +08:00
* @return bool
2021-07-08 23:44:43 +08:00
*/
2021-09-11 12:41:28 +08:00
public function insertCode(array $message, array $code): bool
2021-07-08 23:44:43 +08:00
{
Db::beginTransaction();
try {
2021-09-05 21:13:48 +08:00
$message['msg_type'] = TalkMessageType::CODE_MESSAGE;
2021-07-08 23:44:43 +08:00
$message['created_at'] = date('Y-m-d H:i:s');
$message['updated_at'] = date('Y-m-d H:i:s');
2021-07-05 21:52:44 +08:00
2021-07-08 23:44:43 +08:00
$insert = TalkRecords::create($message);
if (!$insert) {
throw new Exception('插入聊天记录失败...');
}
2021-09-05 21:13:48 +08:00
$code['record_id'] = $insert->id;
2021-07-08 23:44:43 +08:00
$code['created_at'] = date('Y-m-d H:i:s');
if (!TalkRecordsCode::create($code)) {
throw new Exception('插入聊天记录(代码消息)失败...');
}
Db::commit();
} catch (Exception $e) {
Db::rollBack();
return false;
}
2021-09-12 21:15:38 +08:00
$this->handle($insert, ['text' => '[代码消息]']);
2021-07-13 22:53:13 +08:00
return true;
2021-07-08 23:44:43 +08:00
}
/**
* 创建文件类消息
*
* @param array $message
* @param array $file
2021-07-13 22:53:13 +08:00
* @return bool
2021-07-08 23:44:43 +08:00
*/
2021-09-11 12:41:28 +08:00
public function insertFile(array $message, array $file): bool
2021-07-08 23:44:43 +08:00
{
Db::beginTransaction();
try {
2021-09-05 21:13:48 +08:00
$message['msg_type'] = TalkMessageType::FILE_MESSAGE;
2021-07-08 23:44:43 +08:00
$message['created_at'] = date('Y-m-d H:i:s');
$message['updated_at'] = date('Y-m-d H:i:s');
$insert = TalkRecords::create($message);
if (!$insert) {
throw new Exception('插入聊天记录失败...');
}
2021-09-05 21:13:48 +08:00
$file['record_id'] = $insert->id;
2022-01-19 22:02:00 +08:00
$file['type'] = MediaTypeConstant::getMediaType($file['suffix']);
2021-07-08 23:44:43 +08:00
$file['created_at'] = date('Y-m-d H:i:s');
2022-01-19 22:02:00 +08:00
2021-07-08 23:44:43 +08:00
if (!TalkRecordsFile::create($file)) {
throw new Exception('插入聊天记录(代码消息)失败...');
}
Db::commit();
} catch (Exception $e) {
Db::rollBack();
2022-01-19 22:02:00 +08:00
logger()->error($e->getMessage());
2021-07-08 23:44:43 +08:00
return false;
}
2022-01-19 22:02:59 +08:00
$this->handle($insert, ['text' => '[文件消息]']);
2021-07-13 22:53:13 +08:00
return true;
2021-07-08 23:44:43 +08:00
}
2021-07-12 23:19:58 +08:00
/**
2021-07-17 00:07:24 +08:00
* 添加投票消息
*
2021-07-12 23:19:58 +08:00
* @param array $message
* @param array $vote
2021-07-17 00:07:24 +08:00
* @return bool
2021-07-12 23:19:58 +08:00
*/
2021-09-11 12:41:28 +08:00
public function insertVote(array $message, array $vote): bool
2021-07-12 23:19:58 +08:00
{
2021-07-17 00:07:24 +08:00
$answer_num = GroupMember::where('group_id', $message['receiver_id'])->where('is_quit', 0)->count();
2021-07-12 23:19:58 +08:00
Db::beginTransaction();
try {
2021-09-05 21:13:48 +08:00
$message['msg_type'] = TalkMessageType::VOTE_MESSAGE;
2021-07-12 23:19:58 +08:00
$message['created_at'] = date('Y-m-d H:i:s');
$message['updated_at'] = date('Y-m-d H:i:s');
2021-09-05 21:13:48 +08:00
$insert = TalkRecords::create($message);
2021-07-17 00:07:24 +08:00
$options = [];
2021-07-17 21:27:48 +08:00
foreach ($vote['answer_option'] as $k => $option) {
2021-07-17 00:07:24 +08:00
$options[chr(65 + $k)] = $option;
2021-07-12 23:19:58 +08:00
}
2021-09-05 21:13:48 +08:00
$vote['record_id'] = $insert->id;
2021-07-17 21:27:48 +08:00
$vote['answer_option'] = $options;
2021-09-05 21:13:48 +08:00
$vote['answer_num'] = $answer_num;
$vote['created_at'] = date('Y-m-d H:i:s');
$vote['updated_at'] = $vote['created_at'];
2021-07-17 21:27:48 +08:00
2021-07-12 23:19:58 +08:00
if (!TalkRecordsVote::create($vote)) {
throw new Exception('插入聊天记录(投票消息)失败...');
}
Db::commit();
} catch (Exception $e) {
Db::rollBack();
return false;
}
2021-09-12 21:15:38 +08:00
$this->handle($insert, ['text' => '[投票消息]']);
2021-07-13 22:53:13 +08:00
return true;
2021-07-12 23:19:58 +08:00
}
2021-07-17 00:07:24 +08:00
/**
* 群投票处理方法
*
* @param int $user_id
* @param array $params
2021-08-10 21:21:26 +08:00
* @return array
2021-07-17 00:07:24 +08:00
*/
2021-07-19 23:58:14 +08:00
public function handleVote(int $user_id, array $params): array
2021-07-17 00:07:24 +08:00
{
$record = TalkRecords::join('talk_records_vote as vote', 'vote.record_id', '=', 'talk_records.id')
->where('talk_records.id', $params['record_id'])
2021-07-17 21:27:48 +08:00
->withCasts([
'answer_option' => 'array'
])
2021-07-17 00:07:24 +08:00
->first([
2021-07-17 21:27:48 +08:00
'talk_records.id', 'talk_records.receiver_id', 'talk_records.talk_type', 'talk_records.msg_type',
2021-07-17 00:07:24 +08:00
'vote.id as vote_id', 'vote.answer_mode', 'vote.answer_option', 'vote.answer_num', 'vote.status as vote_status'
]);
2021-08-10 21:21:26 +08:00
if (!$record) return [false, []];
2021-07-17 00:07:24 +08:00
if ($record->msg_type != TalkMessageType::VOTE_MESSAGE) {
2021-07-19 23:58:14 +08:00
return [false, []];
2021-07-17 00:07:24 +08:00
}
if (!UserRelation::isFriendOrGroupMember($user_id, $record->receiver_id, $record->talk_type)) {
2021-07-19 23:58:14 +08:00
return [false, []];
2021-07-17 00:07:24 +08:00
}
2021-07-18 23:41:25 +08:00
if (TalkRecordsVoteAnswer::where('vote_id', $record->vote_id)->where('user_id', $user_id)->exists()) {
2021-07-19 23:58:14 +08:00
return [false, []];
2021-07-17 00:07:24 +08:00
}
2021-07-18 23:41:25 +08:00
$options = $params['options'];
2021-07-17 00:07:24 +08:00
sort($options);
foreach ($options as $value) {
2021-07-19 23:58:14 +08:00
if (!isset($record->answer_option[$value])) return [false, []];
2021-07-17 00:07:24 +08:00
}
// 单选模式取第一个
2021-07-18 23:41:25 +08:00
if ($record->answer_mode == 0) {
2021-07-17 00:07:24 +08:00
$options = [$options[0]];
}
try {
Db::transaction(function () use ($options, $record, $user_id) {
TalkRecordsVote::where('id', $record->vote_id)->update([
'answered_num' => Db::raw('answered_num + 1'),
'status' => Db::raw('if(answered_num >= answer_num, 1, 0)'),
'updated_at' => date('Y-m-d H:i:s'),
]);
foreach ($options as $option) {
TalkRecordsVoteAnswer::create([
'vote_id' => $record->vote_id,
'user_id' => $user_id,
'option' => $option,
'created_at' => date('Y-m-d H:i:s'),
]);
}
});
} catch (\Exception $e) {
2021-07-19 23:58:14 +08:00
return [false, []];
2021-07-17 00:07:24 +08:00
}
2021-07-19 23:58:14 +08:00
// 更新投票缓存
2021-07-28 23:42:21 +08:00
VoteCache::getInstance()->updateCache($record->vote_id);
2021-09-12 21:15:38 +08:00
2021-07-19 23:58:14 +08:00
$cache = VoteStatisticsCache::getInstance()->updateVoteCache($record->vote_id);
2021-07-18 23:41:25 +08:00
2021-07-19 23:58:14 +08:00
// todo 推送消息
return [true, $cache];
2021-07-17 00:07:24 +08:00
}
2021-07-25 22:57:41 +08:00
/**
* 添加登录消息
*
* @param array $message
* @param array $loginParams
* @return bool
*/
2021-09-11 12:41:28 +08:00
public function insertLogin(array $message, array $loginParams): bool
2021-07-25 22:57:41 +08:00
{
2021-09-12 21:15:38 +08:00
$user_id = di()->get(RobotRepository::class)->findTypeByUserId(RobotConstant::LOGIN_ROBOT);
2021-09-12 16:23:43 +08:00
if ($user_id == 0) return false;
2021-07-25 22:57:41 +08:00
Db::beginTransaction();
try {
2021-09-12 16:23:43 +08:00
$message['user_id'] = $user_id;
$message['talk_type'] = TalkModeConstant::PRIVATE_CHAT;
$message['msg_type'] = TalkMessageType::USER_LOGIN_MESSAGE;
$message['created_at'] = date('Y-m-d H:i:s');
$message['updated_at'] = date('Y-m-d H:i:s');
2021-07-25 22:57:41 +08:00
$insert = TalkRecords::create($message);
if (!$insert) {
throw new Exception('插入聊天记录失败...');
}
2021-09-05 21:13:48 +08:00
$loginParams['record_id'] = $insert->id;
2021-07-25 22:57:41 +08:00
$loginParams['created_at'] = date('Y-m-d H:i:s');
if (!TalkRecordsLogin::create($loginParams)) {
throw new Exception('插入聊天记录(登录消息)失败...');
}
Db::commit();
} catch (Exception $e) {
Db::rollBack();
return false;
}
// 创建对话列表
2021-09-12 16:23:43 +08:00
di()->get(TalkListService::class)->create($insert->receiver_id, $insert->user_id, $insert->talk_type, true);
2021-07-25 22:57:41 +08:00
2021-09-12 21:15:38 +08:00
$this->handle($insert, ['text' => '[登录提醒]']);
return true;
}
/**
* 处理数据
*
* @param TalkRecords $record
* @param array $option
*/
private function handle(TalkRecords $record, array $option = []): void
{
if ($record->talk_type == TalkModeConstant::PRIVATE_CHAT) {
UnreadTalkCache::getInstance()->increment($record->user_id, $record->receiver_id);
}
LastMessage::getInstance()->save($record->talk_type, $record->user_id, $record->receiver_id, [
'text' => $option['text'],
2021-07-25 22:57:41 +08:00
'created_at' => date('Y-m-d H:i:s')
]);
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_TALK, [
2021-09-12 21:15:38 +08:00
'sender_id' => $record->user_id,
'receiver_id' => $record->receiver_id,
'talk_type' => $record->talk_type,
'record_id' => $record->id
2021-07-25 22:57:41 +08:00
]));
}
2021-07-05 21:52:44 +08:00
}