diff --git a/app/Controllers/Admin/PodcastController.php b/app/Controllers/Admin/PodcastController.php index 0fe70a48bbe3d91c67cecaf1619d8f9ac1695d10..5583213b96b691c2c85b97849ae8fc3d17714472 100644 --- a/app/Controllers/Admin/PodcastController.php +++ b/app/Controllers/Admin/PodcastController.php @@ -192,6 +192,7 @@ class PodcastController extends BaseController } $podcast = new Podcast([ + 'guid' => podcast_uuid(url_to('podcast_feed', $this->request->getPost('name'))), 'title' => $this->request->getPost('title'), 'name' => $this->request->getPost('name'), 'description_markdown' => $this->request->getPost('description'), diff --git a/app/Controllers/Admin/PodcastImportController.php b/app/Controllers/Admin/PodcastImportController.php index fbc0cca288ae9b10708aad04341145345b313d2b..2125d0972df22b0e7016f4fab868301fbc4ceaaa 100644 --- a/app/Controllers/Admin/PodcastImportController.php +++ b/app/Controllers/Admin/PodcastImportController.php @@ -128,11 +128,17 @@ class PodcastImportController extends BaseController (string) $nsPodcast->location->attributes()['osm'], ); } + if (property_exists($nsPodcast, 'guid') && $nsPodcast->guid !== null) { + $guid = (string) $nsPodcast->guid; + } else { + $guid = podcast_uuid(url_to('podcast_feed', $this->request->getPost('name'))); + } $podcast = new Podcast([ + 'guid' => $guid, 'name' => $this->request->getPost('name'), 'imported_feed_url' => $this->request->getPost('imported_feed_url'), - 'new_feed_url' => base_url(route_to('podcast_feed', $this->request->getPost('name'))), + 'new_feed_url' => url_to('podcast_feed', $this->request->getPost('name')), 'title' => (string) $feed->channel[0]->title, 'description_markdown' => $converter->convert($channelDescriptionHtml), 'description_html' => $channelDescriptionHtml, diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php index b04c92667a82de5f1baddf01b4e7a7bbb3e36681..f330d0841c8fbdb2a655c3312c7997848501a68d 100644 --- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php +++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php @@ -24,6 +24,10 @@ class AddPodcasts extends Migration 'unsigned' => true, 'auto_increment' => true, ], + 'guid' => [ + 'type' => 'CHAR', + 'constraint' => 36, + ], 'actor_id' => [ 'type' => 'INT', 'unsigned' => true, @@ -190,6 +194,7 @@ class AddPodcasts extends Migration $this->forge->addPrimaryKey('id'); // TODO: remove name in favor of username from actor $this->forge->addUniqueKey('name'); + $this->forge->addUniqueKey('guid'); $this->forge->addUniqueKey('actor_id'); $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE'); $this->forge->addForeignKey('category_id', 'categories', 'id'); diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index 20dd2840890ec9939e3d17ff404ecf9c87dc972c..6ed3b702a1c9aa5b53e6ffecee6891840bd25e1d 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -23,6 +23,7 @@ use RuntimeException; /** * @property int $id + * @property string $guid * @property int $actor_id * @property Actor|null $actor * @property string $name @@ -137,6 +138,7 @@ class Podcast extends Entity */ protected $casts = [ 'id' => 'integer', + 'guid' => 'string', 'actor_id' => 'integer', 'name' => 'string', 'title' => 'string', diff --git a/app/Helpers/misc_helper.php b/app/Helpers/misc_helper.php index 68404ba10418f5fd32e253ca4866fdf6dab12de1..212b8271ee331fbc8cd532d52e763dd371fbb9f6 100644 --- a/app/Helpers/misc_helper.php +++ b/app/Helpers/misc_helper.php @@ -148,4 +148,18 @@ if (! function_exists('format_duration')) { } } +if (! function_exists('podcast_uuid')) { + /** + * Generate UUIDv5 for podcast. For more information, see + * https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#guid + */ + function podcast_uuid(string $feedUrl): string + { + $uuid = service('uuid'); + // 'ead4c236-bf58-58c6-a2c6-a6b28d128cb6' is the uuid of the podcast namespace + return $uuid->uuid5('ead4c236-bf58-58c6-a2c6-a6b28d128cb6', $feedUrl) + ->toString(); + } +} + //-------------------------------------------------------------------- diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php index eeb24254da1a78cd5396439e84d26a2155e4221e..10079326600cc84e1de5e65a55c098b58e996f33 100644 --- a/app/Helpers/rss_helper.php +++ b/app/Helpers/rss_helper.php @@ -50,6 +50,7 @@ if (! function_exists('get_rss_feed')) { $channel->addChild('generator', 'Castopod Host - https://castopod.org/'); $channel->addChild('docs', 'https://cyber.harvard.edu/rss/rss.html'); + $channel->addChild('guid', $podcast->guid, $podcastNamespace); $channel->addChild('title', $podcast->title); $channel->addChildWithCDATA('description', $podcast->description_html); diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index 1b20c1feecc2f79f3aed6eaebc262bd9cb145f10..739593e73af6405449fee6cbeaf92bea70ca3ddf 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -33,6 +33,7 @@ class PodcastModel extends Model */ protected $allowedFields = [ 'id', + 'guid', 'title', 'name', 'description_markdown',