@ayush24k/telezipper 1.4.0 → 1.5.1

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.
package/README.md CHANGED
@@ -44,106 +44,66 @@ Example:
44
44
  telezipper ./my-folder -o ./output
45
45
  ```
46
46
 
47
- ### With Password Protection
47
+ ### Chunking + Upload to Telegram (MTProto)
48
+ This tool now uses **MTProto** (the Telegram Client Protocol) to support **large file uploads (up to 2GB)** and faster speeds.
48
49
 
49
- ```bash
50
- telezipper <source> -p <password> -o <output-directory>
51
- ```
52
-
53
- Example:
54
- ```bash
55
- telezipper ./my-folder -p MySecurePassword123 -o ./output
56
- ```
57
-
58
- ### With Telegram Upload
50
+ To use it, you need a `TELEGRAM_API_ID` and `TELEGRAM_API_HASH`. You can get these from [my.telegram.org](https://my.telegram.org).
59
51
 
60
- You can provide Telegram credentials in two ways:
52
+ You can pass them as arguments or set them in a `.env` file.
61
53
 
62
- #### Option 1: Command-line arguments (Recommended for flexibility)
54
+ ### Usage Examples
63
55
 
56
+ #### 1. Basic Zip (No Password, No Telegram)
64
57
  ```bash
65
- telezipper <source> --telegram --bot-token YOUR_BOT_TOKEN --chat-id YOUR_CHAT_ID
58
+ telezipper ./my-folder
59
+ # Output: ./output/chunk_1.zip
66
60
  ```
67
61
 
68
- Example:
62
+ #### 2. Zip with Password
69
63
  ```bash
70
- telezipper ./my-folder --telegram --bot-token 123456:ABC-DEF1234ghIkl --chat-id 987654321
64
+ telezipper ./my-folder -p "secret123"
65
+ # Output: Encrypted zip files in ./output
71
66
  ```
72
67
 
73
- #### Option 2: Environment variables
74
-
75
- Create a `.env` file in the project directory or set environment variables:
68
+ #### 3. Zip + Upload to Telegram (Env Vars Set)
69
+ Assuming `.env` has credentials:
70
+ ```bash
71
+ telezipper ./my-folder --telegram
72
+ ```
76
73
 
74
+ #### 4. Zip + Upload to Telegram (CLI Args)
77
75
  ```bash
78
- TELEGRAM_BOT_TOKEN=your_bot_token_here
79
- TELEGRAM_CHAT_ID=your_chat_id_here
76
+ telezipper ./my-folder --telegram --api-id 12345 --api-hash abcdef123 --chat-id -100123456789
80
77
  ```
81
78
 
82
- Then run:
79
+ #### 5. Password Protected Upload
83
80
  ```bash
