2026-03-12 14:03:01 +08:00
|
|
|
|
import fs from 'node:fs'
|
2026-03-12 10:04:29 +08:00
|
|
|
|
import path from 'node:path'
|
|
|
|
|
|
import notificationRules from '../src/config/notificationRules.js'
|
|
|
|
|
|
|
|
|
|
|
|
const rootDir = path.resolve(import.meta.dirname, '..')
|
|
|
|
|
|
const targetFile = path.join(
|
|
|
|
|
|
rootDir,
|
|
|
|
|
|
'android',
|
|
|
|
|
|
'app',
|
|
|
|
|
|
'src',
|
|
|
|
|
|
'main',
|
|
|
|
|
|
'java',
|
|
|
|
|
|
'com',
|
|
|
|
|
|
'echo',
|
|
|
|
|
|
'app',
|
|
|
|
|
|
'notification',
|
|
|
|
|
|
'NotificationRuleData.kt',
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const toKotlinString = (value) => JSON.stringify(value).replace(/\$/g, '\\$')
|
|
|
|
|
|
|
|
|
|
|
|
const toKotlinStringList = (values = []) =>
|
|
|
|
|
|
values.length ? `listOf(${values.map((value) => toKotlinString(value)).join(', ')})` : 'emptyList()'
|
|
|
|
|
|
|
|
|
|
|
|
const toKotlinRegex = (spec) => {
|
|
|
|
|
|
if (!spec?.pattern) return 'null'
|
|
|
|
|
|
const flags = spec.flags?.includes('i') ? ', setOf(RegexOption.IGNORE_CASE)' : ''
|
|
|
|
|
|
return `Regex(${toKotlinString(spec.pattern)}${flags})`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 14:03:01 +08:00
|
|
|
|
const toOptionalString = (value) => (value ? toKotlinString(value) : 'null')
|
|
|
|
|
|
|
2026-03-12 10:04:29 +08:00
|
|
|
|
const toRuleBlock = (rule) => ` NotificationRuleDefinition(
|
|
|
|
|
|
id = ${toKotlinString(rule.id)},
|
|
|
|
|
|
label = ${toKotlinString(rule.label)},
|
|
|
|
|
|
channels = ${toKotlinStringList(rule.channels)},
|
|
|
|
|
|
keywords = ${toKotlinStringList(rule.keywords)},
|
|
|
|
|
|
requiredTextPatterns = ${toKotlinStringList(rule.requiredTextPatterns)},
|
|
|
|
|
|
direction = NotificationRuleDirection.${rule.direction === 'income' ? 'INCOME' : 'EXPENSE'},
|
2026-03-12 14:03:01 +08:00
|
|
|
|
entryType = ${toKotlinString(rule.entryType || 'expense')},
|
|
|
|
|
|
fundSourceType = ${toKotlinString(rule.fundSourceType || 'cash')},
|
|
|
|
|
|
fundSourceName = ${toOptionalString(rule.fundSourceName)},
|
|
|
|
|
|
fundSourceNameFromChannel = ${rule.fundSourceNameFromChannel ? 'true' : 'false'},
|
|
|
|
|
|
fundTargetType = ${toKotlinString(rule.fundTargetType || 'merchant')},
|
|
|
|
|
|
fundTargetName = ${toOptionalString(rule.fundTargetName)},
|
|
|
|
|
|
fundTargetNameFromChannel = ${rule.fundTargetNameFromChannel ? 'true' : 'false'},
|
|
|
|
|
|
impactExpense = ${rule.impactExpense === false ? 'false' : 'true'},
|
|
|
|
|
|
impactIncome = ${rule.impactIncome ? 'true' : 'false'},
|
2026-03-12 10:04:29 +08:00
|
|
|
|
defaultCategory = ${toKotlinString(rule.defaultCategory)},
|
|
|
|
|
|
autoCapture = ${rule.autoCapture ? 'true' : 'false'},
|
|
|
|
|
|
merchantPattern = ${toKotlinRegex(rule.merchantPattern)},
|
2026-03-12 14:03:01 +08:00
|
|
|
|
defaultMerchant = ${toOptionalString(rule.defaultMerchant)},
|
2026-03-12 10:04:29 +08:00
|
|
|
|
)`
|
|
|
|
|
|
|
|
|
|
|
|
const content = `package com.echo.app.notification
|
|
|
|
|
|
|
|
|
|
|
|
// Generated from src/config/notificationRules.js by scripts/sync-notification-rules.mjs.
|
|
|
|
|
|
internal object NotificationRuleData {
|
|
|
|
|
|
val fallbackRules: List<NotificationRuleDefinition> = listOf(
|
|
|
|
|
|
${notificationRules.map(toRuleBlock).join(',\n')}
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
|
|
fs.writeFileSync(targetFile, content)
|
|
|
|
|
|
console.log(`[rules:sync] wrote ${path.relative(rootDir, targetFile)}`)
|