| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- // Usage: node scripts/add_user_count_to_csv.mjs [OPTS] [INPUT-FILE]
- // Looks up the number of users for each domain in the input csv file and adds
- // columns for the number of users in the domain, subdomains, and total.
- import fs from 'node:fs'
- // https://github.com/import-js/eslint-plugin-import/issues/1810
- // eslint-disable-next-line import/no-unresolved
- import * as csv from 'csv/sync'
- import minimist from 'minimist'
- import UserGetter from '../app/src/Features/User/UserGetter.js'
- import { db } from '../app/src/infrastructure/mongodb.js'
- import _ from 'lodash'
- const argv = minimist(process.argv.slice(2), {
- string: ['domain', 'output'],
- boolean: ['help'],
- alias: {
- domain: 'd',
- output: 'o',
- },
- default: {
- domain: 'Email domain',
- output: '/dev/stdout',
- },
- })
- if (argv.help || argv._.length > 1) {
- console.error(`Usage: node scripts/add_user_count_to_csv.mjs [OPTS] [INPUT-FILE]
- Looks up the number of users for each domain in the input file and adds
- columns for the number of users in the domain, subdomains, and total.
- Options:
- --domain name of the csv column containing the email domain (default: "Email domain")
- --output output file (default: /dev/stdout)
- `)
- process.exit(1)
- }
- const input = fs.readFileSync(argv._[0], 'utf8')
- const records = csv.parse(input, { columns: true })
- if (records.length === 0) {
- console.error('No records in input file')
- process.exit(1)
- }
- async function main() {
- for (const record of records) {
- const domain = record[argv.domain]
- const { domainUserCount, subdomainUserCount } = await getUserCount(domain, {
- _id: 1,
- })
- record['Domain Users'] = domainUserCount
- record['Subdomain Users'] = subdomainUserCount
- record['Total Users'] = domainUserCount + subdomainUserCount
- }
- const output = csv.stringify(records, { header: true })
- fs.writeFileSync(argv.output, output)
- }
- async function getUserCount(domain) {
- const domainUsers = await UserGetter.promises.getUsersByHostname(domain, {
- _id: 1,
- })
- const subdomainUsers = await getUsersByHostnameWithSubdomain(domain, {
- _id: 1,
- })
- return {
- domainUserCount: domainUsers.length,
- subdomainUserCount: subdomainUsers.length,
- }
- }
- async function getUsersByHostnameWithSubdomain(domain, projection) {
- const reversedDomain = domain.trim().split('').reverse().join('')
- const reversedDomainRegex = _.escapeRegExp(reversedDomain)
- const query = {
- emails: { $exists: true },
- // look for users in subdomains of a domain, but not the domain itself
- // e.g. for domain 'foo.edu', match 'cs.foo.edu' but not 'foo.edu'
- // we use the reversed hostname index to do this efficiently
- // we need to escape the domain name to prevent '.' from matching any character
- 'emails.reversedHostname': { $regex: '^' + reversedDomainRegex + '\\.' },
- }
- return await db.users.find(query, { projection }).toArray()
- }
- try {
- await main()
- console.log('Done')
- process.exit(0)
- } catch (error) {
- console.error(error)
- process.exit(1)
- }
|