From a2cbb146d7426ecb35e99f494be7383748c1238b Mon Sep 17 00:00:00 2001 From: fcaps Date: Sun, 12 Nov 2023 23:41:34 +0100 Subject: [PATCH] refactor news-routes to be rendered in the backend + removed potential memory-leaking setInterval --- express.js | 6 ++-- package.json | 3 +- public/js/app/news.js | 60 --------------------------------- public/js/app/newsArticle.js | 52 ---------------------------- routes/views/news.js | 60 +++++++++++++++++++++++++++++++++ scripts/extractor.js | 13 ++++--- scripts/getNews.js | 36 -------------------- templates/views/news.pug | 12 ++++--- templates/views/newsArticle.pug | 12 +++---- yarn.lock | 5 +++ 10 files changed, 92 insertions(+), 167 deletions(-) delete mode 100644 public/js/app/news.js delete mode 100644 public/js/app/newsArticle.js create mode 100644 routes/views/news.js delete mode 100644 scripts/getNews.js diff --git a/express.js b/express.js index 3ad756c9..94321794 100644 --- a/express.js +++ b/express.js @@ -11,6 +11,7 @@ let OidcStrategy = require('passport-openidconnect'); const middleware = require('./routes/middleware'); const cors = require('cors'); const app = express(); +const newsRouter = require('./routes/views/news'); app.locals.clanInvitations = {}; @@ -55,7 +56,6 @@ app.use(session({ app.use(passport.initialize()); app.use(passport.session()); -app.use(require('./scripts/getNews')); app.use(flash()); app.use(middleware.username); app.use(middleware.flashMessage); @@ -97,10 +97,12 @@ app.listen(process.env.PORT, () => { // --- R O U T E S --- // when the website is asked to render "/pageName" it will come here and see what are the "instructions" to render said page. If the page isn't here, then the website won't render it properly. +app.use("/news", newsRouter) + // --- UNPROTECTED ROUTES --- const appGetRouteArray = [ // This first '' is the home/index page - '', 'newshub', 'news', 'campaign-missions', 'scfa-vs-faf', 'donation', 'tutorials-guides', 'ai', 'patchnotes', 'faf-teams', 'contribution', 'content-creators', 'tournaments', 'training', 'leaderboards', 'play', 'newsArticle', 'clans',]; + '', 'newshub', 'campaign-missions', 'scfa-vs-faf', 'donation', 'tutorials-guides', 'ai', 'patchnotes', 'faf-teams', 'contribution', 'content-creators', 'tournaments', 'training', 'leaderboards', 'play', 'clans',]; //Renders every page written above appGetRouteArray.forEach(page => app.get(`/${page}`, (req, res) => { diff --git a/package.json b/package.json index a33206e8..37b8eb84 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "passport-openidconnect": "^0.1.1", "pug": "3.0.2", "request": "2.88.2", - "showdown": "^2.1.0" + "showdown": "^2.1.0", + "url-slug": "^4.0.1" }, "devDependencies": { "awesomplete": "^1.1.5", diff --git a/public/js/app/news.js b/public/js/app/news.js deleted file mode 100644 index 857ebee7..00000000 --- a/public/js/app/news.js +++ /dev/null @@ -1,60 +0,0 @@ - -let articleTitleArray = []; - -async function getNewshub() { - const response = await fetch(`js/app/members/news.json`); - const data = await response.json(); - - for (let i = 0; i < data.length; i++) { - let title = data[i].title.replace(/ /g, '-'); - articleTitleArray.push(title); - } - - return await data; -} - - -let articleMain = document.getElementById('articleMain'); - -function updateNewshub() { - getNewshub() - .then(data => { - for (let i = 0; i < data.length; i++) { - articleMain.insertAdjacentHTML("afterbegin", ` -
-
-
- -

-
- -
-
`); - } - let articleImage = document.querySelectorAll('.articleImage'); - let articleTitle = document.querySelectorAll('.articleTitle'); - let articleAuthorDate = document.querySelectorAll('.articleAuthorDate'); - let articleContent = document.querySelectorAll('.articleContent'); - - - for (let i = 0; i < data.length; i++) { - let date = data[i].date; - let content = data[i].content; - articleImage[i].style.backgroundImage = `url("${data[i].media}")`; - articleTitle[i].innerHTML = `${data[i].title}`; - articleAuthorDate[i].innerHTML = `By ${data[i].author} on ${date.substring(0, 10)}`; - articleContent[i].innerHTML = `${content.substring(0, 150)}...`; - } - }); -} - -updateNewshub(); - -function articleActivate(article) { - getNewshub() - .then(data => { - let currentURL = window.location.href; - window.location.href = `${currentURL}/${articleTitleArray[article]}`; - }); -} - diff --git a/public/js/app/newsArticle.js b/public/js/app/newsArticle.js deleted file mode 100644 index cb4091fc..00000000 --- a/public/js/app/newsArticle.js +++ /dev/null @@ -1,52 +0,0 @@ -let articleTitleArray = []; - -async function getNewshub() { - const response = await fetch(`/js/app/members/news.json`); - const data = await response.json(); - -//we push the title names into an array so we can loop through the different routes - for (let i = 0; i < data.length; i++) { - let title = data[i].title.replace(/ /g, '-'); - articleTitleArray.push(title); - } - return await data; -} - - -let activeTitle = document.getElementById('title'); -let activeAuthorDate = document.getElementById('authorDate'); -let activeImage = document.getElementById('featuredImage'); -let activeContent = document.getElementById('content'); -let activeBackground = document.getElementById('newsBackground'); -let randomNumber = Math.floor(Math.random() * (3 + 1)); - -function articleActivate(article) { - getNewshub() - .then(data => { - let date = data[article].date; - activeTitle.innerHTML = data[article].title; - activeAuthorDate.innerHTML = `By ${data[article].author} on ${date.substring(0, 10)}`; - activeImage.innerHTML = `News`; - activeContent.innerHTML = data[article].content; - activeBackground.style.backgroundImage = `url("../../images/black${randomNumber}.jpg")`; - }); -} - -//So here we check the name of the article in the url and display the article, the slice is done so we only check the title and not the name. - -let url = window.location.href; -const sliceIndicator = url.indexOf('/news'); -// The slice has + 9 because thats the amount of characters in "/newshub/" yes with two /, not one! -let findMatch = url.slice(sliceIndicator + 6); - -getNewshub() - .then(data => { - for (let i = 0; i < data.length; i++) { - if (articleTitleArray[i] === findMatch) { - articleActivate(i); - } - } - }); - - - diff --git a/routes/views/news.js b/routes/views/news.js new file mode 100644 index 00000000..f1b7a3a5 --- /dev/null +++ b/routes/views/news.js @@ -0,0 +1,60 @@ +const express = require('express'); +const router = express.Router(); +const fs = require('fs') + +function getNewsArticles() { + const readFile = fs.readFileSync('./public/js/app/members/news.json', + {encoding:'utf8', flag:'r'}); + return JSON.parse(readFile); +} + +function getNewsArticleBySlug(articles, slug) { + let [newsArticle] = articles.filter((entry) => { + if (entry.slug === slug) { + return entry + } + }) ?? [] + + return newsArticle ?? null +} + +function getNewsArticleByDeprecatedSlug(articles, slug) { + let [newsArticle] = articles.filter((entry) => { + if (entry.bcSlug === slug) { + return entry + } + }) ?? [] + + return newsArticle ?? null +} + +router.get(`/`, (req, res) => { + res.render('news', {news: getNewsArticles()}); +}) + +router.get(`/:slug`, (req, res) => { + const newsArticles = getNewsArticles(); + const newsArticle = getNewsArticleBySlug(newsArticles, req.params.slug) + + if (newsArticle === null) { + const newsArticleByOldSlug = getNewsArticleByDeprecatedSlug(newsArticles, req.params.slug) + + if (newsArticleByOldSlug) { + // old slug style, here for backward compatibility + res.redirect(301, newsArticleByOldSlug.slug) + + return + } + + res.redirect(req.baseUrl) + + return + } + + res.render('newsArticle', { + newsArticle: newsArticle + }); + +}) + +module.exports = router diff --git a/scripts/extractor.js b/scripts/extractor.js index bd382514..80b0ffc3 100644 --- a/scripts/extractor.js +++ b/scripts/extractor.js @@ -6,6 +6,7 @@ process.env.WP_URL = process.env.WP_URL || 'https:direct.faforever.com'; const fs = require('fs'); const axios = require('axios'); +const {convert} = require('url-slug') let d = new Date(); let timeFilter = 12; @@ -64,11 +65,13 @@ async function news() { //Now we get a js array rather than a js object. Otherwise we can't sort it out. let dataObjectToArray = Object.values(response.data); let data = dataObjectToArray.map(item => ({ - date: item.date, - title: item.title.rendered, - content: item.content.rendered, - author: item._embedded.author[0].name, - media: item._embedded['wp:featuredmedia'][0].source_url, + slug: convert(item.title.rendered), + bcSlug: item.title.rendered.replace(/ /g, '-'), + date: item.date, + title: item.title.rendered, + content: item.content.rendered, + author: item._embedded.author[0].name, + media: item._embedded['wp:featuredmedia'][0].source_url, })); return await data; } catch (e) { diff --git a/scripts/getNews.js b/scripts/getNews.js deleted file mode 100644 index ebe3fc46..00000000 --- a/scripts/getNews.js +++ /dev/null @@ -1,36 +0,0 @@ -const fs = require('fs'); -const {Router} = require('express'); -const router = Router(); - -// Interval so the news update themselves -setInterval(()=>{ - - - try { -//We get our news title from here -const readFile = fs.readFileSync('./public/js/app/members/news.json', - {encoding:'utf8', flag:'r'}); -const data = JSON.parse(readFile); - - -let articleTitle = []; - -//we push the title names into an array so we can loop through the different routes\ - - for (let i = 0; i < data.length; i++) { - let title = data[i].title.replace(/ /g, '-'); - articleTitle.push(title); - } - //we create a get route for each article found - articleTitle.forEach(page => router.get(`/news/${page}`, (req, res) => { - res.render('newsArticle'); - })); - } catch (e) { - console.log('error on flash!') - } - - -},1000 * 60 * 5); - - -module.exports = router; diff --git a/templates/views/news.pug b/templates/views/news.pug index 734fe927..df2bfa9d 100644 --- a/templates/views/news.pug +++ b/templates/views/news.pug @@ -7,7 +7,11 @@ block content h2 Recent h1.highlightText News #articleMain.column12 - - -block js - script( src="../../js/app/news.js") + each newsArticle in news + div(class=['articleContainer', 'column4']) + div.articleImage(style='background-image:url(' + newsArticle.media + ')' ) + div.articleText + h2.articleAuthorDate=`By ${newsArticle.author} on ${newsArticle.date.substring(0, 10)}` + h1.articleTitle=newsArticle.title + div.articleContent !{newsArticle.content.substring(0, 150)} ... + button(onClick="window.location.href = '/news/" + newsArticle.slug + "'") Learn More diff --git a/templates/views/newsArticle.pug b/templates/views/newsArticle.pug index f0ca4a62..f8a586f3 100644 --- a/templates/views/newsArticle.pug +++ b/templates/views/newsArticle.pug @@ -6,16 +6,14 @@ block content .newsAbsolute a(href='/news') button Back to News page - #newsBackground - + #newsBackground(style='background-image:url(\'/images/black' + Math.floor(Math.random() * 4) + '.jpg\')' ) #newsMain .newsContainer.column12 - h1#title + h1#title=newsArticle.title .newsContainer.column12 #featuredImage + img(src=newsArticle.media alt=newsArticle.title) .newsContainer.column12 - h1#authorDate + h1#authorDate=`By ${newsArticle.author} on ${newsArticle.date.substring(0, 10)}` .newsContainer.column12 - #content -block js - script( src="../../js/app/newsArticle.js") + #content !{newsArticle.content} diff --git a/yarn.lock b/yarn.lock index 9a1cedc6..6af508b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5727,6 +5727,11 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" +url-slug@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-slug/-/url-slug-4.0.1.tgz#e6c52589d671598339fe97a32edc415687a3489a" + integrity sha512-OkHgffjR6bce7jNTp5BUDBhg2IcnqSAi9DEhLH8Rhxrq84uPBMbHFzvOxniEIRpSSGBcG13LhrtNR5XzUdztfQ== + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"