diff --git a/docs/en/social-media.md b/docs/en/social-media.md index c7f80753eb..082887d1d7 100644 --- a/docs/en/social-media.md +++ b/docs/en/social-media.md @@ -551,3 +551,53 @@ YouTube provides official RSS feeds for channels, for instance + +### Music Charts + + + +::: details Chart +| Top artists | Top songs | Top music videos | Trending | +| ----------- | --------- | ---------------- | -------- | +| TopArtists | TopSongs | TopVideos | TrendingVideos | +::: + +::: details Country Code +| Argentina | Australia | Austria | Belgium | Bolivia | Brazil | Canada | +| --------- | --------- | ------- | ------- | ------- | ------ | ------ | +| ar | au | at | be | bo | br | ca | + +| Chile | Colombia | Costa Rica | Czechia | Denmark | Dominican Republic | Ecuador | +| ----- | -------- | ---------- | ------- | ------- | ------------------ | ------- | +| cl | co | cr | cz | dk | do | ec | + +| Egypt | El Salvador | Estonia | Finland | France | Germany | Guatemala | +| ----- | ----------- | ------- | ------- | ------ | ------- | --------- | +| eg | sv | ee | fi | fr | de | gt | + +| Honduras | Hungary | Iceland | India | Indonesia | Ireland | Israel | Italy | +| -------- | ------- | ------- | ----- | --------- | ------- | ------ | ----- | +| hn | hu | is | in | id | ie | il | it | + +| Japan | Kenya | Luxembourg | Mexico | Netherlands | New Zealand | Nicaragua | +| ----- | ----- | ---------- | ------ | ----------- | ----------- | --------- | +| jp | ke | lu | mx | nl | nz | ni | + +| Nigeria | Norway | Panama | Paraguay | Peru | Poland | Portugal | Romania | +| ------- | ------ | ------ | -------- | ---- | ------ | -------- | ------- | +| ng | no | pa | py | pe | pl | pt | ro | + +| Russia | Saudi Arabia | Serbia | South Africa | South Korea | Spain | Sweden | Switzerland | +| ----- | ------------- | ------ | ------------ | ----------- | ----- | ------ | ----------- | +| ru | sa | rs | za | kr | es | se | ch | + +| Tanzania | Turkey | Uganda | Ukraine | United Arab Emirates | United Kingdom | United States | +| -------- | ------ | ------ | ------- | -------------------- | -------------- | ------------- | +| tz | tr | ug | ua | ae | gb | us | + +| Uruguay | Zimbabwe | +| ------- | -------- | +| uy | zw | +::: + + diff --git a/docs/social-media.md b/docs/social-media.md index 254ceb9d50..1330ddf8b4 100644 --- a/docs/social-media.md +++ b/docs/social-media.md @@ -889,7 +889,7 @@ Instagram Stories 没有可靠的 guid,你的 RSS 阅读器可能将同一条 ### 分类页面 - + @@ -919,19 +919,71 @@ YouTube 官方亦有提供频道 RSS,形如 + ### 自定义网址 - + ### 播放列表 - + ### 订阅列表 - + + +### 音乐排行榜 + + + +::: details 排行榜 + +| 热门音乐人 | 热门歌曲 | 热门音乐视频 | 时下流行 | +| ---------- | -------- | --------- | -------------- | +| TopArtists | TopSongs | TopVideos | TrendingVideos | +| ::: | | | | + +::: details 国家代码 + +| Argentina | Australia | Austria | Belgium | Bolivia | Brazil | Canada | +| --------- | --------- | ------- | ------- | ------- | ------ | ------ | +| ar | au | at | be | bo | br | ca | + +| Chile | Colombia | Costa Rica | Czechia | Denmark | Dominican Republic | Ecuador | +| ----- | -------- | ---------- | ------- | ------- | ------------------ | ------- | +| cl | co | cr | cz | dk | do | ec | + +| Egypt | El Salvador | Estonia | Finland | France | Germany | Guatemala | +| ----- | ----------- | ------- | ------- | ------ | ------- | --------- | +| eg | sv | ee | fi | fr | de | gt | + +| Honduras | Hungary | Iceland | India | Indonesia | Ireland | Israel | Italy | +| -------- | ------- | ------- | ----- | --------- | ------- | ------ | ----- | +| hn | hu | is | in | id | ie | il | it | + +| Japan | Kenya | Luxembourg | Mexico | Netherlands | New Zealand | Nicaragua | +| ----- | ----- | ---------- | ------ | ----------- | ----------- | --------- | +| jp | ke | lu | mx | nl | nz | ni | + +| Nigeria | Norway | Panama | Paraguay | Peru | Poland | Portugal | Romania | +| ------- | ------ | ------ | -------- | ---- | ------ | -------- | ------- | +| ng | no | pa | py | pe | pl | pt | ro | + +| Russia | Saudi Arabia | Serbia | South Africa | South Korea | Spain | Sweden | Switzerland | +| ------ | ------------ | ------ | ------------ | ----------- | ----- | ------ | ----------- | +| ru | sa | rs | za | kr | es | se | ch | + +| Tanzania | Turkey | Uganda | Ukraine | United Arab Emirates | United Kingdom | United States | +| -------- | ------ | ------ | ------- | -------------------- | -------------- | ------------- | +| tz | tr | ug | ua | ae | gb | us | + +| Uruguay | Zimbabwe | +| ------- | -------- | +| uy | zw | +| ::: | | + + ## 巴哈姆特 diff --git a/lib/v2/youtube/charts.js b/lib/v2/youtube/charts.js new file mode 100644 index 0000000000..728628c1c1 --- /dev/null +++ b/lib/v2/youtube/charts.js @@ -0,0 +1,97 @@ +const got = require('@/utils/got'); +const { renderDescription } = require('./utils'); +const config = require('@/config').value; + +module.exports = async (ctx) => { + const contentMap = { + TopArtists: { + contentKey: 'artists', + viewKey: 'artistViews', + title: 'Top artists', + }, + TopSongs: { + contentKey: 'trackTypes', + viewKey: 'trackViews', + title: 'Top songs', + }, + TopVideos: { + contentKey: 'videos', + viewKey: 'videoViews', + title: 'Top music videos', + }, + TrendingVideos: { + contentKey: 'videos', + viewKey: 'videoViews', + title: 'Trending', + }, + }; + + const { category = 'TopVideos', country } = ctx.params; + const embed = !ctx.params.embed; + + const { content } = await ctx.cache.tryGet( + `youtube:charts:${country ? country : 'global'}`, + async () => { + const { data } = await got.post('https://charts.youtube.com/youtubei/v1/browse', { + searchParams: { + alt: 'json', + key: 'AIzaSyCzEW7JUJdSql0-2V4tHUb6laYm4iAE_dM', + }, + json: { + browseId: 'FEmusic_analytics_charts_home', + context: { + capabilities: {}, + client: { + clientName: 'WEB_MUSIC_ANALYTICS', + clientVersion: '0.2', + experimentIds: [], + experimentsToken: '', + gl: 'US', + hl: 'en', + theme: 'MUSIC', + }, + request: { + internalExperimentFlags: [], + }, + }, + query: `chart_params_type=WEEK&perspective=CHART&flags=viral_video_chart&selected_chart=TRACKS&chart_params_id=weekly:0:0${country ? `:${country}` : ''}`, + }, + }); + return data.contents.sectionListRenderer.contents[0].musicAnalyticsSectionRenderer; + }, + config.cache.routeExpire, + false + ); + + const { entityId } = content.perspectiveMetadata; + let items; + + if (category === 'TopArtists') { + items = content[contentMap[category].contentKey][0][contentMap[category].viewKey].map((item) => ({ + title: item.name, + link: `https://charts.youtube.com/artist/${encodeURIComponent(item.id)}`, + guid: `youtube:charts:${category}:${entityId}:${item.id}`, + })); + } else { + items = content[contentMap[category].contentKey][category !== 'TrendingVideos' ? 0 : 1][contentMap[category].viewKey].map((item) => { + const videoId = category === 'TopSongs' ? item.encryptedVideoId : item.id; + const author = item.artists + .filter((a) => a.name) + .map((artist) => artist.name) + .join(', '); + return { + title: `${item.title ?? item.name} - ${author}`, + description: renderDescription(embed, videoId, item.thumbnail?.thumbnails.pop().url, ''), + link: `https://www.youtube.com/watch?v=${videoId}`, + guid: `youtube:charts:${category}:${entityId}:${item.id}`, + author, + }; + }); + } + + ctx.state.data = { + title: `YouTube Music Charts - ${contentMap[category].title}`, + link: `https://charts.youtube.com/charts/${category}/${country ? country : 'global'}`, + item: items, + }; +}; diff --git a/lib/v2/youtube/maintainer.js b/lib/v2/youtube/maintainer.js index 058159c6b8..fd8019917e 100644 --- a/lib/v2/youtube/maintainer.js +++ b/lib/v2/youtube/maintainer.js @@ -1,5 +1,7 @@ module.exports = { + '/c/:id/:embed?': ['TonyRL'], '/channel/:id/:embed?': ['DIYgod'], + '/charts/:category?/:country?/:embed?': ['TonyRL'], '/playlist/:id/:embed?': ['HenryQW'], '/subscriptions/:embed?': ['TonyRL'], '/user/:username/:embed?': ['DIYgod'], diff --git a/lib/v2/youtube/radar.js b/lib/v2/youtube/radar.js index cf2e38d83e..d0d5bc8fba 100644 --- a/lib/v2/youtube/radar.js +++ b/lib/v2/youtube/radar.js @@ -1,6 +1,14 @@ module.exports = { 'youtube.com': { _name: 'YouTube', + charts: [ + { + title: '音乐排行榜', + docs: 'https://docs.rsshub.app/social-media.html#youtube', + source: ['/charts/:category/:country/*', '/charts/:category/:country', '/charts/:category'], + target: (params) => `/youtube/charts/${params.category}${params.country ? params.country : ''}`, + }, + ], www: [ { title: '用户', diff --git a/lib/v2/youtube/router.js b/lib/v2/youtube/router.js index 8d6165cf45..fe7412948d 100644 --- a/lib/v2/youtube/router.js +++ b/lib/v2/youtube/router.js @@ -1,6 +1,7 @@ module.exports = (router) => { router.get('/c/:username/:embed?', require('./custom')); router.get('/channel/:id/:embed?', require('./channel')); + router.get('/charts/:category?/:country?/:embed?', require('./charts')); router.get('/playlist/:id/:embed?', require('./playlist')); router.get('/subscriptions/:embed?', require('./subscriptions')); router.get('/user/:username/:embed?', require('./user'));