hyperf-chat/app/Service/Group/GroupService.php

488 lines
16 KiB
PHP
Raw Normal View History

2021-01-28 20:07:14 +08:00
<?php
2021-03-26 22:03:11 +08:00
declare(strict_types=1);
2021-01-28 20:07:14 +08:00
2021-07-28 23:08:07 +08:00
namespace App\Service\Group;
2021-01-28 20:07:14 +08:00
2021-05-20 22:23:48 +08:00
use App\Cache\LastMessage;
2021-07-10 00:18:40 +08:00
use App\Cache\SocketRoom;
2021-07-20 23:12:18 +08:00
use App\Constants\TalkEventConstant;
2021-07-08 19:30:03 +08:00
use App\Constants\TalkMessageType;
2021-07-20 23:12:18 +08:00
use App\Constants\TalkModeConstant;
use App\Event\TalkEvent;
2021-07-09 22:57:19 +08:00
use App\Model\Talk\TalkRecords;
use App\Model\Talk\TalkRecordsInvite;
use App\Model\Group\Group;
use App\Model\Group\GroupMember;
2021-07-09 22:57:19 +08:00
use App\Model\Talk\TalkList;
2021-01-28 20:07:14 +08:00
use Hyperf\DbConnection\Db;
use Exception;
2021-07-28 23:08:07 +08:00
use App\Service\BaseService;
2021-01-28 20:07:14 +08:00
/**
* Class GroupService
2021-03-26 22:03:11 +08:00
*
2021-01-28 20:07:14 +08:00
* @package App\Service
*/
class GroupService extends BaseService
{
2021-07-28 23:08:07 +08:00
/**
* 判断群组是否已解散
*
* @param int $group_id 群ID
* @return bool
*/
public function isDismiss(int $group_id): bool
{
return Group::query()->where('id', $group_id)->where('is_dismiss', 1)->exists();
}
2021-01-28 20:07:14 +08:00
/**
* 创建群组
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
2021-01-28 20:07:14 +08:00
* @param array $group_info 群聊名称
* @param array $friend_ids 好友的用户ID
* @return array
*/
public function create(int $user_id, array $group_info, $friend_ids = [])
{
2021-03-31 22:30:10 +08:00
$invite_ids = implode(',', $friend_ids);
2021-01-28 20:07:14 +08:00
$friend_ids[] = $user_id;
$groupMember = [];
$chatList = [];
2021-01-28 20:07:14 +08:00
Db::beginTransaction();
try {
2021-07-10 00:18:40 +08:00
$group = Group::create([
'creator_id' => $user_id,
2021-01-28 20:07:14 +08:00
'group_name' => $group_info['name'],
2021-03-26 22:03:11 +08:00
'avatar' => $group_info['avatar'],
'profile' => $group_info['profile'],
'max_num' => Group::MAX_MEMBER_NUM,
'is_overt' => 0,
'is_mute' => 0,
'is_dismiss' => 0,
2021-01-28 20:07:14 +08:00
'created_at' => date('Y-m-d H:i:s')
]);
2021-07-05 21:52:44 +08:00
foreach ($friend_ids as $friend_id) {
2021-01-28 20:07:14 +08:00
$groupMember[] = [
2021-07-10 00:18:40 +08:00
'group_id' => $group->id,
2021-07-05 21:52:44 +08:00
'user_id' => $friend_id,
'leader' => $user_id == $friend_id ? 2 : 0,
2021-01-28 20:07:14 +08:00
'created_at' => date('Y-m-d H:i:s'),
];
$chatList[] = [
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-05 21:52:44 +08:00
'user_id' => $friend_id,
2021-07-10 00:18:40 +08:00
'receiver_id' => $group->id,
2021-07-05 21:52:44 +08:00
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
2021-01-28 20:07:14 +08:00
];
}
2021-07-30 23:23:48 +08:00
if (!GroupMember::insert($groupMember)) {
2021-01-28 20:07:14 +08:00
throw new Exception('创建群成员信息失败');
}
2021-07-30 23:23:48 +08:00
if (!TalkList::insert($chatList)) {
2021-01-28 20:07:14 +08:00
throw new Exception('创建群成员的聊天列表失败');
}
2021-07-05 21:52:44 +08:00
$result = TalkRecords::create([
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-05 21:52:44 +08:00
'user_id' => 0,
2021-07-10 00:18:40 +08:00
'receiver_id' => $group->id,
2021-07-08 19:30:03 +08:00
'msg_type' => TalkMessageType::GROUP_INVITE_MESSAGE,
2021-07-05 21:52:44 +08:00
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
2021-01-28 20:07:14 +08:00
]);
2021-07-05 21:52:44 +08:00
TalkRecordsInvite::create([
2021-03-26 22:03:11 +08:00
'record_id' => $result->id,
'type' => 1,
2021-01-28 20:07:14 +08:00
'operate_user_id' => $user_id,
2021-03-31 22:30:10 +08:00
'user_ids' => $invite_ids
2021-01-28 20:07:14 +08:00
]);
Db::commit();
} catch (Exception $e) {
Db::rollBack();
2021-07-10 00:18:40 +08:00
return [false, null];
2021-01-28 20:07:14 +08:00
}
2021-07-20 23:12:18 +08:00
LastMessage::getInstance()->save(TalkModeConstant::GROUP_CHAT, $user_id, $group->id, [
2021-05-20 22:23:48 +08:00
'text' => '[入群通知]',
'created_at' => date('Y-m-d H:i:s')
]);
2021-01-28 20:07:14 +08:00
2021-07-10 00:18:40 +08:00
// 加入聊天室
2021-07-10 00:25:05 +08:00
foreach ($friend_ids as $value) {
SocketRoom::getInstance()->addRoomMember(strval($group->id), strval($value));
2021-07-10 00:18:40 +08:00
}
2021-07-20 23:12:18 +08:00
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_TALK, [
2021-07-10 00:18:40 +08:00
'sender_id' => $user_id,
'receiver_id' => $group->id,
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-10 00:25:05 +08:00
'record_id' => $result->id
2021-07-10 00:18:40 +08:00
]));
return [true, $group];
}
/**
* @param int $group_id
* @param int $user_id
* @param array $params
* @return bool
*/
public function update(int $group_id, int $user_id, array $params)
{
return (bool)Group::where('id', $group_id)->where('creator_id', $user_id)->update([
'group_name' => $params['group_name'] ?? '',
'profile' => $params['profile'] ?? '',
'avatar' => $params['avatar'] ?? ''
]);
2021-01-28 20:07:14 +08:00
}
/**
2021-03-26 22:03:11 +08:00
* 解散群组(群主权限)
2021-01-28 20:07:14 +08:00
*
* @param int $group_id 群ID
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
2021-01-28 20:07:14 +08:00
* @return bool
*/
public function dismiss(int $group_id, int $user_id)
{
$group = Group::where('id', $group_id)->first(['creator_id', 'is_dismiss']);
if (!$group || $group->creator_id != $user_id || $group->is_dismiss == 1) {
2021-01-28 20:07:14 +08:00
return false;
}
2021-07-10 00:18:40 +08:00
try {
DB::transaction(function () use ($group_id, $user_id) {
Group::where('id', $group_id)->where('creator_id', $user_id)->update([
'is_dismiss' => 1,
'dismissed_at' => date('Y-m-d H:i:s'),
]);
2021-03-26 22:03:11 +08:00
2021-07-10 00:18:40 +08:00
GroupMember::where('group_id', $group_id)->update([
'is_quit' => 1,
'deleted_at' => date('Y-m-d H:i:s'),
]);
});
} catch (\Exception $e) {
return false;
}
SocketRoom::getInstance()->delRoom($group_id);
// ... TODO 推送群消息(预留)
2021-03-26 22:03:11 +08:00
return true;
2021-01-28 20:07:14 +08:00
}
/**
* 邀请加入群组
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
* @param int $group_id 聊天群ID
2021-01-28 20:07:14 +08:00
* @param array $friend_ids 被邀请的用户ID
2021-07-10 00:18:40 +08:00
* @return bool
2021-01-28 20:07:14 +08:00
*/
public function invite(int $user_id, int $group_id, $friend_ids = [])
{
2021-07-10 00:18:40 +08:00
if (!$friend_ids) return false;
2021-01-28 20:07:14 +08:00
$info = GroupMember::where('group_id', $group_id)->where('user_id', $user_id)->first(['id', 'is_quit']);
// 判断主动邀请方是否属于聊天群成员
if (!$info && $info->is_quit == 1) {
2021-07-10 00:18:40 +08:00
return false;
2021-01-28 20:07:14 +08:00
}
$updateArr = $insertArr = $updateArr1 = $insertArr1 = [];
$members = GroupMember::where('group_id', $group_id)->whereIn('user_id', $friend_ids)->get(['id', 'user_id', 'is_quit'])->keyBy('user_id')->toArray();
2021-07-20 23:12:18 +08:00
$chatArr = TalkList::where('talk_type', TalkModeConstant::GROUP_CHAT)
2021-07-05 21:52:44 +08:00
->where('receiver_id', $group_id)
->whereIn('user_id', $friend_ids)
->get(['id', 'user_id', 'is_delete'])
->keyBy('user_id')->toArray();
2021-01-28 20:07:14 +08:00
foreach ($friend_ids as $uid) {
2021-03-26 22:03:11 +08:00
if (!isset($members[$uid])) {
$insertArr[] = [
2021-03-26 22:03:11 +08:00
'group_id' => $group_id,
'user_id' => $uid,
'created_at' => date('Y-m-d H:i:s')
];
2021-07-05 21:52:44 +08:00
} else if ($members[$uid]['is_quit'] == 1) {
2021-01-28 20:07:14 +08:00
$updateArr[] = $members[$uid]['id'];
}
if (!isset($chatArr[$uid])) {
$insertArr1[] = [
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-05 21:52:44 +08:00
'user_id' => $uid,
'receiver_id' => $group_id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
];
2021-07-05 21:52:44 +08:00
} else if ($chatArr[$uid]['is_delete'] == 1) {
2021-01-28 20:07:14 +08:00
$updateArr1[] = $chatArr[$uid]['id'];
}
}
2021-07-08 19:09:06 +08:00
Db::beginTransaction();
2021-01-28 20:07:14 +08:00
try {
if ($updateArr) {
GroupMember::whereIn('id', $updateArr)->update([
2021-03-26 22:03:11 +08:00
'leader' => 0,
'is_mute' => 0,
'is_quit' => 0,
'user_card' => '',
'created_at' => date('Y-m-d H:i:s')
]);
2021-01-28 20:07:14 +08:00
}
if ($insertArr) {
2021-07-30 23:23:48 +08:00
GroupMember::insert($insertArr);
2021-01-28 20:07:14 +08:00
}
if ($updateArr1) {
2021-07-05 21:52:44 +08:00
TalkList::whereIn('id', $updateArr1)->update([
'is_delete' => 1,
'created_at' => date('Y-m-d H:i:s')
]);
2021-01-28 20:07:14 +08:00
}
if ($insertArr1) {
2021-07-30 23:23:48 +08:00
TalkList::insert($insertArr1);
2021-01-28 20:07:14 +08:00
}
2021-07-05 21:52:44 +08:00
$result = TalkRecords::create([
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-05 21:52:44 +08:00
'user_id' => 0,
'receiver_id' => $group_id,
2021-07-08 19:30:03 +08:00
'msg_type' => TalkMessageType::GROUP_INVITE_MESSAGE,
2021-07-05 21:52:44 +08:00
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
2021-01-28 20:07:14 +08:00
]);
2021-07-05 21:52:44 +08:00
TalkRecordsInvite::create([
2021-03-26 22:03:11 +08:00
'record_id' => $result->id,
'type' => 1,
2021-01-28 20:07:14 +08:00
'operate_user_id' => $user_id,
2021-03-26 22:03:11 +08:00
'user_ids' => implode(',', $friend_ids)
2021-01-28 20:07:14 +08:00
]);
Db::commit();
2021-03-26 22:03:11 +08:00
} catch (Exception $e) {
2021-01-28 20:07:14 +08:00
Db::rollBack();
2021-07-10 00:18:40 +08:00
return false;
2021-01-28 20:07:14 +08:00
}
2021-07-20 23:12:18 +08:00
LastMessage::getInstance()->save(TalkModeConstant::GROUP_CHAT, $user_id, $group_id, [
2021-05-20 22:23:48 +08:00
'text' => '[入群通知]',
'created_at' => date('Y-m-d H:i:s')
]);
2021-07-10 00:18:40 +08:00
// 加入聊天室
foreach ($friend_ids as $value) {
SocketRoom::getInstance()->addRoomMember(strval($group_id), strval($value));
}
2021-07-20 23:12:18 +08:00
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_TALK, [
2021-07-10 00:18:40 +08:00
'sender_id' => $user_id,
'receiver_id' => $group_id,
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-10 00:18:40 +08:00
'record_id' => $result->id
]));
return true;
2021-01-28 20:07:14 +08:00
}
/**
2021-03-26 22:03:11 +08:00
* 退出群组(仅普通管理员及群成员)
2021-01-28 20:07:14 +08:00
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
2021-01-28 20:07:14 +08:00
* @param int $group_id 群组ID
2021-07-10 00:18:40 +08:00
* @return bool
2021-01-28 20:07:14 +08:00
*/
public function quit(int $user_id, int $group_id)
{
2021-06-29 17:30:43 +08:00
// 判断是否属于管理员
2021-07-28 23:08:07 +08:00
if (di()->get(GroupMemberService::class)->isAuth($group_id, $user_id)) {
2021-07-10 00:18:40 +08:00
return false;
}
2021-01-28 20:07:14 +08:00
Db::beginTransaction();
try {
2021-03-26 22:03:11 +08:00
$count = GroupMember::where('group_id', $group_id)->where('user_id', $user_id)->where('is_quit', 0)->update([
'is_quit' => 1,
'deleted_at' => date('Y-m-d H:i:s'),
]);
2021-01-28 20:07:14 +08:00
2021-07-10 00:18:40 +08:00
if ($count == 0) throw new Exception('更新记录失败...');
2021-03-26 22:03:11 +08:00
2021-07-05 21:52:44 +08:00
$result = TalkRecords::create([
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-05 21:52:44 +08:00
'user_id' => 0,
'receiver_id' => $group_id,
2021-07-08 19:30:03 +08:00
'msg_type' => TalkMessageType::GROUP_INVITE_MESSAGE,
2021-07-05 21:52:44 +08:00
'content' => $user_id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
2021-01-28 20:07:14 +08:00
2021-07-05 21:52:44 +08:00
TalkRecordsInvite::create([
2021-03-26 22:03:11 +08:00
'record_id' => $result->id,
'type' => 2,
'operate_user_id' => $user_id,
2021-03-26 22:03:11 +08:00
'user_ids' => $user_id
]);
2021-01-28 20:07:14 +08:00
2021-07-05 21:52:44 +08:00
TalkList::where([
2021-07-20 23:12:18 +08:00
['talk_type', '=', TalkModeConstant::GROUP_CHAT],
2021-07-05 21:52:44 +08:00
['user_id', '=', $user_id],
['receiver_id', '=', $group_id],
2021-07-10 00:18:40 +08:00
])->update(['is_delete' => 1]);
2021-03-26 22:03:11 +08:00
2021-01-28 20:07:14 +08:00
Db::commit();
} catch (Exception $e) {
Db::rollBack();
2021-07-10 00:18:40 +08:00
return false;
2021-01-28 20:07:14 +08:00
}
2021-07-10 00:18:40 +08:00
// 移出聊天室
SocketRoom::getInstance()->delRoomMember(strval($group_id), strval($user_id));
2021-07-20 23:12:18 +08:00
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_TALK, [
2021-07-10 00:18:40 +08:00
'sender_id' => $user_id,
'receiver_id' => (int)$params['group_id'],
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-10 00:18:40 +08:00
'record_id' => $result->id
]));
return true;
2021-01-28 20:07:14 +08:00
}
/**
* 踢出群组(管理员特殊权限)
*
2021-04-20 16:30:57 +08:00
* @param int $group_id 群ID
* @param int $user_id 操作用户ID
2021-01-28 20:07:14 +08:00
* @param array $member_ids 群成员ID
2021-07-10 00:18:40 +08:00
* @return bool
2021-01-28 20:07:14 +08:00
*/
public function removeMember(int $group_id, int $user_id, array $member_ids)
{
2021-07-28 23:08:07 +08:00
if (di()->get(GroupMemberService::class)->isAuth($group_id, $user_id)) {
2021-07-10 00:18:40 +08:00
return false;
2021-01-28 20:07:14 +08:00
}
Db::beginTransaction();
try {
2021-03-26 22:03:11 +08:00
$count = GroupMember::where('group_id', $group_id)->whereIn('user_id', $member_ids)->where('is_quit', 0)->update([
'is_quit' => 1,
'deleted_at' => date('Y-m-d H:i:s'),
]);
2021-01-28 20:07:14 +08:00
2021-07-10 00:18:40 +08:00
if ($count == 0) throw new Exception('更新记录失败...');
2021-03-26 22:03:11 +08:00
2021-07-05 21:52:44 +08:00
$result = TalkRecords::create([
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-05 21:52:44 +08:00
'user_id' => 0,
'receiver_id' => $group_id,
2021-07-08 19:30:03 +08:00
'msg_type' => TalkMessageType::GROUP_INVITE_MESSAGE,
2021-07-05 21:52:44 +08:00
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
2021-01-28 20:07:14 +08:00
]);
2021-07-05 21:52:44 +08:00
TalkRecordsInvite::create([
2021-03-26 22:03:11 +08:00
'record_id' => $result->id,
'type' => 3,
2021-01-28 20:07:14 +08:00
'operate_user_id' => $user_id,
2021-03-26 22:03:11 +08:00
'user_ids' => implode(',', $member_ids)
2021-01-28 20:07:14 +08:00
]);
2021-07-20 23:12:18 +08:00
TalkList::whereIn('user_id', $member_ids)->where('receiver_id', $group_id)->where('talk_type', TalkModeConstant::GROUP_CHAT)->update([
2021-07-05 21:52:44 +08:00
'is_delete' => 1,
2021-03-26 22:03:11 +08:00
'updated_at' => date('Y-m-d H:i:s')
]);
2021-01-28 20:07:14 +08:00
Db::commit();
} catch (Exception $e) {
Db::rollBack();
2021-07-10 00:18:40 +08:00
return false;
}
// 移出聊天室
foreach ($member_ids as $uid) {
SocketRoom::getInstance()->delRoomMember(strval($group_id), strval($uid));
2021-01-28 20:07:14 +08:00
}
2021-07-20 23:12:18 +08:00
event()->dispatch(new TalkEvent(TalkEventConstant::EVENT_TALK, [
2021-07-10 00:18:40 +08:00
'sender_id' => $user_id,
'receiver_id' => $group_id,
2021-07-20 23:12:18 +08:00
'talk_type' => TalkModeConstant::GROUP_CHAT,
2021-07-10 00:18:40 +08:00
'record_id' => $result->id
]));
return true;
}
/**
* 更新用户群名片
*
* @param int $group_id 群ID
* @param int $user_id 用户ID
* @param string $user_card 用户名片
* @return bool
*/
public function updateMemberCard(int $group_id, int $user_id, string $user_card)
{
return (bool)GroupMember::where('group_id', $group_id)->where('user_id', $user_id)->update(['user_card' => $user_card]);
}
/**
* 获取用户所在的群聊
*
* @param int $user_id 用户ID
* @return array
*/
public function getUserGroups(int $user_id): array
{
$fields = [
'group.id',
'group.group_name',
'group.avatar',
'group.profile',
'group_member.leader',
];
$items = GroupMember::join('group', 'group.id', '=', 'group_member.group_id')
->where([
['group_member.user_id', '=', $user_id],
['group_member.is_quit', '=', 0]
])->orderBy('id', 'desc')->get($fields)->toArray();
$list = [];
if ($items) {
$list = TalkList::query()->where('user_id', $user_id)
2021-07-20 23:12:18 +08:00
->where('talk_type', TalkModeConstant::GROUP_CHAT)
2021-07-10 00:18:40 +08:00
->whereIn('receiver_id', array_column($items, 'id'))
->get(['receiver_id', 'is_disturb'])->keyBy('receiver_id')->toArray();
}
foreach ($items as $key => $item) {
$items[$key]['is_disturb'] = isset($list[$item['id']]) ? $list[$item['id']]['is_disturb'] : 0;
}
return $items;
2021-01-28 20:07:14 +08:00
}
}