refactor: exported string session parsing/serialization to a module

This commit is contained in:
teidesu 2022-10-09 20:49:39 +03:00
parent 8adb79511f
commit 416b3d9ef9
3 changed files with 107 additions and 56 deletions

View file

@ -38,6 +38,7 @@ import { ITelegramStorage, MemoryStorage } from './storage'
import defaultReaderMap from '@mtcute/tl/binary/reader' import defaultReaderMap from '@mtcute/tl/binary/reader'
import defaultWriterMap from '@mtcute/tl/binary/writer' import defaultWriterMap from '@mtcute/tl/binary/writer'
import { readStringSession, writeStringSession } from "./utils/string-session";
export namespace BaseTelegramClient { export namespace BaseTelegramClient {
export interface Options { export interface Options {
@ -444,41 +445,23 @@ export class BaseTelegramClient extends EventEmitter {
) )
if ((this._importForce || !this.primaryConnection.getAuthKey()) && this._importFrom) { if ((this._importForce || !this.primaryConnection.getAuthKey()) && this._importFrom) {
const buf = parseUrlSafeBase64(this._importFrom) const data = readStringSession(this._readerMap, this._importFrom)
if (buf[0] !== 1)
throw new Error(`Invalid session string (version = ${buf[0]})`)
const reader = new TlBinaryReader(this._readerMap, buf, 1) if (data.testMode !== !this._testMode) {
const flags = reader.int()
const hasSelf = flags & 1
if (!(flags & 2) !== !this._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'
) )
} }
const primaryDc = reader.object() this._primaryDc = this.primaryConnection.params.dc = data.primaryDc
if (primaryDc._ !== 'dcOption') { await this.storage.setDefaultDc(data.primaryDc)
throw new Error(
`Invalid session string (dc._ = ${primaryDc._})` if (data.self) {
) await this.storage.setSelf(data.self)
} }
this._primaryDc = this.primaryConnection.params.dc = primaryDc await this.primaryConnection.setupKeys(data.authKey)
await this.storage.setDefaultDc(primaryDc) await this.storage.setAuthKeyFor(data.primaryDc.id, data.authKey)
if (hasSelf) {
const selfId = reader.int53()
const selfBot = reader.boolean()
await this.storage.setSelf({ userId: selfId, isBot: selfBot })
}
const key = reader.bytes()
await this.primaryConnection.setupKeys(key)
await this.storage.setAuthKeyFor(primaryDc.id, key)
await this._saveStorage(true) await this._saveStorage(true)
} }
@ -968,35 +951,13 @@ export class BaseTelegramClient extends EventEmitter {
if (!this.primaryConnection.getAuthKey()) if (!this.primaryConnection.getAuthKey())
throw new Error('Auth key is not generated yet') throw new Error('Auth key is not generated yet')
const writer = TlBinaryWriter.alloc(this._writerMap, 512) return writeStringSession(this._writerMap, {
version: 1,
const self = await this.storage.getSelf() self: await this.storage.getSelf(),
testMode: this._testMode,
const version = 1 primaryDc: this._primaryDc,
let flags = 0 authKey: this.primaryConnection.getAuthKey()!,
})
if (self) {
flags |= 1
}
if (this._testMode) {
flags |= 2
}
writer.buffer[0] = version
writer.pos += 1
writer.int(flags)
writer.object(this._primaryDc)
if (self) {
writer.int53(self.userId)
writer.boolean(self.isBot)
}
writer.bytes(this.primaryConnection.getAuthKey()!)
return encodeUrlSafeBase64(writer.result())
} }
/** /**

View file

@ -19,3 +19,4 @@ export * from './misc-utils'
export * from './peer-utils' export * from './peer-utils'
export * from './sorted-array' export * from './sorted-array'
export * from './tl-json' export * from './tl-json'
export * from './string-session'

View file

@ -0,0 +1,89 @@
import { tl } from '@mtcute/tl'
import { TlBinaryReader, TlBinaryWriter, TlReaderMap, TlWriterMap } from "@mtcute/tl-runtime/dist";
import { encodeUrlSafeBase64, parseUrlSafeBase64 } from "./buffer-utils";
import { ITelegramStorage } from '../storage'
export interface StringSessionData {
version: number
testMode: boolean
primaryDc: tl.TypeDcOption
self?: ITelegramStorage.SelfInfo | null
authKey: Buffer
}
export function writeStringSession(
writerMap: TlWriterMap,
data: StringSessionData
): string {
const writer = TlBinaryWriter.alloc(writerMap, 512)
const version = data.version
if (version !== 1) {
throw new Error(`Unsupported string session version: ${version}`)
}
let flags = 0
if (data.self) {
flags |= 1
}
if (data.testMode) {
flags |= 2
}
writer.buffer[0] = version
writer.pos += 1
writer.int(flags)
writer.object(data.primaryDc)
if (data.self) {
writer.int53(data.self.userId)
writer.boolean(data.self.isBot)
}
writer.bytes(data.authKey)
return encodeUrlSafeBase64(writer.result())
}
export function readStringSession(readerMap: TlReaderMap, data: string): StringSessionData {
const buf = parseUrlSafeBase64(data)
if (buf[0] !== 1)
throw new Error(`Invalid session string (version = ${buf[0]})`)
const reader = new TlBinaryReader(readerMap, buf, 1)
const flags = reader.int()
const hasSelf = flags & 1
const testMode = !!(flags & 2)
const primaryDc = reader.object()
if (primaryDc._ !== 'dcOption') {
throw new Error(
`Invalid session string (dc._ = ${primaryDc._})`
)
}
let self: ITelegramStorage.SelfInfo | null = null
if (hasSelf) {
const selfId = reader.int53()
const selfBot = reader.boolean()
self = {
userId: selfId,
isBot: selfBot,
}
}
const key = reader.bytes()
return {
version: 1,
testMode,
primaryDc,
self,
authKey: key,
}
}