Refacto API to be pseudo compatible with gpodder
This commit is contained in:
parent
6d6f8b4cf7
commit
098db9f09e
@ -13,7 +13,7 @@ declare(strict_types=1);
|
||||
return [
|
||||
'routes' => [
|
||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'top#index', 'url' => '/top', 'verb' => 'GET'],
|
||||
['name' => 'toplist#index', 'url' => '/toplist/{count}', 'verb' => 'GET'],
|
||||
['name' => 'search#index', 'url' => '/search/{value}', 'verb' => 'GET'],
|
||||
],
|
||||
];
|
||||
|
@ -5,7 +5,7 @@
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"require-dev": {
|
||||
"nextcloud/ocp": "^27.0.1",
|
||||
"psalm/phar": "^5.13.1",
|
||||
"psalm/phar": "^5.14.1",
|
||||
"nextcloud/coding-standard": "^1.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
2
composer.lock
generated
2
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "a5d69457fcb9b9b73dd75bcd2b7c9791",
|
||||
"content-hash": "817269c30922145fbaf4270b2cb22d8e",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
|
@ -36,8 +36,8 @@ class SearchController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
usort($podcasts, fn (array $a, array $b) => new \DateTime((string) $b['last_pub']) <=> new \DateTime((string) $a['last_pub']));
|
||||
$podcasts = array_intersect_key($podcasts, array_unique(array_map(fn (array $feed) => $feed['feed_url'], $podcasts)));
|
||||
usort($podcasts, fn (array $a, array $b) => new \DateTime((string) $b['lastpub']) <=> new \DateTime((string) $a['lastpub']));
|
||||
$podcasts = array_intersect_key($podcasts, array_unique(array_map(fn (array $feed) => $feed['url'], $podcasts)));
|
||||
|
||||
return new JSONResponse($podcasts);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
class TopController extends Controller
|
||||
class ToplistController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
@ -27,10 +27,7 @@ class TopController extends Controller
|
||||
public function index(): JSONResponse
|
||||
{
|
||||
try {
|
||||
$response = $this->fyydService->hot();
|
||||
$json = (array) json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR);
|
||||
|
||||
return new JSONResponse($json, $response->getStatusCode());
|
||||
return new JSONResponse($this->fyydService->hot());
|
||||
} catch (\Exception $e) {
|
||||
return new JSONResponse([$e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
@ -5,11 +5,13 @@ declare(strict_types=1);
|
||||
namespace OCA\RePod\Service;
|
||||
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\Http\Client\IResponse;
|
||||
use OCP\IUserSession;
|
||||
use OCP\L10N\IFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @psalm-import-type Podcast from IProvider
|
||||
*/
|
||||
class FyydService implements IProvider
|
||||
{
|
||||
private const BASE_URL = 'https://api.fyyd.de/0.2/';
|
||||
@ -41,15 +43,18 @@ class FyydService implements IProvider
|
||||
/** @var string[] $feed */
|
||||
foreach ($json['data'] as $feed) {
|
||||
$podcasts[] = [
|
||||
'provider' => 'fyyd',
|
||||
'id' => $feed['id'],
|
||||
'provider' => 'fyyd',
|
||||
'website' => $feed['htmlURL'],
|
||||
'description' => $feed['description'],
|
||||
'title' => $feed['title'],
|
||||
'author' => $feed['author'],
|
||||
'image' => $feed['imgURL'],
|
||||
'provider_url' => $feed['htmlURL'],
|
||||
'feed_url' => $feed['xmlURL'],
|
||||
'last_pub' => $feed['lastpub'],
|
||||
'nb_episodes' => $feed['episode_count'],
|
||||
'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'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -57,8 +62,12 @@ class FyydService implements IProvider
|
||||
return $podcasts;
|
||||
}
|
||||
|
||||
public function hot(): IResponse
|
||||
/**
|
||||
* @return Podcast[]
|
||||
*/
|
||||
public function hot(int $count = 10): array
|
||||
{
|
||||
$podcasts = [];
|
||||
$language = 'en';
|
||||
$userLang = $this->userService->getLangCode();
|
||||
|
||||
@ -75,10 +84,34 @@ class FyydService implements IProvider
|
||||
|
||||
$podcastClient = $this->clientService->newClient();
|
||||
|
||||
return $podcastClient->get(self::BASE_URL.'feature/podcast/hot', [
|
||||
$podcastResponse = $podcastClient->get(self::BASE_URL.'feature/podcast/hot', [
|
||||
'query' => [
|
||||
'count' => $count,
|
||||
'language' => $language,
|
||||
],
|
||||
]);
|
||||
$postCastJson = (array) json_decode((string) $podcastResponse->getBody(), true, flags: JSON_THROW_ON_ERROR);
|
||||
|
||||
if (array_key_exists('data', $postCastJson) && is_array($postCastJson['data'])) {
|
||||
/** @var string[] $feed */
|
||||
foreach ($postCastJson['data'] as $feed) {
|
||||
$podcasts[] = [
|
||||
'id' => $feed['id'],
|
||||
'provider' => 'fyyd',
|
||||
'website' => $feed['htmlURL'],
|
||||
'description' => $feed['description'],
|
||||
'title' => $feed['title'],
|
||||
'author' => $feed['author'],
|
||||
'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'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $podcasts;
|
||||
}
|
||||
}
|
||||
|
@ -4,20 +4,26 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\Service;
|
||||
|
||||
/**
|
||||
* @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
|
||||
{
|
||||
/**
|
||||
* @return array<array{
|
||||
* provider: string,
|
||||
* id: string,
|
||||
* title: string,
|
||||
* author: string,
|
||||
* image: string,
|
||||
* provider_url: string,
|
||||
* feed_url: string,
|
||||
* last_pub: string,
|
||||
* nb_episodes: string
|
||||
* }>
|
||||
* @return Podcast[]
|
||||
*/
|
||||
public function search(string $value): array;
|
||||
}
|
||||
|
@ -34,15 +34,18 @@ class ItunesService implements IProvider
|
||||
/** @var string[] $feed */
|
||||
foreach ($json['results'] as $feed) {
|
||||
$podcasts[] = [
|
||||
'provider' => 'itunes',
|
||||
'id' => $feed['id'],
|
||||
'provider' => 'itunes',
|
||||
'website' => $feed['trackViewUrl'],
|
||||
'description' => $feed['primaryGenreName'],
|
||||
'title' => $feed['trackName'],
|
||||
'author' => $feed['artistName'],
|
||||
'image' => $feed['artworkUrl600'],
|
||||
'provider_url' => $feed['trackViewUrl'],
|
||||
'feed_url' => $feed['feedUrl'],
|
||||
'last_pub' => $feed['releaseDate'],
|
||||
'nb_episodes' => $feed['trackCount'],
|
||||
'url' => $feed['feedUrl'],
|
||||
'position_last_week' => null,
|
||||
'mygpo_link' => $feed['trackViewUrl'],
|
||||
'logo_url' => $feed['artworkUrl600'],
|
||||
'lastpub' => $feed['releaseDate'],
|
||||
'episode_count' => $feed['trackCount'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
6302
package-lock.json
generated
6302
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@
|
||||
"@nextcloud/babel-config": "^1.0.0",
|
||||
"@nextcloud/browserslist-config": "^2.3.0",
|
||||
"@nextcloud/eslint-config": "^8.2.1",
|
||||
"@nextcloud/stylelint-config": "^2.3.0",
|
||||
"@nextcloud/stylelint-config": "^2.3.1",
|
||||
"@nextcloud/webpack-vue-config": "^5.5.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<NcAppNavigationItem :loading="loading"
|
||||
:title="feed ? feed.title : subscriptionUrl"
|
||||
:to="`/${subscriptionUrl}`">
|
||||
:title="feed ? feed.title : url"
|
||||
:to="`/${url}`">
|
||||
<template #icon>
|
||||
<NcAvatar v-if="feed"
|
||||
:display-name="feed.author"
|
||||
@ -29,7 +29,7 @@ import { generateUrl } from '@nextcloud/router'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
|
||||
export default {
|
||||
name: 'SubscriptionListItem',
|
||||
name: 'FeedListItem',
|
||||
components: {
|
||||
Alert,
|
||||
Delete,
|
||||
@ -38,7 +38,7 @@ export default {
|
||||
NcAvatar,
|
||||
},
|
||||
props: {
|
||||
subscriptionUrl: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
@ -52,7 +52,7 @@ export default {
|
||||
},
|
||||
async mounted() {
|
||||
try {
|
||||
const podcastData = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/podcast_data?url={url}', { url: this.subscriptionUrl }))
|
||||
const podcastData = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/podcast_data?url={url}', { url: this.url }))
|
||||
this.feed = podcastData.data.data
|
||||
} catch (e) {
|
||||
this.failed = true
|
||||
@ -65,7 +65,7 @@ export default {
|
||||
async deleteSubscription() {
|
||||
try {
|
||||
this.loading = true
|
||||
await axios.post(generateUrl('/apps/gpoddersync/subscription_change/create'), { add: [], remove: [this.subscriptionUrl] })
|
||||
await axios.post(generateUrl('/apps/gpoddersync/subscription_change/create'), { add: [], remove: [this.url] })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
showError(t('Error while removing the feed'))
|
@ -2,14 +2,14 @@
|
||||
<ul>
|
||||
<NcListItem v-for="feed in feeds"
|
||||
:key="`${feed.provider}_${feed.id}`"
|
||||
:counter-number="feed.nb_episodes"
|
||||
:details="formatTimeAgo(new Date(feed.last_pub))"
|
||||
:counter-number="feed.episode_count"
|
||||
:details="formatTimeAgo(new Date(feed.lastpub))"
|
||||
:title="feed.title"
|
||||
:to="`/${feed.feed_url}`">
|
||||
:to="`/${feed.url}`">
|
||||
<template #icon>
|
||||
<NcAvatar :display-name="feed.author"
|
||||
:is-no-user="true"
|
||||
:url="feed.image" />
|
||||
:url="feed.logo_url" />
|
||||
</template>
|
||||
<template #subtitle>
|
||||
{{ feed.author }}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<a @click="addSubscription">
|
||||
<img :alt="author"
|
||||
:src="imgUrl"
|
||||
<img :alt="`${title} - ${author}`"
|
||||
:src="logo"
|
||||
:title="author">
|
||||
</a>
|
||||
</template>
|
||||
@ -15,23 +15,27 @@ export default {
|
||||
name: 'TopItem',
|
||||
components: {},
|
||||
props: {
|
||||
xmlUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
imgUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
author: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
logo: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async addSubscription() {
|
||||
try {
|
||||
await axios.post(generateUrl('/apps/gpoddersync/subscription_change/create'), { add: [this.xmlUrl], remove: [] })
|
||||
await axios.post(generateUrl('/apps/gpoddersync/subscription_change/create'), { add: [this.url], remove: [] })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
showError(t('Error while adding the feed'))
|
||||
|
@ -8,8 +8,9 @@
|
||||
<ul v-if="!loading" class="tops">
|
||||
<li v-for="top in tops" :key="top.id">
|
||||
<TopItem :author="top.author"
|
||||
:img-url="top.imgURL"
|
||||
:xml-url="top.xmlURL" />
|
||||
:logo="top.logo_url"
|
||||
:title="top.title"
|
||||
:url="top.url" />
|
||||
</li>
|
||||
</ul>
|
||||
<span class="caption">{{ t('Suggests by fyyd') }}</span>
|
||||
@ -39,8 +40,8 @@ export default {
|
||||
async mounted() {
|
||||
try {
|
||||
this.loading = true
|
||||
const top = await axios.get(generateUrl('/apps/repod/top'))
|
||||
this.tops = top.data.data
|
||||
const toplist = await axios.get(generateUrl('/apps/repod/toplist/10'))
|
||||
this.tops = toplist.data
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
showError(t('Could not fetch tops'))
|
||||
|
@ -11,9 +11,9 @@
|
||||
</router-link>
|
||||
<NcLoadingIcon v-if="loading" />
|
||||
<ul v-if="!loading">
|
||||
<SubscriptionListItem v-for="subscriptionUrl of subscriptions"
|
||||
<FeedListItem v-for="subscriptionUrl of subscriptions"
|
||||
:key="subscriptionUrl"
|
||||
:subscription-url="subscriptionUrl" />
|
||||
:url="subscriptionUrl" />
|
||||
</ul>
|
||||
</NcAppContentList>
|
||||
</NcAppNavigation>
|
||||
@ -31,20 +31,20 @@ import {
|
||||
NcAppNavigationNew,
|
||||
NcLoadingIcon,
|
||||
} from '@nextcloud/vue'
|
||||
import FeedListItem from '../components/FeedListItem.vue'
|
||||
import Plus from 'vue-material-design-icons/Plus.vue'
|
||||
import SubscriptionListItem from '../components/SubscriptionListItem.vue'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
FeedListItem,
|
||||
NcAppContent,
|
||||
NcAppContentList,
|
||||
NcAppNavigation,
|
||||
NcAppNavigationNew,
|
||||
NcLoadingIcon,
|
||||
Plus,
|
||||
SubscriptionListItem,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
Loading…
Reference in New Issue
Block a user