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[]>(SQL` SELECT email, roles, adminNotifications FROM users WHERE roles != '' AND roles != '*-external' `); const awaitingModerationGrouped: Record = {}; 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();