Loading app/Controllers/Analytics.php +9 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,15 @@ class Analytics extends Controller ) { helper('media'); podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize); $serviceName = isset($_GET['s']) ? $_GET['s'] : ''; podcast_hit( $podcastId, $episodeId, $bytesThreshold, $fileSize, $serviceName ); return redirect()->to(media_url(implode('/', $filename))); } } app/Controllers/Feed.php +23 −4 Original line number Diff line number Diff line Loading @@ -15,13 +15,32 @@ class Feed extends Controller { public function index($podcastName) { // The page cache is set to a decade so it is deleted manually upon podcast update $this->cachePage(DECADE); helper('rss'); $podcast = (new PodcastModel())->where('name', $podcastName)->first(); if (!$podcast) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); } return $this->response->setXML(get_rss_feed($podcast)); $service = null; try { $service = \Opawg\UserAgentsPhp\UserAgentsRSS::find( $_SERVER['HTTP_USER_AGENT'] ); } catch (\Exception $e) { // If things go wrong the show must go on and the user must be able to download the file log_message('critical', $e); } $cacheName = "podcast{$podcast->id}_feed" . ($service ? "_{$service['slug']}" : ''); if (!($found = cache($cacheName))) { $found = get_rss_feed( $podcast, $service ? '?s=' . urlencode($service['name']) : '' ); cache()->save($cacheName, $found, DECADE); } return $this->response->setXML($found); } } app/Database/Migrations/2020-06-08-140000_add_analytics_podcasts_by_player.php +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,10 @@ class AddAnalyticsPodcastsByPlayer extends Migration 'date' => [ 'type' => 'date', ], 'service' => [ 'type' => 'VARCHAR', 'constraint' => 128, ], 'app' => [ 'type' => 'VARCHAR', 'constraint' => 128, Loading @@ -51,6 +55,7 @@ class AddAnalyticsPodcastsByPlayer extends Migration $this->forge->addPrimaryKey([ 'podcast_id', 'date', 'service', 'app', 'device', 'os', Loading app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_stored_procedure.php +3 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ CREATE PROCEDURE `{$prefix}analytics_podcasts` ( IN `p_region_code` VARCHAR(3) CHARSET utf8mb4, IN `p_latitude` FLOAT, IN `p_longitude` FLOAT, IN `p_service` VARCHAR(128) CHARSET utf8mb4, IN `p_app` VARCHAR(128) CHARSET utf8mb4, IN `p_device` VARCHAR(32) CHARSET utf8mb4, IN `p_os` VARCHAR(32) CHARSET utf8mb4, Loading @@ -52,8 +53,8 @@ IF NOT `p_bot` THEN VALUES (p_podcast_id, p_country_code, p_region_code, p_latitude, p_longitude, DATE(NOW())) ON DUPLICATE KEY UPDATE `hits`=`hits`+1; END IF; INSERT INTO `{$prefix}analytics_podcasts_by_player`(`podcast_id`, `app`, `device`, `os`, `bot`, `date`) VALUES (p_podcast_id, p_app, p_device, p_os, p_bot, DATE(NOW())) INSERT INTO `{$prefix}analytics_podcasts_by_player`(`podcast_id`, `service`, `app`, `device`, `os`, `bot`, `date`) VALUES (p_podcast_id, p_service, p_app, p_device, p_os, p_bot, DATE(NOW())) ON DUPLICATE KEY UPDATE `hits`=`hits`+1; END EOD; Loading app/Helpers/analytics_helper.php +16 −13 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ function set_user_session_player() $userAgent = $_SERVER['HTTP_USER_AGENT']; try { $playerFound = \Podlibre\UserAgentsPhp\UserAgents::find($userAgent); $playerFound = \Opawg\UserAgentsPhp\UserAgents::find($userAgent); } catch (\Exception $e) { // If things go wrong the show must go on and the user must be able to download the file } Loading Loading @@ -227,6 +227,7 @@ function webpage_hit($podcast_id) * ✅ Castopod does not do pre-load * ✅ IP deny list https://github.com/client9/ipcat * ✅ User-agent Filtering https://github.com/opawg/user-agents * ✅ RSS User-agent https://github.com/opawg/podcast-rss-useragents * ✅ Ignores 2 bytes range "Range: 0-1" (performed by official Apple iOS Podcast app) * ✅ In case of partial content, adds up all requests to check >1mn was downloaded * ✅ Identifying Uniques is done with a combination of IP Address and User Agent Loading @@ -234,11 +235,17 @@ function webpage_hit($podcast_id) * @param int $episodeId The Episode ID * @param int $bytesThreshold The minimum total number of bytes that must be downloaded so that an episode is counted (>1mn) * @param int $fileSize The podcast complete file size * @param string $serviceName The name of the service that had fetched the RSS feed * * @return void */ function podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize) { function podcast_hit( $podcastId, $episodeId, $bytesThreshold, $fileSize, $serviceName ) { $session = \Config\Services::session(); $session->start(); Loading Loading @@ -328,22 +335,18 @@ function podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize) // We save the download count for this user until midnight: cache()->save($listenerHashId, $downloadsByUser, $midnightTTL); $app = $session->get('player')['app']; $device = $session->get('player')['device']; $os = $session->get('player')['os']; $bot = $session->get('player')['bot']; $db->query("CALL $procedureName(?,?,?,?,?,?,?,?,?,?,?);", [ $db->query("CALL $procedureName(?,?,?,?,?,?,?,?,?,?,?,?);", [ $podcastId, $episodeId, $session->get('location')['countryCode'], $session->get('location')['regionCode'], $session->get('location')['latitude'], $session->get('location')['longitude'], $app == null ? '' : $app, $device == null ? '' : $device, $os == null ? '' : $os, $bot == null ? 0 : $bot, $serviceName, $session->get('player')['app'], $session->get('player')['device'], $session->get('player')['os'], $session->get('player')['bot'], $newListener, ]); } Loading Loading
app/Controllers/Analytics.php +9 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,15 @@ class Analytics extends Controller ) { helper('media'); podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize); $serviceName = isset($_GET['s']) ? $_GET['s'] : ''; podcast_hit( $podcastId, $episodeId, $bytesThreshold, $fileSize, $serviceName ); return redirect()->to(media_url(implode('/', $filename))); } }
app/Controllers/Feed.php +23 −4 Original line number Diff line number Diff line Loading @@ -15,13 +15,32 @@ class Feed extends Controller { public function index($podcastName) { // The page cache is set to a decade so it is deleted manually upon podcast update $this->cachePage(DECADE); helper('rss'); $podcast = (new PodcastModel())->where('name', $podcastName)->first(); if (!$podcast) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); } return $this->response->setXML(get_rss_feed($podcast)); $service = null; try { $service = \Opawg\UserAgentsPhp\UserAgentsRSS::find( $_SERVER['HTTP_USER_AGENT'] ); } catch (\Exception $e) { // If things go wrong the show must go on and the user must be able to download the file log_message('critical', $e); } $cacheName = "podcast{$podcast->id}_feed" . ($service ? "_{$service['slug']}" : ''); if (!($found = cache($cacheName))) { $found = get_rss_feed( $podcast, $service ? '?s=' . urlencode($service['name']) : '' ); cache()->save($cacheName, $found, DECADE); } return $this->response->setXML($found); } }
app/Database/Migrations/2020-06-08-140000_add_analytics_podcasts_by_player.php +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,10 @@ class AddAnalyticsPodcastsByPlayer extends Migration 'date' => [ 'type' => 'date', ], 'service' => [ 'type' => 'VARCHAR', 'constraint' => 128, ], 'app' => [ 'type' => 'VARCHAR', 'constraint' => 128, Loading @@ -51,6 +55,7 @@ class AddAnalyticsPodcastsByPlayer extends Migration $this->forge->addPrimaryKey([ 'podcast_id', 'date', 'service', 'app', 'device', 'os', Loading
app/Database/Migrations/2020-06-11-210000_add_analytics_podcasts_stored_procedure.php +3 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ CREATE PROCEDURE `{$prefix}analytics_podcasts` ( IN `p_region_code` VARCHAR(3) CHARSET utf8mb4, IN `p_latitude` FLOAT, IN `p_longitude` FLOAT, IN `p_service` VARCHAR(128) CHARSET utf8mb4, IN `p_app` VARCHAR(128) CHARSET utf8mb4, IN `p_device` VARCHAR(32) CHARSET utf8mb4, IN `p_os` VARCHAR(32) CHARSET utf8mb4, Loading @@ -52,8 +53,8 @@ IF NOT `p_bot` THEN VALUES (p_podcast_id, p_country_code, p_region_code, p_latitude, p_longitude, DATE(NOW())) ON DUPLICATE KEY UPDATE `hits`=`hits`+1; END IF; INSERT INTO `{$prefix}analytics_podcasts_by_player`(`podcast_id`, `app`, `device`, `os`, `bot`, `date`) VALUES (p_podcast_id, p_app, p_device, p_os, p_bot, DATE(NOW())) INSERT INTO `{$prefix}analytics_podcasts_by_player`(`podcast_id`, `service`, `app`, `device`, `os`, `bot`, `date`) VALUES (p_podcast_id, p_service, p_app, p_device, p_os, p_bot, DATE(NOW())) ON DUPLICATE KEY UPDATE `hits`=`hits`+1; END EOD; Loading
app/Helpers/analytics_helper.php +16 −13 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ function set_user_session_player() $userAgent = $_SERVER['HTTP_USER_AGENT']; try { $playerFound = \Podlibre\UserAgentsPhp\UserAgents::find($userAgent); $playerFound = \Opawg\UserAgentsPhp\UserAgents::find($userAgent); } catch (\Exception $e) { // If things go wrong the show must go on and the user must be able to download the file } Loading Loading @@ -227,6 +227,7 @@ function webpage_hit($podcast_id) * ✅ Castopod does not do pre-load * ✅ IP deny list https://github.com/client9/ipcat * ✅ User-agent Filtering https://github.com/opawg/user-agents * ✅ RSS User-agent https://github.com/opawg/podcast-rss-useragents * ✅ Ignores 2 bytes range "Range: 0-1" (performed by official Apple iOS Podcast app) * ✅ In case of partial content, adds up all requests to check >1mn was downloaded * ✅ Identifying Uniques is done with a combination of IP Address and User Agent Loading @@ -234,11 +235,17 @@ function webpage_hit($podcast_id) * @param int $episodeId The Episode ID * @param int $bytesThreshold The minimum total number of bytes that must be downloaded so that an episode is counted (>1mn) * @param int $fileSize The podcast complete file size * @param string $serviceName The name of the service that had fetched the RSS feed * * @return void */ function podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize) { function podcast_hit( $podcastId, $episodeId, $bytesThreshold, $fileSize, $serviceName ) { $session = \Config\Services::session(); $session->start(); Loading Loading @@ -328,22 +335,18 @@ function podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize) // We save the download count for this user until midnight: cache()->save($listenerHashId, $downloadsByUser, $midnightTTL); $app = $session->get('player')['app']; $device = $session->get('player')['device']; $os = $session->get('player')['os']; $bot = $session->get('player')['bot']; $db->query("CALL $procedureName(?,?,?,?,?,?,?,?,?,?,?);", [ $db->query("CALL $procedureName(?,?,?,?,?,?,?,?,?,?,?,?);", [ $podcastId, $episodeId, $session->get('location')['countryCode'], $session->get('location')['regionCode'], $session->get('location')['latitude'], $session->get('location')['longitude'], $app == null ? '' : $app, $device == null ? '' : $device, $os == null ? '' : $os, $bot == null ? 0 : $bot, $serviceName, $session->get('player')['app'], $session->get('player')['device'], $session->get('player')['os'], $session->get('player')['bot'], $newListener, ]); } Loading