Merge remote-tracking branch 'origin/dev' into moderator

This commit is contained in:
William Oldham 2025-01-21 09:10:52 +00:00
commit a117575d13
37 changed files with 668 additions and 334 deletions

353
package-lock.json generated
View File

@ -1010,6 +1010,16 @@
"node": ">=18.0.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
"integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
@ -1133,6 +1143,348 @@
"deprecated": "Use @eslint/object-schema instead",
"dev": true
},
"node_modules/@img/sharp-darwin-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
"integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-darwin-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
"integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-x64": "1.0.4"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
"integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
"integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
"integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
"cpu": [
"arm"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
"integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-s390x": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
"integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
"cpu": [
"s390x"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
"integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
"integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
"integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-linux-arm": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
"integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.0.5"
}
},
"node_modules/@img/sharp-linux-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
"integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-linux-s390x": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
"integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
"cpu": [
"s390x"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-s390x": "1.0.4"
}
},
"node_modules/@img/sharp-linux-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
"integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.0.4"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
"integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
"integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-x64": "1.0.4"
}
},
"node_modules/@img/sharp-wasm32": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
"integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
"cpu": [
"wasm32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
"@emnapi/runtime": "^1.2.0"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-ia32": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
"integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
"cpu": [
"ia32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
@ -5496,6 +5848,7 @@
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
"integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.3",

View File

@ -12,9 +12,9 @@ async function checkBan(request, response, next) {
}
// Set access levels
request.tester = request.user.accessLevel >= 1 && request.user.accessLevel <= 3;
request.moderator = request.user.accessLevel == 2 || request.user.accessLevel == 3;
request.developer = request.user.accessLevel == 3;
response.locals.tester = request.user.accessLevel >= 1 && request.user.accessLevel <= 3;
response.locals.moderator = request.user.accessLevel == 2 || request.user.accessLevel == 3;
response.locals.developer = request.user.accessLevel == 3;
// Check if user has access to the environment
let accessAllowed = false;
@ -23,7 +23,7 @@ async function checkBan(request, response, next) {
accessAllowed = request.developer;
break;
case 'test':
accessAllowed = request.tester || request.moderator || request.developer;
accessAllowed = response.locals.tester || response.locals.moderator || response.locals.developer;
break;
case 'prod':
accessAllowed = true;
@ -35,7 +35,7 @@ async function checkBan(request, response, next) {
if (!accessAllowed) {
response.status(500);
if (request.directory === 'web') {
return response.render('web/login.ejs', {toast: 'No access. Must be tester or dev', cdnURL: config.CDN_domain,});
return response.render('web/login.ejs', {toast: 'No access. Must be tester or dev' });
} else {
return response.render('portal/partials/ban_notification.ejs', {
user: null,
@ -43,41 +43,42 @@ async function checkBan(request, response, next) {
});
}
}
const user = await db.getUserSettings(request.pid);
if (user && moment(user.ban_lift_date) <= moment() && user.account_status !== 3) {
user.account_status = 0;
await user.save();
const userSettings = await db.getUserSettings(request.pid);
if (userSettings && moment(userSettings.ban_lift_date) <= moment() && userSettings.account_status !== 3) {
userSettings.account_status = 0;
await userSettings.save();
}
// This includes ban checks for both Juxt specifically and the account server, ideally this should be squashed
// assuming we support more gradual bans on PNID's
if (user && (user.account_status < 0 || user.account_status > 1 || request.user.accessLevel < 0)) {
if (userSettings && (userSettings.account_status < 0 || userSettings.account_status > 1 || request.user.accessLevel < 0)) {
if (request.directory === 'web') {
let banMessage = '';
switch (user.account_status) {
switch (userSettings.account_status) {
case 2:
banMessage = `${request.user.username} has been banned until: ${ moment(user.ban_lift_date) }. \n\nReason: ${user.ban_reason}. \n\nIf you have any questions contact the moderators in the Discord server or forum.`;
banMessage = `${request.user.username} has been banned until: ${ moment(userSettings.ban_lift_date) }. \n\nReason: ${userSettings.ban_reason}. \n\nIf you have any questions contact the moderators in the Discord server or forum.`;
break;
case 3:
banMessage = `${request.user.username} has been banned forever. \n\nReason: ${user.ban_reason}. \n\nIf you have any questions contact the moderators in the Discord server or forum.`;
banMessage = `${request.user.username} has been banned forever. \n\nReason: ${userSettings.ban_reason}. \n\nIf you have any questions contact the moderators in the Discord server or forum.`;
break;
default:
banMessage = `${request.user.username} has been banned. \n\nIf you have any questions contact the moderators in the Discord server or forum.`;
}
return response.render('web/login.ejs', {toast: banMessage, cdnURL: config.CDN_domain,});
return response.render('web/login.ejs', {toast: banMessage });
} else {
return response.render(request.directory + '/partials/ban_notification.ejs', {
user: user,
user: userSettings,
moment: moment,
cdnURL: config.CDN_domain,
lang: request.lang,
pid: request.pid,
PNID: request.user.username,
networkBan: request.user.accessLevel < 0
});
}
}
user.last_active = Date.now();
await user.save();
if (userSettings) {
userSettings.last_active = Date.now();
await userSettings.save();
}
next();
}

View File

@ -68,8 +68,8 @@ async function auth(request, response, next) {
});
}
request.lang = util.processLanguage(request.paramPackData);
//console.timeEnd(`Time Request ${request.timerDate}`);
response.locals.lang = util.processLanguage(request.paramPackData);
response.locals.pid = request.pid;
return next();
}

View File

@ -2,11 +2,10 @@ const util = require('../util');
async function detectVersion(request, response, next) {
request.timerDate = Date.now();
console.time(`Time Request ${request.timerDate}`);
// Check the domain and set the directory
if (includes(request, 'juxt')) {
request.directory = 'web';
request.lang = util.processLanguage();
response.locals.lang = util.processLanguage();
} else {
request.directory = includes(request, 'portal') ? 'portal' : 'ctr';
}

View File

@ -19,7 +19,7 @@ async function checkDiscovery(request, response, next) {
break;
}
if (request.directory === 'web') {
return response.render('web/login.ejs', {toast: message, cdnURL: config.CDN_domain,});
return response.render('web/login.ejs', {toast: message });
} else {
return response.render('portal/partials/ban_notification.ejs', {
user: null,
@ -29,6 +29,7 @@ async function checkDiscovery(request, response, next) {
} else {
request.guest_access = discovery ? discovery.guest_access : false;
request.new_users = discovery ? discovery.new_users : false;
response.locals.cdnURL = config.CDN_domain;
}
next();

View File

@ -10,7 +10,7 @@ async function staticFiles(request, response, next) {
isStartOfPath(request.path, '/images/') ||
isStartOfPath(request.path, '/image/')) {
request.lang = util.processLanguage();
response.locals.lang = util.processLanguage();
if (request.subdomains.includes('juxt')) {
request.directory = 'web';

View File

@ -21,7 +21,7 @@ async function webAuth(request, response, next) {
response.clearCookie('refresh_token', { domain: domain, path: '/' });
response.clearCookie('token_type', { domain: domain, path: '/' });
if (request.path === '/login') {
request.lang = util.processLanguage();
response.locals.lang = util.processLanguage();
request.token = request.cookies.access_token;
request.paramPackData = null;
return next();
@ -37,6 +37,7 @@ async function webAuth(request, response, next) {
(isStartOfPath(request.path, '/posts/') && !request.path.includes('/empathy'))) {
if (!request.pid && request.guest_access && !request.isWrite) {
request.pid = 1000000000;
response.locals.pid = request.pid;
return next();
} else if (!request.pid) {
return response.redirect('/login');
@ -53,6 +54,7 @@ async function webAuth(request, response, next) {
return response.redirect('/login');
}
response.locals.pid = request.pid;
return next();
}

View File

@ -58,10 +58,7 @@ app.use((req, res) => {
logger.warn(req.protocol + '://' + req.get('host') + req.originalUrl);
res.render(req.directory + '/error.ejs', {
code: 404,
message: 'Page not found',
cdnURL: config.CDN_domain,
lang: req.lang,
pid: req.pid
message: 'Page not found'
});
});

View File

@ -14,7 +14,7 @@ const config = require('../../../../../config.json');
const router = express.Router();
router.get('/posts', async function (req, res) {
if (!req.moderator) {
if (!res.locals.moderator) {
return res.redirect('/titles/show');
}
@ -36,13 +36,7 @@ router.get('/posts', async function (req, res) {
]);
res.render(req.directory + '/reports.ejs', {
lang: req.lang,
moment: moment,
cdnURL: config.CDN_domain,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator,
developer: req.developer,
userMap,
communityMap,
userContent,
@ -52,7 +46,7 @@ router.get('/posts', async function (req, res) {
});
router.get('/accounts', async function (req, res) {
if (!req.moderator) {
if (!res.locals.moderator) {
return res.redirect('/titles/show');
}
@ -67,16 +61,10 @@ router.get('/accounts', async function (req, res) {
last_active: {
$gte: new Date(Date.now() - 10 * 60 * 1000)
}
}).count()
}).count();
res.render(req.directory + '/users.ejs', {
lang: req.lang,
moment: moment,
cdnURL: config.CDN_domain,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator,
developer: req.developer,
userMap,
users,
page,
@ -87,7 +75,7 @@ router.get('/accounts', async function (req, res) {
});
router.get('/accounts/:pid', async function (req, res) {
if (!req.moderator) {
if (!res.locals.moderator) {
return res.redirect('/titles/show');
}
const pnid = await util.getUserDataFromPid(req.params.pid).catch((e) => {
@ -102,13 +90,7 @@ router.get('/accounts/:pid', async function (req, res) {
const communityMap = await util.getCommunityHash();
res.render(req.directory + '/moderate_user.ejs', {
lang: req.lang,
moment: moment,
cdnURL: config.CDN_domain,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator,
developer: req.developer,
userSettings,
userContent,
posts,
@ -118,7 +100,7 @@ router.get('/accounts/:pid', async function (req, res) {
});
router.post('/accounts/:pid', async (req, res) => {
if (!req.moderator) {
if (!res.locals.moderator) {
return res.redirect('/titles/show');
}
@ -138,7 +120,7 @@ router.post('/accounts/:pid', async (req, res) => {
await util.newNotification({
pid: pid,
type: 'notice',
text: `You have been limited from posting until ${moment(req.body.ban_lift_date)}. Reason: \"${req.body.ban_reason}\". If you have any questions contact the moderators in the Discord server or forum.`,
text: `You have been limited from posting until ${moment(req.body.ban_lift_date)}. Reason: "${req.body.ban_reason}". If you have any questions contact the moderators in the Discord server or forum.`,
image: '/images/bandwidthalert.png',
link: '/titles/2551084080/new'
});
@ -146,7 +128,7 @@ router.post('/accounts/:pid', async (req, res) => {
});
router.delete('/:reportID', async function (req, res) {
if (!req.moderator) {
if (!res.locals.moderator) {
return res.sendStatus(401);
}
@ -158,15 +140,23 @@ router.delete('/:reportID', async function (req, res) {
if (!post) {
return res.sendStatus(404);
}
const reason = req.query.reason ? req.query.reason : 'Removed by moderator';
await post.removePost(reason, req.pid);
await report.resolve(req.pid, reason);
await post.removePost(req.query.reason ? req.query.reason : 'Removed by moderator', req.pid);
await report.resolve(req.pid, req.query.reason ? req.query.reason : 'Removed by moderator');
await util.newNotification({
pid: post.pid,
type: 'notice',
text: `Your post "${post.id}" has been removed for the following reason: "${reason}"`,
image: '/images/bandwidthalert.png',
link: '/titles/2551084080/new'
});
return res.sendStatus(200);
});
router.put('/:reportID', async function (req, res) {
if (!req.moderator) {
if (!res.locals.moderator) {
return res.sendStatus(401);
}
@ -181,7 +171,7 @@ router.put('/:reportID', async function (req, res) {
});
router.get('/communities', async function (req, res) {
if (!req.developer) {
if (!res.locals.developer) {
return res.redirect('/titles/show');
}
@ -192,13 +182,7 @@ router.get('/communities', async function (req, res) {
const communities = search ? await database.getCommunitiesFuzzySearch(search, limit, page * limit) : await database.getCommunities(limit, page * limit);
res.render(req.directory + '/manage_communities.ejs', {
lang: req.lang,
moment: moment,
cdnURL: config.CDN_domain,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator,
developer: req.developer,
communities,
page,
search
@ -206,23 +190,17 @@ router.get('/communities', async function (req, res) {
});
router.get('/communities/new', async function (req, res) {
if (!req.developer) {
if (!res.locals.developer) {
return res.redirect('/titles/show');
}
res.render(req.directory + '/new_community.ejs', {
lang: req.lang,
moment: moment,
cdnURL: config.CDN_domain,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator,
developer: req.developer
moment: moment
});
});
router.post('/communities/new', upload.fields([{ name: 'browserIcon', maxCount: 1 }, { name: 'CTRbrowserHeader', maxCount: 1 }, { name: 'WiiUbrowserHeader', maxCount: 1 }]), async (req, res) => {
if (!req.developer) {
if (!res.locals.developer) {
return res.redirect('/titles/show');
}
const communityID = await generateCommunityUID();
@ -260,7 +238,7 @@ router.post('/communities/new', upload.fields([{ name: 'browserIcon', maxCount:
open: true,
allows_comments: true,
type: req.body.type,
parent: req.body.parent === 'null' ? null : req.body.parent,
parent: req.body.parent === 'null' || req.body.parent.trim() === '' ? null : req.body.parent,
owner: req.pid,
created_at: moment(new Date()),
empathy_count: 0,
@ -276,10 +254,12 @@ router.post('/communities/new', upload.fields([{ name: 'browserIcon', maxCount:
const newCommunity = new COMMUNITY(document);
await newCommunity.save();
res.redirect(`/admin/communities/${communityID}`);
util.updateCommunityHash(document);
});
router.get('/communities/:community_id', async function (req, res) {
if (!req.developer) {
if (!res.locals.developer) {
return res.redirect('/titles/show');
}
@ -290,13 +270,7 @@ router.get('/communities/:community_id', async function (req, res) {
}
res.render(req.directory + '/edit_community.ejs', {
lang: req.lang,
moment: moment,
cdnURL: config.CDN_domain,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator,
developer: req.developer,
community,
});
@ -306,7 +280,7 @@ router.post('/communities/:id', upload.fields([{ name: 'browserIcon', maxCount:
name: 'CTRbrowserHeader',
maxCount: 1
}, { name: 'WiiUbrowserHeader', maxCount: 1 }]), async (req, res) => {
if (!req.developer) {
if (!res.locals.developer) {
return res.redirect('/titles/show');
}
@ -351,7 +325,7 @@ router.post('/communities/:id', upload.fields([{ name: 'browserIcon', maxCount:
platform_id: req.body.platform,
icon: tgaIcon,
title_id: req.body.title_ids.replace(/ /g, '').split(','),
parent: req.body.parent === 'null' ? null : req.body.parent,
parent: req.body.parent === 'null' || req.body.parent.trim() === '' ? null : req.body.parent,
app_data: req.body.app_data,
is_recommended: req.body.is_recommended,
name: req.body.name,
@ -360,10 +334,12 @@ router.post('/communities/:id', upload.fields([{ name: 'browserIcon', maxCount:
await COMMUNITY.findOneAndUpdate({ community_id: communityID }, { $set: document }, { upsert: true }).exec();
res.redirect(`/admin/communities/${communityID}`);
util.updateCommunityHash(document);
});
router.delete('/communities/:id', async (req, res) => {
if (!req.developer) {
if (!res.locals.developer) {
return res.redirect('/titles/show');
}

View File

@ -34,24 +34,14 @@ router.get('/', async function (req, res) {
res.render(req.directory + '/communities.ejs', {
cache: true,
popularCommunities: popularCommunities,
newCommunities: newCommunities,
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
newCommunities: newCommunities
});
});
router.get('/all', async function (req, res) {
const communities = await database.getCommunities(90);
res.render(req.directory + '/all_communities.ejs', {
communities: communities,
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
communities: communities
});
});
@ -74,7 +64,7 @@ router.get('/:communityID/related', async function (req, res) {
}
const community = await database.getCommunityByID(req.params.communityID.toString());
if (!community) {
return res.render(req.directory + '/error.ejs', { code: 404, message: 'Community not Found', pid: req.pid, lang: req.lang, cdnURL: config.CDN_domain });
return res.render(req.directory + '/error.ejs', { code: 404, message: 'Community not Found' });
}
const communityMap = await util.getCommunityHash();
const children = await database.getSubCommunities(community.olive_community_id);
@ -86,12 +76,7 @@ router.get('/:communityID/related', async function (req, res) {
selection: 2,
communityMap,
community,
children,
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
children
});
});
@ -104,7 +89,7 @@ router.get('/:communityID/:type', async function (req, res) {
}
const community = await database.getCommunityByID(req.params.communityID.toString());
if (!community) {
return res.render(req.directory + '/error.ejs', { code: 404, message: 'Community not Found', pid: req.pid, lang: req.lang, cdnURL: config.CDN_domain });
return res.render(req.directory + '/error.ejs', { code: 404, message: 'Community not Found' });
}
if (!community.permissions) {
@ -141,16 +126,13 @@ router.get('/:communityID/:type', async function (req, res) {
numPosts,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/titles/${req.params.communityID}/${req.params.type}/more?offset=${posts.length}&pjax=true`
};
if (req.query.pjax) {
return res.render(req.directory + '/partials/posts_list.ejs', {
bundle,
moment,
lang: req.lang
moment
});
}
@ -164,16 +146,11 @@ router.get('/:communityID/:type', async function (req, res) {
userSettings: userSettings,
userContent: userContent,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
pnid: req.user,
children,
type,
bundle,
template: 'posts_list',
moderator: req.moderator
template: 'posts_list'
});
});
@ -207,8 +184,6 @@ router.get('/:communityID/:type/more', async function (req, res) {
numPosts: posts.length,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/titles/${req.params.communityID}/${req.params.type}/more?offset=${offset + posts.length}&pjax=true`
};
@ -218,12 +193,7 @@ router.get('/:communityID/:type/more', async function (req, res) {
moment: moment,
database: database,
bundle,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
account_server: config.account_server_domain.slice(8)
});
} else {
res.sendStatus(204);

View File

@ -2,6 +2,7 @@ const express = require('express');
const database = require('../../../../database');
const util = require('../../../../util');
const config = require('../../../../../config.json');
const { POST } = require('../../../../models/post');
const moment = require('moment');
const router = express.Router();
@ -18,8 +19,6 @@ router.get('/', async function (req, res) {
open: true,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/feed/more?offset=${posts.length}&pjax=true`
};
@ -27,27 +26,63 @@ router.get('/', async function (req, res) {
return res.render(req.directory + '/partials/posts_list.ejs', {
bundle,
moment,
lang: req.lang
});
}
res.render(req.directory + '/feed.ejs', {
moment: moment,
title: req.lang.global.activity_feed,
title: res.locals.lang.global.activity_feed,
userContent: userContent,
posts: posts,
communityMap: communityMap,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
bundle,
tab: 0,
template: 'posts_list',
moderator: req.moderator
});
});
router.get('/all', async function (req, res) {
const userContent = await database.getUserContent(req.pid);
const communityMap = await util.getCommunityHash();
if (!userContent) {
return res.redirect('/404');
}
const posts = await POST.find({
parent: null,
message_to_pid: null,
removed: false
}).limit(config.post_limit).sort({ created_at: -1});
const bundle = {
posts,
open: true,
communityMap,
userContent,
link: `/feed/all/more?offset=${posts.length}&pjax=true`
};
if (req.query.pjax) {
return res.render(req.directory + '/partials/posts_list.ejs', {
bundle,
moment
});
}
res.render(req.directory + '/feed.ejs', {
moment: moment,
title: res.locals.lang.global.activity_feed,
userContent: userContent,
posts: posts,
communityMap: communityMap,
account_server: config.account_server_domain.slice(8),
bundle,
tab: 1,
template: 'posts_list'
});
});
router.get('/more', async function (req, res) {
let offset = parseInt(req.query.offset);
const userContent = await database.getUserContent(req.pid);
@ -57,6 +92,42 @@ router.get('/more', async function (req, res) {
}
const posts = await database.getNewsFeedOffset(userContent, config.post_limit, offset);
const bundle = {
posts,
numPosts: posts.length,
open: true,
communityMap,
userContent,
link: `/feed/more?offset=${offset + posts.length}&pjax=true`
};
if (posts.length > 0) {
res.render(req.directory + '/partials/posts_list.ejs', {
communityMap: communityMap,
moment: moment,
database: database,
bundle,
account_server: config.account_server_domain.slice(8)
});
} else {
res.sendStatus(204);
}
});
router.get('/all/more', async function (req, res) {
let offset = parseInt(req.query.offset);
const userContent = await database.getUserContent(req.pid);
const communityMap = await util.getCommunityHash();
if (!offset) {
offset = 0;
}
const posts = await POST.find({
parent: null,
message_to_pid: null,
removed: false
}).skip(offset).limit(config.post_limit).sort({ created_at: -1});
const bundle = {
posts,
numPosts: posts.length,
@ -69,6 +140,45 @@ router.get('/more', async function (req, res) {
moderator: req.moderator
};
if (posts.length > 0) {
res.render(req.directory + '/partials/posts_list.ejs', {
communityMap: communityMap,
moment: moment,
database: database,
bundle,
account_server: config.account_server_domain.slice(8)
});
} else {
res.sendStatus(204);
}
});
router.get('/all/more', async function (req, res) {
let offset = parseInt(req.query.offset);
const userContent = await database.getUserContent(req.pid);
const communityMap = await util.getCommunityHash();
if (!offset) {
offset = 0;
}
const posts = await POST.find({
parent: null,
message_to_pid: null,
removed: false
}).skip(offset).limit(config.post_limit).sort({ created_at: -1});
const bundle = {
posts,
numPosts: posts.length,
open: true,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/feed/all/more?offset=${offset + posts.length}&pjax=true`,
moderator: req.moderator
};
if (posts.length > 0) {
res.render(req.directory + '/partials/posts_list.ejs', {
communityMap: communityMap,

View File

@ -14,13 +14,8 @@ router.get('/', async function (req, res) {
const usersMap = await util.getUserHash();
res.render(req.directory + '/messages.ejs', {
moment: moment,
pid: req.pid,
conversations: conversations,
cdnURL: config.CDN_domain,
usersMap: usersMap,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
moderator: req.moderator
usersMap: usersMap
});
});
@ -73,10 +68,7 @@ router.post('/new', async function (req, res) {
res.status(422);
return res.render(req.directory + '/error.ejs', {
code: 422,
message: 'Upload failed. Please try again later.',
pid: req.pid,
lang: req.lang,
cdnURL: config.CDN_domain
message: 'Upload failed. Please try again later.'
});
}
}
@ -86,10 +78,7 @@ router.post('/new', async function (req, res) {
res.status(422);
return res.render(req.directory + '/error.ejs', {
code: 422,
message: 'Upload failed. Please try again later.',
pid: req.pid,
lang: req.lang,
cdnURL: config.CDN_domain
message: 'Upload failed. Please try again later.'
});
}
}
@ -146,8 +135,7 @@ router.post('/new', async function (req, res) {
platform_id: req.paramPackData ? req.paramPackData.platform_id : 0,
region_id: req.paramPackData ? req.paramPackData.region_id : 2,
verified: (req.user.accessLevel >= 2),
message_to_pid: req.body.message_to_pid,
moderator: req.moderator
message_to_pid: req.body.message_to_pid
};
const duplicatePost = await database.getDuplicatePosts(req.pid, document);
if (duplicatePost && req.params.post_id) {
@ -237,12 +225,7 @@ router.get('/:message_id', async function (req, res) {
user2: user2,
conversation: conversation,
messages: messages,
userMap: userMap,
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
userMap: userMap
});
await conversation.markAsRead(req.pid);
});

View File

@ -16,7 +16,6 @@ router.get('/my_news', async function (req, res) {
if (req.query.pjax) {
return res.render(req.directory + '/partials/notifications.ejs', {
bundle,
lang: req.lang,
moment
});
}
@ -25,11 +24,7 @@ router.get('/my_news', async function (req, res) {
moment,
selection: 0,
bundle,
cdnURL: config.CDN_domain,
lang: req.lang,
pid: req.pid,
template: 'notifications',
moderator: req.moderator
template: 'notifications'
});
notifications.filter(noti => noti.read === false).forEach(function (notification) {
notification.markRead();
@ -49,7 +44,6 @@ router.get('/friend_requests', async function (req, res) {
if (req.query.pjax) {
return res.render(req.directory + '/partials/requests.ejs', {
bundle,
lang: req.lang,
moment
});
}
@ -58,11 +52,7 @@ router.get('/friend_requests', async function (req, res) {
moment,
selection: 1,
bundle,
cdnURL: config.CDN_domain,
lang: req.lang,
pid: req.pid,
template: 'requests',
moderator: req.moderator
template: 'requests'
});
});

View File

@ -26,10 +26,7 @@ const postLimit = rateLimit({
} else {
res.render(req.directory + '/error.ejs', {
code: 429,
message: 'Too many new posts have been created.',
cdnURL: config.CDN_domain,
lang: req.lang,
pid: req.pid
message: 'Too many new posts have been created.'
});
}
},
@ -63,14 +60,14 @@ router.post('/empathy', yeahLimit, async function (req, res) {
$ne: req.pid
}
},
{
$inc: {
empathy_count: 1
},
$push: {
yeahs: req.pid
}
});
{
$inc: {
empathy_count: 1
},
$push: {
yeahs: req.pid
}
});
res.send({ status: 200, id: post.id, count: post.empathy_count + 1 });
if (req.pid !== post.pid) {
await util.newNotification({
@ -88,14 +85,14 @@ router.post('/empathy', yeahLimit, async function (req, res) {
$eq: req.pid
}
},
{
$inc: {
empathy_count: -1
},
$pull: {
yeahs: req.pid
}
});
{
$inc: {
empathy_count: -1
},
$pull: {
yeahs: req.pid
}
});
res.send({ status: 200, id: post.id, count: post.empathy_count - 1 });
} else {
res.send({ status: 423, id: post.id, count: post.empathy_count });
@ -133,13 +130,8 @@ router.get('/:post_id', async function (req, res) {
replies: replies,
community: community,
communityMap: communityMap,
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
postPNID,
pnid: req.user,
moderator: req.moderator
});
});
@ -148,10 +140,10 @@ router.delete('/:post_id', async function (req, res) {
if (!post) {
return res.sendStatus(404);
}
if (req.pid !== post.pid && !req.moderator) {
if (req.pid !== post.pid && !res.locals.moderator) {
return res.sendStatus(401);
}
if (req.moderator && req.pid !== post.pid) {
if (res.locals.moderator && req.pid !== post.pid) {
await post.removePost(req.query.reason ? req.query.reason : 'Removed by moderator', req.pid);
} else {
await post.removePost('User requested removal', req.pid);
@ -233,10 +225,7 @@ async function newPost(req, res) {
res.status(422);
return res.render(req.directory + '/error.ejs', {
code: 422,
message: 'Upload failed. Please try again later.',
pid: req.pid,
lang: req.lang,
cdnURL: config.CDN_domain
message: 'Upload failed. Please try again later.'
});
}
}
@ -246,10 +235,7 @@ async function newPost(req, res) {
res.status(422);
return res.render(req.directory + '/error.ejs', {
code: 422,
message: 'Upload failed. Please try again later.',
pid: req.pid,
lang: req.lang,
cdnURL: config.CDN_domain
message: 'Upload failed. Please try again later.'
});
}
}
@ -305,9 +291,8 @@ async function newPost(req, res) {
pid: req.pid,
platform_id: req.paramPackData ? req.paramPackData.platform_id : 0,
region_id: req.paramPackData ? req.paramPackData.region_id : 2,
verified: req.moderator,
parent: parentPost ? parentPost.id : null,
moderator: req.moderator
verified: res.locals.moderator,
parent: parentPost ? parentPost.id : null
};
const duplicatePost = await database.getDuplicatePosts(req.pid, document);
if (duplicatePost && req.params.post_id) {

View File

@ -6,22 +6,13 @@ const router = express.Router();
router.get('/', async function (req, res) {
if (req.pid === 1000000000) {
return res.render(req.directory + '/guest_notice.ejs', {
cdnURL: config.CDN_domain,
lang: req.lang,
moderator: req.moderator
});
return res.render(req.directory + '/guest_notice.ejs');
}
const user = await database.getUserSettings(req.pid);
const content = await database.getUserContent(req.pid);
if (!user || !content) {
return res.render(req.directory + '/first_run.ejs', {
cdnURL: config.CDN_domain,
lang: req.lang,
pid: req.pid,
moderator: req.moderator
});
return res.render(req.directory + '/first_run.ejs');
}
if (req.query.topic_tag) {
@ -41,11 +32,7 @@ router.get('/', async function (req, res) {
});
router.get('/first', async function (req, res) {
res.render(req.directory + '/first_run.ejs', {
cdnURL: config.CDN_domain,
lang: req.lang,
moderator: req.moderator
});
res.render(req.directory + '/first_run.ejs');
});
router.post('/newUser', async function (req, res) {

View File

@ -20,16 +20,13 @@ router.get('/', async function (req, res) {
open: true,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/topics/more?tag=${tag}&offset=${posts.length}&pjax=true`
};
if (req.query.pjax) {
return res.render(req.directory + '/partials/posts_list.ejs', {
bundle,
moment,
lang: req.lang
moment
});
}
@ -40,13 +37,8 @@ router.get('/', async function (req, res) {
posts: posts,
communityMap: communityMap,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
bundle,
template: 'posts_list',
moderator: req.moderator
template: 'posts_list'
});
});
@ -66,8 +58,6 @@ router.get('/more', async function (req, res) {
open: true,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/topics/more?tag=${tag}&offset=${posts.length}&pjax=true`
};
@ -77,12 +67,7 @@ router.get('/more', async function (req, res) {
moment: moment,
database: database,
bundle,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
account_server: config.account_server_domain.slice(8)
});
} else {
res.sendStatus(204);

View File

@ -53,12 +53,7 @@ router.get('/me/settings', async function (req, res) {
communityMap: communityMap,
moment: moment,
userSettings: userSettings,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
account_server: config.account_server_domain.slice(8)
});
});
@ -156,7 +151,6 @@ async function userPage(req, res, userID) {
await redis.setValue(`${userID}_user_page_posts`, JSON.stringify(posts), 60 * 60 * 1);
}
const numPosts = await database.getTotalPostsByUserID(userID);
const communityMap = await util.getCommunityHash();
let friends = [];
@ -175,14 +169,11 @@ async function userPage(req, res, userID) {
numPosts,
communityMap,
userContent: parentUserContent ? parentUserContent : userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/users/${userID}/more?offset=${posts.length}&pjax=true`
};
if (req.query.pjax) {
return res.render(req.directory + '/partials/posts_list.ejs', {
bundle,
lang: req.lang,
moment
});
}
@ -197,15 +188,10 @@ async function userPage(req, res, userID) {
userSettings,
bundle,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
link,
friends,
parentUserContent,
isActive: isDateInRange(userSettings.last_active, 10),
moderator: req.moderator
isActive: isDateInRange(userSettings.last_active, 10)
});
}
@ -235,15 +221,12 @@ async function userRelations(req, res, userID) {
numPosts: posts.length,
communityMap,
userContent: parentUserContent ? parentUserContent : userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/users/${userID}/yeahs/more?offset=${posts.length}&pjax=true`
};
if (req.query.pjax) {
return res.render(req.directory + '/partials/posts_list.ejs', {
bundle,
lang: req.lang,
moment
});
} else {
@ -257,15 +240,10 @@ async function userRelations(req, res, userID) {
userSettings,
bundle,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
link,
friends,
parentUserContent,
isActive: isDateInRange(userSettings.last_active, 10),
moderator: req.moderator
isActive: isDateInRange(userSettings.last_active, 10)
});
}
}
@ -300,7 +278,7 @@ async function userRelations(req, res, userID) {
if (req.query.pjax) {
return res.render(req.directory + '/partials/following_list.ejs', {
bundle,
bundle
});
}
res.render(req.directory + '/user_page.ejs', {
@ -313,14 +291,9 @@ async function userRelations(req, res, userID) {
userSettings,
bundle,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
link,
parentUserContent,
isActive: isDateInRange(userSettings.last_active, 10),
moderator: req.moderator
isActive: isDateInRange(userSettings.last_active, 10)
});
}
@ -339,8 +312,6 @@ async function morePosts(req, res, userID) {
open: true,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/users/${userID}/more?offset=${offset + posts.length}&pjax=true`
};
@ -350,12 +321,7 @@ async function morePosts(req, res, userID) {
moment: moment,
database: database,
bundle,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
account_server: config.account_server_domain.slice(8)
});
} else {
res.sendStatus(204);
@ -377,8 +343,6 @@ async function moreYeahPosts(req, res, userID) {
open: true,
communityMap,
userContent,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
link: `/users/${userID}/yeahs/more?offset=${offset + posts.length}&pjax=true`
};
@ -388,12 +352,7 @@ async function moreYeahPosts(req, res, userID) {
moment: moment,
database: database,
bundle,
account_server: config.account_server_domain.slice(8),
cdnURL: config.CDN_domain,
lang: req.lang,
mii_image_CDN: config.mii_image_CDN,
pid: req.pid,
moderator: req.moderator
account_server: config.account_server_domain.slice(8)
});
} else {
res.sendStatus(204);

View File

@ -8,7 +8,7 @@ const request = require('request');
const logger = require('../../../../logger');
router.get('/', async function (req, res) {
res.render(req.directory + '/login.ejs', { toast: null, cdnURL: config.CDN_domain, });
res.render(req.directory + '/login.ejs', { toast: null, });
});
router.post('/', async (req, res) => {
@ -17,13 +17,13 @@ router.post('/', async (req, res) => {
console.error(e.details);
switch (e.details) {
case 'INVALID_ARGUMENT: User not found':
res.render(req.directory + '/login.ejs', { toast: 'Username was invalid.', cdnURL: config.CDN_domain, });
res.render(req.directory + '/login.ejs', { toast: 'Username was invalid.' });
break;
case 'INVALID_ARGUMENT: Password is incorrect':
res.render(req.directory + '/login.ejs', { toast: 'Password was incorrect.', cdnURL: config.CDN_domain, });
res.render(req.directory + '/login.ejs', { toast: 'Password was incorrect.' });
break;
default:
res.render(req.directory + '/login.ejs', { toast: 'Invalid username or password.', cdnURL: config.CDN_domain, });
res.render(req.directory + '/login.ejs', { toast: 'Invalid username or password.' });
break;
}
});
@ -33,7 +33,7 @@ router.post('/', async (req, res) => {
const PNID = await util.getUserDataFromToken(login.accessToken);
if (!PNID) {
return res.render(req.directory + '/login.ejs', { toast: 'Invalid username or password.', cdnURL: config.CDN_domain, });
return res.render(req.directory + '/login.ejs', { toast: 'Invalid username or password.' });
}
const pid = PNID.pid;
@ -59,11 +59,7 @@ router.post('/', async (req, res) => {
if (discovery.status !== 0) {
return res.render(req.directory + '/error.ejs', {
code: 504,
message: message,
cdnURL: config.CDN_domain,
lang: req.lang,
pid: pid,
moderator: req.moderator
message: message
});
}
const cookieDomain = (req.hostname.indexOf('miiverse') !== -1) ? '.miiverse.cc' : '.pretendo.network';

View File

@ -227,9 +227,21 @@ function setName(pid, name) {
if (!pid || !name) {
return;
}
userMap.delete(pid);
userMap.set(pid, name.replace(/[\u{0080}-\u{FFFF}]/gu, '').replace(/\u202e/g, ''));
this.userMap.delete(pid);
this.userMap.set(pid, name.replace(/[\u{0080}-\u{FFFF}]/gu, '').replace(/\u202e/g, ''));
}
function updateCommunityHash(community) {
if (!community) {
return;
}
for (let i = 0; i < community.title_id.length; i++) {
communityMap.set(community.title_id[i], community.name);
communityMap.set(community.title_id[i] + '-id', community.olive_community_id);
}
communityMap.set(community.olive_community_id, community.name);
}
async function resizeImage(file, width, height) {
return new Promise(function (resolve) {
const image = Buffer.from(file, 'base64');
@ -495,6 +507,7 @@ module.exports = {
getUserHash,
refreshCache,
setName,
updateCommunityHash,
resizeImage,
getTGAFromPNG,
createBMPTgaBuffer,

View File

@ -28,7 +28,7 @@
<%} else { %>
<button id="load-more-posts-button" onclick="loadCommunityPosts()" style="background: #1F8A42">Load More Posts</button>
<% newPosts.forEach(function(post) { %>
<%- include('post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false }); %>
<%- include('post_template', { post: post, reply: false }); %>
<% }); %>
<%}%>
</div>

View File

@ -7,6 +7,18 @@
<h1 id="page-title" class=""><%= title %></h1>
</header>
<div class="body-content tab2-content" id="community-post-list">
<menu class="tab-header no-margin">
<li id="tab-header-my-feed" class="tab-button <%if(tab === 0){ %>selected<%}%>" data-show-post-button="1">
<a href="/feed" data-pjax-replace="1" data-sound="SE_WAVE_SELECT_TAB">
<span class="new-post">My Feed</span>
</a>
</li>
<li id="tab-header-global-feed" class="tab-button <%if(tab === 1){ %>selected<%}%>">
<a href="/feed/all" data-pjax-cache-container="#body" data-pjax-replace="1" data-sound="SE_WAVE_SELECT_TAB">
<span>Global Feed</span>
</a>
</li>
</menu>
<div class="tab-body post-list">
<%- include('partials/' + template, { bundle }); %>
</div>

View File

@ -1,3 +1,3 @@
<% newPosts.forEach(function(post) { %>
<%- include('post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false }); %>
<%- include('post_template', { post: post, reply: false }); %>
<% }); %>

View File

@ -2,8 +2,8 @@
<%if(!bundle.notifications) {%><li><p><%= lang.notifications.none %></p></li><%}%>
<%if(bundle.notifications){%>
<% for(var notification of bundle.notifications) {%>
<li>
<% if(notification.type === 'follow') {%>
<li>
<a href="/users/<%= notification.objectID %>" data-pjax="#body" class="icon-container notify">
<img src="<%= cdnURL %>/mii/<%= notification.objectID %>/normal_face.png" class="icon">
</a>
@ -30,20 +30,20 @@
</p>
<%}%>
</div>
</li>
<%} else if (notification.type === 'notice') {%>
<li>
<a href="<%= notification.link %>" data-pjax="#body" class="icon-container notify">
<img src="<%= notification.image %>" class="icon">
</a>
<a class="body" href="<%= notification.link %>">
<span class="text">
<span class="nick-name"><%= notification.text %></span>
<div class="body">
<a class="body" href="<%= notification.link %>">
<p class="" style="color: black">
<span class=""><%= notification.text %></span>
<span class="timestamp"> <%= moment(notification.lastUpdated).fromNow() %></span>
</span>
</a>
</li>
</p>
</a>
</div>
<%}%>
</li>
<%}%>
<%}%>
</ul>

View File

@ -3,9 +3,9 @@
<p class="no-posts-text"><%= lang.global.no_posts %></p>
<%} else { %>
<% bundle.posts.forEach(function(post) { %>
<%- include('post_template', { post: post, mii_image_CDN: bundle.mii_image_CDN, lang: bundle.lang, userContent: bundle.userContent, communityMap: bundle.communityMap, reply: false }); %>
<%- include('post_template', { post: post, userContent: bundle.userContent, communityMap: bundle.communityMap, reply: false }); %>
<% }); %>
<div class="button-wrapper center">
<button type="button" class="load-more" data-href="<%= bundle.link %>"><%= bundle.lang.global.more %></button>
<button type="button" class="load-more" data-href="<%= bundle.link %>"><%= lang.global.more %></button>
</div>
<%}%>

View File

@ -23,10 +23,10 @@
</header>
<div class="body-content tab2-content" id="post">
<div class="post-wrapper parent">
<%- include('partials/post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false, pid: pid, yeah: true }); %>
<%- include('partials/post_template', { post: post, reply: false, pid: pid, yeah: true }); %>
</div>
<% replies.forEach(function(post) { %>
<%- include('partials/post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: true, pid: pid }); %>
<%- include('partials/post_template', { post: post, reply: true, pid: pid }); %>
<% }); %>
</div>
<% if((

View File

@ -11,8 +11,19 @@
<a href="#" class="button" data-offset="10" onclick="loadFeedPosts(this)"><%= lang.global.more %></a>
<div id="new-post"></div>
</div>
<div class="body-content" id="activity-feed">
<menu class="tab-header">
<li id="tab-header-my-feed" class="tab-button <%if(tab === 0){ %>selected<%}%>" data-show-post-button="1">
<a href="/feed/" data-pjax-replace="1" data-sound="SE_WAVE_SELECT_TAB">
<span class="new-post">My Feed</span>
</a>
</li>
<li id="tab-header-global-feed" class="tab-button <%if(tab === 1){ %>selected<%}%>">
<a href="/feed/all" data-pjax-cache-container="#body" data-pjax-replace="1" data-sound="SE_WAVE_SELECT_TAB">
<span>Global Feed</span>
</a>
</li>
</menu>
<div class="tab-body post-list">
<%- include('partials/' + template, { bundle }); %>
</div>

View File

@ -2,8 +2,8 @@
<%if(!bundle.notifications) {%><li><p><%= lang.notifications.none %></p></li><%}%>
<%if(bundle.notifications){%>
<% for(var notification of bundle.notifications) {%>
<% if(notification.type === 'follow') {%>
<li>
<% if(notification.type === 'follow') {%>
<a href="/users/<%= notification.objectID %>" data-pjax="#body" class="icon-container notify">
<img src="<%= cdnURL %>/mii/<%= notification.objectID %>/normal_face.png" class="icon">
</a>
@ -30,20 +30,20 @@
</p>
<%}%>
</div>
</li>
<%} else if (notification.type === 'notice') {%>
<li>
<a href="<%= notification.link %>" data-pjax="#body" class="icon-container notify">
<img src="<%= notification.image %>" class="icon">
</a>
<a class="body" href="<%= notification.link %>">
<div class="body">
<a class="body" href="<%= notification.link %>">
<span class="text">
<span class="nick-name"><%= notification.text %></span>
<%= notification.text %>
<span class="timestamp"> <%= moment(notification.lastUpdated).fromNow() %></span>
</span>
</a>
</li>
</span>
</a>
</div>
<%}%>
</li>
<%}%>
<%}%>
</ul>

View File

@ -3,9 +3,9 @@
<p class="no-posts-text"><%= lang.global.no_posts %></p>
<%} else { %>
<% bundle.posts.forEach(function(post) { %>
<%- include('post_template', { post: post, mii_image_CDN: bundle.mii_image_CDN, lang: bundle.lang, userContent: bundle.userContent, communityMap: bundle.communityMap, reply: false }); %>
<%- include('post_template', { post: post, userContent: bundle.userContent, communityMap: bundle.communityMap, reply: false }); %>
<% }); %>
<div class="button-wrapper center">
<button type="button" class="load-more" data-href="<%= bundle.link %>"><%= bundle.lang.global.more %></button>
<button type="button" class="load-more" data-href="<%= bundle.link %>"><%= lang.global.more %></button>
</div>
<%}%>

View File

@ -29,10 +29,10 @@
</header>
<div class="body-content post-list" id="post">
<div class="post-wrapper parent">
<%- include('partials/post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false, pid: pid, mainPost: true }); %>
<%- include('partials/post_template', { post: post, reply: false, pid: pid, mainPost: true }); %>
</div>
<% replies.forEach(function(post) { %>
<%- include('partials/post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: true, pid: pid }); %>
<%- include('partials/post_template', { post: post, reply: true, pid: pid }); %>
<% }); %>
</div>
<% if((

View File

@ -12,7 +12,7 @@
</header>
<div class="body-content tab2-content" id="community-post-list">
<div class="header-banner-container">
<img src="<%= cdnURL %>/images/banner.png" class="header-banner with-top-button">
<img src="/images/banner.png" class="header-banner with-top-button">
</div>
<div class="community-info info-content with-header-banner">
<span class="icon-container"><img src="<%if (banned || pnid.deleted) { %>/images/bandwidthlost.png<% } else { %><%= cdnURL %>/mii/<%=pnid.pid%>/normal_face.png<%}%>" class="icon" alt=""></span>

View File

@ -8,6 +8,10 @@
<%- include('partials/nav_bar', { selection: 1, pid: pid }); %>
<div id="toast"></div>
<div id="wrapper">
<div class="buttons tabs" style="margin-bottom: 1.5em;">
<a id="my-feed" href="/feed" <% if(tab == 0) {%>class="selected"<%}%>>My Feed</a>
<a id="all-feed" href="/feed/all" <% if(tab == 1) {%>class="selected"<%}%>>Global Feed</a>
</div>
<%- include('partials/' + template, { bundle }); %>
</div>
</div>

View File

@ -75,7 +75,7 @@
<p class="no-posts-text"><%= lang.activity_feed.empty %></p>
<%} else { %>
<% newPosts.forEach(function(post) { %>
<%- include('post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false }); %>
<%- include('post_template', { post: post, reply: false }); %>
<% }); %>
<%}%>
</div>

View File

@ -1,3 +1,3 @@
<% newPosts.forEach(function(post) { %>
<%- include('post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false }); %>
<%- include('post_template', { post: post, reply: false }); %>
<% }); %>

View File

@ -40,7 +40,7 @@
</a>
<a class="body" href="<%= notification.link %>">
<span class="text">
<span class="nick-name"><%= notification.text %></span>
<%= notification.text %>
<span class="timestamp"> <%= moment(notification.lastUpdated).fromNow() %></span>
</span>
</a>

View File

@ -3,7 +3,7 @@
<p class="no-posts-text"><%= lang.global.no_posts %></p>
<%} else { %>
<% bundle.posts.forEach(function(post) { %>
<%- include('post_template', { post: post, mii_image_CDN: bundle.mii_image_CDN, lang: bundle.lang, userContent: bundle.userContent, communityMap: bundle.communityMap, reply: false }); %>
<%- include('post_template', { post: post, userContent: bundle.userContent, communityMap: bundle.communityMap, reply: false }); %>
<% }); %>
<div id="wrapper" class="bottom">
<button id="load-more" data-href="<%= bundle.link %>"><%= lang.global.more %></button>

View File

@ -57,10 +57,10 @@
<!--<button id="header-post-button" class="header-button" href="#" data-module-hide="post" data-module-show="add-post-page" data-header="false" data-menu="false">+</button>-->
<%}%>
<%}%>
<%- include('partials/post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false, mainPost: true }); %>
<%- include('partials/post_template', { post: post, reply: false, mainPost: true }); %>
<span class="replies-line"></span>
<% replies.forEach(function(post) { %>
<%- include('partials/post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: true }); %>
<%- include('partials/post_template', { post: post, reply: true }); %>
<span class="replies-line"></span>
<% }); %>
</div>

View File

@ -81,7 +81,7 @@
</span>
</div>
</summary>
<%- include('partials/post_template', { post: post, mii_image_CDN: mii_image_CDN, lang: lang, reply: false }); %>
<%- include('partials/post_template', { post: post, reply: false }); %>
<div class="button-spacer">
<button onclick="remove(this)" data-id="<%=report._id%>">Remove Post</button>
<button onclick="ignore(this)" data-id="<%=report._id%>">Ignore Report</button>