4
0
mirror of https://github.com/AzuraCast/AzuraCast.git synced 2024-06-26 10:57:06 +00:00

Add ability to view requests, delete un-queued ones, and force queue in LS to not overload.

This commit is contained in:
Buster Silver 2017-04-14 01:40:56 -05:00
parent 47de040244
commit c97662787b
7 changed files with 178 additions and 25 deletions

View File

@ -35,7 +35,7 @@ class StationRequestRepository extends \App\Doctrine\Repository
}
// Check if the song is already enqueued as a request.
$pending_request_threshold = time() - (60 * 30);
$pending_request_threshold = time() - (60 * 10);
try {
$pending_request = $this->_em->createQuery('SELECT sr.timestamp

View File

@ -0,0 +1,43 @@
<?php
namespace Controller\Stations;
use Entity;
class RequestsController extends BaseController
{
protected function permissions()
{
return $this->acl->isAllowed('view station reports', $this->station->id);
}
public function indexAction()
{
$this->view->requests = $this->em->createQuery('SELECT sr, sm, s FROM Entity\StationRequest sr
JOIN sr.track sm
JOIN sm.song s
WHERE sr.station_id = :station_id
ORDER BY sr.timestamp DESC')
->setParameter('station_id', $this->station->id)
->getArrayResult();
}
public function deleteAction()
{
$id = (int)$this->getParam('request_id');
$media = $this->em->getRepository(Entity\StationRequest::class)->findOneBy([
'id' => $id,
'station_id' => $this->station->id,
'played_at' => 0
]);
if ($media instanceof Entity\StationRequest) {
$this->em->remove($media);
$this->em->flush();
$this->alert('<b>Request deleted!</b>', 'green');
}
return $this->redirectFromHere(['action' => 'index', 'media_id' => null]);
}
}

View File

@ -55,6 +55,13 @@ return function(\Slim\App $app) {
});
$this->group('/requests', function () {
$this->get('', 'stations:requests:index')->setName('stations:requests:index');
$this->get('/delete/{request_id}', 'stations:requests:delete')->setName('stations:requests:delete');
});
$this->group('/reports', function () {
$this->get('/timeline[/format/{format}]', 'stations:index:timeline')->setName('stations:index:timeline');

View File

@ -0,0 +1,77 @@
<?php $this->layout('main', ['title' => _('Song Requests'), 'manual' => true]) ?>
<div class="block-header">
<h2><?=$this->e($station->name) ?></h2>
</div>
<div class="card">
<div class="card-header ch-alt">
<h2><?=_('Song Requests') ?></h2>
</div>
<div class="table-responsive">
<table class="data-table table table-striped">
<colgroup>
<col width="20%">
<col width="20%">
<col width="30%">
<col width="15%">
<col width="15%">
</colgroup>
<thead>
<tr>
<th data-column-id="timestamp"><?=_('Date Requested') ?></th>
<th data-column-id="played_at"><?=_('Date Played') ?></th>
<th data-column-id="song"><?=_('Song Title') ?></th>
<th data-column-id="ip"><?=_('Requester IP') ?></th>
<th data-column-id="actions"><?=_('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach($requests as $request_row): ?>
<tr class="input" id="request_<?=$request_row['id'] ?>">
<td class="text-center"><?=date('F j, Y g:ia', $request_row['timestamp']) ?></td>
<td class="text-center">
<?php if ($request_row['played_at'] > 0): ?>
<?=date('F j, Y g:ia', $request_row['played_at']) ?>
<?php else: ?>
<?=_('Not Played') ?>
<?php endif; ?>
</td>
<td>
<?php if ($request_row['track']['song']['title']): ?>
<b><?=$request_row['track']['song']['title'] ?></b><br>
<?=$request_row['track']['song']['artist'] ?>
<?php else: ?>
<?=$request_row['track']['song']['text'] ?>
<?php endif; ?>
</td>
<td><?=$request_row['ip'] ?></td>
<td>
<?php if ($request_row['played_at'] == 0): ?>
<a class="btn btn-sm btn-danger" href="<?=$url->routeFromHere(['action' => 'delete', 'request_id' => $request_row['id']]) ?>"><?=_('Delete') ?></a>
<?php else: ?>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
$(function() {
$(".data-table").bootgrid({
caseSensitive: false,
sorting: false,
css: {
icon: 'zmdi icon',
iconColumns: 'zmdi-view-module',
iconDown: 'zmdi-sort-amount-desc',
iconRefresh: 'zmdi-refresh',
iconUp: 'zmdi-sort-amount-asc'
}
});
});
</script>

View File

@ -44,6 +44,9 @@
<a href="" data-ma-action="submenu-toggle"><i class="zmdi zmdi-assignment"></i> <?=_('Reports') ?></a>
<ul>
<?php if ($station->enable_requests): ?>
<li><a href="<?=$url->named('stations:requests:index', ['station' => $station->id]) ?>"><?=_('Song Requests') ?></a></li>
<?php endif; ?>
<li><a href="<?=$url->named('stations:index:timeline', ['station' => $station->id]) ?>"><?=_('Song Playback Timeline') ?></a></li>
<?php if ($backend->supportsMedia()): ?>
<li><a href="<?=$url->named('stations:reports:performance', ['station' => $station->id]) ?>"><?=_('Song Listener Impact') ?></a></li>

View File

@ -325,6 +325,12 @@ class LiquidSoap extends BackendAbstract
public function request($music_file)
{
$queue = $this->command('requests.queue');
if (!empty($queue[0])) {
throw new \Exception('Song(s) still pending in request queue.');
}
return $this->command('requests.push ' . $music_file);
}
@ -343,14 +349,14 @@ class LiquidSoap extends BackendAbstract
fwrite($fp, str_replace(["\\'", '&amp;'], ["'", '&'], urldecode($command_str)) . "\nquit\n");
$eat = '';
$response = [];
while (!feof($fp)) {
$eat .= fgets($fp, 1024);
$response[] = trim(fgets($fp, 1024));
}
fclose($fp);
return true;
return $response;
}
protected function _getTelnetPort()

View File

@ -3,19 +3,21 @@ namespace AzuraCast\Sync;
use Doctrine\ORM\EntityManager;
use Entity\Station;
use Entity\StationRequest;
class RadioRequests extends SyncAbstract
{
/** @var EntityManager $em */
protected $em;
public function run()
{
/** @var EntityManager $em */
$em = $this->di['em'];
$this->em = $this->di['em'];
$stations = $em->getRepository(Station::class)->findAll();
$stations = $this->em->getRepository(Station::class)->findAll();
foreach ($stations as $station) {
/** @var $station Station */
if (!$station->enable_requests) {
continue;
}
@ -28,29 +30,44 @@ class RadioRequests extends SyncAbstract
$threshold = time() - ($threshold_minutes * 60);
// Look up all requests that have at least waited as long as the threshold.
$requests = $em->createQuery('SELECT sr, sm FROM \Entity\StationRequest sr JOIN sr.track sm
$request = $this->em->createQuery('SELECT sr, sm FROM \Entity\StationRequest sr JOIN sr.track sm
WHERE sr.played_at = 0 AND sr.station_id = :station_id AND sr.timestamp <= :threshold
ORDER BY sr.id ASC')
->setParameter('station_id', $station->id)
->setParameter('threshold', $threshold)
->execute();
->setMaxResults(1)
->getOneOrNullResult();
foreach ($requests as $request) {
\App\Debug::log($station->name . ': Request to play ' . $request->track->artist . ' - ' . $request->track->title);
// Log the request as played.
$request->played_at = time();
$em->persist($request);
$em->flush();
// Send request to the station to play the request.
$backend = $station->getBackendAdapter($this->di);
if (method_exists($backend, 'request')) {
$backend->request($request->track->getFullPath());
}
if ($request instanceof StationRequest) {
$this->_submitRequest($station, $request);
}
}
}
protected function _submitRequest(Station $station, StationRequest $request)
{
\App\Debug::log($station->name . ': Request to play ' . $request->track->artist . ' - ' . $request->track->title);
// Send request to the station to play the request.
$backend = $station->getBackendAdapter($this->di);
if (!method_exists($backend, 'request')) {
return false;
}
try {
$backend->request($request->track->getFullPath());
} catch(\Exception $e) {
\App\Debug::log('Request error: '.$e->getMessage());
return false;
}
// Log the request as played.
$request->played_at = time();
$this->em->persist($request);
$this->em->flush();
return true;
}
}