diff --git a/src/renderer/helpers/api/piped.js b/src/renderer/helpers/api/piped.js index 4aa87330f..c36c6a06c 100644 --- a/src/renderer/helpers/api/piped.js +++ b/src/renderer/helpers/api/piped.js @@ -1,8 +1,12 @@ +import store from '../../store/index' import { isNullOrEmpty, toLocalePublicationString } from '../utils' -const apiUrl = 'https://pipedapi.kavin.rocks' + +function getCurrentInstance() { + return store.getters.getCurrentPipedInstance +} export async function pipedRequest({ resource, id = '', params = {}, doLogError = true, subResource = '' }) { - const requestUrl = apiUrl + '/' + resource + '/' + id + (!isNullOrEmpty(subResource) ? `/${subResource}` : '') + '?' + new URLSearchParams(params).toString() + const requestUrl = getCurrentInstance() + '/' + resource + '/' + id + (!isNullOrEmpty(subResource) ? `/${subResource}` : '') + '?' + new URLSearchParams(params).toString() return await fetch(requestUrl) .then((response) => response.json()) .then((json) => { @@ -67,3 +71,54 @@ function parsePipedComments(comments) { } }) } + +export async function getPipedPlaylist(playlistId) { + const pList = await pipedRequest({ resource: 'playlists', id: playlistId }) + console.error(pList) + const parsedVideos = parsePipedVideos(pList.relatedStreams) + return { + playlist: parsePipedPlaylist(playlistId, pList, parsedVideos), + videos: parsedVideos + } +} + +export function getPipedUrlInfo(url) { + const regex = /^(?.*)\/(?vi|ytc)\/(?[^?]*).*host=(?[^&]*)/ + return url.match(regex).groups +} + +export function pipedImageToYouTube(url) { + const { host, imageProtocol, resource } = getPipedUrlInfo(url) + return `https://${host}/${imageProtocol}/${resource}` +} + +function parsePipedPlaylist(playlistId, result, parsedVideos) { + return { + id: playlistId, + title: result.name, + description: '', + firstVideoId: parsedVideos[0].videoId, + viewCount: null, + videoCount: result.videos, + channelName: result.uploader, + channelThumbnail: result.uploaderAvatar, + channelId: result.uploaderUrl.replace('/channel/', ''), + infoSource: 'piped' + } +} + +function parsePipedVideos(videoList) { + return videoList.map(video => { + return { + videoId: video.url.replace('/watch?v=', ''), + title: video.title, + author: video.uploaderName, + authorId: video.uploaderUrl.replace('/channel/', ''), + lengthSeconds: video.duration, + description: video.shortDescription, + uploaded: video.uploaded, // uploaded time stamp + viewCount: video.views, + thumbnail: video.thumbnail + } + }) +} diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js index 8551c4f27..c828ee757 100644 --- a/src/renderer/views/Playlist/Playlist.js +++ b/src/renderer/views/Playlist/Playlist.js @@ -9,7 +9,7 @@ import FtButton from '../../components/ft-button/ft-button.vue' import { getLocalPlaylist, parseLocalPlaylistVideo } from '../../helpers/api/local' import { extractNumberFromString } from '../../helpers/utils' import { invidiousGetPlaylistInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious' - +import { getPipedPlaylist, pipedImageToYouTube } from '../../helpers/api/piped' export default defineComponent({ name: 'Playlist', components: { @@ -45,7 +45,8 @@ export default defineComponent({ }, computed: { backendPreference: function () { - return this.$store.getters.getBackendPreference + return 'piped' + // return this.$store.getters.getBackendPreference }, backendFallback: function () { return this.$store.getters.getBackendFallback @@ -77,6 +78,9 @@ export default defineComponent({ case 'invidious': this.getPlaylistInvidious() break + case 'piped': + this.getPlaylistPiped() + break } }, getPlaylistLocal: function () { @@ -162,6 +166,21 @@ export default defineComponent({ }) }, + getPlaylistPiped: async function () { + this.isLoading = true + const { playlist, videos } = await getPipedPlaylist(this.playlistId) + this.infoData = playlist + + this.playlistItems = this.playlistItems.concat(videos) + + this.updateSubscriptionDetails({ + channelThumbnailUrl: pipedImageToYouTube(playlist.channelThumbnail), + channelName: playlist.channelName, + channelId: playlist.channelId + }) + this.isLoading = false + }, + getNextPage: function () { switch (this.infoData.infoSource) { case 'local':