mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 12:04:02 +00:00
chore(ops): add reminder trigger helper
This commit is contained in:
@@ -39,7 +39,8 @@
|
|||||||
"test:e2e": "bun run scripts/e2e/billing-flow.ts",
|
"test:e2e": "bun run scripts/e2e/billing-flow.ts",
|
||||||
"ops:deploy:smoke": "bun run scripts/ops/deploy-smoke.ts",
|
"ops:deploy:smoke": "bun run scripts/ops/deploy-smoke.ts",
|
||||||
"ops:telegram:webhook": "bun run scripts/ops/telegram-webhook.ts",
|
"ops:telegram:webhook": "bun run scripts/ops/telegram-webhook.ts",
|
||||||
"ops:telegram:commands": "bun run scripts/ops/telegram-commands.ts"
|
"ops:telegram:commands": "bun run scripts/ops/telegram-commands.ts",
|
||||||
|
"ops:reminder": "bun run scripts/ops/trigger-reminder.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "1.3.10",
|
"@types/bun": "1.3.10",
|
||||||
|
|||||||
108
scripts/ops/trigger-reminder.ts
Normal file
108
scripts/ops/trigger-reminder.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
type ReminderType = 'utilities' | 'rent-warning' | 'rent-due'
|
||||||
|
|
||||||
|
function parseReminderType(raw: string | undefined): ReminderType {
|
||||||
|
const value = raw?.trim()
|
||||||
|
|
||||||
|
if (value === 'utilities' || value === 'rent-warning' || value === 'rent-due') {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
'Usage: bun run ops:reminder <utilities|rent-warning|rent-due> [period] [--dry-run]'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseArgs(argv: readonly string[]) {
|
||||||
|
const reminderType = parseReminderType(argv[2])
|
||||||
|
const rawPeriod = argv[3]?.trim()
|
||||||
|
const dryRun = argv.includes('--dry-run')
|
||||||
|
|
||||||
|
return {
|
||||||
|
reminderType,
|
||||||
|
period: rawPeriod && rawPeriod.length > 0 ? rawPeriod : undefined,
|
||||||
|
dryRun
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readText(command: string[], name: string): string {
|
||||||
|
const result = Bun.spawnSync(command, {
|
||||||
|
stdout: 'pipe',
|
||||||
|
stderr: 'pipe'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result.exitCode !== 0) {
|
||||||
|
const stderr = result.stderr.toString().trim()
|
||||||
|
throw new Error(`${name} failed: ${stderr || `exit code ${result.exitCode}`}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = result.stdout.toString().trim()
|
||||||
|
if (!value) {
|
||||||
|
throw new Error(`${name} returned an empty value`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveBotApiUrl(): string {
|
||||||
|
const envValue = process.env.BOT_API_URL?.trim()
|
||||||
|
if (envValue) {
|
||||||
|
return envValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return readText(
|
||||||
|
['terraform', '-chdir=infra/terraform', 'output', '-raw', 'bot_api_service_url'],
|
||||||
|
'terraform output bot_api_service_url'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveSchedulerSecret(): string {
|
||||||
|
const envValue = process.env.SCHEDULER_SHARED_SECRET?.trim()
|
||||||
|
if (envValue) {
|
||||||
|
return envValue
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectId = process.env.GCP_PROJECT_ID?.trim() || 'gen-lang-client-0200379851'
|
||||||
|
return readText(
|
||||||
|
[
|
||||||
|
'gcloud',
|
||||||
|
'secrets',
|
||||||
|
'versions',
|
||||||
|
'access',
|
||||||
|
'latest',
|
||||||
|
'--secret=scheduler-shared-secret',
|
||||||
|
'--project',
|
||||||
|
projectId
|
||||||
|
],
|
||||||
|
'gcloud secrets versions access'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const { reminderType, period, dryRun } = parseArgs(process.argv)
|
||||||
|
const botApiUrl = resolveBotApiUrl().replace(/\/$/, '')
|
||||||
|
const schedulerSecret = resolveSchedulerSecret()
|
||||||
|
|
||||||
|
const response = await fetch(`${botApiUrl}/jobs/reminder/${reminderType}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
'x-household-scheduler-secret': schedulerSecret
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
...(period ? { period } : {}),
|
||||||
|
...(dryRun ? { dryRun: true } : {})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const text = await response.text()
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`${response.status} ${response.statusText}: ${text}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch((error) => {
|
||||||
|
console.error(error instanceof Error ? error.message : String(error))
|
||||||
|
process.exitCode = 1
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user