From 3f9bc372cee489cc01399d93290a7514cf64b796 Mon Sep 17 00:00:00 2001 From: Michel Roux Date: Thu, 24 Aug 2023 12:48:10 +0200 Subject: [PATCH] EpisodeActionExtra done --- appinfo/routes.php | 2 +- lib/Controller/EpisodesController.php | 17 +++ ...chController.php => PodcastController.php} | 2 +- .../EpisodeAction/EpisodeActionExtraData.php | 112 +++++++++++++++ .../EpisodeAction/EpisodeActionReader.php | 130 ++++++++++++++++++ src/views/Feed.vue | 2 +- .../SubscriptionChangeEntity.php | 17 +++ .../SubscriptionChangeMapper.php | 43 ++++++ .../SubscriptionChangeRepository.php | 40 ++++++ .../SubscriptionChangeWriter.php | 30 ++++ 10 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 lib/Controller/EpisodesController.php rename lib/Controller/{FetchController.php => PodcastController.php} (96%) create mode 100644 lib/Core/EpisodeAction/EpisodeActionExtraData.php create mode 100644 lib/Core/EpisodeAction/EpisodeActionReader.php create mode 100644 stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeEntity.php create mode 100644 stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeMapper.php create mode 100644 stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeRepository.php create mode 100644 stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeWriter.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 89e6a4d..8666e6d 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -13,7 +13,7 @@ declare(strict_types=1); return [ 'routes' => [ ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], - ['name' => 'fetch#index', 'url' => '/fetch', 'verb' => 'GET'], + ['name' => 'podcast#index', 'url' => '/podcast', 'verb' => 'GET'], ['name' => 'search#index', 'url' => '/search', 'verb' => 'GET'], ['name' => 'toplist#index', 'url' => '/toplist', 'verb' => 'GET'], ], diff --git a/lib/Controller/EpisodesController.php b/lib/Controller/EpisodesController.php new file mode 100644 index 0000000..4ccb52d --- /dev/null +++ b/lib/Controller/EpisodesController.php @@ -0,0 +1,17 @@ +episodeUrl = $episodeUrl; + $this->podcastName = $podcastName; + $this->episodeName = $episodeName; + $this->episodeLink = $episodeLink; + $this->episodeImage = $episodeImage; + $this->episodeDescription = $episodeDescription; + $this->fetchedAtUnix = $fetchedAtUnix; + $this->episodeAction = $episodeAction; + } + + public function __toString(): string + { + return $this->episodeUrl ?? '/no episodeUrl/'; + } + + public function getEpisodeAction(): ?EpisodeAction + { + return $this->episodeAction; + } + + public function getEpisodeUrl(): ?string + { + return $this->episodeUrl; + } + + /** + * @return EpisodeActionExtraDataType + */ + public function toArray(): array + { + return + [ + 'podcastName' => $this->podcastName, + 'episodeUrl' => $this->episodeUrl, + 'episodeName' => $this->episodeName, + 'episodeLink' => $this->episodeLink, + 'episodeImage' => $this->episodeImage, + 'episodeDescription' => $this->episodeDescription, + 'fetchedAtUnix' => $this->fetchedAtUnix, + 'episodeAction' => $this->episodeAction ? $this->episodeAction->toArray() : null, + ]; + } + + /** + * @return EpisodeActionExtraDataType + */ + public function jsonSerialize(): mixed + { + return $this->toArray(); + } + + public function getPodcastName(): ?string + { + return $this->podcastName; + } + + public function getEpisodeName(): ?string + { + return $this->episodeName; + } + + public function getEpisodeLink(): ?string + { + return $this->episodeLink; + } + + public function getFetchedAtUnix(): int + { + return $this->fetchedAtUnix; + } + + public function getEpisodeImage(): ?string + { + return $this->episodeImage; + } +} diff --git a/lib/Core/EpisodeAction/EpisodeActionReader.php b/lib/Core/EpisodeAction/EpisodeActionReader.php new file mode 100644 index 0000000..e8a2354 --- /dev/null +++ b/lib/Core/EpisodeAction/EpisodeActionReader.php @@ -0,0 +1,130 @@ +channel; + $episodeName = null; + $episodeLink = null; + $episodeImage = null; + $episodeDescription = null; + $episodeUrlPath = parse_url($episodeUrl, PHP_URL_PATH); + + // Find episode by url and add data for it + /** @var \SimpleXMLElement $item */ + foreach ($channel->item as $item) { + $url = (string) $item->enclosure['url']; + + // First try to match the url directly + if (false === strpos($episodeUrl, $url)) { + // Then try to match the path only + // The podcast http://feeds.feedburner.com/abcradio/10percenthappier has a "rss_browser" query parameter + // for every item that changed all the time, so we can't match the full url + $path = parse_url($url, PHP_URL_PATH); + + if ($episodeUrlPath !== $path) { + continue; + } + } + + // Get episode action + $episodeAction = $this->episodeActionRepository->findByEpisodeUrl($url, $this->userService->getUserUID()); + + // Get episode name + $episodeName = $this->stringOrNull($item->title); + + // Get episode link + $episodeLink = $this->stringOrNull($item->link); + + // Get episode image + $episodeImageChildren = $item->children('http://www.itunes.com/dtds/podcast-1.0.dtd'); + if ($episodeImageChildren) { + $episodeImageAttributes = (array) $episodeImageChildren->image->attributes(); + $episodeImage = $this->stringOrNull(array_key_exists('href', $episodeImageAttributes) ? (string) $episodeImageAttributes['href'] : ''); + $iTunesChildren = $item->children('itunes', true); + + if ($iTunesChildren && !$episodeImage) { + $episodeImage = $this->stringOrNull((string) $iTunesChildren->image['href']); + } + + if (!$episodeImage) { + $episodeImage = $this->stringOrNull($channel->image->url); + } + + if ($iTunesChildren && !$episodeImage) { + $episodeImage = $this->stringOrNull((string) $iTunesChildren->image['href']); + } + + if (!$episodeImage) { + $channelImageChildren = $channel->children('http://www.itunes.com/dtds/podcast-1.0.dtd'); + if ($channelImageChildren) { + $episodeImageAttributes = (array) $channelImageChildren->image->attributes(); + $episodeImage = $this->stringOrNull(array_key_exists('href', $episodeImageAttributes) ? (string) $episodeImageAttributes['href'] : ''); + } + } + + if (!$episodeImage) { + preg_match('/stringOrNull($matches[1]); + } + } + + // Get episode description + $episodeContentChildren = $item->children('content', true); + + if ($episodeContentChildren) { + $episodeDescription = $this->stringOrNull($episodeContentChildren->encoded); + } + + if (!$episodeDescription) { + $episodeDescription = $this->stringOrNull($item->description); + } + + // Open links in new browser window/tab + $episodeDescription = str_replace('stringOrNull($channel->title), + $episodeName, + $episodeLink, + $episodeImage, + $episodeDescription, + $fetchedAtUnix ?? (new \DateTime())->getTimestamp(), + $episodeAction + ); + } + + return $episodes; + } + + private function stringOrNull(mixed $value): ?string + { + if ($value) { + return (string) $value; + } + + return null; + } +} diff --git a/src/views/Feed.vue b/src/views/Feed.vue index 3733090..c96df8b 100644 --- a/src/views/Feed.vue +++ b/src/views/Feed.vue @@ -44,7 +44,7 @@ export default { }, async mounted() { try { - const podcastData = await axios.get(generateUrl('/apps/repod/fetch?url={url}', { url: this.url })) + const podcastData = await axios.get(generateUrl('/apps/repod/podcast?url={url}', { url: this.url })) this.feed = podcastData.data.data } catch (e) { this.failed = true diff --git a/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeEntity.php b/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeEntity.php new file mode 100644 index 0000000..644a520 --- /dev/null +++ b/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeEntity.php @@ -0,0 +1,17 @@ + + */ + public function jsonSerialize(): mixed + { + } +} diff --git a/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeMapper.php b/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeMapper.php new file mode 100644 index 0000000..beaa296 --- /dev/null +++ b/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeMapper.php @@ -0,0 +1,43 @@ + + */ +class SubscriptionChangeMapper extends QBMapper +{ + public function __construct(IDBConnection $db) + { + } + + /** + * @return SubscriptionChangeEntity[] + */ + public function findAll(string $userId) + { + } + + /** + * @return ?SubscriptionChangeEntity + */ + public function findByUrl(string $url, string $userId) + { + } + + public function remove(SubscriptionChangeEntity $subscriptionChangeEntity): void + { + } + + /** + * @return SubscriptionChangeEntity[] + */ + public function findAllSubscriptionState(bool $subscribed, \DateTime $sinceTimestamp, string $userId) + { + } +} diff --git a/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeRepository.php b/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeRepository.php new file mode 100644 index 0000000..60583ee --- /dev/null +++ b/stubs/OCA/GPodderSync/Db/SubscriptionChange/SubscriptionChangeRepository.php @@ -0,0 +1,40 @@ +