From 1fab10eb0d63bb7c3edf34ffe691e2aec2c2e43c Mon Sep 17 00:00:00 2001
From: Benjamin Bellamy <ben@podlibre.org>
Date: Mon, 21 Jun 2021 11:58:43 +0000
Subject: [PATCH] =?UTF-8?q?feat(rss):=20add=20=CB=82podcast:guid=CB=83=20t?=
 =?UTF-8?q?ag=20for=20channel?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/Controllers/Admin/PodcastController.php        |  1 +
 app/Controllers/Admin/PodcastImportController.php  |  8 +++++++-
 .../Migrations/2020-05-30-101500_add_podcasts.php  |  5 +++++
 app/Entities/Podcast.php                           |  2 ++
 app/Helpers/misc_helper.php                        | 14 ++++++++++++++
 app/Helpers/rss_helper.php                         |  1 +
 app/Models/PodcastModel.php                        |  1 +
 7 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/app/Controllers/Admin/PodcastController.php b/app/Controllers/Admin/PodcastController.php
index 0fe70a48bb..5583213b96 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 fbc0cca288..2125d0972d 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 b04c92667a..f330d0841c 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 20dd284089..6ed3b702a1 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 68404ba104..212b8271ee 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 eeb24254da..1007932660 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 1b20c1feec..739593e73a 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',
-- 
GitLab