Back ready !
This commit is contained in:
parent
392b5bcabc
commit
941e1cabbd
@ -13,7 +13,8 @@ declare(strict_types=1);
|
|||||||
return [
|
return [
|
||||||
'routes' => [
|
'routes' => [
|
||||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
||||||
['name' => 'toplist#index', 'url' => '/toplist/{count}', 'verb' => 'GET'],
|
['name' => 'fetch#index', 'url' => '/fetch/{uri}', 'verb' => 'GET'],
|
||||||
['name' => 'search#index', 'url' => '/search/{value}', 'verb' => 'GET'],
|
['name' => 'search#index', 'url' => '/search/{value}', 'verb' => 'GET'],
|
||||||
|
['name' => 'toplist#index', 'url' => '/toplist/{count}', 'verb' => 'GET'],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"nextcloud/ocp": "^27.0.2",
|
"nextcloud/ocp": "^27.0.2",
|
||||||
"psalm/phar": "^5.14.1",
|
"psalm/phar": "^5.15.0",
|
||||||
"nextcloud/coding-standard": "^1.1.1"
|
"nextcloud/coding-standard": "^1.1.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
14
composer.lock
generated
14
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "3fa8e5aac39e7c385a793eff9a78e763",
|
"content-hash": "c0c30dda23dd29e41502385edf3227da",
|
||||||
"packages": [],
|
"packages": [],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
@ -94,16 +94,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "php-cs-fixer/shim",
|
"name": "php-cs-fixer/shim",
|
||||||
"version": "v3.22.0",
|
"version": "v3.23.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHP-CS-Fixer/shim.git",
|
"url": "https://github.com/PHP-CS-Fixer/shim.git",
|
||||||
"reference": "f6692934a6d1fe40fd8bc3339487490baa4a6700"
|
"reference": "ddca9b342374087121e44cca3b7d8aca8f121fa7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/f6692934a6d1fe40fd8bc3339487490baa4a6700",
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/ddca9b342374087121e44cca3b7d8aca8f121fa7",
|
||||||
"reference": "f6692934a6d1fe40fd8bc3339487490baa4a6700",
|
"reference": "ddca9b342374087121e44cca3b7d8aca8f121fa7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -140,9 +140,9 @@
|
|||||||
"description": "A tool to automatically fix PHP code style",
|
"description": "A tool to automatically fix PHP code style",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHP-CS-Fixer/shim/issues",
|
"issues": "https://github.com/PHP-CS-Fixer/shim/issues",
|
||||||
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.22.0"
|
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.23.0"
|
||||||
},
|
},
|
||||||
"time": "2023-07-16T23:08:49+00:00"
|
"time": "2023-08-14T12:28:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psalm/phar",
|
"name": "psalm/phar",
|
||||||
|
47
lib/Controller/FetchController.php
Normal file
47
lib/Controller/FetchController.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
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\Service\UserService;
|
||||||
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\JSONResponse;
|
||||||
|
use OCP\Http\Client\IClientService;
|
||||||
|
use OCP\IRequest;
|
||||||
|
|
||||||
|
class FetchController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
IRequest $request,
|
||||||
|
private IClientService $clientService,
|
||||||
|
private UserService $userService,
|
||||||
|
private PodcastDataReader $podcastDataReader
|
||||||
|
) {
|
||||||
|
parent::__construct(Application::APP_ID, $request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(string $uri): JSONResponse
|
||||||
|
{
|
||||||
|
$podcastData = $this->podcastDataReader->getCachedOrFetchPodcastData($uri, $this->userService->getUserUID());
|
||||||
|
|
||||||
|
if ($podcastData) {
|
||||||
|
return new JSONResponse($podcastData->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
$client = $this->clientService->newClient();
|
||||||
|
$feed = $client->get($uri);
|
||||||
|
$statusCode = $feed->getStatusCode();
|
||||||
|
|
||||||
|
if ($statusCode < 200 || $statusCode >= 300) {
|
||||||
|
throw new \ErrorException("Web request returned non-2xx status code: {$statusCode}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$podcastData = PodcastData::parseRssXml((string) $feed->getBody());
|
||||||
|
|
||||||
|
return new JSONResponse($podcastData->toArray());
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace OCA\RePod\Controller;
|
namespace OCA\RePod\Controller;
|
||||||
|
|
||||||
|
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||||
use OCA\RePod\AppInfo\Application;
|
use OCA\RePod\AppInfo\Application;
|
||||||
use OCA\RePod\Service\FyydService;
|
use OCA\RePod\Service\FyydService;
|
||||||
use OCA\RePod\Service\ItunesService;
|
use OCA\RePod\Service\ItunesService;
|
||||||
@ -36,8 +37,8 @@ class SearchController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usort($podcasts, fn (array $a, array $b) => new \DateTime((string) $b['lastpub']) <=> new \DateTime((string) $a['lastpub']));
|
usort($podcasts, fn (PodcastData $a, PodcastData $b) => $a->getFetchedAtUnix() <=> $b->getFetchedAtUnix());
|
||||||
$podcasts = array_intersect_key($podcasts, array_unique(array_map(fn (array $feed) => $feed['url'], $podcasts)));
|
$podcasts = array_intersect_key($podcasts, array_unique(array_map(fn (PodcastData $feed) => $feed->getLink(), $podcasts)));
|
||||||
|
|
||||||
return new JSONResponse($podcasts);
|
return new JSONResponse($podcasts);
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,12 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace OCA\RePod\Service;
|
namespace OCA\RePod\Service;
|
||||||
|
|
||||||
|
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
use OCP\IUserSession;
|
use OCP\IUserSession;
|
||||||
use OCP\L10N\IFactory;
|
use OCP\L10N\IFactory;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
/**
|
|
||||||
* @psalm-import-type Podcast from IProvider
|
|
||||||
*/
|
|
||||||
class FyydService implements IProvider
|
class FyydService implements IProvider
|
||||||
{
|
{
|
||||||
private const BASE_URL = 'https://api.fyyd.de/0.2/';
|
private const BASE_URL = 'https://api.fyyd.de/0.2/';
|
||||||
@ -42,20 +40,14 @@ class FyydService implements IProvider
|
|||||||
if (array_key_exists('data', $json) && is_array($json['data'])) {
|
if (array_key_exists('data', $json) && is_array($json['data'])) {
|
||||||
/** @var string[] $feed */
|
/** @var string[] $feed */
|
||||||
foreach ($json['data'] as $feed) {
|
foreach ($json['data'] as $feed) {
|
||||||
$podcasts[] = [
|
$podcasts[] = new PodcastData(
|
||||||
'id' => $feed['id'],
|
$feed['title'],
|
||||||
'provider' => 'fyyd',
|
$feed['author'],
|
||||||
'website' => $feed['htmlURL'],
|
$feed['xmlURL'],
|
||||||
'description' => $feed['description'],
|
$feed['description'],
|
||||||
'title' => $feed['title'],
|
$feed['imgURL'],
|
||||||
'author' => $feed['author'],
|
strtotime($feed['lastpub'])
|
||||||
'url' => $feed['xmlURL'],
|
);
|
||||||
'position_last_week' => $feed['rank'],
|
|
||||||
'mygpo_link' => $feed['url_fyyd'],
|
|
||||||
'logo_url' => $feed['imgURL'],
|
|
||||||
'lastpub' => $feed['lastpub'],
|
|
||||||
'episode_count' => $feed['episode_count'],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +55,7 @@ class FyydService implements IProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Podcast[]
|
* @return PodcastData[]
|
||||||
*/
|
*/
|
||||||
public function hot(int $count = 10): array
|
public function hot(int $count = 10): array
|
||||||
{
|
{
|
||||||
@ -95,20 +87,14 @@ class FyydService implements IProvider
|
|||||||
if (array_key_exists('data', $postCastJson) && is_array($postCastJson['data'])) {
|
if (array_key_exists('data', $postCastJson) && is_array($postCastJson['data'])) {
|
||||||
/** @var string[] $feed */
|
/** @var string[] $feed */
|
||||||
foreach ($postCastJson['data'] as $feed) {
|
foreach ($postCastJson['data'] as $feed) {
|
||||||
$podcasts[] = [
|
$podcasts[] = new PodcastData(
|
||||||
'id' => $feed['id'],
|
$feed['title'],
|
||||||
'provider' => 'fyyd',
|
$feed['author'],
|
||||||
'website' => $feed['htmlURL'],
|
$feed['xmlURL'],
|
||||||
'description' => $feed['description'],
|
$feed['description'],
|
||||||
'title' => $feed['title'],
|
$feed['imgURL'],
|
||||||
'author' => $feed['author'],
|
strtotime($feed['lastpub'])
|
||||||
'url' => $feed['xmlURL'],
|
);
|
||||||
'position_last_week' => $feed['rank'],
|
|
||||||
'mygpo_link' => $feed['url_fyyd'],
|
|
||||||
'logo_url' => $feed['imgURL'],
|
|
||||||
'lastpub' => $feed['lastpub'],
|
|
||||||
'episode_count' => $feed['episode_count'],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,26 +4,12 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace OCA\RePod\Service;
|
namespace OCA\RePod\Service;
|
||||||
|
|
||||||
/**
|
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||||
* @psalm-type Podcast = array{
|
|
||||||
* id: string,
|
|
||||||
* provider: string,
|
|
||||||
* website: string,
|
|
||||||
* description: string,
|
|
||||||
* title: string,
|
|
||||||
* author: string,
|
|
||||||
* url: string,
|
|
||||||
* position_last_week: ?string,
|
|
||||||
* mygpo_link: string,
|
|
||||||
* logo_url: string,
|
|
||||||
* lastpub: string,
|
|
||||||
* episode_count: string
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
interface IProvider
|
interface IProvider
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return Podcast[]
|
* @return PodcastData[]
|
||||||
*/
|
*/
|
||||||
public function search(string $value): array;
|
public function search(string $value): array;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace OCA\RePod\Service;
|
namespace OCA\RePod\Service;
|
||||||
|
|
||||||
|
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
|
|
||||||
class ItunesService implements IProvider
|
class ItunesService implements IProvider
|
||||||
@ -33,20 +34,14 @@ class ItunesService implements IProvider
|
|||||||
if (array_key_exists('results', $json) && is_array($json['results'])) {
|
if (array_key_exists('results', $json) && is_array($json['results'])) {
|
||||||
/** @var string[] $feed */
|
/** @var string[] $feed */
|
||||||
foreach ($json['results'] as $feed) {
|
foreach ($json['results'] as $feed) {
|
||||||
$podcasts[] = [
|
$podcasts[] = new PodcastData(
|
||||||
'id' => $feed['id'],
|
$feed['trackName'],
|
||||||
'provider' => 'itunes',
|
$feed['artistName'],
|
||||||
'website' => $feed['trackViewUrl'],
|
$feed['feedUrl'],
|
||||||
'description' => $feed['primaryGenreName'],
|
$feed['primaryGenreName'],
|
||||||
'title' => $feed['trackName'],
|
$feed['artworkUrl600'],
|
||||||
'author' => $feed['artistName'],
|
strtotime($feed['releaseDate'])
|
||||||
'url' => $feed['feedUrl'],
|
);
|
||||||
'position_last_week' => null,
|
|
||||||
'mygpo_link' => $feed['trackViewUrl'],
|
|
||||||
'logo_url' => $feed['artworkUrl600'],
|
|
||||||
'lastpub' => $feed['releaseDate'],
|
|
||||||
'episode_count' => $feed['trackCount'],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,13 @@ class UserService
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUserUID(): string
|
||||||
|
{
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
|
|
||||||
|
return $user ? $user->getUID() : '';
|
||||||
|
}
|
||||||
|
|
||||||
public function getIsoCode(): string
|
public function getIsoCode(): string
|
||||||
{
|
{
|
||||||
return $this->l10n->getUserLanguage($this->userSession->getUser());
|
return $this->l10n->getUserLanguage($this->userSession->getUser());
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
findUnusedCode="false"
|
findUnusedCode="false"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns="https://getpsalm.org/schema/config"
|
xmlns="https://getpsalm.org/schema/config"
|
||||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
|
||||||
>
|
>
|
||||||
<projectFiles>
|
<projectFiles>
|
||||||
<directory name="lib" />
|
<directory name="lib" />
|
||||||
|
@ -19,6 +19,19 @@ namespace OCA\GPodderSync\Core\EpisodeAction;
|
|||||||
*/
|
*/
|
||||||
class EpisodeAction
|
class EpisodeAction
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $podcast,
|
||||||
|
private string $episode,
|
||||||
|
private string $action,
|
||||||
|
private string $timestamp,
|
||||||
|
private int $started,
|
||||||
|
private int $position,
|
||||||
|
private int $total,
|
||||||
|
private ?string $guid,
|
||||||
|
private ?int $id
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -17,6 +17,17 @@ namespace OCA\GPodderSync\Core\PodcastData;
|
|||||||
*/
|
*/
|
||||||
class PodcastData implements \JsonSerializable
|
class PodcastData implements \JsonSerializable
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ?string $title,
|
||||||
|
private ?string $author,
|
||||||
|
private ?string $link,
|
||||||
|
private ?string $description,
|
||||||
|
private ?string $imageUrl,
|
||||||
|
private int $fetchedAtUnix,
|
||||||
|
private ?string $imageBlob = null
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return PodcastData
|
* @return PodcastData
|
||||||
* @throws \Exception if the XML data could not be parsed
|
* @throws \Exception if the XML data could not be parsed
|
||||||
|
@ -13,6 +13,13 @@ namespace OCA\GPodderSync\Core\PodcastData;
|
|||||||
*/
|
*/
|
||||||
class PodcastMetrics implements \JsonSerializable
|
class PodcastMetrics implements \JsonSerializable
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $url,
|
||||||
|
private int $listenedSeconds = 0,
|
||||||
|
private ?PodcastActionCounts $actionCounts = null
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -6,6 +6,12 @@ namespace OCA\GPodderSync\Core\SubscriptionChange;
|
|||||||
|
|
||||||
class SubscriptionChange
|
class SubscriptionChange
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $url,
|
||||||
|
private bool $isSubscribed
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -6,6 +6,10 @@ namespace OCA\GPodderSync\Core\SubscriptionChange;
|
|||||||
|
|
||||||
class SubscriptionChangeRequestParser
|
class SubscriptionChangeRequestParser
|
||||||
{
|
{
|
||||||
|
public function __construct(private SubscriptionChangesReader $subscriptionChangeReader)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SubscriptionChange[]
|
* @return SubscriptionChange[]
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user