route('login'); } $userLogged = User::where('id', '=', Auth::id())->get()->first(); $allNotifications = DB::table('notifications')->orderBy('id','desc')->limit('3')->get(); $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $playlists = DB::table('playlists')->where('port','=',$siteData->stream_port)->orderBy('name','asc')->get(); $schedules = DB::table('playlists_schedules')->where('port','=',$siteData->stream_port)->get(); /* a capa e buscada pelo navegador, entao a tela precisa saber se esta ligada */ $siteSettings = DB::connection('mysql_site_' . session('serverID'))->table('settings') ->where('site_id', '=', session('siteID'))->first(); return view('radio.home', ['userLogged' => $userLogged , 'allNotifications' => $allNotifications, 'topHref' => 'radio', 'siteData' => $siteData, 'streamData' => $getStreamDetails, 'getServerDetails' => $getServerDetails, 'playlists' => $playlists, 'schedules' => $schedules, 'coverOn' => ($siteSettings->metadata_cover ?? '1') !== '0']); } public function ajaxListeners() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $set = DB::table('settings')->where('id','=',1)->get()->first(); $headers = array( 'Content-Type:application/json', 'Authorization: Basic ' . base64_encode($set->master_user.":".$set->master_pass) ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://".$getServerDetails->ip.":".$getStreamDetails->port."/admin/listclients"); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_USERAGENT, 'BRASCASTX'); $resultado = curl_exec($ch); curl_close($ch); $resultado = xml_entity_decode($resultado); $xml = @simplexml_load_string(utf8_encode($resultado)); if(!$xml){ return '

0

'.__('radio.home_listeners_multiple').'
'; }else{ return '

'.(!$xml->source->listeners ? '0' : $xml->listeners).'

'.($xml->source->listeners == 1 ? __('radio.home_listeners_unique') : __('radio.home_listeners_multiple')).'
'; } } public function actionAutoDJ() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/data/history.php?p='.$getStreamDetails->port); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_USERAGENT, 'BRASCASTX'); $jsonGetInfo = curl_exec($ch); curl_close($ch); $dataInfo = json_decode($jsonGetInfo,true); $finalCodecInfo = ($getStreamDetails->autodj_codec == 'aac' ? 'AAC+' : 'MP3').'('.$getStreamDetails->autodj_bitrate.'kbps, Stereo, 44.1kHz)'; $rawTime = $getStreamDetails->autodj_time ?? null; if ($rawTime) { $timestamp = strtotime($rawTime); $locale = Cookie::get('locale', 'pt'); $finalBroadcastTime = ($locale === 'pt') ? date('d/m/Y H:i', $timestamp) : date('Y-m-d H:i', $timestamp); } else { $finalBroadcastTime = '--'; } $getCurrentPlaylist = DB::table('playlists')->where('id','=',$getStreamDetails->current_playlist_id)->get()->first(); $playlists = DB::table('playlists')->where('port','=',$siteData->stream_port)->orderBy('name','asc')->get(); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15); curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_URL,'https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/data/info.php?p='.$getStreamDetails->port); $result=curl_exec($ch); $dataAutoDJInfo = json_decode($result, true); if (session('siteID') == '25158') { // return dd($result);//'https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/data/info.php?p='.$getStreamDetails->port; } curl_close($ch); return view('radio.ajax.autodj',['getStreamDetails' => $getStreamDetails,'dataInfo' => $dataInfo, 'finalCodecInfo' => $finalCodecInfo, 'finalBroadcastTime' => $finalBroadcastTime, 'getCurrentPlaylist' => $getCurrentPlaylist, 'dataAutoDJInfo' => $dataAutoDJInfo, 'playlists' => $playlists]); } public function actionLive() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $djConnected = DB::table('djs')->where('port','=',$siteData->stream_port)->where('active','=','1')->get(); $codecLive = 'AAC+'; $bitrateLive = '128'; if($djConnected->count()){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://".$getServerDetails->ip.":".$getStreamDetails->port."/status-json.xsl"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_setopt($ch, CURLOPT_USERAGENT, 'BRASCASTX'); $result = json_decode(curl_exec($ch)); curl_close($ch); $types = array('audio/aacp' => 'AAC+', 'audio/mpeg' => 'MP3','audio/aac' => 'AAC+',); $bitrateLive = (isset($result->icestats->source[0]->bitrate) ? $result->icestats->source[0]->bitrate : '128'); $codecLive = (isset($result->icestats->source[0]->server_type) ? $types[$result->icestats->source[0]->server_type] : 'AAC+'); } return view('radio.ajax.aovivo',['djConnected' => $djConnected , 'getStreamDetails' => $getStreamDetails, 'bitrateLive' => $bitrateLive, 'codecLive' => $codecLive]); } public function actionRelay() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); return view('radio.ajax.relay',['getStreamDetails' => $getStreamDetails]); } public function actionManu() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); return view('radio.ajax.manutention',['getStreamDetails' => $getStreamDetails]); } public function execAction($type = null,$action = null,$param = null) { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } if(!$type){ return false; } $allTypes = array("SkipSong", "AutoDJControl","ReloadPlaylist","StopRelay","StopLive"); if (!in_array($type, $allTypes)){return false;} $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); if($getStreamDetails->status == '2'){ return array("result"=>true,"message"=>"O AutoDJ não pode iniciar pois está suspenso."); } if($type == 'AutoDJControl' && $action == 'start'){ $isLiveConnected = DB::table('djs')->where('port','=',$siteData->stream_port)->where('active','=','1')->get()->count(); if($isLiveConnected){ return array("result"=>true,"message"=>"O AutoDJ não pode iniciar pois existe uma transmissão ao vivo conectada."); }else{ $getPlaylistData = DB::table('playlists')->where('id','=',$param)->get()->first(); $param = ($getPlaylistData->id ? $getPlaylistData->id : null); DB::table('relays')->where('port','=',$siteData->stream_port)->update(['active' => '0']); DB::table('streamings')->where('port','=',$siteData->stream_port)->update([ 'current_playlist_id' => $param, 'current_playlist_type' => 0, 'autodj_time' => now() ]); setLog($siteData->stream_port, 'AutoDJ ligado manualmente', request()->ip()); $message = 'Playlist iniciada com sucesso!'; } }elseif($type == 'AutoDJControl' && $action == 'change'){ $expParam = explode('|',$param); $nparam = (count($expParam) > 1 ? $expParam[0] : null); $getPlaylistData = DB::table('playlists')->where('id','=',$nparam)->get()->first(); $param = (isset($getPlaylistData->id) ? $getPlaylistData->id.'|'.$expParam[1] : null); DB::table('streamings')->where('port','=',$siteData->stream_port)->update([ 'current_playlist_id' => $getPlaylistData->id, 'current_playlist_type' => 0, 'autodj_time' => now() ]); setLog($siteData->stream_port, 'Playlist trocada manualmente', request()->ip()); $message = __('radio.home_msg_actions_playlist_changed'); }elseif($type == 'AutoDJControl' && $action == 'stop'){ DB::table('streamings')->where('port','=',$siteData->stream_port)->update(['current_playlist_id' => null ]); setLog($siteData->stream_port, 'AutoDJ desligado manualmente', request()->ip()); $message = __('radio.home_msg_actions_autodj_stopped'); }elseif($type == 'ReloadPlaylist'){ setLog($siteData->stream_port, 'Playlist reiniciada manualmente', request()->ip()); $message = __('radio.home_msg_actions_playlist_reloaded'); }elseif($type == 'StopRelay'){ $message = __('radio.home_msg_actions_relay_stopped'); $actualRelay = DB::table('relays')->where('port','=',$siteData->stream_port)->where('active','=','1')->first(); if ($actualRelay) { setLog($siteData->stream_port, 'Desligou a retransmissão manualmente: '. $actualRelay->id, request()->ip());} }elseif($type == 'StopLive'){ $message = 'Locutor desconectado com sucesso'; setLog($siteData->stream_port, 'Locutor desconectado manualmente', request()->ip()); }else{ setLog($siteData->stream_port, 'Áudio pulado manualmente', request()->ip()); $message = __('radio.home_msg_actions_audio_skiped'); } if($type == 'StopRelay'){ $post = [ 'p' => $siteData->stream_port, 'ac' => 'stop' ]; $ch = curl_init('https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/stream/ManageRelay.php'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_USERAGENT, "CURL"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Hash: 4BEAD0A3736F606092EADB5540B277966C2735F98294BD50547DB391ABB37E99", "Secret: streamingbrascastsrvr" ]); $result = curl_exec($ch); curl_close($ch); $actualRelay = DB::table('relays')->where('port','=',$siteData->stream_port)->where('active','=','1')->first(); $update = [ 'active' => '0' ]; if ($actualRelay->type == '1') { // só limpa se for tipo 1 (semanal), tipo 2 mantem a hora e inicio para o usuario atualizar posteriormente $update['start_time'] = null; $update['end_time'] = null; } else if ($actualRelay->type == '2'){ $update['always'] = '0'; // tipo 2 quer dizer que tem fim, então coloca o always como 0 para garantir; } DB::table('relays')->where('id','=',$actualRelay->id)->update($update); }if($type == 'StopLive'){ $post = [ 'p' => $siteData->stream_port, 'ac' => 'stop' ]; $ch = curl_init('https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/stream/LiveControl.php'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_USERAGENT, "CURL"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Hash: 4BEAD0A3736F606092EADB5540B277966C2735F98294BD50547DB391ABB37E99", "Secret: streamingbrascastsrvr" ]); $result = curl_exec($ch); curl_close($ch); DB::table('djs')->where('port','=',$siteData->stream_port)->where('active','=','1')->update(['active' => '0']); }else{ $ch = curl_init('https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/stream/'.$type.'.php?p='.$getStreamDetails->port.'&p_dj='.$getStreamDetails->autodj_port.($action ? '&a='.$action : '').($param ? '&o='.$param : '')); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT,120); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120); curl_setopt($ch, CURLOPT_USERAGENT, "CURL"); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Hash: 4BEAD0A3736F606092EADB5540B277966C2735F98294BD50547DB391ABB37E99", "Secret: streamingbrascastsrvr" ]); $result = curl_exec($ch); curl_close($ch); } $array = array("result"=>$result,"message"=>$message,"ap"=>$param); return $array; } /* public function statusInfo() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $haveDJConnected = DB::table('djs')->where('port','=',$siteData->stream_port)->where('active','=','1')->get()->count(); $relayConected = DB::table('relays')->where('port','=',$siteData->stream_port)->where('active','=','1')->get()->count(); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_URL,'https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/data/info.php?p='.$getStreamDetails->port); $result=curl_exec($ch); $dataAutoDJInfo = json_decode($result,true); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $verifyDjConnected = (isset($dataAutoDJInfo['status_live']) && $dataAutoDJInfo['status_live'] == 'on' ? 1 : ($haveDJConnected >= 1 ? 1 : 0)); if($haveDJConnected && $dataAutoDJInfo['status_autodj'] == 'on' && $dataAutoDJInfo['status_live'] == 'off'){ DB::table('djs')->where('port','=',$siteData->stream_port)->update([ 'active' => '0' ]); } if($httpcode != '200'){ return array("iconblock01"=>"opacity-50 text-danger","block01_h1" => "Manutenção", "block01_h2" => '', "iconblock02"=>null, "block02_h1" => null,"block02_h2" => null, "msgAutoDJ" => false,"act" => "block01-tab","btnact" => "btn-block01-tab","target01"=>"block01-tab","target02"=>"block02-tab","relay" => null); }elseif($dataAutoDJInfo['status_autodj'] == 'on' && $relayConected == '0' && $verifyDjConnected == 0){ return array("iconblock01"=>"blink","block01_h1" => __('radio.home_block_item_autodj'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"opacity-50 text-danger", "block02_h1" => __('radio.home_block_item_live'),"block02_h2" => __('radio.home_block_item_type_1'), "msgAutoDJ" => false,"act" => "block01-tab","btnact" => "btn-block01-tab","target01"=>"block01-tab","target02"=>"block02-tab","relay" => null); }elseif($dataAutoDJInfo['status_autodj'] == 'on' && $relayConected == '0' && $verifyDjConnected == 1){ return array("iconblock01"=>"blink","block01_h1" => __('radio.home_block_item_live'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"text-primary", "block02_h1" => __('radio.home_block_item_autodj'),"block02_h2" => __('radio.home_block_item_type_3'), "msgAutoDJ" => true,"act" => "block02-tab","btnact" => "btn-block01-tab","target01"=>"block02-tab","target02"=>"block01-tab","relay" => null); }elseif($dataAutoDJInfo['status_autodj'] == 'off' && $relayConected == '0' && $verifyDjConnected == 1){ return array("iconblock01"=>"blink","block01_h1" => __('radio.home_block_item_live'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"opacity-50 text-danger", "block02_h1" => __('radio.home_block_item_autodj'),"block02_h2" => __('radio.home_block_item_type_1'), "msgAutoDJ" => false,"act" => "block02-tab","btnact" => "btn-block01-tab","target01"=>"block02-tab","target02"=>"block01-tab","relay" => null); }elseif($dataAutoDJInfo['status_autodj'] == 'on' && $relayConected >= '1' && $verifyDjConnected == 0){ return array("iconblock01"=>"text-danger","block01_h1" => __('radio.home_block_item_live'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"text-primary", "block02_h1" => __('radio.home_block_item_autodj'),"block02_h2" => __('radio.home_block_item_type_3'), "msgAutoDJ" => true,"act" => "block03-tab","btnact" => "btn-block03-tab","target01"=>"block03-tab","target02"=>"block01-tab","relay" => true); }else{ return array("iconblock01"=>"text-danger","block01_h1" => __('radio.home_block_item_autodj'), "block01_h2" => __('radio.home_block_item_type_1'), "iconblock02"=>"opacity-50 text-danger", "block02_h1" => __('radio.home_block_item_live'),"block02_h2" => __('radio.home_block_item_type_1'), "msgAutoDJ" => false,"act" => "block01-tab","btnact" => "btn-block01-tab","target01"=>"block01-tab","target02"=>"block02-tab","relay" => null); } } */ public function statusInfo() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $haveDJConnected = DB::table('djs')->where('port','=',$siteData->stream_port)->where('active','=','1')->get()->count(); $relayConected = DB::table('relays')->where('port','=',$siteData->stream_port)->where('active','=','1')->get()->count(); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://'.$getServerDetails->ip.':'.$getStreamDetails->port.'/status-json.xsl'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8); curl_setopt($ch, CURLOPT_TIMEOUT, 8); curl_setopt($ch, CURLOPT_USERAGENT, 'BRASCASTX'); $result = json_decode(curl_exec($ch)); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $autoDJStatus = 'off'; $verifyDjConnected = ($haveDJConnected >= 1 ? 1 : 0); if (isset($result->icestats->source) && stripos(json_encode($result->icestats->source),'/autodj') !== false || isset($result->icestats->source) && stripos(json_encode($result->icestats->source[0]->server_name),'/autodj') !== false) { $autoDJStatus = 'on'; } /*if($haveDJConnected && $dataAutoDJInfo['status_autodj'] == 'on' && $dataAutoDJInfo['status_live'] == 'off'){ DB::table('djs')->where('port','=',$siteData->stream_port)->update([ 'active' => '0' ]); }*/ if($autoDJStatus == 'on' && $relayConected == '0' && $verifyDjConnected == 0){ return array("iconblock01"=>"blink","block01_h1" => __('radio.home_block_item_autodj'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"opacity-50 text-danger", "block02_h1" => __('radio.home_block_item_live'),"block02_h2" => __('radio.home_block_item_type_1'), "msgAutoDJ" => false,"act" => "block01-tab","btnact" => "btn-block01-tab","target01"=>"block01-tab","target02"=>"block02-tab","relay" => null, 'info' => 1); }elseif($autoDJStatus == 'on' && $relayConected == '0' && $verifyDjConnected == 1){ return array("iconblock01"=>"blink","block01_h1" => __('radio.home_block_item_live'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"text-primary", "block02_h1" => __('radio.home_block_item_autodj'),"block02_h2" => __('radio.home_block_item_type_3'), "msgAutoDJ" => true,"act" => "block02-tab","btnact" => "btn-block01-tab","target01"=>"block02-tab","target02"=>"block01-tab","relay" => null, 'info' => 2); }elseif($autoDJStatus == 'off' && $relayConected == '0' && $verifyDjConnected == 1){ return array("iconblock01"=>"blink","block01_h1" => __('radio.home_block_item_live'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"opacity-50 text-danger", "block02_h1" => __('radio.home_block_item_autodj'),"block02_h2" => __('radio.home_block_item_type_1'), "msgAutoDJ" => false,"act" => "block02-tab","btnact" => "btn-block01-tab","target01"=>"block02-tab","target02"=>"block01-tab","relay" => null, 'info' => 3); }elseif($autoDJStatus == 'on' && $relayConected >= '1' && $verifyDjConnected == 0){ return array("iconblock01"=>"text-danger","block01_h1" => __('radio.home_block_item_live'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02"=>"text-primary", "block02_h1" => __('radio.home_block_item_autodj'),"block02_h2" => __('radio.home_block_item_type_3'), "msgAutoDJ" => true,"act" => "block03-tab","btnact" => "btn-block03-tab","target01"=>"block03-tab","target02"=>"block01-tab","relay" => true, 'info' => 4); }elseif($autoDJStatus == 'on' && $relayConected >= '1' && $verifyDjConnected == 1){ return array( "iconblock01" => "blink", "block01_h1" => __('radio.home_block_item_live'), "block01_h2" => __('radio.home_block_item_type_2'), "iconblock02" => "text-primary", "block02_h1" => __('radio.home_block_item_autodj'), "block02_h2" => "Relay em 2º plano", "msgAutoDJ" => true, "act" => "block02-tab", "btnact" => "btn-block01-tab", "target01" => "block02-tab", "target02" => "block01-tab", "relay" => false, "msgRelay" => "Relay em 2º plano", 'info' => 5 ); }else{ return array("iconblock01"=>"text-danger","block01_h1" => __('radio.home_block_item_autodj'), "block01_h2" => __('radio.home_block_item_type_1'), "iconblock02"=>"opacity-50 text-danger", "block02_h1" => __('radio.home_block_item_live'),"block02_h2" => __('radio.home_block_item_type_1'), "msgAutoDJ" => false,"act" => "block01-tab","btnact" => "btn-block01-tab","target01"=>"block01-tab","target02"=>"block02-tab","relay" => null, 'info' => 6); } } public function infoCurrent() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $ch1 = curl_init(); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch1, CURLOPT_TIMEOUT, 10); curl_setopt($ch1, CURLOPT_URL,'https://'.$getServerDetails->name.'.'.env('BASE_SERVER_URL','brascast.com').'/bras_api/data/info.php?p='.$getStreamDetails->port); $result1=curl_exec($ch1); $dataStatus = json_decode($result1,true); curl_close($ch1); if(!isset($dataStatus) || $dataStatus['status_live'] == 'on' || $dataStatus['status_autodj'] != 'on' && $dataStatus['status_live'] != 'on'){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://".$getServerDetails->ip.":".$getStreamDetails->port."/status-json.xsl"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_setopt($ch, CURLOPT_USERAGENT, 'BRASCASTX'); $resultado = json_decode(curl_exec($ch)); curl_close($ch); $cur = (isset($resultado->icestats->source[0]->title) ? $resultado->icestats->source[0]->title : ''); $dataLive = json_encode(array('now' => $cur, 'next' => '')); $dataAutoDJInfo = json_decode($dataLive, true); }else if(!isset($dataStatus) || $dataStatus['status_autodj'] != 'on') { $dataAutoDJInfo = json_encode(array('now' => '', 'next' => '')); }else{ $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_URL, 'https://' . $getServerDetails->name . '.' . env('BASE_SERVER_URL', 'brascast.com') . '/bras_api/data/current.php?p=' . $getStreamDetails->port); $result = curl_exec($ch); $dataAutoDJInfo = json_decode($result, true); curl_close($ch); } return str_replace('\\','',$dataAutoDJInfo); } public function getCoverOld() { if(Auth::check() === false){ Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $siteSettings = DB::connection('mysql_site_'.session('serverID'))->table('settings')->where('site_id','=',session('siteID'))->first(); $getStreamDetails = DB::table('streamings')->where('port','=',$siteData->stream_port)->get()->first(); $getServerDetails = DB::table('servers')->where('id','=',$getStreamDetails->server_id)->get()->first(); $finalCover = null; if (isset($siteSettings) && $siteSettings->metadata_cover == '0') { return response()->json(['cover' => $finalCover]); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://".$getServerDetails->ip.":".$getStreamDetails->port."/status-json.xsl"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_setopt($ch, CURLOPT_USERAGENT, 'BRASCASTX'); $resultado = json_decode(curl_exec($ch)); curl_close($ch); $cur = (isset($resultado->icestats->source[0]->title) ? $resultado->icestats->source[0]->title : null); $cur = str_replace('_',' ',$cur); $exp = explode('-',$cur); $defaultCont = array('Hora Certa'); if(strpos($cur, ' - Completo') || strpos($cur, ' - Parte ')) { $expCur = explode('-',$cur); $finalCover = env('STORAGE_URL').'covers/default/'.md5($expCur[0]).'.jpg'; }else{ $defaultLive = array('PROGRAMAÇÃO AO VIVO','PROGRAMACAO AO VIVO','PROGRAMAÇÃO AOVIVO','PROGRAMACAO AOVIVO','ㅤ'); if(in_array($cur,$defaultLive)){ $finalCover = env('STORAGE_URL').'covers/default/5b36dd0016ac6a4f4df796162752812a.jpg'; }else if(in_array($cur,$defaultCont)){ $finalCover = env('STORAGE_URL').'covers/default/'.md5($cur).'.jpg'; }else{ $url = env('STORAGE_URL').'covers/'.md5($getStreamDetails->port).'/'.md5($cur).'.jpg'; $headers = @get_headers($url); if(isset($headers[0]) && strpos($headers[0],'200')){ $finalCover = $url; }else{ $expPodcast = explode(' - ', $cur); $podcastName = trim($expPodcast[0]); $podcast = DB::connection('mysql_site_'.session('serverID')) ->table('podcasts') ->where('site_id', '=', session('siteID')) ->whereRaw('TRIM(name) = ?', [$podcastName]) ->first(); if($podcast){ $finalCover = env('STORAGE_URL').'covers/default/ac9cef765e0dbf0bda625b3d1d3b446d.png'; }else{ $cur = str_replace('Ao Vivo','',$cur); $finalCover = getDeezerCover($cur); if (!$finalCover) { $finalCover = getItunesCoverWithFallback($cur, $exp); } if (!$finalCover && isset($exp[0])) { $finalCover = getDeezerCover($exp[0]); } if (!$finalCover) { $finalCover = null; } } } } } return response()->json(['cover' => $finalCover]); } public function getCover() { if (Auth::check() === false) { Auth::logout(); return redirect()->route('login'); } $connection = 'mysql_site_' . session('serverID'); $siteData = DB::connection($connection) ->table('sites') ->where('id', '=', session('siteID')) ->first(); $siteSettings = DB::connection($connection) ->table('settings') ->where('site_id', '=', session('siteID')) ->first(); // Capa desativada nas configurações do site if (!$siteData || ($siteSettings && $siteSettings->metadata_cover == '0')) { return response()->json(['cover' => null]); } $cover = Cache::remember( 'cover:' . $siteData->stream_port, 10, // segundos — evita flood na cover-api com o polling do player function () use ($siteData) { try { $response = Http::timeout(3) ->connectTimeout(2) ->get('https://cover-api.brascast.com/cover', [ 'p' => $siteData->stream_port, 's' => $siteData->stream_server, ]); if (!$response->successful()) { return null; } $data = $response->json(); if (empty($data['success'])) { return null; } return $data['image_url'] ?: null; } catch (\Throwable $e) { return null; } } ); return response()->json(['cover' => $cover]); } /** * Tudo o que a /radio/home mostra, numa resposta so. * * A tela antiga pedia seis vezes: ouvintes, estado, bloco do auto dj, bloco * do ao vivo, faixa atual e capa. Essas seis chamadas buscavam quatro * enderecos diferentes no servidor de streaming, e repetiam o mesmo endereco * ate tres vezes. Medido daqui, com o servidor no Brasil, davam 3,1 s. * * Aqui cada endereco e buscado uma vez so e os quatro saem juntos, com * curl_multi: o tempo passa a ser o da chamada mais lenta, e o navegador faz * uma ida e volta em vez de seis. Com servidor noutro continente essa * diferenca vira segundos. * * A informacao devolvida e exatamente a mesma que as seis rotas antigas * entregam; o que mudou foi o transporte. */ public function state() { if (Auth::check() === false) { Auth::logout(); return redirect()->route('login'); } $siteData = SiteContext::current(); $stream = DB::table('streamings')->where('port', '=', $siteData->stream_port)->first(); if (! $stream) { return response()->json(['ok' => false, 'error' => 'stream_not_found'], 404); } $server = DB::table('servers')->where('id', '=', $stream->server_id)->first(); $master = DB::table('settings')->where('id', '=', 1)->first(); $base = 'https://' . $server->name . '.' . env('BASE_SERVER_URL', 'brascast.com'); $icecast = 'http://' . $server->ip . ':' . $stream->port; $alvos = [ 'status' => ['url' => $icecast . '/status-json.xsl'], 'listeners' => [ 'url' => $icecast . '/admin/listclients', 'headers' => ['Authorization: Basic ' . base64_encode($master->master_user . ':' . $master->master_pass)], ], 'info' => ['url' => $base . '/bras_api/data/info.php?p=' . $stream->port], 'history' => ['url' => $base . '/bras_api/data/history.php?p=' . $stream->port], ]; $respostas = $this->fetchAll($alvos); $status = json_decode((string) $respostas['status'], false); $info = json_decode((string) $respostas['info'], true); $history = json_decode((string) $respostas['history'], true); $djs = DB::table('djs')->where('port', '=', $siteData->stream_port)->where('active', '=', '1')->get(); $relays = DB::table('relays')->where('port', '=', $siteData->stream_port)->where('active', '=', '1')->count(); return response()->json([ 'ok' => true, 'listeners' => $this->countListeners($respostas['listeners']), 'sources' => $this->sources($status, $djs->count(), $relays), 'now' => [ 'current' => $history['current'] ?? null, 'next' => $history['next'] ?? null, ], 'autodj' => [ 'codec' => ($stream->autodj_codec == 'aac' ? 'AAC+' : 'MP3') . '(' . $stream->autodj_bitrate . 'kbps, Stereo, ' . $stream->autodj_sample . 'kHz)', 'since' => $this->broadcastTime($stream->autodj_time ?? null), 'playlist' => DB::table('playlists')->where('id', '=', $stream->current_playlist_id)->value('name'), 'status' => $info['status_autodj'] ?? null, 'history' => array_values((array) ($history['list'] ?? [])), ], 'live' => $this->liveBlock($djs, $status), ]); } /** * Busca todos os enderecos ao mesmo tempo. * * O tempo total passa a ser o da chamada mais lenta, e nao a soma delas. * Falha de um endereco nao derruba os outros: quem falhou volta null e a * tela mostra o que deu para saber. */ private function fetchAll(array $alvos): array { $multi = curl_multi_init(); $handles = []; foreach ($alvos as $chave => $alvo) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $alvo['url'], CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 3, CURLOPT_TIMEOUT => 8, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_USERAGENT => 'BRASCASTX', CURLOPT_HTTPHEADER => $alvo['headers'] ?? [], ]); curl_multi_add_handle($multi, $ch); $handles[$chave] = $ch; } do { $andamento = curl_multi_exec($multi, $ativos); if ($ativos) { curl_multi_select($multi, 1); } } while ($ativos && $andamento === CURLM_OK); $saida = []; foreach ($handles as $chave => $ch) { $corpo = curl_multi_getcontent($ch); $codigo = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); $saida[$chave] = $codigo >= 200 && $codigo < 300 ? $corpo : null; curl_multi_remove_handle($multi, $ch); curl_close($ch); } curl_multi_close($multi); return $saida; } /** O numero de ouvintes, do xml do Icecast. */ private function countListeners($xmlBruto): int { if (! $xmlBruto) { return 0; } $xml = @simplexml_load_string(xml_entity_decode($xmlBruto)); return $xml ? (int) $xml->listeners : 0; } /** * Quais fontes existem na tela e qual esta no ar. * * Mesma regra do statusInfo(): auto dj e ao vivo convivem, um no ar e o * outro em espera; relay entra no lugar do auto dj; sem nenhum dos dois a * tela cai em manutencao. */ private function sources($status, int $djs, int $relays): array { $autodj = 'off'; if (isset($status->icestats->source)) { $texto = json_encode($status->icestats->source); $primeiro = json_encode($status->icestats->source[0]->server_name ?? ''); if (stripos($texto, '/autodj') !== false || stripos($primeiro, '/autodj') !== false) { $autodj = 'on'; } } $aoVivo = $djs >= 1; $temRelay = $relays >= 1; if ($autodj === 'off' && ! $aoVivo && ! $temRelay) { return ['onair' => 'manu', 'autodj' => 'off', 'live' => 'off', 'relay' => 'off']; } $noAr = $aoVivo ? 'live' : ($temRelay ? 'relay' : 'autodj'); return [ 'onair' => $noAr, /* ligado mas em segundo plano quando o ar e de outro */ 'autodj' => $autodj === 'on' ? ($noAr === 'autodj' ? 'live' : 'standby') : 'off', 'live' => $aoVivo ? ($noAr === 'live' ? 'live' : 'standby') : 'off', 'relay' => $temRelay ? ($noAr === 'relay' ? 'live' : 'standby') : 'off', ]; } /** * Data de inicio, no formato do idioma em uso. * * So o ingles usa ano-mes-dia. O idioma sai de app()->getLocale(), que e * o que o middleware preenche a partir da coluna do usuario: lendo o * cookie, quem estava em portugues com o cookie de outra coisa via a * data invertida. */ private function broadcastTime($rawTime, bool $comSegundos = false): string { if (! $rawTime) { return '--'; } $timestamp = strtotime($rawTime); if ($timestamp === false) { return '--'; } $hora = $comSegundos ? 'H:i:s' : 'H:i'; return app()->getLocale() === 'en' ? date('Y-m-d ' . $hora, $timestamp) : date('d/m/Y ' . $hora, $timestamp); } /** Dados do locutor no ar, quando ha um. */ private function liveBlock($djs, $status): array { if (! $djs->count()) { return ['connected' => false, 'name' => null, 'ip' => null, 'since' => null, 'codec' => 'AAC+', 'bitrate' => '128']; } $tipos = ['audio/aacp' => 'AAC+', 'audio/mpeg' => 'MP3', 'audio/aac' => 'AAC+']; $fonte = $status->icestats->source[0] ?? null; return [ 'connected' => true, 'name' => $djs[0]->name, 'ip' => $djs[0]->last_ip, 'since' => $this->broadcastTime($djs[0]->last_login ?? null, true), 'codec' => $tipos[$fonte->server_type ?? ''] ?? 'AAC+', 'bitrate' => (string) ($fonte->bitrate ?? '128'), ]; } }