CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/next/pages/news/feed.json.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2023 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import LRU from "lru-cache";
7
8
import { get } from "@cocalc/server/news/get";
9
import getCustomize from "@cocalc/database/settings/customize";
10
import { slugURL } from "@cocalc/util/news";
11
import { NewsItem } from "@cocalc/util/types/news";
12
import { renderMarkdown } from "lib/news";
13
import { GetServerSideProps } from "next";
14
import IconLogo from "public/logo/icon.svg";
15
16
const cache = new LRU<"feed", any>({ max: 10, ttl: 60 * 1000 });
17
18
export default function RSS() {
19
return null;
20
}
21
22
export const getServerSideProps: GetServerSideProps = async ({ res }) => {
23
if (!res) return { props: {} };
24
25
try {
26
res.setHeader("Content-Type", "application/feed+json");
27
res.setHeader("Cache-Control", "public, max-age=3600");
28
res.write(JSON.stringify(await feed()));
29
res.end();
30
} catch (err) {
31
console.error(err);
32
res.statusCode = 500;
33
res.write(JSON.stringify({ error: `${err.message}` }));
34
res.end();
35
}
36
37
return {
38
props: {},
39
};
40
};
41
42
async function feed() {
43
const cached = cache.get("feed");
44
if (cached) return cached;
45
const data = await get();
46
const feed = await getFeed(data);
47
48
cache.set("feed", feed);
49
return feed;
50
}
51
52
function getItems(data: NewsItem[], dns): object[] {
53
return data.map((n) => {
54
const { id, text, title, date, url } = n;
55
const date_published = (
56
typeof date === "number" ? new Date(date * 1000) : date
57
).toISOString();
58
const selfURL = `https://${dns}/${slugURL(n)}`;
59
60
return {
61
id,
62
url: selfURL,
63
external_url: url,
64
title,
65
content_html: renderMarkdown(text),
66
date_published,
67
};
68
});
69
}
70
71
// This follows https://www.jsonfeed.org/version/1.1/
72
async function getFeed(data: NewsItem[]): Promise<object> {
73
const { siteName, dns } = await getCustomize();
74
const icon_url = IconLogo.src;
75
const home_page_url = `https://${dns}/news`;
76
const feed_url = `https://${dns}/feed.json`;
77
78
const feed = {
79
version: "https://jsonfeed.org/version/1.1",
80
title: `${siteName} News`,
81
home_page_url,
82
description: `News about ${siteName} – also available at https://${dns}/news`,
83
icon: icon_url,
84
favicon: icon_url,
85
feed_url,
86
items: getItems(data, dns),
87
};
88
89
return feed;
90
}
91
92