mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-14 21:26:37 +00:00
A new "smarter" synchronization system that can be invoked and debugged directly from the admin pages.
This commit is contained in:
parent
5a53cce814
commit
7bc30d8bed
92
app/library/PVL/NewsManager.php
Normal file
92
app/library/PVL/NewsManager.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
namespace PVL;
|
||||
|
||||
use \Entity\NetworkNews;
|
||||
|
||||
class NewsManager
|
||||
{
|
||||
public static function syncNetwork()
|
||||
{
|
||||
$em = \Zend_Registry::get('em');
|
||||
|
||||
// Pull featured images.
|
||||
$timestamp_threshold = strtotime('-6 weeks');
|
||||
|
||||
$api_params = array(
|
||||
'api_key' => 'Hp1W4lpJ0dhHA7pOGih0yow02ZXAFHdiIR5bzFS67C0xlERPAZ',
|
||||
'limit' => 10,
|
||||
);
|
||||
$api_url = 'http://api.tumblr.com/v2/blog/news.ponyvillelive.com/posts/photo?'.http_build_query($api_params);
|
||||
|
||||
$results_raw = @file_get_contents($api_url);
|
||||
$news_items = array();
|
||||
|
||||
if ($results_raw)
|
||||
{
|
||||
$results = json_decode($results_raw, true);
|
||||
$posts = $results['response']['posts'];
|
||||
|
||||
$network_news = array();
|
||||
foreach((array)$posts as $post)
|
||||
{
|
||||
$image = $post['photos'][0]['original_size'];
|
||||
|
||||
if ($image['height'] > 250)
|
||||
continue;
|
||||
|
||||
// Copy the image to the local static directory (for SSL and other caching support).
|
||||
$image_url = $image['url'];
|
||||
$image_url_basename = basename($image_url);
|
||||
|
||||
$local_path_base = 'rotators/'.$image_url_basename;
|
||||
|
||||
$local_path = DF_UPLOAD_FOLDER.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $local_path_base);
|
||||
$local_url = $local_path_base;
|
||||
|
||||
if (!file_exists($local_path))
|
||||
@copy($image_url, $local_path);
|
||||
|
||||
$tags = array_map('strtolower', (array)$post['tags']);
|
||||
if (in_array('archive', $tags))
|
||||
continue;
|
||||
|
||||
$description = \DF\Utilities::truncateText(strip_tags($post['caption']), 250);
|
||||
|
||||
if (strpos($description, ':') !== FALSE)
|
||||
{
|
||||
list($title, $description) = explode(':', $description, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
$title = $description;
|
||||
$description = NULL;
|
||||
}
|
||||
|
||||
$news_row = array(
|
||||
'id' => 'tumblr_'.$post['id'],
|
||||
'title' => trim($title),
|
||||
'body' => trim($description),
|
||||
'image_url' => $local_url,
|
||||
'web_url' => $post['post_url'],
|
||||
'timestamp' => $post['timestamp'],
|
||||
);
|
||||
|
||||
if ($news_row['timestamp'] >= $timestamp_threshold)
|
||||
$news_items[] = $news_row;
|
||||
}
|
||||
|
||||
// Delete current rotator contents.
|
||||
$em->createQuery('DELETE FROM Entity\NetworkNews nn')->execute();
|
||||
|
||||
foreach($news_items as $item)
|
||||
{
|
||||
$record = new NetworkNews;
|
||||
$record->fromArray($item);
|
||||
|
||||
$em->persist($record);
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,9 +18,9 @@ class ScheduleManager
|
|||
|
||||
$schedule_items = array();
|
||||
$schedule_records = array();
|
||||
$schedule_stations = array();
|
||||
|
||||
// PVL news
|
||||
/*
|
||||
// PVL news (retired for con center)
|
||||
$schedule_items[] = array(
|
||||
'name' => 'PVL Global Events',
|
||||
'url' => 'https://www.google.com/calendar/feeds/lj3d00magjlucuk902rarrhhrg%40group.calendar.google.com/public/full',
|
||||
|
@ -29,28 +29,27 @@ class ScheduleManager
|
|||
'image_url' => \DF\Url::content('pvl_square.png'),
|
||||
);
|
||||
$schedule_stations[0] = NULL;
|
||||
*/
|
||||
|
||||
$stations = $em->createQuery('SELECT s FROM Entity\Station s WHERE s.category IN (:types) AND s.is_active = 1')
|
||||
->setParameter('types', array('audio', 'video'))
|
||||
->execute();
|
||||
->getArrayResult();
|
||||
|
||||
foreach($stations as $station)
|
||||
{
|
||||
if ($station->gcal_url)
|
||||
if ($station['gcal_url'])
|
||||
{
|
||||
$schedule_stations[$station->id] = $station;
|
||||
|
||||
$schedule_items[] = array(
|
||||
'name' => $station->name,
|
||||
'url' => $station->gcal_url,
|
||||
'name' => $station['name'],
|
||||
'url' => $station['gcal_url'],
|
||||
'type' => 'station',
|
||||
'station_id' => $station->id,
|
||||
'image_url' => \DF\Url::content($station->image_url),
|
||||
'station_id' => $station['id'],
|
||||
'image_url' => \DF\Url::content($station['image_url']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
\PVL\Debug::startTimer('Get Calendar Records');
|
||||
Debug::startTimer('Get Calendar Records');
|
||||
|
||||
$time_check_start = time();
|
||||
|
||||
|
@ -80,11 +79,14 @@ class ScheduleManager
|
|||
$calendar_array = json_decode($calendar_raw, true);
|
||||
|
||||
if (empty($calendar_array['feed']['entry']))
|
||||
{
|
||||
Debug::log($calendar_raw);
|
||||
continue;
|
||||
}
|
||||
|
||||
$events = (array)$calendar_array['feed']['entry'];
|
||||
|
||||
\PVL\Debug::print_r($calendar_array);
|
||||
Debug::print_r($calendar_array);
|
||||
|
||||
$all_events = array();
|
||||
|
||||
|
@ -149,10 +151,16 @@ class ScheduleManager
|
|||
}
|
||||
}
|
||||
|
||||
\PVL\Debug::endTimer('Get Calendar Records');
|
||||
Debug::endTimer('Get Calendar Records');
|
||||
|
||||
if (count($schedule_records) == 0)
|
||||
{
|
||||
Debug::log('Error: No calendar records loaded');
|
||||
return;
|
||||
}
|
||||
|
||||
// Add/Remove all differential records.
|
||||
\PVL\Debug::startTimer('Sync DB Records');
|
||||
Debug::startTimer('Sync DB Records');
|
||||
|
||||
$em->createQuery('DELETE FROM Entity\Schedule s WHERE s.type = :type AND s.station_id NOT IN (:station_ids)')
|
||||
->setParameter('type', 'station')
|
||||
|
@ -161,7 +169,7 @@ class ScheduleManager
|
|||
|
||||
foreach($schedule_records as $station_id => $station_records)
|
||||
{
|
||||
$station = $schedule_stations[$station_id];
|
||||
$station = Station::find($station_id);
|
||||
|
||||
if ($station_id == 0)
|
||||
{
|
||||
|
@ -204,19 +212,20 @@ class ScheduleManager
|
|||
$em->persist($record);
|
||||
}
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
|
||||
\PVL\Debug::endTimer('Sync DB Records');
|
||||
Debug::endTimer('Sync DB Records');
|
||||
|
||||
Settings::setSetting('schedule_manager_last_run', time());
|
||||
}
|
||||
|
||||
public static function requestExternalUrl($url, $name = 'Calendar')
|
||||
{
|
||||
\PVL\Debug::startTimer('Request URL '.$name);
|
||||
\PVL\Debug::log($url);
|
||||
Debug::startTimer('Request URL '.$name);
|
||||
Debug::log($url);
|
||||
|
||||
// Start cURL request.
|
||||
$curl = curl_init();
|
||||
|
@ -228,11 +237,11 @@ class ScheduleManager
|
|||
$return_raw = \PVL\Utilities::curl_exec_utf8($curl);
|
||||
// End cURL request.
|
||||
|
||||
\PVL\Debug::endTimer('Request URL '.$name);
|
||||
Debug::endTimer('Request URL '.$name);
|
||||
|
||||
$error = curl_error($curl);
|
||||
if ($error)
|
||||
\PVL\Debug::log('Curl Error:'.$error);
|
||||
Debug::log('Curl Error:'.$error);
|
||||
|
||||
return $return_raw;
|
||||
}
|
||||
|
|
124
app/library/PVL/SyncManager.php
Normal file
124
app/library/PVL/SyncManager.php
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
namespace PVL;
|
||||
|
||||
use \Entity\Settings;
|
||||
|
||||
class SyncManager
|
||||
{
|
||||
public static function syncNowplaying()
|
||||
{
|
||||
set_time_limit(60);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Prevent nowplaying from running on top of itself.
|
||||
$last_start = Settings::getSetting('nowplaying_last_started', 0);
|
||||
$last_end = Settings::getSetting('nowplaying_last_run', 0);
|
||||
|
||||
if ($last_start > $last_end && $last_start >= (time() - 60))
|
||||
return;
|
||||
|
||||
// Sync schedules.
|
||||
Settings::setSetting('nowplaying_last_started', time());
|
||||
|
||||
NowPlaying::generate();
|
||||
|
||||
Settings::setSetting('nowplaying_last_run', time());
|
||||
}
|
||||
|
||||
public static function syncShort()
|
||||
{
|
||||
set_time_limit(60);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Send notifications related to schedules (high priority).
|
||||
NotificationManager::run();
|
||||
|
||||
Settings::setSetting('sync_fast_last_run', time());
|
||||
}
|
||||
|
||||
public static function syncMedium()
|
||||
{
|
||||
set_time_limit(300);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Pull the homepage news.
|
||||
NewsManager::syncNetwork();
|
||||
|
||||
// Sync schedules (highest priority).
|
||||
ScheduleManager::run(!DF_IS_COMMAND_LINE);
|
||||
|
||||
// Sync show episodes and artist news (high priority).
|
||||
PodcastManager::run();
|
||||
|
||||
// Sync CentovaCast song data.
|
||||
try
|
||||
{
|
||||
CentovaCast::sync();
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
echo "Error syncing CentovaCast:\n";
|
||||
echo $e->getMessage()."\n";
|
||||
}
|
||||
|
||||
// Generate cache files.
|
||||
CacheManager::generateSlimPlayer();
|
||||
|
||||
Settings::setSetting('sync_last_run', time());
|
||||
}
|
||||
|
||||
public static function syncLong()
|
||||
{
|
||||
set_time_limit(1800);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Sync analytical and statistical data (long running).
|
||||
AnalyticsManager::run();
|
||||
|
||||
// Update convention archives.
|
||||
ConventionManager::run();
|
||||
|
||||
// Sync the BronyTunes library.
|
||||
Service\BronyTunes::load();
|
||||
|
||||
// Sync the Pony.fm library.
|
||||
Service\PonyFm::load();
|
||||
|
||||
// Sync the EqBeats library.
|
||||
Service\EqBeats::load();
|
||||
|
||||
Settings::setSetting('sync_slow_last_run', time());
|
||||
}
|
||||
|
||||
public static function getSyncTimes()
|
||||
{
|
||||
$syncs = array(
|
||||
'nowplaying' => array(
|
||||
'name' => 'Now Playing Data',
|
||||
'latest' => Settings::getSetting('nowplaying_last_run', 0),
|
||||
),
|
||||
'short' => array(
|
||||
'name' => '1-Minute Sync',
|
||||
'latest' => Settings::getSetting('sync_fast_last_run', 0),
|
||||
),
|
||||
'medium' => array(
|
||||
'name' => '5-Minute Sync',
|
||||
'latest' => Settings::getSetting('sync_last_run', 0),
|
||||
),
|
||||
'long' => array(
|
||||
'name' => '1-Hour Sync',
|
||||
'latest' => Settings::getSetting('sync_slow_last_run', 0),
|
||||
),
|
||||
);
|
||||
|
||||
foreach($syncs as $sync_key => $sync_info)
|
||||
{
|
||||
$sync_latest = $sync_info['latest'];
|
||||
|
||||
$syncs[$sync_key]['diff'] = time()-$sync_latest;
|
||||
$syncs[$sync_key]['diff_text'] = \DF\Utilities::timeDifferenceText($sync_latest, time());
|
||||
}
|
||||
|
||||
return $syncs;
|
||||
}
|
||||
}
|
|
@ -58,89 +58,4 @@ class NetworkNews extends \DF\Doctrine\Entity
|
|||
|
||||
return $network_news;
|
||||
}
|
||||
|
||||
public static function load()
|
||||
{
|
||||
$em = self::getEntityManager();
|
||||
|
||||
// Pull featured images.
|
||||
$timestamp_threshold = strtotime('-6 weeks');
|
||||
|
||||
$api_params = array(
|
||||
'api_key' => 'Hp1W4lpJ0dhHA7pOGih0yow02ZXAFHdiIR5bzFS67C0xlERPAZ',
|
||||
'limit' => 10,
|
||||
);
|
||||
$api_url = 'http://api.tumblr.com/v2/blog/news.ponyvillelive.com/posts/photo?'.http_build_query($api_params);
|
||||
|
||||
$results_raw = @file_get_contents($api_url);
|
||||
$news_items = array();
|
||||
|
||||
if ($results_raw)
|
||||
{
|
||||
$results = json_decode($results_raw, true);
|
||||
$posts = $results['response']['posts'];
|
||||
|
||||
$network_news = array();
|
||||
foreach((array)$posts as $post)
|
||||
{
|
||||
$image = $post['photos'][0]['original_size'];
|
||||
|
||||
if ($image['height'] > 250)
|
||||
continue;
|
||||
|
||||
// Copy the image to the local static directory (for SSL and other caching support).
|
||||
$image_url = $image['url'];
|
||||
$image_url_basename = basename($image_url);
|
||||
|
||||
$local_path_base = 'rotators/'.$image_url_basename;
|
||||
|
||||
$local_path = DF_UPLOAD_FOLDER.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $local_path_base);
|
||||
$local_url = $local_path_base;
|
||||
|
||||
if (!file_exists($local_path))
|
||||
@copy($image_url, $local_path);
|
||||
|
||||
$tags = array_map('strtolower', (array)$post['tags']);
|
||||
if (in_array('archive', $tags))
|
||||
continue;
|
||||
|
||||
$description = \DF\Utilities::truncateText(strip_tags($post['caption']), 250);
|
||||
|
||||
if (strpos($description, ':') !== FALSE)
|
||||
{
|
||||
list($title, $description) = explode(':', $description, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
$title = $description;
|
||||
$description = NULL;
|
||||
}
|
||||
|
||||
$news_row = array(
|
||||
'id' => 'tumblr_'.$post['id'],
|
||||
'title' => trim($title),
|
||||
'body' => trim($description),
|
||||
'image_url' => $local_url,
|
||||
'web_url' => $post['post_url'],
|
||||
'timestamp' => $post['timestamp'],
|
||||
);
|
||||
|
||||
if ($news_row['timestamp'] >= $timestamp_threshold)
|
||||
$news_items[] = $news_row;
|
||||
}
|
||||
|
||||
// Delete current rotator contents.
|
||||
$em->createQuery('DELETE FROM '.__CLASS__.' nn')->execute();
|
||||
|
||||
foreach($news_items as $item)
|
||||
{
|
||||
$record = new self;
|
||||
$record->fromArray($item);
|
||||
|
||||
$em->persist($record);
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -96,5 +96,43 @@ class Admin_IndexController extends \DF\Controller\Action
|
|||
|
||||
$this->view->network_metrics = json_encode($network_metrics);
|
||||
$this->view->station_metrics = json_encode($station_metrics);
|
||||
|
||||
// Synchronization statuses
|
||||
if ($this->acl->isAllowed('administer all'))
|
||||
$this->view->sync_times = \PVL\SyncManager::getSyncTimes();
|
||||
}
|
||||
|
||||
public function syncAction()
|
||||
{
|
||||
$this->acl->checkPermission('administer all');
|
||||
|
||||
$this->doNotRender();
|
||||
|
||||
\PVL\Debug::setEchoMode(TRUE);
|
||||
\PVL\Debug::startTimer('sync_task');
|
||||
|
||||
$type = $this->getParam('type', 'nowplaying');
|
||||
switch($type)
|
||||
{
|
||||
case "long":
|
||||
\PVL\SyncManager::syncLong();
|
||||
break;
|
||||
|
||||
case "medium":
|
||||
\PVL\SyncManager::syncMedium();
|
||||
break;
|
||||
|
||||
case "short":
|
||||
\PVL\SyncManager::syncShort();
|
||||
break;
|
||||
|
||||
case "nowplaying":
|
||||
default:
|
||||
\PVL\SyncManager::syncNowplaying();
|
||||
break;
|
||||
}
|
||||
|
||||
\PVL\Debug::endTimer('sync_task');
|
||||
\PVL\Debug::log('Sync task complete. See log above.');
|
||||
}
|
||||
}
|
|
@ -47,6 +47,24 @@ if ($skin == "dark")
|
|||
<div id="network_listeners_by_day" style="height: 250px;"></div>
|
||||
<div id="station_listeners_by_day" style="height: 450px;"></div>
|
||||
</div>
|
||||
<div class="well no-margin">
|
||||
<h2>Synchronization Status</h2>
|
||||
<div class="row-fluid">
|
||||
<? foreach($this->sync_times as $sync_key => $sync_info): ?>
|
||||
<div class="span3">
|
||||
<h4><?=$sync_info['name'] ?></h4>
|
||||
<p><?=date('F j, Y g:ia', $sync_info['latest']) ?><br><small><?=$sync_info['diff_text'] ?> ago</small></p>
|
||||
|
||||
<?=$this->button(array(
|
||||
'type' => 'small',
|
||||
'href' => $this->routeFromHere(array('action' => 'sync', 'type' => $sync_key)),
|
||||
'text' => 'Run Manually',
|
||||
'target' => '_blank',
|
||||
)) ?>
|
||||
</div>
|
||||
<? endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -6,22 +6,4 @@
|
|||
require_once dirname(__FILE__) . '/../app/bootstrap.php';
|
||||
$application->bootstrap();
|
||||
|
||||
if (DF_APPLICATION_ENV != 'production')
|
||||
\PVL\Debug::setEchoMode(TRUE);
|
||||
|
||||
set_time_limit(60);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Prevent nowplaying from running on top of itself.
|
||||
$last_start = \Entity\Settings::getSetting('nowplaying_last_started', 0);
|
||||
$last_end = \Entity\Settings::getSetting('nowplaying_last_run', 0);
|
||||
|
||||
if ($last_start > $last_end && $last_start >= (time() - 60))
|
||||
exit;
|
||||
|
||||
// Sync schedules.
|
||||
\Entity\Settings::setSetting('nowplaying_last_started', time());
|
||||
|
||||
\PVL\NowPlaying::generate();
|
||||
|
||||
\Entity\Settings::setSetting('nowplaying_last_run', time());
|
||||
\PVL\SyncManager::syncNowplaying();
|
|
@ -6,27 +6,4 @@
|
|||
require_once dirname(__FILE__) . '/../app/bootstrap.php';
|
||||
$application->bootstrap();
|
||||
|
||||
set_time_limit(300);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Generate cache files.
|
||||
\PVL\CacheManager::generateSlimPlayer();
|
||||
|
||||
// Sync schedules (highest priority).
|
||||
\PVL\ScheduleManager::run();
|
||||
|
||||
// Sync show episodes and artist news (high priority).
|
||||
\PVL\PodcastManager::run();
|
||||
|
||||
// Sync CentovaCast song data.
|
||||
try
|
||||
{
|
||||
\PVL\CentovaCast::sync();
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
echo "Error syncing CentovaCast:\n";
|
||||
echo $e->getMessage()."\n";
|
||||
}
|
||||
|
||||
\Entity\Settings::setSetting('sync_last_run', time());
|
||||
\PVL\SyncManager::syncMedium();
|
|
@ -6,13 +6,4 @@
|
|||
require_once dirname(__FILE__) . '/../app/bootstrap.php';
|
||||
$application->bootstrap();
|
||||
|
||||
set_time_limit(60);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Pull the homepage news.
|
||||
\Entity\NetworkNews::load();
|
||||
|
||||
// Send notifications related to schedules (high priority).
|
||||
\PVL\NotificationManager::run();
|
||||
|
||||
\Entity\Settings::setSetting('sync_fast_last_run', time());
|
||||
\PVL\SyncManager::syncShort();
|
|
@ -6,22 +6,4 @@
|
|||
require_once dirname(__FILE__) . '/../app/bootstrap.php';
|
||||
$application->bootstrap();
|
||||
|
||||
set_time_limit(1800);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
// Sync analytical and statistical data (long running).
|
||||
\PVL\AnalyticsManager::run();
|
||||
|
||||
// Update convention archives.
|
||||
\PVL\ConventionManager::run();
|
||||
|
||||
// Sync the BronyTunes library.
|
||||
\PVL\Service\BronyTunes::load();
|
||||
|
||||
// Sync the Pony.fm library.
|
||||
\PVL\Service\PonyFm::load();
|
||||
|
||||
// Sync the EqBeats library.
|
||||
\PVL\Service\EqBeats::load();
|
||||
|
||||
\Entity\Settings::setSetting('sync_slow_last_run', time());
|
||||
\PVL\SyncManager::syncLong();
|
Loading…
Reference in New Issue
Block a user