diff --git a/src/main/index.js b/src/main/index.js index b911fef6f67a..6bdff568c470 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -457,7 +457,7 @@ function runApp() { darkTheme: nativeTheme.shouldUseDarkColors, icon: process.env.NODE_ENV === 'development' ? path.join(__dirname, '../../_icons/iconColor.png') - /* eslint-disable-next-line */ + /* eslint-disable-next-line n/no-path-concat */ : `${__dirname}/_icons/iconColor.png`, autoHideMenuBar: true, // useContentSize: true, @@ -548,7 +548,7 @@ function runApp() { if (windowStartupUrl != null) { newWindow.loadURL(windowStartupUrl) } else { - /* eslint-disable-next-line */ + /* eslint-disable-next-line n/no-path-concat */ newWindow.loadFile(`${__dirname}/index.html`) } } diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js index 854c762d30ec..ca61126f3eed 100644 --- a/src/renderer/components/data-settings/data-settings.js +++ b/src/renderer/components/data-settings/data-settings.js @@ -16,6 +16,7 @@ import { showToast, writeFileFromDialog } from '../../helpers/utils' +import { invidiousAPICall } from '../../helpers/api/invidious' export default Vue.extend({ name: 'DataSettings', @@ -1018,7 +1019,7 @@ export default Vue.extend({ params: {} } - this.invidiousAPICall(subscriptionsPayload).then((response) => { + invidiousAPICall(subscriptionsPayload).then((response) => { resolve(response) }).catch((err) => { console.error(err) @@ -1116,7 +1117,6 @@ export default Vue.extend({ }, ...mapActions([ - 'invidiousAPICall', 'updateProfile', 'compactProfiles', 'updateShowProgressBar', diff --git a/src/renderer/components/ft-list-channel/ft-list-channel.js b/src/renderer/components/ft-list-channel/ft-list-channel.js index 31de269b672c..4ea0bec01220 100644 --- a/src/renderer/components/ft-list-channel/ft-list-channel.js +++ b/src/renderer/components/ft-list-channel/ft-list-channel.js @@ -1,5 +1,6 @@ import Vue from 'vue' import i18n from '../../i18n/index' +import { youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'FtListChannel', @@ -76,14 +77,9 @@ export default Vue.extend({ parseInvidiousData: function () { // Can be prefixed with `https://` or `//` (protocol relative) - let thumbnailUrl = this.data.authorThumbnails[2].url + const thumbnailUrl = this.data.authorThumbnails[2].url - // Update protocol relative URL to be prefixed with `https://` - if (thumbnailUrl.startsWith('//')) { - thumbnailUrl = `https:${thumbnailUrl}` - } - - this.thumbnail = thumbnailUrl.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + this.thumbnail = youtubeImageUrlToInvidious(thumbnailUrl, this.currentInvidiousInstance) this.channelName = this.data.author this.id = this.data.authorId diff --git a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js index 89bf80e65ecc..9d0483041679 100644 --- a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js +++ b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js @@ -7,6 +7,7 @@ import FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubbl import FtButton from '../../components/ft-button/ft-button.vue' import FtPrompt from '../../components/ft-prompt/ft-prompt.vue' import { showToast } from '../../helpers/utils' +import { youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'FtProfileChannelList', @@ -80,7 +81,7 @@ export default Vue.extend({ return 0 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + channel.thumbnail = youtubeImageUrlToInvidious(channel.thumbnail, this.currentInvidiousInstance) } channel.selected = false return channel @@ -101,7 +102,7 @@ export default Vue.extend({ return 0 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + channel.thumbnail = youtubeImageUrlToInvidious(channel.thumbnail, this.currentInvidiousInstance) } channel.selected = false return channel diff --git a/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js b/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js index 7ae4cdcf7128..2e4cea562385 100644 --- a/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js +++ b/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js @@ -7,6 +7,7 @@ import FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubbl import FtButton from '../../components/ft-button/ft-button.vue' import FtSelect from '../ft-select/ft-select.vue' import { showToast } from '../../helpers/utils' +import { youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'FtProfileFilterChannelsList', @@ -71,7 +72,7 @@ export default Vue.extend({ return index === -1 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + channel.thumbnail = youtubeImageUrlToInvidious(channel.thumbnail, this.currentInvidiousInstance) } channel.selected = false return channel @@ -98,7 +99,7 @@ export default Vue.extend({ return index === -1 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + channel.thumbnail = youtubeImageUrlToInvidious(channel.thumbnail, this.currentInvidiousInstance) } channel.selected = false return channel diff --git a/src/renderer/components/side-nav/side-nav.js b/src/renderer/components/side-nav/side-nav.js index 7c7be13ef65c..b9940b4a0372 100644 --- a/src/renderer/components/side-nav/side-nav.js +++ b/src/renderer/components/side-nav/side-nav.js @@ -1,6 +1,7 @@ import Vue from 'vue' import FtFlexBox from '../ft-flex-box/ft-flex-box.vue' import SideNavMoreOptions from '../side-nav-more-options/side-nav-more-options.vue' +import { youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'SideNav', @@ -41,7 +42,7 @@ export default Vue.extend({ return 0 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + channel.thumbnail = youtubeImageUrlToInvidious(channel.thumbnail, this.currentInvidiousInstance) } return channel diff --git a/src/renderer/components/top-nav/top-nav.js b/src/renderer/components/top-nav/top-nav.js index d948f0d19e97..90026ea8db15 100644 --- a/src/renderer/components/top-nav/top-nav.js +++ b/src/renderer/components/top-nav/top-nav.js @@ -8,6 +8,7 @@ import debounce from 'lodash.debounce' import { IpcChannels } from '../../../constants' import { openInternalPath, showToast } from '../../helpers/utils' import { clearLocalSearchSuggestionsSession, getLocalSearchSuggestions } from '../../helpers/api/local' +import { invidiousAPICall } from '../../helpers/api/invidious' export default Vue.extend({ name: 'TopNav', @@ -257,7 +258,7 @@ export default Vue.extend({ } } - this.invidiousAPICall(searchPayload).then((results) => { + invidiousAPICall(searchPayload).then((results) => { this.searchSuggestionsDataList = results.suggestions }).catch((err) => { console.error(err) @@ -339,7 +340,6 @@ export default Vue.extend({ }, ...mapActions([ 'getYoutubeUrlInfo', - 'invidiousAPICall' ]) } }) diff --git a/src/renderer/components/watch-video-comments/watch-video-comments.js b/src/renderer/components/watch-video-comments/watch-video-comments.js index dcc517637e76..b79d2f7accca 100644 --- a/src/renderer/components/watch-video-comments/watch-video-comments.js +++ b/src/renderer/components/watch-video-comments/watch-video-comments.js @@ -1,5 +1,4 @@ import Vue from 'vue' -import { mapActions } from 'vuex' import FtCard from '../ft-card/ft-card.vue' import FtLoader from '../../components/ft-loader/ft-loader.vue' import FtSelect from '../../components/ft-select/ft-select.vue' @@ -12,6 +11,7 @@ import { stripHTML, toLocalePublicationString } from '../../helpers/utils' +import { invidiousGetCommentReplies, invidiousGetComments } from '../../helpers/api/invidious' export default Vue.extend({ name: 'WatchVideoComments', @@ -245,50 +245,12 @@ export default Vue.extend({ } }, - parseInvidiousCommentData: function (response) { - return response.comments.map((comment) => { - comment.showReplies = false - comment.authorLink = comment.authorId - comment.authorThumb = comment.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) - if (this.hideCommentLikes) { - comment.likes = null - } else { - comment.likes = comment.likeCount - } - comment.text = autolinker.link(stripHTML(comment.content)) - comment.dataType = 'invidious' - comment.isOwner = comment.authorIsChannelOwner - - if (typeof (comment.replies) !== 'undefined' && typeof (comment.replies.replyCount) !== 'undefined') { - comment.numReplies = comment.replies.replyCount - comment.replyContinuation = comment.replies.continuation - } else { - comment.numReplies = 0 - comment.replyContinuation = '' - } - - comment.replies = [] - comment.time = toLocalePublicationString({ - publishText: comment.publishedText - }) - - return comment - }) - }, - getCommentDataInvidious: function () { - const payload = { - resource: 'comments', + invidiousGetComments({ id: this.id, - params: { - continuation: this.nextPageToken ?? '', - sort_by: this.sortNewest ? 'new' : 'top' - } - } - - this.invidiousAPICall(payload).then((response) => { - const commentData = this.parseInvidiousCommentData(response) - + nextPageToken: this.nextPageToken, + sortNewest: this.sortNewest + }).then(({ response, commentData }) => { this.commentData = this.commentData.concat(commentData) this.nextPageToken = response.continuation this.isLoading = false @@ -301,7 +263,12 @@ export default Vue.extend({ }) if (process.env.IS_ELECTRON && this.backendFallback && this.backendPreference === 'invidious') { showToast(this.$t('Falling back to local API')) - this.getCommentDataLocal() + this.getCommentDataLocal({ + videoId: this.id, + setCookie: false, + sortByNewest: this.sortNewest, + continuation: this.nextPageToken ? this.nextPageToken : undefined + }) } else { this.isLoading = false } @@ -310,32 +277,21 @@ export default Vue.extend({ getCommentRepliesInvidious: function (index) { showToast(this.$t('Comments.Getting comment replies, please wait')) - const payload = { - resource: 'comments', - id: this.id, - params: { - continuation: this.commentData[index].replyContinuation - } - } - - this.invidiousAPICall(payload).then((response) => { - const commentData = this.parseInvidiousCommentData(response) - - this.commentData[index].replies = commentData - this.commentData[index].showReplies = true - this.isLoading = false - }).catch((xhr) => { - console.error(xhr) - const errorMessage = this.$t('Invidious API Error (Click to copy)') - showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => { - copyToClipboard(xhr.responseText) + const replyToken = this.commentData[index].replyToken + invidiousGetCommentReplies({ id: this.id, replyToken: replyToken }) + .then(({ commentData, continuation }) => { + this.commentData[index].replies = commentData + this.commentData[index].showReplies = true + this.commentData[index].replyToken = continuation + this.isLoading = false + }).catch((xhr) => { + console.error(xhr) + const errorMessage = this.$t('Invidious API Error (Click to copy)') + showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => { + copyToClipboard(xhr.responseText) + }) + this.isLoading = false }) - this.isLoading = false - }) - }, - - ...mapActions([ - 'invidiousAPICall' - ]) + } } }) diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js index 58e68db6eaef..a1c10f4f16f7 100644 --- a/src/renderer/components/watch-video-info/watch-video-info.js +++ b/src/renderer/components/watch-video-info/watch-video-info.js @@ -287,7 +287,6 @@ export default Vue.extend({ }, mounted: function () { if ('mediaSession' in navigator) { - /* eslint-disable-next-line */ navigator.mediaSession.metadata = new MediaMetadata({ title: this.title, artist: this.channelName, diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js index 247730c6890b..05f32a003a37 100644 --- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js +++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js @@ -1,10 +1,11 @@ import Vue from 'vue' -import { mapActions, mapMutations } from 'vuex' +import { mapMutations } from 'vuex' import FtLoader from '../ft-loader/ft-loader.vue' import FtCard from '../ft-card/ft-card.vue' import FtListVideoLazy from '../ft-list-video-lazy/ft-list-video-lazy.vue' import { copyToClipboard, showToast } from '../../helpers/utils' import { getLocalPlaylist, parseLocalPlaylistVideo } from '../../helpers/api/local' +import { invidiousGetPlaylistInfo } from '../../helpers/api/invidious' export default Vue.extend({ name: 'WatchVideoPlaylist', @@ -316,12 +317,7 @@ export default Vue.extend({ getPlaylistInformationInvidious: function () { this.isLoading = true - const payload = { - resource: 'playlists', - id: this.playlistId - } - - this.invidiousGetPlaylistInfo(payload).then((result) => { + invidiousGetPlaylistInfo({ playlistId: this.playlistId }).then((result) => { this.playlistTitle = result.title this.channelName = result.author this.channelId = result.authorId @@ -364,10 +360,6 @@ export default Vue.extend({ this.randomizedPlaylistItems = items }, - ...mapActions([ - 'invidiousGetPlaylistInfo' - ]), - ...mapMutations([ 'setCachedPlaylist' ]) diff --git a/src/renderer/helpers/api/invidious.js b/src/renderer/helpers/api/invidious.js new file mode 100644 index 000000000000..cf13d97459fe --- /dev/null +++ b/src/renderer/helpers/api/invidious.js @@ -0,0 +1,112 @@ +import store from '../../store/index' +import { stripHTML, toLocalePublicationString } from '../utils' +import autolinker from 'autolinker' + +function getCurrentInstance() { + return store.getters.getCurrentInvidiousInstance +} + +export function invidiousAPICall({ resource, id = '', params = {} }) { + return new Promise((resolve, reject) => { + const requestUrl = getCurrentInstance() + '/api/v1/' + resource + '/' + id + '?' + new URLSearchParams(params).toString() + + fetch(requestUrl) + .then((response) => response.json()) + .then((json) => { + if (json.error !== undefined) { + throw new Error(json.error) + } + resolve(json) + }) + .catch((error) => { + console.error('Invidious API error', requestUrl, error) + reject(error) + }) + }) +} + +export async function invidiousGetChannelInfo(channelId) { + return await invidiousAPICall({ + resource: 'channels', + id: channelId, + }) +} + +export async function invidiousGetPlaylistInfo(playlistId) { + return await invidiousAPICall({ + resource: 'playlists', + id: playlistId, + }) +} + +export async function invidiousGetVideoInformation(videoId) { + return await invidiousAPICall({ + resource: 'videos', + id: videoId, + }) +} +export async function invidiousGetComments({ id, nextPageToken = '', sortNewest = true }) { + const payload = { + resource: 'comments', + id: id, + params: { + continuation: nextPageToken ?? '', + sort_by: sortNewest ? 'new' : 'top' + } + } + const response = await invidiousAPICall(payload) + + const commentData = parseInvidiousCommentData(response) + + return { response, commentData } +} + +export async function invidiousGetCommentReplies({ id, replyToken }) { + const payload = { + resource: 'comments', + id: id, + params: { + continuation: replyToken + } + } + + const response = await invidiousAPICall(payload) + return { commentData: parseInvidiousCommentData(response), continuation: response.continuation ?? null } +} + +export function youtubeImageUrlToInvidious(url, currentInstance = null) { + if (currentInstance === null) { + currentInstance = getCurrentInstance() + } + // Can be prefixed with `https://` or `//` (protocol relative) + if (url.startsWith('//')) { + url = 'https:' + url + } + + return url.replace('https://yt3.ggpht.com', `${currentInstance}/ggpht`) +} + +export function invidiousImageUrlToInvidious(url, currentInstance = null) { + return url.replace(/^.+(ggpht.+)/, currentInstance) +} + +function parseInvidiousCommentData(response) { + return response.comments.map((comment) => { + comment.showReplies = false + comment.authorLink = comment.authorId + comment.authorThumb = youtubeImageUrlToInvidious(comment.authorThumbnails[1].url) + comment.likes = comment.likeCount + comment.text = autolinker.link(stripHTML(comment.content)) + comment.dataType = 'invidious' + comment.isOwner = comment.authorIsChannelOwner + comment.numReplies = comment.replies?.replyCount ?? 0 + comment.replyToken = comment.replies?.continuation ?? '' + comment.isHearted = comment.creatorHeart !== undefined + comment.replies = [] + comment.time = toLocalePublicationString({ + publishText: comment.publishedText + }) + + return comment + }) +} diff --git a/src/renderer/main.js b/src/renderer/main.js index 635a61c6f250..dc68e6f34e98 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -125,7 +125,7 @@ library.add( Vue.component('FontAwesomeIcon', FontAwesomeIcon) -/* eslint-disable-next-line */ +/* eslint-disable-next-line no-new */ new Vue({ el: '#app', router, diff --git a/src/renderer/store/modules/invidious.js b/src/renderer/store/modules/invidious.js index 669ae926f9a7..c188b90ccada 100644 --- a/src/renderer/store/modules/invidious.js +++ b/src/renderer/store/modules/invidious.js @@ -25,11 +25,10 @@ const actions = { const response = await fetch(requestUrl) const json = await response.json() instances = json.filter((instance) => { - if (instance[0].includes('.onion') || instance[0].includes('.i2p') || !instance[1].api || (!process.env.IS_ELECTRON && !instance[1].cors)) { - return false - } else { - return true - } + return !(instance[0].includes('.onion') || + instance[0].includes('.i2p') || + !instance[1].api || + (!process.env.IS_ELECTRON && !instance[1].cors)) }).map((instance) => { return instance[1].uri.replace(/\/$/, '') }) @@ -38,10 +37,9 @@ const actions = { } // If the invidious instance fetch isn't returning anything interpretable if (instances.length === 0) { - // Starts fallback strategy: read from static file - // And fallback to hardcoded entry(s) if static file absent + // Fallback: read from static file const fileName = 'invidious-instances.json' - /* eslint-disable-next-line */ + /* eslint-disable-next-line n/no-path-concat */ const fileLocation = process.env.NODE_ENV === 'development' ? './static/' : `${__dirname}/static/` if (await pathExists(`${fileLocation}${fileName}`)) { console.warn('reading static file for invidious instances') @@ -49,12 +47,6 @@ const actions = { instances = JSON.parse(fileData).map((entry) => { return entry.url }) - } else { - console.error('unable to read static file for invidious instances') - instances = [ - 'https://invidious.sethforprivacy.com', - 'https://invidious.namazso.eu' - ] } } commit('setInvidiousInstancesList', instances) @@ -64,67 +56,6 @@ const actions = { const instanceList = state.invidiousInstancesList const randomIndex = Math.floor(Math.random() * instanceList.length) commit('setCurrentInvidiousInstance', instanceList[randomIndex]) - }, - - invidiousAPICall({ state }, payload) { - return new Promise((resolve, reject) => { - const requestUrl = state.currentInvidiousInstance + '/api/v1/' + payload.resource + '/' + payload.id + '?' + new URLSearchParams(payload.params).toString() - - fetch(requestUrl) - .then((response) => response.json()) - .then((json) => { - resolve(json) - }) - .catch((error) => { - console.error('Invidious API error', requestUrl, error) - reject(error) - }) - }) - }, - - invidiousGetChannelInfo({ commit, dispatch }, channelId) { - return new Promise((resolve, reject) => { - const payload = { - resource: 'channels', - id: channelId, - params: {} - } - - dispatch('invidiousAPICall', payload).then((response) => { - resolve(response) - }).catch((xhr) => { - console.error(xhr) - reject(xhr) - }) - }) - }, - - invidiousGetPlaylistInfo({ commit, dispatch }, payload) { - return new Promise((resolve, reject) => { - dispatch('invidiousAPICall', payload).then((response) => { - resolve(response) - }).catch((xhr) => { - console.error(xhr) - reject(xhr) - }) - }) - }, - - invidiousGetVideoInformation({ dispatch }, videoId) { - return new Promise((resolve, reject) => { - const payload = { - resource: 'videos', - id: videoId, - params: {} - } - - dispatch('invidiousAPICall', payload).then((response) => { - resolve(response) - }).catch((xhr) => { - console.error(xhr) - reject(xhr) - }) - }) } } diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js index fd2fafc00b2b..0b09504fc538 100644 --- a/src/renderer/store/modules/utils.js +++ b/src/renderer/store/modules/utils.js @@ -452,7 +452,7 @@ const actions = { async getExternalPlayerCmdArgumentsData ({ commit }, payload) { const fileName = 'external-player-map.json' let fileData - /* eslint-disable-next-line */ + /* eslint-disable-next-line n/no-path-concat */ const fileLocation = process.env.NODE_ENV === 'development' ? './static/' : `${__dirname}/static/` if (await pathExists(`${fileLocation}${fileName}`)) { diff --git a/src/renderer/views/Channel/Channel.js b/src/renderer/views/Channel/Channel.js index 748801c02c6d..f5a668f76baa 100644 --- a/src/renderer/views/Channel/Channel.js +++ b/src/renderer/views/Channel/Channel.js @@ -17,6 +17,7 @@ import { MAIN_PROFILE_ID } from '../../../constants' import i18n from '../../i18n/index' import { copyToClipboard, showToast } from '../../helpers/utils' import packageDetails from '../../../../package.json' +import { invidiousAPICall, invidiousGetChannelInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'Search', @@ -371,7 +372,7 @@ export default Vue.extend({ this.apiUsed = 'invidious' const expectedId = this.originalId - this.invidiousGetChannelInfo(this.id).then((response) => { + invidiousGetChannelInfo(this.id).then((response) => { if (expectedId !== this.originalId) { return } @@ -388,18 +389,21 @@ export default Vue.extend({ this.subCount = response.subCount } const thumbnail = response.authorThumbnails[3].url - this.thumbnailUrl = thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + this.thumbnailUrl = youtubeImageUrlToInvidious(thumbnail, this.currentInvidiousInstance) this.updateSubscriptionDetails({ channelThumbnailUrl: thumbnail, channelName: channelName, channelId: channelId }) this.channelDescription = autolinker.link(response.description) this.relatedChannels = response.relatedChannels.map((channel) => { - channel.authorThumbnails[channel.authorThumbnails.length - 1].url = channel.authorThumbnails[channel.authorThumbnails.length - 1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + channel.authorThumbnails = channel.authorThumbnails.map(thumbnail => { + thumbnail.url = youtubeImageUrlToInvidious(thumbnail.url, this.currentInvidiousInstance) + return thumbnail + }) channel.channelId = channel.authorId return channel }) this.latestVideos = response.latestVideos if (response.authorBanners instanceof Array && response.authorBanners.length > 0) { - this.bannerUrl = response.authorBanners[0].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) + this.bannerUrl = youtubeImageUrlToInvidious(response.authorBanners[0].url, this.currentInvidiousInstance) } else { this.bannerUrl = null } @@ -427,7 +431,7 @@ export default Vue.extend({ } } - this.invidiousAPICall(payload).then((response) => { + invidiousAPICall(payload).then((response) => { this.latestVideos = this.latestVideos.concat(response) this.latestVideosPage++ this.isElementListLoading = false @@ -490,7 +494,7 @@ export default Vue.extend({ } } - this.invidiousAPICall(payload).then((response) => { + invidiousAPICall(payload).then((response) => { this.playlistContinuationString = response.continuation this.latestPlaylists = response.playlists this.isElementListLoading = false @@ -527,7 +531,7 @@ export default Vue.extend({ payload.params.continuation = this.playlistContinuationString } - this.invidiousAPICall(payload).then((response) => { + invidiousAPICall(payload).then((response) => { this.playlistContinuationString = response.continuation this.latestPlaylists = this.latestPlaylists.concat(response.playlists) this.isElementListLoading = false @@ -748,7 +752,7 @@ export default Vue.extend({ } } - this.invidiousAPICall(payload).then((response) => { + invidiousAPICall(payload).then((response) => { this.searchResults = this.searchResults.concat(response) this.isElementListLoading = false this.searchPage++ @@ -769,8 +773,6 @@ export default Vue.extend({ ...mapActions([ 'updateProfile', - 'invidiousGetChannelInfo', - 'invidiousAPICall', 'updateSubscriptionDetails' ]) } diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js index 998fc9e62dbf..f1ef1662a482 100644 --- a/src/renderer/views/Playlist/Playlist.js +++ b/src/renderer/views/Playlist/Playlist.js @@ -9,6 +9,7 @@ import FtButton from '../../components/ft-button/ft-button.vue' import i18n from '../../i18n/index' import { getLocalPlaylist, parseLocalPlaylistVideo } from '../../helpers/api/local' import { extractNumberFromString } from '../../helpers/utils' +import { invidiousGetPlaylistInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'Playlist', @@ -124,12 +125,7 @@ export default Vue.extend({ getPlaylistInvidious: function () { this.isLoading = true - const payload = { - resource: 'playlists', - id: this.playlistId - } - - this.invidiousGetPlaylistInfo(payload).then((result) => { + invidiousGetPlaylistInfo({ playlistId: this.playlistId }).then((result) => { this.infoData = { id: result.playlistId, title: result.title, @@ -138,7 +134,7 @@ export default Vue.extend({ viewCount: result.viewCount, videoCount: result.videoCount, channelName: result.author, - channelThumbnail: result.authorThumbnails[2].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`), + channelThumbnail: youtubeImageUrlToInvidious(result.authorThumbnails[2].url, this.currentInvidiousInstance), channelId: result.authorId, infoSource: 'invidious' } @@ -196,7 +192,6 @@ export default Vue.extend({ }, ...mapActions([ - 'invidiousGetPlaylistInfo', 'updateSubscriptionDetails' ]), diff --git a/src/renderer/views/Popular/Popular.js b/src/renderer/views/Popular/Popular.js index a70e4f578f1f..03f35f87530f 100644 --- a/src/renderer/views/Popular/Popular.js +++ b/src/renderer/views/Popular/Popular.js @@ -1,10 +1,11 @@ import Vue from 'vue' -import { mapActions } from 'vuex' import FtLoader from '../../components/ft-loader/ft-loader.vue' import FtCard from '../../components/ft-card/ft-card.vue' import FtElementList from '../../components/ft-element-list/ft-element-list.vue' import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue' +import { invidiousAPICall } from '../../helpers/api/invidious' + export default Vue.extend({ name: 'Popular', components: { @@ -44,7 +45,7 @@ export default Vue.extend({ } this.isLoading = true - const result = await this.invidiousAPICall(searchPayload) + const result = await invidiousAPICall(searchPayload) .catch((err) => { console.error(err) }) @@ -74,10 +75,6 @@ export default Vue.extend({ } break } - }, - - ...mapActions([ - 'invidiousAPICall' - ]) + } } }) diff --git a/src/renderer/views/Search/Search.js b/src/renderer/views/Search/Search.js index 6447095822a1..344dbf7332c6 100644 --- a/src/renderer/views/Search/Search.js +++ b/src/renderer/views/Search/Search.js @@ -1,10 +1,10 @@ import Vue from 'vue' -import { mapActions } from 'vuex' import FtLoader from '../../components/ft-loader/ft-loader.vue' import FtCard from '../../components/ft-card/ft-card.vue' import FtElementList from '../../components/ft-element-list/ft-element-list.vue' import { copyToClipboard, searchFiltersMatch, showToast } from '../../helpers/utils' import { getLocalSearchContinuation, getLocalSearchResults } from '../../helpers/api/local' +import { invidiousAPICall } from '../../helpers/api/invidious' export default Vue.extend({ name: 'Search', @@ -214,7 +214,7 @@ export default Vue.extend({ } } - this.invidiousAPICall(searchPayload).then((result) => { + invidiousAPICall(searchPayload).then((result) => { if (!result) { return } @@ -295,10 +295,6 @@ export default Vue.extend({ } this.isLoading = false - }, - - ...mapActions([ - 'invidiousAPICall' - ]) + } } }) diff --git a/src/renderer/views/SubscribedChannels/SubscribedChannels.js b/src/renderer/views/SubscribedChannels/SubscribedChannels.js index 8a4a66c79f4d..60c9910fc343 100644 --- a/src/renderer/views/SubscribedChannels/SubscribedChannels.js +++ b/src/renderer/views/SubscribedChannels/SubscribedChannels.js @@ -7,6 +7,7 @@ import FtInput from '../../components/ft-input/ft-input.vue' import FtPrompt from '../../components/ft-prompt/ft-prompt.vue' import ytch from 'yt-channel-info' import { showToast } from '../../helpers/utils' +import { invidiousGetChannelInfo, youtubeImageUrlToInvidious, invidiousImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'SubscribedChannels', @@ -24,9 +25,7 @@ export default Vue.extend({ filteredChannels: [], re: { url: /(.+=\w)\d+(.+)/, - ivToIv: /^.+(ggpht.+)/, - ivToYt: /^.+ggpht\/(.+)/, - ytToIv: /^.+ggpht\.com\/(.+)/ + ivToYt: /^.+ggpht\/(.+)/ }, thumbnailSize: 176, ytBaseURL: 'https://yt3.ggpht.com', @@ -165,13 +164,13 @@ export default Vue.extend({ let newURL = originalURL if (new URL(originalURL).hostname === 'yt3.ggpht.com') { if (this.backendPreference === 'invidious') { // YT to IV - newURL = originalURL.replace(this.re.ytToIv, `${this.currentInvidiousInstance}/ggpht/$1`) + newURL = youtubeImageUrlToInvidious(originalURL, this.currentInvidiousInstance) } } else { if (this.backendPreference === 'local') { // IV to YT newURL = originalURL.replace(this.re.ivToYt, `${this.ytBaseURL}/$1`) } else { // IV to IV - newURL = originalURL.replace(this.re.ivToIv, `${this.currentInvidiousInstance}/$1`) + newURL = invidiousImageUrlToInvidious(originalURL, this.currentInvidiousInstance) } } @@ -193,7 +192,7 @@ export default Vue.extend({ }, this.errorCount * 500) } else { setTimeout(() => { - this.invidiousGetChannelInfo(channel.id).then(response => { + invidiousGetChannelInfo(channel.id).then(response => { this.updateSubscriptionDetails({ channelThumbnailUrl: this.thumbnailURL(response.authorThumbnails[0].url), channelName: channel.name, @@ -207,7 +206,6 @@ export default Vue.extend({ ...mapActions([ 'updateProfile', 'updateSubscriptionDetails', - 'invidiousGetChannelInfo' ]) } }) diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index fdd0365d3f55..b1c3c2cf8625 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -11,6 +11,7 @@ import FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubbl import ytch from 'yt-channel-info' import { MAIN_PROFILE_ID } from '../../../constants' import { calculatePublishedDate, copyToClipboard, showToast } from '../../helpers/utils' +import { invidiousAPICall } from '../../helpers/api/invidious' export default Vue.extend({ name: 'Subscriptions', @@ -359,7 +360,7 @@ export default Vue.extend({ params: {} } - this.invidiousAPICall(subscriptionsPayload).then(async (result) => { + invidiousAPICall(subscriptionsPayload).then(async (result) => { resolve(await Promise.all(result.map((video) => { video.publishedDate = new Date(video.published * 1000) return video @@ -481,7 +482,6 @@ export default Vue.extend({ }, ...mapActions([ - 'invidiousAPICall', 'updateShowProgressBar', 'updateProfileSubscriptions', 'updateAllSubscriptionsList' diff --git a/src/renderer/views/Trending/Trending.js b/src/renderer/views/Trending/Trending.js index 3950adda2826..2ab09df50741 100644 --- a/src/renderer/views/Trending/Trending.js +++ b/src/renderer/views/Trending/Trending.js @@ -1,5 +1,4 @@ import Vue from 'vue' -import { mapActions } from 'vuex' import FtCard from '../../components/ft-card/ft-card.vue' import FtLoader from '../../components/ft-loader/ft-loader.vue' import FtElementList from '../../components/ft-element-list/ft-element-list.vue' @@ -8,6 +7,7 @@ import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue' import { copyToClipboard, showToast } from '../../helpers/utils' import { getLocalTrending } from '../../helpers/api/local' +import { invidiousAPICall } from '../../helpers/api/invidious' export default Vue.extend({ name: 'Trending', @@ -133,7 +133,7 @@ export default Vue.extend({ trendingPayload.params.type = this.currentTab.charAt(0).toUpperCase() + this.currentTab.slice(1) } - this.invidiousAPICall(trendingPayload).then((result) => { + invidiousAPICall(trendingPayload).then((result) => { if (!result) { return } @@ -177,10 +177,6 @@ export default Vue.extend({ } break } - }, - - ...mapActions([ - 'invidiousAPICall' - ]) + } } }) diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js index eea456b118f9..395c7da5c93b 100644 --- a/src/renderer/views/Watch/Watch.js +++ b/src/renderer/views/Watch/Watch.js @@ -27,6 +27,7 @@ import { parseLocalTextRuns, parseLocalWatchNextVideo } from '../../helpers/api/local' +import { invidiousGetVideoInformation, youtubeImageUrlToInvidious } from '../../helpers/api/invidious' export default Vue.extend({ name: 'Watch', @@ -159,10 +160,6 @@ export default Vue.extend({ showFamilyFriendlyOnly: function() { return this.$store.getters.getShowFamilyFriendlyOnly }, - - youtubeNoCookieEmbeddedFrame: function () { - return `` - }, hideChannelSubscriptions: function () { return this.$store.getters.getHideChannelSubscriptions }, @@ -656,7 +653,7 @@ export default Vue.extend({ this.dashSrc = this.createInvidiousDashManifest() this.videoStoryboardSrc = `${this.currentInvidiousInstance}/api/v1/storyboards/${this.videoId}?height=90` - this.invidiousGetVideoInformation(this.videoId) + invidiousGetVideoInformation(this.videoId) .then(result => { if (result.error) { throw new Error(result.error) @@ -679,7 +676,7 @@ export default Vue.extend({ this.channelId = result.authorId this.channelName = result.author const channelThumb = result.authorThumbnails[1] - this.channelThumbnail = channelThumb ? channelThumb.url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) : '' + this.channelThumbnail = channelThumb ? youtubeImageUrlToInvidious(channelThumb.url, this.currentInvidiousInstance) : '' this.updateSubscriptionDetails({ channelThumbnailUrl: channelThumb?.url, channelName: result.author, @@ -1417,7 +1414,6 @@ export default Vue.extend({ ...mapActions([ 'updateHistory', 'updateWatchProgress', - 'invidiousGetVideoInformation', 'updateSubscriptionDetails' ]) }