refacto: remove atomlink that leads to weird bugs
This commit is contained in:
parent
c48432c0b5
commit
540c5df7e5
@ -4,8 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\Controller;
|
||||
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastDataReader;
|
||||
use OCA\RePod\AppInfo\Application;
|
||||
use OCA\RePod\Core\PodcastData\PodcastData;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\Http\Client\IClientService;
|
||||
@ -15,16 +16,24 @@ class PodcastController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private IClientService $clientService
|
||||
private IClientService $clientService,
|
||||
private PodcastDataReader $podcastDataReader
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
|
||||
public function index(string $url): JSONResponse {
|
||||
$podcast = $this->podcastDataReader->tryGetCachedPodcastData($url);
|
||||
|
||||
if ($podcast) {
|
||||
return new JSONResponse($podcast);
|
||||
}
|
||||
|
||||
$client = $this->clientService->newClient();
|
||||
$feed = $client->get($url);
|
||||
$podcast = PodcastData::parseRssXml((string) $feed->getBody());
|
||||
$this->podcastDataReader->trySetCachedPodcastData($url, $podcast);
|
||||
|
||||
return new JSONResponse($podcast->toArrayWithExtras(), $feed->getStatusCode());
|
||||
return new JSONResponse($podcast, $feed->getStatusCode());
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ namespace OCA\RePod\Core\EpisodeAction;
|
||||
|
||||
use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionReader as CoreEpisodeActionReader;
|
||||
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
|
||||
use OCA\RePod\Core\PodcastData\PodcastData;
|
||||
use OCA\RePod\Service\UserService;
|
||||
|
||||
class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
@ -53,40 +52,40 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
$name = (string) $item->title;
|
||||
|
||||
// Get episode link
|
||||
$link = PodcastData::stringOrNull($item->link);
|
||||
$link = $this->stringOrNull($item->link);
|
||||
|
||||
// Get episode image
|
||||
$image = PodcastData::stringOrNull($item->image->url);
|
||||
$image = $this->stringOrNull($item->image->url);
|
||||
|
||||
if (!$image && $iTunesItemChildren) {
|
||||
$imageAttributes = $iTunesItemChildren->image->attributes();
|
||||
$image = PodcastData::stringOrNull($imageAttributes ? (string) $imageAttributes->href : '');
|
||||
$image = $this->stringOrNull($imageAttributes ? (string) $imageAttributes->href : '');
|
||||
}
|
||||
|
||||
if (!$image) {
|
||||
$image = PodcastData::stringOrNull($channel->image->url);
|
||||
$image = $this->stringOrNull($channel->image->url);
|
||||
}
|
||||
|
||||
if (!$image && $iTunesChannelChildren) {
|
||||
$imageAttributes = $iTunesChannelChildren->image->attributes();
|
||||
$image = PodcastData::stringOrNull($imageAttributes ? (string) $imageAttributes->href : '');
|
||||
$image = $this->stringOrNull($imageAttributes ? (string) $imageAttributes->href : '');
|
||||
}
|
||||
|
||||
if (!$image) {
|
||||
preg_match('/<itunes:image\s+href="([^"]+)"/', $xmlString, $matches);
|
||||
$image = PodcastData::stringOrNull($matches[1]);
|
||||
$image = $this->stringOrNull($matches[1]);
|
||||
}
|
||||
|
||||
// Get episode description
|
||||
$itemContent = $item->children('content', true);
|
||||
if ($itemContent) {
|
||||
$description = PodcastData::stringOrNull($itemContent->encoded);
|
||||
$description = $this->stringOrNull($itemContent->encoded);
|
||||
} else {
|
||||
$description = PodcastData::stringOrNull($item->description);
|
||||
$description = $this->stringOrNull($item->description);
|
||||
}
|
||||
|
||||
if (!$description && $iTunesItemChildren) {
|
||||
$description = PodcastData::stringOrNull($iTunesItemChildren->summary);
|
||||
$description = $this->stringOrNull($iTunesItemChildren->summary);
|
||||
}
|
||||
|
||||
// Remove tags
|
||||
@ -94,9 +93,9 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
|
||||
// Get episode duration
|
||||
if ($iTunesItemChildren) {
|
||||
$rawDuration = PodcastData::stringOrNull($iTunesItemChildren->duration);
|
||||
$rawDuration = $this->stringOrNull($iTunesItemChildren->duration);
|
||||
} else {
|
||||
$rawDuration = PodcastData::stringOrNull($item->duration);
|
||||
$rawDuration = $this->stringOrNull($item->duration);
|
||||
}
|
||||
|
||||
$splitDuration = array_reverse(explode(':', $rawDuration ?? ''));
|
||||
@ -105,7 +104,7 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
$duration += !empty($splitDuration[2]) ? (int) $splitDuration[2] * 60 : 0;
|
||||
|
||||
// Get episode pubDate
|
||||
$rawPubDate = PodcastData::stringOrNull($item->pubDate);
|
||||
$rawPubDate = $this->stringOrNull($item->pubDate);
|
||||
$pubDate = $rawPubDate ? new \DateTime($rawPubDate) : null;
|
||||
|
||||
$episodes[] = new EpisodeActionExtraData(
|
||||
@ -127,4 +126,15 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
|
||||
return $episodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|\SimpleXMLElement|string $value
|
||||
*/
|
||||
private function stringOrNull($value): ?string {
|
||||
if ($value) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\Core\PodcastData;
|
||||
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastData as CorePodcastData;
|
||||
|
||||
/**
|
||||
* @psalm-type PodcastDataType = array{
|
||||
* title: ?string,
|
||||
* author: ?string,
|
||||
* link: ?string,
|
||||
* description: ?string,
|
||||
* imageUrl: ?string,
|
||||
* fetchedAtUnix: int,
|
||||
* imageBlob: ?string,
|
||||
* atomLink: ?string
|
||||
* }
|
||||
*/
|
||||
class PodcastData extends CorePodcastData implements \JsonSerializable
|
||||
{
|
||||
public function __construct(
|
||||
?string $title,
|
||||
?string $author,
|
||||
?string $link,
|
||||
?string $description,
|
||||
?string $imageUrl,
|
||||
int $fetchedAtUnix,
|
||||
?string $imageBlob = null,
|
||||
private ?string $atomLink
|
||||
) {
|
||||
parent::__construct(
|
||||
$title,
|
||||
$author,
|
||||
$link,
|
||||
$description,
|
||||
$imageUrl,
|
||||
$fetchedAtUnix,
|
||||
$imageBlob
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception if the XML data could not be parsed
|
||||
*/
|
||||
public static function parseRssXml(string $xmlString, ?int $fetchedAtUnix = null): PodcastData {
|
||||
$xml = new \SimpleXMLElement($xmlString);
|
||||
$channel = $xml->channel;
|
||||
|
||||
return new PodcastData(
|
||||
self::stringOrNull($channel->title),
|
||||
self::getXPathContent($xml, '/rss/channel/itunes:author'),
|
||||
self::stringOrNull($channel->link),
|
||||
self::stringOrNull($channel->description),
|
||||
self::getXPathContent($xml, '/rss/channel/image/url')
|
||||
?? self::getXPathAttribute($xml, '/rss/channel/itunes:image/@href'),
|
||||
$fetchedAtUnix ?? (new \DateTime())->getTimestamp(),
|
||||
null,
|
||||
self::getXPathContent($xml, '/rss/channel/atom:link/@href')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|\SimpleXMLElement|string $value
|
||||
*/
|
||||
public static function stringOrNull($value): ?string {
|
||||
if ($value) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getAtomLink(): ?string {
|
||||
return $this->atomLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PodcastDataType
|
||||
*/
|
||||
public function toArrayWithExtras() {
|
||||
return array_merge(parent::toArray(), [
|
||||
'atomLink' => $this->atomLink,
|
||||
]);
|
||||
}
|
||||
|
||||
private static function getXPathContent(\SimpleXMLElement $xml, string $xpath): ?string {
|
||||
$match = $xml->xpath($xpath);
|
||||
if ($match) {
|
||||
return (string) $match[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function getXPathAttribute(\SimpleXMLElement $xml, string $xpath): ?string {
|
||||
$match = $xml->xpath($xpath);
|
||||
if ($match) {
|
||||
return (string) $match[0][0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -26,7 +26,6 @@ import Episodes from '../components/Feed/Episodes.vue'
|
||||
import Loading from '../components/Atoms/Loading.vue'
|
||||
import axios from '@nextcloud/axios'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { toUrl } from '../utils/url.js'
|
||||
|
||||
export default {
|
||||
name: 'Feed',
|
||||
@ -53,11 +52,6 @@ export default {
|
||||
async mounted() {
|
||||
try {
|
||||
const podcastData = await axios.get(generateUrl('/apps/repod/podcast?url={url}', { url: this.url }))
|
||||
|
||||
if (podcastData.data.atomLink && podcastData.data.atomLink !== this.url) {
|
||||
this.$router.push(toUrl(podcastData.data.atomLink))
|
||||
}
|
||||
|
||||
this.feed = podcastData.data
|
||||
} catch (e) {
|
||||
this.failed = true
|
||||
|
Loading…
Reference in New Issue
Block a user