diff options
Diffstat (limited to 'src/routes/feeds/activity-notifications/+server.ts')
| -rw-r--r-- | src/routes/feeds/activity-notifications/+server.ts | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/src/routes/feeds/activity-notifications/+server.ts b/src/routes/feeds/activity-notifications/+server.ts index 64ba3fdc..145e236e 100644 --- a/src/routes/feeds/activity-notifications/+server.ts +++ b/src/routes/feeds/activity-notifications/+server.ts @@ -2,16 +2,15 @@ import { type Notification, notifications, } from "$lib/Data/AniList/notifications"; +import { refreshAniListToken } from "$lib/Utility/anilistOauth"; import { siteUrl } from "$lib/Utility/appOrigin"; -import root from "$lib/Utility/root"; +import { decryptFeedToken } from "$lib/Utility/feedToken"; const htmlEncode = (input: string) => { return input.replace(/[\u00A0-\u9999<>&]/g, (i) => `&#${i.charCodeAt(0)};`); }; -const render = ( - posts: Notification[] = [], -) => `<?xml version="1.0" encoding="UTF-8" ?> +const channel = (items: string) => `<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" @@ -27,7 +26,14 @@ xmlns:media="http://search.yahoo.com/mrss/"> <lastBuildDate>${new Date().toUTCString()}</lastBuildDate> <language>en-US</language> <snf:logo><url>${siteUrl("/favicon-196x196.png")}</url></snf:logo> - ${posts + ${items} + </channel> +</rss> +`; + +const render = (posts: Notification[] = []) => + channel( + posts .filter((notification: Notification) => notification.type !== undefined) .map((notification: Notification) => { let title = `${notification.user.name}${notification.context}`; @@ -66,28 +72,40 @@ xmlns:media="http://search.yahoo.com/mrss/"> <pubDate>${new Date(notification.createdAt * 1000).toUTCString()}</pubDate> </item>`; }) - .join("")} - </channel> -</rss> -`; - -export const GET = async ({ url }) => { - let token = url.searchParams.get("token"); - const refresh = url.searchParams.get("refresh"); - let notification = await notifications(token || ""); + .join(""), + ); - if (notification === null) { - token = ( - await (await fetch(root(`/api/oauth/refresh?token=${refresh}`))).json() - ).access_token; +// Old feed URLs carried the tokens in clear (?token=&refresh=); they no longer +// resolve, so degrade to a single item nudging the user to re-copy the link +// instead of silently going empty. +const staleNotice = () => + channel(`<item> +<guid isPermaLink="false">due-moe-feed-url-outdated</guid> +<title>${htmlEncode("Your due.moe RSS feed URL is outdated — re-copy it from Settings")}</title> +<link>${siteUrl("/settings#feeds")}</link> +<description>${htmlEncode("This feed link no longer works. Open due.moe → Settings → RSS Feeds and copy the new URL into your reader.")}</description> +<pubDate>${new Date().toUTCString()}</pubDate> +</item>`); - notification = await notifications(token as string); - } - - return new Response(token ? render(notification || []) : render(), { +const feed = (body: string) => + new Response(body, { headers: { - "Cache-Control": `max-age=0`, + "Cache-Control": "max-age=0", "Content-Type": "application/xml", }, }); + +export const GET = async ({ url }) => { + const sealed = url.searchParams.get("feed"); + const refreshToken = sealed ? await decryptFeedToken(sealed) : null; + + if (!refreshToken) return feed(staleNotice()); + + const accessToken = await refreshAniListToken(refreshToken); + + if (!accessToken) return feed(render()); + + const notification = await notifications(accessToken); + + return feed(render(notification || [])); }; |