mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-24 23:12:34 +08:00
feat: use youtubei api as fallback for youtube channel
This commit is contained in:
@@ -131,3 +131,34 @@ export const getDataByUsername = async ({ username, embed, filterShorts }: { use
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
export const getDataByChannelId = async ({ channelId, embed, filterShorts }: { channelId: string; embed: boolean; filterShorts: boolean }): Promise<Data> => {
|
||||
// Get original uploads playlist ID if needed
|
||||
const originalPlaylistId = filterShorts ? null : (await utils.getChannelWithId(channelId, 'contentDetails', cache)).data.items[0].contentDetails.relatedPlaylists.uploads;
|
||||
|
||||
// Use the utility function to get the appropriate playlist ID based on filterShorts setting
|
||||
const playlistId = filterShorts ? utils.getPlaylistWithShortsFilter(channelId) : originalPlaylistId;
|
||||
|
||||
const data = (await utils.getPlaylistItems(playlistId, 'snippet', cache)).data.items;
|
||||
|
||||
return {
|
||||
title: `${data[0].snippet.channelTitle} - YouTube`,
|
||||
link: `https://www.youtube.com/channel/${channelId}`,
|
||||
description: `YouTube channel ${data[0].snippet.channelTitle}`,
|
||||
item: data
|
||||
.filter((d) => d.snippet.title !== 'Private video' && d.snippet.title !== 'Deleted video')
|
||||
.map((item) => {
|
||||
const snippet = item.snippet;
|
||||
const videoId = snippet.resourceId.videoId;
|
||||
const img = utils.getThumbnail(snippet.thumbnails);
|
||||
return {
|
||||
title: snippet.title,
|
||||
description: utils.renderDescription(embed, videoId, img, utils.formatDescription(snippet.description)),
|
||||
pubDate: parseDate(snippet.publishedAt),
|
||||
link: `https://www.youtube.com/watch?v=${videoId}`,
|
||||
author: snippet.videoOwnerChannelTitle,
|
||||
image: img.url,
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,16 +12,19 @@ export const getChannelIdByUsername = (username: string) =>
|
||||
return navigationEndpoint.payload.browseId;
|
||||
});
|
||||
|
||||
export const getDataByUsername = async ({ username, embed }: { username: string; embed: boolean; filterShorts: boolean }): Promise<Data> => {
|
||||
const innertube = await innertubePromise;
|
||||
export const getDataByUsername = async ({ username, embed, filterShorts }: { username: string; embed: boolean; filterShorts: boolean }): Promise<Data> => {
|
||||
const channelId = (await getChannelIdByUsername(username)) as string;
|
||||
return getDataByChannelId({ channelId, embed, filterShorts });
|
||||
};
|
||||
|
||||
export const getDataByChannelId = async ({ channelId, embed }: { channelId: string; embed: boolean; filterShorts: boolean }): Promise<Data> => {
|
||||
const innertube = await innertubePromise;
|
||||
const channel = await innertube.getChannel(channelId);
|
||||
const videos = await channel.getVideos();
|
||||
|
||||
return {
|
||||
title: `${channel.metadata.title || username} - YouTube`,
|
||||
link: `https://www.youtube.com/${username}`,
|
||||
title: `${channel.metadata.title || channelId} - YouTube`,
|
||||
link: `https://www.youtube.com/channel/${channelId}`,
|
||||
image: channel.metadata.avatar?.[0].url,
|
||||
description: channel.metadata.description,
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
import utils from './utils';
|
||||
import { config } from '@/config';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
import utils, { callApi } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { getDataByChannelId as getDataByChannelIdYoutubei } from './api/youtubei';
|
||||
import { getDataByChannelId as getDataByChannelIdGoogle } from './api/google';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/channel/:id/:routeParams?',
|
||||
@@ -38,6 +36,7 @@ YouTube provides official RSS feeds for channels, for instance [https://www.yout
|
||||
{
|
||||
name: 'YOUTUBE_KEY',
|
||||
description: ' YouTube API Key, support multiple keys, split them with `,`, [API Key application](https://console.developers.google.com/)',
|
||||
optional: true,
|
||||
},
|
||||
],
|
||||
requirePuppeteer: false,
|
||||
@@ -49,9 +48,6 @@ YouTube provides official RSS feeds for channels, for instance [https://www.yout
|
||||
};
|
||||
|
||||
async function handler(ctx) {
|
||||
if (!config.youtube || !config.youtube.key) {
|
||||
throw new ConfigNotFoundError('YouTube RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const id = ctx.req.param('id');
|
||||
|
||||
// Parse route parameters
|
||||
@@ -69,32 +65,11 @@ async function handler(ctx) {
|
||||
throw new InvalidParameterError(`Invalid YouTube channel ID. \nYou may want to use <code>/youtube/user/:id</code> instead.`);
|
||||
}
|
||||
|
||||
// Get original uploads playlist ID if needed
|
||||
const originalPlaylistId = filterShorts ? null : (await utils.getChannelWithId(id, 'contentDetails', cache)).data.items[0].contentDetails.relatedPlaylists.uploads;
|
||||
const data = await callApi({
|
||||
googleApi: getDataByChannelIdGoogle,
|
||||
youtubeiApi: getDataByChannelIdYoutubei,
|
||||
params: { channelId: id, embed, filterShorts },
|
||||
});
|
||||
|
||||
// Use the utility function to get the appropriate playlist ID based on filterShorts setting
|
||||
const playlistId = filterShorts ? utils.getPlaylistWithShortsFilter(id) : originalPlaylistId;
|
||||
|
||||
const data = (await utils.getPlaylistItems(playlistId, 'snippet', cache)).data.items;
|
||||
|
||||
return {
|
||||
title: `${data[0].snippet.channelTitle} - YouTube`,
|
||||
link: `https://www.youtube.com/channel/${id}`,
|
||||
description: `YouTube channel ${data[0].snippet.channelTitle}`,
|
||||
item: data
|
||||
.filter((d) => d.snippet.title !== 'Private video' && d.snippet.title !== 'Deleted video')
|
||||
.map((item) => {
|
||||
const snippet = item.snippet;
|
||||
const videoId = snippet.resourceId.videoId;
|
||||
const img = utils.getThumbnail(snippet.thumbnails);
|
||||
return {
|
||||
title: snippet.title,
|
||||
description: utils.renderDescription(embed, videoId, img, utils.formatDescription(snippet.description)),
|
||||
pubDate: parseDate(snippet.publishedAt),
|
||||
link: `https://www.youtube.com/watch?v=${videoId}`,
|
||||
author: snippet.videoOwnerChannelTitle,
|
||||
image: img.url,
|
||||
};
|
||||
}),
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Route, ViewType } from '@/types';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
import { getDataByUsername as getDataByUsernameYoutubei } from './api/youtubei';
|
||||
import { getDataByUsername as getDataByUsernameGoogle } from './api/google';
|
||||
import { callApi } from './utils';
|
||||
@@ -25,6 +23,7 @@ export const route: Route = {
|
||||
{
|
||||
name: 'YOUTUBE_KEY',
|
||||
description: ' YouTube API Key, support multiple keys, split them with `,`, [API Key application](https://console.developers.google.com/)',
|
||||
optional: true,
|
||||
},
|
||||
],
|
||||
requirePuppeteer: false,
|
||||
@@ -45,9 +44,6 @@ export const route: Route = {
|
||||
};
|
||||
|
||||
async function handler(ctx) {
|
||||
if (!config.youtube || !config.youtube.key) {
|
||||
throw new ConfigNotFoundError('YouTube RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const username = ctx.req.param('username');
|
||||
|
||||
// Parse route parameters
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@
|
||||
"uuid": "11.1.0",
|
||||
"winston": "3.17.0",
|
||||
"xxhash-wasm": "1.1.0",
|
||||
"youtubei.js": "^13.4.0",
|
||||
"youtubei.js": "13.4.0",
|
||||
"zod": "3.24.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Generated
+1
-1
@@ -281,7 +281,7 @@ importers:
|
||||
specifier: 1.1.0
|
||||
version: 1.1.0
|
||||
youtubei.js:
|
||||
specifier: ^13.4.0
|
||||
specifier: 13.4.0
|
||||
version: 13.4.0
|
||||
zod:
|
||||
specifier: 3.24.4
|
||||
|
||||
Reference in New Issue
Block a user