mirror of https://github.com/FreeTubeApp/FreeTube
add piped playlist support
This commit is contained in:
parent
5ef7627195
commit
17c7510f90
|
@ -1,8 +1,12 @@
|
||||||
|
import store from '../../store/index'
|
||||||
import { isNullOrEmpty, toLocalePublicationString } from '../utils'
|
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 = '' }) {
|
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)
|
return await fetch(requestUrl)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((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 = /^(?<baseUrl>.*)\/(?<imageProtocol>vi|ytc)\/(?<resource>[^?]*).*host=(?<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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import FtButton from '../../components/ft-button/ft-button.vue'
|
||||||
import { getLocalPlaylist, parseLocalPlaylistVideo } from '../../helpers/api/local'
|
import { getLocalPlaylist, parseLocalPlaylistVideo } from '../../helpers/api/local'
|
||||||
import { extractNumberFromString } from '../../helpers/utils'
|
import { extractNumberFromString } from '../../helpers/utils'
|
||||||
import { invidiousGetPlaylistInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious'
|
import { invidiousGetPlaylistInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious'
|
||||||
|
import { getPipedPlaylist, pipedImageToYouTube } from '../../helpers/api/piped'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Playlist',
|
name: 'Playlist',
|
||||||
components: {
|
components: {
|
||||||
|
@ -45,7 +45,8 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
backendPreference: function () {
|
backendPreference: function () {
|
||||||
return this.$store.getters.getBackendPreference
|
return 'piped'
|
||||||
|
// return this.$store.getters.getBackendPreference
|
||||||
},
|
},
|
||||||
backendFallback: function () {
|
backendFallback: function () {
|
||||||
return this.$store.getters.getBackendFallback
|
return this.$store.getters.getBackendFallback
|
||||||
|
@ -77,6 +78,9 @@ export default defineComponent({
|
||||||
case 'invidious':
|
case 'invidious':
|
||||||
this.getPlaylistInvidious()
|
this.getPlaylistInvidious()
|
||||||
break
|
break
|
||||||
|
case 'piped':
|
||||||
|
this.getPlaylistPiped()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getPlaylistLocal: function () {
|
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 () {
|
getNextPage: function () {
|
||||||
switch (this.infoData.infoSource) {
|
switch (this.infoData.infoSource) {
|
||||||
case 'local':
|
case 'local':
|
||||||
|
|
Loading…
Reference in New Issue