aboutsummaryrefslogtreecommitdiff
path: root/src/routes/feeds/activity-notifications/+server.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes/feeds/activity-notifications/+server.ts')
-rw-r--r--src/routes/feeds/activity-notifications/+server.ts64
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 || []));
};