-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.ts
More file actions
143 lines (116 loc) · 5.33 KB
/
setup.ts
File metadata and controls
143 lines (116 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env bun
/**
* Interactive first-run setup for Tele-Bot.
*
* Checks if TELEGRAM_BOT_TOKEN and TELEGRAM_ALLOWED_USERS are set.
* If missing, prompts the user and writes them to .env automatically.
*/
import { existsSync, readFileSync, writeFileSync } from "fs";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";
import * as readline from "readline";
import { BOT_NAME } from "./src/branding";
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)));
const ENV_FILE = resolve(ROOT, ".env");
const ENV_EXAMPLE_FILE = resolve(ROOT, ".env.example");
// ── Helpers ────────────────────────────────────────────────────────────────
/** Read current .env content (or use example as base). */
function readEnvContent(): string {
if (existsSync(ENV_FILE)) {
return readFileSync(ENV_FILE, "utf-8");
}
if (existsSync(ENV_EXAMPLE_FILE)) {
return readFileSync(ENV_EXAMPLE_FILE, "utf-8");
}
return `# ${BOT_NAME} - Environment Configuration\n\n`;
}
/** Extract value for a key from .env content. */
function getEnvValue(content: string, key: string): string {
const match = content.match(new RegExp(`^${key}=(.*)$`, "m"));
return match ? (match[1] ?? "").trim() : "";
}
/** Set or add a key=value line in .env content. */
function setEnvValue(content: string, key: string, value: string): string {
const regex = new RegExp(`^#?\\s*${key}=.*$`, "m");
const line = `${key}=${value}`;
if (regex.test(content)) {
return content.replace(regex, line);
}
return content.trimEnd() + `\n${line}\n`;
}
/** Prompt user for input using readline (reliable for sequential prompts). */
function prompt(question: string): Promise<string> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true,
});
return new Promise((resolve) => {
rl.question(question, (answer) => {
rl.close();
resolve(answer.trim());
});
});
}
/** Validate Telegram bot token format. */
function isValidToken(token: string): boolean {
return /^\d+:[A-Za-z0-9_-]{35,}$/.test(token);
}
/** Validate numeric user ID. */
function isValidUserId(id: string): boolean {
return /^\d+$/.test(id.trim());
}
// ── Main ───────────────────────────────────────────────────────────────────
console.log(`\n🤖 \x1b[1m${BOT_NAME} Setup\x1b[0m`);
console.log("─".repeat(40));
let envContent = readEnvContent();
let changed = false;
// ── Token ──────────────────────────────────────────────────────────────────
let token = getEnvValue(envContent, "TELEGRAM_BOT_TOKEN");
// Treat placeholder value as missing
if (!token || token.startsWith("1234567890")) token = "";
if (!token) {
console.log("\n📌 \x1b[33mTELEGRAM_BOT_TOKEN\x1b[0m is not set.");
console.log(" Get your token from \x1b[36m@BotFather\x1b[0m on Telegram.");
console.log(" (Send /newbot to @BotFather and copy the token)\n");
while (true) {
token = await prompt(" Enter bot token: ");
if (isValidToken(token)) break;
console.log(" ❌ Invalid token format. Should look like: 123456789:ABCdef...");
}
envContent = setEnvValue(envContent, "TELEGRAM_BOT_TOKEN", token);
changed = true;
console.log(" ✅ Token saved.");
} else {
console.log(`\n✅ TELEGRAM_BOT_TOKEN: already set (${token.split(":")[0] ?? "???"}:***)`);
}
// ── Allowed Users ──────────────────────────────────────────────────────────
let allowedUsers = getEnvValue(envContent, "TELEGRAM_ALLOWED_USERS");
// Treat placeholder/empty as missing
if (!allowedUsers || allowedUsers === "123456789") allowedUsers = "";
if (!allowedUsers) {
console.log("\n📌 \x1b[33mTELEGRAM_ALLOWED_USERS\x1b[0m is not set.");
console.log(" This is YOUR Telegram user ID (a number, not a username).");
console.log(" To find it: message \x1b[36m@userinfobot\x1b[0m on Telegram and it will reply with your ID.\n");
while (true) {
allowedUsers = await prompt(" Enter your Telegram user ID: ");
// Support comma-separated multiple IDs
const ids = allowedUsers.split(",").map((s) => s.trim());
if (ids.every(isValidUserId)) break;
console.log(" ❌ Invalid format. Enter numeric ID(s), e.g.: 123456789");
}
envContent = setEnvValue(envContent, "TELEGRAM_ALLOWED_USERS", allowedUsers);
changed = true;
console.log(" ✅ User ID saved.");
} else {
console.log(`✅ TELEGRAM_ALLOWED_USERS: already set (${allowedUsers})`);
}
// ── Write .env ─────────────────────────────────────────────────────────────
if (changed) {
writeFileSync(ENV_FILE, envContent, "utf-8");
console.log(`\n💾 Configuration written to \x1b[32m.env\x1b[0m`);
} else {
console.log("\n✨ All required settings are already configured.");
}
console.log("\n" + "─".repeat(40));
console.log("🚀 Starting bot...\n");