2021-04-14 15:58:40 +00:00
|
|
|
|
<?php
|
|
|
|
|
|
2021-06-08 09:52:11 +00:00
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
2022-02-19 16:06:11 +00:00
|
|
|
|
* @copyright 2020 Ad Aures
|
2021-04-14 15:58:40 +00:00
|
|
|
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
|
|
|
|
* @link https://castopod.org/
|
|
|
|
|
*/
|
|
|
|
|
|
2022-02-24 14:48:17 +00:00
|
|
|
|
use AdAures\Ipcat\IpDb;
|
|
|
|
|
use Config\Services;
|
|
|
|
|
use GeoIp2\Database\Reader;
|
|
|
|
|
use Opawg\UserAgentsPhp\UserAgents;
|
2021-05-19 16:35:13 +00:00
|
|
|
|
use WhichBrowser\Parser;
|
2021-04-14 15:58:40 +00:00
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('base64_url_encode')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Encode Base64 for URLs
|
|
|
|
|
*/
|
2021-05-14 17:59:35 +00:00
|
|
|
|
function base64_url_encode(string $input): string
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
|
|
|
|
return strtr(base64_encode($input), '+/=', '._-');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('base64_url_decode')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Decode Base64 from URL
|
|
|
|
|
*/
|
2021-05-14 17:59:35 +00:00
|
|
|
|
function base64_url_decode(string $input): string
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
2021-05-19 16:35:13 +00:00
|
|
|
|
return base64_decode(strtr($input, '._-', '+/='), true);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-24 15:28:17 +00:00
|
|
|
|
if (! function_exists('client_ip')) {
|
|
|
|
|
/**
|
|
|
|
|
* Get the client IP, depending on available headers
|
|
|
|
|
*/
|
|
|
|
|
function client_ip(): string
|
|
|
|
|
{
|
|
|
|
|
if (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
|
|
|
|
return $_SERVER['HTTP_X_FORWARDED_FOR'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $_SERVER['REMOTE_ADDR'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('set_user_session_deny_list_ip')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set user country in session variable, for analytic purposes
|
|
|
|
|
*/
|
2021-05-06 14:00:48 +00:00
|
|
|
|
function set_user_session_deny_list_ip(): void
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$session = Services::session();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->start();
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! $session->has('denyListIp')) {
|
2023-02-24 15:28:17 +00:00
|
|
|
|
$session->set('denyListIp', IpDb::find(client_ip()) !== null);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('set_user_session_location')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set user country in session variable, for analytic purposes
|
|
|
|
|
*/
|
2021-05-06 14:00:48 +00:00
|
|
|
|
function set_user_session_location(): void
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$session = Services::session();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->start();
|
|
|
|
|
|
|
|
|
|
$location = [
|
|
|
|
|
'countryCode' => 'N/A',
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'regionCode' => 'N/A',
|
|
|
|
|
'latitude' => null,
|
|
|
|
|
'longitude' => null,
|
2021-04-14 15:58:40 +00:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Finds location:
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! $session->has('location')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
try {
|
2021-06-08 09:52:11 +00:00
|
|
|
|
$cityReader = new Reader(WRITEPATH . 'uploads/GeoLite2-City/GeoLite2-City.mmdb');
|
2023-02-24 15:28:17 +00:00
|
|
|
|
$city = $cityReader->city(client_ip());
|
2021-04-14 15:58:40 +00:00
|
|
|
|
|
|
|
|
|
$location = [
|
2021-05-18 17:16:36 +00:00
|
|
|
|
'countryCode' => $city->country->isoCode === null
|
2021-04-14 15:58:40 +00:00
|
|
|
|
? 'N/A'
|
|
|
|
|
: $city->country->isoCode,
|
2021-05-18 17:16:36 +00:00
|
|
|
|
'regionCode' => $city->subdivisions[0]->isoCode === null
|
2021-04-14 15:58:40 +00:00
|
|
|
|
? 'N/A'
|
|
|
|
|
: $city->subdivisions[0]->isoCode,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'latitude' => round($city->location->latitude, 3),
|
2021-04-14 15:58:40 +00:00
|
|
|
|
'longitude' => round($city->location->longitude, 3),
|
|
|
|
|
];
|
|
|
|
|
// If things go wrong the show must go on and the user must be able to download the file
|
2021-05-14 17:59:35 +00:00
|
|
|
|
} catch (Exception) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->set('location', $location);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('set_user_session_player')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set user player in session variable, for analytic purposes
|
|
|
|
|
*/
|
2021-05-06 14:00:48 +00:00
|
|
|
|
function set_user_session_player(): void
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$session = Services::session();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->start();
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! $session->has('player')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$playerFound = null;
|
|
|
|
|
$userAgent = $_SERVER['HTTP_USER_AGENT'];
|
|
|
|
|
|
|
|
|
|
try {
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$playerFound = UserAgents::find($userAgent);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// If things go wrong the show must go on and the user must be able to download the file
|
2021-05-14 17:59:35 +00:00
|
|
|
|
} catch (Exception) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
if ($playerFound) {
|
|
|
|
|
$session->set('player', $playerFound);
|
|
|
|
|
} else {
|
|
|
|
|
$session->set('player', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'app' => '- unknown -',
|
2021-04-14 15:58:40 +00:00
|
|
|
|
'device' => '',
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'os' => '',
|
|
|
|
|
'bot' => 0,
|
2021-04-14 15:58:40 +00:00
|
|
|
|
]);
|
|
|
|
|
// Add to unknown list
|
|
|
|
|
try {
|
2021-06-11 08:03:54 +00:00
|
|
|
|
$db = db_connect();
|
2021-06-08 09:52:11 +00:00
|
|
|
|
$procedureNameAnalyticsUnknownUseragents = $db->prefixTable('analytics_unknown_useragents');
|
|
|
|
|
$db->query("CALL {$procedureNameAnalyticsUnknownUseragents}(?)", [$userAgent]);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// If things go wrong the show must go on and the user must be able to download the file
|
2021-05-14 17:59:35 +00:00
|
|
|
|
} catch (Exception) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('set_user_session_browser')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set user browser in session variable, for analytic purposes
|
2021-05-19 16:35:13 +00:00
|
|
|
|
*
|
|
|
|
|
* FIXME: session key should be null instead of "Could not get browser name"
|
2021-04-14 15:58:40 +00:00
|
|
|
|
*/
|
2021-05-06 14:00:48 +00:00
|
|
|
|
function set_user_session_browser(): void
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$session = Services::session();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->start();
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! $session->has('browser')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$browserName = '- Other -';
|
|
|
|
|
try {
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$whichbrowser = new Parser(getallheaders());
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$browserName = $whichbrowser->browser->name;
|
2021-05-14 17:59:35 +00:00
|
|
|
|
} catch (Exception) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$browserName = '- Could not get browser name -';
|
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if ($browserName === '') {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$browserName = '- Could not get browser name -';
|
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->set('browser', $browserName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('set_user_session_referer')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set user referer in session variable, for analytic purposes
|
|
|
|
|
*/
|
2021-05-06 14:00:48 +00:00
|
|
|
|
function set_user_session_referer(): void
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$session = Services::session();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->start();
|
|
|
|
|
|
|
|
|
|
$newreferer = isset($_SERVER['HTTP_REFERER'])
|
|
|
|
|
? $_SERVER['HTTP_REFERER']
|
|
|
|
|
: '- Direct -';
|
|
|
|
|
$newreferer =
|
2022-10-17 14:17:50 +00:00
|
|
|
|
parse_url((string) $newreferer, PHP_URL_HOST) ===
|
2021-04-14 15:58:40 +00:00
|
|
|
|
parse_url(current_url(false), PHP_URL_HOST)
|
|
|
|
|
? '- Direct -'
|
|
|
|
|
: $newreferer;
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! $session->has('referer') || $newreferer !== '- Direct -') {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->set('referer', $newreferer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('set_user_session_entry_page')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set user entry page in session variable, for analytic purposes
|
|
|
|
|
*/
|
2021-05-06 14:00:48 +00:00
|
|
|
|
function set_user_session_entry_page(): void
|
2021-04-14 15:58:40 +00:00
|
|
|
|
{
|
2021-05-06 14:00:48 +00:00
|
|
|
|
$session = Services::session();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->start();
|
|
|
|
|
|
|
|
|
|
$entryPage = $_SERVER['REQUEST_URI'];
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! $session->has('entryPage')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->set('entryPage', $entryPage);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! function_exists('podcast_hit')) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
/**
|
2021-05-19 16:35:13 +00:00
|
|
|
|
* Counting podcast episode downloads for analytic purposes ✅ No IP address is ever stored on the server. ✅ Only
|
|
|
|
|
* aggregate data is stored in the database. We follow IAB Podcast Measurement Technical Guidelines Version 2.0:
|
|
|
|
|
* https://iabtechlab.com/standards/podcast-measurement-guidelines/
|
2022-03-30 16:09:06 +00:00
|
|
|
|
* https://iabtechlab.com/wp-content/uploads/2017/12/Podcast_Measurement_v2-Dec-20-2017.pdf ✅ 24-hour window ✅
|
|
|
|
|
* 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
|
2021-05-19 16:35:13 +00:00
|
|
|
|
*
|
2021-04-14 15:58:40 +00:00
|
|
|
|
* @param integer $podcastId The podcast ID
|
|
|
|
|
* @param integer $episodeId The Episode ID
|
|
|
|
|
* @param integer $bytesThreshold The minimum total number of bytes that must be downloaded so that an episode is counted (>1mn)
|
|
|
|
|
* @param integer $fileSize The podcast complete file size
|
2021-06-11 14:51:14 +00:00
|
|
|
|
* @param double $duration The episode duration in seconds
|
2021-05-14 17:59:35 +00:00
|
|
|
|
* @param int $publicationTime The episode's publication time as a UNIX timestamp
|
2021-04-14 15:58:40 +00:00
|
|
|
|
* @param string $serviceName The name of the service that had fetched the RSS feed
|
|
|
|
|
*/
|
|
|
|
|
function podcast_hit(
|
2021-05-06 14:00:48 +00:00
|
|
|
|
int $podcastId,
|
|
|
|
|
int $episodeId,
|
|
|
|
|
int $bytesThreshold,
|
|
|
|
|
int $fileSize,
|
2021-06-11 14:51:14 +00:00
|
|
|
|
float $duration,
|
2021-05-14 17:59:35 +00:00
|
|
|
|
int $publicationTime,
|
2022-09-28 15:02:09 +00:00
|
|
|
|
string $serviceName,
|
|
|
|
|
?int $subscriptionId,
|
2021-05-06 14:00:48 +00:00
|
|
|
|
): void {
|
|
|
|
|
$session = Services::session();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$session->start();
|
|
|
|
|
|
2023-02-24 15:28:17 +00:00
|
|
|
|
$clientIp = client_ip();
|
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// We try to count (but if things went wrong the show should go on and the user should be able to download the file):
|
|
|
|
|
try {
|
|
|
|
|
// If the user IP is denied it's probably a bot:
|
|
|
|
|
if ($session->get('denyListIp')) {
|
|
|
|
|
$session->get('player')['bot'] = true;
|
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
//We get the HTTP header field `Range`:
|
|
|
|
|
$httpRange = isset($_SERVER['HTTP_RANGE'])
|
|
|
|
|
? $_SERVER['HTTP_RANGE']
|
|
|
|
|
: null;
|
|
|
|
|
|
2022-03-30 16:09:06 +00:00
|
|
|
|
$salt = config('Analytics')
|
|
|
|
|
->salt;
|
|
|
|
|
// We create a sha1 hash for this Salt+Current_Date+IP_Address+User_Agent+Episode_ID (used to count only once multiple episode downloads):
|
|
|
|
|
$episodeListenerHashId =
|
|
|
|
|
'Analytics_Episode_' .
|
|
|
|
|
sha1(
|
|
|
|
|
$salt . '_' . date(
|
|
|
|
|
'Y-m-d'
|
2023-02-24 15:28:17 +00:00
|
|
|
|
) . '_' . $clientIp . '_' . $_SERVER['HTTP_USER_AGENT'] . '_' . $episodeId
|
2022-03-30 16:09:06 +00:00
|
|
|
|
);
|
2022-04-01 13:29:25 +00:00
|
|
|
|
// The cache expires at midnight:
|
|
|
|
|
$secondsToMidnight = strtotime('tomorrow') - time();
|
2022-03-30 16:09:06 +00:00
|
|
|
|
$downloadedBytes = cache($episodeListenerHashId);
|
2022-04-01 13:29:25 +00:00
|
|
|
|
if ($downloadedBytes === null) {
|
|
|
|
|
// If it was never downloaded that means that zero bytes were downloaded:
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$downloadedBytes = 0;
|
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// If the number of downloaded bytes was previously below the 1mn threshold we go on:
|
|
|
|
|
// (Otherwise it means that this was already counted, therefore we don't do anything)
|
|
|
|
|
if ($downloadedBytes < $bytesThreshold) {
|
|
|
|
|
// If HTTP_RANGE is null we are downloading the complete file:
|
2021-05-19 16:35:13 +00:00
|
|
|
|
if (! $httpRange) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$downloadedBytes = $fileSize;
|
2021-05-19 16:35:13 +00:00
|
|
|
|
} elseif ($httpRange !== 'bytes=0-1') {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// [0-1] bytes range requests are used (by Apple) to check that file exists and that 206 partial content is working.
|
2021-05-06 14:00:48 +00:00
|
|
|
|
// We don't count these requests.
|
|
|
|
|
// We calculate how many bytes are being downloaded based on HTTP_RANGE values:
|
2022-10-17 14:17:50 +00:00
|
|
|
|
$ranges = explode(',', substr((string) $httpRange, 6));
|
2021-05-06 14:00:48 +00:00
|
|
|
|
foreach ($ranges as $range) {
|
|
|
|
|
$parts = explode('-', $range);
|
2021-05-18 17:16:36 +00:00
|
|
|
|
$downloadedBytes += array_key_exists(1, $parts)
|
2021-05-06 14:00:48 +00:00
|
|
|
|
? $fileSize
|
2021-05-12 14:00:25 +00:00
|
|
|
|
: (int) $parts[1] -
|
2021-05-18 17:16:36 +00:00
|
|
|
|
(array_key_exists(0, $parts) ? 0 : (int) $parts[0]);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// We save the number of downloaded bytes for this user and this episode:
|
2021-05-19 16:35:13 +00:00
|
|
|
|
cache()
|
2022-04-01 13:29:25 +00:00
|
|
|
|
->save($episodeListenerHashId, $downloadedBytes, $secondsToMidnight);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
|
|
|
|
|
// If more that 1mn was downloaded, that's a hit, we send that to the database:
|
|
|
|
|
if ($downloadedBytes >= $bytesThreshold) {
|
2021-06-11 08:03:54 +00:00
|
|
|
|
$db = db_connect();
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$procedureName = $db->prefixTable('analytics_podcasts');
|
|
|
|
|
|
2021-05-14 17:59:35 +00:00
|
|
|
|
$age = intdiv(time() - $publicationTime, 86400);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
|
2022-03-30 16:09:06 +00:00
|
|
|
|
// We create a sha1 hash for this Salt+Current_Date+IP_Address+User_Agent+Podcast_ID (used to count unique listeners):
|
|
|
|
|
$podcastListenerHashId =
|
|
|
|
|
'Analytics_Podcast_' .
|
|
|
|
|
sha1(
|
|
|
|
|
$salt . '_' . date(
|
|
|
|
|
'Y-m-d'
|
2023-02-24 15:28:17 +00:00
|
|
|
|
) . '_' . $clientIp . '_' . $_SERVER['HTTP_USER_AGENT'] . '_' . $podcastId
|
2022-03-30 16:09:06 +00:00
|
|
|
|
);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
$newListener = 1;
|
|
|
|
|
// Has this listener already downloaded an episode today:
|
2022-03-30 16:09:06 +00:00
|
|
|
|
$downloadsByUser = cache($podcastListenerHashId);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// We add one download
|
|
|
|
|
if ($downloadsByUser) {
|
|
|
|
|
$newListener = 0;
|
2021-05-06 14:00:48 +00:00
|
|
|
|
++$downloadsByUser;
|
2021-04-14 15:58:40 +00:00
|
|
|
|
} else {
|
|
|
|
|
$downloadsByUser = 1;
|
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// We save the download count for this user until midnight:
|
2021-05-19 16:35:13 +00:00
|
|
|
|
cache()
|
2022-04-01 13:29:25 +00:00
|
|
|
|
->save($podcastListenerHashId, $downloadsByUser, $secondsToMidnight);
|
2021-04-14 15:58:40 +00:00
|
|
|
|
|
|
|
|
|
$db->query(
|
2022-09-28 15:02:09 +00:00
|
|
|
|
"CALL {$procedureName}(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);",
|
2021-04-14 15:58:40 +00:00
|
|
|
|
[
|
|
|
|
|
$podcastId,
|
|
|
|
|
$episodeId,
|
|
|
|
|
$session->get('location')['countryCode'],
|
|
|
|
|
$session->get('location')['regionCode'],
|
|
|
|
|
$session->get('location')['latitude'],
|
|
|
|
|
$session->get('location')['longitude'],
|
|
|
|
|
$serviceName,
|
|
|
|
|
$session->get('player')['app'],
|
|
|
|
|
$session->get('player')['device'],
|
|
|
|
|
$session->get('player')['os'],
|
|
|
|
|
$session->get('player')['bot'],
|
|
|
|
|
$fileSize,
|
|
|
|
|
$duration,
|
|
|
|
|
$age,
|
|
|
|
|
$newListener,
|
2022-09-28 15:02:09 +00:00
|
|
|
|
$subscriptionId,
|
2021-04-14 15:58:40 +00:00
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-06 14:00:48 +00:00
|
|
|
|
} catch (Exception $exception) {
|
2021-04-14 15:58:40 +00:00
|
|
|
|
// If things go wrong the show must go on and the user must be able to download the file
|
2021-06-08 09:52:11 +00:00
|
|
|
|
log_message('critical', $exception->getMessage());
|
2021-04-14 15:58:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|