teleproto 1.225.0 → 1.225.2

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.
@@ -1,10 +1,7 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 sanyok12345. All rights reserved.
4
-
5
- This project, teleproto, is an independent work originally derived from GramJS.
6
- GramJS is an open source project licensed under the MIT License.
7
- Portions of teleproto are adapted from GramJS and remain subject to the MIT terms.
3
+ Copyright (c) 2019 GramJS
4
+ Copyright (c) 2025-present sanyok12345
8
5
 
9
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
10
7
  of this software and associated documentation files (the "Software"), to deal
@@ -22,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
19
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
20
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
21
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
- SOFTWARE.
22
+ SOFTWARE.
package/README.md CHANGED
@@ -1,150 +1,115 @@
1
- # teleproto
1
+ [![npm](https://img.shields.io/npm/v/teleproto)](https://www.npmjs.com/package/teleproto)
2
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue)](./LICENSE)
2
3
 
3
- <p align="center">
4
- <img src="https://img.shields.io/npm/v/teleproto" alt="npm version">
5
- <img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen" alt="node version">
6
- <img src="https://img.shields.io/badge/language-TypeScript-3178c6" alt="typescript">
7
- <img src="https://img.shields.io/badge/license-MIT-blue" alt="license">
8
- <a href="https://t.me/teleproto"><img src="https://img.shields.io/badge/Telegram-Chat-26A5E4?logo=telegram" alt="telegram chat"></a>
9
- </p>
4
+ This project was forked from the open source GramJS project in 2025 and is now developed independently.
10
5
 
