diff --git a/package-lock.json b/package-lock.json index 0920ccfef..cc17004d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4782,10 +4782,11 @@ "dev": true }, "node_modules/@graphql-tools/utils": { - "version": "10.6.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.6.2.tgz", - "integrity": "sha512-ABZHTpwiVR8oE2//NI/nnU3nNhbBpqMlMYyCF5cnqjLfhlyOdFfoRuhYEATEsmMfDg0ijGreULywK/SmepVGfw==", + "version": "10.6.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.6.4.tgz", + "integrity": "sha512-itCgjwVxbO+3uI/K73G9heedG8KelNFzgn368rUhPjTrkJX6NyLQwT5EMq/A8tvazMXyJYdtnN5nD+tT4DUpbQ==", "dev": true, + "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "cross-inspect": "1.0.1", @@ -11204,9 +11205,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001686", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz", - "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==", + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", "funding": [ { "type": "opencollective", @@ -11220,7 +11221,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/capital-case": { "version": "1.0.4", diff --git a/src/containers/library/playlist/detail.graphql b/src/containers/library/playlist/detail.graphql index edb154868..06964c4a9 100644 --- a/src/containers/library/playlist/detail.graphql +++ b/src/containers/library/playlist/detail.graphql @@ -39,3 +39,16 @@ query getPlaylistPageData($id: ID!) { } } } + +query getPlaylistFeedData($id: ID!) { + playlist(id: $id) { + id + title + summary + recordings(offset: 0, first: 1500) { + nodes { + ...generateFeed + } + } + } +} diff --git a/src/containers/library/playlist/detail.tsx b/src/containers/library/playlist/detail.tsx index 937594ed0..9c2063127 100644 --- a/src/containers/library/playlist/detail.tsx +++ b/src/containers/library/playlist/detail.tsx @@ -91,7 +91,11 @@ function PlaylistDetail({ playlist }: Must<IPlaylistDetailProps>): JSX.Element { /> ) : ( <ButtonShare - shareUrl={`https://audioverse.org/${languageRoute}/playlists/${id}`} + shareUrl={root.lang(languageRoute).playlists.playlist(id).get()} + rssUrl={root + .lang(languageRoute) + .playlists.playlist(id) + .feed.get()} backgroundColor={BaseColors.CREAM} light={true} contentType="PLAYLIST" diff --git a/src/lib/routes/playlists.ts b/src/lib/routes/playlists.ts index f4db3f6b2..d4129c58e 100644 --- a/src/lib/routes/playlists.ts +++ b/src/lib/routes/playlists.ts @@ -3,6 +3,7 @@ import node from './primatives/node'; const playlists = (r: string) => ({ playlist: (playlistId: string | number) => node(`${r}/${playlistId}`, (r) => ({ + feed: node(`${r}/feed.xml`), items: (canonicalPath: string) => node(`${r}/items/${canonicalPath.split('/').slice(3).join('/')}`), })), diff --git a/src/pages/[language]/playlists/[playlist]/feed.xml/index.ts b/src/pages/[language]/playlists/[playlist]/feed.xml/index.ts new file mode 100644 index 000000000..3a61b2c83 --- /dev/null +++ b/src/pages/[language]/playlists/[playlist]/feed.xml/index.ts @@ -0,0 +1,50 @@ +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; + +import { generateFeed, sendRSSHeaders } from '~lib/generateFeed'; +import { getPlaylistFeedData } from '~src/containers/library/playlist/__generated__/detail'; +import root from '~src/lib/routes'; + +export default (): void => void 0; + +export async function getServerSideProps({ + params, + res, +}: GetServerSidePropsContext<{ language: string; playlist: string }>): Promise< + GetServerSidePropsResult<Record<string, unknown>> +> { + const id = params?.playlist as string; + const languageRoute = params?.language as string; + + const { playlist } = await getPlaylistFeedData({ + id, + }).catch(() => ({ + playlist: null, + })); + + if (!playlist) { + return { + notFound: true, + }; + } + + if (res) { + sendRSSHeaders(res); + + const feed = await generateFeed( + languageRoute, + { + link: root.lang(languageRoute).playlists.playlist(id).get(), + title: playlist.title, + description: playlist.summary, + }, + playlist.recordings.nodes || [], + ); + res.write(feed); + + res.end(); + } + + return { + props: {}, + }; +}