147 lines
4.6 KiB
TypeScript
147 lines
4.6 KiB
TypeScript
import type { UserConfigPersisted } from './config.js'
|
|
import type { MtcuteFeature } from './features/types.js'
|
|
import type { PackageManager } from './package-manager.js'
|
|
|
|
import * as colors from 'colorette'
|
|
import inquirer from 'inquirer'
|
|
import { open } from 'openurl'
|
|
|
|
import { readConfig, writeConfig } from './config.js'
|
|
import { TELEGRAM_APPS_PAGE } from './constants.js'
|
|
import { getFeatureChoices } from './features/cli.js'
|
|
|
|
interface UserConfigAnswers {
|
|
reuse?: boolean
|
|
apiId?: string
|
|
apiHash?: string
|
|
botToken?: string
|
|
features: MtcuteFeature[]
|
|
}
|
|
|
|
export interface UserConfig extends UserConfigPersisted {
|
|
name: string
|
|
botToken?: string
|
|
features: MtcuteFeature[]
|
|
packageManager: PackageManager
|
|
}
|
|
|
|
export async function askForConfigPersisted(): Promise<UserConfigPersisted> {
|
|
const existing = await readConfig()
|
|
|
|
if (existing) {
|
|
const { reuse } = await inquirer.prompt<UserConfigAnswers>([
|
|
{
|
|
type: 'confirm',
|
|
name: 'reuse',
|
|
message: 'Found existing config, do you want to reuse it?',
|
|
default: true,
|
|
},
|
|
])
|
|
|
|
if (reuse) return existing
|
|
}
|
|
|
|
const answers = await inquirer.prompt<UserConfigAnswers>([
|
|
{
|
|
type: 'input',
|
|
name: 'apiId',
|
|
message: 'API ID (press Enter to obtain one):',
|
|
validate: (v: string) => {
|
|
if (!v) {
|
|
// eslint-disable-next-line no-restricted-globals
|
|
setTimeout(() => {
|
|
try {
|
|
open(TELEGRAM_APPS_PAGE)
|
|
} catch {}
|
|
}, 1000)
|
|
|
|
return [
|
|
colors.italic(`Opening ${colors.blue(TELEGRAM_APPS_PAGE)}...`),
|
|
`🔒 Log in with your ${colors.blueBright('Telegram')} account`,
|
|
'📝 Fill out the form:',
|
|
` - ${colors.bold('App title, short name')}: anything you want, can be changed later`,
|
|
` - ${colors.bold('Platform')}: doesn't matter`,
|
|
` - ${colors.bold('URL')}: can be left blank`,
|
|
`🚀 Click ${colors.bold('Create application')}`,
|
|
`${colors.bold(
|
|
colors.red('❗ DO NOT'),
|
|
)} share your API hash with anyone, as it can't be revoked`,
|
|
].join('\n')
|
|
}
|
|
if (!/^\d+$/.test(v)) return 'API ID must be a number'
|
|
|
|
return true
|
|
},
|
|
},
|
|
{
|
|
type: 'input',
|
|
name: 'apiHash',
|
|
message: 'API hash:',
|
|
validate: (v: string) => {
|
|
if (!v) return 'API hash is required'
|
|
if (!v.match(/^[a-f0-9]{32}$/i)) return 'API hash must be 32 hex characters'
|
|
|
|
return true
|
|
},
|
|
},
|
|
{
|
|
type: 'confirm',
|
|
name: 'reuse',
|
|
message: 'Do you want to save these credentials for later use?',
|
|
default: true,
|
|
},
|
|
])
|
|
|
|
const config: UserConfigPersisted = {
|
|
apiId: Number(answers.apiId),
|
|
apiHash: answers.apiHash!,
|
|
}
|
|
|
|
if (answers.reuse) {
|
|
await writeConfig(config)
|
|
}
|
|
|
|
return config
|
|
}
|
|
|
|
export async function askForConfig(packageManager: PackageManager): Promise<UserConfig> {
|
|
const persisted = await askForConfigPersisted()
|
|
|
|
let allowEmptyBotToken = false
|
|
const { botToken, features } = await inquirer.prompt<UserConfigAnswers>([
|
|
{
|
|
type: 'input',
|
|
name: 'botToken',
|
|
message: 'Bot token (optional):',
|
|
validate: (v: string) => {
|
|
if (!v) {
|
|
if (allowEmptyBotToken) return true
|
|
|
|
allowEmptyBotToken = true
|
|
|
|
return [
|
|
`You most likely need a bot token. You can obtain one from ${colors.blue('@BotFather')}`,
|
|
` Press ${colors.bold('Enter')} again if you want to create a ${colors.magenta('userbot')}`,
|
|
].join('\n')
|
|
}
|
|
if (!v.match(/^\d+:[\w-]{16,50}$/)) return 'Invalid bot token'
|
|
|
|
return true
|
|
},
|
|
},
|
|
{
|
|
type: 'checkbox',
|
|
choices: getFeatureChoices(packageManager),
|
|
name: 'features',
|
|
message: 'Select features:',
|
|
},
|
|
])
|
|
|
|
return {
|
|
...persisted,
|
|
name: '', // will be filled later
|
|
packageManager,
|
|
botToken: botToken || undefined,
|
|
features,
|
|
}
|
|
}
|