Commit 972bcbf6 authored by Benjamin Bellamy's avatar Benjamin Bellamy 💬
Browse files

feat: add CDN url

feat: rename ?s to ?_from to match podcastindex recommendation
feat: adust map height
feat: display pie chart on 1 column for small and medium screens
feat: handle empty rss user agent
fix: correct bug when importing episode with empty image
fix: add service to FakePodcastsAnalyticsSeeder, resize pie charts so that all lines fit
fix: set page title to ->title when it exists
fix: replace %20 with +

closes #37
parent 384b6b27
Pipeline #362 passed with stage
in 4 minutes and 45 seconds
......@@ -12,6 +12,7 @@
# Instance configuration
app.baseURL="https://YOUR_DOMAIN_NAME/"
app.mediaBaseURL="https://YOUR_MEDIA_DOMAIN_NAME/"
app.adminGateway="cp-admin"
app.authGateway="cp-auth"
......@@ -19,7 +20,7 @@ app.authGateway="cp-auth"
database.default.hostname="localhost"
database.default.database="castopod"
database.default.username="root"
database.default.password="root"
database.default.password="****"
database.default.DBPrefix="cp_"
# Cache configuration (advanced)
......
......@@ -20,7 +20,7 @@ PHP Dependencies:
([ BSD-3-Clause License ](https://github.com/vlucas/phpdotenv/blob/master/LICENSE))
- [HTML To Markdown for PHP](https://github.com/thephpleague/html-to-markdown)
([MIT License](https://github.com/thephpleague/html-to-markdown/blob/master/LICENSE))
- [podlibre/user-agents-php](https://github.com/podlibre/user-agents-php)
- [opawg/user-agents-php](https://github.com/opawg/user-agents-php)
([MIT License](https://github.com/podlibre/user-agents-php/blob/main/LICENSE))
- [podlibre/ipcat](https://github.com/podlibre/ipcat)
([GNU General Public License v3.0](https://github.com/podlibre/ipcat/blob/master/LICENSE))
......@@ -47,6 +47,9 @@ Other:
- [OPAWG/User agent list](https://github.com/opawg/user-agents)
([by Open Podcast Analytics Working Group](https://github.com/opawg))
([MIT license](https://github.com/opawg/user-agents/blob/master/LICENSE))
- [OPAWG/podcast-rss-useragents](https://github.com/opawg/podcast-rss-useragents)
([by Open Podcast Analytics Working Group](https://github.com/opawg))
([MIT license](https://github.com/opawg/podcast-rss-useragents/blob/master/LICENSE))
- [client9/ipcat](https://github.com/client9/ipcat)
([GNU General Public License v3.0](https://github.com/client9/ipcat/blob/master/LICENSE))
- [GeoLite2 City](https://dev.maxmind.com/geoip/geoip2/geolite2/)
......
......@@ -22,7 +22,20 @@ class App extends BaseConfig
| environments.
|
*/
public $baseURL = 'http://localhost:8080/';
public $baseURL = 'http://127.0.0.1:8080/';
/*
|--------------------------------------------------------------------------
| Media Base URL
|--------------------------------------------------------------------------
|
| URL to your media root. Typically this will be your base URL,
| WITH a trailing slash:
|
| http://cdn.example.com/
|
*/
public $mediaBaseURL = 'http://127.0.0.2:8080/';
/*
|--------------------------------------------------------------------------
......
......@@ -361,9 +361,10 @@ class Podcast extends BaseController
? $nsItunes->subtitle . "\n" . $nsItunes->summary
: $item->description)
),
'image' => empty($nsItunes->image->attributes())
? null
: download_file($nsItunes->image->attributes()),
'image' =>
!$nsItunes->image || empty($nsItunes->image->attributes())
? null
: download_file($nsItunes->image->attributes()),
'parental_advisory' => empty($nsItunes->explicit)
? null
: (in_array($nsItunes->explicit, ['yes', 'true'])
......
......@@ -55,7 +55,7 @@ class Analytics extends Controller
) {
helper('media');
$serviceName = isset($_GET['s']) ? $_GET['s'] : '';
$serviceName = isset($_GET['_from']) ? $_GET['_from'] : '';
podcast_hit(
$podcastId,
......@@ -64,6 +64,6 @@ class Analytics extends Controller
$fileSize,
$serviceName
);
return redirect()->to(media_url(implode('/', $filename)));
return redirect()->to(media_base_url($filename));
}
}
......@@ -38,10 +38,7 @@ class Feed extends Controller
($service ? "_{$service['slug']}" : '');
if (!($found = cache($cacheName))) {
$found = get_rss_feed(
$podcast,
$service ? '?s=' . urlencode($service['name']) : ''
);
$found = get_rss_feed($podcast, $service ? $service['name'] : '');
// The page cache is set to expire after next episode publication or a decade by default so it is deleted manually upon podcast update
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
......
......@@ -150,6 +150,7 @@ class Install extends Controller
{
$rules = [
'hostname' => 'required|validate_url',
'media_base_url' => 'permit_empty|validate_url',
'admin_gateway' => 'required',
'auth_gateway' => 'required|differs[admin_gateway]',
];
......@@ -165,8 +166,12 @@ class Install extends Controller
}
$baseUrl = $this->request->getPost('hostname');
$mediaBaseUrl = $this->request->getPost('media_base_url');
self::writeEnv([
'app.baseURL' => $baseUrl,
'app.mediaBaseURL' => empty($mediaBaseUrl)
? $baseUrl
: $mediaBaseUrl,
'app.adminGateway' => $this->request->getPost('admin_gateway'),
'app.authGateway' => $this->request->getPost('auth_gateway'),
]);
......
......@@ -28,6 +28,13 @@ class FakePodcastsAnalyticsSeeder extends Seeder
true
);
$jsonRSSUserAgents = json_decode(
file_get_contents(
'https://raw.githubusercontent.com/opawg/podcast-rss-useragents/master/src/rss-ua.json'
),
true
);
if ($podcast) {
$firstEpisode = (new EpisodeModel())
->selectMin('published_at')
......@@ -67,6 +74,10 @@ class FakePodcastsAnalyticsSeeder extends Seeder
$jsonUserAgents[
rand(1, count($jsonUserAgents) - 1)
];
$service =
$jsonRSSUserAgents[
rand(1, count($jsonRSSUserAgents) - 1)
]['name'];
$app = isset($player['app']) ? $player['app'] : '';
$device = isset($player['device'])
? $player['device']
......@@ -132,6 +143,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder
$analytics_podcasts_by_player[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'service'=> $service,
'app' => $app,
'device' => $device,
'os' => $os,
......
......@@ -45,6 +45,11 @@ class Episode extends Entity
*/
protected $enclosure_url;
/**
* @var string
*/
protected $enclosure_web_url;
/**
* @var string
*/
......@@ -194,6 +199,11 @@ class Episode extends Entity
);
}
public function getWebEnclosureUrl()
{
return $this->getEnclosureUrl() . '?_from=-+Website+-';
}
public function getLink()
{
return base_url(
......
......@@ -74,3 +74,18 @@ function media_url($uri = '', string $protocol = null): string
{
return base_url(config('App')->mediaRoot . '/' . $uri, $protocol);
}
function media_base_url($uri = '')
{
// convert segment array to string
if (is_array($uri)) {
$uri = implode('/', $uri);
}
$uri = trim($uri, '/');
return rtrim(config('App')->mediaBaseURL, '/') .
'/' .
config('App')->mediaRoot .
'/' .
$uri;
}
......@@ -103,7 +103,11 @@ function get_rss_feed($podcast, $serviceName = '')
$item->addChild('title', $episode->title);
$enclosure = $item->addChild('enclosure');
$enclosure->addAttribute('url', $episode->enclosure_url . $serviceName);
$enclosure->addAttribute(
'url',
$episode->enclosure_url .
(empty($serviceName) ? '' : '?_from=' . urlencode($serviceName))
);
$enclosure->addAttribute('length', $episode->enclosure_filesize);
$enclosure->addAttribute('type', $episode->enclosure_mimetype);
......
......@@ -13,6 +13,9 @@ return [
'form' => [
'instance_config' => 'Instance configuration',
'hostname' => 'Hostname',
'media_base_url' => 'Media base URL',
'media_base_url_hint' =>
'If you use a CDN and/or an external analytics service, you may set them here.',
'admin_gateway' => 'Admin gateway',
'admin_gateway_hint' =>
'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.',
......
......@@ -13,6 +13,9 @@ return [
'form' => [
'instance_config' => 'Paramètres de l’instance',
'hostname' => 'Nom d’hôte',
'media_base_url' => 'Adresse racine des médias',
'media_base_url_hint' =>
'Si vous utilisez un CDN et/ou un service de mesure d’audience externe, vous pouvez les définir ici.',
'admin_gateway' => 'Adresse d’administration',
'admin_gateway_hint' =>
'Le chemin pour accéder à l’administration (par exemple https://example.com/cp-admin). Il est défini par défaut à cp-admin, nous vous recommandons de le changer par mesure de sécurité.',
......
.chart-map {
height: 800px;
height: 600px;
border: solid 10px #eee;
}
.chart-pie {
height: 400px;
height: 450px;
width: 100%;
border: solid 1px #eee;
}
......
......@@ -14,7 +14,9 @@
<body class="flex flex-col min-h-screen mx-auto">
<header class="border-b">
<div class="container flex items-center justify-between px-2 py-4 mx-auto">
<a href="<?= route_to('home') ?>" class="text-2xl">Castopod</a>
<a href="<?= route_to('home') ?>" class="text-2xl"><?= isset($page)
? $page->title
: 'Castopod' ?></a>
</div>
</header>
<main class="container flex-1 px-4 py-10 mx-auto">
......
......@@ -10,7 +10,7 @@
<?= $this->section('content') ?>
<div class="grid grid-cols-2 divide-x">
<div class="lg:divide-x lg:grid lg:grid-cols-2">
<div class="mb-12 mr-6 text-center">
<h2><?= lang('Charts.by_country_weekly') ?></h2>
<div class="chart-pie" id="by-country-pie" data-chart-type="pie-chart" data-chart-url="<?= route_to(
......
......@@ -10,7 +10,7 @@
<?= $this->section('content') ?>
<div class="grid grid-cols-2 divide-x">
<div class="lg:divide-x lg:grid lg:grid-cols-2">
<div class="mb-12 mr-6 text-center">
<h2><?= lang('Charts.by_player_weekly') ?></h2>
<div class="chart-pie" id="by-app-weekly-pie" data-chart-type="pie-chart" data-chart-url="<?= route_to(
......
......@@ -10,7 +10,7 @@
<?= $this->section('content') ?>
<div class="grid grid-cols-2 divide-x">
<div class="lg:divide-x lg:grid lg:grid-cols-2">
<div class="mb-12 mr-6 text-center">
<h2><?= lang('Charts.by_domain_weekly') ?></h2>
......
......@@ -96,7 +96,7 @@
</time>
</div>
<audio controls preload="none" class="w-full mt-auto">
<source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
<source src="<?= $episode->enclosure_web_url ?>" type="<?= $episode->enclosure_type ?>">
Your browser does not support the audio tag.
</audio>
</div>
......
......@@ -22,6 +22,21 @@
'required' => 'required',
]) ?>
<?= form_label(
lang('Install.form.media_base_url'),
'media_base_url',
[],
lang('Install.form.media_base_url_hint'),
true
) ?>
<?= form_input([
'id' => 'media_base_url',
'name' => 'media_base_url',
'class' => 'form-input mb-4',
'value' => old('media_base_url', ''),
]) ?>
<?= form_label(
lang('Install.form.admin_gateway'),
'admin_gateway',
......@@ -51,7 +66,12 @@
]) ?>
<?= button(
lang('Install.form.next') . icon('arrow-right', 'ml-2'),
lang('Install.form.next') .
icon(
'arrow-right',
'ml-2'
),
null,
['variant' => 'primary'],
['type' => 'submit', 'class' => 'self-end']
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment