*/ namespace app\enterprise\model; use app\admin\model\KeywordLanguages; use app\admin\model\QuestionLanguages; use app\manage\model\Config; use app\BaseModel; use think\facade\Db; use think\facade\Cache; class Message extends BaseModel { protected $pk="msg_id"; protected $json = ["extends"]; protected $jsonAssoc = true; protected static $fileType=['file','image','video','voice','emoji']; //给用户发送自动消息 public static function sendAutoReply($field, $user_id, $cs_uid, $language_code){ //获取自动回复的消息内容 $content = Config::getFieldValue($field, $language_code); // 如果设置了自动回复消息,则发送 if($content){ $userInfo=User::field('user_id,realname,avatar')->where(['user_id'=>$cs_uid])->find();//客服信息 if($userInfo){ $userInfo = $userInfo->toArray(); $userInfo['dispalayName']=$userInfo['realname']; $userInfo['id']=$userInfo['user_id']; $userInfo['avatar']=avatarUrl($userInfo['avatar'],$userInfo['realname'],$userInfo['user_id']); $msg=[ 'id'=>\utils\Str::getUuid(), 'user_id'=>$cs_uid, 'content'=>$content, 'toContactId'=>$user_id, 'sendTime'=>time()*1000, 'type'=>'event', 'is_group'=>0, 'status'=>'succeed', 'fromUser'=>$userInfo, 'at'=>[], ]; if (!empty($msg['content'])) { self::sendMsg($msg,0,1); } } } } // 添加聊天记录 public static function addData($data){ return Db::name('message')->insert($data); } // 更新消息状态 public static function editData($update,$map){ return Db::name('message')->where($map)->update($update); } // 查询聊天记录 public static function getList($map,$where,$sort,$listRows,$pageSize){ $list= Db::name('message') ->where($map) ->where($where) ->order($sort) ->paginate(['list_rows'=>$listRows,'page'=>$pageSize]); return $list; } // 发送消息 public function sendMessage($param,$globalConfig=false){ $param['language_code'] = $param['language_code'] ?? 'en'; $is_group = $param['is_group'] ?? 0; $uid=self::$uid ? : ($param['user_id'] ?? 1); $is_robot = false; //是否给机器人发送消息 if($param['toContactId']==-1){ $is_group=0; } // 如果是系统账号,直接禁言 if($is_group>1){ $this->error=lang('im.forbidChat'); return false; } $isForward=$param['is_forward'] ?? 0; $sendInterval = $globalConfig['chatInfo']['sendInterval'] ?? 0; // 如果设置了消息频率则验证,转发不收限制 if ($sendInterval && !$isForward) { if (Cache::has('send_' . $uid)) { $this->error=lang('im.sendTimeLimit',['time'=>$sendInterval]); return false; } } if($param['type']=='text'){ // 限制文字内容长度 $text = strip_tags($param['content']); $textLen = mb_strlen($text); if ($textLen > 2048) { $this->error=lang('im.msgContentLimit') . $textLen; return false; } $param['content'] = preg_link($param['content']); // 接入聊天内容检测服务 event('GreenText',['content'=>$param['content'],'service'=>"chat_detection"]); } $chatSetting = $globalConfig['chatInfo']; if($param['toContactId']!=-1){ if ($is_group == 0) { $kefuUser=$chatSetting['autoAddUser']['user_ids'] ?? []; $manageUser=User::where([['status','=',1],['role','>',0]])->column('user_id'); $kefu=array_unique(array_merge($kefuUser,$manageUser)); $csUid = self::$userInfo['cs_uid'] ?? 0; $manage=false; // 发送者和接受者是客服或者管理员也可以发送消息 if(in_array($uid,$kefu) || in_array($param['toContactId'],$kefu)){ $manage=true; } if($chatSetting['simpleChat'] == 0 && !$manage){ $this->error=lang('im.forbidChat'); return false; } // 如果是单聊,并且是社区模式和不是自己的客服、需要判断是否是好友 if ($globalConfig['sysInfo']['runMode'] == 2 && $csUid != $param['toContactId'] && !$manage) { // 判断我是不是对方的客服 $cus = User::where(['user_id' => $param['toContactId']])->value('cs_uid'); if ($cus != $uid) { $friend = Friend::where(['friend_user_id' => $uid, 'create_user' => $param['toContactId']])->find(); if (!$friend) { $this->error=lang('im.notFriend'); return false; } $otherFriend = Friend::where(['friend_user_id' => $param['toContactId'], 'create_user' => $uid])->find(); if (!$otherFriend) { $this->error=lang('im.friendNot'); return false; } } } //判断是否给机器人客服发送消息 $autoCsUid = getAutoCsUid(); if ($autoCsUid && $param['toContactId'] == $autoCsUid) { $is_robot = true; } }else{ // 群聊必须群成员才能发送消息 $group_id = explode('-', $param['toContactId'])[1] ?? ''; if(!$group_id){ $this->error=lang('system.parameterError'); return false; } if(!self::nospeak($group_id,$uid)){ if($isForward){ return false; } return shutdown(lang('group.notSpeak')); } // 群聊必须群成员才能发送消息 $groupUser=GroupUser::where(['user_id'=>$uid,'status'=>1,'group_id'=>$group_id,'delete_time'=>0])->find(); if(!$groupUser){ $this->error = lang('group.notCustom'); return false; } if($groupUser['no_speak_time']>time()){ $this->error = lang('group.notSpeak',['time'=>date('Y-m-d H:i:s',$groupUser['no_speak_time'])]); return false; } } } if ($sendInterval) { Cache::set('send_' . $uid, time(), $sendInterval); } $data = self::sendMsg($param,$is_group, 0, $uid); // 机器人自动回复问题推送给用户 if ($is_robot && $param['type'] == 'text') { if (!empty($param['question_id'])) { $param['type'] = 'answer'; $param['content'] = QuestionLanguages::where('id', $param['question_id'])->value('answer'); $param['extends'] = json_encode([ 'question_id' => $param['question_id'], ]); } else { //获取关键词匹配 $keyword_ids = KeywordLanguages::getKeywordByContent($param['content']); $question = QuestionLanguages::getQuestion($keyword_ids, $param['content']); $data['question'] = $question; if ($question) { $param['type'] = 'list'; $content = [ 'title' => Config::getFieldValue('reply_keyword',$param['language_code']), 'list' => $question, ]; $param['content'] = json_encode($content); } else { $param['type'] = 'text'; $param['content'] = Config::getFieldValue('reply_keyword_math_fail',$param['language_code']); } } if (!empty($param['content'])) { $fromUserId = (int)$param['toContactId']; $user_id = (int)$param['user_id']; $param['toContactId'] = $user_id; $param['user_id'] = $fromUserId; $param['fromUser'] = null; $param['id'] = \utils\Str::getUuid(); self::sendMsg($param,$is_group, 0, $user_id); } } return $data; } //实际发送消息 public static function sendMsg($param,$is_group=0,$is_sys=0, $uid=0){ // $uid = $uid ?: ($param['user_id'] ?? 1); $uid = self::$uid ?: ($param['user_id'] ?? 1); $toContactId=$param['toContactId']; $manage=[]; // 重新建立会话,更新会话删除记录 $isDelChat=ChatDelog::where(['user_id'=>$uid,'to_user'=>$toContactId])->find(); if($isDelChat){ ChatDelog::where(['user_id'=>$uid,'to_user'=>$toContactId])->delete(); ChatDelog::updateCache($uid); } if($is_group==1){ $group_id = explode('-', $param['toContactId'])[1] ?? ''; $chat_identify=$toContactId; $toContactId=$group_id; $manage=GroupUser::getGroupManage($group_id); }else{ $chat_identify=chat_identify($param['user_id'],$toContactId); } $fileSzie=isset($param['file_size'])?$param['file_size']:''; $fileName=isset($param['file_name'])?$param['file_name']:''; $ossUrl=getDiskUrl(); // 如果是转发图片文件的消息,必须把域名去除掉 $content=$param['content']; if(in_array($param['type'],self::$fileType)){ if(strpos($param['content'],$ossUrl)!==false){ $content=str_replace($ossUrl,'',$param['content']); } } $param['content']=$content; $atList=($param['at'] ?? null) ? array_map('intval', $param['at']): []; // 如果at里面有0,代表@所有人 if($atList && in_array(0,$atList)){ $atList=GroupUser::where([['group_id','=',$toContactId],['status','=',1],['user_id','<>',$param['user_id']]])->column('user_id'); } $at=$atList ? implode(',',$atList) : null; $data=[ 'from_user'=>$param['user_id'], 'to_user'=>$toContactId, 'id'=>$param['id'], 'content'=>$param['type'] != 'list' ? str_encipher($param['content'],true) : $param['content'], 'chat_identify'=>$chat_identify, 'create_time'=>time(), 'type'=>$param['type'], 'is_group'=>$toContactId==-1 ? 3 : $is_group, 'is_read'=>$is_group ? 1 : 0, 'file_id'=>$param['file_id'] ?? 0, "file_cate"=>$param['file_cate'] ?? 0, 'file_size'=>$fileSzie, 'file_name'=>$fileName, 'at'=>$at, 'pid'=>$param['pid'] ?? 0, 'extends'=>($param['extends'] ?? null) ? $param['extends'] : null, 'translate_content' => $param['translate_content'] ?? null, 'language_code' => $param['language_code'] ?? '', ]; $message=new self(); $message->update(['is_last'=>0],['chat_identify'=>$chat_identify]); $message->save($data); // 拼接消息推送 $type=$is_group?'group':'simple'; $sendData=$param; $sendData['status']='succeed'; $sendData['at']=$atList; $sendData['msg_id']=$message->msg_id; $sendData['is_click']=(int)$message->is_click; $sendData['is_read']=0; $sendData['to_user']=(string)$toContactId; $sendData['role']=$manage[self::$uid] ?? 3; $sendData['sendTime']=(int)$sendData['sendTime']; $sendData['translate_content'] = $param['translate_content'] ?? ''; //这里单聊中发送对方的消息,对方是接受状态,自己是对方的联系人,要把发送对象设置为发送者的ID。 if($is_group){ $sendData['toContactId']=$param['toContactId']; // 将团队所有成员的未读状态+1 GroupUser::editGroupUser([['group_id','=',$toContactId],['user_id','<>',$uid]],['unread'=>Db::raw('unread+1')]); }else{ //$sendData['toContactId']=$toContactId;//$uid; $sendData['toContactId'] = $param['user_id']; } $sendData['fileSize']=$fileSzie; $sendData['fileName']=$fileName; if(in_array($sendData['type'],self::$fileType)){ $sendData['content']=getFileUrl($sendData['content']); if($sendData['type']=='image'){ $pre=1; }else{ $pre=2; } $sendData['preview']=previewUrl($sendData['content'],$pre); $sendData['extUrl']=getExtUrl($sendData['content']); $sendData['download']= $sendData['file_id'] ? getMainHost().'/filedown/'.encryptIds($sendData['file_id']) : ''; } $forContactId=$sendData['toContactId']; if($is_sys){ $forContactId=$toContactId; } if($is_group==0){ $toContactId=[$toContactId,$param['user_id']]; } $sendData['toUser']=(string)$param['toContactId']; $user=new User(); // 将聊天窗口的联系人信息带上,方便临时会话 $sendData['contactInfo']=$user->setContact($forContactId,$is_group,$sendData['type'],$sendData['content']); if (empty($sendData['fromUser'])) { $sendData['fromUser'] = [ 'id' => $sendData['contactInfo']['id'], 'displayName' => $sendData['contactInfo']['displayName'], 'avatar' => $sendData['contactInfo']['avatar'], 'account' => '', ]; } $sendData['fromUser']['id']=(int)$sendData['fromUser']['id']; // 向发送方发送消息 wsSendMsg($toContactId,$type,$sendData,$is_group); $sendData['toContactId']=$param['toContactId']; return $sendData; } // 群禁言 public static function nospeak($group_id,$user_id){ $group=Group::find($group_id); if($group->owner_id==$user_id){ return true; } if($group->setting){ $setting=json_decode($group->setting,true); $nospeak=isset($setting['nospeak'])?$setting['nospeak']:0; $role=GroupUser::where(['group_id'=>$group_id,'user_id'=>$user_id])->value('role'); if($nospeak==1 && $role>2){ return false; }elseif($nospeak==2 && $role!=1){ return false; } } return true; } // 将消息中的@用户加入到atListQueue中 public static function setAtread($messages,$user_id){ foreach($messages as $k=>$v){ if(!isset($v['at'])){ continue; } if($v['at'] && in_array($user_id,$v['at'])){ $atListQueue=Cache::get("atListQueue"); $atListQueue[$v['msg_id']][]=$user_id; Cache::set("atListQueue",$atListQueue); } } } }