userService = new UserService; } /** * 直播列表 * @param Request $request [description] * @return [type] [description] */ public function liveList($nopage=0) { try { $lives = InteractLive::with('femaleLiveLog.female:id,photo,nickname', 'femaleLiveLog.matchMaker:id,nickname,app_avatar', 'channels')/*->whereHas('femaleLiveLog')*/->where('in_live', 1)->orderBy('click_num', 'desc'); if ($nopage) { $lives = $lives->limit(10)->get(); }else{ $lives = $lives->paginate(16); } $result = $this->livesInfo($lives); if (empty($result)) return $lives; return $result; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 直播列表V2 * @param Request $request [description] * @return [type] [description] */ public function liveListV2($nopage=0) { try { $lives = InteractLive::with('channels')/*->whereHas('femaleLiveLog')*/->where('in_live', 1)->orderBy('click_num', 'desc'); if ($nopage) { $lives = $lives->limit(10)->get(); }else{ $lives = $lives->paginate(16); } return $lives; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 直播首页轮播 * @return [type] [description] */ public function liveCarousel() { $carousel = [ [ 'pic'=>'https://images.ufutx.com/202011/26/03dadd5626725d2e72e622a2c7f95a02.png', 'path'=>'https://mp.weixin.qq.com/s/UFL2ikgGN37jo8ZYKQc2-Q' ] ]; return $carousel; } //创建直播 public function storeInteractLive() { try { \DB::beginTransaction(); $user = auth()->user(); //直播间参数 //创建福恋直播 $live = $this->storeFLInteractLive($user); \DB::commit(); if (empty($live)) throw new \Exception("创建福恋直播失败", 1); //创建IM聊天室 if (empty($live->chat_room_id)) { //网易账号 $user->createIMUser(); $chat_room = $live->createChatRoom($user->id, $live->name); if (empty($chat_room)) throw new \Exception("创建IM聊天室失败", 1); $live->chat_room_id = $chat_room['roomid']; $live->save(); \DB::commit(); } //创建主播直播流 $channel_name = env('APP_ENV').'_live_id_'.$live->id.'_main'; $channel = $live->createLiveChannel($channel_name, 'main'); if (empty($channel)) throw new \Exception("创建直播流失败", 1); //创建互动直播 //判断直播间是否存在 $room = $live->channelRoom(); if (empty($room) || !in_array($room['stats'] , [1,2,4])) { $channel_id = $live->createChannelRoom(0, $live->name, $user->id, $webrtc=0, $selfconfig=[], $roomconfig=''); if (empty($channel_id)) throw new \Exception("创建音视频房间失败", 1); $live->channel_id = $channel_id; $live->save(); \DB::commit(); //增加房间推流任务 $result = $live->addRtmpTask($user->id); if (empty($result)) throw new \Exception("直播布局失败", 1); } //是否在开播状态 if (empty($live->in_live)) { //修改开播信息 $live->increment('num'); $live->in_live = 1; $live->save(); //开始直播 $this->startNextLiveLog($live); } $live->channels; \DB::commit(); //发送广播通知 SendIMBroadcastMsg::dispatch()->onQueue('love'); return $live; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } //创建直播v2 public function storeInteractLiveV2() { try { \DB::beginTransaction(); $user = auth()->user(); //直播间参数 //创建福恋直播 $live = $this->storeFLInteractLive($user); \DB::commit(); if (empty($live)) throw new \Exception("创建福恋直播失败", 1); //创建IM聊天室 if (empty($live->chat_room_id)) { //网易账号 $user->createIMUser(); $chat_room = $live->createChatRoom($user->id, $live->name); if (empty($chat_room)) throw new \Exception("创建IM聊天室失败", 1); $live->chat_room_id = $chat_room['roomid']; $live->save(); \DB::commit(); } //创建主播直播流 $channel_name = env('APP_ENV').'_team_live_id_'.$live->id.'2'; $channel = $live->createLiveChannel($channel_name,'main'); if (empty($channel)) throw new \Exception("创建直播流失败", 1); //创建互动直播 //判断直播间是否存在 $room = $live->channelRoom(); if (empty($room) || !in_array($room['stats'] , [1,2,4])) { $im = new IMService(); $result = $im->createChannelV2($live->name, $user->id); if(!isset($result['cid'])) throw new \Exception("创建音视频房间失败", 1); $live->channel_id = $result['cid']; $live->save(); \DB::commit(); //增加房间推流任务 $result = $live->addRtmpTask($user->id); if (empty($result)) throw new \Exception("直播布局失败", 1); } //是否在开播状态 if (empty($live->in_live)) { //修改开播信息 $live->increment('num'); $live->in_live = 1; $live->save(); //开始直播 $this->startNextLiveLog($live); } $live->channels; \DB::commit(); //发送广播通知 // SendIMBroadcastMsg::dispatch()->onQueue('love'); return $live; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } /** * 创建福恋直播间 * @param array $param [description] * @return [type] [description] */ public function storeFLInteractLive($user) { try { $password = request()->input('password'); $has_password = request()->input('has_password', 0); $male_fee = request()->input('male_fee',0); $name = $user->nickname.uniqid(); $param = [ 'user_id'=>$user->id, 'name'=>$name, 'password'=>$password, 'has_password'=>$has_password, 'male_fee'=>$male_fee, 'in_live'=>0, 'num'=>0, ]; $live = auth()->user()->InteractLive; if (empty($live)) { $live = InteractLive::create($param); }else { if (empty($live->name)) { $live->name = $name; } $live->password = $password; $live->has_password = $has_password; $live->male_fee = $male_fee; $live->save(); } return $live; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 直播详情 * @param [type] $live_id [description] * @param [type] $match_maker 是否携带红娘信息 * @param [type] $leisureLiveLog 空闲的直播记录 * @param [type] $lastLiveLog 正在直播的直播记录 * @return [type] [description] */ public function live($live_id, $match_maker=null, $leisureLiveLog=false, $lastLiveLog=false) { try { $live = InteractLive::where('id', $live_id); if ($match_maker) { $live = $live->with('matchMaker:id,nickname,app_avatar'); } if ($leisureLiveLog) { $live = $live->with('leisureLiveLog'); } if ($lastLiveLog) { $live = $live->with('lastLiveLog'); } $live = $live->first(); return $live; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 通过聊天室id查找直播间 * @param [type] $room_id [description] * @return [type] [description] */ public function liveByChatroom($room_id) { try { $live = InteractLive::with('femaleLiveLog.female:id,photo,nickname', 'femaleLiveLog.matchMaker:id,nickname,app_avatar', 'channels')->where('chat_room_id', $room_id)->first(); if (empty($live)) return ['code'=>1, 'msg'=>'直播间不存在']; $this->liveInfo($live); return $live; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 上线房间用户 * @param [type] $live [description] * @param [type] $user [description] */ public function addLiveMember($live, $user) { try { $member = $live->memberLogs()->where('user_id', $user->id)->first(); if (empty($member)) { $live->memberLogs()->create([ 'user_id'=>$user->id, 'in_live'=>1, ]); }elseif ($member && empty($member->in_live)) { $member->in_live = 1; $member->save(); } return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 下线房间用户 * @param [type] $live_id [description] * @param [type] $user_id [description] * @return [type] [description] */ public function leaveLiveMember($live, $user) { try { $member = $live->memberLogs()->where('user_id', $user->id)->where('in_live', 1)->first(); if ($member) { $member->in_live = 0; $member->save(); } return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * [inLiveMembers 直播间在线人数列表] * @param [type] $live [description] * @param [type] $limit [description] * @param [type] $nopage [description] * @return [type] [description] */ public function inLiveMembers($live, $limit) { try { $chatromm_members = $live->chatroomMembers($live->chat_room_id, $type=1, $endtime=0, $limit); return $chatromm_members; } catch (\Exception $e) { $this->getError($e); return false; } } /** * [applyInteractLive 申请直播] * @param [type] $live_id [description] * @return [type] [description] */ public function applyInteractLive($live_id) { try { $log = InteractApplyLog::firstOrCreate(['user_id'=>auth()->id(), 'live_id'=> $live_id, 'is_audited'=>0]); $log->updated_at = date('Y-m-d H:i:s'); $log->save(); return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 每日赠送三张不限时相亲卡 * 未使用不再赠送 * @param [type] $user_id [description] * @return [type] [description] */ public function daliySendLiveCard($user_id) { try { //判断今天是否赠送 $count = InteractLiveCard::where('type', 'give')->where('user_id', $user_id)->where('created_at', '>', date('Y-m-d'))->count(); if ($count) { return true; } //判断剩余赠送卡数 $count = InteractLiveCard::where('type', 'give')->where('user_id', $user_id)->where('is_used', 0)->count()?:0; $num = 3 - $count; if ($num) { $result = $this->sendLiveCard($user_id, $live_id=0, $num); if (empty($result)) throw new \Exception("创建赠送记录失败", 1); } return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 赠送相亲卡 * @param [type] $user_id [description] * @param integer $live_id [description] * @param integer $num [description] * @param [type] $end_time [description] * @return [type] [description] */ public function sendLiveCard($user_id, $live_id=0, $num=3, $end_time=null) { try { $data = []; $date = date('Y-m-d H:i:s'); while ($num) { $da = [ 'live_id'=>0, 'user_id'=>$user_id, 'type'=>'give', 'minute'=>0, 'end_time'=>$end_time, 'is_used'=>0, 'created_at'=>$date, 'updated_at'=>$date, ]; $data[] = $da; $num--; } InteractLiveCard::insert($data); return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 相亲申请记录 * @param [type] $live_id [description] * @param integer $is_audited [description] * @return [type] [description] */ public function liveApplyLogs($live_id, $is_audited=0) { try { $logs = InteractApplyLog::with('user:id,nickname,app_avatar,sex')->whereHas('user')->where('live_id', $live_id)->where('is_audited',$is_audited)->paginate(); foreach ($logs as $log) { // $log->id = $log->user->id; $log->nickname = $log->user->nickname; $log->app_avatar = $log->user->app_avatar; $log->sex = $log->user->sex; $profile = $log->user->profileCourtship; if (empty($profile)) { unset($log->user->profileCourtship, $log->user); continue; } $log->age = \CommonUtilsService::getAge($profile->birthday); $log->city = $profile->city; unset($log->user->profileCourtship, $log->user); } return $logs; } catch (\Exception $e) { $this->getError($e); return false; } } /** * [auditedApplyLog 审核相亲记录] * @param [type] $log_id [description] * @return [type] [description] */ public function auditedApplyLog($log) { try { if ($log->is_audited) { return ['code'=>1, 'msg'=>'该记录已经审核过']; } $is_audited = request()->input('is_audited'); $log->is_audited = $is_audited; $log->save(); return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 直播间正在直播用户信息 * @param [type] $live_id [description] * @return [type] [description] */ public function liveUsersInfo($live_id) { try { $live = $this->live($live_id); $log = $live->liveLogs()->where('num',$live->num)->where('is_over', 0)->orderBy('id', 'desc')->first(); if (empty($log)) return $log; //缓存在嘉宾信息 $key = $log->usersInfoKey(); if (Cache::has($key) && Cache::get($key)) { $log = Cache::get($key); }else{ $user_param = 'id,app_avatar,sex,is_approved,nickname'; $profile_param = 'user_id,birthday,stature,city,introduction'; $log = $live->liveLogs()->with('matchMaker:'.$user_param, 'female:'.$user_param, 'male:'.$user_param, 'matchMaker.profileCourtship:'.$profile_param, 'female.profileCourtship:'.$profile_param, 'male.profileCourtship:'.$profile_param)->where('is_over', 0)->where('num',$live->num)->orderBy('id', 'desc')->first(); $log->channels = $live->channels; unset($live->channels); Cache::forever($key, $log); } if (empty($log)) return $log; //是否是会员 if ($log->matchMaker) { $matchMaker = $log->matchMaker; $log->matchMaker = $this->liveUserInfo($matchMaker); } if ($log->female) { $female = $log->female; $log->female = $this->liveUserInfo($female); } if ($log->male) { $male = $log->male; $log->male = $this->liveUserInfo($male); } $log->live = $live; return $log; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 观众用户信息 * @param [type] $user [description] * @return [type] [description] */ public function liveUserInfo($user) { try { $mine = auth()->user(); //是否超级会员 $user->isSuper = $user->isSuperRank($user->id); //粉丝数 $user->follower_count = $user->followers()->count()?:0; //关注数 $user->follow_count = $user->followings()->count()?:0; //是否已关注 $user->is_followed = $mine->isFollowing($user); //年龄 $user->age = \CommonUtilsService::getAge($user->profileCourtship?$user->profileCourtship->birthday:null); //是否是好友 $user->isFriend = $mine->isFriend($user)?1:0; return $user; } catch (\Exception $e) { $this->getError($e); return false; } return $user; } /** * 踢人 * @param [type] $live_id [description] * @param [type] $user_id [description] * @return [type] [description] */ public function banLiveUser($live_id, $user_id) { try { $live = $this->live($live_id, false,false, true); //检查权限 if ($live->user_id != auth()->id()) return ['code'=>1, 'msg'=>'暂无权限']; //生成踢人记录); $live->banLogs()->create([ 'user_id'=>$user_id, 'start_time'=>date('Y-m-d H:i:s'), 'end_time'=> date('Y-m-d H:i:s',strtotime('+1 day', time())), ]); //是否正在直播 $log = $live->lastLiveLog; if ($log && ($log->female_user_id == $user_id || $log->male_user_id == $user_id )) { //结束直播 $log = $this->overLiveLog($live, $log); //扣费 // $this->deductionCoin($log, $user_id); } return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 扣费 * @param [type] $log [description] * @param [type] $user_id [description] * @return [type] [description] */ public function deductionCoin($log, $user_id) { //todo //更新福币信息 //生成扣费记录 } /** * 结束直播 * @param [type] $log [description] * @param [type] $user_id [description] * @return [type] [description] */ public function overLiveLog($live, $log) { //单人结束与双人结束 if ($log->female_user_id && $log->male_user_id) {//双人 //结束直播 $log->duration = $this->calcuLogDuration($log); } $log->end_time = date('Y-m-d H:i:s'); $log->is_over = 1; $log->click_num = $this->calcuLogClickNum($live, $log); $log->save(); //删除缓存嘉宾信息 $key = $log->usersInfoKey(); Cache::forget($key); return $log; } /** * 计算当前直播时长 * @param [type] $log [description] * @return [type] [description] */ public function calcuLogDuration($log) { if (empty($log->start_time)) return 0; $start_time = strtotime($log->start_time); $end_time = time(); $second = $end_time - $start_time; $minute = number_format($second / 60, 2, '.', ''); return $minute; } /** * 计算单场直播的点击量 * @param [type] $live [description] * @param [type] $log [description] * @return [type] [description] */ public function calcuLogClickNum($live, $log) { //当前开播场次的所有点击量 $click_num = $live->liveLogs()->where('id', '<>', $log->id)->whereNotNull('female_user_id')->whereNotNull('male_user_id')->where('num', $live->num)->sum('click_num')?:0; $click_num_key = $live->clickNumKey(); $live_click_num = (int)Cache::get($click_num_key); return $live_click_num > $click_num?($live_click_num- $click_num):0; } /** * 加入互动直播 * @param [type] $live_id [description] * @return [type] [description] */ public function joinInteractLive($live_id) { try { $user = auth()->user(); $live = $this->live($live_id, false, true, true); if (empty($live)) throw new \Exception("直播不存在", 1); //是否有权限 $result = $this->checkJoinLive($live); if (empty($result)) throw new \Exception("检测权限失败", 1); if ($result && is_array($result)) return $result; //是否是自己正在直播,掉线重新进入 $lastLiveLog = $live->lastLiveLog; $log = $live->leisureLiveLog; if ($lastLiveLog && $log) throw new \Exception("直播id".$live->id.'加入异常', 1); //直播中直接进入 if ($lastLiveLog && $live->num == $lastLiveLog->num && ($lastLiveLog->female_user_id == $user->id || $lastLiveLog->male_user_id == $user->id)) return $live; //正在空闲直播间 if ($log && $live->num == $log->num && ($log->female_user_id == $user->id || $log->male_user_id == $user->id)) return $live; //直播是否空闲 $log = $live->leisureLiveLog; if (empty($log) || $log->num != $live->num) return ['code'=>1, 'msg'=>'该直播已经满员']; //性别 $sex = auth()->user()->sex; if (empty($sex)) return ['code'=>1, 'msg'=>'性别信息未填写']; //消费相亲卡 \DB::beginTransaction(); // $result = $this->useLiveCard($log->id); // if (empty($result)) throw new \Exception("使用相亲卡失败", 1); //更新直播记录 if ($sex == 1 && empty($log->male_user_id)) { $log->male_user_id = auth()->id(); }elseif ($sex == 2 && empty($log->female_user_id)) { $log->female_user_id = auth()->id(); }else{ return ['code'=>1, 'msg'=>'没有符合符合性别的卡座']; } //更新开始时间 //判断当前人员是否已满 if ($log->male_user_id && $log->female_user_id) { //更新记录开始时间 $log->start_time = date('Y-m-d H:i:s'); }elseif (empty($log->male_user_id) || empty($log->female_user_id)) { //更新第一个上麦嘉宾时间 $log->first_start_time = date('Y-m-d H:i:s'); } $log->save(); //更新直播推流任务 $result = $live->updateRtmpTask($live->user_id, $log->male_user_id, $log->female_user_id); if (empty($result)) throw new \Exception("修改推流任务失败", 1); //删除缓存嘉宾信息 $key = $log->usersInfoKey(); Cache::forget($key); \DB::commit(); return $live; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } /** * 消费相亲卡 * @param [type] $live_log_id 直播记录id * @param integer $card_live_id 专属直播间卡id * @return [type] [description] */ public function useLiveCard($live_log_id, $card_live_id=0) { try { $card = InteractLiveCard::where('user_id', auth()->id())->where(function($sql) use($card_live_id){ $sql->where('live_id', $card_live_id)->orWhere('live_id', 0); })->where(function($sql) { $sql->where('end_time', '<', date('Y-m-d H:i:s'))->orWhereNull('end_time'); })->where('is_used', 0)->orderBy('end_time', 'asc')->first(); $card->is_used = 1; $card->live_log_id = $live_log_id; $card->save(); return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 检测加入互动直播条件 * @param [type] $live_id [description] * @return [type] [description] */ public function checkJoinLive($live) { try { //直播是否开播 if (empty($live->in_live)) return ['code'=>1, 'msg'=>'该直播间还未开播']; $user = auth()->user(); //是否已经在其他直播间 $log = InteractLiveLog::where(function($sql) use($user){ $sql->where('female_user_id', $user->id)->orWhere('male_user_id', $user->id); })->where('is_over', 0)->first(); if ($log) return ['code'=>1, 'msg'=>'正在其他直播间直播']; //是否有相亲卡 // $result = $user->hasInteractLiveCard($card_live_id=0); // if ($result && is_array($result) && $result['code']) return $result; //如果没有是否有足够的福币 if ($live->has_password && $user->sex == 1) { $result = $user->hasEnoughCoin($live); if (empty($result)) return ['code'=>1, 'msg'=>'福币不足']; if ($result && is_array($result)) return $result; } return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 开播 * @return [type] [description] */ public function onLive() { try { $user = auth()->user(); //是否是红娘 // if (empty($user->live_match_maker)) return ['code'=>1, 'msg'=>'您还不是直播红娘']; //是否已经创建房间 $live = $user->interactLive; // if (empty($live)) return ['code'=>1, 'msg'=>'您还没有创建直播间']; // //是否在开播状态 // // if ($live->in_live) return ['code'=>1, 'msg'=>'正在开播状态']; // //开始下一场直播 // $this->startNextLiveLog($live); // $channel = $live->channel('main'); // //查看是否有推流任务 // if (empty($channel)) { // //创建直播流 // $channel_name = env('APP_ENV').'_live_id_'.$live->id.'_main'; // $channel = $live->createLiveChannel($channel_name, 'main'); // if (empty($channel)) throw new \Exception("创建直播流失败", 1); // } // $task = $live->getRtmpTask(); // if (empty($task)) // { // $result = $live->addRtmpTask($user->id); // if (empty($result)) throw new \Exception("直播布局失败", 1); // } // //修改开播信息 // $live->increment('num'); // $live->in_live = 1; // $live->save(); // $live->channels = $live->channel('main'); return $live; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 下播 * @return [type] [description] */ public function offLive() { try { $user = auth()->user(); //获取直播间 $live = $user->interactLive; $click_num = $live->click_num; if (empty($live)) return ['code'=>1, 'msg'=>'还没有直播间']; //正在直播记录 $log = $live->liveLogs()->where('is_over', 0)->where('num', $live->num)->whereNotNull('female_user_id')->whereNotNull('male_user_id')->first(); if ($log) return ['code'=>1, 'msg'=>'还有直播正在进行']; //关闭直播间 $result = $this->closeLive($live); if (empty($result)) throw new \Exception("关闭直播间失败", 1); $live->app_avatar = $user->avatar; $live->mk_nickname = $user->nickname; $live->start_time = $live->liveLogs()->where('num', $live->num)->orderBy('id', 'asc')->value('created_at')->toDateTimeString(); $live->end_time = $live->liveLogs()->where('num', $live->num)->whereNotNull('end_time')->orderBy('id', 'desc')->value('end_time'); //计算此次直播时长 $live->duration= strtotime($live->end_time)-strtotime( $live->start_time); //计算此次直播总时长 $live->total_duration = number_format((strtotime($live->end_time) - strtotime($live->start_time)) / 60, 2, '.', ''); //粉丝数 $live->fans_count = $user->followers()->where('hidden_profile', '<>', 'ALLSEX')/*->where('type', 'single')*/->count()?:0; $live->isSuperRank = $user->isSuperRank(); $live->click_num = $click_num; // SendIMBroadcastMsg::dispatch()->onQueue('love'); return $live; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } /** * 关闭直播间 * @param [type] $live [description] * @return [type] [description] */ public function closeLive($live) { try { \DB::beginTransaction(); //修改直播信息 $live->click_num = 0; $live->in_live = 0; $live->save(); //删除缓存 $log = $live->liveLogs()->where('num', $live->num)->where('is_over', 0)->orderBy('id', 'desc')->first(); if ($log) { $key = $log->usersInfoKey(); Cache::forget($key); } //关闭此次直播所有记录 $live->liveLogs()->where('num', $live->num)->where('is_over', 0)->update(['is_over'=>1, 'end_time'=>date('Y-m-d H:i:s')]); //更新所有房间在线用户 $live->memberLogs()->update(['in_live'=>0]); //关闭申请记录 $live->applyLogs()->update(['is_audited'=>-1]); \DB::commit(); return true; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } /** * 直播相亲卡列表 * @param [type] $is_used [description] * @return [type] [description] */ public function liveCards($is_used=null, $nopage=0) { try { $user = auth()->user(); $cards = $user->interactLiveCards(); if ($is_used != null) { $cards = $cards->where('is_used', $is_used); } $cards = $cards->where(function($sql) { $sql->whereNull('end_time')->orWhere('end_time', '>', date('Y-m-d H:i:s')); }); if ($nopage) { $cards = $cards->get(); }else{ $cards = $cards->paginate(); } return $cards; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 主动退出直播间 * @param [type] $live_id [description] * @return [type] [description] */ public function leaveInteractLive($live_id) { try { \DB::beginTransaction(); $user = auth()->user(); //获取当前直播记录 $live = $this->live($live_id, false, true, true); //正在直播 $lastLiveLog = $live->lastLiveLog; //空闲直播 $leisureLiveLog = $live->leisureLiveLog; if (empty($lastLiveLog) && empty($leisureLiveLog)) return $live; //正在直播 if ($lastLiveLog && $lastLiveLog->female_user_id != $user->id && $lastLiveLog->male_user_id != $user->id) return $live; if ($lastLiveLog) { $result = $this->leaveLastLog($live, $lastLiveLog,$user); if (empty($result)) throw new \Exception("Error Processing Request", 1); \DB::commit(); return $live; } //空闲直播中 缺少男嘉宾或者女嘉宾 if ($leisureLiveLog && $leisureLiveLog->female_user_id != $user->id && $leisureLiveLog->male_user_id != $user->id) return $live; //结束空闲直播 if ($leisureLiveLog) { $result = $this->leaveLeisureLog($live, $leisureLiveLog, $user); if (empty($result)) throw new \Exception("Error Processing Request", 1); \DB::commit(); return $live; } throw new \Exception("Error Processing Request", 1); } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } /** * 离开正在直播 * @param [type] $log [description] * @return [type] [description] */ public function leaveLastLog($live, $log, $user) { try { // $sex = $user->sex; //结束直播 $log = $this->overLiveLog($live, $log); //开始下一场直播 $this->startNextLiveLog($live, ($log->female_user_id == $user->id)?null:$log->female_user_id, ($log->male_user_id == $user->id)?null:$log->male_user_id); // if ($sex == 1) { // //删除房间直播流 // $type = 'male'; // }elseif ($sex == 2) { // $type = 'female'; // }else{ // throw new \Exception("无性别", 1); // } //删除房间直播流 // $live->removeRtmpTask($live->name, $type); // $live->deleteLiveChannel($type); return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 离开空直播 * @param [type] $log [description] * @return [type] [description] */ public function leaveLeisureLog($live, $log, $user) { try { //结束直播 $log = $this->overLiveLog($live, $log); //开始下一场直播 $this->startNextLiveLog($live); // $sex = $user->sex; // if ($sex == 1) { // $log->male_user_id = null; // //删除房间直播流 // }elseif ($sex == 2) { // $log->female_user_id = null; // }else{ // throw new \Exception("无性别", 1); // } // $log->save(); //删除缓存嘉宾信息 // $key = $log->usersInfoKey(); // Cache::forget($key); return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 请出互动直播 * @param [type] $live_id [description] * @return [type] [description] */ public function askLeaveInteractLive($live_id, $user_id) { try { $user = User::find($user_id); //判断是不是该场直播红娘 $mine = auth()->user(); $live = $this->live($live_id, false, true, true); if ($mine->id != $live->user_id) return ['code'=>1, 'msg'=>'check']; $use = User::find($user_id); //正在直播 $lastLiveLog = $live->lastLiveLog; $leisureLiveLog = $live->leisureLiveLog; if (empty($lastLiveLog) && empty($leisureLiveLog)) return $live; if ($lastLiveLog && $lastLiveLog->female_user_id != $user_id && $lastLiveLog->male_user_id != $user_id) return $live; if ($lastLiveLog) { $this->leaveLastLog($live, $lastLiveLog, $user); \DB::commit(); return $live; } if ($leisureLiveLog && $leisureLiveLog->female_user_id != $user_id && $leisureLiveLog->male_user_id != $user_id) return $live; //结束空闲直播 if ($leisureLiveLog) { $this->leaveLeisureLog($live, $leisureLiveLog, $user); \DB::commit(); return $live; } throw new \Exception("Error Processing Request", 1); } catch (\Exception $e) { $this->getError($e); return false; } } /** * 开始下一场直播记录 * @param [type] $live [description] * @param [type] $female_user_id [description] * @param [type] $male_user_id [description] * @return [type] [description] */ public function startNextLiveLog($live, $female_user_id=null, $male_user_id=null) { $log = $live->liveLogs()->create([ 'mk_user_id'=>$live->user_id, 'male_user_id'=>$male_user_id, 'female_user_id'=>$female_user_id, 'num'=>$live->num, 'first_start_time'=>$female_user_id||$male_user_id?date('Y-m-d H:i:s'):null, ]); return $log; } /** * 邀请用户参加互动直播 * @param [type] $live_id [description] * @param [type] $user_id [description] * @return [type] [description] */ public function inviteJoinLive($live_id, $user_id) { try { $mine = auth()->user(); $live = $this->live($live_id); //检查权限 $result = $this->checkInvite($live, $mine->id); if (empty($result)) throw new \Exception("检查权限失败", 1); if ($result && is_array($result)) return $result; //发送IM自定义消息 $content = '你好,用户【'.$mine->nickname.'】邀请你参加相亲直播'; $type = 'invite_live'; $mine->sendIMAttachMsg($mine->id, $user_id, $type, $content); //生成系统消息 $this->userService->sendNotice($user_id, $mine, $type, $content, $message='', $live->id); return $live; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 检查邀请直播权限 * @param [type] $live [description] * @param [type] $user_id [description] * @return [type] [description] */ public function checkInvite($live, $user_id) { try { //是否是红娘 if ($user_id != $live->user_id) return ['code'=>1, 'msg'=>'mk']; //是否正在开播 if (empty($live->in_live)) return ['code'=>1, 'msg'=>'out_live']; return true; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 推荐直播 * @return [type] [description] */ public function recommendLive() { try { //查询当前空闲直播间 $lives = InteractLive::with('femaleLiveLog.female:id,photo,nickname', 'femaleLiveLog.matchMaker:id,nickname,app_avatar', 'channels')->where('in_live', 1)->where('has_password', 0)->orderBy('click_num', 'asc')->paginate(2); $result = $this->livesInfo($lives); if (empty($result)) return $lives; return $result; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 直播列表详细信息 * @param [type] $lives [description] * @return [type] [description] */ public function livesInfo($lives) { try { foreach ($lives as $live) { $this->liveInfo($live); } return $lives; } catch (\Exception $e) { $this->getError($e); return false; } } public function liveInfo($live) { $user = auth()->user(); if (empty($live->femaleLiveLog)) return $live; //红娘信息 $live->match_maker = $live->femaleLiveLog->matchMaker; unset($live->femaleLiveLog); //嘉宾信息 if ($user->sex == 2) {//男嘉宾 $female_user_id = $live->liveLogs()->whereNotNull('male_user_id')->orderBy('id', 'desc')->value('male_user_id'); if (empty($female_user_id)) return $live; }else{//女嘉宾 $female_user_id = $live->liveLogs()->whereNotNull('female_user_id')->orderBy('id', 'desc')->value('female_user_id'); if (empty($female_user_id)) return $live; } $female = User::where('id', $female_user_id)->select('id', 'nickname', 'photo', 'app_avatar')->with('profileCourtship:user_id,city,birthday,introduction')->first(); if (empty($female)) return $live; $female->city = $female->profileCourtship?$female->profileCourtship->city:null; $birthday = $female->profileCourtship?$female->profileCourtship->birthday:null; $female->age = \CommonUtilsService::getAge($birthday); $female->photo = $female->photo?:$female->app_avatar; $female->introduction = $female->profileCourtship?$female->profileCourtship->introduction:null; $live->female = $female; unset($female->profileCourtship); return $live; } public function inLivePhotos() { try { $lives = $this->liveList(1); $photos = []; $sex = auth()->user()->sex; foreach ($lives as $live) { if ($live->female && $live->female->photo) { $photos[] = $live->female->photo; }else{ $photos[] = $sex == 1?'https://ufutx-images.oss-accelerate.aliyuncs.com/202012/09/efa7d7a8ef213793d4c314213c2be6f6.png':'https://ufutx-images.oss-accelerate.aliyuncs.com/202012/09/adeca0c8079adfe84d88f142d46f8262.png'; } } return $photos; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 直播礼物 * @return array * gifts 礼物列表 * coin 福币信息 */ public function liveGifts() { try { //礼物列表 $gifts = $this->gifts(); //福币信息 $coin = auth()->user()->coinInfo(); $coin->remain_amount = $coin->remain_amount + $coin->amount_from_other; if (empty($coin)) return false; return ['gifts'=>$gifts, 'coin'=>$coin]; } catch (\Exception $e) { $this->getError($e); return false; } } public function gifts() { $gifts = InteractLiveGift::all(); return $gifts; } public function getRatioCoins() { $os = request()->header('client_os'); if ($os == 'IOS') { $ratio_coins = RatioCoin::where('coin','<>', 14980)->get(); foreach ($ratio_coins as $ratio_coin) { $ratio_coin->coin = $ratio_coin->ios_coin; } }else{ $ratio_coins = RatioCoin::all(); } return $ratio_coins; } /** * 充值信息列表 * @return [type] [description] */ public function ratioCoins() { try { //列表信息 $ratio_coins = $this->getRatioCoins(); //福币信息 $coin = auth()->user()->coinInfo(); return ['coin'=>$coin, 'ratio_coins'=>$ratio_coins]; } catch (\Exception $e) { $this->getError($e); return false; } } /** * 赠送礼物 * @param [type] $user_id [description] * @param [type] $gift_id [description] * @return [type] [description] */ public function sendLiveGift($user_id, $gift_id, $type='live') { try { $mine = auth()->user(); $user = User::find($user_id); $gift = InteractLiveGift::find($gift_id); if (empty($gift)) throw new \Exception("礼物不存在", 1); $mine_coin = $mine->coinInfo(); //检查是否够福币 if (($mine_coin->remain_amount+$mine_coin->amount_from_other) < $gift->coin) return ['code'=>1, 'msg'=>'赠送失败,福币不足']; $result = $this->sendLiveGiftDetail($mine, $user, $gift); if (empty($result)) throw new \Exception("送礼物失败", 1); if ($type == 'live') { if (empty(request()->input('live_id'))) throw new \Exception("没有直播间信息", 1); //赠送礼物 \DB::beginTransaction(); //聊天室消息通知 $live = $this->live(request()->live_id); $msg = [ 'send_user'=> [ 'id'=>$mine->id, 'nickname'=>$mine->nickname, 'photo'=>$mine->userAvatar(), ], 'user'=>[ 'id'=>$user->id, 'nickname'=>$user->nickname, 'photo'=>$user->userAvatar(), ], 'live'=>$gift->toArray(), 'num'=>1, ]; $attach = json_encode(['type'=>(InteractLive::CHATMSGTYPE)['send_gift'], 'data'=>$msg]); $result = $live->chatroomSendMsg($user_id, $msgType=100, $attach); if (empty($result)) throw new \Exception("送礼物消息失败", 1); \DB::commit(); } return true; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } public function chatroomSendMsg($user_id, $gift_id) { try { $send_user = auth()->user(); $user = User::find($user_id); $gift = InteractLiveGift::find($gift_id); //聊天室消息通知 $live = TeamLive::find(request()->live_id); $msg = [ 'send_user'=> [ 'id'=>$send_user->id, 'nickname'=>$send_user->nickname, 'photo'=>$send_user->userAvatar(), ], 'user'=>[ 'id'=>$user->id, 'nickname'=>$user->nickname, 'photo'=>$user->userAvatar(), ], 'live'=>$gift->toArray(), 'num'=>1, ]; $attach = json_encode(['type'=>(InteractLive::CHATMSGTYPE)['send_gift'], 'data'=>$msg]); $im = new IMService(); $result = $im->chatroomSendMsg($live->chat_room_id, $user_id.time(), $user_id, $msgType=100, $attach); if (empty($result) || $result['code'] != 200) throw new \Exception("发送聊天室消息失败", 1); return true; } catch (\Exception $e) { $this->getError($e); return false; } } public function sendGift($gift, $send_user, $other_user,$channel=null, $channel_id=null) { try { \DB::beginTransaction(); //交易福币值 $coin_value = $gift->coin; //赠送人生成赠送礼物记录 $log = $other_user->addInteractLiveGift($send_user->id, $gift->id, $num=1, $coin_value); //增加礼物记录渠道 if ($channel) { $log->channelLog()->create(['channel'=>$channel, 'channel_id'=>$channel_id]); } //赠送人生成福币记录 $result = $send_user->addCoinLog($type='GIVEGIFT', $gift->id, $coin_value); if (empty($result)) throw new \Exception("赠送人扣除福币记录失败", 1); //领收人增加福币记录 $result = $other_user->addCoinLog($type='RECGIFT', $gift->id, $coin_value); if (empty($result)) throw new \Exception("获取人增加福币记录失败", 1); //赠送人扣除福币 $result = $send_user->updateCoinInfo('sub', $coin_value); if (empty($result)) throw new \Exception("赠送人扣除福币失败", 1); //领收人增加福币 $other_user->updateCoinInfo('add', $coin_value, 'other'); \DB::commit(); return true; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } /** * 赠送礼物细节 * @param [type] $send_user_id 赠送人id * @param [type] $user_id 被赠送人id * @param [type] $gift_id 礼物id * @return [type] [description] */ public function sendLiveGiftDetail($send_user, $user, $gift) { try { \DB::beginTransaction(); //交易福币值 $coin_value = $gift->coin; //赠送人生成赠送礼物记录 $user->addInteractLiveGift($send_user->id, $gift->id, $num=1, $coin_value); //赠送人生成福币记录 $result = $send_user->addCoinLog($type='GIVEGIFT', $gift->id, $coin_value); if (empty($result)) throw new \Exception("赠送人扣除福币记录失败", 1); //领收人增加福币记录 $result = $user->addCoinLog($type='RECGIFT', $gift->id, $coin_value); if (empty($result)) throw new \Exception("获取人增加福币记录失败", 1); //赠送人扣除福币 $result = $send_user->updateCoinInfo('sub', $coin_value); if (empty($result)) throw new \Exception("赠送人扣除福币失败", 1); //领收人增加福币 $user->updateCoinInfo('add', $coin_value, 'other'); \DB::commit(); return true; } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } /** * 福币记录 * @return [type] [description] */ public function userCoinLogs() { try { $user = auth()->user(); $type = request()->input('type'); $logs = $user->coinLogs(); if ($type == 'rec') { $logs = $logs->whereIn('type', ['RECSYSTEM', 'RECGIFT', 'RECHARGE', 'RECMOMENT']); } $logs = $logs->orderBy('id', 'desc')->paginate(); foreach ($logs as $log) { // if ($log->type == 'RECSYSTEM') { // $log->type = 'RECHARGE'; // } $log->title = \CommonUtilsService::getCoinLogDetailType($log->remark,$log->type); } return $logs; } catch (\Exception $e) { $this->getError($e); return false; } } public function liveOnlineUsers() { try { $sex = request()->input('sex'); $users = User::where('app_online', 1)->where('sex', $sex)->where('id', '<>', auth()->id())->where('type', 'single')->select('id', 'app_avatar', 'nickname', 'sex')->paginate(); $users = $this->inviteUsersInfo($users); return $users; } catch (\Exception $e) { $this->getError($e); } } /** * 邀请用户列表信息 * @param [type] $users [description] * @return [type] [description] */ public function inviteUsersInfo($users) { foreach ($users as $user) { $profile = $user->profileCourtship; if (empty($profile)) { unset($user->profileCourtship); continue; } $user->age = \CommonUtilsService::getAge($profile->birthday); $user->city = $profile->city; unset($user->profileCourtship); } return $users; } public function liveMembers($live, $nopage=0, $limit=0) { try { $members = $live->members()->with('profileCourtship')->where('in_live', 1); $sex = request()->input('sex'); if ($sex) { $members = $members->where('sex', $sex); } if ($nopage) { $members = $members->limit($limit)->get(); }else{ $members = $members->paginate(); } $attributes = ['user_id','birthday','city']; $hiddens = ['uid','is_new', 'face_socre', 'photo', 'card_num', 'circle_avatar', 'mobile', 'mobile', 'email', 'location_longitude', 'location_latitude', 'temp_member', 'industry', 'industry_sub','from_openid', 'from_user_id','from_official_openid', 'from_platform', 'my_qrcode', 'my_qrcode_rect','my_share_rect','my_share','home_share','is_admin','is_real_approved','approve_time','hidden','hidden_profile','can_be_found','system_info','is_photo_audited','is_audited','scene','tag_num','negative_score','info_complete_score', 'is_update_score','is_subscribe','mark', 'liveness','approve_date','last_visit','face_score']; $array = []; foreach ($members as $member) { if ($member->profileCourtship) { foreach ($attributes as $attribute) { $member->$attribute = $member->profileCourtship->$attribute; } } //是否是好友 $member->is_friend = $member->isFriend(auth()->user())?1:0; //是否超级会员 $member->is_super_rank = $member->isSuperRank(); //年龄 $member->age = \CommonUtilsService::getAge($member->profileCourtship?$member->profileCourtship->birthday:null); foreach ($hiddens as $hidden) { unset($member->$hidden); } unset($member->profileCourtship, $member->pivot); } return $members; } catch (Exception $e) { $this->getError($e); return false; } } /** * 直播付费 * @param [type] $live_id [description] * @return [type] [description] */ public function payLive($live_id) { try { //直播间 $live = InteractLive::find($live_id); $user = auth()->user(); //直播费用 每分钟 if ($user->sex == 2) { return true; } //是否正在连麦 $log = InteractLiveLog::where('live_id', $live_id)->where('male_user_id', $user->id)->where('num', $live->num)->whereNotNull('female_user_id')->where('is_over',0)->orderBy('id', 'desc')->first(); if (empty($log)) return true; $fee = $live->male_fee; if (empty($fee)) { return true; } //扣费 \DB::beginTransaction(); $result = $user->updateCoinInfo('sub', $fee); if (empty($result)) throw new \Exception("扣费失败", 1); $result = $user->addCoinLog('INTERLIVE', $live_id, $fee); if (empty($result)) throw new \Exception("添加扣费记录失败", 1); \DB::commit(); return $user->coinInfo(); } catch (\Exception $e) { \DB::rollback(); $this->getError($e); return false; } } public function inLiveNum() { try { $count = InteractLive::inLive()->count(); return $count; } catch (\Exception $e) { $this->getError($e); return false; } } public function getOnlyTeamLive($team_id, $version=1) { try { //是否创建直播 $live = TeamLive::where('team_id', $team_id)->where('user_id', auth()->id())->where('version', $version)->first(); if (empty($live)) { $live = $this->addTeamLive($team_id, $version); } return $live; } catch (\Exception $e) { $this->getError($e); return false; } } public function addTeamLive($team_id, $version=1) { try { $name = auth()->user()->nickname.uniqid(); $param = [ 'user_id'=>auth()->id(), 'team_id'=>$team_id, 'name'=>$name, 'in_live'=>0, 'version'=>$version, ]; $live = TeamLive::create($param); return $live; } catch (\Exception $e) { $this->getError($e); return false; } } public function getChatRoom($live) { try { \Log::info("获取聊天室信息"); //网易账号 auth()->user()->createIMUser(); $chat_room = $live->createChatRoom($live->user_id, $live->name); if (empty($chat_room)) throw new \Exception("创建IM聊天室失败", 1); return $chat_room['roomid']; } catch (\Exception $e) { $this->getError($e); return false; } } public function getChannel($live) { try { $channel_name = env('APP_ENV').'_team_live_id_'.$live->id; if($live->version == 2){ $channel_name .= $live->version; } $channel = $live->createLiveChannel($channel_name); if (empty($channel)) throw new \Exception("创建直播流失败", 1); return $channel; } catch (\Exception $e) { $this->getError($e); return false; } } public function getChannelRoom($live) { try { $name = Request()->route()->getName(); \Log::info('获取互动直播间'); $version = 1; if($name == 'teams/lives/v2'){ $version = 2; } $room = $live->channelRoom(); if (empty($room) || !in_array($room['stats'] , [1,2,4])) { $channel_id = $live->createChannelRoom(0, $live->name, $live->user_id, $webrtc=0, $selfconfig=[], $roomconfig='', $version); if (empty($channel_id)) throw new \Exception("创建音视频房间失败", 1); $live->channel_id = $channel_id; $live->save(); if ($version == 1) { //增加房间推流任务 $result = $live->addRtmpTask($live->user_id); if (empty($result)) throw new \Exception("直播布局失败", 1); } return true; }else{ return $room; } } catch (\Exception $e) { $this->getError($e); return false; } } }