diff --git a/src/routes.js b/src/routes.js index de307ab..5f33fd2 100644 --- a/src/routes.js +++ b/src/routes.js @@ -1,125 +1,178 @@ -const config = require('../config'); -const path = require('path'); - module.exports = (app, utils) => { - // Middleware to handle cookies and theme/language overrides + const config = require('../config') + const path = require('path') + app.all('*', (req, res, next) => { - const { theme, default_lang: lang } = req.query; - - if (theme) { - req.cookies.theme = theme.toLowerCase(); - res.cookie('theme', req.cookies.theme, { maxAge: 31536000, httpOnly: true, secure: true }); - } else if (!req.cookies.theme || req.cookies.theme === '') { - req.cookies.theme = config.theme; + let themeOverride = req.query.theme + if(themeOverride) { + themeOverride = themeOverride.toLowerCase() + req.cookies.theme = themeOverride + res.cookie('theme', themeOverride, { maxAge: 31536000, httpOnly: true }) + } else if(!req.cookies.theme && req.cookies.theme !== '') { + req.cookies.theme = config.theme } - if (lang) { - req.cookies.default_lang = lang.toLowerCase(); - res.cookie('default_lang', req.cookies.default_lang, { maxAge: 31536000, httpOnly: true, secure: true }); - } else if (!req.cookies.default_lang) { - req.cookies.default_lang = config.default_lang; + let langOverride = req.query.default_lang + if(langOverride) { + langOverride = langOverride.toLowerCase() + req.cookies.default_lang = langOverride + res.cookie('default_lang', langOverride, { maxAge: 31536000, httpOnly: true }) + } else if(!req.cookies.default_lang) { + req.cookies.default_lang = config.default_lang } - next(); - }); + return next() + }) - // Route for handling media requests app.get('*', async (req, res, next) => { - try { - if (req.url.startsWith('/w/load.php')) return res.sendStatus(404); + if(req.url.startsWith('/w/load.php')) { + return res.sendStatus(404) + } - if (req.url.startsWith('/media')) { - const media = await utils.proxyMedia(req); - if (media?.success) { - if (media.mime) res.setHeader('Content-Type', media.mime); - return res.sendFile(media.path); + if(req.url.startsWith('/media')) { + let media + let mime = '' + + if(req.url.startsWith('/media/maps_wikimedia_org/')) { + media = await proxyMedia(req, 'maps.wikimedia.org') + } else if(req.url.startsWith('/media/api/rest_v1/media')) { + media = await proxyMedia(req, 'wikimedia.org/api/rest_v1/media') + if(req.url.includes('render/svg/')) { + mime = 'image/svg+xml' } - return res.sendStatus(404); + } else { + media = await proxyMedia(req) } - if (req.url.startsWith('/static/images/project-logos/') || req.url === '/static/images/mobile/copyright/wikipedia.png') { - return res.sendFile(utils.wikilessLogo()); - } + if(media.success === true) { + if(mime != '') { + res.setHeader('Content-Type', mime) + } - if (req.url.startsWith('/static/favicon/wikipedia.ico')) { - return res.sendFile(utils.wikilessFavicon()); + return res.sendFile(media.path) } - - if (req.url.startsWith('/static/images/mobile/copyright/')) { - const lang = req.url.match(/-(\w+)\.svg/)?.[1] || ''; - const customLogo = utils.customLogos(req.url, lang); - if (customLogo) return res.sendFile(customLogo); - } - - next(); - } catch (error) { - console.error('Error in media handling route:', error); - res.sendStatus(500); + return res.sendStatus(404) } - }); - // Wiki routes - app.get(['/wiki/:page?/:sub_page?', '/wiki//:page?/:sub_page?'], (req, res) => { - if (req.url.startsWith('/wiki//') && req.params.page) { - req.params.page = `/${req.params.page}`; + if(req.url.startsWith('/static/images/project-logos/') || req.url === '/static/images/mobile/copyright/wikipedia.png' || req.url === '/static/apple-touch/wikipedia.png') { + return res.sendFile(wikilessLogo()) } - return utils.handleWikiPage(req, res, '/wiki/'); - }); + if(req.url.startsWith('/static/favicon/wikipedia.ico')) { + return res.sendFile(wikilessFavicon()) + } + + // custom wikipedia logos for different languages + if(req.url.startsWith('/static/images/mobile/copyright/')) { + let custom_lang = '' + if(req.url.includes('-fr.svg')) { + custom_lang = 'fr' + } + if(req.url.includes('-ko.svg')) { + custom_lang = 'ko' + } + if(req.url.includes('-vi.svg')) { + custom_lang = 'vi' + } + + const custom_logo = customLogos(req.url, custom_lang) + if(custom_logo) { + return res.sendFile(custom_logo) + } + } + + return next() + }) + + app.get('/wiki/:page?/:sub_page?', (req, res, next) => { + return handleWikiPage(req, res, '/wiki/') + }) + + app.get('/wiki//:page?/:sub_page?', (req, res, next) => { + const page = req.params.page + if(page) { + // issue #25 + req.params.page = `/${req.params.page}` + } + return handleWikiPage(req, res, '/wiki/') + }) + + // Handle the search request and redirect to the correct wiki page app.get('/w/index.php', (req, res, next) => { - const searchQuery = req.query.search; + const searchQuery = req.query.search if (searchQuery) { - const lang = req.query.lang || req.cookies.default_lang || config.default_lang; - const redirectUrl = `/wiki/${encodeURIComponent(searchQuery)}?lang=${lang}`; - return res.redirect(redirectUrl); + // Construct the URL to redirect to the proper wiki page + const lang = req.query.lang || req.cookies.default_lang || config.default_lang + const redirectUrl = `/wiki/${encodeURIComponent(searchQuery)}?lang=${lang}` + return res.redirect(redirectUrl) } - next(); - }); + return next() + }) - app.get('/api/rest_v1/page/pdf/:page', async (req, res) => { - if (!req.params.page) return res.redirect('/'); - try { - const media = await utils.proxyMedia(req, '/api/rest_v1/page/pdf'); - if (media?.success) { - const filename = `${req.params.page}.pdf`; - return res.download(media.path, filename); - } - res.sendStatus(404); - } catch (error) { - console.error('Error in PDF generation:', error); - res.sendStatus(500); + app.get('/w/:file', (req, res, next) => { + return handleWikiPage(req, res, '/w/') + }) + + app.get('/wiki/Special:Map/*', (req, res, next) => { + return handleWikiPage(req, res, '/wiki/Map') + }) + + app.get('/api/rest_v1/page/pdf/:page', async (req, res, next) => { + if(!req.params.page) { + return res.redirect('/') } - }); - // Chinese variants redirect - app.get('/zh*', (req, res) => { - const [, lang, page] = req.path.split('/'); - return res.redirect(`/wiki/${page}?lang=${lang}`); - }); + const media = await proxyMedia(req, '/api/rest_v1/page/pdf') - // Home route - app.get('/', (req, res) => utils.handleWikiPage(req, res, '/')); + if(media.success === true) { + let filename = `${req.params.page}.pdf` + return res.download(media.path, filename) + } + return res.sendStatus(404) + }) - // Static routes - app.get('/about', (req, res) => res.sendFile(path.join(__dirname, '../static/about.html'))); + // handle chinese variants + app.get('/zh*', (req, res, next) => { + const pathSplit = req.path.split('/') + const lang = pathSplit[1] + const page = pathSplit[2] + return res.redirect(`/wiki/${page}?lang=${lang}`) + }) - app.get('/preferences', (req, res) => res.send(utils.preferencesPage(req, res))); + app.get('/', (req, res, next) => { + return handleWikiPage(req, res, '/') + }) - app.post('/preferences', (req, res) => { - const { theme, default_lang } = req.body; - const back = req.url.split('?back=')[1] || '/'; + app.get('/about', (req, res, next) => { + return res.sendFile(path.join(__dirname, '../static/about.html')) + }) - res.cookie('theme', theme, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true, secure: true }); - res.cookie('default_lang', default_lang, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true, secure: true }); + app.get('/preferences', (req, res, next) => { + return res.send(preferencesPage(req, res)) + }) - return res.redirect(back.startsWith('/') ? back : '/'); - }); + app.post('/preferences', (req, res, next) => { + const theme = req.body.theme + const default_lang = req.body.default_lang + let back = req.url.split('?back=')[1] - app.post('/DownloadAsPdf', (req, res) => { - const { page, lang } = req.body; - if (!page) return res.redirect('/'); - const language = lang || req.cookies.default_lang || config.default_lang; - const url = `/w/index.php?title=Special%3ADownloadAsPdf&page=${encodeURIComponent(page)}&action=redirect-to-electron&lang=${language}`; - return res.redirect(url); - }); -}; + res.cookie('theme', theme, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true }) + res.cookie('default_lang', default_lang, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true }) + + if(back === 'undefined' || !back.startsWith('/')) { + back = '/' + } + + return res.redirect(back) + }) + + app.post(/DownloadAsPdf/, (req, res, next) => { + if(!req.body.page) { + return res.redirect('/') + } + + const lang = req.body.lang || req.cookies.default_lang || config.default_lang + + return res.redirect(`/w/index.php?title=Special%3ADownloadAsPdf&page=${req.body.page}&action=redirect-to-electron&lang=${lang}`) + }) +}