feat(create-bot): various improvements
- improved bun support - deno support - use antfu/eslint-config - fixed some issues - removed pre-commit hooks
This commit is contained in:
parent
7f7f513bc8
commit
64da48926f
29 changed files with 324 additions and 345 deletions
|
@ -5,22 +5,24 @@ Starter kit for creating bots using `@mtcute/node` or `@mtcute/bun`.
|
||||||
[Learn more](https://mtcute.dev/guide/)
|
[Learn more](https://mtcute.dev/guide/)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- **Linters**: can generate linting configs for `eslint` and `prettier`
|
- **Linters**: can set up linters using [@antfu/eslint-config](https://github.com/antfu/eslint-config)
|
||||||
- **TypeScript**: can generate a TypeScript project
|
- **TypeScript**: can generate a TypeScript project
|
||||||
- **Docker**: can generate a Dockerfile for easy deployment
|
- **Docker**: can generate a Dockerfile for easy deployment
|
||||||
- **I18n**: can generate a basic i18n setup using `@mtcute/i18n`
|
- **I18n**: can generate a basic i18n setup using `@mtcute/i18n`
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Depending on your preferred package manager, run one of the following commands:
|
Depending on your preferred package manager and runtime, run one of the following commands:
|
||||||
```bash
|
```bash
|
||||||
pnpm create @mtcute/bot
|
pnpm create @mtcute/bot my-awesome-bot
|
||||||
# or
|
# or
|
||||||
yarn create @mtcute/bot
|
yarn create @mtcute/bot my-awesome-bot
|
||||||
# or
|
# or
|
||||||
npm create @mtcute/bot
|
npm create @mtcute/bot my-awesome-bot
|
||||||
# or
|
# or
|
||||||
bun create @mtcute/bot
|
bun create @mtcute/bot my-awesome-bot
|
||||||
|
# or
|
||||||
|
deno run -A npm:@mtcute/create-bot my-awesome-bot
|
||||||
```
|
```
|
||||||
|
|
||||||
and follow the instructions
|
and follow the instructions
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm run -w build-package create-bot",
|
"build": "pnpm run -w build-package create-bot",
|
||||||
"run": "ts-node-esm src/main.ts"
|
"run": "ts-node-esm src/main.ts",
|
||||||
|
"run:deno": "node scripts/generate-import-map.js && deno run --import-map=./scripts/import-map.json -A --unstable-sloppy-imports src/main.ts"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"create-bot": "./src/main.js"
|
"create-bot": "./src/main.js"
|
||||||
|
|
1
packages/create-bot/scripts/.gitignore
vendored
Normal file
1
packages/create-bot/scripts/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import-map.json
|
11
packages/create-bot/scripts/generate-import-map.js
Normal file
11
packages/create-bot/scripts/generate-import-map.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import * as fs from 'fs'
|
||||||
|
|
||||||
|
const packageJson = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url)))
|
||||||
|
|
||||||
|
const importMap = {}
|
||||||
|
|
||||||
|
for (const [name, version] of Object.entries(packageJson.dependencies)) {
|
||||||
|
importMap[name] = `npm:${name}@${version}`
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(new URL('import-map.json', import.meta.url), JSON.stringify({ imports: importMap }, null, 2))
|
|
@ -1,6 +1,7 @@
|
||||||
import { promises as fs } from 'fs'
|
import { promises as fs } from 'node:fs'
|
||||||
import { homedir } from 'os'
|
import { homedir } from 'node:os'
|
||||||
import * as path from 'path'
|
import * as path from 'node:path'
|
||||||
|
import process from 'node:process'
|
||||||
|
|
||||||
export interface UserConfigPersisted {
|
export interface UserConfigPersisted {
|
||||||
apiId: number
|
apiId: number
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
|
import { join } from 'node:path'
|
||||||
|
|
||||||
import { UserConfig } from './cli.js'
|
import { UserConfig } from './cli.js'
|
||||||
import { MtcuteFeature } from './features/types.js'
|
import { MtcuteFeature } from './features/types.js'
|
||||||
|
import { fetchAllLatestVersionsJsr } from './jsr.js'
|
||||||
import { getInstallCommand, PackageManager } from './package-manager.js'
|
import { getInstallCommand, PackageManager } from './package-manager.js'
|
||||||
import { exec } from './utils.js'
|
import { exec } from './utils.js'
|
||||||
|
|
||||||
|
export interface DependenciesList {
|
||||||
|
dependencies: string[]
|
||||||
|
devDepdenencies: string[]
|
||||||
|
}
|
||||||
|
|
||||||
export function buildDependenciesList(config: UserConfig) {
|
export function buildDependenciesList(config: UserConfig) {
|
||||||
const dependencies = []
|
const dependencies = []
|
||||||
const devDepdenencies = ['dotenv-cli']
|
const devDepdenencies = []
|
||||||
|
|
||||||
if (config.packageManager === PackageManager.Bun) {
|
if (config.packageManager === PackageManager.Bun) {
|
||||||
dependencies.push('@mtcute/bun')
|
dependencies.push('@mtcute/bun')
|
||||||
|
} else if (config.packageManager === PackageManager.Deno) {
|
||||||
|
dependencies.push('@std/dotenv', '@mtcute/deno')
|
||||||
} else {
|
} else {
|
||||||
dependencies.push('@mtcute/node')
|
// node
|
||||||
|
dependencies.push('dotenv-cli', '@mtcute/node')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.features.includes(MtcuteFeature.Dispatcher)) {
|
if (config.features.includes(MtcuteFeature.Dispatcher)) {
|
||||||
|
@ -25,29 +36,19 @@ export function buildDependenciesList(config: UserConfig) {
|
||||||
dependencies.push('@mtcute/crypto-node')
|
dependencies.push('@mtcute/crypto-node')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.features.includes(MtcuteFeature.TypeScript)) {
|
if (config.features.includes(MtcuteFeature.TypeScript) && config.packageManager !== PackageManager.Deno) {
|
||||||
devDepdenencies.push('typescript', '@types/node')
|
devDepdenencies.push('typescript', '@types/node')
|
||||||
|
|
||||||
|
if (config.packageManager === PackageManager.Bun) {
|
||||||
|
devDepdenencies.push('@types/bun')
|
||||||
|
} else {
|
||||||
|
// node can't handle typescript natively
|
||||||
|
devDepdenencies.push('tsx')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.features.includes(MtcuteFeature.Linters)) {
|
if (config.features.includes(MtcuteFeature.Linters)) {
|
||||||
devDepdenencies.push(
|
devDepdenencies.push('@antfu/eslint-config')
|
||||||
'husky',
|
|
||||||
'lint-staged',
|
|
||||||
'eslint',
|
|
||||||
'eslint-config-prettier',
|
|
||||||
'eslint-plugin-ascii',
|
|
||||||
'eslint-plugin-import',
|
|
||||||
'eslint-plugin-simple-import-sort',
|
|
||||||
'prettier',
|
|
||||||
)
|
|
||||||
|
|
||||||
if (config.features.includes(MtcuteFeature.TypeScript)) {
|
|
||||||
devDepdenencies.push(
|
|
||||||
'eslint-import-resolver-typescript',
|
|
||||||
'@typescript-eslint/eslint-plugin',
|
|
||||||
'@typescript-eslint/parser',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -59,6 +60,35 @@ export function buildDependenciesList(config: UserConfig) {
|
||||||
export async function installDependencies(cwd: string, config: UserConfig) {
|
export async function installDependencies(cwd: string, config: UserConfig) {
|
||||||
const { dependencies, devDepdenencies } = buildDependenciesList(config)
|
const { dependencies, devDepdenencies } = buildDependenciesList(config)
|
||||||
|
|
||||||
|
if (config.packageManager === PackageManager.Deno) {
|
||||||
|
// deno doesn't have a package manager per se, but we can generate an import map
|
||||||
|
// to basically achieve the same thing
|
||||||
|
//
|
||||||
|
// since we don't have a package manager, we have to resolve "latest" versions ourselves :c
|
||||||
|
// additionally, there's no notion of "dev" dependencies is deno. though fairly enough,
|
||||||
|
// there should be no dev deps in our deno template (but let's just keep it for consistency)
|
||||||
|
|
||||||
|
const allDeps = [...dependencies, ...devDepdenencies]
|
||||||
|
const versions = await fetchAllLatestVersionsJsr(allDeps)
|
||||||
|
|
||||||
|
const denoJson = {
|
||||||
|
imports: {} as Record<string, string>,
|
||||||
|
tasks: {
|
||||||
|
start: `deno run -A --unstable-ffi ./src/main.${
|
||||||
|
config.features.includes(MtcuteFeature.TypeScript) ? 'ts' : 'js'
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const dep of allDeps) {
|
||||||
|
denoJson.imports[dep] = `jsr:${dep}@^${versions.get(dep)!}`
|
||||||
|
}
|
||||||
|
|
||||||
|
await Deno.writeTextFile(join(cwd, 'deno.json'), JSON.stringify(denoJson, null, 4))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await exec(cwd, ...getInstallCommand({ mgr: config.packageManager, packages: dependencies }))
|
await exec(cwd, ...getInstallCommand({ mgr: config.packageManager, packages: dependencies }))
|
||||||
await exec(cwd, ...getInstallCommand({ mgr: config.packageManager, packages: devDepdenencies, dev: true }))
|
await exec(cwd, ...getInstallCommand({ mgr: config.packageManager, packages: devDepdenencies, dev: true }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,23 @@ export function getFeatureChoices(packageMananger: PackageManager): CheckboxChoi
|
||||||
checked: true,
|
checked: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: ' 🥰 Setup Prettier & ESLint',
|
name: ' 📦 Initialize git repository',
|
||||||
short: 'Linters',
|
short: 'Git',
|
||||||
value: MtcuteFeature.Linters,
|
value: MtcuteFeature.Git,
|
||||||
checked: true,
|
checked: true,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
if (packageMananger !== PackageManager.Bun) {
|
if (packageMananger !== PackageManager.Deno) {
|
||||||
|
arr.unshift({
|
||||||
|
name: ' 🥰 Setup ESLint with @antfu/eslint-config',
|
||||||
|
short: 'Linters',
|
||||||
|
value: MtcuteFeature.Linters,
|
||||||
|
checked: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packageMananger !== PackageManager.Bun && packageMananger !== PackageManager.Deno) {
|
||||||
arr.unshift({
|
arr.unshift({
|
||||||
name: ' 🚀 Native addon (better performance)',
|
name: ' 🚀 Native addon (better performance)',
|
||||||
short: 'Native addon',
|
short: 'Native addon',
|
||||||
|
|
|
@ -5,4 +5,5 @@ export enum MtcuteFeature {
|
||||||
Docker = 'docker',
|
Docker = 'docker',
|
||||||
TypeScript = 'typescript',
|
TypeScript = 'typescript',
|
||||||
Linters = 'linters',
|
Linters = 'linters',
|
||||||
|
Git = 'git',
|
||||||
}
|
}
|
||||||
|
|
25
packages/create-bot/src/jsr.ts
Normal file
25
packages/create-bot/src/jsr.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
export async function fetchLatestVersionJsr(pkg: string): Promise<string> {
|
||||||
|
const res = await fetch(`https://jsr.io/${pkg}/meta.json`)
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`Failed to fetch ${pkg} metadata: ${await res.text()}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const meta = (await res.json()) as {
|
||||||
|
latest: string
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta.latest
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchAllLatestVersionsJsr(pkgs: string[]): Promise<Map<string, string>> {
|
||||||
|
const res = new Map<string, string>()
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
pkgs.map(async (pkg) => {
|
||||||
|
res.set(pkg, await fetchLatestVersionJsr(pkg))
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
import * as colors from 'colorette'
|
import * as colors from 'colorette'
|
||||||
import { dirname, join } from 'node:path'
|
import { basename, dirname, join } from 'node:path'
|
||||||
|
import process from 'node:process'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
import { askForConfig } from './cli.js'
|
import { askForConfig } from './cli.js'
|
||||||
|
@ -23,9 +24,18 @@ if (packageManager === PackageManager.Bun) {
|
||||||
console.log(`${colors.red('‼️ Warning:')} ${colors.yellow('Bun')} support is ${colors.bold('experimental')}`)
|
console.log(`${colors.red('‼️ Warning:')} ${colors.yellow('Bun')} support is ${colors.bold('experimental')}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packageManager === PackageManager.Deno) {
|
||||||
|
console.log(`${colors.red('‼️ Warning:')} ${colors.yellow('Deno')} support is ${colors.bold('experimental')}`)
|
||||||
|
}
|
||||||
|
|
||||||
const config = await askForConfig(packageManager)
|
const config = await askForConfig(packageManager)
|
||||||
config.name = projectName
|
config.name = basename(projectName)
|
||||||
const outDir = process.env.TARGET_DIR || join(process.cwd(), projectName)
|
let outDir = process.env.TARGET_DIR || projectName
|
||||||
|
|
||||||
|
if (!outDir.match(/^([A-Za-z]:)?[/\\]/)) {
|
||||||
|
// assume it's a relative path
|
||||||
|
outDir = join(process.cwd(), outDir)
|
||||||
|
}
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
|
|
||||||
|
@ -33,20 +43,25 @@ await runTemplater(join(__dirname, '../template'), outDir, config)
|
||||||
|
|
||||||
await installDependencies(outDir, config)
|
await installDependencies(outDir, config)
|
||||||
|
|
||||||
await exec(outDir, 'git', 'init')
|
|
||||||
|
|
||||||
if (config.features.includes(MtcuteFeature.Linters)) {
|
if (config.features.includes(MtcuteFeature.Linters)) {
|
||||||
if (process.platform === 'win32') {
|
await exec(outDir, ...getExecCommand(config.packageManager, 'eslint', '--fix', '.'))
|
||||||
// windows doesn't track executable bit, but git does
|
}
|
||||||
await exec(outDir, 'git', 'update-index', '--chmod=+x', '.husky/pre-commit')
|
|
||||||
} else {
|
|
||||||
await exec(outDir, 'chmod', '+x', '.husky/pre-commit')
|
|
||||||
}
|
|
||||||
|
|
||||||
await exec(outDir, ...getExecCommand(config.packageManager, 'husky'))
|
if (config.features.includes(MtcuteFeature.Git)) {
|
||||||
|
await exec(outDir, 'git', 'init', '.', '--initial-branch', 'main')
|
||||||
|
await exec(outDir, 'git', 'add', '.')
|
||||||
|
await exec(outDir, 'git', 'commit', '-m', 'Initial commit')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`✅ Scaffolded new project at ${colors.blue(outDir)}`)
|
console.log(`✅ Scaffolded new project at ${colors.blue(outDir)}`)
|
||||||
console.log('🚀 Run it with:')
|
console.log('🚀 Run it with:')
|
||||||
console.log(` ${colors.blue('$')} cd ${projectName}`)
|
console.log(` ${colors.blue('$')} cd ${projectName}`)
|
||||||
console.log(` ${colors.blue('$')} ${config.packageManager} start`)
|
|
||||||
|
if (config.packageManager === PackageManager.Deno) {
|
||||||
|
console.log(` ${colors.blue('$')} deno task start`)
|
||||||
|
// for whatever reason, deno keeps hanging after the we finish
|
||||||
|
// and doesn't even handle SIGINT. just exit lol
|
||||||
|
process.exit(0)
|
||||||
|
} else {
|
||||||
|
console.log(` ${colors.blue('$')} ${config.packageManager} start`)
|
||||||
|
}
|
||||||
|
|
|
@ -1,20 +1,48 @@
|
||||||
|
import * as colors from 'colorette'
|
||||||
|
import process from 'node:process'
|
||||||
|
|
||||||
|
export function getPackageManagerVersion(): [string, string] | null {
|
||||||
|
if (typeof Deno !== 'undefined') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const userAgent = process.env.npm_config_user_agent
|
||||||
|
|
||||||
|
if (!userAgent) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const software = userAgent.split(' ')[0]
|
||||||
|
const manager = software.split('/')[0]
|
||||||
|
const version = software.split('/')[1]
|
||||||
|
|
||||||
|
if (!version.match(/^\d+\.\d+\.\d+$/)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return [manager, version]
|
||||||
|
}
|
||||||
|
|
||||||
export enum PackageManager {
|
export enum PackageManager {
|
||||||
Npm = 'npm',
|
Npm = 'npm',
|
||||||
Yarn = 'yarn',
|
Yarn = 'yarn',
|
||||||
Pnpm = 'pnpm',
|
Pnpm = 'pnpm',
|
||||||
Bun = 'bun',
|
Bun = 'bun',
|
||||||
|
Deno = 'deno',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPackageManager(): PackageManager {
|
export function getPackageManager(): PackageManager {
|
||||||
const userAgent = process.env.npm_config_user_agent
|
const parsed = getPackageManagerVersion()
|
||||||
|
|
||||||
|
if (!parsed) {
|
||||||
|
if (typeof Deno !== 'undefined') return PackageManager.Deno
|
||||||
|
|
||||||
|
console.warn(colors.yellow('[warning] could not detect package manager, falling back to pnpm'))
|
||||||
|
|
||||||
if (!userAgent) {
|
|
||||||
return PackageManager.Pnpm // fall back to the most based one
|
return PackageManager.Pnpm // fall back to the most based one
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = userAgent.split('/')[0]
|
switch (parsed[0]) {
|
||||||
|
|
||||||
switch (name) {
|
|
||||||
case 'pnpm':
|
case 'pnpm':
|
||||||
return PackageManager.Pnpm
|
return PackageManager.Pnpm
|
||||||
case 'yarn':
|
case 'yarn':
|
||||||
|
@ -24,7 +52,7 @@ export function getPackageManager(): PackageManager {
|
||||||
case 'bun':
|
case 'bun':
|
||||||
return PackageManager.Bun
|
return PackageManager.Bun
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported package manager: ${name}`)
|
throw new Error(`Unsupported package manager: ${parsed[0]}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,5 +94,20 @@ export function getExecCommand(mgr: PackageManager, ...cmd: string[]) {
|
||||||
return ['pnpm', 'exec', ...cmd]
|
return ['pnpm', 'exec', ...cmd]
|
||||||
case PackageManager.Bun:
|
case PackageManager.Bun:
|
||||||
return ['bun', 'run', ...cmd]
|
return ['bun', 'run', ...cmd]
|
||||||
|
case PackageManager.Deno:
|
||||||
|
throw new Error('Deno does not support exec commands')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function packageManagerToRuntime(mgr: PackageManager) {
|
||||||
|
switch (mgr) {
|
||||||
|
case PackageManager.Npm:
|
||||||
|
case PackageManager.Yarn:
|
||||||
|
case PackageManager.Pnpm:
|
||||||
|
return 'node'
|
||||||
|
case PackageManager.Bun:
|
||||||
|
return 'bun'
|
||||||
|
case PackageManager.Deno:
|
||||||
|
return 'deno'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import * as path from 'node:path'
|
||||||
|
|
||||||
import type { UserConfig } from './cli.js'
|
import type { UserConfig } from './cli.js'
|
||||||
import { MtcuteFeature } from './features/types.js'
|
import { MtcuteFeature } from './features/types.js'
|
||||||
|
import { getPackageManagerVersion, packageManagerToRuntime } from './package-manager.js'
|
||||||
|
|
||||||
const templater = Handlebars.create()
|
const templater = Handlebars.create()
|
||||||
|
|
||||||
|
@ -37,6 +38,8 @@ export async function runTemplaterForFile(file: string, config: UserConfig): Pro
|
||||||
|
|
||||||
const result = execute({
|
const result = execute({
|
||||||
...config,
|
...config,
|
||||||
|
runtime: packageManagerToRuntime(config.packageManager),
|
||||||
|
packageManagerVersion: getPackageManagerVersion()?.join('@'),
|
||||||
features: config.features.reduce<Record<MtcuteFeature, boolean>>(
|
features: config.features.reduce<Record<MtcuteFeature, boolean>>(
|
||||||
(acc, f) => {
|
(acc, f) => {
|
||||||
acc[f] = true
|
acc[f] = true
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { spawn } from 'cross-spawn'
|
||||||
|
|
||||||
export function exec(cwd: string, ...cmd: string[]) {
|
export function exec(cwd: string, ...cmd: string[]) {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
console.log(`${colors.blue('$')} ${cmd.join(' ')}`)
|
console.log(`${colors.blue('$')} ${cmd.map((it) => (it.includes(' ') ? JSON.stringify(it) : it)).join(' ')}`)
|
||||||
|
|
||||||
const proc = spawn(cmd[0], cmd.slice(1), {
|
const proc = spawn(cmd[0], cmd.slice(1), {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
{{emit_if features.linters}}
|
|
||||||
node_modules/
|
|
||||||
.husky/
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
dist/
|
|
||||||
|
|
||||||
*.json
|
|
|
@ -1,210 +0,0 @@
|
||||||
{{emit_if features.linters}}
|
|
||||||
module.exports = {
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
es2021: true,
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
extends: ['eslint:recommended', 'plugin:import/recommended', 'prettier'],
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 'latest',
|
|
||||||
sourceType: 'module',
|
|
||||||
},
|
|
||||||
plugins: ['ascii', 'import', 'simple-import-sort'],
|
|
||||||
reportUnusedDisableDirectives: true,
|
|
||||||
rules: {
|
|
||||||
// see https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/style.js#L122
|
|
||||||
indent: [
|
|
||||||
2,
|
|
||||||
4,
|
|
||||||
{
|
|
||||||
SwitchCase: 1,
|
|
||||||
VariableDeclarator: 1,
|
|
||||||
outerIIFEBody: 1,
|
|
||||||
// MemberExpression: null,
|
|
||||||
FunctionDeclaration: {
|
|
||||||
parameters: 1,
|
|
||||||
body: 1,
|
|
||||||
},
|
|
||||||
FunctionExpression: {
|
|
||||||
parameters: 1,
|
|
||||||
body: 1,
|
|
||||||
},
|
|
||||||
CallExpression: {
|
|
||||||
arguments: 1,
|
|
||||||
},
|
|
||||||
ArrayExpression: 1,
|
|
||||||
ObjectExpression: 1,
|
|
||||||
ImportDeclaration: 1,
|
|
||||||
flatTernaryExpressions: false,
|
|
||||||
// list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js
|
|
||||||
ignoredNodes: [
|
|
||||||
'JSXElement',
|
|
||||||
'JSXElement > *',
|
|
||||||
'JSXAttribute',
|
|
||||||
'JSXIdentifier',
|
|
||||||
'JSXNamespacedName',
|
|
||||||
'JSXMemberExpression',
|
|
||||||
'JSXSpreadAttribute',
|
|
||||||
'JSXExpressionContainer',
|
|
||||||
'JSXOpeningElement',
|
|
||||||
'JSXClosingElement',
|
|
||||||
'JSXText',
|
|
||||||
'JSXEmptyExpression',
|
|
||||||
'JSXSpreadChild',
|
|
||||||
],
|
|
||||||
ignoreComments: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
semi: [2, 'never', { beforeStatementContinuationChars: 'never' }],
|
|
||||||
'semi-spacing': [2, { before: false, after: true }],
|
|
||||||
'wrap-iife': [2, 'inside'],
|
|
||||||
'no-caller': 2,
|
|
||||||
'no-cond-assign': [2, 'except-parens'],
|
|
||||||
'no-constant-condition': 0,
|
|
||||||
'no-debugger': 2,
|
|
||||||
'no-dupe-args': 2,
|
|
||||||
'no-dupe-keys': 2,
|
|
||||||
'no-duplicate-case': 2,
|
|
||||||
'no-empty': [2, { allowEmptyCatch: true }],
|
|
||||||
'no-empty-function': 'off',
|
|
||||||
'no-extra-boolean-cast': 2,
|
|
||||||
'no-extra-semi': 2,
|
|
||||||
'no-func-assign': 2,
|
|
||||||
'no-new': 2,
|
|
||||||
'no-sparse-arrays': 2,
|
|
||||||
'no-unexpected-multiline': 2,
|
|
||||||
'no-unreachable': 2,
|
|
||||||
|
|
||||||
'max-params': [1, 5],
|
|
||||||
'max-depth': [1, 4],
|
|
||||||
'no-eq-null': 0,
|
|
||||||
'no-unused-expressions': 0,
|
|
||||||
'dot-notation': 2,
|
|
||||||
'use-isnan': 2,
|
|
||||||
|
|
||||||
// Best practices
|
|
||||||
'block-scoped-var': 2,
|
|
||||||
complexity: [0, 11],
|
|
||||||
curly: [2, 'multi-line'],
|
|
||||||
eqeqeq: [2, 'always', { null: 'ignore' }],
|
|
||||||
'no-else-return': 2,
|
|
||||||
'no-extra-bind': 2,
|
|
||||||
'no-implicit-coercion': 2,
|
|
||||||
'no-return-assign': 0,
|
|
||||||
'no-sequences': 2,
|
|
||||||
yoda: 2,
|
|
||||||
|
|
||||||
// Variables
|
|
||||||
'no-restricted-globals': ['error'],
|
|
||||||
'no-var': 1,
|
|
||||||
|
|
||||||
// Codestyle
|
|
||||||
'arrow-parens': [2, 'always'],
|
|
||||||
'array-bracket-spacing': [2, 'never'],
|
|
||||||
'brace-style': [2, '1tbs', { allowSingleLine: true }],
|
|
||||||
camelcase: [2, { properties: 'never' }],
|
|
||||||
'comma-dangle': ['warn', 'always-multiline'],
|
|
||||||
'comma-spacing': [2, { before: false, after: true }],
|
|
||||||
'eol-last': 2,
|
|
||||||
'func-call-spacing': [2, 'never'],
|
|
||||||
'block-spacing': 2,
|
|
||||||
'keyword-spacing': [2, { before: true, after: true }],
|
|
||||||
'max-len': [
|
|
||||||
2,
|
|
||||||
{
|
|
||||||
code: 120,
|
|
||||||
ignoreUrls: true,
|
|
||||||
ignoreComments: false,
|
|
||||||
ignoreRegExpLiterals: true,
|
|
||||||
ignoreStrings: true,
|
|
||||||
ignoreTemplateLiterals: true,
|
|
||||||
ignorePattern: 'require',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'no-lonely-if': 2,
|
|
||||||
'no-mixed-spaces-and-tabs': 2,
|
|
||||||
'no-multi-spaces': 2,
|
|
||||||
'no-multiple-empty-lines': [2, { max: 1, maxBOF: 0, maxEOF: 0 }],
|
|
||||||
'no-trailing-spaces': 2,
|
|
||||||
'ascii/valid-name': 2,
|
|
||||||
'no-unneeded-ternary': 2,
|
|
||||||
'no-nested-ternary': 2,
|
|
||||||
'object-curly-spacing': [2, 'always'],
|
|
||||||
'one-var-declaration-per-line': [2, 'initializations'],
|
|
||||||
'one-var': [2, { let: 'never', const: 'never' }],
|
|
||||||
'operator-linebreak': [2, 'after'],
|
|
||||||
'padded-blocks': [2, 'never'],
|
|
||||||
'quote-props': [2, 'as-needed', { numbers: true }],
|
|
||||||
quotes: [2, 'single', { avoidEscape: true }],
|
|
||||||
'space-before-blocks': [2, 'always'],
|
|
||||||
'space-before-function-paren': [
|
|
||||||
2,
|
|
||||||
{
|
|
||||||
named: 'never',
|
|
||||||
anonymous: 'always',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'space-in-parens': 2,
|
|
||||||
'key-spacing': [2, { beforeColon: false, afterColon: true, mode: 'strict' }],
|
|
||||||
'space-infix-ops': 2,
|
|
||||||
'padding-line-between-statements': [
|
|
||||||
'error',
|
|
||||||
{ blankLine: 'always', prev: '*', next: 'return' },
|
|
||||||
{ blankLine: 'always', prev: '*', next: 'block-like' },
|
|
||||||
{ blankLine: 'any', prev: 'block-like', next: 'block-like' },
|
|
||||||
{ blankLine: 'any', prev: 'case', next: 'case' },
|
|
||||||
],
|
|
||||||
|
|
||||||
'simple-import-sort/imports': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
groups: [['^@mtcute'], ['^[a-z]'], ['^#']],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'simple-import-sort/exports': 'error',
|
|
||||||
'import/no-relative-packages': 'error',
|
|
||||||
'import/no-mutable-exports': 'error',
|
|
||||||
'import/no-default-export': 'error',
|
|
||||||
// https://github.com/import-js/eslint-plugin-import/issues/2903
|
|
||||||
'import/named': 'off',
|
|
||||||
},
|
|
||||||
{{#if features.typescript}}
|
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: ['**/*.ts'],
|
|
||||||
env: { browser: true, es6: true, node: true },
|
|
||||||
extends: ['plugin:@typescript-eslint/recommended'],
|
|
||||||
globals: { Atomics: 'readonly', SharedArrayBuffer: 'readonly' },
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
plugins: ['@typescript-eslint'],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/consistent-type-assertions': 2,
|
|
||||||
'@typescript-eslint/no-explicit-any': 2,
|
|
||||||
'@typescript-eslint/no-unused-vars': [
|
|
||||||
2,
|
|
||||||
{
|
|
||||||
args: 'after-used',
|
|
||||||
argsIgnorePattern: '^_',
|
|
||||||
ignoreRestSiblings: true,
|
|
||||||
vars: 'all',
|
|
||||||
varsIgnorePattern: '^_',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
'import/resolver': {
|
|
||||||
node: true,
|
|
||||||
typescript: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{{/if}}
|
|
||||||
settings: {
|
|
||||||
'import/resolver': {
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
{{#if (ne runtime "deno")}}
|
||||||
node_modules/
|
node_modules/
|
||||||
|
{{/if}}
|
||||||
dist/
|
dist/
|
||||||
private/
|
|
||||||
.nyc_output/
|
.nyc_output/
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
.idea
|
.idea
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{{emit_if features.linters}}
|
|
||||||
#!/usr/bin/env sh
|
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
pnpm exec lint-staged
|
|
|
@ -1,7 +0,0 @@
|
||||||
{{emit_if features.linters}}
|
|
||||||
module.exports = {
|
|
||||||
'*.{js,jsx,ts,tsx}': [
|
|
||||||
`prettier --write`,
|
|
||||||
`eslint --fix`,
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{{emit_if features.linters}}
|
|
||||||
{
|
|
||||||
"arrowParens": "always",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"embeddedLanguageFormatting": "auto",
|
|
||||||
"htmlWhitespaceSensitivity": "css",
|
|
||||||
"insertPragma": false,
|
|
||||||
"jsxBracketSameLine": false,
|
|
||||||
"jsxSingleQuote": false,
|
|
||||||
"printWidth": 80,
|
|
||||||
"proseWrap": "preserve",
|
|
||||||
"quoteProps": "as-needed",
|
|
||||||
"requirePragma": false,
|
|
||||||
"semi": false,
|
|
||||||
"singleQuote": true,
|
|
||||||
"tabWidth": 4,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"useTabs": false,
|
|
||||||
"vueIndentScriptAndStyle": false
|
|
||||||
}
|
|
|
@ -12,4 +12,4 @@ RUN pnpm install --frozen-lockfile
|
||||||
COPY src /app/src
|
COPY src /app/src
|
||||||
RUN pnpm run build
|
RUN pnpm run build
|
||||||
|
|
||||||
CMD [ "node", "/app/dist/index.js" ]
|
CMD [ "node", "/app/dist/main.js" ]
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
# {{name}}
|
# {{name}}
|
||||||
|
|
||||||
MTCute powered Telegram bot
|
mtcute powered Telegram bot
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm install --frozen-lockfile
|
{{#if (ne runtime "deno")}}
|
||||||
|
{{#if (eq packageManager "npm")}}
|
||||||
|
npm ci
|
||||||
|
{{else}}
|
||||||
|
{{packageManager}} install --frozen-lockfile
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# edit .env
|
# edit .env
|
||||||
pnpm start
|
{{#if (eq runtime "deno")}}
|
||||||
|
deno task start
|
||||||
|
{{else}}
|
||||||
|
{{packageManager}} start
|
||||||
|
{{/if}}
|
||||||
```
|
```
|
||||||
|
|
||||||
*generated with @mtcute/create-bot*
|
*generated with @mtcute/create-bot*
|
21
packages/create-bot/template/eslint.config.js.hbs
Normal file
21
packages/create-bot/template/eslint.config.js.hbs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{{emit_if features.linters}}
|
||||||
|
import antfu from '@antfu/eslint-config'
|
||||||
|
|
||||||
|
export default antfu({
|
||||||
|
stylistic: {
|
||||||
|
indent: 4,
|
||||||
|
},
|
||||||
|
{{#if features.typescript}}
|
||||||
|
typescript: true,
|
||||||
|
{{/if}}
|
||||||
|
yaml: false,
|
||||||
|
rules: {
|
||||||
|
'curly': ['error', 'multi-line'],
|
||||||
|
'style/brace-style': ['error', '1tbs', { allowSingleLine: true }],
|
||||||
|
'style/quotes': ['error', 'single', { avoidEscape: true }],
|
||||||
|
'import/order': ['error', { 'newlines-between': 'always' }],
|
||||||
|
'antfu/if-newline': 'off',
|
||||||
|
'style/max-statements-per-line': ['error', { max: 2 }],
|
||||||
|
'no-console': 'off',
|
||||||
|
},
|
||||||
|
})
|
|
@ -1,27 +1,31 @@
|
||||||
|
{{emit_if (ne runtime "deno")}}
|
||||||
{
|
{
|
||||||
"name": "{{ name }}",
|
"name": "{{ name }}",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
{{#if packageManagerVersion}}
|
||||||
|
"packageManager": "{{packageManagerVersion}}",
|
||||||
|
{{/if}}
|
||||||
"scripts": {
|
"scripts": {
|
||||||
{{#if features.linters}}
|
{{#if features.linters}}
|
||||||
"prepare": "husky || true",
|
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint --fix .",
|
"lint:fix": "eslint --fix .",
|
||||||
"format": "prettier --write \"src/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\"",
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq packageManager "bun")}}
|
{{#if (eq runtime "bun")}}
|
||||||
{{#if features.typescript}}
|
{{#if features.typescript}}
|
||||||
"start": "bun ./src/index.ts"
|
"start": "bun ./src/main.ts",
|
||||||
|
"build": "tsc && bun build src/main.ts --target=bun --outdir=dist"
|
||||||
{{else}}
|
{{else}}
|
||||||
"start": "bun ./src/index.js"
|
"start": "bun ./src/main.js"
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if features.typescript}}
|
{{#if features.typescript}}
|
||||||
"start": "tsc && dotenv node ./dist/index.js",
|
"start": "dotenv tsx ./src/main.ts",
|
||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
{{else}}
|
{{else}}
|
||||||
"start": "dotenv node ./src/index.js"
|
"start": "dotenv node ./src/main.js"
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
}
|
}
|
||||||
|
|
24
packages/create-bot/template/src/env.js.hbs
Normal file
24
packages/create-bot/template/src/env.js.hbs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{{emit_if (not features.typescript)}}
|
||||||
|
{{#if (eq runtime "deno")}}
|
||||||
|
import '@std/dotenv/load'
|
||||||
|
|
||||||
|
const API_ID = Number.parseInt(Deno.env.get('API_ID'))
|
||||||
|
const API_HASH = Deno.env.get('API_HASH')
|
||||||
|
{{#if botToken}}
|
||||||
|
const BOT_TOKEN = Deno.env.get('BOT_TOKEN')
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
import process from 'node:process'
|
||||||
|
|
||||||
|
const API_ID = Number.parseInt(process.env.API_ID)
|
||||||
|
const API_HASH = process.env.API_HASH
|
||||||
|
{{#if botToken}}
|
||||||
|
const BOT_TOKEN = process.env.BOT_TOKEN
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
if (Number.isNaN(API_ID) || !API_HASH) {
|
||||||
|
throw new Error('API_ID or API_HASH not set!')
|
||||||
|
}
|
||||||
|
|
||||||
|
export { API_HASH, API_ID{{#if botToken}}, BOT_TOKEN{{/if}} }
|
|
@ -1,11 +1,23 @@
|
||||||
{{emit_if features.typescript}}
|
{{emit_if features.typescript}}
|
||||||
const API_ID = parseInt(process.env.API_ID!)
|
{{#if (eq runtime "deno")}}
|
||||||
|
import '@std/dotenv/load'
|
||||||
|
|
||||||
|
const API_ID = Number.parseInt(Deno.env.get('API_ID')!)
|
||||||
|
const API_HASH = Deno.env.get('API_HASH')!
|
||||||
|
{{#if botToken}}
|
||||||
|
const BOT_TOKEN = Deno.env.get('BOT_TOKEN')!
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
import process from 'node:process'
|
||||||
|
|
||||||
|
const API_ID = Number.parseInt(process.env.API_ID!)
|
||||||
const API_HASH = process.env.API_HASH!
|
const API_HASH = process.env.API_HASH!
|
||||||
{{#if botToken}}
|
{{#if botToken}}
|
||||||
const BOT_TOKEN = process.env.BOT_TOKEN!
|
const BOT_TOKEN = process.env.BOT_TOKEN!
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
if (isNaN(API_ID) || !API_HASH) {
|
if (Number.isNaN(API_ID) || !API_HASH) {
|
||||||
throw new Error('API_ID or API_HASH not set!')
|
throw new Error('API_ID or API_HASH not set!')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
{{emit_if (and (not features.typescript) features.i18n)}}
|
{{emit_if (and (not features.typescript) features.i18n)}}
|
||||||
|
|
||||||
import { createMtcuteI18n } from '@mtcute/i18n'
|
import { createMtcuteI18n } from '@mtcute/i18n'
|
||||||
|
|
||||||
|
{{#if (eq runtime "node")}}
|
||||||
import { en } from './en.js'
|
import { en } from './en.js'
|
||||||
import { ru } from './ru.js'
|
import { ru } from './ru.js'
|
||||||
|
{{else}}
|
||||||
|
import { en } from './en.ts'
|
||||||
|
import { ru } from './ru.ts'
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
export const tr = createMtcuteI18n({
|
export const tr = createMtcuteI18n({
|
||||||
primaryLanguage: {
|
primaryLanguage: {
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
{{#if features.dispatcher}}
|
{{#if features.dispatcher}}
|
||||||
import { Dispatcher, filters } from '@mtcute/dispatcher'
|
import { Dispatcher, filters } from '@mtcute/dispatcher'
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq packageManager "bun")}}
|
{{#if (eq runtime "bun")}}
|
||||||
import { TelegramClient } from '@mtcute/bun'
|
import { TelegramClient } from '@mtcute/bun'
|
||||||
|
{{else if (eq runtime "deno")}}
|
||||||
|
import { TelegramClient } from '@mtcute/deno'
|
||||||
{{else}}
|
{{else}}
|
||||||
import { TelegramClient } from '@mtcute/node'
|
import { TelegramClient } from '@mtcute/node'
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -31,11 +33,9 @@ dp.onNewMessage(filters.start, async (msg) => {
|
||||||
})
|
})
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
tg.run(
|
{{#if botToken}}
|
||||||
{{#if botToken}}
|
const user = await tg.start({ botToken: env.BOT_TOKEN })
|
||||||
{ botToken: env.BOT_TOKEN },
|
{{else}}
|
||||||
{{/if}}
|
const user = await tg.start()
|
||||||
(user) => {
|
{{/if}}
|
||||||
console.log('Logged in as', user.username)
|
console.log('Logged in as', user.username)
|
||||||
},
|
|
||||||
)
|
|
|
@ -2,15 +2,25 @@
|
||||||
{{#if features.dispatcher}}
|
{{#if features.dispatcher}}
|
||||||
import { Dispatcher, filters } from '@mtcute/dispatcher'
|
import { Dispatcher, filters } from '@mtcute/dispatcher'
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq packageManager "bun")}}
|
{{#if (eq runtime "bun")}}
|
||||||
import { TelegramClient } from '@mtcute/bun'
|
import { TelegramClient } from '@mtcute/bun'
|
||||||
|
{{else if (eq runtime "deno")}}
|
||||||
|
import { TelegramClient } from '@mtcute/deno'
|
||||||
{{else}}
|
{{else}}
|
||||||
import { TelegramClient } from '@mtcute/node'
|
import { TelegramClient } from '@mtcute/node'
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if (eq runtime "node")}}
|
||||||
import * as env from './env.js'
|
import * as env from './env.js'
|
||||||
|
{{else}}
|
||||||
|
import * as env from './env.ts'
|
||||||
|
{{/if}}
|
||||||
{{#if features.i18n}}
|
{{#if features.i18n}}
|
||||||
|
{{#if (eq runtime "node")}}
|
||||||
import { tr } from './i18n/index.js'
|
import { tr } from './i18n/index.js'
|
||||||
|
{{else}}
|
||||||
|
import { tr } from './i18n/index.ts'
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
const tg = new TelegramClient({
|
const tg = new TelegramClient({
|
||||||
|
@ -31,11 +41,9 @@ dp.onNewMessage(filters.start, async (msg) => {
|
||||||
})
|
})
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
tg.run(
|
{{#if botToken}}
|
||||||
{{#if botToken}}
|
const user = await tg.start({ botToken: env.BOT_TOKEN })
|
||||||
{ botToken: env.BOT_TOKEN },
|
{{else}}
|
||||||
{{/if}}
|
const user = await tg.start()
|
||||||
(user) => {
|
{{/if}}
|
||||||
console.log('Logged in as', user.username)
|
console.log('Logged in as', user.username)
|
||||||
},
|
|
||||||
)
|
|
|
@ -1,28 +1,29 @@
|
||||||
{{emit_if features.typescript}}
|
{{emit_if (and features.typescript (ne runtime "deno"))}}
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
|
{{#if (eq runtime "bun")}}
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"noEmit": true,
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
{{else}}
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
"target": "es2020",
|
{{/if}}
|
||||||
|
"target": "es2022",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"inlineSources": true,
|
"inlineSources": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitAny": true,
|
|
||||||
"noImplicitThis": true,
|
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./src"
|
"./src"
|
||||||
],
|
],
|
||||||
"ts-node": {
|
|
||||||
"esm": true,
|
|
||||||
"experimentalSpecifierResolution": "node"
|
|
||||||
},
|
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"**/node_modules",
|
"**/node_modules",
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue