Compare commits
No commits in common. "d98281f30fc5205190ecbabfb714e8f8eabd647d" and "690948b8b1e58af87b765990e50cfcf2d055212a" have entirely different histories.
d98281f30f
...
690948b8b1
9 changed files with 82 additions and 83 deletions
|
@ -43,19 +43,6 @@ const client = new TelegramClient({ ... })
|
|||
await client.importSession(convertFromGramjsSession("..."))
|
||||
```
|
||||
|
||||
### Store session
|
||||
|
||||
In some version GramJS added support for storing session as a directory of files,
|
||||
and can be imported like so:
|
||||
|
||||
```ts
|
||||
import { readGramjsStoreSession, convertFromGramjsSession } from '@mtcute/convert'
|
||||
|
||||
const client = new TelegramClient({ ... })
|
||||
const session = await readGramjsStoreSession('/path/to/session')
|
||||
await client.importSession(convertFromGramjsSession(session))
|
||||
```
|
||||
|
||||
## [MTKruto](https://github.com/MTKruto/MTKruto)
|
||||
|
||||
```ts
|
||||
|
@ -65,19 +52,6 @@ const client = new TelegramClient({ ... })
|
|||
await client.importSession(convertFromMtkrutoSession("..."))
|
||||
```
|
||||
|
||||
## [Telegram Desktop](https://github.com/telegramdesktop/tdesktop) (tdata)
|
||||
|
||||
```ts
|
||||
import { convertFromTdata } from '@mtcute/convert'
|
||||
|
||||
const client = new TelegramClient({ ... })
|
||||
await client.importSession(convertFromTdata({
|
||||
path: '/path/to/tdata',
|
||||
ignoreVersion: true // note: this might break
|
||||
// passcode: '123456' // if you have a passcode
|
||||
}))
|
||||
```
|
||||
|
||||
## Backwards
|
||||
|
||||
If you need to convert a session from mtcute to another library, you can use the `convertTo*` functions instead:
|
||||
|
|
|
@ -60,7 +60,7 @@ no extra steps are required.
|
|||
|
||||
## Bun
|
||||
|
||||
Support for Bun is provided in `@mtcute/bun` package, and
|
||||
Experimental support for Bun is provided in `@mtcute/bun` package, and
|
||||
Bun is also supported in `@mtcute/create-bot`.
|
||||
|
||||
```bash
|
||||
|
@ -71,7 +71,7 @@ bun add @mtcute/bun
|
|||
|
||||
## Deno
|
||||
|
||||
Support for Deno is provided in `@mtcute/deno` package, which is published
|
||||
Experimental support for Deno is provided in `@mtcute/deno` package, which is published
|
||||
to the [jsr.io](https://jsr.io) registry:
|
||||
|
||||
```ts
|
||||
|
@ -137,20 +137,34 @@ See also: [Tree-shaking](/guide/advanced/treeshaking.md)
|
|||
|
||||
## Other runtimes
|
||||
|
||||
mtcute strives to be as runtime-agnostic as possible, so it should work in any environment that supports some basic ES2020 features (notably, bigints. There's an [unofficial fork](https://github.com/cyan-2048/mtcute) that uses polyfills for bigints, if you're into that).
|
||||
mtcute strives to be as runtime-agnostic as possible, so it should work in any environment that supports
|
||||
some basic ES2020 features.
|
||||
|
||||
In case your runtime of choice is not listed above, you can try using `@mtcute/core` directly
|
||||
|
||||
You will need to provide your own implementations of storage, networking and crypto - feel free to take a look at web/node implementations for reference (or even extend them to better fit your needs, e.g. if some runtime only partially supports some Node.js APIs).
|
||||
You will need to provide your own implementations of storage, networking and crypto - feel free to take a
|
||||
look at web/node implementations for reference (or even extend them to better fit your needs, e.g. if some runtime
|
||||
only partially supports some Node.js APIs).
|
||||
|
||||
```ts
|
||||
import { TelegramClient } from '@mtcute/core/client.js'
|
||||
import { setPlatform } from '@mtcute/core/platform.js'
|
||||
|
||||
setPlatform(new MyPlatform())
|
||||
|
||||
const tg = new TelegramClient({
|
||||
...,
|
||||
storage: new MyStorage(),
|
||||
crypto: new MyCrypto()
|
||||
transport: new MyTransport(),
|
||||
platform: new MyPlatform(),
|
||||
transport: () => new MyTransport(),
|
||||
})
|
||||
```
|
||||
|
||||
::: info
|
||||
You only need to call `setPlatform` once, before creating any clients.
|
||||
Platform is set once globally and cannot be changed afterwards.
|
||||
It is safe to call `setPlatform` multiple times, as long as the constructor is the same - it will be ignored if the platform is already set.
|
||||
|
||||
A good starting point might be to use [WebPlatform](https://ref.mtcute.dev/classes/_mtcute_web.WebPlatform.html),
|
||||
since it implements everything in portable JavaScript.
|
||||
:::
|
|
@ -103,7 +103,14 @@ You can handle these errors using `TelegramClient#onError`:
|
|||
```ts
|
||||
const tg = new TelegramClient(...)
|
||||
|
||||
tg.onError.add((err) => {
|
||||
tg.onError((err, conn) => {
|
||||
if (conn) {
|
||||
// `err` is the error
|
||||
// `conn` is the connection where the error happened
|
||||
console.log(err, conn)
|
||||
}
|
||||
|
||||
// `err` is not a connection-related error
|
||||
console.log(err)
|
||||
})
|
||||
```
|
||||
|
@ -112,8 +119,7 @@ tg.onError.add((err) => {
|
|||
mtcute handles reconnection and stuff automatically, so you don't need to
|
||||
call `.connect()` again!
|
||||
|
||||
This should primarily be used for logging and debugging, as well as some
|
||||
edge cases where you might need access to low-level connection state
|
||||
This should primarily be used for logging and debugging
|
||||
:::
|
||||
|
||||
## Dispatcher errors
|
||||
|
|
|
@ -38,28 +38,29 @@ const tg = new TelegramClient({
|
|||
|
||||
The updates themselves are dispatched on the client as events (see [reference](https://ref.mtcute.dev/classes/_mtcute_core.index.TelegramClient.html#on)):
|
||||
```ts
|
||||
tg.onNewMessage.add((msg) => {
|
||||
tg.on('new_message', (msg) => {
|
||||
console.log(msg.text)
|
||||
})
|
||||
|
||||
// You can also handle any supported update at once:
|
||||
tg.onUpdate.add((upd) => {
|
||||
tg.on('update', (upd) => {
|
||||
if (upd.name === 'new_message') {
|
||||
console.log(upd.data.text)
|
||||
}
|
||||
})
|
||||
|
||||
// As well as raw MTProto updates:
|
||||
tg.onRawUpdate.add((upd, users, chats) => {
|
||||
tg.on('raw_update', (upd, users, chats) => {
|
||||
console.log(upd._)
|
||||
})
|
||||
```
|
||||
|
||||
::: tip
|
||||
The handlers should be synchronous, so if you want to do something async, make sure to also handle the errors:
|
||||
Client events are based on EventEmitter. It expects handlers to be synchronous,
|
||||
so if you want to do something async, make sure to also handle the errors:
|
||||
|
||||
```ts
|
||||
tg.onNewMessage.add(async (msg) => {
|
||||
tg.on('new_message', async (msg) => {
|
||||
try {
|
||||
await msg.answerText('test')
|
||||
} catch (e) {
|
||||
|
|
|
@ -9,7 +9,7 @@ To download a file, just use `downloadIterable`, `downloadStream`,
|
|||
`downloadBuffer`or `downloadToFile` method on the object that represents a file, for example:
|
||||
|
||||
```ts
|
||||
tg.onNewMessage.add(async (msg) => {
|
||||
tg.on('new_message', async (msg) => {
|
||||
if (msg.media?.type === 'photo') {
|
||||
await tg.downloadToFile('download.jpg', msg.media)
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ them you'll need to have some understanding of how files in MTProto work.
|
|||
File ID is available in `.fileId` field:
|
||||
|
||||
```ts
|
||||
tg.onNewMessage.add(async (msg) => {
|
||||
tg.on('new_message', async (msg) => {
|
||||
if (msg.media?.type === 'photo') {
|
||||
console.log(msg.media.fileId)
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ for different users/bots.
|
|||
Unique File ID is available in `.uniqueFileId` field:
|
||||
|
||||
```ts
|
||||
tg.onNewMessage.add(async (msg) => {
|
||||
tg.on('new_message', async (msg) => {
|
||||
if (msg.media?.type === 'photo') {
|
||||
console.log(msg.media.uniqueFileId)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ Instead of Dispatcher, you can also use client events (however you will miss
|
|||
features that Dispatcher provides):
|
||||
|
||||
```ts
|
||||
tg.onInlineQuery.add(async (query) => {
|
||||
tg.on('inline_query', async (query) => {
|
||||
await query.answer([])
|
||||
})
|
||||
```
|
||||
|
|
|
@ -29,18 +29,15 @@ and also caching won't work past a single run.
|
|||
|
||||
## SQLite storage
|
||||
|
||||
The preferred storage for a server application is the one using SQLite,
|
||||
The preferred storage for a Node.js application is the one using SQLite,
|
||||
because it does not require loading the entire thing into memory, and
|
||||
is also faster than simply reading/writing a file.
|
||||
|
||||
mtcute implements sqlite storages in runtime-specific packages,
|
||||
using the best libraries available for each runtime:
|
||||
- Node.js: [better-sqlite3](https://www.npmjs.com/package/better-sqlite3)
|
||||
- Bun: `bun:sqlite`
|
||||
- Deno: [@db/sqlite](https://jsr.io/@db/sqlite)
|
||||
mtcute implements it in a separate package, `@mtcute/sqlite`, and internally
|
||||
uses [better-sqlite3](https://www.npmjs.com/package/better-sqlite3)
|
||||
|
||||
```ts{4}
|
||||
import { SqliteStorage } from '@mtcute/node' // or '@mtcute/bun' / '@mtcute/deno'
|
||||
import { SqliteStorage } from '@mtcute/sqlite'
|
||||
|
||||
const tg = new TelegramClient({
|
||||
storage: new SqliteStorage('my-account.session')
|
||||
|
@ -48,7 +45,7 @@ const tg = new TelegramClient({
|
|||
```
|
||||
|
||||
::: tip
|
||||
In runtime-specific packages, SQLite storage is the default,
|
||||
If you are using `@mtcute/node`, SQLite storage is the default,
|
||||
and you can simply pass a string with file name instead
|
||||
of instantiating `SqliteStorage` manually:
|
||||
|
||||
|
@ -59,7 +56,8 @@ const tg = new TelegramClient({
|
|||
```
|
||||
:::
|
||||
|
||||
To improve performance, we use WAL mode by default ([Learn more](https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/performance.md)).
|
||||
To improve performance, `@mtcute/sqlite` by default uses
|
||||
WAL mode ([Learn more](https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/performance.md)).
|
||||
|
||||
When using WAL, along with your SQLite file there may also
|
||||
be `-shm` and `-wal` files. If you don't like seeing those files,
|
||||
|
@ -83,11 +81,8 @@ const tg = new TelegramClient({
|
|||
})
|
||||
```
|
||||
|
||||
> Note that the string passed will be used as-is as the database name,
|
||||
> so you might want to prefix it to avoid conflicts.
|
||||
|
||||
::: tip
|
||||
In `@mtcute/web`, IndexedDB storage is the default,
|
||||
In the browser, IndexedDB storage is the default,
|
||||
and you can simply pass a string with file name instead
|
||||
of instantiating `IdbStorage` manually:
|
||||
|
||||
|
@ -149,14 +144,14 @@ Most of the string is occupied by 256 bytes long
|
|||
MTProto authorization key, which, when Base64 encoded,
|
||||
results in **344** characters. Additionally, information
|
||||
about user (their ID and whether the user is a bot) and their DC
|
||||
is included, which results in an average of ~**400** characters
|
||||
is included, which results in an average of **407** characters
|
||||
:::
|
||||
|
||||
## Implementing custom storage
|
||||
|
||||
The easiest way to implement a custom storage would be to make a subclass of `MemoryStorage`.
|
||||
|
||||
Additionaly, mtcute abstracts away the sqlite storage implementation, so you can use the the `BaseSqliteStorage` API to implement sqlite storage using your library of choice (see [Node.js implementation](https://github.com/mtcute/mtcute/tree/master/packages/node/src/sqlite) for reference).
|
||||
The easiest way to implement a custom storage would be to make a subclass of `MemoryStorage`,
|
||||
or check the [source code of SqliteStorage](https://github.com/mtcute/mtcute/blob/master/packages/sqlite/src/index.ts)
|
||||
and implement something similar with your DB of choice.
|
||||
|
||||
### Architecture
|
||||
|
||||
|
@ -168,7 +163,8 @@ A storage provider in mtcute is composed of:
|
|||
more efficient and organized access to the data. Repositories are registered in the driver and are used to
|
||||
access the data in the storage
|
||||
|
||||
Such composable architecture allows for custom storages to implement a specific set of repositories, and to reuse the same driver for different providers.
|
||||
Such composable architecture allows for custom storages to implement a specific set of repositories,
|
||||
and to reuse the same driver for different providers.
|
||||
|
||||
In mtcute, these sets of repositories are defined:
|
||||
- [IMtStorageProvider](https://ref.mtcute.dev/types/_mtcute_core.index.IMtStorageProvider.html), used by `BaseTelegramClient` for low-level
|
||||
|
|
|
@ -15,7 +15,7 @@ import { TcpTransport } from '@mtcute/node'
|
|||
|
||||
const tg = new TelegramClient({
|
||||
// ...
|
||||
transport: new TcpTransport()
|
||||
transport: () => new TcpTransport()
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -35,7 +35,7 @@ import { WebSocketTransport } from '@mtcute/web'
|
|||
|
||||
const tg = new TelegramClient({
|
||||
// ...
|
||||
transport: new WebSocketTransport()
|
||||
transport: () => new WebSocketTransport()
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -46,14 +46,19 @@ In browser, it is used automatically, you don't need to pass this explicitly
|
|||
## HTTP(s) Proxy transport
|
||||
|
||||
To access Telegram via HTTP(s) proxy, you can use
|
||||
`HttpProxyTcpTransport`, which is provided by runtime-specific packages:
|
||||
`HttpProxyTcpTransport`, which is provided
|
||||
by `@mtcute/http-proxy` (Node.js only):
|
||||
|
||||
```bash
|
||||
pnpm add @mtcute/http-proxy
|
||||
```
|
||||
|
||||
```ts{5-8}
|
||||
import { HttpProxyTcpTransport } from '@mtcute/node' // or '@mtcute/bun' / '@mtcute/deno'
|
||||
import { HttpProxyTcpTransport } from '@mtcute/http-proxy'
|
||||
|
||||
const tg = new TelegramClient({
|
||||
// ...
|
||||
transport: new HttpProxyTcpTransport({
|
||||
transport: () => new HttpProxyTcpTransport({
|
||||
host: '127.0.0.1',
|
||||
port: 8080
|
||||
})
|
||||
|
@ -63,14 +68,19 @@ const tg = new TelegramClient({
|
|||
## SOCKS4/5 Proxy transport
|
||||
|
||||
To access Telegram via SOCKS4/5 proxy, you can use
|
||||
`SocksProxyTcpTransport`, which is provided by runtime-specific packages:
|
||||
`SocksTcpTransport`, which is provided
|
||||
by `@mtcute/socks-proxy` (Node.js only):
|
||||
|
||||
```bash
|
||||
pnpm add @mtcute/socks-proxy
|
||||
```
|
||||
|
||||
```ts{5-8}
|
||||
import { SocksProxyTcpTransport } from '@mtcute/node' // or '@mtcute/bun' / '@mtcute/deno'
|
||||
import { SocksTcpTransport } from '@mtcute/socks-proxy'
|
||||
|
||||
const tg = new TelegramClient({
|
||||
// ...
|
||||
transport: new SocksProxyTcpTransport({
|
||||
transport: () => new SocksTcpTransport({
|
||||
host: '127.0.0.1',
|
||||
port: 8080
|
||||
})
|
||||
|
@ -80,14 +90,18 @@ const tg = new TelegramClient({
|
|||
## MTProxy transport
|
||||
|
||||
To access Telegram via MTProxy (MTProto proxy), you can use
|
||||
`MtProxyTcpTransport`, which is provided by runtime-specific packages:
|
||||
`MtProxyTcpTransport`, which is provided by `@mtcute/mtproxy` (Node.js only):
|
||||
|
||||
```bash
|
||||
pnpm add @mtcute/mtproxy
|
||||
```
|
||||
|
||||
```ts{5-8}
|
||||
import { MtProxyTcpTransport } from '@mtcute/node' // or '@mtcute/bun' / '@mtcute/deno'
|
||||
import { MtProxyTcpTransport } from '@mtcute/mtproxy'
|
||||
|
||||
const tg = new TelegramClient({
|
||||
// ...
|
||||
transport: new MtProxyTcpTransport({
|
||||
transport: () => new MtProxyTcpTransport({
|
||||
host: '127.0.0.1',
|
||||
port: 8080,
|
||||
secret: '0123456789abcdef0123456789abcdef'
|
||||
|
@ -108,11 +122,9 @@ could be used to change proxy used to connect to Telegram.
|
|||
To change the transport, simply call `changeTransport`:
|
||||
|
||||
```ts
|
||||
tg.mt.network.changeTransport(new MtProxyTcpTransport({...}))
|
||||
tg.changeTransport(() => new MtProxyTcpTransport({...}))
|
||||
```
|
||||
|
||||
> Note: the `mt` field is only available on `BaseTelegramClient` instances.
|
||||
|
||||
## Implementing custom transport
|
||||
|
||||
When targeting an environment which is not supported already,
|
||||
|
@ -123,7 +135,3 @@ You can check out source code for the bundled transports
|
|||
to get the basic idea
|
||||
[here](https://github.com/mtcute/mtcute/tree/master/packages/core/src/network/transports),
|
||||
and re-use any packet codecs that are included.
|
||||
|
||||
Transports in mtcute are built on top of [`@fuman/net`](https://github.com/teidesu/fuman/tree/main/packages/net), which is an in-house networking abstraction library used by mtcute.
|
||||
It is a very powerful library which makes it super easy to implement custom transports.
|
||||
There isn't much documentation, but feel free to check out the source code [here](https://github.com/teidesu/fuman/blob/main/packages/node/src/net/connection.ts).
|
|
@ -1,13 +1,13 @@
|
|||
import type { StringSessionData } from '@mtcute/core/utils.js'
|
||||
import type { TelethonSession } from '../telethon/types.js'
|
||||
|
||||
import type { GramjsSession } from './types.js'
|
||||
import { readStringSession } from '@mtcute/core/utils.js'
|
||||
|
||||
import { convertFromTelethonSession } from '../telethon/convert.js'
|
||||
|
||||
import { parseGramjsSession } from './parse.js'
|
||||
import { serializeGramjsSession } from './serialize.js'
|
||||
|
||||
export function convertFromGramjsSession(session: GramjsSession | string): StringSessionData {
|
||||
export function convertFromGramjsSession(session: TelethonSession | string): StringSessionData {
|
||||
if (typeof session === 'string') {
|
||||
session = parseGramjsSession(session)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue