Skip to content
This repository has been archived by the owner on Aug 3, 2024. It is now read-only.

RSS Feeds #1159

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"dependencies": {
"@ltd/j-toml": "^1.38.0",
"dayjs": "^1.11.7",
"feed": "^4.2.2",
"floating-vue": "^2.0.0-beta.20",
"highlight.js": "^11.7.0",
"js-yaml": "^4.1.0",
Expand Down
67 changes: 67 additions & 0 deletions server/routes/feed/[feed_type]/notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Feed } from 'feed'
import { renderString } from '~/helpers/parse'

export default defineEventHandler(async (event) => {
const config = useRuntimeConfig()
const API_URL = config.apiBaseUrl
const WEBSITE_URL = config.public.siteUrl
const authorization = getHeader(event, 'Authorization')

if (authorization === undefined) {
setResponseStatus(event, 401)
return 'Please pass a valid authentication token to view your notifications as an RSS feed.'
}

try {
const userInfo = await $fetch(API_URL + 'user', {
headers: {
Authorization: authorization,
},
})

const userNotifications = await $fetch(API_URL + `user/${userInfo.id}/notifications`, {
headers: {
Authorization: authorization,
},
})

const feed = new Feed({
title: `Notifications for ${userInfo.username}`,
link: WEBSITE_URL + '/notifications',
generator: 'Modrinth',
description: `${userInfo.username} has ${userNotifications.length} notification${
userNotifications.length === 1 ? '' : 's'
}`,
})

userNotifications.forEach((notification) => {
feed.addItem({
title: renderString(notification.title),
description: renderString(notification.text),
id: notification.id,
link: WEBSITE_URL + notification.link,
date: new Date(notification.created),
})
})

switch (event.context.params.feed_type.toLowerCase()) {
case 'rss':
setResponseHeader(event, 'Content-Type', 'application/rss+xml')
return feed.rss2()
case 'atom':
setResponseHeader(event, 'Content-Type', 'application/atom+xml')
return feed.atom1()
case 'json':
setResponseHeader(event, 'Content-Type', 'application/feed+json')
return feed.json1()
default:
setResponseStatus(event, 500)
return 'Invalid Feed Type'
}
} catch (e) {
setResponseStatus(event, 401)
return (
'Please pass a valid authentication token to view your notifications as an RSS feed.\n\n' + e
)
}
})
71 changes: 71 additions & 0 deletions server/routes/feed/[feed_type]/project/[id].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Feed } from 'feed'
import { renderString } from '~/helpers/parse'

export default defineEventHandler(async (event) => {
const config = useRuntimeConfig()
const API_URL = config.apiBaseUrl
const WEBSITE_URL = config.public.siteUrl

const projectInformation = await $fetch(API_URL + 'project/' + event.context.params.id)
const projectVersions = await $fetch(API_URL + 'project/' + event.context.params.id + '/version')
const projectTeam = await $fetch(API_URL + 'project/' + event.context.params.id + '/members')

let featuredImage = projectInformation.gallery.filter((image) => image.featured)[0]

if (featuredImage) {
featuredImage = featuredImage.url
}

const feed = new Feed({
title: projectInformation.title,
id: projectInformation.id,
description: renderString(projectInformation.description),
generator: 'Modrinth',
link: WEBSITE_URL + `/${projectInformation.project_type}/${projectInformation.id}`,
language: 'en',
updated: new Date(projectInformation.updated),
favicon: projectInformation.icon_url ?? 'https://cdn.modrinth.com/placeholder.png',
image: featuredImage ?? undefined,
})

projectVersions.forEach((version) => {
feed.addItem({
title: `New Version Released: ${version.name}`,
id: `release-${version.id}`,
link:
WEBSITE_URL +
`/${projectInformation.project_type}/${projectInformation.id}/version/${version.id}`,
content:
`This version is for ${version.game_versions.join(', ')}<br>` +
IMB11 marked this conversation as resolved.
Show resolved Hide resolved
// Check for changelog length being greater than 1 to ensure no blank changelog section.
// Legacy changelog support.
IMB11 marked this conversation as resolved.
Show resolved Hide resolved
`<h3>Changelog</h3>${renderString(
version.changelog.length > 1 ? version.changelog : 'No changelog was specified.'
)}`,
author: [
...projectTeam.map((member) => {
return {
name: member.user.username,
link: WEBSITE_URL + `/user/${member.user.id}`,
}
}),
],
IMB11 marked this conversation as resolved.
Show resolved Hide resolved
date: new Date(version.date_published),
})
})

switch (event.context.params.feed_type.toLowerCase()) {
case 'rss':
setResponseHeader(event, 'Content-Type', 'application/rss+xml')
return feed.rss2()
case 'atom':
setResponseHeader(event, 'Content-Type', 'application/atom+xml')
return feed.atom1()
case 'json':
setResponseHeader(event, 'Content-Type', 'application/feed+json')
return feed.json1()
default:
setResponseStatus(event, 500)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 500? This is not a server error

return 'Invalid Feed Type'
}
})