commit 33d644c63fbe199711c692badcc7753737b2be45
parent 238dbfec1df6e137de1326423c598210f653e5e5
Author: MTRNord <mtrnord1@gmail.com>
Date: Fri, 14 Jan 2022 19:55:44 +0100
Add very basic rss feed support
Diffstat:
5 files changed, 183 insertions(+), 1 deletion(-)
diff --git a/next.config.js b/next.config.js
@@ -36,4 +36,13 @@ module.exports = {
eslint: {
dirs: ['pages', 'components', "helpers", "e2e"],
},
+ async redirects() {
+ return [
+ {
+ source: '/posts.rss',
+ destination: '/api/posts/feed.rss',
+ permanent: false,
+ },
+ ]
+ },
}
diff --git a/package-lock.json b/package-lock.json
@@ -7,6 +7,7 @@
"name": "matrix-art",
"dependencies": {
"cors": "^2.8.5",
+ "feed": "^4.2.2",
"lightgallery": "^2.3.0",
"meilisearch": "^0.23.0",
"next": "12.0.7",
@@ -4465,6 +4466,17 @@
"pend": "~1.2.0"
}
},
+ "node_modules/feed": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz",
+ "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==",
+ "dependencies": {
+ "xml-js": "^1.6.11"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/fetch-cookie": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.10.1.tgz",
@@ -7490,6 +7502,11 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "node_modules/sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
"node_modules/scheduler": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
@@ -8520,6 +8537,17 @@
}
}
},
+ "node_modules/xml-js": {
+ "version": "1.6.11",
+ "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
+ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
+ "dependencies": {
+ "sax": "^1.2.4"
+ },
+ "bin": {
+ "xml-js": "bin/cli.js"
+ }
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -11959,6 +11987,14 @@
"pend": "~1.2.0"
}
},
+ "feed": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz",
+ "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==",
+ "requires": {
+ "xml-js": "^1.6.11"
+ }
+ },
"fetch-cookie": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.10.1.tgz",
@@ -14170,6 +14206,11 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
"scheduler": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
@@ -14976,6 +15017,14 @@
"dev": true,
"requires": {}
},
+ "xml-js": {
+ "version": "1.6.11",
+ "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
+ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
+ "requires": {
+ "sax": "^1.2.4"
+ }
+ },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
@@ -17,6 +17,7 @@
},
"dependencies": {
"cors": "^2.8.5",
+ "feed": "^4.2.2",
"lightgallery": "^2.3.0",
"meilisearch": "^0.23.0",
"next": "12.0.7",
diff --git a/pages/api/directory.tsx b/pages/api/directory.tsx
@@ -8,7 +8,6 @@ const db = new PouchDB(path.join(process.cwd(), "matrix-art-db"));
// Initialize the cors middleware
const cors = initMiddleware(
- // You can read more about the available options here: https://github.com/expressjs/cors#configuration-options
Cors({
// Only allow requests with GET, POST, DELETE and OPTIONS
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
diff --git a/pages/api/posts/feed.rss.ts b/pages/api/posts/feed.rss.ts
@@ -0,0 +1,123 @@
+import initMiddleware from "../../../helpers/init-middleware";
+import Cors from 'cors';
+import { NextApiRequest, NextApiResponse } from "next";
+import { Feed } from "feed";
+import { get_data } from "../directory";
+import { client } from "../../../components/ClientContext";
+import { constMatrixArtServer } from "../../../helpers/matrix_client";
+import { MatrixImageEvents } from "../../../helpers/event_types";
+import { isImageGalleryEvent } from "../../../components/FrontPageImage";
+
+// Initialize the cors middleware
+const cors = initMiddleware(
+ Cors({
+ // Only allow requests with GET and OPTIONS
+ methods: ['GET', 'OPTIONS'],
+ })
+);
+
+export default async function handler(req: NextApiRequest, res: NextApiResponse) {
+ // Run cors
+ await cors(req, res);
+
+ if (req.method !== "GET") {
+ res.status(504);
+ }
+
+ res.setHeader("content-type", "application/rss+xml");
+ const feed = new Feed({
+ title: "Matrix-Art",
+ description: "Matrix-Art is a Devianart style application for posting media based on Matrix.",
+ id: "https://" + (req.headers.host || "art.midnightthoughts.space"),
+ link: "https://" + (req.headers.host || "art.midnightthoughts.space"),
+ language: "en",
+ copyright: "",
+ feed: "https://" + (req.headers.host || "art.midnightthoughts.space") + "/posts.rss"
+ });
+
+ try {
+ const directory = await get_data();
+
+ if (!client?.accessToken) {
+ try {
+ let serverUrl = constMatrixArtServer + "/_matrix/client";
+ await client?.registerAsGuest(serverUrl);
+ } catch (error) {
+ console.error("Failed to register as guest:", error);
+ return {
+ props: {
+ image_events: []
+ }
+ };
+ }
+ }
+ let image_events: MatrixImageEvents[] = [];
+ // TODO fix this somehow. It is super inefficent.
+ for (let user of directory) {
+ // We dont need many events
+ const roomId = await client?.followUser(user.user_room);
+ const events = await client?.getTimeline(roomId, 100);
+ // Filter events by type
+ let images = events.filter((event) => event.type == "m.image_gallery" || event.type == "m.image") as MatrixImageEvents[];
+ images = await Promise.all(images.map(async (image) => {
+ try {
+ const profile = await client.getProfile(image.sender);
+ image.content.displayname = profile.displayname;
+ } catch {
+ image.content.displayname = image.sender;
+ }
+ return image;
+ }));
+ image_events = [...image_events, ...images];
+ console.log("Adding", image_events.length, "items");
+ }
+
+ for (let imageEvent of image_events) {
+ feed.addContributor({
+ name: imageEvent.content.displayname
+ });
+ if (isImageGalleryEvent(imageEvent)) {
+ for (let image of imageEvent.content["m.image_gallery"]) {
+ feed.addItem({
+ title: image["m.text"],
+ id: "https://" + (req.headers.host || "art.midnightthoughts.space") + "/post/" + imageEvent.event_id + "_" + image["m.file"].url,
+ link: "https://" + (req.headers.host || "art.midnightthoughts.space") + "/post/" + imageEvent.event_id,
+ description: "",
+ content: "",
+ author: [
+ {
+ name: imageEvent.content.displayname,
+ }
+ ],
+ // TODO extract real time
+ date: new Date(),
+ image: client?.downloadLink(image["m.file"].url)
+ });
+ }
+ } else {
+ feed.addItem({
+ title: imageEvent.content["m.text"],
+ id: "https://" + (req.headers.host || "art.midnightthoughts.space") + "/post/" + imageEvent.event_id,
+ link: "https://" + (req.headers.host || "art.midnightthoughts.space") + "/post/" + imageEvent.event_id,
+ description: "",
+ content: "",
+ author: [
+ {
+ name: imageEvent.content.displayname,
+ }
+ ],
+ date: new Date(),
+ image: client?.downloadLink(imageEvent.content["m.file"].url)
+ });
+ }
+
+ }
+
+ } catch { }
+
+ feed.addCategory("Photography");
+ feed.addCategory("Media");
+ feed.addCategory("Images");
+ feed.addCategory("SocialMedia");
+ res.status(200).send(feed.atom1());
+}
+\ No newline at end of file