search in PHP completed
All checks were successful
repod / nextcloud (push) Successful in 1m6s
repod / nodejs (push) Successful in 1m22s

This commit is contained in:
Michel Roux 2023-07-27 23:01:24 +02:00
parent 431cbf0c42
commit 2a4662e85b
6 changed files with 99 additions and 35 deletions

View File

@ -6,11 +6,16 @@ require_once './vendor/autoload.php';
use Nextcloud\CodingStandard\Config; use Nextcloud\CodingStandard\Config;
class MyConfig extends Config { class MyConfig extends Config
{
public function getRules(): array public function getRules(): array
{ {
$rules = parent::getRules(); $rules = parent::getRules();
$rules['@PhpCsFixer'] = true;
$rules['curly_braces_position']['classes_opening_brace'] = 'next_line_unless_newline_at_signature_end'; $rules['curly_braces_position']['classes_opening_brace'] = 'next_line_unless_newline_at_signature_end';
$rules['phpdoc_separation'] = false;
$rules['phpdoc_to_comment'] = false;
$rules['single_line_comment_style'] = false;
return $rules; return $rules;
} }
} }

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/** /**
* Create your routes in here. The name is the lowercase name of the controller * Create your routes in here. The name is the lowercase name of the controller
* without the controller part, the stuff after the hash is the method. * without the controller part, the stuff after the hash is the method.
* e.g. page#index -> OCA\RePod\Controller\PageController->index() * e.g. page#index -> OCA\RePod\Controller\PageController->index().
* *
* The controller class has to be registered in the application.php file since * The controller class has to be registered in the application.php file since
* it's instantiated in there * it's instantiated in there
@ -14,6 +14,6 @@ return [
'routes' => [ 'routes' => [
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
['name' => 'top#index', 'url' => '/top/{count}', 'verb' => 'GET'], ['name' => 'top#index', 'url' => '/top/{count}', 'verb' => 'GET'],
['name' => 'search#index', 'url' => '/search/{value}', 'verb' => 'GET'] ['name' => 'search#index', 'url' => '/search/{value}', 'verb' => 'GET'],
] ],
]; ];

View File

@ -18,13 +18,16 @@ class Application extends App implements IBootstrap
public const APP_ID = 'repod'; public const APP_ID = 'repod';
private const GPODDERSYNC_ID = 'gpoddersync'; private const GPODDERSYNC_ID = 'gpoddersync';
public function __construct() { public function __construct()
{
parent::__construct(self::APP_ID); parent::__construct(self::APP_ID);
} }
public function boot(IBootContext $context): void { public function boot(IBootContext $context): void
{
/** @psalm-suppress DeprecatedInterface */ /** @psalm-suppress DeprecatedInterface */
$appContainer = $context->getAppContainer(); $appContainer = $context->getAppContainer();
/** @var IAppManager $appManager */ /** @var IAppManager $appManager */
$appManager = $appContainer->get(IAppManager::class); $appManager = $appContainer->get(IAppManager::class);
@ -40,10 +43,12 @@ class Application extends App implements IBootstrap
Util::connectHook('\OCP\Config', 'js', $this, 'extendJsConfig'); Util::connectHook('\OCP\Config', 'js', $this, 'extendJsConfig');
} }
public function register(IRegistrationContext $context): void { public function register(IRegistrationContext $context): void
{
} }
public static function extendJsConfig(array $settings): void { public static function extendJsConfig(array $settings): void
{
/** @var IAppManager $appManager */ /** @var IAppManager $appManager */
$appManager = Server::get(IAppManager::class); $appManager = Server::get(IAppManager::class);
@ -51,7 +56,7 @@ class Application extends App implements IBootstrap
/** @var array $appConfig */ /** @var array $appConfig */
$appConfig = json_decode((string) $settings['array']['oc_appconfig'], true); $appConfig = json_decode((string) $settings['array']['oc_appconfig'], true);
$appConfig['repod'] = [ $appConfig['repod'] = [
'gpodder' => $appManager->isEnabledForUser(self::GPODDERSYNC_ID) 'gpodder' => $appManager->isEnabledForUser(self::GPODDERSYNC_ID),
]; ];
$settings['array']['oc_appconfig'] = json_encode($appConfig); $settings['array']['oc_appconfig'] = json_encode($appConfig);
} }

