'use strict'; const { SitemapStream, streamToPromise } = require('sitemap'); const nconf = require('nconf'); const db = require('./database'); const categories = require('./categories'); const topics = require('./topics'); const privileges = require('./privileges'); const meta = require('./meta'); const plugins = require('./plugins'); const utils = require('./utils'); const sitemap = module.exports; sitemap.maps = { topics: [], }; sitemap.render = async function () { const topicsPerPage = meta.config.sitemapTopics; const returnData = { url: nconf.get('url'), topics: [], }; const topicCount = await db.getObjectField('global', 'topicCount'); const numPages = Math.ceil(Math.max(0, topicCount / topicsPerPage)); for (var x = 1; x <= numPages; x += 1) { returnData.topics.push(x); } return returnData; }; sitemap.getPages = async function () { if (sitemap.maps.pages && Date.now() < sitemap.maps.pagesCacheExpireTimestamp) { return sitemap.maps.pages.toString(); } const urls = [{ url: '', changefreq: 'weekly', priority: 0.6, }, { url: '/recent', changefreq: 'daily', priority: 0.4, }, { url: '/users', changefreq: 'daily', priority: 0.4, }, { url: '/groups', changefreq: 'daily', priority: 0.4, }]; const data = await plugins.fireHook('filter:sitemap.getPages', { urls: urls }); const smStream = new SitemapStream({ hostname: nconf.get('url') }); data.urls.forEach(url => smStream.write(url)); smStream.end(); sitemap.maps.pages = await streamToPromise(smStream); sitemap.maps.pagesCacheExpireTimestamp = Date.now() + (1000 * 60 * 60 * 24); return sitemap.maps.pages.toString(); }; sitemap.getCategories = async function () { if (sitemap.maps.categories && Date.now() < sitemap.maps.categoriesCacheExpireTimestamp) { return sitemap.maps.categories.toString(); } const categoryUrls = []; const categoriesData = await categories.getCategoriesByPrivilege('categories:cid', 0, 'find'); categoriesData.forEach(function (category) { if (category) { categoryUrls.push({ url: '/category/' + category.slug, changefreq: 'weekly', priority: 0.4, }); } }); const smStream = new SitemapStream({ hostname: nconf.get('url') }); categoryUrls.forEach(url => smStream.write(url)); smStream.end(); sitemap.maps.categories = await streamToPromise(smStream); sitemap.maps.categoriesCacheExpireTimestamp = Date.now() + (1000 * 60 * 60 * 24); return sitemap.maps.categories.toString(); }; sitemap.getTopicPage = async function (page) { if (parseInt(page, 10) <= 0) { return; } const numTopics = meta.config.sitemapTopics; const min = (parseInt(page, 10) - 1) * numTopics; const max = min + numTopics; if (sitemap.maps.topics[page - 1] && Date.now() < sitemap.maps.topics[page - 1].cacheExpireTimestamp) { return sitemap.maps.topics[page - 1].sm.toString(); } const topicUrls = []; let tids = await db.getSortedSetRevRange('topics:recent', min, max); tids = await privileges.topics.filterTids('topics:read', tids, 0); const topicData = await topics.getTopicsFields(tids, ['tid', 'title', 'slug', 'lastposttime']); topicData.forEach(function (topic) { if (topic) { topicUrls.push({ url: '/topic/' + topic.slug, lastmodISO: utils.toISOString(topic.lastposttime), changefreq: 'daily', priority: 0.6, }); } }); const smStream = new SitemapStream({ hostname: nconf.get('url') }); topicUrls.forEach(url => smStream.write(url)); smStream.end(); sitemap.maps.topics[page - 1] = { sm: await streamToPromise(smStream), cacheExpireTimestamp: Date.now() + (1000 * 60 * 60 * 24), }; return sitemap.maps.topics[page - 1].sm.toString(); }; sitemap.clearCache = function () { if (sitemap.maps.pages) { sitemap.maps.pagesCacheExpireTimestamp = 0; } if (sitemap.maps.categories) { sitemap.maps.categoriesCacheExpireTimestamp = 0; } sitemap.maps.topics.forEach((topicMap) => { topicMap.cacheExpireTimestamp = 0; }); }; require('./promisify')(sitemap);