tdata to grammers
Open the account of a Telegram Desktop tdata folder in grammers
0.11: opentele2-grammers turns the account into grammers SessionData and the API profile into
grammers ConnectionParams. With its client feature it also runs the opentele2 flows (QR login,
session admin, consistency checks, tdata from a client) over a live grammers Client. grammers is a
Rust library; Python and Node use Telethon and mtcute instead.
Work on a copy of the folder. grammers’ SessionData and its DcOption print the raw auth key
with Debug: never log them, and never share or commit a session file.
Install
grammers is a Rust library. In Python, use Telethon (see tdata to Telethon); in Node, use mtcute (see tdata to mtcute).
grammers is a Rust library. In Python, use Telethon (see tdata to Telethon); in Node, use mtcute (see tdata to mtcute).
cargo add opentele2-core opentele2-grammers
cargo add grammers-client@0.11 grammers-mtsender@0.11 grammers-session@0.11
cargo add tokio --features macros,rt-multi-thread
# The client flows: QR login, session admin, consistency checks, tdata from a client.
cargo add opentele2-grammers --features clientThe default opentele2-grammers depends on grammers-session and grammers-mtsender only; the
client feature adds grammers-client.
Turn the account into SessionData
session_data(account) gives a grammers SessionData: the main DC as home DC, every production DC
with its first IPv4 and IPv6 endpoints (the stored config’s when the account has one), the account’s
key on the main DC only, and the self user in peer_infos. The updates state is empty, so grammers
fetches it on first use.
SessionData is the grammers format. Python and Node build Telethon and mtcute sessions from the same account: telethon_string_session / mtcute_string_session, or telethonStringSession / toStringSession.
SessionData is the grammers format. Python and Node build Telethon and mtcute sessions from the same account: telethon_string_session / mtcute_string_session, or telethonStringSession / toStringSession.
use grammers_session::storages::MemorySession;
use opentele2_core::tdata::TData;
fn main() -> opentele2_core::Result<()> {
let tdata = TData::load("tdata", b"", None)?; // passcode bytes, key file name
let account = tdata.main_account().expect("folder has an account");
let _session = MemorySession::from(opentele2_grammers::session_data(account));
Ok(())
}data.import_to(&session).await copies the same data into any other grammers Session, such as
an SqliteSession.
Turn the profile into ConnectionParams
connection_params(&profile) copies the profile’s device model, system version, app version,
system language code and language code into grammers’ ConnectionParams. The api_id goes to
grammers separately, the api_hash at sign-in.
Python's opentele2 TelegramClient takes api=API.TelegramDesktop; Node passes initConnectionOptions(profile) from opentele2/mtcute to mtcute.
Python's opentele2 TelegramClient takes api=API.TelegramDesktop; Node passes initConnectionOptions(profile) from opentele2/mtcute to mtcute.
use opentele2_core::api::{self, Client, Versions};
fn main() {
let desktop = api::profile(Client::Desktop, &Versions::offline());
let params = opentele2_grammers::connection_params(&desktop);
println!("{} {} {}", params.device_model, params.system_version, params.app_version);
}grammers 0.11 builds initConnection itself and always sends an empty lang_pack and no
params, and ConnectionParams has no field for either. A grammers session with the desktop
profile matches Telegram Desktop’s device, system, app and language fields, but not its
lang_pack (tdesktop) or tz_offset. See initConnection fingerprints.
Connect a client
Build a grammers SenderPool over the session with the profile’s api_id and connection params,
wrap its handle in a Client and run the pool on the runtime.
Python: TDesktop('tdata').ToTelethon(...) returns an opentele2 TelegramClient ready for connect(). Node: build an mtcute TelegramClient with initConnectionOptions and importSession(toStringSession(...)).
Python: TDesktop('tdata').ToTelethon(...) returns an opentele2 TelegramClient ready for connect(). Node: build an mtcute TelegramClient with initConnectionOptions and importSession(toStringSession(...)).
use std::sync::Arc;
use grammers_client::Client;
use grammers_mtsender::SenderPool;
use grammers_session::storages::MemorySession;
use opentele2_core::api::{self, Versions};
use opentele2_core::tdata::TData;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let tdata = TData::load("tdata", b"", None)?;
let account = tdata.main_account().expect("folder has an account");
let desktop = api::profile(api::Client::Desktop, &Versions::offline());
let session = Arc::new(MemorySession::from(opentele2_grammers::session_data(account)));
let params = opentele2_grammers::connection_params(&desktop);
let SenderPool { runner, handle, .. } =
SenderPool::with_configuration(Arc::clone(&session), desktop.api_id, params);
let client = Client::new(handle);
let pool = tokio::spawn(runner.run());
let me = client.get_me().await?;
println!("{:?}", me.first_name());
client.disconnect();
pool.await?;
Ok(())
}Use the client flows
With the client feature, opentele2_grammers::client runs over anything that implements its
Invoker trait, which grammers_client::Client does. Flows that read or change session state also
take the grammers Session the pool was built with, because grammers 0.11 keeps the client’s
session private.
| Flow | Function |
|---|---|
| Self user id | get_me_id(&client) |
| QR login with 2FA | qr_ |
| Sessions | sessions, current_session, terminate_session, terminate_all_sessions, sessions_table, is_official_app |
| Consistency checks | run_ |
| tdata from a client | account_, tdata_from_client(...) |
Python runs the same flows as TelegramClient methods (QRLoginToNewClient, GetSessions, PrintSessions, RunConsistencyChecks, ToTDesktop); Node runs them over an mtcute client from opentele2/mtcute (qrLoginToNewClient, getSessions, formatSessions, runConsistencyChecks, tdataFromClient).
Python runs the same flows as TelegramClient methods (QRLoginToNewClient, GetSessions, PrintSessions, RunConsistencyChecks, ToTDesktop); Node runs them over an mtcute client from opentele2/mtcute (qrLoginToNewClient, getSessions, formatSessions, runConsistencyChecks, tdataFromClient).
// cargo add opentele2-grammers --features client
use grammers_client::Client;
use opentele2_grammers::client::{self, ClientError};
async fn show(client: &Client) -> Result<(), ClientError> {
println!("logged in as {}", client::get_me_id(client).await?);
println!("{}", client::sessions_table(client).await?); // the PrintSessions table
println!("official app: {}", client::is_official_app(client).await?);
Ok(())
}The crate has no warning channel: the QR attempt warnings are not emitted and the consistency
warning is left to you (ConsistencyReport::warning). No flow here logs out.
Go back from grammers
account_from_session(&data, index) is the inverse of session_data: the home DC key and the self
user of a SessionData become a tdata account. The client to tdata guide
saves it as a folder, from saved data or from a live client.
Next
- Sessions: what
SessionDataholds and the other formats. - Consistency and sessions: the checks and session admin over grammers.
- Reference: Python · Node · Rust.