chore!: moved away from global platform
This commit is contained in:
parent
2ac7cbd35b
commit
cb04b111a5
48 changed files with 166 additions and 211 deletions
|
@ -11,19 +11,18 @@ import {
|
||||||
BaseTelegramClient as BaseTelegramClientBase,
|
BaseTelegramClient as BaseTelegramClientBase,
|
||||||
TelegramClient as TelegramClientBase,
|
TelegramClient as TelegramClientBase,
|
||||||
} from '@mtcute/core/client.js'
|
} from '@mtcute/core/client.js'
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
|
|
||||||
import { downloadToFile } from './methods/download-file.js'
|
import { downloadToFile } from './methods/download-file.js'
|
||||||
import { downloadAsNodeStream } from './methods/download-node-stream.js'
|
import { downloadAsNodeStream } from './methods/download-node-stream.js'
|
||||||
import { BunPlatform } from './platform.js'
|
|
||||||
import { SqliteStorage } from './sqlite/index.js'
|
import { SqliteStorage } from './sqlite/index.js'
|
||||||
import { BunCryptoProvider } from './utils/crypto.js'
|
import { BunCryptoProvider } from './utils/crypto.js'
|
||||||
import { TcpTransport } from './utils/tcp.js'
|
import { TcpTransport } from './utils/tcp.js'
|
||||||
|
import { BunPlatform } from './platform.js'
|
||||||
|
|
||||||
export type { TelegramClientOptions }
|
export type { TelegramClientOptions }
|
||||||
|
|
||||||
export interface BaseTelegramClientOptions
|
export interface BaseTelegramClientOptions
|
||||||
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto'> {
|
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto' | 'platform'> {
|
||||||
/**
|
/**
|
||||||
* Storage to use for this client.
|
* Storage to use for this client.
|
||||||
*
|
*
|
||||||
|
@ -33,23 +32,14 @@ export interface BaseTelegramClientOptions
|
||||||
* @default `"client.session"`
|
* @default `"client.session"`
|
||||||
*/
|
*/
|
||||||
storage?: string | ITelegramStorageProvider
|
storage?: string | ITelegramStorageProvider
|
||||||
|
|
||||||
/**
|
|
||||||
* **ADVANCED USE ONLY**
|
|
||||||
*
|
|
||||||
* Whether to not set up the platform.
|
|
||||||
* This is useful if you call `setPlatform` yourself.
|
|
||||||
*/
|
|
||||||
platformless?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseTelegramClient extends BaseTelegramClientBase {
|
export class BaseTelegramClient extends BaseTelegramClientBase {
|
||||||
constructor(opts: BaseTelegramClientOptions) {
|
constructor(opts: BaseTelegramClientOptions) {
|
||||||
if (!opts.platformless) setPlatform(new BunPlatform())
|
|
||||||
|
|
||||||
super({
|
super({
|
||||||
crypto: new BunCryptoProvider(),
|
crypto: new BunCryptoProvider(),
|
||||||
transport: TcpTransport,
|
transport: TcpTransport,
|
||||||
|
platform: new BunPlatform(),
|
||||||
...opts,
|
...opts,
|
||||||
storage:
|
storage:
|
||||||
typeof opts.storage === 'string'
|
typeof opts.storage === 'string'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { afterAll, beforeAll, describe } from 'vitest'
|
import { afterAll, beforeAll, describe } from 'vitest'
|
||||||
import { LogManager } from '@mtcute/core/utils.js'
|
import { LogManager } from '@mtcute/core/utils.js'
|
||||||
import {
|
import {
|
||||||
|
defaultPlatform,
|
||||||
testAuthKeysRepository,
|
testAuthKeysRepository,
|
||||||
testKeyValueRepository,
|
testKeyValueRepository,
|
||||||
testPeersRepository,
|
testPeersRepository,
|
||||||
|
@ -14,7 +15,7 @@ if (import.meta.env.TEST_ENV === 'bun') {
|
||||||
const storage = new SqliteStorage(':memory:')
|
const storage = new SqliteStorage(':memory:')
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
storage.driver.setup(new LogManager())
|
storage.driver.setup(new LogManager(undefined, defaultPlatform), defaultPlatform)
|
||||||
await storage.driver.load()
|
await storage.driver.load()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import { Worker, parentPort } from 'node:worker_threads'
|
import { Worker, parentPort } from 'node:worker_threads'
|
||||||
|
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
import type {
|
import type {
|
||||||
ClientMessageHandler,
|
ClientMessageHandler,
|
||||||
RespondFn,
|
RespondFn,
|
||||||
SendFn,
|
SendFn,
|
||||||
SomeWorker,
|
SomeWorker,
|
||||||
TelegramWorkerOptions,
|
TelegramWorkerOptions,
|
||||||
TelegramWorkerPortOptions,
|
|
||||||
WorkerCustomMethods,
|
WorkerCustomMethods,
|
||||||
WorkerMessageHandler,
|
WorkerMessageHandler,
|
||||||
} from '@mtcute/core/worker.js'
|
} from '@mtcute/core/worker.js'
|
||||||
|
@ -16,9 +14,13 @@ import {
|
||||||
TelegramWorkerPort as TelegramWorkerPortBase,
|
TelegramWorkerPort as TelegramWorkerPortBase,
|
||||||
} from '@mtcute/core/worker.js'
|
} from '@mtcute/core/worker.js'
|
||||||
|
|
||||||
import { BunPlatform } from './platform.js'
|
import { BunPlatform } from './platform'
|
||||||
|
|
||||||
export type { TelegramWorkerOptions, TelegramWorkerPortOptions, WorkerCustomMethods }
|
export type { TelegramWorkerOptions, WorkerCustomMethods }
|
||||||
|
|
||||||
|
export interface TelegramWorkerPortOptions {
|
||||||
|
worker: SomeWorker
|
||||||
|
}
|
||||||
|
|
||||||
let _registered = false
|
let _registered = false
|
||||||
|
|
||||||
|
@ -45,9 +47,11 @@ export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorke
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
||||||
constructor(readonly options: TelegramWorkerPortOptions) {
|
constructor(options: TelegramWorkerPortOptions) {
|
||||||
setPlatform(new BunPlatform())
|
super({
|
||||||
super(options)
|
worker: options.worker,
|
||||||
|
platform: new BunPlatform(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mtcute/core": "workspace:^",
|
"@mtcute/core": "workspace:^",
|
||||||
"@fuman/utils": "workspace:^",
|
"@fuman/utils": "workspace:^",
|
||||||
"@fuman/ip": "workspace:^"
|
"@fuman/net": "workspace:^"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@mtcute/test": "workspace:^"
|
"@mtcute/test": "workspace:^"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { MtArgumentError } from '@mtcute/core'
|
import { MtArgumentError } from '@mtcute/core'
|
||||||
import { base64, typed } from '@fuman/utils'
|
import { base64, typed } from '@fuman/utils'
|
||||||
import { ip } from '@fuman/ip'
|
import { ip } from '@fuman/net'
|
||||||
|
|
||||||
import type { TelethonSession } from './types.js'
|
import type { TelethonSession } from './types.js'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { MtArgumentError } from '@mtcute/core'
|
import { MtArgumentError } from '@mtcute/core'
|
||||||
import { base64, typed } from '@fuman/utils'
|
import { base64, typed } from '@fuman/utils'
|
||||||
import { ip } from '@fuman/ip'
|
import { ip } from '@fuman/net'
|
||||||
|
|
||||||
import type { TelethonSession } from './types.js'
|
import type { TelethonSession } from './types.js'
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
"./utils.js": "./src/utils/index.ts",
|
"./utils.js": "./src/utils/index.ts",
|
||||||
"./client.js": "./src/highlevel/client.ts",
|
"./client.js": "./src/highlevel/client.ts",
|
||||||
"./worker.js": "./src/highlevel/worker/index.ts",
|
"./worker.js": "./src/highlevel/worker/index.ts",
|
||||||
"./methods.js": "./src/highlevel/methods.ts",
|
"./methods.js": "./src/highlevel/methods.ts"
|
||||||
"./platform.js": "./src/platform.ts"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm run -w build-package core",
|
"build": "pnpm run -w build-package core",
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
writeStringSession,
|
writeStringSession,
|
||||||
} from '../utils/index.js'
|
} from '../utils/index.js'
|
||||||
import { LogManager } from '../utils/logger.js'
|
import { LogManager } from '../utils/logger.js'
|
||||||
|
import type { ICorePlatform } from '../types/platform'
|
||||||
|
|
||||||
import type { ConnectionState, ITelegramClient, ServerUpdateHandler } from './client.types.js'
|
import type { ConnectionState, ITelegramClient, ServerUpdateHandler } from './client.types.js'
|
||||||
import { AppConfigManager } from './managers/app-config-manager.js'
|
import { AppConfigManager } from './managers/app-config-manager.js'
|
||||||
|
@ -57,9 +58,11 @@ export class BaseTelegramClient implements ITelegramClient {
|
||||||
readonly mt: MtClient
|
readonly mt: MtClient
|
||||||
readonly crypto: ICryptoProvider
|
readonly crypto: ICryptoProvider
|
||||||
readonly storage: TelegramStorageManager
|
readonly storage: TelegramStorageManager
|
||||||
|
readonly platform: ICorePlatform
|
||||||
|
|
||||||
constructor(readonly params: BaseTelegramClientOptions) {
|
constructor(readonly params: BaseTelegramClientOptions) {
|
||||||
this.log = this.params.logger ?? new LogManager('client')
|
this.log = this.params.logger ?? new LogManager('client', params.platform)
|
||||||
|
this.platform = this.params.platform
|
||||||
this.mt = new MtClient({
|
this.mt = new MtClient({
|
||||||
...this.params,
|
...this.params,
|
||||||
logger: this.log.create('mtproto'),
|
logger: this.log.create('mtproto'),
|
||||||
|
@ -238,11 +241,12 @@ export class BaseTelegramClient implements ITelegramClient {
|
||||||
if (defaultDcAuthKey && !force) return
|
if (defaultDcAuthKey && !force) return
|
||||||
|
|
||||||
const data = typeof session === 'string' ? readStringSession(session) : session
|
const data = typeof session === 'string' ? readStringSession(session) : session
|
||||||
|
const testMode = data.primaryDcs.main.testMode
|
||||||
|
|
||||||
if (data.testMode && !this.params.testMode) {
|
if (testMode && !this.params.testMode) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'This session string is not for the current backend. '
|
'This session string is not for the current backend. '
|
||||||
+ `Session is ${data.testMode ? 'test' : 'prod'}, `
|
+ `Session is ${testMode ? 'test' : 'prod'}, `
|
||||||
+ `but the client is ${this.params.testMode ? 'test' : 'prod'}`,
|
+ `but the client is ${this.params.testMode ? 'test' : 'prod'}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -285,7 +289,6 @@ export class BaseTelegramClient implements ITelegramClient {
|
||||||
return writeStringSession({
|
return writeStringSession({
|
||||||
version: 3,
|
version: 3,
|
||||||
self: await this.storage.self.fetch(),
|
self: await this.storage.self.fetch(),
|
||||||
testMode: Boolean(this.params.testMode),
|
|
||||||
primaryDcs,
|
primaryDcs,
|
||||||
authKey,
|
authKey,
|
||||||
})
|
})
|
||||||
|
|
|
@ -281,7 +281,7 @@ import { withParams } from './methods/misc/with-params.js'
|
||||||
// from methods/_init.ts
|
// from methods/_init.ts
|
||||||
// @copy
|
// @copy
|
||||||
type TelegramClientOptions = (
|
type TelegramClientOptions = (
|
||||||
| (PartialOnly<Omit<BaseTelegramClientOptions, 'storage'>, 'transport' | 'crypto'> & {
|
| (PartialOnly<Omit<BaseTelegramClientOptions, 'storage'>, 'transport' | 'crypto' | 'platform'> & {
|
||||||
/**
|
/**
|
||||||
* Storage to use for this client.
|
* Storage to use for this client.
|
||||||
*
|
*
|
||||||
|
|
|
@ -4,6 +4,7 @@ import type Long from 'long'
|
||||||
import type { ConnectionKind, RpcCallOptions } from '../network/index.js'
|
import type { ConnectionKind, RpcCallOptions } from '../network/index.js'
|
||||||
import type { MustEqual, PublicPart } from '../types/utils.js'
|
import type { MustEqual, PublicPart } from '../types/utils.js'
|
||||||
import type { Logger } from '../utils/logger.js'
|
import type { Logger } from '../utils/logger.js'
|
||||||
|
import type { ICorePlatform } from '../types/platform'
|
||||||
|
|
||||||
import type { AppConfigManager } from './managers/app-config-manager.js'
|
import type { AppConfigManager } from './managers/app-config-manager.js'
|
||||||
import type { TelegramStorageManager } from './storage/storage.js'
|
import type { TelegramStorageManager } from './storage/storage.js'
|
||||||
|
@ -35,6 +36,7 @@ export interface ITelegramClient {
|
||||||
readonly storage: PublicPart<TelegramStorageManager>
|
readonly storage: PublicPart<TelegramStorageManager>
|
||||||
readonly appConfig: PublicPart<AppConfigManager>
|
readonly appConfig: PublicPart<AppConfigManager>
|
||||||
readonly stopSignal: AbortSignal
|
readonly stopSignal: AbortSignal
|
||||||
|
readonly platform: ICorePlatform
|
||||||
|
|
||||||
prepare(): Promise<void>
|
prepare(): Promise<void>
|
||||||
connect(): Promise<void>
|
connect(): Promise<void>
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { makeParsedUpdateHandler } from '../updates/parsed.js'
|
||||||
|
|
||||||
// @copy
|
// @copy
|
||||||
type TelegramClientOptions = (
|
type TelegramClientOptions = (
|
||||||
| (PartialOnly<Omit<BaseTelegramClientOptions, 'storage'>, 'transport' | 'crypto'> & {
|
| (PartialOnly<Omit<BaseTelegramClientOptions, 'storage'>, 'transport' | 'crypto' | 'platform'> & {
|
||||||
/**
|
/**
|
||||||
* Storage to use for this client.
|
* Storage to use for this client.
|
||||||
*
|
*
|
||||||
|
|
|
@ -2,7 +2,6 @@ import Long from 'long'
|
||||||
import { parseFileId, tdFileId } from '@mtcute/file-id'
|
import { parseFileId, tdFileId } from '@mtcute/file-id'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
import { getPlatform } from '../../../platform.js'
|
|
||||||
import { assertTypeIs } from '../../../utils/type-assertions.js'
|
import { assertTypeIs } from '../../../utils/type-assertions.js'
|
||||||
import type { ITelegramClient } from '../../client.types.js'
|
import type { ITelegramClient } from '../../client.types.js'
|
||||||
import { isUploadedFile } from '../../types/files/uploaded-file.js'
|
import { isUploadedFile } from '../../types/files/uploaded-file.js'
|
||||||
|
@ -321,7 +320,7 @@ export async function _normalizeInputMedia(
|
||||||
} else if (typeof input === 'string' && input.match(/^file:/)) {
|
} else if (typeof input === 'string' && input.match(/^file:/)) {
|
||||||
await upload(input.substring(5))
|
await upload(input.substring(5))
|
||||||
} else {
|
} else {
|
||||||
const parsed = typeof input === 'string' ? parseFileId(getPlatform(), input) : input
|
const parsed = typeof input === 'string' ? parseFileId(input) : input
|
||||||
|
|
||||||
if (parsed.location._ === 'photo') {
|
if (parsed.location._ === 'photo') {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -3,7 +3,6 @@ import type { IReadable } from '@fuman/io'
|
||||||
import { read } from '@fuman/io'
|
import { read } from '@fuman/io'
|
||||||
import { AsyncLock } from '@fuman/utils'
|
import { AsyncLock } from '@fuman/utils'
|
||||||
|
|
||||||
import { getPlatform } from '../../../platform.js'
|
|
||||||
import { MtArgumentError } from '../../../types/errors.js'
|
import { MtArgumentError } from '../../../types/errors.js'
|
||||||
import { randomLong } from '../../../utils/long-utils.js'
|
import { randomLong } from '../../../utils/long-utils.js'
|
||||||
import type { ITelegramClient } from '../../client.types.js'
|
import type { ITelegramClient } from '../../client.types.js'
|
||||||
|
@ -111,10 +110,8 @@ export async function uploadFile(
|
||||||
let fileName = params.fileName
|
let fileName = params.fileName
|
||||||
let fileMime = params.fileMime
|
let fileMime = params.fileMime
|
||||||
|
|
||||||
const platform = getPlatform()
|
if (client.platform.normalizeFile) {
|
||||||
|
const res = await client.platform.normalizeFile(file)
|
||||||
if (platform.normalizeFile) {
|
|
||||||
const res = await platform.normalizeFile(file)
|
|
||||||
|
|
||||||
if (res?.file) {
|
if (res?.file) {
|
||||||
file = res.file
|
file = res.file
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
||||||
import type { tl } from '@mtcute/tl'
|
import type { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
import { getPlatform } from '../../../platform.js'
|
|
||||||
import { makeInspectable } from '../../utils/index.js'
|
import { makeInspectable } from '../../utils/index.js'
|
||||||
import { memoizeGetters } from '../../utils/memoize.js'
|
import { memoizeGetters } from '../../utils/memoize.js'
|
||||||
import { FileLocation } from '../files/index.js'
|
import { FileLocation } from '../files/index.js'
|
||||||
|
@ -125,7 +124,7 @@ export abstract class RawDocument extends FileLocation {
|
||||||
* representing this document.
|
* representing this document.
|
||||||
*/
|
*/
|
||||||
get fileId(): string {
|
get fileId(): string {
|
||||||
return toFileId(getPlatform(), {
|
return toFileId({
|
||||||
type: this._fileIdType(),
|
type: this._fileIdType(),
|
||||||
dcId: this.raw.dcId,
|
dcId: this.raw.dcId,
|
||||||
fileReference: this.raw.fileReference,
|
fileReference: this.raw.fileReference,
|
||||||
|
@ -141,7 +140,7 @@ export abstract class RawDocument extends FileLocation {
|
||||||
* Get a unique File ID representing this document.
|
* Get a unique File ID representing this document.
|
||||||
*/
|
*/
|
||||||
get uniqueFileId(): string {
|
get uniqueFileId(): string {
|
||||||
return toUniqueFileId(getPlatform(), td.FileType.Document, {
|
return toUniqueFileId(td.FileType.Document, {
|
||||||
_: 'common',
|
_: 'common',
|
||||||
id: this.raw.id,
|
id: this.raw.id,
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,7 +2,6 @@ import Long from 'long'
|
||||||
import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
||||||
import type { tl } from '@mtcute/tl'
|
import type { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
import { getPlatform } from '../../../platform.js'
|
|
||||||
import { MtArgumentError, MtTypeAssertionError } from '../../../types/errors.js'
|
import { MtArgumentError, MtTypeAssertionError } from '../../../types/errors.js'
|
||||||
import { assertTypeIs } from '../../../utils/type-assertions.js'
|
import { assertTypeIs } from '../../../utils/type-assertions.js'
|
||||||
import { inflateSvgPath, strippedPhotoToJpg, svgPathToFile } from '../../utils/file-utils.js'
|
import { inflateSvgPath, strippedPhotoToJpg, svgPathToFile } from '../../utils/file-utils.js'
|
||||||
|
@ -204,7 +203,7 @@ export class Thumbnail extends FileLocation {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._media._ === 'stickerSet') {
|
if (this._media._ === 'stickerSet') {
|
||||||
return toFileId(getPlatform(), {
|
return toFileId({
|
||||||
type: td.FileType.Thumbnail,
|
type: td.FileType.Thumbnail,
|
||||||
dcId: this.dcId!,
|
dcId: this.dcId!,
|
||||||
fileReference: null,
|
fileReference: null,
|
||||||
|
@ -222,7 +221,7 @@ export class Thumbnail extends FileLocation {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return toFileId(getPlatform(), {
|
return toFileId({
|
||||||
type: this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail,
|
type: this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail,
|
||||||
dcId: this.dcId!,
|
dcId: this.dcId!,
|
||||||
fileReference: this._media.fileReference,
|
fileReference: this._media.fileReference,
|
||||||
|
@ -251,7 +250,7 @@ export class Thumbnail extends FileLocation {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._media._ === 'stickerSet') {
|
if (this._media._ === 'stickerSet') {
|
||||||
return toUniqueFileId(getPlatform(), td.FileType.Thumbnail, {
|
return toUniqueFileId(td.FileType.Thumbnail, {
|
||||||
_: 'photo',
|
_: 'photo',
|
||||||
id: Long.ZERO,
|
id: Long.ZERO,
|
||||||
source: {
|
source: {
|
||||||
|
@ -263,7 +262,7 @@ export class Thumbnail extends FileLocation {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return toUniqueFileId(getPlatform(), this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail, {
|
return toUniqueFileId(this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail, {
|
||||||
_: 'photo',
|
_: 'photo',
|
||||||
id: this._media.id,
|
id: this._media.id,
|
||||||
source: {
|
source: {
|
||||||
|
|
|
@ -2,7 +2,6 @@ import Long from 'long'
|
||||||
import { tdFileId, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
import { tdFileId, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
||||||
import type { tl } from '@mtcute/tl'
|
import type { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
import { getPlatform } from '../../../platform.js'
|
|
||||||
import { MtArgumentError } from '../../../types/errors.js'
|
import { MtArgumentError } from '../../../types/errors.js'
|
||||||
import { toggleChannelIdMark } from '../../../utils/peer-utils.js'
|
import { toggleChannelIdMark } from '../../../utils/peer-utils.js'
|
||||||
import { strippedPhotoToJpg } from '../../utils/file-utils.js'
|
import { strippedPhotoToJpg } from '../../utils/file-utils.js'
|
||||||
|
@ -62,7 +61,7 @@ export class ChatPhotoSize extends FileLocation {
|
||||||
throw new MtArgumentError('Input peer was invalid')
|
throw new MtArgumentError('Input peer was invalid')
|
||||||
}
|
}
|
||||||
|
|
||||||
return toFileId(getPlatform(), {
|
return toFileId({
|
||||||
dcId: this.obj.dcId,
|
dcId: this.obj.dcId,
|
||||||
type: tdFileId.FileType.ProfilePhoto,
|
type: tdFileId.FileType.ProfilePhoto,
|
||||||
fileReference: null,
|
fileReference: null,
|
||||||
|
@ -84,7 +83,7 @@ export class ChatPhotoSize extends FileLocation {
|
||||||
* TDLib and Bot API compatible unique File ID representing this size
|
* TDLib and Bot API compatible unique File ID representing this size
|
||||||
*/
|
*/
|
||||||
get uniqueFileId(): string {
|
get uniqueFileId(): string {
|
||||||
return toUniqueFileId(getPlatform(), tdFileId.FileType.ProfilePhoto, {
|
return toUniqueFileId(tdFileId.FileType.ProfilePhoto, {
|
||||||
_: 'photo',
|
_: 'photo',
|
||||||
id: this.obj.photoId,
|
id: this.obj.photoId,
|
||||||
// eslint-disable-next-line ts/no-unsafe-assignment
|
// eslint-disable-next-line ts/no-unsafe-assignment
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { parseFileId, tdFileId as td } from '@mtcute/file-id'
|
||||||
import type { tl } from '@mtcute/tl'
|
import type { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
import { parseMarkedPeerId } from '../../utils/peer-utils.js'
|
import { parseMarkedPeerId } from '../../utils/peer-utils.js'
|
||||||
import { getPlatform } from '../../platform.js'
|
|
||||||
import { assertNever } from '../../types/utils.js'
|
import { assertNever } from '../../types/utils.js'
|
||||||
|
|
||||||
import FileType = td.FileType
|
import FileType = td.FileType
|
||||||
|
@ -45,7 +44,7 @@ function dialogPhotoToInputPeer(
|
||||||
* @param fileId File ID, either parsed or as a string
|
* @param fileId File ID, either parsed or as a string
|
||||||
*/
|
*/
|
||||||
export function fileIdToInputWebFileLocation(fileId: string | FileId): tl.RawInputWebFileLocation {
|
export function fileIdToInputWebFileLocation(fileId: string | FileId): tl.RawInputWebFileLocation {
|
||||||
if (typeof fileId === 'string') fileId = parseFileId(getPlatform(), fileId)
|
if (typeof fileId === 'string') fileId = parseFileId(fileId)
|
||||||
|
|
||||||
if (fileId.location._ !== 'web') {
|
if (fileId.location._ !== 'web') {
|
||||||
throw new td.ConversionError('inputWebFileLocation')
|
throw new td.ConversionError('inputWebFileLocation')
|
||||||
|
@ -65,7 +64,7 @@ export function fileIdToInputWebFileLocation(fileId: string | FileId): tl.RawInp
|
||||||
* @param fileId File ID, either parsed or as a string
|
* @param fileId File ID, either parsed or as a string
|
||||||
*/
|
*/
|
||||||
export function fileIdToInputFileLocation(fileId: string | FileId): tl.TypeInputFileLocation {
|
export function fileIdToInputFileLocation(fileId: string | FileId): tl.TypeInputFileLocation {
|
||||||
if (typeof fileId === 'string') fileId = parseFileId(getPlatform(), fileId)
|
if (typeof fileId === 'string') fileId = parseFileId(fileId)
|
||||||
|
|
||||||
const loc = fileId.location
|
const loc = fileId.location
|
||||||
|
|
||||||
|
@ -219,7 +218,7 @@ export function fileIdToInputFileLocation(fileId: string | FileId): tl.TypeInput
|
||||||
* @param fileId File ID, either parsed or as a string
|
* @param fileId File ID, either parsed or as a string
|
||||||
*/
|
*/
|
||||||
export function fileIdToInputDocument(fileId: string | FileId): tl.RawInputDocument {
|
export function fileIdToInputDocument(fileId: string | FileId): tl.RawInputDocument {
|
||||||
if (typeof fileId === 'string') fileId = parseFileId(getPlatform(), fileId)
|
if (typeof fileId === 'string') fileId = parseFileId(fileId)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
fileId.location._ !== 'common'
|
fileId.location._ !== 'common'
|
||||||
|
@ -256,7 +255,7 @@ export function fileIdToInputDocument(fileId: string | FileId): tl.RawInputDocum
|
||||||
* @param fileId File ID, either parsed or as a string
|
* @param fileId File ID, either parsed or as a string
|
||||||
*/
|
*/
|
||||||
export function fileIdToInputPhoto(fileId: string | FileId): tl.RawInputPhoto {
|
export function fileIdToInputPhoto(fileId: string | FileId): tl.RawInputPhoto {
|
||||||
if (typeof fileId === 'string') fileId = parseFileId(getPlatform(), fileId)
|
if (typeof fileId === 'string') fileId = parseFileId(fileId)
|
||||||
|
|
||||||
if (fileId.location._ !== 'photo') {
|
if (fileId.location._ !== 'photo') {
|
||||||
throw new td.ConversionError('inputPhoto')
|
throw new td.ConversionError('inputPhoto')
|
||||||
|
@ -281,7 +280,7 @@ export function fileIdToInputPhoto(fileId: string | FileId): tl.RawInputPhoto {
|
||||||
* @param fileId File ID, either parsed or as a string
|
* @param fileId File ID, either parsed or as a string
|
||||||
*/
|
*/
|
||||||
export function fileIdToEncryptedFile(fileId: string | FileId): tl.RawInputEncryptedFile {
|
export function fileIdToEncryptedFile(fileId: string | FileId): tl.RawInputEncryptedFile {
|
||||||
if (typeof fileId === 'string') fileId = parseFileId(getPlatform(), fileId)
|
if (typeof fileId === 'string') fileId = parseFileId(fileId)
|
||||||
|
|
||||||
if (fileId.location._ !== 'common' || fileId.type !== FileType.Encrypted) {
|
if (fileId.location._ !== 'common' || fileId.type !== FileType.Encrypted) {
|
||||||
throw new td.ConversionError('inputEncryptedFile')
|
throw new td.ConversionError('inputEncryptedFile')
|
||||||
|
@ -301,7 +300,7 @@ export function fileIdToEncryptedFile(fileId: string | FileId): tl.RawInputEncry
|
||||||
* @param fileId File ID, either parsed or as a string
|
* @param fileId File ID, either parsed or as a string
|
||||||
*/
|
*/
|
||||||
export function fileIdToSecureFile(fileId: string | FileId): tl.RawInputSecureFile {
|
export function fileIdToSecureFile(fileId: string | FileId): tl.RawInputSecureFile {
|
||||||
if (typeof fileId === 'string') fileId = parseFileId(getPlatform(), fileId)
|
if (typeof fileId === 'string') fileId = parseFileId(fileId)
|
||||||
|
|
||||||
if (fileId.location._ !== 'common' || (fileId.type !== FileType.Secure && fileId.type !== FileType.SecureRaw)) {
|
if (fileId.location._ !== 'common' || (fileId.type !== FileType.Secure && fileId.type !== FileType.SecureRaw)) {
|
||||||
throw new td.ConversionError('inputSecureFile')
|
throw new td.ConversionError('inputSecureFile')
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import { StubTelegramClient } from '@mtcute/test'
|
import { StubTelegramClient } from '@mtcute/test'
|
||||||
|
import { sleep } from '@fuman/utils'
|
||||||
|
|
||||||
import { sleep } from '../../utils/misc-utils.js'
|
|
||||||
import type { ITelegramClient } from '../client.types.js'
|
import type { ITelegramClient } from '../client.types.js'
|
||||||
|
|
||||||
import { batchedQuery } from './query-batcher.js'
|
import { batchedQuery } from './query-batcher.js'
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { LogManager } from '../../utils/logger.js'
|
||||||
import type { ConnectionState, ITelegramClient, ServerUpdateHandler } from '../client.types.js'
|
import type { ConnectionState, ITelegramClient, ServerUpdateHandler } from '../client.types.js'
|
||||||
import { PeersIndex } from '../types/peers/peers-index.js'
|
import { PeersIndex } from '../types/peers/peers-index.js'
|
||||||
import type { RawUpdateHandler } from '../updates/types.js'
|
import type { RawUpdateHandler } from '../updates/types.js'
|
||||||
|
import type { ICorePlatform } from '../../types/platform'
|
||||||
|
|
||||||
import { AppConfigManagerProxy } from './app-config.js'
|
import { AppConfigManagerProxy } from './app-config.js'
|
||||||
import { WorkerInvoker } from './invoker.js'
|
import { WorkerInvoker } from './invoker.js'
|
||||||
|
@ -15,10 +16,12 @@ import { TelegramStorageProxy } from './storage.js'
|
||||||
|
|
||||||
export interface TelegramWorkerPortOptions {
|
export interface TelegramWorkerPortOptions {
|
||||||
worker: SomeWorker
|
worker: SomeWorker
|
||||||
|
platform: ICorePlatform
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class TelegramWorkerPort<Custom extends WorkerCustomMethods> implements ITelegramClient {
|
export abstract class TelegramWorkerPort<Custom extends WorkerCustomMethods> implements ITelegramClient {
|
||||||
readonly log: LogManager
|
readonly log: LogManager
|
||||||
|
readonly platform: ICorePlatform
|
||||||
|
|
||||||
private _connection
|
private _connection
|
||||||
private _invoker
|
private _invoker
|
||||||
|
@ -51,7 +54,8 @@ export abstract class TelegramWorkerPort<Custom extends WorkerCustomMethods> imp
|
||||||
readonly stopSignal: AbortSignal = this._abortController.signal
|
readonly stopSignal: AbortSignal = this._abortController.signal
|
||||||
|
|
||||||
constructor(readonly options: TelegramWorkerPortOptions) {
|
constructor(readonly options: TelegramWorkerPortOptions) {
|
||||||
this.log = new LogManager('worker')
|
this.log = new LogManager('worker', options.platform)
|
||||||
|
this.platform = options.platform
|
||||||
|
|
||||||
this._connection = this.connectToWorker(this.options.worker, this._onMessage)
|
this._connection = this.connectToWorker(this.options.worker, this._onMessage)
|
||||||
this._invoker = new WorkerInvoker(this._connection[0])
|
this._invoker = new WorkerInvoker(this._connection[0])
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Long from 'long'
|
import Long from 'long'
|
||||||
import { describe, expect, it, vi } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
import { defaultTestCryptoProvider } from '@mtcute/test'
|
import { defaultPlatform, defaultTestCryptoProvider } from '@mtcute/test'
|
||||||
import type { TlBinaryReader, TlReaderMap } from '@mtcute/tl-runtime'
|
import type { TlBinaryReader, TlReaderMap } from '@mtcute/tl-runtime'
|
||||||
import { hex, utf8 } from '@fuman/utils'
|
import { hex, utf8 } from '@fuman/utils'
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ for (let i = 0; i < 256; i += 32) {
|
||||||
|
|
||||||
describe('AuthKey', () => {
|
describe('AuthKey', () => {
|
||||||
async function create() {
|
async function create() {
|
||||||
const logger = new LogManager()
|
const logger = new LogManager(undefined, defaultPlatform)
|
||||||
const readerMap: TlReaderMap = {}
|
const readerMap: TlReaderMap = {}
|
||||||
const crypto = await defaultTestCryptoProvider()
|
const crypto = await defaultTestCryptoProvider()
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
defaultTestIpv6Dc,
|
defaultTestIpv6Dc,
|
||||||
isTlRpcError,
|
isTlRpcError,
|
||||||
} from '../utils/index.js'
|
} from '../utils/index.js'
|
||||||
|
import type { ICorePlatform } from '../types/platform.js'
|
||||||
|
|
||||||
import { ConfigManager } from './config-manager.js'
|
import { ConfigManager } from './config-manager.js'
|
||||||
import type { NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js'
|
import type { NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js'
|
||||||
|
@ -57,6 +58,8 @@ export interface MtClientOptions {
|
||||||
*/
|
*/
|
||||||
crypto: ICryptoProvider
|
crypto: ICryptoProvider
|
||||||
|
|
||||||
|
platform: ICorePlatform
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to use IPv6 datacenters
|
* Whether to use IPv6 datacenters
|
||||||
* (IPv6 will be preferred when choosing a DC by id)
|
* (IPv6 will be preferred when choosing a DC by id)
|
||||||
|
@ -223,7 +226,7 @@ export class MtClient extends EventEmitter {
|
||||||
constructor(readonly params: MtClientOptions) {
|
constructor(readonly params: MtClientOptions) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this.log = params.logger ?? new LogManager()
|
this.log = params.logger ?? new LogManager(undefined, params.platform)
|
||||||
|
|
||||||
if (params.logLevel !== undefined) {
|
if (params.logLevel !== undefined) {
|
||||||
this.log.mgr.level = params.logLevel
|
this.log.mgr.level = params.logLevel
|
||||||
|
@ -256,6 +259,7 @@ export class MtClient extends EventEmitter {
|
||||||
log: this.log,
|
log: this.log,
|
||||||
readerMap: this._readerMap,
|
readerMap: this._readerMap,
|
||||||
writerMap: this._writerMap,
|
writerMap: this._writerMap,
|
||||||
|
platform: params.platform,
|
||||||
...params.storageOptions,
|
...params.storageOptions,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -282,6 +286,7 @@ export class MtClient extends EventEmitter {
|
||||||
onNetworkChanged: connected => this.emit('networkChanged', connected),
|
onNetworkChanged: connected => this.emit('networkChanged', connected),
|
||||||
onUpdate: upd => this.emit('update', upd),
|
onUpdate: upd => this.emit('update', upd),
|
||||||
stopSignal: this.stopSignal,
|
stopSignal: this.stopSignal,
|
||||||
|
platform: params.platform,
|
||||||
...params.network,
|
...params.network,
|
||||||
},
|
},
|
||||||
this._config,
|
this._config,
|
||||||
|
|
|
@ -4,13 +4,13 @@ import type Long from 'long'
|
||||||
import { type ReconnectionStrategy, defaultReconnectionStrategy } from '@fuman/net'
|
import { type ReconnectionStrategy, defaultReconnectionStrategy } from '@fuman/net'
|
||||||
import { Deferred } from '@fuman/utils'
|
import { Deferred } from '@fuman/utils'
|
||||||
|
|
||||||
import { getPlatform } from '../platform.js'
|
|
||||||
import type { StorageManager } from '../storage/storage.js'
|
import type { StorageManager } from '../storage/storage.js'
|
||||||
import { MtArgumentError, MtUnsupportedError, MtcuteError } from '../types/index.js'
|
import { MtArgumentError, MtUnsupportedError, MtcuteError } from '../types/index.js'
|
||||||
import type { ComposedMiddleware, Middleware } from '../utils/composer.js'
|
import type { ComposedMiddleware, Middleware } from '../utils/composer.js'
|
||||||
import { composeMiddlewares } from '../utils/composer.js'
|
import { composeMiddlewares } from '../utils/composer.js'
|
||||||
import type { DcOptions, ICryptoProvider, Logger } from '../utils/index.js'
|
import type { DcOptions, ICryptoProvider, Logger } from '../utils/index.js'
|
||||||
import { assertTypeIs, isTlRpcError } from '../utils/type-assertions.js'
|
import { assertTypeIs, isTlRpcError } from '../utils/type-assertions.js'
|
||||||
|
import type { ICorePlatform } from '../types/platform'
|
||||||
|
|
||||||
import type { ConfigManager } from './config-manager.js'
|
import type { ConfigManager } from './config-manager.js'
|
||||||
import { basic as defaultMiddlewares } from './middlewares/default.js'
|
import { basic as defaultMiddlewares } from './middlewares/default.js'
|
||||||
|
@ -29,6 +29,7 @@ export interface NetworkManagerParams {
|
||||||
storage: StorageManager
|
storage: StorageManager
|
||||||
crypto: ICryptoProvider
|
crypto: ICryptoProvider
|
||||||
log: Logger
|
log: Logger
|
||||||
|
platform: ICorePlatform
|
||||||
|
|
||||||
enableErrorReporting: boolean
|
enableErrorReporting: boolean
|
||||||
apiId: number
|
apiId: number
|
||||||
|
@ -253,6 +254,7 @@ export class DcConnectionManager {
|
||||||
inactivityTimeout: this.manager.params.inactivityTimeout ?? 60_000,
|
inactivityTimeout: this.manager.params.inactivityTimeout ?? 60_000,
|
||||||
enableErrorReporting: this.manager.params.enableErrorReporting,
|
enableErrorReporting: this.manager.params.enableErrorReporting,
|
||||||
salts: this._salts,
|
salts: this._salts,
|
||||||
|
platform: this.manager.params.platform,
|
||||||
})
|
})
|
||||||
|
|
||||||
const mainParams = baseConnectionParams()
|
const mainParams = baseConnectionParams()
|
||||||
|
@ -485,7 +487,7 @@ export class NetworkManager {
|
||||||
readonly params: NetworkManagerParams & NetworkManagerExtraParams,
|
readonly params: NetworkManagerParams & NetworkManagerExtraParams,
|
||||||
readonly config: ConfigManager,
|
readonly config: ConfigManager,
|
||||||
) {
|
) {
|
||||||
const deviceModel = `mtcute on ${getPlatform().getDeviceModel()}`
|
const deviceModel = `mtcute on ${params.platform.getDeviceModel()}`
|
||||||
|
|
||||||
this._initConnectionParams = {
|
this._initConnectionParams = {
|
||||||
_: 'initConnection',
|
_: 'initConnection',
|
||||||
|
@ -616,7 +618,7 @@ export class NetworkManager {
|
||||||
throw new MtArgumentError('DC manager already exists')
|
throw new MtArgumentError('DC manager already exists')
|
||||||
}
|
}
|
||||||
|
|
||||||
this._resetOnNetworkChange = getPlatform().onNetworkChanged?.(this.notifyNetworkChanged.bind(this))
|
this._resetOnNetworkChange = this.params.platform.onNetworkChanged?.(this.notifyNetworkChanged.bind(this))
|
||||||
|
|
||||||
const dc = new DcConnectionManager(this, defaultDcs.main.id, defaultDcs, true)
|
const dc = new DcConnectionManager(this, defaultDcs.main.id, defaultDcs, true)
|
||||||
this._dcConnections.set(defaultDcs.main.id, dc)
|
this._dcConnections.set(defaultDcs.main.id, dc)
|
||||||
|
|
|
@ -149,6 +149,8 @@ export abstract class PersistentConnection extends EventEmitter {
|
||||||
private async _onError(err: Error) {
|
private async _onError(err: Error) {
|
||||||
this._updateLogPrefix()
|
this._updateLogPrefix()
|
||||||
this.onError(err)
|
this.onError(err)
|
||||||
|
|
||||||
|
return 'reconnect' as const
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeTransport(transport: TelegramTransport): Promise<void> {
|
async changeTransport(transport: TelegramTransport): Promise<void> {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import type { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'
|
||||||
import { TlBinaryReader, TlBinaryWriter, TlSerializationCounter } from '@mtcute/tl-runtime'
|
import { TlBinaryReader, TlBinaryWriter, TlSerializationCounter } from '@mtcute/tl-runtime'
|
||||||
import { Deferred, u8 } from '@fuman/utils'
|
import { Deferred, u8 } from '@fuman/utils'
|
||||||
|
|
||||||
import { getPlatform } from '../platform.js'
|
|
||||||
import { MtArgumentError, MtTimeoutError, MtcuteError } from '../types/index.js'
|
import { MtArgumentError, MtTimeoutError, MtcuteError } from '../types/index.js'
|
||||||
import { createAesIgeForMessageOld } from '../utils/crypto/mtproto.js'
|
import { createAesIgeForMessageOld } from '../utils/crypto/mtproto.js'
|
||||||
import type { ICryptoProvider } from '../utils/index.js'
|
import type { ICryptoProvider } from '../utils/index.js'
|
||||||
|
@ -16,6 +15,7 @@ import {
|
||||||
removeFromLongArray,
|
removeFromLongArray,
|
||||||
timers,
|
timers,
|
||||||
} from '../utils/index.js'
|
} from '../utils/index.js'
|
||||||
|
import type { ICorePlatform } from '../types/platform'
|
||||||
|
|
||||||
import { doAuthorization } from './authorization.js'
|
import { doAuthorization } from './authorization.js'
|
||||||
import type { MtprotoSession, PendingMessage, PendingRpc } from './mtproto-session.js'
|
import type { MtprotoSession, PendingMessage, PendingRpc } from './mtproto-session.js'
|
||||||
|
@ -39,6 +39,7 @@ export interface SessionConnectionParams extends PersistentConnectionParams {
|
||||||
|
|
||||||
readerMap: TlReaderMap
|
readerMap: TlReaderMap
|
||||||
writerMap: TlWriterMap
|
writerMap: TlWriterMap
|
||||||
|
platform: ICorePlatform
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEMP_AUTH_KEY_EXPIRY = 86400 // 24 hours
|
const TEMP_AUTH_KEY_EXPIRY = 86400 // 24 hours
|
||||||
|
@ -97,7 +98,7 @@ export class SessionConnection extends PersistentConnection {
|
||||||
this._handleRawMessage = this._handleRawMessage.bind(this)
|
this._handleRawMessage = this._handleRawMessage.bind(this)
|
||||||
|
|
||||||
this._usePfs = this.params.usePfs ?? false
|
this._usePfs = this.params.usePfs ?? false
|
||||||
this._online = getPlatform().isOnline?.() ?? true
|
this._online = params.platform.isOnline?.() ?? true
|
||||||
}
|
}
|
||||||
|
|
||||||
private _online
|
private _online
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
import { describe, expect, it, vi } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
import { defaultTestCryptoProvider } from '@mtcute/test'
|
import { defaultPlatform, defaultTestCryptoProvider } from '@mtcute/test'
|
||||||
import { Bytes } from '@fuman/io'
|
import { Bytes } from '@fuman/io'
|
||||||
import { hex } from '@fuman/utils'
|
import { hex } from '@fuman/utils'
|
||||||
|
|
||||||
import { getPlatform } from '../../platform.js'
|
|
||||||
import { LogManager } from '../../utils/index.js'
|
import { LogManager } from '../../utils/index.js'
|
||||||
|
|
||||||
import { IntermediatePacketCodec } from './intermediate.js'
|
import { IntermediatePacketCodec } from './intermediate.js'
|
||||||
import type { MtProxyInfo } from './obfuscated.js'
|
import type { MtProxyInfo } from './obfuscated.js'
|
||||||
import { ObfuscatedPacketCodec } from './obfuscated.js'
|
import { ObfuscatedPacketCodec } from './obfuscated.js'
|
||||||
import { TransportError } from './abstract'
|
import { TransportError } from './abstract.js'
|
||||||
|
|
||||||
const p = getPlatform()
|
|
||||||
|
|
||||||
describe('ObfuscatedPacketCodec', () => {
|
describe('ObfuscatedPacketCodec', () => {
|
||||||
const create = async (randomSource?: string, proxy?: MtProxyInfo) => {
|
const create = async (randomSource?: string, proxy?: MtProxyInfo) => {
|
||||||
const codec = new ObfuscatedPacketCodec(new IntermediatePacketCodec(), proxy)
|
const codec = new ObfuscatedPacketCodec(new IntermediatePacketCodec(), proxy)
|
||||||
const crypto = await defaultTestCryptoProvider(randomSource)
|
const crypto = await defaultTestCryptoProvider(randomSource)
|
||||||
codec.setup(crypto, new LogManager())
|
codec.setup(crypto, new LogManager(undefined, defaultPlatform))
|
||||||
|
|
||||||
return [codec, crypto] as const
|
return [codec, crypto] as const
|
||||||
}
|
}
|
||||||
|
@ -191,7 +188,7 @@ describe('ObfuscatedPacketCodec', () => {
|
||||||
const spyInnerReset = vi.spyOn(inner, 'reset')
|
const spyInnerReset = vi.spyOn(inner, 'reset')
|
||||||
|
|
||||||
const codec = new ObfuscatedPacketCodec(inner)
|
const codec = new ObfuscatedPacketCodec(inner)
|
||||||
codec.setup(await defaultTestCryptoProvider(), new LogManager())
|
codec.setup(await defaultTestCryptoProvider(), new LogManager(undefined, defaultPlatform))
|
||||||
|
|
||||||
await codec.tag()
|
await codec.tag()
|
||||||
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
import type { UploadFileLike } from './highlevel/types/files/utils.js'
|
|
||||||
import { MtUnsupportedError } from './types/errors.js'
|
|
||||||
import type { MaybePromise } from './types/index.js'
|
|
||||||
|
|
||||||
// todo: can we make this non-global?
|
|
||||||
|
|
||||||
export interface ICorePlatform {
|
|
||||||
beforeExit: (fn: () => void) => () => void
|
|
||||||
log: (color: number, level: number, tag: string, fmt: string, args: unknown[]) => void
|
|
||||||
getDefaultLogLevel: () => number | null
|
|
||||||
getDeviceModel: () => string
|
|
||||||
normalizeFile?: (file: UploadFileLike) => MaybePromise<{
|
|
||||||
file?: UploadFileLike
|
|
||||||
fileSize?: number
|
|
||||||
fileName?: string
|
|
||||||
} | null>
|
|
||||||
onNetworkChanged?: (fn: (connected: boolean) => void) => () => void
|
|
||||||
isOnline?: () => boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB: when using with some bundlers (e.g. vite) re-importing this module will not return the same object
|
|
||||||
// so we need to store the platform in a global object to be able to survive hot-reloads etc.
|
|
||||||
// try to use Symbol if available, otherwise fallback to a string
|
|
||||||
const platformKey = typeof Symbol !== 'undefined' ? Symbol.for('mtcute.platform') : '__MTCUTE_PLATFORM__'
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
let _platform: ICorePlatform | null = (globalThis as any)?.[platformKey] ?? null
|
|
||||||
|
|
||||||
export function setPlatform(platform: ICorePlatform): void {
|
|
||||||
if (_platform) {
|
|
||||||
if (_platform.constructor !== platform.constructor) {
|
|
||||||
throw new MtUnsupportedError('Platform may not be changed at runtime!')
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_platform = platform
|
|
||||||
|
|
||||||
;(globalThis as any)[platformKey] = platform
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getPlatform(): ICorePlatform {
|
|
||||||
if (!_platform) {
|
|
||||||
throw new MtUnsupportedError('Platform is not set! Have you instantiated the client?')
|
|
||||||
}
|
|
||||||
|
|
||||||
return _platform
|
|
||||||
}
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import type { ICorePlatform } from '../types/platform'
|
||||||
import type { MaybePromise } from '../types/utils.js'
|
import type { MaybePromise } from '../types/utils.js'
|
||||||
import type { Logger } from '../utils/logger.js'
|
import type { Logger } from '../utils/logger.js'
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ export interface IStorageDriver {
|
||||||
* Setup the driver, passing the logger instance,
|
* Setup the driver, passing the logger instance,
|
||||||
* in case your driver needs it
|
* in case your driver needs it
|
||||||
*/
|
*/
|
||||||
setup?: (log: Logger) => void
|
setup?: (log: Logger, platform: ICorePlatform) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,9 +54,11 @@ export abstract class BaseStorageDriver implements IStorageDriver {
|
||||||
private _destroyed = false
|
private _destroyed = false
|
||||||
|
|
||||||
protected _log!: Logger
|
protected _log!: Logger
|
||||||
|
protected _platform!: ICorePlatform
|
||||||
|
|
||||||
setup(log: Logger): void {
|
setup(log: Logger, platform: ICorePlatform): void {
|
||||||
this._log = log.create('sqlite')
|
this._log = log.create('sqlite')
|
||||||
|
this._platform = platform
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get loaded(): boolean {
|
protected get loaded(): boolean {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { __tlReaderMap } from '@mtcute/tl/binary/reader.js'
|
import { __tlReaderMap } from '@mtcute/tl/binary/reader.js'
|
||||||
import { __tlWriterMap } from '@mtcute/tl/binary/writer.js'
|
import { __tlWriterMap } from '@mtcute/tl/binary/writer.js'
|
||||||
|
import { defaultPlatform } from '@mtcute/test'
|
||||||
|
|
||||||
import { LogManager } from '../../utils/logger.js'
|
import { LogManager } from '../../utils/logger.js'
|
||||||
import { MemoryStorageDriver } from '../memory/driver.js'
|
import { MemoryStorageDriver } from '../memory/driver.js'
|
||||||
|
@ -7,7 +8,7 @@ import { MemoryStorageDriver } from '../memory/driver.js'
|
||||||
import type { ServiceOptions } from './base.js'
|
import type { ServiceOptions } from './base.js'
|
||||||
|
|
||||||
export function testServiceOptions(): ServiceOptions {
|
export function testServiceOptions(): ServiceOptions {
|
||||||
const logger = new LogManager()
|
const logger = new LogManager(undefined, defaultPlatform)
|
||||||
logger.level = 0
|
logger.level = 0
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { getPlatform } from '../../platform.js'
|
|
||||||
import { BaseStorageDriver } from '../driver.js'
|
import { BaseStorageDriver } from '../driver.js'
|
||||||
|
|
||||||
import type { ISqliteDatabase, ISqliteStatement } from './types.js'
|
import type { ISqliteDatabase, ISqliteStatement } from './types.js'
|
||||||
|
@ -136,7 +135,7 @@ export abstract class BaseSqliteStorageDriver extends BaseStorageDriver {
|
||||||
|
|
||||||
this.db.transaction(() => this._initialize())()
|
this.db.transaction(() => this._initialize())()
|
||||||
|
|
||||||
this._cleanup = getPlatform().beforeExit(() => {
|
this._cleanup = this._platform.beforeExit(() => {
|
||||||
this._save()
|
this._save()
|
||||||
this._destroy()
|
this._destroy()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import type { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'
|
import type { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'
|
||||||
|
|
||||||
import { getPlatform } from '../platform.js'
|
|
||||||
import { asyncResettable } from '../utils/index.js'
|
import { asyncResettable } from '../utils/index.js'
|
||||||
import type { Logger } from '../utils/logger.js'
|
import type { Logger } from '../utils/logger.js'
|
||||||
|
import type { ICorePlatform } from '../types/platform'
|
||||||
|
|
||||||
import type { IMtStorageProvider } from './provider.js'
|
import type { IMtStorageProvider } from './provider.js'
|
||||||
import { AuthKeysService } from './service/auth-keys.js'
|
import { AuthKeysService } from './service/auth-keys.js'
|
||||||
|
@ -13,6 +13,7 @@ import type { IStorageDriver } from './driver.js'
|
||||||
|
|
||||||
interface StorageManagerOptions {
|
interface StorageManagerOptions {
|
||||||
provider: IMtStorageProvider
|
provider: IMtStorageProvider
|
||||||
|
platform: ICorePlatform
|
||||||
log: Logger
|
log: Logger
|
||||||
readerMap: TlReaderMap
|
readerMap: TlReaderMap
|
||||||
writerMap: TlWriterMap
|
writerMap: TlWriterMap
|
||||||
|
@ -44,6 +45,7 @@ export interface StorageManagerExtraOptions {
|
||||||
export class StorageManager {
|
export class StorageManager {
|
||||||
readonly provider: IMtStorageProvider
|
readonly provider: IMtStorageProvider
|
||||||
readonly driver: IStorageDriver
|
readonly driver: IStorageDriver
|
||||||
|
readonly platform: ICorePlatform
|
||||||
readonly log: Logger
|
readonly log: Logger
|
||||||
readonly dcs: DefaultDcsService
|
readonly dcs: DefaultDcsService
|
||||||
readonly salts: FutureSaltsService
|
readonly salts: FutureSaltsService
|
||||||
|
@ -51,6 +53,7 @@ export class StorageManager {
|
||||||
|
|
||||||
constructor(readonly options: StorageManagerOptions & StorageManagerExtraOptions) {
|
constructor(readonly options: StorageManagerOptions & StorageManagerExtraOptions) {
|
||||||
this.provider = this.options.provider
|
this.provider = this.options.provider
|
||||||
|
this.platform = this.options.platform
|
||||||
this.driver = this.provider.driver
|
this.driver = this.provider.driver
|
||||||
this.log = this.options.log.create('storage')
|
this.log = this.options.log.create('storage')
|
||||||
|
|
||||||
|
@ -69,10 +72,10 @@ export class StorageManager {
|
||||||
private _cleanupRestore?: () => void
|
private _cleanupRestore?: () => void
|
||||||
|
|
||||||
private _load = asyncResettable(async () => {
|
private _load = asyncResettable(async () => {
|
||||||
this.driver.setup?.(this.log)
|
this.driver.setup?.(this.log, this.platform)
|
||||||
|
|
||||||
if (this.options.cleanup ?? true) {
|
if (this.options.cleanup ?? true) {
|
||||||
this._cleanupRestore = getPlatform().beforeExit(() => {
|
this._cleanupRestore = this.platform.beforeExit(() => {
|
||||||
this._destroy().catch(err => this.log.error('cleanup error: %e', err))
|
this._destroy().catch(err => this.log.error('cleanup error: %e', err))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './errors.js'
|
export * from './errors.js'
|
||||||
export * from './peers.js'
|
export * from './peers.js'
|
||||||
export * from './utils.js'
|
export * from './utils.js'
|
||||||
|
export * from './platform.js'
|
||||||
|
|
17
packages/core/src/types/platform.ts
Normal file
17
packages/core/src/types/platform.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import type { UploadFileLike } from '../highlevel/types/files/utils.js'
|
||||||
|
|
||||||
|
import type { MaybePromise } from './index.js'
|
||||||
|
|
||||||
|
export interface ICorePlatform {
|
||||||
|
beforeExit: (fn: () => void) => () => void
|
||||||
|
log: (color: number, level: number, tag: string, fmt: string, args: unknown[]) => void
|
||||||
|
getDefaultLogLevel: () => number | null
|
||||||
|
getDeviceModel: () => string
|
||||||
|
normalizeFile?: (file: UploadFileLike) => MaybePromise<{
|
||||||
|
file?: UploadFileLike
|
||||||
|
fileSize?: number
|
||||||
|
fileName?: string
|
||||||
|
} | null>
|
||||||
|
onNetworkChanged?: (fn: (connected: boolean) => void) => () => void
|
||||||
|
isOnline?: () => boolean
|
||||||
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
import Long from 'long'
|
import Long from 'long'
|
||||||
import { describe, expect, it, vi } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
|
import { defaultPlatform } from '@mtcute/test'
|
||||||
|
|
||||||
import { LogManager } from './logger.js'
|
import { LogManager } from './logger.js'
|
||||||
|
|
||||||
describe('logger', () => {
|
describe('logger', () => {
|
||||||
const createManager = () => {
|
const createManager = () => {
|
||||||
const mgr = new LogManager()
|
const mgr = new LogManager(undefined, defaultPlatform)
|
||||||
mgr.level = LogManager.INFO
|
mgr.level = LogManager.INFO
|
||||||
|
|
||||||
const spy = vi.fn<typeof mgr.handler>()
|
const spy = vi.fn<typeof mgr.handler>()
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { hex } from '@fuman/utils'
|
import { hex } from '@fuman/utils'
|
||||||
|
|
||||||
import type { ICorePlatform } from '../platform.js'
|
import type { ICorePlatform } from '../types/platform.js'
|
||||||
import { getPlatform } from '../platform.js'
|
|
||||||
|
|
||||||
import { isTlRpcError } from './type-assertions.js'
|
import { isTlRpcError } from './type-assertions.js'
|
||||||
|
|
||||||
|
@ -160,19 +159,17 @@ export class LogManager extends Logger {
|
||||||
static DEBUG = 4
|
static DEBUG = 4
|
||||||
static VERBOSE = 5
|
static VERBOSE = 5
|
||||||
|
|
||||||
readonly platform: ICorePlatform
|
|
||||||
level: number
|
level: number
|
||||||
handler: (color: number, level: number, tag: string, fmt: string, args: unknown[]) => void
|
handler: (color: number, level: number, tag: string, fmt: string, args: unknown[]) => void
|
||||||
|
|
||||||
constructor(tag = 'base') {
|
constructor(tag = 'base', platform: ICorePlatform) {
|
||||||
// workaround because we cant pass this to super
|
// workaround because we cant pass this to super
|
||||||
// eslint-disable-next-line ts/no-unsafe-argument
|
// eslint-disable-next-line ts/no-unsafe-argument
|
||||||
super(null as any, tag)
|
super(null as any, tag)
|
||||||
;(this as any).mgr = this
|
;(this as any).mgr = this
|
||||||
|
|
||||||
this.platform = getPlatform()
|
this.level = platform.getDefaultLogLevel() ?? DEFAULT_LOG_LEVEL
|
||||||
this.level = this.platform.getDefaultLogLevel() ?? DEFAULT_LOG_LEVEL
|
this.handler = platform.log.bind(platform)
|
||||||
this.handler = this.platform.log.bind(this.platform)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filter: (tag: string) => boolean = defaultFilter
|
private _filter: (tag: string) => boolean = defaultFilter
|
||||||
|
|
|
@ -11,17 +11,17 @@ import {
|
||||||
BaseTelegramClient as BaseTelegramClientBase,
|
BaseTelegramClient as BaseTelegramClientBase,
|
||||||
TelegramClient as TelegramClientBase,
|
TelegramClient as TelegramClientBase,
|
||||||
} from '@mtcute/core/client.js'
|
} from '@mtcute/core/client.js'
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
|
|
||||||
import { downloadToFile } from './methods/download-file.js'
|
import { downloadToFile } from './methods/download-file.js'
|
||||||
import { DenoPlatform } from './platform.js'
|
import { DenoPlatform } from './platform.js'
|
||||||
import { SqliteStorage } from './sqlite/index.js'
|
import { SqliteStorage } from './sqlite/index.js'
|
||||||
import { DenoCryptoProvider } from './utils/crypto.js'
|
import { DenoCryptoProvider } from './utils/crypto.js'
|
||||||
|
import { TcpTransport } from './utils/tcp.js'
|
||||||
|
|
||||||
export type { TelegramClientOptions }
|
export type { TelegramClientOptions }
|
||||||
|
|
||||||
export interface BaseTelegramClientOptions
|
export interface BaseTelegramClientOptions
|
||||||
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto'> {
|
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto' | 'platform'> {
|
||||||
/**
|
/**
|
||||||
* Storage to use for this client.
|
* Storage to use for this client.
|
||||||
*
|
*
|
||||||
|
@ -31,23 +31,14 @@ export interface BaseTelegramClientOptions
|
||||||
* @default `"client.session"`
|
* @default `"client.session"`
|
||||||
*/
|
*/
|
||||||
storage?: string | ITelegramStorageProvider
|
storage?: string | ITelegramStorageProvider
|
||||||
|
|
||||||
/**
|
|
||||||
* **ADVANCED USE ONLY**
|
|
||||||
*
|
|
||||||
* Whether to not set up the platform.
|
|
||||||
* This is useful if you call `setPlatform` yourself.
|
|
||||||
*/
|
|
||||||
platformless?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseTelegramClient extends BaseTelegramClientBase {
|
export class BaseTelegramClient extends BaseTelegramClientBase {
|
||||||
constructor(opts: BaseTelegramClientOptions) {
|
constructor(opts: BaseTelegramClientOptions) {
|
||||||
if (!opts.platformless) setPlatform(new DenoPlatform())
|
|
||||||
|
|
||||||
super({
|
super({
|
||||||
crypto: new DenoCryptoProvider(),
|
crypto: new DenoCryptoProvider(),
|
||||||
transport: {} as any, // todo
|
transport: TcpTransport,
|
||||||
|
platform: new DenoPlatform(),
|
||||||
...opts,
|
...opts,
|
||||||
storage:
|
storage:
|
||||||
typeof opts.storage === 'string'
|
typeof opts.storage === 'string'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ICorePlatform } from '@mtcute/core/platform.js'
|
import type { ICorePlatform } from '@mtcute/core'
|
||||||
|
|
||||||
import { defaultLoggingHandler } from './common-internals-web/logging.js'
|
import { defaultLoggingHandler } from './common-internals-web/logging.js'
|
||||||
import { beforeExit } from './utils/exit-hook.js'
|
import { beforeExit } from './utils/exit-hook.js'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { afterAll, beforeAll, describe } from 'vitest'
|
import { afterAll, beforeAll, describe } from 'vitest'
|
||||||
import { LogManager } from '@mtcute/core/utils.js'
|
import { LogManager } from '@mtcute/core/utils.js'
|
||||||
import {
|
import {
|
||||||
|
defaultPlatform,
|
||||||
testAuthKeysRepository,
|
testAuthKeysRepository,
|
||||||
testKeyValueRepository,
|
testKeyValueRepository,
|
||||||
testPeersRepository,
|
testPeersRepository,
|
||||||
|
@ -17,7 +18,7 @@ if (import.meta.env.TEST_ENV === 'deno') {
|
||||||
const storage = new SqliteStorage(':memory:')
|
const storage = new SqliteStorage(':memory:')
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
storage.driver.setup(new LogManager())
|
storage.driver.setup(new LogManager(undefined, defaultPlatform), defaultPlatform)
|
||||||
await storage.driver.load()
|
await storage.driver.load()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
import type {
|
import type {
|
||||||
ClientMessageHandler,
|
ClientMessageHandler,
|
||||||
RespondFn,
|
RespondFn,
|
||||||
SendFn,
|
SendFn,
|
||||||
SomeWorker,
|
SomeWorker,
|
||||||
TelegramWorkerOptions,
|
TelegramWorkerOptions,
|
||||||
TelegramWorkerPortOptions,
|
|
||||||
WorkerCustomMethods,
|
WorkerCustomMethods,
|
||||||
WorkerMessageHandler,
|
WorkerMessageHandler,
|
||||||
} from '@mtcute/core/worker.js'
|
} from '@mtcute/core/worker.js'
|
||||||
|
@ -16,8 +14,10 @@ import {
|
||||||
|
|
||||||
import { DenoPlatform } from './platform.js'
|
import { DenoPlatform } from './platform.js'
|
||||||
|
|
||||||
export type { TelegramWorkerOptions, TelegramWorkerPortOptions, WorkerCustomMethods }
|
export type { TelegramWorkerOptions, WorkerCustomMethods }
|
||||||
|
export interface TelegramWorkerPortOptions {
|
||||||
|
worker: SomeWorker
|
||||||
|
}
|
||||||
let _registered = false
|
let _registered = false
|
||||||
|
|
||||||
export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorkerBase<T> {
|
export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorkerBase<T> {
|
||||||
|
@ -44,9 +44,11 @@ export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorke
|
||||||
const platform = new DenoPlatform()
|
const platform = new DenoPlatform()
|
||||||
|
|
||||||
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
||||||
constructor(readonly options: TelegramWorkerPortOptions) {
|
constructor(options: TelegramWorkerPortOptions) {
|
||||||
setPlatform(platform)
|
super({
|
||||||
super(options)
|
worker: options.worker,
|
||||||
|
platform,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
||||||
|
|
|
@ -11,15 +11,13 @@ import {
|
||||||
BaseTelegramClient as BaseTelegramClientBase,
|
BaseTelegramClient as BaseTelegramClientBase,
|
||||||
TelegramClient as TelegramClientBase,
|
TelegramClient as TelegramClientBase,
|
||||||
} from '@mtcute/core/client.js'
|
} from '@mtcute/core/client.js'
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
|
|
||||||
import { NodePlatform } from './common-internals-node/platform.js'
|
|
||||||
import { downloadToFile } from './methods/download-file.js'
|
import { downloadToFile } from './methods/download-file.js'
|
||||||
import { downloadAsNodeStream } from './methods/download-node-stream.js'
|
import { downloadAsNodeStream } from './methods/download-node-stream.js'
|
||||||
import { SqliteStorage } from './sqlite/index.js'
|
import { SqliteStorage } from './sqlite/index.js'
|
||||||
import { NodeCryptoProvider } from './utils/crypto.js'
|
import { NodeCryptoProvider } from './utils/crypto.js'
|
||||||
import { TcpTransport } from './utils/tcp.js'
|
import { TcpTransport } from './utils/tcp.js'
|
||||||
// import { TcpTransport } from './utils/tcp.js'
|
import { NodePlatform } from './common-internals-node/platform.js'
|
||||||
|
|
||||||
export type { TelegramClientOptions }
|
export type { TelegramClientOptions }
|
||||||
|
|
||||||
|
@ -34,7 +32,7 @@ try {
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
export interface BaseTelegramClientOptions
|
export interface BaseTelegramClientOptions
|
||||||
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto'> {
|
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto' | 'platform'> {
|
||||||
/**
|
/**
|
||||||
* Storage to use for this client.
|
* Storage to use for this client.
|
||||||
*
|
*
|
||||||
|
@ -45,23 +43,15 @@ export interface BaseTelegramClientOptions
|
||||||
*/
|
*/
|
||||||
storage?: string | ITelegramStorageProvider
|
storage?: string | ITelegramStorageProvider
|
||||||
|
|
||||||
/**
|
|
||||||
* **ADVANCED USE ONLY**
|
|
||||||
*
|
|
||||||
* Whether to not set up the platform.
|
|
||||||
* This is useful if you call `setPlatform` yourself.
|
|
||||||
*/
|
|
||||||
platformless?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseTelegramClient extends BaseTelegramClientBase {
|
export class BaseTelegramClient extends BaseTelegramClientBase {
|
||||||
constructor(opts: BaseTelegramClientOptions) {
|
constructor(opts: BaseTelegramClientOptions) {
|
||||||
if (!opts.platformless) setPlatform(new NodePlatform())
|
|
||||||
|
|
||||||
super({
|
super({
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
crypto: nativeCrypto ? new nativeCrypto() : new NodeCryptoProvider(),
|
crypto: nativeCrypto ? new nativeCrypto() : new NodeCryptoProvider(),
|
||||||
transport: TcpTransport,
|
transport: TcpTransport,
|
||||||
|
platform: new NodePlatform(),
|
||||||
...opts,
|
...opts,
|
||||||
storage:
|
storage:
|
||||||
typeof opts.storage === 'string'
|
typeof opts.storage === 'string'
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import * as os from 'node:os'
|
import * as os from 'node:os'
|
||||||
|
|
||||||
import type { ICorePlatform } from '@mtcute/core/platform.js'
|
import type { ICorePlatform } from '@mtcute/core'
|
||||||
|
|
||||||
import { normalizeFile } from '../utils/normalize-file.js'
|
import { normalizeFile } from '../utils/normalize-file.js'
|
||||||
|
|
||||||
import { beforeExit } from './exit-hook.js'
|
import { beforeExit } from './exit-hook.js'
|
||||||
import { defaultLoggingHandler } from './logging.js'
|
import { defaultLoggingHandler } from './logging.js'
|
||||||
|
|
||||||
const toBuffer = (buf: Uint8Array): Buffer => Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
|
|
||||||
|
|
||||||
export class NodePlatform implements ICorePlatform {
|
export class NodePlatform implements ICorePlatform {
|
||||||
// ICorePlatform
|
// ICorePlatform
|
||||||
declare log: typeof defaultLoggingHandler
|
declare log: typeof defaultLoggingHandler
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { afterAll, beforeAll, describe } from 'vitest'
|
import { afterAll, beforeAll, describe } from 'vitest'
|
||||||
import { LogManager } from '@mtcute/core/utils.js'
|
import { LogManager } from '@mtcute/core/utils.js'
|
||||||
import {
|
import {
|
||||||
|
defaultPlatform,
|
||||||
testAuthKeysRepository,
|
testAuthKeysRepository,
|
||||||
testKeyValueRepository,
|
testKeyValueRepository,
|
||||||
testPeersRepository,
|
testPeersRepository,
|
||||||
|
@ -14,7 +15,7 @@ if (import.meta.env.TEST_ENV === 'node') {
|
||||||
const storage = new SqliteStorage(':memory:')
|
const storage = new SqliteStorage(':memory:')
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
storage.driver.setup(new LogManager())
|
storage.driver.setup(new LogManager(undefined, defaultPlatform), defaultPlatform)
|
||||||
await storage.driver.load()
|
await storage.driver.load()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import { Worker, parentPort } from 'node:worker_threads'
|
import { Worker, parentPort } from 'node:worker_threads'
|
||||||
|
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
import type {
|
import type {
|
||||||
ClientMessageHandler,
|
ClientMessageHandler,
|
||||||
RespondFn,
|
RespondFn,
|
||||||
SendFn,
|
SendFn,
|
||||||
SomeWorker,
|
SomeWorker,
|
||||||
TelegramWorkerOptions,
|
TelegramWorkerOptions,
|
||||||
TelegramWorkerPortOptions,
|
|
||||||
WorkerCustomMethods,
|
WorkerCustomMethods,
|
||||||
WorkerMessageHandler,
|
WorkerMessageHandler,
|
||||||
} from '@mtcute/core/worker.js'
|
} from '@mtcute/core/worker.js'
|
||||||
|
@ -18,7 +16,11 @@ import {
|
||||||
|
|
||||||
import { NodePlatform } from './common-internals-node/platform.js'
|
import { NodePlatform } from './common-internals-node/platform.js'
|
||||||
|
|
||||||
export type { TelegramWorkerOptions, TelegramWorkerPortOptions, WorkerCustomMethods }
|
export type { TelegramWorkerOptions, WorkerCustomMethods }
|
||||||
|
|
||||||
|
export interface TelegramWorkerPortOptions {
|
||||||
|
worker: SomeWorker
|
||||||
|
}
|
||||||
|
|
||||||
let _registered = false
|
let _registered = false
|
||||||
|
|
||||||
|
@ -45,9 +47,11 @@ export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorke
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
||||||
constructor(readonly options: TelegramWorkerPortOptions) {
|
constructor(options: TelegramWorkerPortOptions) {
|
||||||
setPlatform(new NodePlatform())
|
super({
|
||||||
super(options)
|
worker: options.worker,
|
||||||
|
platform: new NodePlatform(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import { getPlatform } from '@mtcute/core/platform.js'
|
import { hex } from '@fuman/utils'
|
||||||
|
|
||||||
import { StubTelegramClient } from './client.js'
|
import { StubTelegramClient } from './client.js'
|
||||||
import { createStub } from './stub.js'
|
import { createStub } from './stub.js'
|
||||||
|
@ -25,7 +25,7 @@ describe('client stub', () => {
|
||||||
const client = new StubTelegramClient()
|
const client = new StubTelegramClient()
|
||||||
|
|
||||||
client.onRawMessage((msg) => {
|
client.onRawMessage((msg) => {
|
||||||
log.push(`message ctor=${getPlatform().hexEncode(msg.subarray(0, 4))}`)
|
log.push(`message ctor=${hex.encode(msg.subarray(0, 4))}`)
|
||||||
client.close().catch(() => {})
|
client.close().catch(() => {})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { IntermediatePacketCodec, tl } from '@mtcute/core'
|
||||||
import type { BaseTelegramClientOptions } from '@mtcute/core/client.js'
|
import type { BaseTelegramClientOptions } from '@mtcute/core/client.js'
|
||||||
import { BaseTelegramClient } from '@mtcute/core/client.js'
|
import { BaseTelegramClient } from '@mtcute/core/client.js'
|
||||||
|
|
||||||
import { defaultCryptoProvider } from './platform.js'
|
import { defaultCryptoProvider, defaultPlatform } from './platform.js'
|
||||||
import { StubMemoryTelegramStorage } from './storage.js'
|
import { StubMemoryTelegramStorage } from './storage.js'
|
||||||
// import { StubTelegramTransport } from './transport.js'
|
// import { StubTelegramTransport } from './transport.js'
|
||||||
import type { InputResponder } from './types.js'
|
import type { InputResponder } from './types.js'
|
||||||
|
@ -57,6 +57,7 @@ export class StubTelegramClient extends BaseTelegramClient {
|
||||||
packetCodec: () => new IntermediatePacketCodec(),
|
packetCodec: () => new IntermediatePacketCodec(),
|
||||||
},
|
},
|
||||||
crypto: defaultCryptoProvider,
|
crypto: defaultCryptoProvider,
|
||||||
|
platform: defaultPlatform,
|
||||||
...params,
|
...params,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,16 @@ import {
|
||||||
BaseTelegramClient as BaseTelegramClientBase,
|
BaseTelegramClient as BaseTelegramClientBase,
|
||||||
TelegramClient as TelegramClientBase,
|
TelegramClient as TelegramClientBase,
|
||||||
} from '@mtcute/core/client.js'
|
} from '@mtcute/core/client.js'
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
|
|
||||||
import { WebCryptoProvider } from './crypto.js'
|
import { WebCryptoProvider } from './crypto.js'
|
||||||
import { IdbStorage } from './idb/index.js'
|
import { IdbStorage } from './idb/index.js'
|
||||||
import { WebPlatform } from './platform.js'
|
|
||||||
import { WebSocketTransport } from './websocket.js'
|
import { WebSocketTransport } from './websocket.js'
|
||||||
|
import { WebPlatform } from './platform.js'
|
||||||
|
|
||||||
export type { TelegramClientOptions }
|
export type { TelegramClientOptions }
|
||||||
|
|
||||||
export interface BaseTelegramClientOptions
|
export interface BaseTelegramClientOptions
|
||||||
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto'> {
|
extends PartialOnly<Omit<BaseTelegramClientOptionsBase, 'storage'>, 'transport' | 'crypto' | 'platform'> {
|
||||||
/**
|
/**
|
||||||
* Storage to use for this client.
|
* Storage to use for this client.
|
||||||
*
|
*
|
||||||
|
@ -27,23 +26,14 @@ export interface BaseTelegramClientOptions
|
||||||
* @default `"client.session"`
|
* @default `"client.session"`
|
||||||
*/
|
*/
|
||||||
storage?: string | ITelegramStorageProvider
|
storage?: string | ITelegramStorageProvider
|
||||||
|
|
||||||
/**
|
|
||||||
* **ADVANCED USE ONLY**
|
|
||||||
*
|
|
||||||
* Whether to not set up the platform.
|
|
||||||
* This is useful if you call `setPlatform` yourself.
|
|
||||||
*/
|
|
||||||
platformless?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseTelegramClient extends BaseTelegramClientBase {
|
export class BaseTelegramClient extends BaseTelegramClientBase {
|
||||||
constructor(opts: BaseTelegramClientOptions) {
|
constructor(opts: BaseTelegramClientOptions) {
|
||||||
if (!opts.platformless) setPlatform(new WebPlatform())
|
|
||||||
|
|
||||||
super({
|
super({
|
||||||
crypto: new WebCryptoProvider(),
|
crypto: new WebCryptoProvider(),
|
||||||
transport: new WebSocketTransport(),
|
transport: new WebSocketTransport(),
|
||||||
|
platform: new WebPlatform(),
|
||||||
...opts,
|
...opts,
|
||||||
storage:
|
storage:
|
||||||
typeof opts.storage === 'string'
|
typeof opts.storage === 'string'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ICorePlatform } from '@mtcute/core/platform.js'
|
import type { ICorePlatform } from '@mtcute/core'
|
||||||
|
|
||||||
import { defaultLoggingHandler } from './common-internals-web/logging.js'
|
import { defaultLoggingHandler } from './common-internals-web/logging.js'
|
||||||
import { beforeExit } from './exit-hook.js'
|
import { beforeExit } from './exit-hook.js'
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
/* eslint-disable no-restricted-globals */
|
/* eslint-disable no-restricted-globals */
|
||||||
import { setPlatform } from '@mtcute/core/platform.js'
|
|
||||||
import type {
|
import type {
|
||||||
ClientMessageHandler,
|
ClientMessageHandler,
|
||||||
RespondFn,
|
RespondFn,
|
||||||
SendFn,
|
SendFn,
|
||||||
SomeWorker,
|
SomeWorker,
|
||||||
TelegramWorkerOptions,
|
TelegramWorkerOptions,
|
||||||
TelegramWorkerPortOptions,
|
|
||||||
WorkerCustomMethods,
|
WorkerCustomMethods,
|
||||||
WorkerMessageHandler,
|
WorkerMessageHandler,
|
||||||
} from '@mtcute/core/worker.js'
|
} from '@mtcute/core/worker.js'
|
||||||
|
@ -17,8 +15,10 @@ import {
|
||||||
|
|
||||||
import { WebPlatform } from './platform.js'
|
import { WebPlatform } from './platform.js'
|
||||||
|
|
||||||
export type { TelegramWorkerOptions, TelegramWorkerPortOptions, WorkerCustomMethods }
|
export type { TelegramWorkerOptions, WorkerCustomMethods }
|
||||||
|
export interface TelegramWorkerPortOptions {
|
||||||
|
worker: SomeWorker
|
||||||
|
}
|
||||||
let _registered = false
|
let _registered = false
|
||||||
|
|
||||||
export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorkerBase<T> {
|
export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorkerBase<T> {
|
||||||
|
@ -103,12 +103,14 @@ export class TelegramWorker<T extends WorkerCustomMethods> extends TelegramWorke
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const platform = new WebPlatform()
|
const platform = /* #__PURE__ */ new WebPlatform()
|
||||||
|
|
||||||
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
export class TelegramWorkerPort<T extends WorkerCustomMethods> extends TelegramWorkerPortBase<T> {
|
||||||
constructor(readonly options: TelegramWorkerPortOptions) {
|
constructor(options: TelegramWorkerPortOptions) {
|
||||||
setPlatform(platform)
|
super({
|
||||||
super(options)
|
worker: options.worker,
|
||||||
|
platform,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void] {
|
||||||
|
|
|
@ -132,9 +132,9 @@ importers:
|
||||||
|
|
||||||
packages/convert:
|
packages/convert:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@fuman/ip':
|
'@fuman/net':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../../private/fuman/packages/ip
|
version: link:../../private/fuman/packages/net
|
||||||
'@fuman/utils':
|
'@fuman/utils':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../../private/fuman/packages/utils
|
version: link:../../private/fuman/packages/utils
|
||||||
|
|
Loading…
Reference in a new issue