11
- Modern Telegram MTProto client for Node.js, written in TypeScript.
12
- `teleproto` is a high-performance fork of GramJS focused on clean API ergonomics, runtime reliability, and up-to-date Telegram layers.
6
+ This README is just a fast *quick start*. Ongoing discussion happens in the [Telegram chat](https://t.me/teleproto).
13
7
 
14
- ## Features
8
+ # What is teleproto?
15
9
 
16
- - **MTProto-first**: Full Telegram API access through high-level client methods and raw `Api` calls.
17
- - **TypeScript-friendly**: Strong typings across client methods, events, sessions, and TL objects.
18
- - **Session options**: Use `StringSession` for portability or `StoreSession` for local persistence.
19
- - **Event system**: Handle updates with builders like `NewMessage`, `EditedMessage`, `CallbackQuery`, and more.
20
- - **Examples included**: Ready-to-run scripts in `teleproto_examples`.
10
+ teleproto is a TypeScript client for Telegram's MTProto API the same protocol Telegram's own apps speak. Through it, your code gets the full account surface: userbots, multi-account automation, file transfer, raw TL invocation when you need it. If you only need to push notifications from a bot, the official Bot API is simpler; teleproto exists for everything *beyond* that.
21
11
 
22
- ## Installation
12
+ # Installing teleproto
23
13
 
24
- ```bash
25
- npm i teleproto
26
- ```
14
+ % npm install teleproto
15
+
16
+ Pure JavaScript, no native build step — installs cleanly on Alpine, ARM, and serverless runtimes.
27
17
 
28
- ## Quick Start
18
+ # Connecting to Telegram
29
19
 
30
- 1. Open https://my.telegram.org
31
- 2. Create an app in **API development tools**
32
- 3. Copy your `api_id` and `api_hash`
20
+ You need an `api_id` and `api_hash` from <https://my.telegram.org>. Then:
33
21
 
34
22
  ```ts
35
23
  import { TelegramClient } from "teleproto";
36
24
  import { StringSession } from "teleproto/sessions";
37
- import readline from "readline";
25
+ import { createInterface } from "node:readline/promises";
26
+
27
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
38
28
 
39
- const apiId = 123456;
40
- const apiHash = "0123456789abcdef0123456789abcdef";
29
+ const apiId = 0; // from https://my.telegram.org
30
+ const apiHash = ""; // from https://my.telegram.org
41
31
  const session = new StringSession("");
42
32
 
43
- const rl = readline.createInterface({
44
- input: process.stdin,
45
- output: process.stdout,
33
+ const client = new TelegramClient(session, apiId, apiHash, {
34
+ connectionRetries: 5,
46
35
  });
47
36
 
48
- const ask = (q: string) =>
49
- new Promise<string>((resolve) => rl.question(q, resolve));
50
-
51
- async function main() {
52
- const client = new TelegramClient(session, apiId, apiHash, {
53
- connectionRetries: 5,
54
- });
55
-
56
- await client.start({
57
- phoneNumber: async () => await ask("Phone number: "),
58
- password: async () => await ask("2FA password (if enabled): "),
59
- phoneCode: async () => await ask("Code from Telegram: "),
60
- onError: (err) => console.error(err),
61
- });
62
-
63
- console.log("Connected as:", (await client.getMe())?.username || "unknown");
64
- console.log("String session:\n", client.session.save());
37
+ await client.start({
38
+ phoneNumber: () => rl.question("Phone: "),
39
+ password: () => rl.question("2FA password: "),
40
+ phoneCode: () => rl.question("Code: "),
41
+ onError: console.error,
42
+ });
65
43
 
66
- await client.sendMessage("me", { message: "Hello from teleproto!" });
67
- await client.disconnect();
68
- rl.close();
69
- }
44
+ console.log(await client.getMe());
45
+ console.log("Session string:", client.session.save());
70
46
 
71
- main().catch(console.error);
47
+ rl.close();
72
48
  ```
73
49
 
74
- ## Sessions
75
-
76
- Use `StringSession` when you want to store auth as a single string:
50
+ The session string is your saved login. Drop it back into `new StringSession(saved)` next time and skip the auth flow entirely.
77
51
 
78
- ```ts
79
- import { StringSession } from "teleproto/sessions";
80
- const session = new StringSession("");
81
- ```
52
+ # Sending and receiving
82
53
 
83
- Use `StoreSession` when you want local folder-based persistence:
84
-
85
- ```ts
86
- import { StoreSession } from "teleproto/sessions";
87
- const session = new StoreSession("teleproto_session");
88
- ```
89
-
90
- ## Events
54
+ Send a message, listen for incoming ones:
91
55
 
92
56
  ```ts
93
57
  import { NewMessage } from "teleproto/events";
94
58
 
59
+ await client.sendMessage("me", { message: "hello from teleproto" });
60
+
95
61
  client.addEventHandler(
96
- async (event) => {
97
- const text = event.message.message || "";
98
- if (/^hello$/i.test(text.trim())) {
99
- await event.message.reply({ message: "Hi there!" });
100
- }
101
- },
102
- new NewMessage({})
62
+ (event) => console.log(event.message.message),
63
+ new NewMessage({}),
103
64
  );
104
65
  ```
105
66
 
106
- ## Raw API
67
+ # Raw MTProto API
68
+
69
+ Every method in Telegram's TL schema is callable directly through `Api.*`. teleproto follows the schema layer-for-layer, so what Telegram adds is usually available here within days.
107
70
 
108
71
  ```ts
109
72
  import { Api } from "teleproto";
110
73
 
111
- const result = await client.invoke(
112
- new Api.help.GetConfig()
113
- );
114
- console.log(result);
74
+ const config = await client.invoke(new Api.help.GetConfig());
115
75
  ```
116
76
 
117
- ## Examples
77
+ # Versioning
118
78
 
119
- Practical scripts are available in `teleproto_examples`:
79
+ teleproto uses a three-part version `MAJOR.LAYER.PATCH`:
120
80
 
121
- - `print_updates.ts`
122
- - `print_messages.ts`
123
- - `replier.ts`
124
- - `interactive_terminal.ts`
81
+ - **MAJOR** — bumped on breaking API changes in teleproto itself.
82
+ - **LAYER** — the Telegram TL schema layer the release ships against
83
+ (e.g. `1.225.x` ships layer 225).
84
+ - **PATCH** — fixes and non-breaking improvements within the same layer.
125
85
 
126
- Run any example from the project root:
86
+ This stays compatible with npm's range syntax:
127
87
 
128
- ```bash
129
- npx ts-node --transpile-only teleproto_examples/print_updates.ts
130
- ```
88
+ - `^1.225.0` accepts new layers and patches — recommended default.
89
+ - `~1.225.0` sticks to layer 225 only; useful if you depend on
90
+ schema specifics that newer layers might change.
91
+ - `1.225.1` is an exact pin.
92
+
93
+ # Examples
94
+
95
+ Runnable scripts live in [teleproto_examples/](teleproto_examples/):
96
+
97
+ - `print_updates.ts` — log every update the client receives
98
+ - `print_messages.ts` — listen for new messages only
99
+ - `replier.ts` — auto-reply pattern for bots and userbots
100
+ - `interactive_terminal.ts` — REPL against a live client
131
101
 
132
- ## Community
102
+ Each is self-contained. Set your credentials at the top and run:
133
103
 
134
- - [Telegram Chat](https://t.me/teleproto) — questions, discussions, updates
135
- - [GitHub Issues](https://github.com/sanyok12345/teleproto/issues) — bug reports and feature requests
104
+ % npx ts-node --transpile-only teleproto_examples/print_updates.ts
136
105
 
137
- ## Support the project ☕
106
+ # Code contributions
138
107
 
139
- If teleproto saves you time or powers your product — consider buying me a coffee.
140
- Every donation keeps the lights on and the commits flowing.
108
+ Please see [CONTRIBUTING.md][1].
141
109
 
142
- | Network | Address |
143
- |---------|---------|
144
- | **TON** | `sanyok12345.ton` |
145
- | **TRX** | `TXCtN1UrxST9ovq5tDN3Zb96eNF4164nK5` |
146
- | **SOL** | `B3XcKmAR9aG2nBiWSMDe76GGa55hPNgLQ92QR2SjRR6F` |
110
+ # License
147
111
 
148
- ## License
112
+ teleproto is distributed under the [MIT License][2].
149
113
 
150
- MIT
114
+ [1]: ./CONTRIBUTING.md
115
+ [2]: ./LICENSE
package/Version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "1.225.0";
1
+ export declare const version = "1.225.2";
package/Version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
- exports.version = "1.225.0";
4
+ exports.version = "1.225.2";
@@ -353,30 +353,6 @@ export declare class TelegramClient extends TelegramBaseClient {
353
353
  * ```
354
354
  */
355
355
  downloadFile(inputLocation: Api.TypeInputFileLocation, fileParams?: downloadMethods.DownloadFileParams): Promise<string | Buffer<ArrayBufferLike> | undefined>;
356
- /**
357
- * Iterates over a file download, yielding chunks of the file.
358
- * This method can be used to stream files in a more convenient way, since it offers more control (pausing, resuming, etc.)
359
- * @param iterFileParams - {@link IterDownloadFunction}
360
- * @return a Buffer downloaded from the inputFile.
361
- * @example
362
- * ```ts
363
- * const photo = message.photo;
364
- * for await (const chunk of client.iterDownload({
365
- * file: new Api.InputPhotoFileLocation({
366
- * id: photo.id,
367
- * accessHash: photo.accessHash,
368
- * fileReference: photo.fileReference,
369
- * thumbSize: size.type
370
- * }),
371
- * offset: start,
372
- * limit: end,
373
- * requestSize:2048*1024
374
- * )){
375
- * console.log("Downloaded chunk of size",chunk.length);
376
- * };
377
- * ```
378
- */
379
- iterDownload(iterFileParams: downloadMethods.IterDownloadFunction): downloadMethods.DirectDownloadIter;
380
356
  /**
381
357
  * Downloads the profile photo from the given user,chat or channel.<br/>
382
358
  * This method will return an empty buffer in case of no profile photo.
@@ -1133,8 +1109,6 @@ export declare class TelegramClient extends TelegramBaseClient {
1133
1109
  /** @hidden */
1134
1110
  _getDownloadConcurrency(fileSize: number): Promise<number>;
1135
1111
  /** @hidden */
1136
- _removeSender(dcId: number): void;
1137
- /** @hidden */
1138
1112
  _getResponseMessage(req: any, result: any, inputChat: any): Api.TypeMessage | Map<number, Api.Message> | (Api.Message | undefined)[] | undefined;
1139
1113
  /** @hidden */
1140
1114
  static get events(): any;
@@ -433,32 +433,6 @@ class TelegramClient extends telegramBaseClient_1.TelegramBaseClient {
433
433
  downloadFile(inputLocation, fileParams = {}) {
434
434
  return downloadMethods.downloadFile(this, inputLocation, fileParams);
435
435
  }
436
- /**
437
- * Iterates over a file download, yielding chunks of the file.
438
- * This method can be used to stream files in a more convenient way, since it offers more control (pausing, resuming, etc.)
439
- * @param iterFileParams - {@link IterDownloadFunction}
440
- * @return a Buffer downloaded from the inputFile.
441
- * @example
442
- * ```ts
443
- * const photo = message.photo;
444
- * for await (const chunk of client.iterDownload({
445
- * file: new Api.InputPhotoFileLocation({
446
- * id: photo.id,
447
- * accessHash: photo.accessHash,
448
- * fileReference: photo.fileReference,
449
- * thumbSize: size.type
450
- * }),
451
- * offset: start,
452
- * limit: end,
453
- * requestSize:2048*1024
454
- * )){
455
- * console.log("Downloaded chunk of size",chunk.length);
456
- * };
457
- * ```
458
- */
459
- iterDownload(iterFileParams) {
460
- return downloadMethods.iterDownload(this, iterFileParams);
461
- }
462
436
  //region download
463
437
  /**
464
438
  * Downloads the profile photo from the given user,chat or channel.<br/>
@@ -1183,7 +1157,6 @@ class TelegramClient extends telegramBaseClient_1.TelegramBaseClient {
1183
1157
  client: this,
1184
1158
  securityChecks: this._securityChecks,
1185
1159
  autoReconnectCallback: this._handleReconnect.bind(this),
1186
- _exportedSenderPromises: this._exportedSenderPromises,
1187
1160
  reconnectRetries: this._reconnectRetries,
1188
1161
  });
1189
1162
  }
@@ -1225,12 +1198,12 @@ class TelegramClient extends telegramBaseClient_1.TelegramBaseClient {
1225
1198
  this._log.info(`Reconnecting to new data center ${newDc}`);
1226
1199
  const DC = await this.getDC(newDc);
1227
1200
  this.session.setDC(newDc, DC.ipAddress, DC.port);
1228
- // authKey's are associated with a server, which has now changed
1229
- // so it's not valid anymore. Set to undefined to force recreating it.
1230
1201
  await this._sender.authKey.setKey(undefined);
1231
1202
  this.session.setAuthKey(undefined);
1232
1203
  this.session.save();
1233
1204
  this._isSwitchingDc = true;
1205
+ await this._filePool.purge();
1206
+ await this._apiSenderPool.purge();
1234
1207
  await this._disconnect();
1235
1208
  this._sender = undefined;
1236
1209
  return await this.connect();
@@ -1332,10 +1305,6 @@ class TelegramClient extends telegramBaseClient_1.TelegramBaseClient {
1332
1305
  return fileSize > 20 * 1024 * 1024 ? largeLimit : smallLimit;
1333
1306
  }
1334
1307
  /** @hidden */
1335
- _removeSender(dcId) {
1336
- delete this._borrowedSenderPromises[dcId];
1337
- }
1338
- /** @hidden */
1339
1308
  _getResponseMessage(req, result, inputChat) {
1340
1309
  return parseMethods._getResponseMessage(this, req, result, inputChat);
1341
1310
  }
@@ -1,119 +1,29 @@
1
1
  import { Api } from "../tl";
2
2
  import type { TelegramClient } from "./TelegramClient";
3
3
  import { EntityLike, OutFile, ProgressCallback } from "../define";
4
- import { RequestIter } from "../requestIter";
5
4
  import bigInt from "big-integer";
6
- /**
7
- * progress callback that will be called each time a new chunk is downloaded.
8
- */
9
5
  export interface progressCallback {
10
- (
11
- /** How much was downloaded */
12
- downloaded: bigInt.BigInteger,
13
- /** Full size of the file to be downloaded */
14
- fullSize: bigInt.BigInteger,
15
- /** other args to be passed if needed */
16
- ...args: any[]): void;
17
- /** When this value is set to true the download will stop */
6
+ (downloaded: bigInt.BigInteger, fullSize: bigInt.BigInteger, ...args: any[]): void;
18
7
  isCanceled?: boolean;
19
- /** Does nothing for now. */
20
8
  acceptsBuffer?: boolean;
21
9
  }
22
10
  export interface DownloadFileParams {
23
- /**
24
- * The output file path, directory,buffer, or stream-like object.
25
- * If the path exists and is a file, it will be overwritten.
26
-
27
- * If the file path is `undefined` or `Buffer`, then the result
28
- will be saved in memory and returned as `Buffer`.
29
- */
30
11
  outputFile?: OutFile;
31
- /** The dcId that the file belongs to. Used to borrow a sender from that DC. The library should handle this for you */
32
12
  dcId?: number;
33
- /** The file size that is about to be downloaded, if known.<br/>
34
- Only used if ``progressCallback`` is specified. */
35
13
  fileSize?: bigInt.BigInteger;
36
- /** How much to download in each chunk. The larger the less requests to be made. (max is 512kb). */
37
14
  partSizeKb?: number;
38
- /** Progress callback accepting one param. (progress :number) which is a float between 0 and 1 */
39
15
  progressCallback?: progressCallback;
40
16
  msgData?: [EntityLike, number];
41
17
  }
42
- /**
43
- * contains optional download params for profile photo.
44
- */
45
18
  export interface DownloadProfilePhotoParams {
46
- /** Whether to download the big version or the small one of the photo */
47
19
  isBig?: boolean;
48
20
  outputFile?: OutFile;
49
21
  }
50
- export interface DirectDownloadIterInterface {
51
- fileLocation: Api.TypeInputFileLocation;
52
- dcId: number;
53
- offset: bigInt.BigInteger;
54
- stride: number;
55
- chunkSize: number;
56
- requestSize: number;
57
- fileSize: number;
58
- msgData: number;
59
- }
60
- export interface IterDownloadFunction {
61
- file?: Api.TypeMessageMedia | Api.TypeInputFile | Api.TypeInputFileLocation;
62
- offset?: bigInt.BigInteger;
63
- stride?: number;
64
- limit?: number;
65
- chunkSize?: number;
66
- requestSize: number;
67
- fileSize?: bigInt.BigInteger;
68
- dcId?: number;
69
- msgData?: [EntityLike, number];
70
- }
71
- export declare class DirectDownloadIter extends RequestIter {
72
- protected request?: Api.upload.GetFile;
73
- private _sender?;
74
- private _timedOut;
75
- protected _stride?: number;
76
- protected _chunkSize?: number;
77
- protected _lastPart?: Buffer;
78
- protected buffer: Buffer[] | undefined;
79
- _init({ fileLocation, dcId, offset, stride, chunkSize, requestSize, fileSize, msgData, }: DirectDownloadIterInterface): Promise<void>;
80
- _loadNextChunk(): Promise<boolean | undefined>;
81
- _request(): Promise<Buffer>;
82
- close(): Promise<void>;
83
- [Symbol.asyncIterator](): AsyncIterator<Buffer, any, undefined>;
84
- }
85
- export declare class GenericDownloadIter extends DirectDownloadIter {
86
- _loadNextChunk(): Promise<boolean | undefined>;
87
- }
88
- /** @hidden */
89
- export declare function iterDownload(client: TelegramClient, { file, offset, stride, limit, chunkSize, requestSize, fileSize, dcId, msgData, }: IterDownloadFunction): DirectDownloadIter;
90
22
  /** @hidden */
91
- export declare function downloadFile(client: TelegramClient, inputLocation: Api.TypeInputFileLocation, { outputFile, partSizeKb, fileSize, progressCallback, dcId, msgData, }: DownloadFileParams): Promise<string | Buffer<ArrayBufferLike> | undefined>;
92
- /**
93
- * All of these are optional and will be calculated automatically if not specified.
94
- */
23
+ export declare function downloadFile(client: TelegramClient, inputLocation: Api.TypeInputFileLocation, { outputFile, partSizeKb, fileSize, progressCallback, dcId, }: DownloadFileParams): Promise<Buffer | string | undefined>;
95
24
  export interface DownloadMediaInterface {
96
- /**
97
- * The output file location, if left undefined this method will return a buffer
98
- */
99
25
  outputFile?: OutFile;
100
- /**
101
- * Which thumbnail size from the document or photo to download, instead of downloading the document or photo itself.<br/>
102
- <br/>
103
- If it's specified but the file does not have a thumbnail, this method will return `undefined`.<br/>
104
- <br/>
105
- The parameter should be an integer index between ``0`` and ``sizes.length``.<br/>
106
- ``0`` will download the smallest thumbnail, and ``sizes.length - 1`` will download the largest thumbnail.<br/>
107
- <br/>
108
- You can also pass the `Api.PhotoSize` instance to use. Alternatively, the thumb size type `string` may be used.<br/>
109
- <br/>
110
- In short, use ``thumb=0`` if you want the smallest thumbnail and ``thumb=sizes.length`` if you want the largest thumbnail.
111
- */
112
26
  thumb?: number | Api.TypePhotoSize;
113
- /**
114
- * A callback function accepting two parameters:
115
- * ``(received bytes, total)``.
116
- */
117
27
  progressCallback?: ProgressCallback;
118
28
  }
119
29
  /** @hidden */
@@ -121,9 +31,9 @@ export declare function downloadMedia(client: TelegramClient, messageOrMedia: Ap
121
31
  /** @hidden */
122
32
  export declare function _downloadDocument(client: TelegramClient, doc: Api.MessageMediaDocument | Api.TypeDocument, outputFile: OutFile | undefined, date: number, thumb?: number | string | Api.TypePhotoSize, progressCallback?: ProgressCallback, msgData?: [EntityLike, number]): Promise<Buffer | string | undefined>;
123
33
  /** @hidden */
124
- export declare function _downloadContact(client: TelegramClient, media: Api.MessageMediaContact, args: DownloadMediaInterface): Promise<Buffer>;
34
+ export declare function _downloadContact(_client: TelegramClient, _media: Api.MessageMediaContact, _args: DownloadMediaInterface): Promise<Buffer>;
125
35
  /** @hidden */
126
- export declare function _downloadWebDocument(client: TelegramClient, media: Api.WebDocument | Api.WebDocumentNoProxy, args: DownloadMediaInterface): Promise<Buffer>;
36
+ export declare function _downloadWebDocument(_client: TelegramClient, _media: Api.WebDocument | Api.WebDocumentNoProxy, _args: DownloadMediaInterface): Promise<Buffer>;
127
37
  /** @hidden */
128
38
  export declare function _downloadCachedPhotoSize(size: Api.PhotoCachedSize | Api.PhotoStrippedSize, outputFile?: OutFile): Promise<string | Buffer<ArrayBufferLike> | undefined>;
129
39
  /** @hidden */