protected function _process(&$np) { if (empty($this->data_url)) { $twitch_url = parse_url($this->stream_url, PHP_URL_PATH); $twitch_username = trim($twitch_url, '/'); $this->data_url = 'https://api.twitch.tv/kraken/streams/' . $twitch_username; } $return_raw = $this->getUrl(); if (empty($return_raw)) { return false; } $return = json_decode($return_raw, true); $stream = $return['stream']; Debug::print_r($stream); if (empty($stream)) { return false; } $np['meta']['status'] = 'online'; $np['meta']['listeners'] = (int) $stream['viewers']; $np['on_air']['text'] = $stream['game']; if (is_array($stream['preview'])) { $np['on_air']['thumbnail'] = $stream['preview']['medium'] . '?t=' . time(); } else { $np['on_air']['thumbnail'] = $stream['preview'] . '?t=' . time(); } return true; }
public function testAction() { $this->doNotRender(); set_time_limit(0); ini_set('memory_limit', '-1'); Debug::setEchoMode(); Debug::log('Donezo!'); }
public static function import($new_songs, $force = false) { $db_stats = array('skipped' => 0, 'updated' => 0, 'inserted' => 0, 'deleted' => 0); if (empty($new_songs)) { return false; } Debug::startTimer('Import data into database'); $em = self::getEntityManager(); $existing_hashes = self::getHashes(); $existing_ids = self::getIds(); $unused_hashes = $existing_hashes; $song_ids = Song::getIds(); $i = 0; foreach ($new_songs as $song_hash => $processed) { if (!in_array($song_hash, $song_ids)) { Song::getOrCreate($processed); } if (isset($existing_hashes[$song_hash])) { if ($force && $existing_hashes[$song_hash] == $processed['id']) { $db_stats['updated']++; $record = self::find($processed['id']); } else { $db_stats['skipped']++; $record = null; } } else { if (isset($existing_ids[$processed['id']])) { $db_stats['updated']++; $record = self::find($processed['id']); } else { $db_stats['inserted']++; $record = new self(); } } if ($record instanceof self) { $existing_ids[$processed['id']] = $processed['hash']; $existing_hashes[$processed['hash']] = $processed['id']; $record->fromArray($processed); $em->persist($record); } unset($unused_hashes[$song_hash]); $i++; if ($i % 200 == 0) { $em->flush(); $em->clear(); } } $em->flush(); $em->clear(); // Clear out any songs not found. $hashes_remaining = array_keys($unused_hashes); $db_stats['deleted'] = count($hashes_remaining); $em->createQuery('DELETE FROM ' . __CLASS__ . ' e WHERE e.hash IN (:hashes)')->setParameter('hashes', $hashes_remaining)->execute(); Debug::endTimer('Import data into database'); Debug::print_r($db_stats); return $db_stats; }
public static function processPodcast(Podcast $record) { $em = self::getEntityManager(); $db_stats = array('record' => $record->name, 'updated' => 0, 'inserted' => 0, 'deleted' => 0); foreach ($record->sources as $source) { if ($source->is_active) { $new_episodes = $source->process(); if (empty($new_episodes)) { continue; } // Reconcile differences. $existing_episodes = array(); foreach ($source->episodes as $episode) { // Remove duplicate episode. if (isset($existing_episodes[$episode->guid])) { $db_stats['deleted']++; $em->remove($episode); } else { $existing_episodes[$episode->guid] = $episode; } } foreach ($new_episodes as $ep_guid => $ep_info) { if (isset($existing_episodes[$ep_guid])) { $db_stats['updated']++; $episode = $existing_episodes[$ep_guid]; } else { $db_stats['inserted']++; $episode = new PodcastEpisode(); $episode->source = $source; $episode->podcast = $record; // Preload banner URL if specified, and if episode is new enough. if ($ep_info['banner_url'] && $ep_info['timestamp'] > time() - 86400 * 14) { PodcastEpisode::getEpisodeRotatorUrl($ep_info, $record, $source); } } $episode->fromArray($ep_info); $em->persist($episode); unset($existing_episodes[$ep_guid]); } foreach ($existing_episodes as $ep_guid => $ep_to_remove) { $db_stats['deleted']++; $em->remove($ep_to_remove); } } else { foreach ($source->episodes as $episode) { $em->remove($episode); } } $em->flush(); } Debug::print_r($db_stats); return true; }
/** * Individual Record Fetching (Retired) */ public static function fetch(Song $song) { $base_url = 'https://pony.fm/api/v1/tracks/radio-details/'; $song_hash = self::_getHash($song); $url = $base_url . $song_hash . '?client=ponyvillelive'; \PVL\Debug::log('Hash Search: ' . $url); $result_raw = @file_get_contents($url); if ($result_raw) { $result = json_decode($result_raw, TRUE); \PVL\Debug::print_r($result); return $result; } return NULL; }
public function testAction() { $this->doNotRender(); set_time_limit(0); ini_set('memory_limit', '-1'); Debug::setEchoMode(); // -------- START HERE -------- // \PVL\CentovaCast::sync(); Debug::log('CCast Sync Complete'); $station = \Entity\Station::getRepository()->findOneBy(array('name' => 'PonyvilleFM')); $tracks = \PVL\CentovaCast::fetchTracks($station); Debug::print_r($tracks); // -------- END HERE -------- // Debug::log('Done!'); }
protected static function _querySearch($song) { $base_url = 'https://eqbeats.org/tracks/search/json'; $url = $base_url . '?' . http_build_query(array('q' => $song->artist . ' ' . $song->title, 'client' => 'ponyvillelive')); Debug::log('Query Search: ' . $url); $result = file_get_contents($url); if ($result) { $rows = json_decode($result, TRUE); foreach ($rows as $row) { $song_hash = Song::getSongHash(array('artist' => $row['user']['name'], 'title' => $row['title'])); if (strcmp($song_hash, $song->id) == 0) { return $row; } } } return NULL; }
public static function load($force = false) { set_time_limit(300); Debug::startTimer('Load remote data'); $remote_url = 'https://bronytunes.com/retrieve_songs.php?client_type=ponyvillelive'; $result_raw = @file_get_contents($remote_url); Debug::endTimer('Load remote data'); if ($result_raw) { $result = json_decode($result_raw, TRUE); $new_songs = array(); foreach ((array) $result as $row) { $processed = External::processRemote($row); $processed['hash'] = Song::getSongHash($processed); $new_songs[$processed['hash']] = $processed; } return External::import($new_songs, $force); } return false; }
public static function run() { $di = \Phalcon\Di::getDefault(); $em = $di->get('em'); // Assemble news items from other sources. $news_items_raw = array(self::_runTumblrNews($di), self::_runConventionPromotions($di), self::_runPodcastEpisodes($di), self::_runScheduleItems($di)); $news_items = array(); foreach ($news_items_raw as $item_group) { $news_items = array_merge($news_items, (array) $item_group); } // Replace/insert into database. $news_stats = array('inserted' => 0, 'updated' => 0, 'deleted' => 0); if (!empty($news_items)) { $old_news_raw = NetworkNews::fetchAll(); $old_news = array(); foreach ($old_news_raw as $old_row) { $old_news[$old_row->id] = $old_row; } // Update or insert items. foreach ($news_items as $item) { if (isset($old_news[$item['id']])) { $news_stats['updated']++; $record = $old_news[$item['id']]; } else { $news_stats['inserted']++; $record = new NetworkNews(); } $record->fromArray($item); $em->persist($record); unset($old_news[$item['id']]); } // Delete unreferenced items. foreach ($old_news as $item_id => $item_to_remove) { $news_stats['deleted']++; $em->remove($item_to_remove); } $em->flush(); // Flush cache of homepage news. \DF\Cache::remove('homepage_featured_news'); } \PVL\Debug::print_r($news_stats); }
protected function _process(&$np) { $ls_url = parse_url($this->stream_url, PHP_URL_PATH); $ls_username = trim($ls_url, '/'); if (empty($this->data_url)) { $this->data_url = 'http://x' . $ls_username . 'x.api.channel.livestream.com/2.0/livestatus.xml'; } $xml = $this->getUrl(); if (empty($xml)) { return false; } $stream_data = Export::XmlToArray($xml); Debug::print_r($stream_data); if ($stream_data['channel']['ls:isLive'] && $stream_data['channel']['ls:isLive'] == 'true') { $np['meta']['status'] = 'online'; $np['meta']['listeners'] = (int) $stream_data['channel']['ls:currentViewerCount']; $np['on_air']['thumbnail'] = 'http://thumbnail.api.livestream.com/thumbnail?name=' . $ls_username . '&t=' . time(); $np['on_air']['text'] = 'Stream Online'; return true; } }
protected function _process(&$np) { if (empty($this->data_url)) { $us_url = parse_url($this->stream_url, PHP_URL_PATH); $us_path_parts = explode('/', trim($us_url, '/')); $us_username = array_pop($us_path_parts); $this->data_url = 'https://api.ustream.tv/channels/' . $us_username . '.json'; } $return_raw = $this->getUrl(); if (empty($return_raw)) { return false; } $return = json_decode($return_raw, true); $channel = $return['channel']; Debug::print_r($channel); if (empty($channel)) { return false; } $np['meta']['status'] = $channel['status'] == 'live' ? 'online' : 'offline'; $np['meta']['listeners'] = isset($channel['stats']['viewer']) ? (int) $channel['stats']['viewer'] : 0; $np['on_air']['text'] = $channel['title']; $np['on_air']['thumbnail'] = $channel['thumbnail']['live'] . '?t=' . time(); return true; }
/** * Process a podcast source and return remote data from it. * * @return array|bool */ public function process() { Debug::log('Processing source: ' . $this->type); $source_info = self::getSourceInfo($this->type); if (!isset($source_info['adapter'])) { Debug::log('No suitable adapter found!'); return FALSE; } $source_settings = isset($source_info['settings']) ? $source_info['settings'] : array(); // Look for new news items. $class_name = '\\PVL\\NewsAdapter\\' . $source_info['adapter']; $news_items = $class_name::fetch($this->url, $source_settings); if (empty($news_items)) { Debug::log('No news items found! Adapter: ' . $class_name); return FALSE; } $new_episodes = array(); foreach ((array) $news_items as $item) { $guid = $item['guid']; $new_episodes[$guid] = array('guid' => $guid, 'timestamp' => $item['timestamp'], 'title' => self::cleanUpText($item['title']), 'body' => self::cleanUpText($item['body']), 'summary' => self::getSummary($item['body']), 'web_url' => $item['web_url'], 'thumbnail_url' => isset($item['thumbnail_url']) ? $item['thumbnail_url'] : NULL, 'banner_url' => isset($item['banner_url']) ? $item['banner_url'] : NULL); } Debug::print_r($new_episodes); return $new_episodes; }
public static function run($force_run = false) { $di = \Phalcon\Di::getDefault(); $em = $di->get('em'); $config = $di->get('config'); // Set up Google Client. $gclient_api_key = $config->apis->google_apis_key; $gclient_app_name = $config->application->name; if (empty($gclient_api_key)) { return null; } $gclient = new \Google_Client(); $gclient->setApplicationName($gclient_app_name); $gclient->setDeveloperKey($gclient_api_key); $gcal = new \Google_Service_Calendar($gclient); // Prevent running repeatedly in too short of a time (avoid API limits). $last_run = Settings::getSetting('schedule_manager_last_run', 0); if ($last_run > time() - 60 && !$force_run) { return null; } $schedule_items = array(); $schedule_records = array(); $stations = $em->createQuery('SELECT s FROM Entity\\Station s WHERE (s.gcal_url IS NOT NULL AND s.gcal_url != \'\') AND s.is_active = 1')->getArrayResult(); $active_stations = Utilities::ipull($stations, 'id'); // Clear all invalid station records. $em->createQuery('DELETE FROM Entity\\Schedule s WHERE (s.station_id IS NOT NULL) AND (s.station_id NOT IN (:station_ids))')->setParameter('station_ids', $active_stations)->execute(); foreach ($stations as $station) { if ($station['gcal_url']) { $schedule_items[] = array('name' => $station['name'], 'url' => $station['gcal_url'], 'type' => 'station', 'station_id' => $station['id'], 'image_url' => \DF\Url::content($station['image_url'])); } } Debug::startTimer('Get Calendar Records'); // Time boundaries for calendar entries. $threshold_start = date(\DateTime::RFC3339, strtotime('-1 week')); $threshold_end = date(\DateTime::RFC3339, strtotime('+1 year')); foreach ($schedule_items as $item) { // Get the "calendar_id" from the URL provided by the user. $orig_url_parts = parse_url($item['url']); $url_path_parts = explode('/', $orig_url_parts['path']); $calendar_id = urldecode($url_path_parts[3]); if (empty($calendar_id)) { continue; } // Call the external Google Calendar client. try { $all_events = $gcal->events->listEvents($calendar_id, array('timeMin' => $threshold_start, 'timeMax' => $threshold_end, 'singleEvents' => 'true', 'orderBy' => 'startTime', 'maxResults' => '300')); } catch (\Exception $e) { continue; } // Process each individual event. foreach ($all_events as $event_orig) { $title = $event_orig->summary; $body = $event_orig->description; $location = $event_orig->location; $web_url = $event_orig->htmlLink; $banner_url = null; $is_all_day = false; $start_time_obj = $event_orig->start; if ($start_time_obj->date) { $is_all_day = true; $start_time = strtotime($start_time_obj->date . ' 00:00:00'); } else { $start_time = strtotime($start_time_obj->dateTime); } $end_time_obj = $event_orig->end; if ($end_time_obj->date) { $is_all_day = true; $end_time = strtotime($end_time_obj->date . ' 00:00:00'); } elseif ($end_time_obj) { $end_time = strtotime($end_time_obj->dateTime); } else { $end_time = $start_time; } // Detect URLs for link. if ($body && !$web_url) { preg_match('@((https?://)?([-\\w]+\\.[-\\w\\.]+)+\\w(:\\d+)?(/([-\\w/_\\.]*(\\?\\S+)?)?)*)@', $body, $urls); if (count($urls) > 0) { $web_url = $urls[0]; } } // Detect URLs for photo. if ($location) { preg_match('@((https?://)?([-\\w]+\\.[-\\w\\.]+)+\\w(:\\d+)?(/([-\\w/_\\.]*(\\?\\S+)?)?)*)@', $location, $urls); if (count($urls) > 0) { $banner_url = $urls[0]; } } $guid = md5(implode('|', array($event_orig->id, $start_time, $end_time, $title, $location))); $schedule_record = array('guid' => $guid, 'type' => $item['type'], 'start_time' => $start_time, 'end_time' => $end_time, 'is_all_day' => $is_all_day, 'title' => $title, 'location' => $location, 'body' => \DF\Utilities::truncateText(strip_tags($body), 300), 'banner_url' => $banner_url, 'web_url' => $web_url); \PVL\Debug::print_r($schedule_record); $schedule_records[$item['station_id']][$guid] = $schedule_record; } } Debug::endTimer('Get Calendar Records'); if (count($schedule_records) == 0) { Debug::log('Error: No calendar records loaded'); return; } // Add/Remove all differential records. Debug::startTimer('Sync DB Records'); foreach ($schedule_records as $station_id => $station_records) { $station = Station::find($station_id); if ($station_id == 0) { $existing_guids_raw = $em->createQuery('SELECT s.guid FROM Entity\\Schedule s WHERE s.station_id IS NULL')->getArrayResult(); } else { $existing_guids_raw = $em->createQuery('SELECT s.guid FROM Entity\\Schedule s WHERE s.station_id = :sid')->setParameter('sid', $station_id)->getArrayResult(); } $existing_guids = array(); foreach ($existing_guids_raw as $i) { $existing_guids[] = $i['guid']; } $new_guids = array_keys($station_records); $guids_to_delete = array_diff($existing_guids, $new_guids); if ($guids_to_delete) { $em->createQuery('DELETE FROM Entity\\Schedule s WHERE s.guid IN (:guids)')->setParameter('guids', $guids_to_delete)->execute(); } $guids_to_add = array_diff($new_guids, $existing_guids); if ($guids_to_add) { foreach ($guids_to_add as $guid) { $schedule_record = $station_records[$guid]; $record = new Schedule(); $record->station = $station; $record->fromArray($schedule_record); $em->persist($record); } } $em->flush(); $em->clear(); } Debug::endTimer('Sync DB Records'); Settings::setSetting('schedule_manager_last_run', time()); }
/** * Process a single video stream's NowPlaying info. * * @param StationStream $stream * @param Station $station * @return array Structured NowPlaying Data */ public static function processVideoStream(StationStream $stream, Station $station, $force = false) { $current_np_data = (array) $stream->nowplaying_data; if (!$force && NOWPLAYING_SEGMENT % 2 == 0 && !empty($current_np_data)) { return $current_np_data; } // Process stream. $custom_class = Station::getStationClassName($station->name); $custom_adapter = '\\PVL\\VideoAdapter\\' . $custom_class; $np = StationStream::api($stream); if (class_exists($custom_adapter)) { $np_adapter = new $custom_adapter($stream, $station); $stream_np = $np_adapter->process(); } else { $adapters = array(new \PVL\VideoAdapter\Livestream($stream, $station), new \PVL\VideoAdapter\TwitchTv($stream, $station), new \PVL\VideoAdapter\UStream($stream, $station), new \PVL\VideoAdapter\StreamUp($stream, $station)); foreach ($adapters as $np_adapter) { if ($np_adapter->canHandle()) { $stream_np = $np_adapter->process(); break; } } } if (!empty($stream_np)) { $np = array_merge($np, $stream_np); $np['status'] = isset($np['meta']['status']) ? $np['meta']['status'] : 'offline'; Debug::log('Adapter Class: ' . get_class($np_adapter)); Debug::print_r($np); } else { $np['on_air'] = array('text' => 'Stream Offline'); $np['meta'] = array('status' => 'offline', 'listeners' => 0); $np['status'] = 'offline'; } $stream->nowplaying_data = $np; return $np; }
public static function syncLong($force = false) { self::initSync(1800); // Sync analytical and statistical data (long running). Debug::runTimer('Run analytics manager', function () { AnalyticsManager::run(); }); // Update convention archives. Debug::runTimer('Run convention archives manager', function () { ConventionManager::run(); }); /* // Clean up old API calls. Debug::runTimer('Run API call cleanup', function() { ApiCall::cleanUp(); }); */ // Clean up old song history entries. Debug::runTimer('Run song history cleanup', function () { SongHistory::cleanUp(); }); // Sync the BronyTunes library. Debug::runTimer('Run BronyTunes sync', function () { Service\BronyTunes::load(); }); // Sync the Pony.fm library. Debug::runTimer('Run Pony.fm sync', function () { Service\PonyFm::load(); }); // Sync the EqBeats library. Debug::runTimer('Run EqBeats sync', function () { Service\EqBeats::load(); }); Settings::setSetting('sync_slow_last_run', time()); }
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: $segment = $this->getParam('segment', 1); define('NOWPLAYING_SEGMENT', $segment); \PVL\SyncManager::syncNowplaying(true); break; } \PVL\Debug::endTimer('sync_task'); \PVL\Debug::log('Sync task complete. See log above.'); }
/** * Send an individual notification. * * @param string $message The main message body of the tweet. * @param null $url URL to reference as a link in the tweet. * @param null $image URL or filesystem path of an image to reference. * @param bool $force Trigger a notification even in development mode. * @return bool */ public static function notify($message, $url = null, $image = null, $force = false) { static $twitter; \PVL\Debug::print_r(func_get_args()); // Suppress notifications for non-production applications. if (DF_APPLICATION_ENV != "production" && !$force) { return false; } // Send through Notifico hook. $payload = $message . ' - ' . $url; \PVL\Service\Notifico::post($payload); // Send through Twitter. if (!$twitter) { $di = \Phalcon\Di::getDefault(); $config = $di->get('config'); $twitter_config = $config->apis->twitter->toArray(); $twitter = new \tmhOAuth($twitter_config); } $message_length = 140; if ($url) { $message_length -= 23; } if ($image) { $message_length -= 23; } // Post t.co URLs directly instead of pulling down data. if (stristr($image, 't.co') !== FALSE) { $url .= ' ' . $image; $image = NULL; } // Cut off the URL $tweet = \DF\Utilities::truncateText($message, $message_length); if ($url) { $tweet .= ' ' . $url; } if ($image) { $image_data = base64_encode(@file_get_contents($image)); if (!empty($image_data)) { $twitter->request('POST', 'https://upload.twitter.com/1.1/media/upload.json', array('media' => $image_data)); \PVL\Debug::print_r($twitter->response['response']); $image_response = @json_decode($twitter->response['response'], true); if (isset($image_response['media_id_string'])) { $media_id = $image_response['media_id_string']; $twitter->request('POST', 'https://api.twitter.com/1.1/statuses/update.json', array('status' => $tweet, 'media_ids' => array($media_id))); \PVL\Debug::print_r($twitter->response['response']); } return true; } } $twitter->request('POST', 'https://api.twitter.com/1.1/statuses/update.json', array('status' => $tweet)); \PVL\Debug::print_r($twitter->response['response']); return true; }
/** * Submit a URL request with a specified cache lifetime. * * @param null $c_opts * @param int $cache_time * @return string */ public static function request($c_opts = null) { // Compose cURL configuration array. if (is_null($c_opts)) { $c_opts = array(); } elseif (!is_array($c_opts)) { $c_opts = array('url' => $c_opts); } $c_defaults = array('method' => 'GET', 'useragent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2) Gecko/20070219 Firefox/2.0.0.2', 'timeout' => 10); $c_opts = array_merge($c_defaults, $c_opts); Debug::log('cURL Outgoing Request: ' . $c_opts['url']); Debug::startTimer('Make cURL Request'); $postfields = false; if (!empty($c_opts['params'])) { if (strtoupper($c_opts['method']) == 'POST') { $postfields = $c_opts['params']; } else { $c_opts['url'] = $c_opts['url'] . '?' . http_build_query($c_opts['params']); } } // Start cURL request. $curl = curl_init($c_opts['url']); // Handle POST support. if (strtoupper($c_opts['method']) == 'POST') { curl_setopt($curl, CURLOPT_POST, true); } if (!empty($c_opts['referer'])) { curl_setopt($curl, CURLOPT_REFERER, $c_opts['referer']); } if ($postfields) { curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $c_opts['timeout']); curl_setopt($curl, CURLOPT_TIMEOUT, $c_opts['timeout']); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_USERAGENT, $c_opts['useragent']); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE); curl_setopt($curl, CURLOPT_MAXREDIRS, 3); // Custom DNS management. curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 600); // Set custom HTTP headers. if (!empty($c_opts['headers'])) { curl_setopt($curl, CURLOPT_HTTPHEADER, $c_opts['headers']); } $return_raw = Utilities::curl_exec_utf8($curl); // End cURL request. Debug::endTimer('Make cURL Request'); // Log more detailed information to screen about resolution times. $conn_info = curl_getinfo($curl); $important_conn_info = array('url', 'http_code', 'total_time', 'namelookup_time', 'connect_time', 'pretransfer_time', 'starttransfer_time', 'redirect_time'); $debug_conn_info = array(); foreach ($important_conn_info as $conn_param) { $debug_conn_info[$conn_param] = $conn_info[$conn_param]; } Debug::print_r($debug_conn_info); $error = curl_error($curl); if ($error) { Debug::log("Curl error: " . $error); } return trim($return_raw); }