mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-19 13:01:19 +00:00
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
This commit is contained in:
parent
384b6b27a3
commit
972bcbf65e
@ -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é.',
|
||||
|
@ -1,9 +1,9 @@
|
||||
.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']
|
||||
|
@ -144,7 +144,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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user