View File

@ -14,7 +14,8 @@ use OCP\Util;
class PageController extends Controller class PageController extends Controller
{ {
public function __construct(IRequest $request, private IConfig $config) { public function __construct(IRequest $request, private IConfig $config)
{
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }
@ -22,7 +23,8 @@ class PageController extends Controller
* @NoAdminRequired * @NoAdminRequired
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function index(): TemplateResponse { public function index(): TemplateResponse
{
Util::addScript(Application::APP_ID, 'repod-main'); Util::addScript(Application::APP_ID, 'repod-main');
$csp = new ContentSecurityPolicy(); $csp = new ContentSecurityPolicy();
@ -36,6 +38,7 @@ class PageController extends Controller
$response = new TemplateResponse(Application::APP_ID, 'main'); $response = new TemplateResponse(Application::APP_ID, 'main');
$response->setContentSecurityPolicy($csp); $response->setContentSecurityPolicy($csp);
return $response; return $response;
} }
} }

View File

@ -4,52 +4,102 @@ declare(strict_types=1);
namespace OCA\RePod\Controller; namespace OCA\RePod\Controller;
use Exception;
use OCA\RePod\AppInfo\Application; use OCA\RePod\AppInfo\Application;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCP\Http\Client\IClientService; use OCP\Http\Client\IClientService;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUserSession;
use OCP\L10N\IFactory;
class SearchController extends Controller class SearchController extends Controller
{ {
public function __construct( public function __construct(
IRequest $request, IRequest $request,
private IClientService $clientService private IClientService $clientService,
private IFactory $l10n,
private IUserSession $userSession
) { ) {
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }
public function index(string $value): JSONResponse { public function index(string $value): JSONResponse
{
$podcasts = []; $podcasts = [];
try { try {
$fyydClient = $this->clientService->newClient(); $fyydClient = $this->clientService->newClient();
$fyydReponse = $fyydClient->get("https://api.fyyd.de/0.2/search/podcast", [ $fyydReponse = $fyydClient->get('https://api.fyyd.de/0.2/search/podcast', [
'query' => [ 'query' => [
'title' => $value, 'title' => $value,
'term' => $value 'term' => $value,
] ],
]); ]);
$fyydJson = (array) json_decode((string) $fyydReponse->getBody(), true, flags: JSON_THROW_ON_ERROR); $fyydJson = (array) json_decode((string) $fyydReponse->getBody(), true, flags: JSON_THROW_ON_ERROR);
if (array_key_exists('data', $fyydJson) && is_array($fyydJson['data'])) { if (array_key_exists('data', $fyydJson) && is_array($fyydJson['data'])) {
/** @var string[] $fyydFeed */ /** @var string[] $fyydFeed */
foreach ($fyydJson['data'] as $fyydFeed) { foreach ($fyydJson['data'] as $fyydFeed) {
$podcasts[] = [ $lastPub = date_format(new \DateTime($fyydFeed['lastpub']), DATE_ATOM);
'id' => $fyydFeed['id'],
'title' => $fyydFeed['title'], if ($lastPub) {
'description' => $fyydFeed['description'], $podcasts[] = [
'image' => $fyydFeed['imgURL'], 'provider' => 'fyyd',
'url' => $fyydFeed['xmlURL'], 'id' => $fyydFeed['id'],
'lang' => $fyydFeed['language'], 'title' => $fyydFeed['title'],
'lastpub' => $fyydFeed['lastpub'] 'author' => $fyydFeed['author'],
]; 'image' => $fyydFeed['imgURL'],
'provider_url' => $fyydFeed['htmlURL'],
'feed_url' => $fyydFeed['xmlURL'],
'last_pub' => $lastPub,
'nb_episodes' => $fyydFeed['episode_count'],
];
}
} }
} }
} catch (Exception $e) { } catch (\Exception $e) {
} }
try {
$itunesClient = $this->clientService->newClient();
$itunesResponse = $itunesClient->get('https://itunes.apple.com/search', [
'query' => [
'media' => 'podcast',
'term' => $value,
'lang' => $this->l10n->getUserLanguage($this->userSession->getUser()),
],
]);
$itunesJson = (array) json_decode((string) $itunesResponse->getBody(), true, flags: JSON_THROW_ON_ERROR);
if (array_key_exists('data', $itunesJson) && is_array($itunesJson['data'])) {
/** @var string[] $itunesFeed */
foreach ($itunesJson['results'] as $itunesFeed) {
$lastPub = date_format(new \DateTime($itunesFeed['releaseDate']), DATE_ATOM);
if ($lastPub) {
$podcasts[] = [
'id' => $itunesFeed['id'],
'title' => $itunesFeed['trackName'],
'author' => $itunesFeed['artistName'],
'image' => $itunesFeed['artworkUrl600'],
'provider_url' => $itunesFeed['trackViewUrl'],
'feed_url' => $itunesFeed['feedUrl'],
'last_pub' => $lastPub,
'nb_episodes' => $itunesFeed['trackCount'],
];
}
}
}
} catch (\Exception $e) {
}
/**
* string[] $a
* string[] $b.
*/
usort($podcasts, fn (array $a, array $b) => $a['last_pub'] <=> $b['last_pub']);
$podcasts = array_intersect_key($podcasts, array_unique(array_map(fn (array $feed) => $feed['feed_url'], $podcasts)));
return new JSONResponse($podcasts); return new JSONResponse($podcasts);
} }
} }

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace OCA\RePod\Controller; namespace OCA\RePod\Controller;
use Exception;
use OCA\RePod\AppInfo\Application; use OCA\RePod\AppInfo\Application;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http; use OCP\AppFramework\Http;
@ -29,12 +28,13 @@ class TopController extends Controller
* @NoAdminRequired * @NoAdminRequired
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function index(int $count = 10): JSONResponse { public function index(int $count = 10): JSONResponse
{
$language = 'en'; $language = 'en';
try { try {
$langClient = $this->clientService->newClient(); $langClient = $this->clientService->newClient();
$langResponse = $langClient->get("https://api.fyyd.de/0.2/feature/podcast/hot/languages"); $langResponse = $langClient->get('https://api.fyyd.de/0.2/feature/podcast/hot/languages');
$langJson = (array) json_decode((string) $langResponse->getBody(), true, flags: JSON_THROW_ON_ERROR); $langJson = (array) json_decode((string) $langResponse->getBody(), true, flags: JSON_THROW_ON_ERROR);
if (array_key_exists('data', $langJson) && is_array($langJson['data'])) { if (array_key_exists('data', $langJson) && is_array($langJson['data'])) {
$language = $this->l10n->getUserLanguage($this->userSession->getUser()); $language = $this->l10n->getUserLanguage($this->userSession->getUser());
@ -42,20 +42,21 @@ class TopController extends Controller
$language = count($language) > 1 ? $language[1] : $language[0]; $language = count($language) > 1 ? $language[1] : $language[0];
$language = in_array($language, $langJson['data']) ? $language : 'en'; $language = in_array($language, $langJson['data']) ? $language : 'en';
} }
} catch (Exception $e) { } catch (\Exception $e) {
} }
try { try {
$podcastClient = $this->clientService->newClient(); $podcastClient = $this->clientService->newClient();
$podcastReponse = $podcastClient->get("https://api.fyyd.de/0.2/feature/podcast/hot", [ $podcastReponse = $podcastClient->get('https://api.fyyd.de/0.2/feature/podcast/hot', [
'query' => [ 'query' => [
'count' => $count, 'count' => $count,
'language' => $language 'language' => $language,
] ],
]); ]);
$podcastJson = (array) json_decode((string) $podcastReponse->getBody(), true, flags: JSON_THROW_ON_ERROR); $podcastJson = (array) json_decode((string) $podcastReponse->getBody(), true, flags: JSON_THROW_ON_ERROR);
return new JSONResponse($podcastJson, $podcastReponse->getStatusCode()); return new JSONResponse($podcastJson, $podcastReponse->getStatusCode());
} catch (Exception $e) { } catch (\Exception $e) {
return new JSONResponse([$e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR); return new JSONResponse([$e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
} }
} }