im/app/enterprise/controller/Im.php

668 lines
24 KiB
PHP
Executable File
Raw Permalink 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\enterprise\controller;
use app\BaseController;
use think\facade\Request;
use think\facade\Db;
use app\enterprise\model\{User, Message, GroupUser, Friend};
use GatewayClient\Gateway;
use Exception;
use League\Flysystem\Util;
use think\facade\Cache;
use Char0n\FFMpegPHP\Movie;
class Im extends BaseController
{
protected $fileType = ['file', 'image','video','voice'];
// 获取联系人列表
public function getContacts()
{
$data = User::getUserList([['status', '=', 1], ['user_id', '<>', $this->userInfo['user_id']]], $this->userInfo['user_id']);
$count=Friend::where(['status'=>2,'friend_user_id'=>$this->uid])->count();
$time=Friend::where(['friend_user_id'=>$this->uid,'is_invite'=>1])->order('create_time desc')->value('create_time');
return success('', $data,$count,$time*1000);
}
//发送消息
public function sendMessage()
{
$param = $this->request->param();
$param['user_id'] = $this->userInfo['user_id'];
$is_group=$param['is_group']??0;
$chatSetting=$this->chatSetting;
if($is_group==0 && $chatSetting['simpleChat']==0){
return warning('目前禁止用户私聊!');
}
// 如果是单聊,并且是社区模式,需要判断是否是好友
if($is_group==0 && $this->globalConfig['sysInfo']['runMode']==2){
$friend=Friend::where(['friend_user_id'=>$this->uid,'create_user'=>$param['toContactId']])->find();
if(!$friend){
return warning('您不在TA的好友列表不能发消息');
}
$otherFriend=Friend::where(['friend_user_id'=>$param['toContactId'],'create_user'=>$this->uid])->find();
if(!$otherFriend){
return warning('TA还不是您的好友不能发消息');
}
}
$data = Message::sendMessage($param);
if ($data) {
return success('', $data);
} else {
return error('发送失败');
}
}
//转发消息
public function forwardMessage()
{
$param = $this->request->param();
$userIds=$param['user_ids'] ?? [];
if(!$userIds || count($userIds)>5){
return warning('请选择转发的用户或者数量不操作5个');
}
$msg_id=$param['msg_id'] ?? 0;
$message=Message::find($msg_id);
if(!$message){
return warning('消息不存在');
}
$message=$message->toArray();
$userInfo=$this->userInfo;
try{
$is_group=0;
$error=0;
$chatSetting=$this->chatSetting;
foreach($userIds as $k=>$v){
$msgInfo=$message;
if(strpos($v,'group')!==false){
$is_group=1;
}else{
$is_group=0;
}
if($is_group==0 && $chatSetting['simpleChat']==0){
$error++;
continue;
}
$msgInfo['id']=\utils\Str::getUuid();
$msgInfo['status']='successd';
$msgInfo['user_id']=$userInfo['user_id'];
$msgInfo['sendTime']=time()*1000;
$msgInfo['toContactId']=$v;
$msgInfo['content']=str_encipher($msgInfo['content'],false);
$msgInfo['fromUser']=[
'id'=>$userInfo['user_id'],
'avatar'=>avatarUrl($userInfo['avatar'],$userInfo['realname'],$userInfo['user_id'],120),
'displayName'=>$userInfo['realname']
];
$msgInfo['is_group']=$is_group;
// 如果是单聊,并且是社区模式,需要判断是否是好友
if($is_group==0 && $this->globalConfig['sysInfo']['runMode']==2){
$friend=Friend::where(['friend_user_id'=>$this->uid,'create_user'=>$v])->find();
if(!$friend){
$error++;
continue;
}
$otherFriend=Friend::where(['friend_user_id'=>$v,'create_user'=>$this->uid])->find();
if(!$otherFriend){
$error++;
continue;
}
}
Message::sendMessage($msgInfo);
}
}catch(\Exception $e){
return error($e->getMessage());
}
if ($error) {
$text='由于规则限制,转发失败'.$error.'条';
} else {
$text='转发成功';
}
return success($text);
}
// 获取用户信息
public function getUserInfo()
{
$user_id = $this->request->param('user_id');
$user=User::find($user_id);
if(!$user){
return error('用户不存在');
}
$user->avatar=avatarUrl($user->avatar,$user->realname,$user->user_id,120);
// 查询好友关系
$friend=Friend::where(['friend_user_id'=>$user_id,'create_user'=>$this->userInfo['user_id']])->find();
$user->friend=$friend ? : '';
$location='';
if($user->last_login_ip){
$location=implode(" ", \Ip::find($user->last_login_ip));
}
$user->location=$location;
$user->password='';
return success('', $user);
}
// 搜索用户
public function searchUser(){
$keywords=$this->request->param('keywords','');
if(!$keywords){
return success('',[]);
}
$map=['status'=>1,'account'=>$keywords];
$list=User::where($map)->field(User::$defaultField)->where([['account','<>',$this->userInfo['account']]])->select()->toArray();
if($list){
$ids=array_column($list,'user_id');
$friendList=Friend::getFriend([['create_user','=',$this->uid],['friend_user_id','in',$ids]]);
foreach($list as $k=>$v){
$list[$k]['avatar']=avatarUrl($v['avatar'],$v['realname'],$v['user_id'],120);
$list[$k]['friend']=$friendList[$v['user_id']] ?? '';
}
}
return success('', $list);
}
// 获取聊天记录
public function getMessageList()
{
$param = $this->request->param();
$is_group = isset($param['is_group']) ? $param['is_group'] : 0;
// 设置当前聊天消息为已读
$chat_identify = $this->setIsRead($is_group, $param['toContactId']);
$type = isset($param['type']) ? $param['type'] : '';
$map = ['chat_identify' => $chat_identify, 'status' => 1, 'is_group' => $is_group];
$where = [];
if ($type && $type != "all") {
$map['type'] = $type;
} else {
if (isset($param['type'])) {
$where[] = ['type', '<>', 'event'];
}
}
$keywords = isset($param['keywords']) ? $param['keywords'] : '';
if ($keywords && in_array($type, ['text', 'all'])) {
$where[] = ['content', 'like', '%' . $keywords . '%'];
}
$listRows = $param['limit'] ?: 20;
$pageSize = $param['page'] ?: 1;
$last_id = $param['last_id'] ?? 0;
if($last_id){
$where[]=['msg_id','<',$last_id];
}
$list = Message::getList($map, $where, 'msg_id desc', $listRows, $pageSize);
$data = $this->recombileMsg($list);
// 如果是消息管理器则不用倒序
if (!isset($param['type'])) {
$data = array_reverse($data);
}
return success('', $data, $list->total());
}
protected function recombileMsg($list)
{
$data = [];
$userInfo = $this->userInfo;
if ($list) {
$listData = $list->toArray()['data'];
$userList = User::matchUser($listData, true, 'from_user', 120);
foreach ($listData as $k => $v) {
// 屏蔽已删除的消息
if ($v['del_user']) {
$delUser = explode(',', $v['del_user']);
if (in_array($userInfo['user_id'], $delUser)) {
unset($list[$k]);
continue;
// $v['type']="event";
// $v['content']="删除了一条消息";
}
}
$content = str_encipher($v['content'],false);
$preview = '';
if (in_array($v['type'], $this->fileType)) {
$content = getFileUrl($content);
$preview = previewUrl($content);
}
$fromUser = $userList[$v['from_user']];
// 处理撤回的消息
if ($v['type'] == "event") {
if ($v['from_user'] == $userInfo['user_id']) {
$content = "" . $content;
} elseif ($v['is_group'] == 1) {
$content = $fromUser['realname'] . $content;
} else {
$content = "对方" . $content;
}
}
$data[] = [
'msg_id' => $v['msg_id'],
'id' => $v['id'],
'status' => "succeed",
'type' => $v['type'],
'sendTime' => $v['create_time'] * 1000,
'content' => $content,
'preview' => $preview,
'download' => $v['file_id'] ? request()->domain().'/filedown/'.encryptIds($v['file_id']) : '',
'is_read' => $v['is_read'],
'is_group' => $v['is_group'],
'toContactId' => $v['to_user'],
'from_user' => $v['from_user'],
'file_id' => $v['file_id'],
'file_cate' => $v['file_cate'],
'fileName' => $v['file_name'],
'fileSize' => $v['file_size'],
'fromUser' => $fromUser,
'extends'=>is_string($v['extends'])?json_decode($v['extends'],true) : $v['extends']
];
}
}
return $data;
}
// 设置当前窗口的消息默认为已读
public function setMsgIsRead()
{
$param = $this->request->param();
$this->setIsRead($param['is_group'], $param['toContactId']);
// 判断是否是一个二维数组
if (is_array($param['messages'][0] ?? '')) {
$messages=$param['messages'];
} else {
$messages=[$param['messages']];
}
if (!$param['is_group']) {
wsSendMsg($param['fromUser'], 'isRead', $messages, 0);
}
return success('');
}
// 设置消息已读
protected function setIsRead($is_group, $to_user)
{
if ($is_group) {
$chat_identify = $to_user;
$toContactId = explode('-', $to_user)[1];
// 更新群里面我的所有未读消息为0
GroupUser::editGroupUser(['user_id' => $this->userInfo['user_id'], 'group_id' => $toContactId], ['unread' => 0]);
} else {
$chat_identify = chat_identify($this->userInfo['user_id'], $to_user);
// 更新我的未读消息为0
Message::update(['is_read' => 1], [['chat_identify', '=', $chat_identify], ['to_user', '=', $this->userInfo['user_id']]]);
// 告诉对方我阅读了消息
wsSendMsg($to_user, 'readAll', ['toContactId' => $this->userInfo['user_id']]);
}
return $chat_identify;
}
// 聊天设置
public function setting()
{
$param = $this->request->param();
if ($param) {
User::where(['user_id' => $this->userInfo['user_id']])->update(['setting' => $param]);
return success('');
}
return warning('设置失败');
}
// 撤回消息
public function undoMessage()
{
$param = $this->request->param();
$id = $param['id'];
$message = Message::where(['id' => $id])->find();
if ($message) {
$text = "撤回了一条消息";
$fromUserName = "对方";
$toContactId = $message['to_user'];
if ($message['is_group'] == 1) {
$fromUserName = $this->userInfo['realname'];
$toContactId = explode('-', $message['chat_identify'])[1];
}
$message->content = str_encipher($text);
$message->type = 'event';
$message->is_undo = 1;
$message->create_time = time();
$message->save();
$data = $message->toArray();
$data['content'] = $fromUserName . $text;
wsSendMsg($toContactId, 'undoMessage', $data, $message['is_group']);
return success('');
} else {
return warning();
}
}
// 删除消息
public function removeMessage()
{
$param = $this->request->param();
$id = $param['id'];
$map = ['id' => $id];
$message = Message::where($map)->find();
if ($message) {
$message->del_user = $this->userInfo['user_id'];
if ($message['is_group'] == 1) {
if ($message['del_user']) {
$message->del_user .= ',' . $this->userInfo['user_id'];
}
} else {
if ($message['del_user'] > 0) {
$message->where($map)->delete();
return success('删除成功!');
}
}
$message->save();
return success('');
} else {
return warning('');
}
}
// 消息免打扰
public function isNotice()
{
$param = $this->request->param();
$user_id = $this->userInfo['user_id'];
$id = $param['id'];
if ($param['is_group'] == 1) {
$group_id = explode('-', $param['id'])[1];
GroupUser::update(['is_notice' => $param['is_notice']], ['user_id' => $user_id, 'group_id' => $group_id]);
} else {
$map = ['create_user' => $user_id, 'friend_user_id' => $id];
$friend = Friend::where($map)->find();
try {
if ($friend) {
$friend->is_notice = $param['is_notice'];
$friend->save();
} else {
$info = [
'create_user' => $user_id,
'friend_user_id' => $id,
'is_notice' => $param['is_notice']
];
Friend::create($info);
}
return success('');
} catch (Exception $e) {
return error($e->getMessage());
}
}
wsSendMsg($user_id,"setIsNotice",['id'=>$id,'is_notice'=>$param['is_notice'],'is_group'=>$param['is_group']]);
return success('');
}
// 设置聊天置顶
public function setChatTop()
{
$param = $this->request->param();
$user_id = $this->userInfo['user_id'];
$is_group = $param['is_group'] ?: 0;
$id = $param['id'];
try {
if ($is_group == 1) {
$group_id = explode('-', $param['id'])[1];
GroupUser::update(['is_top' => $param['is_top']], ['user_id' => $user_id, 'group_id' => $group_id]);
} else {
$map = ['create_user' => $user_id, 'friend_user_id' => $id];
$friend = Friend::where($map)->find();
if ($friend) {
$friend->is_top = $param['is_top'];
$friend->save();
} else {
$info = [
'create_user' => $user_id,
'friend_user_id' => $id,
'is_top' => $param['is_top']
];
Friend::create($info);
}
}
wsSendMsg($user_id,"setChatTop",['id'=>$id,'is_top'=>$param['is_top'],'is_group'=>$is_group]);
return success('');
} catch (Exception $e) {
return error($e->getMessage());
}
}
// 删除聊天
public function delChat()
{
$param = $this->request->param();
$user_id = $this->userInfo['user_id'];
$is_group = $param['is_group'] ?: 0;
$id = $param['id'];
if(!$is_group){
$chat_identify=chat_identify($user_id,$id);
}else{
return success('');
}
Message::where(['chat_identify' => $chat_identify])->update(['is_last' => 0]);
return success('');
}
// 向用户发送消息
public function sendToMsg(){
$param=$this->request->param();
$toContactId=$param['toContactId'];
$type=$param['type'];
$status=$param['status'];
$event=$param['event'] ?? 'calling';
if($event=='calling'){
$status=3;
}
$sdp=$param['sdp'] ?? '';
$iceCandidate=$param['iceCandidate'] ?? '';
$callTime=$param['callTime'] ?? '';
$msg_id=$param['msg_id'] ?? '';
$id=$param['id'] ?? '';
$code=($param['code'] ?? '') ?: 901;
// 如果该用户不在线,则发送忙线
Gateway::$registerAddress = config('gateway.registerAddress');
if(!Gateway::isUidOnline($toContactId)){
$toContactId=$this->userInfo['user_id'];
$code=907;
$event='busy';
sleep(1);
}
switch($code){
case 902:
$content='已取消通话';
break;
case 903:
$content='已拒绝';
break;
case 905:
$content='未接通';
break;
case 906:
$content='通话时长 '.date("i:s",$callTime);
break;
case 907:
$content='忙线中';
break;
case 908:
$content='其他端已操作';
break;
default:
$content=$type==1 ?'视频通话' : '语音通话';
break;
}
switch($event){
case 'calling':
$content=$type==1 ?'视频通话' : '语音通话';
break;
case 'acceptRtc':
$content='接听通话请求';
break;
case 'iceCandidate':
$content='数据交换中';
break;
}
$userInfo=$this->userInfo;
$userInfo['id']=$userInfo['user_id'];
$data=[
'id'=>$id,
'msg_id'=>$msg_id,
'sendTime'=>time()*1000,
'toContactId'=>$toContactId,
'content'=>$content,
'type'=>'webrtc',
'status'=>'succeed',
'is_group'=>0,
'is_read'=>0,
'fromUser'=>$userInfo,
'extends'=>[
'type'=>$type, //通话类型1视频0语音。
'status'=>$status, //1拨打方2接听方
'event'=>$event,
'callTime'=>$callTime,
'sdp'=>$sdp,
'code'=>$code, //通话状态:呼叫901取消902拒绝903接听904未接通905接通后挂断906忙线907,其他端操作908
'iceCandidate'=>$iceCandidate,
'isMobile'=>$this->request->isMobile() ? 1 : 0,
]
];
if($event=='calling'){
$chat_identify=chat_identify($userInfo['id'],$toContactId);
$msg=[
'from_user'=>$userInfo['id'],
'to_user'=>$toContactId,
'id'=>$id,
'content'=>str_encipher($content),
'chat_identify'=>$chat_identify,
'create_time'=>time(),
'type'=>$data['type'],
'is_group'=>0,
'is_read'=>0,
'extends'=>$data['extends'],
];
$message=new Message();
$message->update(['is_last'=>0],['chat_identify'=>$chat_identify]);
$message->save($msg);
$msg_id=$message->msg_id;
$data['msg_id']=$msg_id;
// 将接收人设置为发送人才能定位到该消息
$data['toContactId']=$userInfo['id'];
$data['toUser']=$toContactId;
}elseif($event=='hangup'){
$message=Message::where(['id'=>$id])->find();
if(!$message){
return error('通话失败!');
}
if($message){
$message->content=str_encipher($content);
$extends=$message->extends;
$extends['code']=$code;
$extends['callTime']=$callTime;
$message->extends=$extends;
$message->save();
}
}
wsSendMsg($toContactId,'webrtc',$data);
$wsData=$data;
if(in_array($event,['calling','acceptRtc','hangup'])){
if(in_array($event,['acceptRtc','hangup'])){
$data['extends']['event']='otherOpt'; //其他端操作
}
$data['toContactId']=$toContactId;
wsSendMsg($userInfo['id'],'webrtc',$data);
}
return success('',$wsData);
}
// 修改密码
public function editPassword()
{
if(env('app.demon_mode',false)){
return warning('演示模式不支持修改');
}
$user_id = $this->userInfo['user_id'];
$user=User::find($user_id);
if(!$user){
return warning('用户不存在');
}
$account=$user->account;
$code=$this->request->param('code','');
$originalPassword = $this->request->param('originalPassword', '');
if($code){
if(Cache::get($account)!=$code){
return warning('验证码不正确!');
}
}elseif($originalPassword){
if(password_hash_tp($originalPassword,$user->salt)!= $user->password){
return warning('原密码不正确!');
}
}else{
return warning('参数错误!');
}
try{
$password = $this->request->param('password','');
if($password){
$salt=$user->salt;
$user->password= password_hash_tp($password,$salt);
}
$user->save();
return success('修改成功');
}catch (\Exception $e){
return error('修改失败');
}
}
// 修改用户信息
public function updateUserInfo(){
try{
$data = $this->request->param();
$user=User::find($this->uid);
if(!$user){
return warning('用户不存在');
}
$user->realname =$data['realname'];
$user->email =$data['email'];
$user->motto=$data['motto'];
$user->sex =$data['sex'];
$user->name_py= pinyin_sentence($data['realname']);
$user->save();
return success('修改成功', $data);
}catch (\Exception $e){
return error($e->getMessage());
}
}
// 修改账户
public function editAccount(){
if(env('app.demon_mode',false)){
return warning('演示模式不支持修改');
}
$code=$this->request->param('code','');
$newCode=$this->request->param('newCode','');
$account=$this->request->param('account','');
$isUser=User::where('account',$account)->find();
if($isUser){
return warning('账户已存在');
}
$user=User::find($this->uid);
if(!$user){
return warning('用户不存在');
}
// 如果已经认证过了,则需要验证验证码
if($user->is_auth){
if(Cache::get($user->account)!=$code){
return warning('验证码不正确!');
}
}
if(Cache::get($account)!=$newCode){
return warning('新账户验证码不正确!');
}
try{
$user->account=$account;
$user->save();
return success('修改成功');
}catch (\Exception $e){
return error('修改失败');
}
}
}