mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-23 04:34:15 -04:00
#101 stats - server
This commit is contained in:
parent
2ee74b0a1d
commit
073612a10f
@ -1,17 +1,12 @@
|
|||||||
import { loadSuml } from './server/loader';
|
import { loadSuml } from './server/loader';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import {buildDict} from "./src/helpers";
|
import {buildDict, buildLocaleList} from "./src/helpers";
|
||||||
|
|
||||||
const config = loadSuml('config');
|
const config = loadSuml('config');
|
||||||
const translations = loadSuml('translations');
|
const translations = loadSuml('translations');
|
||||||
|
|
||||||
const locale = config.locale;
|
const locale = config.locale;
|
||||||
const locales = buildDict(function* () {
|
const locales = buildLocaleList();
|
||||||
for (let locale of process.env.LOCALES.split('|')) {
|
|
||||||
const [code, name, url] = locale.split(',');
|
|
||||||
yield [code, {name, url}];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const title = translations.title;
|
const title = translations.title;
|
||||||
const description = translations.description;
|
const description = translations.description;
|
||||||
const banner = process.env.BASE_URL + '/api/banner/zaimki.png';
|
const banner = process.env.BASE_URL + '/api/banner/zaimki.png';
|
||||||
|
@ -145,7 +145,12 @@
|
|||||||
for (let pronoun in this.profile.pronouns) {
|
for (let pronoun in this.profile.pronouns) {
|
||||||
if (!this.profile.pronouns.hasOwnProperty(pronoun)) { continue; }
|
if (!this.profile.pronouns.hasOwnProperty(pronoun)) { continue; }
|
||||||
|
|
||||||
const link = decodeURIComponent(pronoun.replace(new RegExp('^' + this.$base), '').replace(new RegExp('^/'), ''));
|
const link = decodeURIComponent(
|
||||||
|
pronoun
|
||||||
|
.replace(new RegExp('^' + this.$base), '')
|
||||||
|
.replace(new RegExp('^' + this.$base.replace(/^https?:\/\//, '')), '')
|
||||||
|
.replace(new RegExp('^/'), '')
|
||||||
|
);
|
||||||
const pronounEntity = buildPronoun(pronouns, link);
|
const pronounEntity = buildPronoun(pronouns, link);
|
||||||
|
|
||||||
if (pronounEntity) {
|
if (pronounEntity) {
|
||||||
|
@ -189,7 +189,12 @@
|
|||||||
this.$router.push(`/@${this.$user().username}`)
|
this.$router.push(`/@${this.$user().username}`)
|
||||||
},
|
},
|
||||||
validatePronoun(pronoun) {
|
validatePronoun(pronoun) {
|
||||||
const link = decodeURIComponent(pronoun.replace(new RegExp('^' + this.$base), '').replace(new RegExp('^/'), ''));
|
const link = decodeURIComponent(
|
||||||
|
pronoun
|
||||||
|
.replace(new RegExp('^' + this.$base), '')
|
||||||
|
.replace(new RegExp('^' + this.$base.replace(/^https?:\/\//, '')), '')
|
||||||
|
.replace(new RegExp('^/'), '')
|
||||||
|
);
|
||||||
|
|
||||||
return buildPronoun(pronouns, link) ? null : 'profile.pronounsNotFound'
|
return buildPronoun(pronouns, link) ? null : 'profile.pronounsNotFound'
|
||||||
},
|
},
|
||||||
|
@ -6,6 +6,7 @@ import cookieParser from 'cookie-parser';
|
|||||||
import grant from "grant";
|
import grant from "grant";
|
||||||
import router from "./routes/user";
|
import router from "./routes/user";
|
||||||
import { loadSuml } from './loader';
|
import { loadSuml } from './loader';
|
||||||
|
import {buildLocaleList} from "../src/helpers";
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ app.use(session({
|
|||||||
|
|
||||||
app.use(async function (req, res, next) {
|
app.use(async function (req, res, next) {
|
||||||
req.config = loadSuml('config');
|
req.config = loadSuml('config');
|
||||||
|
req.locales = buildLocaleList();
|
||||||
req.rawUser = authenticate(req);
|
req.rawUser = authenticate(req);
|
||||||
req.user = req.rawUser && req.rawUser.authenticated ? req.rawUser : null;
|
req.user = req.rawUser && req.rawUser.authenticated ? req.rawUser : null;
|
||||||
req.admin = req.user && req.user.roles === 'admin';
|
req.admin = req.user && req.user.roles === 'admin';
|
||||||
|
@ -2,7 +2,7 @@ import { Router } from 'express';
|
|||||||
import SQL from 'sql-template-strings';
|
import SQL from 'sql-template-strings';
|
||||||
import avatar from '../avatar';
|
import avatar from '../avatar';
|
||||||
import {config as socialLoginConfig} from "../social";
|
import {config as socialLoginConfig} from "../social";
|
||||||
import {now} from "../../src/helpers";
|
import {now, sortByValue} from "../../src/helpers";
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
@ -46,4 +46,50 @@ router.get('/admin/users', async (req, res) => {
|
|||||||
return res.json(groupedUsers);
|
return res.json(groupedUsers);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/admin/stats', async (req, res) => {
|
||||||
|
if (!req.admin) {
|
||||||
|
return res.status(401).json({error: 'Unauthorised'});
|
||||||
|
}
|
||||||
|
|
||||||
|
const users = {
|
||||||
|
overall: (await req.db.get(SQL`SELECT count(*) AS c FROM users`)).c,
|
||||||
|
admins: (await req.db.get(SQL`SELECT count(*) AS c FROM users WHERE roles=${'admin'}`)).c,
|
||||||
|
};
|
||||||
|
|
||||||
|
const locales = {};
|
||||||
|
for (let locale in req.locales) {
|
||||||
|
if (!req.locales.hasOwnProperty(locale)) { continue; }
|
||||||
|
const profiles = await req.db.all(SQL`SELECT pronouns FROM profiles WHERE locale=${locale}`);
|
||||||
|
const pronouns = {}
|
||||||
|
for (let profile of profiles) {
|
||||||
|
const pr = JSON.parse(profile.pronouns);
|
||||||
|
for (let pronoun in pr) {
|
||||||
|
if (!pr.hasOwnProperty(pronoun)) { continue; }
|
||||||
|
|
||||||
|
if (pronoun.includes(',') || pr[pronoun] < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const p = pronoun.replace(/^.*:\/\//, '').replace(/^\//, '').toLowerCase().replace(/^[a-z]+\.[^/]+\//, '');
|
||||||
|
if (pronouns[p] === undefined) {
|
||||||
|
pronouns[p] = 0;
|
||||||
|
}
|
||||||
|
pronouns[p]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locales[locale] = {
|
||||||
|
name: req.locales[locale].name,
|
||||||
|
url: req.locales[locale].url,
|
||||||
|
profiles: profiles.length,
|
||||||
|
pronouns: sortByValue(pronouns, true),
|
||||||
|
nouns: {
|
||||||
|
approved: (await req.db.get(SQL`SELECT count(*) AS c FROM nouns WHERE locale=${locale} AND approved=1`)).c,
|
||||||
|
awaiting: (await req.db.get(SQL`SELECT count(*) AS c FROM nouns WHERE locale=${locale} AND approved=0`)).c,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({ users, locales });
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -131,3 +131,30 @@ export const now = function () {
|
|||||||
export const isEmoji = char => {
|
export const isEmoji = char => {
|
||||||
return !!char.match(/^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])$/)
|
return !!char.match(/^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])$/)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const buildLocaleList = () => {
|
||||||
|
return buildDict(function* () {
|
||||||
|
for (let locale of process.env.LOCALES.split('|')) {
|
||||||
|
const [code, name, url] = locale.split(',');
|
||||||
|
yield [code, {name, url}];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const zip = (list, reverse) => {
|
||||||
|
return buildDict(function* () {
|
||||||
|
for (let [k, v] of list) {
|
||||||
|
yield reverse ? [v, k] : [k, v];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sortByValue = (obj, reverse = false) => {
|
||||||
|
const sortedArray = [];
|
||||||
|
for (let i in obj) {
|
||||||
|
if (obj.hasOwnProperty(i)) {
|
||||||
|
sortedArray.push([parseInt(obj[i]), i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return zip(sortedArray.sort((a, b) => reverse ? b[0] - a[0] : a[0] - b[0]), true);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user