mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Convert export_institution_chat script to ES module
GitOrigin-RevId: 8570922654049edb514f8091421e5be2f04988cd
This commit is contained in:
parent
bafda84420
commit
d2e6608f01
1 changed files with 146 additions and 0 deletions
146
services/web/scripts/export_institution_chat.mjs
Normal file
146
services/web/scripts/export_institution_chat.mjs
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import {
|
||||||
|
db,
|
||||||
|
READ_PREFERENCE_SECONDARY,
|
||||||
|
waitForDb,
|
||||||
|
ObjectId,
|
||||||
|
} from '../app/src/infrastructure/mongodb.js'
|
||||||
|
import minimist from 'minimist'
|
||||||
|
import InstitutionHubsController from '../modules/metrics/app/src/InstitutionHubsController.js'
|
||||||
|
|
||||||
|
function usage() {
|
||||||
|
console.log(
|
||||||
|
`Usage: node export_institution_chat.js --institution <id> --from <date> --to <date> [--pretty] [--help]
|
||||||
|
|
||||||
|
--institution=ID
|
||||||
|
The V1 institution ID
|
||||||
|
|
||||||
|
--from=DATE
|
||||||
|
The start of the report period. Specified as an ISO 8601 date string
|
||||||
|
(e.g. 2024-08-01T00:00:00.000Z)
|
||||||
|
|
||||||
|
--to=DATE
|
||||||
|
The end of the report period. Specified as an ISO 8601 date string
|
||||||
|
(e.g. 2024-09-01T00:00:00.000Z)
|
||||||
|
|
||||||
|
--help
|
||||||
|
Prints this help page\n`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseArgs() {
|
||||||
|
const argv = minimist(process.argv.slice(2), {
|
||||||
|
string: ['institution', 'from', 'to'],
|
||||||
|
bool: ['help'],
|
||||||
|
default: {
|
||||||
|
help: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (argv.help) {
|
||||||
|
usage()
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!argv.institution || !argv.from || !argv.to) {
|
||||||
|
usage()
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const institutionId = parseInt(argv.institution, 10)
|
||||||
|
const from = new Date(argv.from).getTime()
|
||||||
|
const to = new Date(argv.to).getTime()
|
||||||
|
|
||||||
|
if (to < from) {
|
||||||
|
console.error('The end date must be after the start date.')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { institutionId, from, to }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchInstitutionAndAffiliations(institutionId) {
|
||||||
|
const { json: affiliations } =
|
||||||
|
await InstitutionHubsController.promises.v1InstitutionsApi(
|
||||||
|
institutionId,
|
||||||
|
'csv_affiliations'
|
||||||
|
)
|
||||||
|
return affiliations.filter(({ license }) => license === 'pro_plus')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUserMappings(affiliations) {
|
||||||
|
const entries = affiliations.map(({ user_id: userId, email }) => [
|
||||||
|
userId,
|
||||||
|
email,
|
||||||
|
])
|
||||||
|
return new Map(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const args = parseArgs()
|
||||||
|
await waitForDb()
|
||||||
|
const affiliations = await fetchInstitutionAndAffiliations(args.institutionId)
|
||||||
|
const userMappings = getUserMappings(affiliations)
|
||||||
|
|
||||||
|
const projectRecords = []
|
||||||
|
|
||||||
|
for (const [userId, email] of userMappings.entries()) {
|
||||||
|
projectRecords.push(...(await processUser(userId, email, args)))
|
||||||
|
}
|
||||||
|
console.log(JSON.stringify(projectRecords, null, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processUser(userId, email, args) {
|
||||||
|
const projectsOwnedByUser = db.projects.find(
|
||||||
|
{ owner_ref: new ObjectId(userId) },
|
||||||
|
{ projection: { name: 1 }, readPreference: READ_PREFERENCE_SECONDARY }
|
||||||
|
)
|
||||||
|
const projectRecords = []
|
||||||
|
for await (const project of projectsOwnedByUser) {
|
||||||
|
const hasMessages = await processProject(project, args)
|
||||||
|
if (hasMessages) {
|
||||||
|
projectRecords.push({
|
||||||
|
projectId: project._id,
|
||||||
|
owner: email,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return projectRecords
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processProject(project, args) {
|
||||||
|
const { _id: projectId } = project
|
||||||
|
const globalRoom = await db.rooms.findOne(
|
||||||
|
{
|
||||||
|
project_id: new ObjectId(projectId),
|
||||||
|
thread_id: { $exists: false },
|
||||||
|
},
|
||||||
|
{ readPreference: READ_PREFERENCE_SECONDARY }
|
||||||
|
)
|
||||||
|
if (!globalRoom) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const messages = await db.messages
|
||||||
|
.find(
|
||||||
|
{
|
||||||
|
room_id: globalRoom._id,
|
||||||
|
timestamp: { $gte: args.from, $lte: args.to },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projection: {
|
||||||
|
user_id: 1,
|
||||||
|
timestamp: 1,
|
||||||
|
},
|
||||||
|
readPreference: READ_PREFERENCE_SECONDARY,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.sort({ timestamp: 1 })
|
||||||
|
.toArray()
|
||||||
|
return messages.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await main()
|
||||||
|
process.exit(0)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
Loading…
Reference in a new issue