Added user specific RSS and ATOM feeds and updated the EJS templates to

add them by default to the user's header section
This commit is contained in:
2025-07-30 01:28:23 +01:00
parent 72316094e4
commit 0cc319a702
8 changed files with 83 additions and 9 deletions

View File

@@ -18,7 +18,7 @@ Read the [configuation guide](docs/CONFIG.md) for configuration help (in config.
* user creation, modification and deletion via frontend
* multi user
* powerful customisation via EJS
* site wide rss, atom
* site wide and user specific rss, atom
* hitcount
* Markdown syntax in posts
* Commenting on posts
@@ -29,7 +29,6 @@ Read the [configuation guide](docs/CONFIG.md) for configuration help (in config.
* probably insecure as hell
# Planned features/todo list
* user specific RSS/atom feeds
* federation (looks tricky)
* All strings (including in edit and post page) customisable
* formatable custom strings

View File

@@ -29,7 +29,7 @@ export function unix_time_to_rss_date(unix_time) {
export function unix_time_to_atom_date(unix_time) {
const { fromUnixTime, format, getUnixTime } = require("date-fns") // A date utility library
let date = fromUnixTime(unix_time)
let formatted_date = format(date, "yyyy-MM-dd\\THH:mm:ss\\Z")
let formatted_date = format(date, "yyyy-MM-dd'T'HH:mm:ss'Z'")
return `${formatted_date}`
}
// This function accepts a list of strings eg ["string1","string2,"string3"] (any length)

View File

@@ -60,7 +60,7 @@ app.set('view engine', 'ejs');
app.set('views', '../views')
////////////////////// SYNDICATION ////////////////////////
// RSS protocol gets
// global RSS protocol gets
app.get("/rss", (req,res) => {
if (config.rss == false) {
res.render("partials/message", {
@@ -78,7 +78,28 @@ app.get("/rss", (req,res) => {
})
};
});
// ATOM protocol gets
// user RSS protocol gets
app.get("/user/:username/rss", (req,res) => {
const username = req.params.username;
const userID = func.get_userID(username);
if (config.rss == false) {
res.render("partials/message", {
message: config.string.rss_disabled,
config: config,
})
}
else {
res.setHeader('content-type', 'application/rss+xml');
res.render("syndication/user_rss", {
config,
posts,
converter,
func,
userID,
})
};
});
// global ATOM protocol gets
app.get("/atom", (req,res) => {
if (config.rss == false) {
res.render("partials/message", {
@@ -93,6 +114,29 @@ app.get("/atom", (req,res) => {
posts,
converter,
func,
getUnixTime,
})
};
});
// user ATOM protocol gets
app.get("/user/:username/atom", (req,res) => {
const username = req.params.username;
const userID = func.get_userID(username);
if (config.rss == false) {
res.render("partials/message", {
message: config.string.rss_disabled,
config: config,
})
}
else {
res.setHeader('content-type', 'application/rss+xml');
res.render("syndication/user_atom", {
config,
posts,
converter,
func,
userID,
getUnixTime,
})
};
});

View File

@@ -4,7 +4,8 @@
<h2>
<%- config.site_description %>
</h2>
<a href="<%= config.rss_url %>">RSS Feed</a><br/>
<a href="/rss">RSS Feed</a><br/>
<a href="/atom">ATOM Feed</a><br/>
<a href="<%= config.new_post_url %>">New post</a><br/>
<a href="<%= config.signup_url %>">Sign Up</a><br/>
<% if (config.enable_hitcount == true) { %>

View File

@@ -2,5 +2,7 @@
<%= user.prettyname %>'s posts
</h1>
<p><%- converter.makeHtml(user.description) %></p>
<a href="<%= config.edit_account_base_url %>/<%= userID %>">edit account</a>
<a href="<%= config.edit_account_base_url %>/<%= userID %>">edit account</a><br/>
<a href="/user/<%= user.username %>/rss">RSS</a><br/>
<a href="/user/<%= user.username %>/atom">ATOM</a>
<%- config.seperator %>

View File

@@ -3,7 +3,7 @@
<title><%= config.site_name %></title>
<link><%= config.site_url %></title>
<description><%= config.site_description %></description>
<updated><%= new Date() %></updated>
<updated><%= func.unix_time_to_atom_date(getUnixTime(new Date())) %></updated>
<id><%= config.site_url %></id>
<% for (let postID = posts.length-1; postID >= 0; postID--) { %>
<% if (posts[postID]["deleted"] != true) { %>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="<%= config.charset %>" ?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><%= config.site_name %></title>
<link><%= config.site_url %></title>
<description><%= config.site_description %></description>
<updated><%= func.unix_time_to_atom_date(getUnixTime(new Date())) %></updated>
<id><%= config.site_url %></id>
<% for (let postID = posts.length-1; postID >= 0; postID--) { %>
<% if (posts[postID]["userID"] == userID) { %>
<% if (posts[postID]["deleted"] != true) { %>
<entry>
<title><%= posts[postID]["title"] %></title>
<link><%= config.site_url %>/post/<%= postID %></link>
<summary><![CDATA[<%- converter.makeHtml(posts[postID]["content"]) %>]]></summary>
<guid isPermaLink="true"><%= config.site_url %>/post/<%= postID %></guid>
<pubDate><%# func.unix_time_to_atom_date(posts[postID]['pubdate']) %></pubDate>
<% for (let tag_index = 0; tag_index < posts[postID]['tags'].length; tag_index++) { %>
<category><![CDATA[<%= posts[postID]['tags'][tag_index] %>]]></category>
<% } %>
</entry>
<% } %>
<% } %>
<% } %>
</feed>

View File

@@ -5,10 +5,12 @@
<link><%= config.site_url %></title>
<description><%= config.site_description %></description>
<% for (let postID = posts.length-1; postID >= 0; postID--) { %>
<% if (posts[postID]["userID"] == userID) { %>
<% if (posts[postID]["deleted"] != true) { %>
<item>
<title><%= posts[postID]["title"] %></title>
<link><%= config.site_url %>/post/<%= postID %></link>
<description><![CDATA[<%= converter.makeHtml(posts[postID]["content"]) %>]]></description>
<description><![CDATA[<%- converter.makeHtml(posts[postID]["content"]) %>]]></description>
<guid isPermaLink="true"><%= config.site_url %>/post/<%= postID %></guid>
<pubDate><%= func.unix_time_to_rss_date(posts[postID]['pubdate']) %></pubDate>
<% for (let tag_index = 0; tag_index < posts[postID]['tags'].length; tag_index++) { %>
@@ -16,5 +18,7 @@
<% } %>
</item>
<% } %>
<% } %>
<% } %>
</channel>
</rss>