import { User, Pagination } from './index' import * as 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) } async function cleanArticle (entry) { const poster = await User.get(entry.user_id) const article = { id: entry.id, slug: slugify(entry.title), title: entry.title, content: entry.content, tags: entry.tags.split(','), created_at: entry.created_at, updated_at: entry.updated_at } if (poster) { article.author = { id: poster.id, display_name: poster.display_name, email: poster.email } } article.description = article.content.replace(/(<([^>]+)>)/ig, '').replace(/\n/g, ' ').substring(0, 197) + '...' return article } export async function preview () { // Fetch 3 latest stories const news = await Models.News.query().orderBy('created_at', 'desc').limit(3) if (!news.length) return [] const articles = [] for (const i in news) { const entry = news[i] articles.push(await cleanArticle(entry)) } return articles } export async function listNews (page) { let count = await Models.News.query().count('id as ids') if (page < 1) page = 1 if (!count.length || !count[0].ids || isNaN(page)) { return { error: 'No news' } } count = count[0].ids const paginated = Pagination(perPage, parseInt(count), page) const news = await Models.News.query().orderBy('created_at', 'desc').offset(paginated.offset).limit(perPage) const articles = [] for (const i in news) { const entry = news[i] articles.push(await cleanArticle(entry)) } return { page: paginated, articles: articles } } export async function article (id) { let article = await Models.News.query().where('id', id) if (!article.length) return {} article = article[0] return cleanArticle(article) } export async function compose (user, body) { const article = { title: body.title, content: body.content, tags: body.tags || '', user_id: user.id, created_at: new Date(), updated_at: new Date() } const result = await Models.News.query().insert(article) result.slug = slugify(result.title) return result } export async function edit (id, body) { const patch = { content: body.content, updated_at: new Date() } const result = await Models.News.query().patchAndFetchById(id, patch) if (!result) throw new Error('Something went wrong.') return {} } export async function generateFeed () { if (feed && new Date(feed.options.updated).getTime() > Date.now() - 3600000) return feed // Update feed hourly const posts = await Models.News.query().orderBy('created_at', 'desc').limit(perPage) const cleanNews = [] for (const 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: '2020 Icy Network', updated: new Date(), feedLinks: { json: config.server.domain + '/news/feed.json', atom: config.server.domain + '/news/atom.xml' }, author: { name: 'Icy Network', email: 'icynet@icynet.eu', link: config.server.domain } }) for (const i in cleanNews) { const post = cleanNews[i] feed.addItem({ title: post.title, 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, link: config.server.domain }], date: new Date(post.updated_at) }) } return feed }