mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-02 21:59:00 +02:00
Merge pull request #24271 from overleaf/ls-script-to-update-manually-billed-users
Scripts to update terms and conditions for manually billed users GitOrigin-RevId: 5efe43a42c3ed21779c9de698268817e2cbb5249
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import Settings from '@overleaf/settings'
|
||||
import recurly from 'recurly'
|
||||
import fs from 'node:fs'
|
||||
import { setTimeout } from 'node:timers/promises'
|
||||
import minimist from 'minimist'
|
||||
import * as csv from 'csv'
|
||||
import Stream from 'node:stream/promises'
|
||||
|
||||
const recurlyApiKey = Settings.apis.recurly.apiKey
|
||||
if (!recurlyApiKey) {
|
||||
throw new Error('Recurly API key is not set in the settings')
|
||||
}
|
||||
const client = new recurly.Client(recurlyApiKey)
|
||||
|
||||
function usage() {
|
||||
console.error(
|
||||
'Script to retrieve details of manually billed users from Recurly'
|
||||
)
|
||||
console.error('')
|
||||
console.error('Usage:')
|
||||
console.error(
|
||||
' node scripts/recurly/get_manually_billed_users_details.mjs [options]'
|
||||
)
|
||||
console.error('')
|
||||
console.error('Options:')
|
||||
console.error(
|
||||
' --input, -i <file> Path to CSV file containing subscription_id, period_end, currency (can be exported from Recurly)'
|
||||
)
|
||||
console.error(' --output, -o <file> Path to output CSV file')
|
||||
console.error('')
|
||||
console.error('Input format:')
|
||||
console.error(
|
||||
' CSV file with the following columns: subscription_id, period_end, currency (header row is skipped)'
|
||||
)
|
||||
}
|
||||
|
||||
function parseArgs() {
|
||||
return minimist(process.argv.slice(2), {
|
||||
alias: { i: 'input', o: 'output' },
|
||||
string: ['input', 'output'],
|
||||
})
|
||||
}
|
||||
|
||||
async function enrichRow(row) {
|
||||
const account = await client.getAccount(`code-${row.account_code}`)
|
||||
return {
|
||||
...row,
|
||||
email: account.email,
|
||||
first_name: account.firstName,
|
||||
last_name: account.lastName,
|
||||
cc_emails: account.ccEmails,
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { input: inputPath, output: outputPath, h, help } = parseArgs()
|
||||
if (help || h || !inputPath || !outputPath) {
|
||||
usage()
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
let processedCount = 0
|
||||
await Stream.pipeline([
|
||||
fs.createReadStream(inputPath),
|
||||
csv.parse({ columns: true }),
|
||||
async function* (rows) {
|
||||
for await (const row of rows) {
|
||||
try {
|
||||
yield await enrichRow(row)
|
||||
} catch (error) {
|
||||
console.error(`Error processing subscription ${row.subscription_id}`)
|
||||
}
|
||||
processedCount++
|
||||
if (processedCount % 1 === 0) {
|
||||
console.log(`Processed ${processedCount} subscriptions`)
|
||||
}
|
||||
await setTimeout(1000)
|
||||
}
|
||||
},
|
||||
csv.stringify({
|
||||
header: true,
|
||||
columns: {
|
||||
subscription_id: 'subscription_id',
|
||||
current_period_ends_at: 'period_end',
|
||||
currency: 'currency',
|
||||
email: 'email',
|
||||
first_name: 'first_name',
|
||||
last_name: 'last_name',
|
||||
cc_emails: 'cc_emails',
|
||||
},
|
||||
}),
|
||||
fs.createWriteStream(outputPath),
|
||||
])
|
||||
console.log(`Processed ${processedCount} subscriptions in total`)
|
||||
}
|
||||
|
||||
try {
|
||||
await main()
|
||||
process.exit(0)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
import recurly from 'recurly'
|
||||
import Settings from '@overleaf/settings'
|
||||
import fs from 'node:fs'
|
||||
import minimist from 'minimist'
|
||||
import * as csv from 'csv'
|
||||
import { setTimeout } from 'node:timers/promises'
|
||||
|
||||
const recurlyApiKey = Settings.apis.recurly.apiKey
|
||||
if (!recurlyApiKey) {
|
||||
throw new Error('Recurly API key is not set in the settings')
|
||||
}
|
||||
const client = new recurly.Client(recurlyApiKey)
|
||||
|
||||
function usage() {
|
||||
console.error(
|
||||
'Script to update terms and conditions for manually billed Recurly subscriptions'
|
||||
)
|
||||
console.error('')
|
||||
console.error('Usage:')
|
||||
console.error(
|
||||
' node scripts/recurly/update_terms_and_conditions_for_manually_billed_users.mjs [options]'
|
||||
)
|
||||
console.error('')
|
||||
console.error('Options:')
|
||||
console.error(
|
||||
' --input, -i <file> Path to CSV file containing subscription IDs (can be exported from Recurly)'
|
||||
)
|
||||
console.error(
|
||||
' --termsAndConditions, -t <file> Path to text file containing terms and conditions'
|
||||
)
|
||||
console.error('')
|
||||
console.error('Input format:')
|
||||
console.error(
|
||||
' - Subscription IDs CSV: First column contains subscription IDs (header row is skipped)'
|
||||
)
|
||||
console.error(
|
||||
' - Terms and conditions: Plain text file with the terms and conditions content'
|
||||
)
|
||||
}
|
||||
|
||||
function parseArgs() {
|
||||
return minimist(process.argv.slice(2), {
|
||||
string: ['input', 'termsAndConditions'],
|
||||
alias: {
|
||||
i: 'input',
|
||||
t: 'termsAndConditions',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function updateTermsAndConditionsForSubscription(
|
||||
subscriptionId,
|
||||
termsAndConditions
|
||||
) {
|
||||
try {
|
||||
await client.updateSubscription(`uuid-${subscriptionId}`, {
|
||||
terms_and_conditions: termsAndConditions,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error updating subscription ${subscriptionId}: ${error.message}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const {
|
||||
termsAndConditions: termsAndConditionsPath,
|
||||
input: inputPath,
|
||||
h,
|
||||
help,
|
||||
} = parseArgs()
|
||||
if (help || h || !termsAndConditionsPath || !inputPath) {
|
||||
usage()
|
||||
process.exit(0)
|
||||
}
|
||||
const termsAndConditions = fs.readFileSync(termsAndConditionsPath, 'utf8')
|
||||
|
||||
const parser = csv.parse({ columns: true })
|
||||
fs.createReadStream(inputPath).pipe(parser)
|
||||
let processedCount = 0
|
||||
for await (const row of parser) {
|
||||
const subscriptionId = row.subscription_id
|
||||
await updateTermsAndConditionsForSubscription(
|
||||
subscriptionId,
|
||||
termsAndConditions
|
||||
)
|
||||
processedCount++
|
||||
if (processedCount % 10 === 0) {
|
||||
console.log(`Processed ${processedCount} subscriptions`)
|
||||
}
|
||||
await setTimeout(1000)
|
||||
}
|
||||
console.log(`Processed ${processedCount} subscriptions in total`)
|
||||
}
|
||||
|
||||
try {
|
||||
await main()
|
||||
process.exit(0)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
}
|
||||
Reference in New Issue
Block a user