tdata
Load, create, edit and save Telegram Desktop 7.3.1 tdata folders. A TData keeps its keys in
Rust; accounts, localKey and passcodeKey copy key bytes out into new buffers.
import { loadTdata, saveTdata } from 'opentele2'
const tdata = await loadTdata('tdata') // loadTdata('tdata', 'passcode') for a locked folder
console.log(String(tdata), tdata.mainAccount?.userId, tdata.mainAccount?.mainDc)
await saveTdata(tdata, 'tdata_copy')Functions
function loadTdata(path: string, passcode?: string | Uint8Array | null, keyFile?: string | null): Promise<TData>
function loadMany(requests: Array<string | LoadRequest>, threads?: number | null): Promise<Array<TData | Error>>
function newTdata(accounts: Array<AccountInput>, passcode?: string | Uint8Array | null,
performanceMode?: boolean | null, activeIndex?: number | null,
draws?: Array<Uint8Array> | null): Promise<TData>
function saveTdata(tdata: TData, path: string, performanceMode?: boolean | null,
draws?: Array<Uint8Array> | null): Promise<void>
function migrateTdata(tdata: TData, draws?: Array<Uint8Array> | null): Promise<boolean>
function addTdataAccount(tdata: TData, userId: bigint, mainDc: number, authKey: Uint8Array): number
function setTdataAccounts(tdata: TData, accounts: Array<AccountInput>): void
function drawPlan(operation: 'new' | 'migrate' | 'save', target: TData | NewDrawPlan): Array<number>| Function | Description |
|---|---|
load | Loads the folder; a string passcode is UTF-8 encoded and keyFile defaults to "data". A wrong passcode rejects with OT_, a missing folder with OT_TFILE_NOT_FOUND. |
load | Loads many folders on a dedicated thread pool and resolves, in input order, to a TData or the Error of each; threads caps the pool (about 64 MiB of Argon2id memory per thread). |
new | A new folder for accounts the way SaveTData creates one, keys from the OS random source; performanceMode (default true) skips the configs files, activeIndex defaults to -1. |
save | Writes the folder into path; performanceMode applies to this save only. |
migrateTdata(tdata) | Installs 7.3 key data in place of a pre-7.3 key file, as the first save would, and resolves to whether it did; a 7.3 key file is left alone. |
add | Adds an account with authKey as the key of mainDc at the lowest free index and returns it; a full folder throws OT_MAX_ACCOUNT_LIMIT, a key that is not 256 bytes OT_BAD_LENGTH. |
set | Replaces the accounts later saves write, keeping the local key; more than TDATA_MAX_ACCOUNTS (or than were loaded) throw OT_MAX_ACCOUNT_LIMIT, two of one index OT_TDATA_SAVE_FAILED. |
draw | The sizes of the random draws an operation will make, so recorded draws can be replayed through draws; nothing is drawn or written. |
draws, a testing hook, replaces the OS random source with exactly these byte arrays in order; a
draw of another size, a missing draw or an unused one rejects with ERR_INVALID_ARG_VALUE.
TData
class TData {
get accounts(): Array<Account>
get activeIndex(): number
set activeIndex(value: number)
get performanceMode(): boolean
set performanceMode(value: boolean)
get appVersion(): number
get localKey(): Buffer
get passcodeKey(): Buffer
get mainAccount(): Account | null
get keyFile(): string
set keyFile(value: string)
get legacyKeyFile(): boolean
toString(): string
}| Member | Description |
|---|---|
accounts | The accounts, in accounts-info order. |
activeIndex | The active index stored in the accounts info; saving writes it. |
performanceMode | When on, saving writes no configs files; loading turns it on. |
appVersion | The Telegram Desktop version in the key file’s TDF$ header; saving always writes 7003001. |
localKey | The 256-byte local key every file but the key file is encrypted with. |
passcodeKey | The 256-byte open or passcode key the local key is wrapped under. |
mainAccount | The account at the active index, else the first one; null without accounts. |
keyFile | The key file data name; setting it renames the key file and account files of later saves, and an empty name throws OT_TDATA_SAVE_FAILED. |
legacyKeyFile | Whether the key file has the pre-7.3 layout. |
toString() | The account count and active index; never key bytes. |
Accounts
interface Account {
index: number
userId: bigint
mainDc: number
authKey: Buffer
keys: Array<DcKey>
config?: Buffer
}
interface AccountInput {
index: number
userId: bigint
mainDc: number
authKey?: Uint8Array
keys?: Array<DcKeyInput>
config?: Uint8Array
}
interface DcKey { dcId: number; authKey: Buffer }
interface DcKeyInput { dcId: number; authKey: Uint8Array }
interface LoadRequest { path: string; passcode?: string | Uint8Array; keyFile?: string }
interface NewDrawPlan { hasPasscode?: boolean; performanceMode?: boolean }
const TDATA_MAX_ACCOUNTS: number // 6
const TDF_MAGIC: string // "TDF$"An AccountInput is what newTdata and the session functions take; every Account is one. With
keys present, authKey is ignored; otherwise authKey is the one key, of mainDc. config is
the serialized MTP config the folder stored for the account, absent when there is none.
MTP config
function accountMtpConfig(account?: AccountInput | null): MtpConfig
function accountEndpoints(account?: AccountInput | null, dcId?: number | null): Endpoints | null
const MTP_FLAG_IPV6: number
const MTP_FLAG_MEDIA_ONLY: number
const MTP_FLAG_TCPO_ONLY: number
const MTP_FLAG_CDN: number
const MTP_FLAG_STATIC: number
const MTP_FLAG_THIS_PORT_ONLY: number
const MTP_FLAG_SECRET: numberinterface Endpoint { id: number; flags: number; ip: string; port: number; secret: Buffer }
interface ProtocolEndpoints { tcp: Array<Endpoint>; http: Array<Endpoint> }
interface Endpoints {
ipv4: ProtocolEndpoints
ipv6: ProtocolEndpoints
selectedIpv4?: Endpoint
selectedIpv6?: Endpoint
}
interface DcEndpoints { dcId: number; endpoints: Array<Endpoint> }
interface RsaPublicKey { dcId: number; n: Buffer; e: Buffer }
interface MtpConfig {
environment: 'production' | 'test'
dcs: Array<DcEndpoints>
cdnPublicKeys: Array<RsaPublicKey>
fields: MtpConfigFields
}accountMtpConfig is the account’s stored config parsed, or the production default when there
is none, it does not parse, or no account is given. accountEndpoints gives the endpoints of
dcId (the main DC by default) by family and protocol, null for a DC the config does not list.
MtpConfigFields holds the scalar config fields in camelCase (chatSizeMax, editTimeLimit,
internalLinksDomain, … reactionDefaultCustom as a bigint). The MTP_FLAG_* constants are
the endpoint flag bits: IPv6, media only, TCP only, CDN, built-in, this port only, has a secret.