diff --git a/README.md b/README.md index 5ccded92460dd35f9421b71c2afe4757c1806a2d..eb53ac4a4b1d339e2fb609e33503ed0f859e9a1f 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ uses the directory [fyyd.de](https://fyyd.de) as a source. - [ ] Check newly released episodes - [x] Support for chapters in episodes - [x] Support for links and timecodes in episode notes +- [ ] Import and export subscriptions - [x] Mobile friendly interface - [x] Unified search integration - [ ] Dashboard integration diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 280dd578d30a7f468901ba4e5028a06d1ac73ddc..5a10766f12ba9a5c21e0b3148d2cce8f9af14a9a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -67,8 +67,6 @@ class Application extends App implements IBootstrap { public function registerCsp() { $manager = $this->getContainer()->getServer()->getContentSecurityPolicyManager(); $policy = new ContentSecurityPolicy(); - $policy->addAllowedConnectDomain('https://de1.api.radio-browser.info'); - $policy->addAllowedConnectDomain('https://api.fyyd.de'); $policy->addAllowedImageDomain('*'); $policy->addAllowedMediaDomain('*'); $manager->addDefaultPolicy($policy); diff --git a/lib/Controller/EpisodeController.php b/lib/Controller/EpisodeController.php index 1d40a892a96f2dcb6b77ad1ebe0e4462f9523d3d..e8f38184763b4a13f47f746ababca5176cc01b7b 100644 --- a/lib/Controller/EpisodeController.php +++ b/lib/Controller/EpisodeController.php @@ -25,14 +25,20 @@ namespace OCA\Podcast\Controller; use OCA\Podcast\AppInfo\Application; use OCA\Podcast\Service\EpisodeService; +use OCA\Podcast\Service\FyydApiService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; use OCP\IRequest; +use OCP\Http\Client\IClientService; + class EpisodeController extends Controller { /** @var EpisodesService */ private $service; + /** @var FyydApiService */ + private $fyydapi; + /** @var string */ private $userId; @@ -40,16 +46,26 @@ class EpisodeController extends Controller { public function __construct(IRequest $request, EpisodeService $service, + FyydApiService $fyydapi, $userId) { parent::__construct(Application::APP_ID, $request); $this->service = $service; + $this->fyydapi = $fyydapi; $this->userId = $userId; } /** * @NoAdminRequired */ - public function index(): DataResponse { + public function index(int $episode_id = null, int $podcast_id = null, + int $count = 20, int $page = 0): DataResponse { + + if ($episode_id) { + return new DataResponse($this->fyydapi->queryEpisode($episode_id)); + } else if ($podcast_id) { + return new DataResponse($this->fyydapi->queryEpisodes($podcast_id, $count, $page)); + } + return new DataResponse($this->service->findAll($this->userId)); } diff --git a/lib/Controller/ShowController.php b/lib/Controller/ShowController.php index fe956428938cda6cdad0ac3a6b18dfbfec5ccfbb..e917b447f109ee4712f5928463a03f49e08af934 100644 --- a/lib/Controller/ShowController.php +++ b/lib/Controller/ShowController.php @@ -25,6 +25,7 @@ namespace OCA\Podcast\Controller; use OCA\Podcast\AppInfo\Application; use OCA\Podcast\Service\ShowService; +use OCA\Podcast\Service\FyydApiService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; use OCP\IRequest; @@ -33,6 +34,9 @@ class ShowController extends Controller { /** @var ShowsService */ private $service; + /** @var FyydApiService */ + private $fyydapi; + /** @var string */ private $userId; @@ -40,16 +44,27 @@ class ShowController extends Controller { public function __construct(IRequest $request, ShowService $service, + FyydApiService $fyydapi, $userId) { parent::__construct(Application::APP_ID, $request); $this->service = $service; + $this->fyydapi = $fyydapi; $this->userId = $userId; } /** * @NoAdminRequired */ - public function index(): DataResponse { + public function index(int $podcast_id = null, string $category = null, + int $count = 20, int $page = 0): DataResponse { + + if ($category) { + return new DataResponse($this->fyydapi->queryCategory($category, $count, + $page)); + } else if ($podcast_id) { + return new DataResponse($this->fyydapi->queryPodcast($podcast_id)); + } + return new DataResponse($this->service->findAll($this->userId)); } diff --git a/package.json b/package.json index fca2a21538fb9ef1edd1b8ddb427c61c9bc606f1..400a9ba0dce7edf09156592523bb18335426abba 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "stylelint:fix": "stylelint src --fix" }, "dependencies": { - "@nextcloud/auth": "^1.3.0", "@nextcloud/axios": "^1.6.0", "@nextcloud/dialogs": "^3.1.1", "@nextcloud/l10n": "^1.4.1", diff --git a/src/services/EpisodeApi.js b/src/services/EpisodeApi.js index 63338133fa953e9c20c2f5ea6b46fa71091b868a..d4170bef364543ef6a8e862d4296e53fb452c0af 100644 --- a/src/services/EpisodeApi.js +++ b/src/services/EpisodeApi.js @@ -22,7 +22,6 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' -import { getRequestToken } from '@nextcloud/auth' export class EpisodeApi { @@ -44,7 +43,6 @@ export class EpisodeApi { description: episode.description, podcast_id: episode.podcast_id, } - axios.defaults.headers.requesttoken = getRequestToken() return axios.post(this.url('/episodes'), episode) .then( (response) => { @@ -60,7 +58,6 @@ export class EpisodeApi { } removeEpisode(episode) { - axios.defaults.headers.requesttoken = getRequestToken() return axios.delete(this.url(`/episodes/${episode.id}`)) .then( (response) => { @@ -76,7 +73,6 @@ export class EpisodeApi { } loadEpisodes(episode) { - axios.defaults.headers.requesttoken = getRequestToken() return axios.get(this.url('/episodes')) .then( (response) => { @@ -91,6 +87,47 @@ export class EpisodeApi { }) } + queryEpisodes(podcastId, page = 0) { + return axios.get(this.url('/episodes'), { + params: { + podcast_id: podcastId, + count: 20, + page, + }, + }) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + } + + queryEpisode(episodeId) { + return axios.get(this.url('/episodes'), { + params: { + episode_id: episodeId, + }, + }) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + + } + updateEpisode({ episode, playtime } = {}) { episode = { id: episode.id, @@ -104,7 +141,6 @@ export class EpisodeApi { description: episode.description, podcast_id: episode.podcast_id, } - axios.defaults.headers.requesttoken = getRequestToken() return axios.put(this.url(`/episodes/${episode.id}`), episode) .then( (response) => { diff --git a/src/services/FyydApi.js b/src/services/FyydApi.js deleted file mode 100644 index dd4e69748458578f5e85dd9c0142c6a208017b44..0000000000000000000000000000000000000000 --- a/src/services/FyydApi.js +++ /dev/null @@ -1,133 +0,0 @@ -/* - * @copyright Copyright (c) 2021 Jonas Heinrich <onny@project-insanity.org> - * - * @author Jonas Heinrich <onny@project-insanity.org> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -import axios from '@nextcloud/axios' - -export class FyydApi { - - url() { - const url = 'https://api.fyyd.de/0.2' - return url - } - - queryPodcast(podcastId) { - - delete axios.defaults.headers.requesttoken - return axios.get(this.url() + '/podcast', { - params: { - podcast_id: podcastId, - }, - }) - .then( - (response) => { - return Promise.resolve(response.data) - }, - (err) => { - return Promise.reject(err) - } - ) - .catch((err) => { - return Promise.reject(err) - }) - - } - - queryEpisodes(podcastId, page) { - - delete axios.defaults.headers.requesttoken - return axios.get(this.url() + '/podcast/episodes', { - params: { - podcast_id: podcastId, - count: 20, - page, - }, - }) - .then( - (response) => { - return Promise.resolve(response.data) - }, - (err) => { - return Promise.reject(err) - } - ) - .catch((err) => { - return Promise.reject(err) - }) - - } - - queryEpisode(episodeId) { - - delete axios.defaults.headers.requesttoken - return axios.get(this.url() + '/episode', { - params: { - episode_id: episodeId, - }, - }) - .then( - (response) => { - return Promise.resolve(response.data) - }, - (err) => { - return Promise.reject(err) - } - ) - .catch((err) => { - return Promise.reject(err) - }) - - } - - queryList(listName, count = 20, page = 0) { - - delete axios.defaults.headers.requesttoken - let queryURL = '' - - if (listName === 'hot') { - queryURL = this.url() + '/feature/podcast/hot' - } else if (listName === 'latest') { - queryURL = this.url() + '/podcast/latest' - } else { - queryURL = this.url() + '/category?category_id=' + listName - } - - return axios.get(queryURL, { - params: { - count, - page, - }, - }) - .then( - (response) => { - return Promise.resolve(response.data) - }, - (err) => { - return Promise.reject(err) - } - ) - .catch((err) => { - return Promise.reject(err) - }) - - } - -} diff --git a/src/services/ShowApi.js b/src/services/ShowApi.js index 09c62b3f00be37f556158b221e4e97e467add313..e2767375434ecffa02badbb79e257b6d9e192e2e 100644 --- a/src/services/ShowApi.js +++ b/src/services/ShowApi.js @@ -22,7 +22,6 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' -import { getRequestToken } from '@nextcloud/auth' const categories = require('../assets/categories.json') @@ -44,7 +43,6 @@ export class ShowApi { homepage: show.htmlURL, feedurl: show.xmlURL, } - axios.defaults.headers.requesttoken = getRequestToken() return axios.post(this.url('/shows'), show) .then( (response) => { @@ -60,7 +58,6 @@ export class ShowApi { } removeShow(show) { - axios.defaults.headers.requesttoken = getRequestToken() return axios.delete(this.url(`/shows/${show.id}`)) .then( (response) => { @@ -76,7 +73,6 @@ export class ShowApi { } loadShows(show) { - axios.defaults.headers.requesttoken = getRequestToken() return axios.get(this.url('/shows')) .then( (response) => { @@ -91,6 +87,50 @@ export class ShowApi { }) } + queryShow(podcastId) { + + return axios.get(this.url('/shows'), { + params: { + podcast_id: podcastId, + }, + }) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + + } + + queryCategory(category, count = 20, page = 0) { + + return axios.get(this.url('/shows'), { + params: { + category, + count, + page, + }, + }) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + + } + getCategoryName(categoryid) { for (let i = 0; i < categories.data.length; i++) { const obj = categories.data[i] diff --git a/src/store/player.js b/src/store/player.js index 509fdf3ccadec4be10115c0f8a4cefbe018b6692..1a35e993933175ff9f515a59541b571489a631c7 100644 --- a/src/store/player.js +++ b/src/store/player.js @@ -21,10 +21,10 @@ */ import { Player } from './../services/Player' -import { FyydApi } from './../services/FyydApi' +import { ShowApi } from './../services/ShowApi' const player = new Player() -const fyydClient = new FyydApi() +const showApiClient = new ShowApi() export default { state: { @@ -208,7 +208,7 @@ export default { }, async setPodcastName(context, podcastId) { - const podcast = await fyydClient.queryPodcast(podcastId) + const podcast = await showApiClient.queryShow(podcastId) context.commit('setPodcastName', podcast.data.title) }, }, diff --git a/src/views/Browse.vue b/src/views/Browse.vue index d0540143a0fdb9a4588c238c1e92a405c670ff4b..b6977c114542afaad2d4c62318052d77d0815f80 100644 --- a/src/views/Browse.vue +++ b/src/views/Browse.vue @@ -41,8 +41,8 @@ import BrowseEmpty from './placeholder/Browse' import ItemSlider from '../components/ItemSlider' import { setBrowserTitle } from '../utils/misc.js' -import { FyydApi } from './../services/FyydApi' -const fyydClient = new FyydApi() +import { ShowApi } from './../services/ShowApi' +const showApiClient = new ShowApi() export default { name: 'Browse', @@ -63,9 +63,9 @@ export default { async queryPodcastLists() { - const hotList = await fyydClient.queryList('hot', 10) + const hotList = await showApiClient.queryCategory('hot', 10) this.podcastsHot = hotList.data - const latestList = await fyydClient.queryList('latest', 10) + const latestList = await showApiClient.queryCategory('latest', 10) this.podcastsLatest = latestList.data this.loading = false diff --git a/src/views/BrowseAll.vue b/src/views/BrowseAll.vue index f986cd1f0bc1895cb1a6379a32f98ab68b4a8d06..20bd4a5efe6aa3d953a9115bf190a42aaef469b0 100644 --- a/src/views/BrowseAll.vue +++ b/src/views/BrowseAll.vue @@ -36,10 +36,10 @@ import ItemGrid from '../components/ItemGrid' import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent' import { setBrowserTitle } from '../utils/misc.js' -import { FyydApi } from './../services/FyydApi' +import { ShowApi } from './../services/ShowApi' import resize from 'vue-resize-directive' -const fyydClient = new FyydApi() +const showApiClient = new ShowApi() export default { name: 'BrowseAll', @@ -72,17 +72,17 @@ export default { let podcasts = null if (this.category === 'hot') { - podcasts = await fyydClient.queryList('hot', 20, page) + podcasts = await showApiClient.queryCategory('hot', 20, page) this.title = t('podcast', 'Hot podcasts') this.podcasts = this.podcasts.concat(podcasts.data) this.page += 1 } else if (this.category === 'new') { - podcasts = await fyydClient.queryList('latest', 20, page) + podcasts = await showApiClient.queryCategory('latest', 20, page) this.title = t('podcast', 'New podcasts') this.podcasts = this.podcasts.concat(podcasts.data) this.page += 1 } else { - podcasts = await fyydClient.queryList(this.categoryId, 20, page) + podcasts = await showApiClient.queryCategory(this.categoryId, 20, page) this.title = t('podcast', 'Podcasts in') + ' ' + podcasts.data.category.title this.podcasts = this.podcasts.concat(podcasts.data.podcasts) if (podcasts.meta.paging.next_page === null) { diff --git a/src/views/Episode.vue b/src/views/Episode.vue index 8263264afeb787d4e7e5577afa1ea93b889363ec..e599d297a7b6e2dc782a6b9011d4f8726456dbc2 100644 --- a/src/views/Episode.vue +++ b/src/views/Episode.vue @@ -93,12 +93,12 @@ import MediaHeader from '../components/MediaHeader' import { mapGetters, mapActions } from 'vuex' import TimeAgo from 'javascript-time-ago' import PlayAnimation from '../components/PlayAnimation' - -import { FyydApi } from './../services/FyydApi' - import { setBrowserTitle } from '../utils/misc.js' -const fyydClient = new FyydApi() +import { EpisodeApi } from './../services/EpisodeApi' +import { ShowApi } from './../services/ShowApi' +const episodeApiClient = new EpisodeApi() +const showApiClient = new ShowApi() const timeAgo = new TimeAgo('en-US') @@ -242,7 +242,7 @@ export default { }, async queryEpisode(episodeId) { - const episode = await fyydClient.queryEpisode(episodeId) + const episode = await episodeApiClient.queryEpisode(episodeId) this.processEpisode(episode) }, @@ -253,7 +253,7 @@ export default { }, async queryPodcastName(podcastId) { - const podcast = await fyydClient.queryPodcast(podcastId) + const podcast = await showApiClient.queryShow(podcastId) this.podcastName = podcast.data.title }, diff --git a/src/views/Show.vue b/src/views/Show.vue index 7f813db978a55f558a0c2aff530a8f881666ed0f..e348d5a528cc5f39e00cd49cb84ff5a33eb8620c 100644 --- a/src/views/Show.vue +++ b/src/views/Show.vue @@ -53,11 +53,13 @@ import MediaHeader from '../components/MediaHeader' import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent' import ShowEmpty from './placeholder/Show' import { mapGetters, mapActions } from 'vuex' -import { FyydApi } from './../services/FyydApi' import { setBrowserTitle } from '../utils/misc.js' import resize from 'vue-resize-directive' -const fyydClient = new FyydApi() +import { ShowApi } from './../services/ShowApi' +import { EpisodeApi } from './../services/EpisodeApi' +const showApiClient = new ShowApi() +const episodeApiClient = new EpisodeApi() export default { name: 'Show', @@ -110,7 +112,7 @@ export default { this.page = 0 this.podcastId = this.$route.params.id document.getElementById('app-content-vue').addEventListener('scroll', this.handleScroll) - this.queryPodcast(this.podcastId) + this.queryShow(this.podcastId) this.queryEpisodes(this.podcastId, this.page) }, @@ -130,8 +132,8 @@ export default { } }, - async queryPodcast(podcastId) { - const podcast = await fyydClient.queryPodcast(podcastId) + async queryShow(podcastId) { + const podcast = await showApiClient.queryShow(podcastId) this.processPodcast(podcast.data) }, @@ -142,7 +144,7 @@ export default { }, async queryEpisodes(podcastId, page) { - const episodes = await fyydClient.queryEpisodes(podcastId, page) + const episodes = await episodeApiClient.queryEpisodes(podcastId, page) this.episodes = this.episodes.concat(episodes.data.episodes) if (episodes.meta.paging.next_page === null) { this.page = null