84
- telezipper ./my-folder --telegram
81
+ telezipper ./my-folder --telegram -p "mypassword"
85
82
  ```
86
83
 
84
+ ### Logging In
85
+ - **User Login**: The tool will ask for your phone number and login code interactively. This session is saved locally in `.telegram_session`.
86
+
87
87
  ## Options
88
88
 
89
89
  - `<source>` - File or folder to zip (required)
90
90
  - `-o, --output <dir>` - Output directory (default: "output")
91
91
  - `-p, --password <password>` - Password to protect zip files (optional)
92
92
  - `--telegram` - Upload zip files to Telegram
93
- - `--bot-token <token>` - Telegram bot token (required if using --telegram without env vars)
94
- - `--chat-id <id>` - Telegram chat ID (required if using --telegram without env vars)
93
+ - `--api-id <id>` - Telegram API ID (required for MTProto)
94
+ - `--api-hash <hash>` - Telegram API Hash (required for MTProto)
95
+ - `--chat-id <id>` - Chat ID to upload to (User ID or Channel/Group ID)
95
96
  - `-h, --help` - Display help
96
97
 
97
- ## Examples
98
-
99
- ### Zip a folder to the default output directory
100
- ```bash
101
- telezipper ./my-project
102
- ```
103
-
104
- ### Zip and specify custom output directory
105
- ```bash
106
- telezipper ./my-project -o ./backups
107
- ```
108
-
109
- ### Zip and upload to Telegram with inline credentials
110
- ```bash
111
- telezipper ./my-project --telegram --bot-token 123456:ABC-DEF --chat-id 987654321
112
- ```
113
-
114
- ### Zip and upload using environment variables
115
- ```bash
116
- # Set environment variables first
117
- export TELEGRAM_BOT_TOKEN=123456:ABC-DEF
118
- export TELEGRAM_CHAT_ID=987654321
119
-
120
- # Then run
121
- telezipper ./my-project --telegram
122
- ```
123
-
124
- ### Zip with password protection
125
- ```bash
126
- telezipper ./my-project -p MySecurePassword123
127
- ```
98
+ ## Features
128
99
 
129
- ### Zip with password and upload to Telegram
130
- ```bash
131
- telezipper ./my-project -p MySecurePassword123 --telegram --bot-token 123456:ABC-DEF --chat-id 987654321
132
- ```
100
+ - šŸš€ **MTProto Support**: Uploads files >50MB (tested up to 2GB).
101
+ - šŸ” **Encrypted Zips**: Optional AES-256 password protection.
102
+ - ⚔ **Parallel Chunking**: Zips chunks in parallel for faster processing.
103
+ - āÆļø **Serial Uploads**: Uploads files one by one with a random delay (2-5s) to avoid flood limits.
104
+ - šŸ’¾ **Smart Chunking**: Splits large folders into zip chunks (max 2GB each).
105
+ - āœ… **MTProto Auth**: Support for User accounts with session persistence.
133
106
 
134
107
  ## How to Get Telegram Credentials
135
-
136
- 1. **Bot Token**: Create a bot using [@BotFather](https://t.me/botfather) on Telegram
137
- 2. **Chat ID**:
138
- - Send a message to your bot
139
- - Visit `https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates`
140
- - Find your chat ID in the response
141
-
142
- ## Features
143
-
144
- - āœ… Automatically splits large folders into 50MB chunks
145
- - āœ… Creates zip files with maximum compression
146
- - āœ… Password protection with AES-256 encryption
147
- - āœ… Optional Telegram upload with progress bars
148
- - āœ… Works from any directory on your system
149
- - āœ… Flexible credential management (CLI args or env vars)
108
+ 1. **API ID & Hash**: Go to [my.telegram.org](https://my.telegram.org), log in, and click "API development tools". Create a new application to get your `App api_id` and `App api_hash`.
109
+ 2. **Chat ID**: You can get your Chat ID by forwarding a message to a bot like @userinfobot. For channels/groups, it usually starts with `-100`.
@@ -16,21 +16,23 @@ program
16
16
  .option("-o, --output <dir>", "Output directory", "output")
17
17
  .option("-p, --password <password>", "Password to protect zip files")
18
18
  .option("--telegram", "Upload zip files to Telegram")
19
- .option("--bot-token <token>", "Telegram bot token (required if using --telegram)")
19
+ .option("--api-id <id>", "Telegram API ID (required for MTProto)")
20
+ .option("--api-hash <hash>", "Telegram API Hash (required for MTProto)")
20
21
  .option("--chat-id <id>", "Telegram chat ID (required if using --telegram)")
21
22
  .parse();
22
23
  (async () => {
23
24
  const source = path_1.default.resolve(program.args[0]);
24
25
  const outputDir = path_1.default.resolve(program.opts().output);
25
26
  const useTelegram = program.opts().telegram || false;
26
- const botToken = program.opts().botToken;
27
27
  const chatId = program.opts().chatId;
28
28
  const password = program.opts().password;
29
+ const apiId = program.opts().apiId;
30
+ const apiHash = program.opts().apiHash;
29
31
  console.log(`\nšŸ•øļø Crawling files in ${source}...`);
30
32
  const files = await (0, crawler_1.crawl)(source);
31
33
  console.log(`šŸ“‚ Found ${files.length} file${files.length !== 1 ? 's' : ''}`);
32
34
  const chunks = (0, chunking_1.chunkFiles)(files);
33
- console.log(`šŸ“¦ Created ${chunks.length} chunk${chunks.length !== 1 ? 's' : ''} (max 48MB each)${password ? ' šŸ”’ Password protected' : ''}\n`);
34
- await (0, zipper_1.zipChunks)(chunks, outputDir, useTelegram, botToken, chatId, password);
35
+ console.log(`šŸ“¦ Created ${chunks.length} chunk${chunks.length !== 1 ? 's' : ''} (max 2GB each)${password ? ' šŸ”’ Password protected' : ''}\n`);
36
+ await (0, zipper_1.zipChunks)(chunks, outputDir, useTelegram, chatId, password, apiId, apiHash);
35
37
  console.log(`\nšŸŽ‰ All done! ${useTelegram ? 'Files uploaded to Telegram.' : `Zips saved to ${outputDir}`}`);
36
38
  })();
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chunkFiles = chunkFiles;
4
- const CHUNK_SIZE = 48 * 1024 * 1024; // 48 MB
4
+ const CHUNK_SIZE = 1.9 * 1024 * 1024 * 1024; // 1.9 GB
5
5
  // groups files into chunks where the total size of each chunk does not exceed CHUNK_SIZE
6
6
  function chunkFiles(files) {
7
7
  const chunks = [];
@@ -9,7 +9,7 @@ function chunkFiles(files) {
9
9
  let currentChunkSize = 0;
10
10
  for (const file of files) {
11
11
  if (file.size > CHUNK_SIZE) {
12
- console.warn(`āš ļø Skipping file ${file.path} as it exceeds the maximum size of 48MB (${(file.size / (1024 * 1024)).toFixed(2)} MB).`);
12
+ console.warn(`āš ļø Skipping file ${file.path} as it exceeds the maximum size of 1.9GB (${(file.size / (1024 * 1024 * 1024)).toFixed(2)} GB).`);
13
13
  continue;
14
14
  }
15
15
  if (currentChunkSize + file.size > CHUNK_SIZE) {
@@ -3,36 +3,74 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initTelegramClient = initTelegramClient;
6
7
  exports.uploadToTelegram = uploadToTelegram;
7
- const node_telegram_bot_api_1 = __importDefault(require("node-telegram-bot-api"));
8
+ const telegram_1 = require("telegram");
9
+ const sessions_1 = require("telegram/sessions");
8
10
  const fs_1 = __importDefault(require("fs"));
9
11
  const path_1 = __importDefault(require("path"));
10
12
  const cli_progress_1 = __importDefault(require("cli-progress"));
11
- // Suppress the polling deprecation warning
12
- process.env.NTBA_FIX_350 = "1";
13
- // upload a zip file to telegram with progress bar
14
- async function uploadToTelegram(zipPath, botToken, chatId) {
15
- const bot_token = botToken || process.env.TELEGRAM_BOT_TOKEN || "";
16
- const chat_id = chatId || process.env.TELEGRAM_CHAT_ID || "";
17
- if (!bot_token || !chat_id) {
18
- throw new Error("āŒ Telegram credentials are missing. Please provide --bot-token and --chat-id or set TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID environment variables.");
13
+ const input_1 = __importDefault(require("input"));
14
+ let client = null;
15
+ const sessionPath = path_1.default.join(process.cwd(), ".telegram_session");
16
+ async function initTelegramClient(apiId, apiHash) {
17
+ const API_ID = Number(apiId || process.env.TELEGRAM_API_ID);
18
+ const API_HASH = apiHash || process.env.TELEGRAM_API_HASH;
19
+ if (!API_ID || !API_HASH) {
20
+ throw new Error("āŒ Telegram API_ID and API_HASH are required for MTProto. Please set them in .env or provide as arguments.");
21
+ }
22
+ let sessionString = "";
23
+ if (fs_1.default.existsSync(sessionPath)) {
24
+ sessionString = fs_1.default.readFileSync(sessionPath, "utf-8");
25
+ }
26
+ const stringSession = new sessions_1.StringSession(sessionString);
27
+ client = new telegram_1.TelegramClient(stringSession, API_ID, API_HASH, {
28
+ connectionRetries: 5,
29
+ });
30
+ await client.start({
31
+ phoneNumber: async () => await input_1.default.text("Please enter your number: "),
32
+ password: async () => await input_1.default.text("Please enter your password: "),
33
+ phoneCode: async () => await input_1.default.text("Please enter the code you received: "),
34
+ onError: (err) => console.log(err),
35
+ });
36
+ // Save session
37
+ fs_1.default.writeFileSync(sessionPath, client.session.save());
38
+ console.log("āœ… Connected to Telegram via MTProto!");
39
+ }
40
+ async function uploadToTelegram(zipPath, chatId) {
41
+ if (!client) {
42
+ throw new Error("āŒ Telegram client not initialized.");
43
+ }
44
+ const chat_id = chatId || process.env.TELEGRAM_CHAT_ID;
45
+ if (!chat_id) {
46
+ throw new Error("āŒ Chat ID is missing.");
19
47
  }
20
- const bot = new node_telegram_bot_api_1.default(bot_token, { polling: false });
21
- const totalSize = fs_1.default.statSync(zipPath).size;
22
48
  const fileName = path_1.default.basename(zipPath);
49
+ const totalSize = fs_1.default.statSync(zipPath).size;
23
50
  const fileSizeMB = (totalSize / (1024 * 1024)).toFixed(2);
24
51
  console.log(`\nšŸ“¤ Uploading ${fileName} (${fileSizeMB} MB)`);
25
52
  const progressBar = new cli_progress_1.default.SingleBar({
26
53
  format: "Uploading [{bar}] {percentage}% | {value}/{total} Bytes",
27
54
  }, cli_progress_1.default.Presets.shades_classic);
28
55
  progressBar.start(totalSize, 0);
29
- const stream = fs_1.default.createReadStream(zipPath);
30
- let uploaded = 0;
31
- stream.on("data", (chunk) => {
32
- uploaded += chunk.length;
33
- progressBar.update(uploaded);
34
- });
35
- await bot.sendDocument(chat_id, stream);
36
- progressBar.stop();
37
- console.log(`āœ… ${fileName} uploaded successfully`);
56
+ try {
57
+ await client.sendFile(chat_id, {
58
+ file: zipPath,
59
+ forceDocument: true,
60
+ progressCallback: (progress) => {
61
+ // progress is 0 to 1 (float)
62
+ // We need to map it to bytes for the progress bar, but GramJS progress is sometimes tricky.
63
+ // Assuming it's ratio.
64
+ progressBar.update(Math.floor(progress * totalSize));
65
+ }
66
+ });
67
+ progressBar.update(totalSize); // Ensure it finishes
68
+ progressBar.stop();
69
+ console.log(`āœ… ${fileName} uploaded successfully`);
70
+ }
71
+ catch (error) {
72
+ progressBar.stop();
73
+ console.error(`āŒ Failed to upload ${fileName}:`, error);
74
+ throw error;
75
+ }
38
76
  }
@@ -13,17 +13,31 @@ const archiver_zip_encrypted_1 = __importDefault(require("archiver-zip-encrypted
13
13
  const telegramUploader_1 = require("./telegramUploader");
14
14
  // Register the encrypted format
15
15
  archiver_1.default.registerFormat('zip-encrypted', archiver_zip_encrypted_1.default);
16
- async function zipChunks(chunks, outputDir, useTelegram, botToken, chatId, password) {
16
+ // Helper for serial execution
17
+ let uploadQueue = Promise.resolve();
18
+ const queueUpload = (action) => {
19
+ const next = uploadQueue.then(action).catch(err => {
20
+ console.error("Queue error:", err);
21
+ throw err;
22
+ });
23
+ uploadQueue = next.catch(() => { }); // Prevent queue from breaking on error, but we still throw for the caller
24
+ return next;
25
+ };
26
+ async function zipChunks(chunks, outputDir, useTelegram, chatId, password, apiId, apiHash) {
17
27
  fs_1.default.mkdirSync(outputDir, { recursive: true });
18
- const uploadQueue = [];
19
- for (let i = 0; i < chunks.length; i++) {
28
+ if (useTelegram) {
29
+ console.log("šŸ”„ Initializing Telegram Client...");
30
+ await (0, telegramUploader_1.initTelegramClient)(apiId, apiHash);
31
+ }
32
+ // Process chunks in parallel (Zipping is parallel, Uploading is queued/serial)
33
+ await Promise.all(chunks.map(async (chunk, i) => {
20
34
  const zipName = `chunk_${i + 1}.zip`;
21
35
  const zipPath = path_1.default.join(outputDir, zipName);
22
- console.log(`šŸ“¦ Zipping ${zipName}...`);
36
+ console.log(`šŸ“¦ Zipping ${zipName} (starting)...`);
23
37
  const progressBar = new cli_progress_1.default.SingleBar({
24
38
  format: `Zipping ${zipName} [{bar}] {percentage}% | {value}/{total} files`,
25
39
  }, cli_progress_1.default.Presets.shades_classic);
26
- progressBar.start(chunks[i].length, 0);
40
+ progressBar.start(chunk.length, 0);
27
41
  await new Promise((resolve, reject) => {
28
42
  const output = fs_1.default.createWriteStream(zipPath);
29
43
  // Use encrypted archiver if password is provided
@@ -37,22 +51,28 @@ async function zipChunks(chunks, outputDir, useTelegram, botToken, chatId, passw
37
51
  archive.pipe(output);
38
52
  output.on("close", () => {
39
53
  progressBar.stop();
40
- if (useTelegram) {
41
- uploadQueue.push((0, telegramUploader_1.uploadToTelegram)(zipPath, botToken, chatId));
42
- }
43
- ;
54
+ console.log(`āœ… Zipped ${zipName}`);
44
55
  resolve();
45
56
  });
46
- archive.on("error", reject);
47
- chunks[i].forEach((file, index) => {
57
+ archive.on("error", (err) => {
58
+ progressBar.stop();
59
+ reject(err);
60
+ });
61
+ chunk.forEach((file) => {
48
62
  archive.file(file.path, { name: path_1.default.basename(file.path) });
49
63
  progressBar.increment();
50
64
  });
51
65
  archive.finalize();
52
66
  });
53
- }
54
- if (useTelegram) {
55
- console.log("\nšŸš€ Uploading all files to Telegram...");
56
- await Promise.all(uploadQueue);
57
- }
67
+ if (useTelegram) {
68
+ // Queue the upload so it happens serially
69
+ await queueUpload(async () => {
70
+ // Random delay between 2 and 5 seconds
71
+ const delay = Math.floor(Math.random() * (5000 - 2000 + 1) + 2000);
72
+ console.log(`ā³ Waiting ${delay / 1000}s before uploading ${zipName}...`);
73
+ await new Promise((resolve) => setTimeout(resolve, delay));
74
+ await (0, telegramUploader_1.uploadToTelegram)(zipPath, chatId);
75
+ });
76
+ }
77
+ }));
58
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ayush24k/telezipper",
3
- "version": "1.4.0",
3
+ "version": "1.5.1",
4
4
  "description": "Split folders into multiple 50MB zip files with optional Telegram upload made for personal use.",
5
5
  "files": [
6
6
  "dist"
@@ -35,14 +35,14 @@
35
35
  "cli-progress": "^3.12.0",
36
36
  "commander": "^14.0.2",
37
37
  "dotenv": "^17.2.3",
38
- "node-telegram-bot-api": "^0.67.0",
38
+ "input": "^1.0.1",
39
+ "telegram": "^2.26.22",
39
40
  "tough-cookie": "^2.5.0"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/archiver": "^7.0.0",
43
44
  "@types/cli-progress": "^3.11.6",
44
45
  "@types/node": "^25.1.0",
45
- "@types/node-telegram-bot-api": "^0.64.13",
46
46
  "typescript": "^5.9.3"
47
47
  }
48
- }
48
+ }