diff --git a/packages/bun/src/client.ts b/packages/bun/src/client.ts index 180a2690..88b0254a 100644 --- a/packages/bun/src/client.ts +++ b/packages/bun/src/client.ts @@ -38,7 +38,7 @@ export class BaseTelegramClient extends BaseTelegramClientBase { constructor(opts: BaseTelegramClientOptions) { super({ crypto: new BunCryptoProvider(), - transport: TcpTransport, + transport: new TcpTransport(), platform: new BunPlatform(), ...opts, storage: diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 1b2031f3..2d557549 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -2,7 +2,8 @@ export * from './client.js' export * from './platform.js' export * from './sqlite/index.js' export * from './utils/crypto.js' -// export * from './utils/tcp.js' +export * from './utils/tcp.js' +export * from './utils/proxies.js' export * from './worker.js' export * from '@mtcute/core' export * from '@mtcute/html-parser' diff --git a/packages/bun/src/utils/tcp.ts b/packages/bun/src/utils/tcp.ts index 5583a1e2..cb0ff8b0 100644 --- a/packages/bun/src/utils/tcp.ts +++ b/packages/bun/src/utils/tcp.ts @@ -1,7 +1,14 @@ import { connectTcp } from '@fuman/bun-net' import { IntermediatePacketCodec, type TelegramTransport } from '@mtcute/core' +import type { ITcpConnection } from '@fuman/net' +import type { BasicDcOption } from '@mtcute/core/utils.js' -export const TcpTransport: TelegramTransport = { - connect: dc => connectTcp({ address: dc.ipAddress, port: dc.port }), - packetCodec: () => new IntermediatePacketCodec(), +export class TcpTransport implements TelegramTransport { + connect(dc: BasicDcOption): Promise { + return connectTcp({ address: dc.ipAddress, port: dc.port }) + } + + packetCodec(): IntermediatePacketCodec { + return new IntermediatePacketCodec() + } } diff --git a/packages/deno/src/client.ts b/packages/deno/src/client.ts index 3b729b78..25f88268 100644 --- a/packages/deno/src/client.ts +++ b/packages/deno/src/client.ts @@ -37,7 +37,7 @@ export class BaseTelegramClient extends BaseTelegramClientBase { constructor(opts: BaseTelegramClientOptions) { super({ crypto: new DenoCryptoProvider(), - transport: TcpTransport, + transport: new TcpTransport(), platform: new DenoPlatform(), ...opts, storage: diff --git a/packages/deno/src/utils/tcp.ts b/packages/deno/src/utils/tcp.ts index 2923b852..20dcd7c5 100644 --- a/packages/deno/src/utils/tcp.ts +++ b/packages/deno/src/utils/tcp.ts @@ -1,7 +1,14 @@ import { connectTcp } from '@fuman/deno-net' +import type { ITcpConnection } from '@fuman/net' import { IntermediatePacketCodec, type TelegramTransport } from '@mtcute/core' +import type { BasicDcOption } from '@mtcute/core/utils.js' -export const TcpTransport: TelegramTransport = { - connect: dc => connectTcp({ address: dc.ipAddress, port: dc.port }), - packetCodec: () => new IntermediatePacketCodec(), +export class TcpTransport implements TelegramTransport { + connect(dc: BasicDcOption): Promise { + return connectTcp({ address: dc.ipAddress, port: dc.port }) + } + + packetCodec(): IntermediatePacketCodec { + return new IntermediatePacketCodec() + } } diff --git a/packages/node/src/utils/tcp.ts b/packages/node/src/utils/tcp.ts index c7a278db..9d345198 100644 --- a/packages/node/src/utils/tcp.ts +++ b/packages/node/src/utils/tcp.ts @@ -1,8 +1,15 @@ +import type { ITcpConnection } from '@fuman/net' import { connectTcp } from '@fuman/node' import type { TelegramTransport } from '@mtcute/core' import { IntermediatePacketCodec } from '@mtcute/core' +import type { BasicDcOption } from '@mtcute/core/utils.js' -export const TcpTransport: TelegramTransport = { - connect: dc => connectTcp({ address: dc.ipAddress, port: dc.port }), - packetCodec: () => new IntermediatePacketCodec(), +export class TcpTransport implements TelegramTransport { + connect(dc: BasicDcOption): Promise { + return connectTcp({ address: dc.ipAddress, port: dc.port }) + } + + packetCodec(): IntermediatePacketCodec { + return new IntermediatePacketCodec() + } } diff --git a/packages/web/src/websocket.test.ts b/packages/web/src/websocket.test.ts deleted file mode 100644 index 03feab54..00000000 --- a/packages/web/src/websocket.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -// todo: move to fuman -// import type { Mock, MockedObject } from 'vitest' -// import { describe, expect, it, vi } from 'vitest' -// import { TransportState } from '@mtcute/core' -// import { getPlatform } from '@mtcute/core/platform.js' -// import { LogManager, defaultProductionDc } from '@mtcute/core/utils.js' -// import { defaultTestCryptoProvider, u8HexDecode } from '@mtcute/test' - -// import { WebSocketTransport } from './websocket.js' - -// const p = getPlatform() - -// describe('WebSocketTransport', () => { -// const create = async () => { -// let closeListener: () => void = () => {} -// const fakeWs = vi.fn().mockImplementation(() => ({ -// addEventListener: vi.fn().mockImplementation((event: string, cb: () => void) => { -// if (event === 'open') { -// cb() -// } -// if (event === 'close') { -// closeListener = cb -// } -// }), -// removeEventListener: vi.fn(), -// close: vi.fn().mockImplementation(() => closeListener()), -// send: vi.fn(), -// })) - -// const transport = new WebSocketTransport({ ws: fakeWs }) -// const logger = new LogManager() -// logger.level = 10 -// transport.setup(await defaultTestCryptoProvider(), logger) - -// return [transport, fakeWs] as const -// } - -// const getLastSocket = (ws: Mock) => { -// return ws.mock.results[ws.mock.results.length - 1].value as MockedObject -// } - -// it('should initiate a websocket connection to the given dc', async () => { -// const [t, ws] = await create() - -// t.connect(defaultProductionDc.main, false) - -// expect(ws).toHaveBeenCalledOnce() -// expect(ws).toHaveBeenCalledWith('wss://venus.web.telegram.org/apiws', 'binary') -// await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready)) -// }) - -// it('should set up event handlers', async () => { -// const [t, ws] = await create() - -// t.connect(defaultProductionDc.main, false) -// const socket = getLastSocket(ws) - -// expect(socket.addEventListener).toHaveBeenCalledWith('message', expect.any(Function)) -// expect(socket.addEventListener).toHaveBeenCalledWith('error', expect.any(Function)) -// expect(socket.addEventListener).toHaveBeenCalledWith('close', expect.any(Function)) -// }) - -// it('should write packet codec tag to the socket', async () => { -// const [t, ws] = await create() - -// t.connect(defaultProductionDc.main, false) -// const socket = getLastSocket(ws) - -// await vi.waitFor(() => -// expect(socket.send).toHaveBeenCalledWith( -// u8HexDecode( -// '29afd26df40fb8ed10b6b4ad6d56ef5df9453f88e6ee6adb6e0544ba635dc6a8a990c9b8b980c343936b33fa7f97bae025102532233abb26d4a1fe6d34f1ba08', -// ), -// ), -// ) -// }) - -// it('should write to the underlying socket', async () => { -// const [t, ws] = await create() - -// t.connect(defaultProductionDc.main, false) -// const socket = getLastSocket(ws) -// await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready)) - -// await t.send(p.hexDecode('00010203040506070809')) - -// expect(socket.send).toHaveBeenCalledWith(u8HexDecode('af020630c8ef14bcf53af33853ea')) -// }) - -// it('should correctly close', async () => { -// const [t, ws] = await create() - -// t.connect(defaultProductionDc.main, false) -// const socket = getLastSocket(ws) -// await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready)) - -// await t.close() - -// expect(socket.close).toHaveBeenCalled() -// }) - -// it('should correctly handle incoming messages', async () => { -// const [t, ws] = await create() - -// const feedSpy = vi.spyOn(t._packetCodec, 'feed') - -// t.connect(defaultProductionDc.main, false) -// const socket = getLastSocket(ws) -// await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready)) - -// const data = p.hexDecode('00010203040506070809') -// const message = new MessageEvent('message', { data }) - -// const onMessageCall = socket.addEventListener.mock.calls.find(([event]) => event === 'message') as unknown as [ -// string, -// (evt: MessageEvent) => void, -// ] -// onMessageCall[1](message) - -// expect(feedSpy).toHaveBeenCalledWith(u8HexDecode('00010203040506070809')) -// }) - -// it('should propagate errors', async () => { -// const [t, ws] = await create() - -// const spyEmit = vi.spyOn(t, 'emit').mockImplementation(() => true) - -// t.connect(defaultProductionDc.main, false) -// const socket = getLastSocket(ws) -// await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready)) - -// const error = new Error('test') -// const onErrorCall = socket.addEventListener.mock.calls.find(([event]) => event === 'error') as unknown as [ -// string, -// (evt: { error: Error }) => void, -// ] -// onErrorCall[1]({ error }) - -// expect(spyEmit).toHaveBeenCalledWith('error', error) -// }) -// }) diff --git a/packages/web/src/websocket.ts b/packages/web/src/websocket.ts index 5b4d6eb0..80526bea 100644 --- a/packages/web/src/websocket.ts +++ b/packages/web/src/websocket.ts @@ -8,14 +8,11 @@ import { MtUnsupportedError, ObfuscatedPacketCodec, } from '@mtcute/core' -import { WebSocketConnection } from '@fuman/net' +import type { WebSocketConstructor } from '@fuman/net' +import { connectWs } from '@fuman/net' import type { BasicDcOption } from './utils' -export interface WebSocketConstructor { - new (address: string, protocol?: string): WebSocket -} - const subdomainsMap: Record = { 1: 'pluto', 2: 'venus', @@ -60,18 +57,9 @@ export class WebSocketTransport implements TelegramTransport { async connect(dc: BasicDcOption, testMode: boolean): Promise { const url = `wss://${this._subdomains[dc.id]}.${this._baseDomain}/apiws${testMode ? '_test' : ''}` - return new Promise((resolve, reject) => { - const socket = new this._WebSocket(url) - - const onError = (event: Event) => { - socket.removeEventListener('error', onError) - reject(event) - } - socket.addEventListener('error', onError) - socket.addEventListener('open', () => { - socket.removeEventListener('error', onError) - resolve(new WebSocketConnection(socket)) - }) + return connectWs({ + url, + implementation: this._WebSocket, }) }