Implement Atom feed for news page
This commit is contained in:
parent
4df05ad316
commit
265acc187f
15
package-lock.json
generated
15
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "icynet.eu",
|
||||
"version": "0.0.1-alpha1",
|
||||
"version": "0.9.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -2679,6 +2679,14 @@
|
||||
"pend": "1.2.0"
|
||||
}
|
||||
},
|
||||
"feed": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/feed/-/feed-1.1.1.tgz",
|
||||
"integrity": "sha1-kUiXUX6U+jJ8xvc7tYWkfEqe0yE=",
|
||||
"requires": {
|
||||
"xml": "1.0.1"
|
||||
}
|
||||
},
|
||||
"figures": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
|
||||
@ -7740,6 +7748,11 @@
|
||||
"mkdirp": "0.5.1"
|
||||
}
|
||||
},
|
||||
"xml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
|
||||
"integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
||||
|
@ -41,6 +41,7 @@
|
||||
"express": "^4.16.2",
|
||||
"express-rate-limit": "^2.9.0",
|
||||
"express-session": "^1.15.6",
|
||||
"feed": "^1.1.1",
|
||||
"fs-extra": "^4.0.2",
|
||||
"gm": "^1.23.0",
|
||||
"knex": "^0.13.0",
|
||||
|
@ -1,8 +1,13 @@
|
||||
import API from './index'
|
||||
import Models from './models'
|
||||
import config from '../../scripts/load-config'
|
||||
|
||||
import Feed from 'feed'
|
||||
|
||||
const perPage = 8
|
||||
|
||||
let feed
|
||||
|
||||
function slugify (title) {
|
||||
return title.toLowerCase().replace(/\W/g, '-').substring(0, 32)
|
||||
}
|
||||
@ -22,13 +27,12 @@ async function cleanArticle (entry, shortenContent = false) {
|
||||
if (poster) {
|
||||
article.author = {
|
||||
id: poster.id,
|
||||
display_name: poster.display_name
|
||||
display_name: poster.display_name,
|
||||
email: poster.email
|
||||
}
|
||||
}
|
||||
|
||||
if (shortenContent) {
|
||||
article.content = article.content.replace(/(<([^>]+)>)/ig, '').substring(0, 128) + '...'
|
||||
}
|
||||
article.description = article.content.replace(/(<([^>]+)>)/ig, '').replace(/\n/g, ' ').substring(0, 197) + '...'
|
||||
|
||||
return article
|
||||
}
|
||||
@ -43,7 +47,7 @@ const News = {
|
||||
let articles = []
|
||||
for (let i in news) {
|
||||
let entry = news[i]
|
||||
articles.push(await cleanArticle(entry, true))
|
||||
articles.push(await cleanArticle(entry))
|
||||
}
|
||||
|
||||
return articles
|
||||
@ -102,6 +106,55 @@ const News = {
|
||||
let result = await Models.News.query().patchAndFetchById(id, patch)
|
||||
if (!result) throw new Error('Something went wrong.')
|
||||
return {}
|
||||
},
|
||||
generateFeed: async () => {
|
||||
if (feed && new Date(feed.options.updated).getTime() > Date.now() - 3600000) return feed // Update feed hourly
|
||||
|
||||
let posts = await Models.News.query().orderBy('created_at', 'desc').limit(perPage)
|
||||
let cleanNews = []
|
||||
|
||||
for (let i in posts) {
|
||||
cleanNews.push(await cleanArticle(posts[i]))
|
||||
}
|
||||
|
||||
feed = new Feed({
|
||||
title: 'Icy Network News',
|
||||
description: 'Icy Network News',
|
||||
id: config.server.domain + '/news',
|
||||
link: config.server.domain + '/news',
|
||||
image: config.server.domain + '/static/image/icynet-icon.png',
|
||||
favicon: config.server.domain + '/favicon.ico',
|
||||
copyright: '2018 Icy Network - Some Rights Reserved',
|
||||
updated: new Date(),
|
||||
feedLinks: {
|
||||
json: config.server.domain + '/news/feed.json',
|
||||
atom: config.server.domain + '/news/atom.xml'
|
||||
},
|
||||
author: {
|
||||
name: 'Icy Network',
|
||||
email: 'icynet@lunasqu.ee',
|
||||
link: config.server.domain
|
||||
}
|
||||
})
|
||||
|
||||
for (let i in cleanNews) {
|
||||
let post = cleanNews[i]
|
||||
|
||||
feed.addItem({
|
||||
title: post.title,
|
||||
id: post.id,
|
||||
link: `${config.server.domain}/news/${post.id}-${slugify(post.title)}`,
|
||||
description: post.description,
|
||||
content: post.content,
|
||||
author: [{
|
||||
name: post.author.display_name,
|
||||
email: post.author.email
|
||||
}],
|
||||
date: new Date(post.updated_at)
|
||||
})
|
||||
}
|
||||
|
||||
return feed
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -797,6 +797,20 @@ router.get('/news/', wrap(async (req, res) => {
|
||||
res.render('news/news', {news: news})
|
||||
}))
|
||||
|
||||
router.get('/news/atom.xml', wrap(async (req, res) => {
|
||||
let feed = await News.generateFeed()
|
||||
|
||||
res.set('Content-Type', 'application/atom+xml')
|
||||
res.send(feed.atom1())
|
||||
}))
|
||||
|
||||
router.get('/news/feed.json', wrap(async (req, res) => {
|
||||
let feed = await News.generateFeed()
|
||||
|
||||
res.set('Content-Type', 'application/json')
|
||||
res.send(feed.json1())
|
||||
}))
|
||||
|
||||
// Render partials
|
||||
router.get('/partials/:view', (req, res, next) => {
|
||||
if (!req.params.view) return next()
|
||||
|
@ -204,7 +204,7 @@ $(document).ready(function () {
|
||||
html += '<div class="prvarticle">'
|
||||
html += '<a class="title" href="/news/' + article.id + '-' + article.slug + '">' + article.title + '</a>'
|
||||
html += '<span class="timestamp">Published at ' + new Date(article.created_at) + '</span>'
|
||||
html += '<div class="prvcontent">' + article.content + '</div>'
|
||||
html += '<div class="prvcontent">' + article.description + '</div>'
|
||||
html += '<a href="/news/' + article.id + '-' + article.slug + '">Read More</a>'
|
||||
html += '</div>'
|
||||
}
|
||||
|
@ -3,6 +3,14 @@ html
|
||||
head
|
||||
meta(charset="utf8")
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1")
|
||||
block meta
|
||||
meta(name="og:title", content="Icy Network")
|
||||
meta(name="og:description", content="Icy Network is a Global Network of Communities and Websites, United by a Single Login")
|
||||
meta(name="og:image", content="https://icynet.eu/static/image/icynet-icon.png")
|
||||
meta(name="og:type", content="website")
|
||||
meta(name="twitter:card", content="summary")
|
||||
meta(name="twitter:title", content="Icy Network")
|
||||
meta(name="twitter:description", content="Icy Network is a Global Network of Communities and Websites, United by a Single Login")
|
||||
if matomo
|
||||
script(type="text/javascript").
|
||||
var _paq = _paq || [];
|
||||
|
@ -1,5 +1,18 @@
|
||||
extends ../layout.pug
|
||||
|
||||
block meta
|
||||
if article
|
||||
meta(name="description", content=article.description)
|
||||
meta(name="og:title", content=article.title)
|
||||
meta(name="og:description", content=article.description)
|
||||
meta(name="og:image", content="https://icynet.eu/static/image/icynet-icon.png")
|
||||
meta(name="og:type", content="article")
|
||||
meta(name="og:updated_time", content=article.updated_at)
|
||||
meta(name="twitter:card", content="summary")
|
||||
meta(name="twitter:title", content=article.title)
|
||||
meta(name="twitter:description", content=article.description)
|
||||
link(rel="alternate", href="/news/atom.xml", title="Icy Network News", type="application/atom+xml")
|
||||
|
||||
block append links
|
||||
if editing
|
||||
script(src="//cdnjs.cloudflare.com/ajax/libs/ckeditor/4.7.2/ckeditor.js")
|
||||
|
@ -1,5 +1,8 @@
|
||||
extends ../layout.pug
|
||||
|
||||
block append meta
|
||||
link(rel="alternate", href="/news/atom.xml", title="Icy Network News", type="application/atom+xml")
|
||||
|
||||
block title
|
||||
|Icy Network - News
|
||||
|
||||
|
Reference in New Issue
Block a user