mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-03 11:07:00 -04:00
124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
import './setup.ts';
|
|
|
|
import SQL from 'sql-template-strings';
|
|
|
|
import dbConnection from './db.ts';
|
|
import type { UserRow } from './express/user.ts';
|
|
import mailer from './mailer.ts';
|
|
|
|
import { loadTranslator } from '~/server/data.ts';
|
|
import { newDate, isGrantedForUser, isPermissionArea } from '~/src/helpers.ts';
|
|
import type { PermissionArea } from '~/src/helpers.ts';
|
|
|
|
const shouldNotify = (frequency: number) => {
|
|
if (frequency === 0) {
|
|
return false;
|
|
}
|
|
|
|
if (frequency === 7) {
|
|
return newDate().getDay() === 6; // Saturdays
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
async function notify() {
|
|
const db = await dbConnection();
|
|
|
|
const awaitingModeration: {
|
|
type: PermissionArea | string & {};
|
|
locale: string;
|
|
c: number;
|
|
}[] = [
|
|
...await db.all(SQL`
|
|
SELECT 'nouns' as type, locale, count(*) as c
|
|
FROM nouns
|
|
WHERE approved = 0 AND deleted=0
|
|
GROUP BY locale
|
|
`),
|
|
...await db.all(SQL`
|
|
SELECT 'inclusive' as type, locale, count(*) as c
|
|
FROM inclusive
|
|
WHERE approved = 0 AND deleted=0
|
|
GROUP BY locale
|
|
`),
|
|
...await db.all(SQL`
|
|
SELECT 'terms' as type, locale, count(*) as c
|
|
FROM terms
|
|
WHERE approved = 0 AND deleted=0
|
|
GROUP BY locale
|
|
`),
|
|
...await db.all(SQL`
|
|
SELECT 'sources' as type, locale, count(*) as c
|
|
FROM sources
|
|
WHERE approved = 0 AND deleted=0
|
|
GROUP BY locale
|
|
`),
|
|
...await db.all(SQL`
|
|
SELECT 'names' as type, locale, count(*) as c
|
|
FROM names
|
|
WHERE approved = 0 AND deleted=0
|
|
GROUP BY locale
|
|
`),
|
|
...await db.all(SQL`
|
|
SELECT 'translations' as type, locale, count(*) as c
|
|
FROM translations
|
|
WHERE status = 0 OR status = 1
|
|
GROUP BY locale
|
|
`),
|
|
...await db.all(SQL`
|
|
SELECT 'reports' as type, null as locale, count(*) as c
|
|
FROM reports
|
|
WHERE isHandled = 0
|
|
`),
|
|
...await db.all(SQL`
|
|
SELECT 'ban-proposals' as type, null as locale, (
|
|
SELECT count(*)
|
|
FROM ban_proposals p
|
|
LEFT JOIN users u ON p.userId = u.id
|
|
WHERE u.bannedBy IS NULL
|
|
) as c
|
|
`),
|
|
].filter((r) => r.c > 0);
|
|
|
|
if (!awaitingModeration.length) {
|
|
console.log('No entries awaiting moderation');
|
|
return;
|
|
}
|
|
|
|
const admins = await db.all<Pick<UserRow, 'email' | 'roles' | 'adminNotifications'>[]>(SQL`
|
|
SELECT email, roles, adminNotifications
|
|
FROM users
|
|
WHERE roles != '' AND roles != '*-external'
|
|
`);
|
|
|
|
const awaitingModerationGrouped: Record<string, { [k: string]: number }> = {};
|
|
let count = 0;
|
|
for (const m of awaitingModeration) {
|
|
for (const admin of admins) {
|
|
if ((!isPermissionArea(m.type) || isGrantedForUser(admin, m.locale, m.type)) &&
|
|
shouldNotify(admin.adminNotifications)) {
|
|
awaitingModerationGrouped[admin.email] ||= {};
|
|
awaitingModerationGrouped[admin.email][`${m.locale || '*'}-${m.type}`] = m.c;
|
|
}
|
|
}
|
|
count += m.c;
|
|
}
|
|
|
|
console.log('Entries awaiting moderation: ', count);
|
|
|
|
for (const email in awaitingModerationGrouped) {
|
|
if (!Object.hasOwn(awaitingModerationGrouped, email)) {
|
|
continue;
|
|
}
|
|
const stats = awaitingModerationGrouped[email];
|
|
console.log('Sending email:', email, stats);
|
|
|
|
await mailer(email, 'notify', await loadTranslator('_'), { stats });
|
|
}
|
|
|
|
await db.close();
|
|
}
|
|
|
|
notify();
|