Client

Struct Client 

Source
pub struct Client(/* private fields */);
Expand description

A client capable of connecting to Telegram and invoking requests.

This structure is the “entry point” of the library, from which you can start using the rest.

This structure owns all the necessary connections to Telegram, and has implementations for the most basic methods, such as connecting, signing in, or processing network events.

On drop, all state is synchronized to the session. The Session must be explicitly saved to disk with its corresponding save method for persistence.

Implementations§

Source§

impl Client

Method implementations related with the authentication of the user into the API.

Most requests to the API require the user to have authorized their key, stored in the session, before being able to use them.

Source

pub async fn is_authorized(&self) -> Result<bool, InvocationError>

Returns true if the current account is authorized. Otherwise, logging in will be required before being able to invoke requests.

This will likely be the first method you want to call on a connected Client. After you determine if the account is authorized or not, you will likely want to use either Client::bot_sign_in or Client::request_login_code.

§Examples
if client.is_authorized().await? {
    println!("Client already authorized and ready to use!");
} else {
    println!("Client is not authorized, you will need to sign_in!");
}
Source

pub async fn bot_sign_in( &self, token: &str, api_hash: &str, ) -> Result<User, InvocationError>

Signs in to the bot account associated with this token.

This is the method you need to call to use the client under a bot account.

It is recommended to save the session on successful login, and if saving fails, it is recommended to Client::sign_out. If the session cannot be saved, then the authorization will be “lost” in the list of logged-in clients, since it is unaccessible.

§Examples
// Note: these values are obviously fake.
//       Obtain your own with the developer's phone at https://my.telegram.org.
const API_HASH: &str = "514727c32270b9eb8cc16daf17e21e57";
//       Obtain your own by talking to @BotFather via a Telegram app.
const TOKEN: &str = "776609994:AAFXAy5-PawQlnYywUlZ_b_GOXgarR3ah_yq";

let user = match client.bot_sign_in(TOKEN, API_HASH).await {
    Ok(user) => user,
    Err(err) => {
        println!("Failed to sign in as a bot :(\n{}", err);
        return Err(err.into());
    }
};

if let Some(first_name) = user.first_name() {
    println!("Signed in as {}!", first_name);
} else {
    println!("Signed in!");
}
Source

pub async fn request_login_code( &self, phone: &str, api_hash: &str, ) -> Result<LoginToken, InvocationError>

Requests the login code for the account associated to the given phone number via another Telegram application or SMS.

This is the method you need to call before being able to sign in to a user account. After you obtain the code and it’s inside your program (e.g. ask the user to enter it via the console’s standard input), you will need to Client::sign_in to complete the process.

§Examples
// Note: these values are obviously fake.
//       Obtain your own with the developer's phone at https://my.telegram.org.
const API_HASH: &str = "514727c32270b9eb8cc16daf17e21e57";
//       The phone used here does NOT need to be the same as the one used by the developer
//       to obtain the API ID and hash.
const PHONE: &str = "+1 415 555 0132";

if !client.is_authorized().await? {
    // We're not logged in, so request the login code.
    client.request_login_code(PHONE, API_HASH).await?;
}
Source

pub async fn sign_in( &self, token: &LoginToken, code: &str, ) -> Result<User, SignInError>

Signs in to the user account.

You must call Client::request_login_code before using this method in order to obtain necessary login token, and also have asked the user for the login code.

It is recommended to save the session on successful login, and if saving fails, it is recommended to Client::sign_out. If the session cannot be saved, then the authorization will be “lost” in the list of logged-in clients, since it is unaccessible.

§Examples

 async fn f(client: grammers_client::Client) -> Result<(), Box<dyn std::error::Error>> {
fn ask_code_to_user() -> String {
    unimplemented!()
}

let token = client.request_login_code(PHONE, API_HASH).await?;
let code = ask_code_to_user();

let user = match client.sign_in(&token, &code).await {
    Ok(user) => user,
    Err(SignInError::PasswordRequired(_token)) => panic!("Please provide a password"),
    Err(SignInError::SignUpRequired { terms_of_service: tos }) => panic!("Sign up required"),
    Err(err) => {
        println!("Failed to sign in as a user :(\n{}", err);
        return Err(err.into());
    }
};

if let Some(first_name) = user.first_name() {
    println!("Signed in as {}!", first_name);
} else {
  println!("Signed in!");
}
Source

pub async fn check_password( &self, password_token: PasswordToken, password: impl AsRef<[u8]>, ) -> Result<User, SignInError>

Sign in using two-factor authentication (user password).

PasswordToken can be obtained from SignInError::PasswordRequired error after the Client::sign_in method fails.

§Examples
use grammers_client::SignInError;

fn get_user_password(hint: &str) -> Vec<u8> {
    unimplemented!()
}


// ... enter phone number, request login code ...

let user = match client.sign_in(&token, &code).await {
    Err(SignInError::PasswordRequired(password_token) ) => {
        let mut password = get_user_password(password_token.hint().unwrap());

        client
            .check_password(password_token, password)
            .await.unwrap()
    }
    Ok(user) => user,
    Ok(_) => panic!("Sign in required"),
    Err(err) => {
        panic!("Failed to sign in as a user :(\n{err}");
    }
};
Source

pub async fn sign_out(&self) -> Result<LoggedOut, InvocationError>

Signs out of the account authorized by this client’s session.

If the client was not logged in, this method returns false.

The client is not disconnected after signing out.

Note that after using this method you will have to sign in again. If all you want to do is disconnect, simply drop the Client instance.

§Examples
if client.sign_out().await.is_ok() {
    println!("Signed out successfully!");
} else {
    println!("No user was signed in, so nothing has changed...");
}
Source

pub fn disconnect(&self)

Signals all clients sharing the same sender pool to disconnect.

Source§

impl Client

Method implementations related to dealing with bots.

Source

pub fn inline_query<C: Into<PeerRef>>( &self, bot: C, query: &str, ) -> InlineResultIter

Perform an inline query to the specified bot.

The query text may be empty.

The return value is used like any other async iterator, by repeatedly calling next.

Executing the query will fail if the input peer does not actually represent a bot account supporting inline mode.

§Examples
// This is equivalent to writing `@bot inline query` in a Telegram app.
let mut inline_results = client.inline_query(bot, "inline query");

while let Some(result) = inline_results.next().await? {
    println!("{}", result.title().unwrap());
}
Source

pub async fn edit_inline_message<M: Into<InputMessage>>( &self, message_id: InputBotInlineMessageId, input_message: M, ) -> Result<bool, InvocationError>

Edits an inline message sent by a bot.

Similar to Client::send_message, advanced formatting can be achieved with the options offered by InputMessage.

Source§

impl Client

Method implementations related to dealing with peers.

Source

pub async fn resolve_username( &self, username: &str, ) -> Result<Option<Peer>, InvocationError>

Resolves a username into the peer that owns it, if any.

Note that this method is expensive to call, and can quickly cause long flood waits.

§Examples
if let Some(peer) = client.resolve_username("username").await? {
    println!("Found peer!: {:?}", peer.name());
}
Source

pub async fn get_me(&self) -> Result<User, InvocationError>

Fetch full information about the currently logged-in user.

Although this method is cheap to call, you might want to cache the results somewhere.

§Examples
println!("Displaying full user information of the logged-in user:");
dbg!(client.get_me().await?);
Source

pub fn iter_participants<C: Into<PeerRef>>(&self, chat: C) -> ParticipantIter

Iterate over the participants of a chat.

The participants are returned in no particular order.

When used to iterate the participants of “user”, the iterator won’t produce values.

§Examples
let mut participants = client.iter_participants(chat);

while let Some(participant) = participants.next().await? {
    println!(
        "{} has role {:?}",
        participant.user.first_name().unwrap_or(&participant.user.bare_id().to_string()),
        participant.role
    );
}
Source

pub async fn kick_participant<C: Into<PeerRef>, U: Into<PeerRef>>( &self, chat: C, user: U, ) -> Result<(), InvocationError>

Kicks the participant from the chat.

This will fail if you do not have sufficient permissions to perform said operation, or the target user is the logged-in account. Use Self::delete_dialog for the latter instead.

The kicked user will be able to join after being kicked (they are not permanently banned).

Kicking someone who was not in the chat prior to running this method will be able to join after as well (effectively unbanning them).

When used to kick users from “user” chat, nothing will be done.

§Examples
match client.kick_participant(chat, user).await {
    Ok(_) => println!("user is no more >:D"),
    Err(_) => println!("Kick failed! Are you sure you're admin?"),
};
Source

pub fn set_banned_rights<C: Into<PeerRef>, U: Into<PeerRef>>( &self, channel: C, user: U, ) -> BannedRightsBuilder<impl Future<Output = Result<(), InvocationError>>>

Set the banned rights for a specific user.

Returns a new BannedRightsBuilder instance. Check out the documentation for that type to learn more about what restrictions can be applied.

Nothing is done until it is awaited, at which point it might result in error if you do not have sufficient permissions to ban the user in the input chat.

By default, the user has all rights, and you need to revoke those you want to take away from the user by setting the permissions to false. This means that not taking away any permissions will effectively unban someone, granting them all default user permissions.

By default, the ban is applied forever, but this can be changed to a shorter duration.

The default group rights are respected, despite individual restrictions.

§Example
// This user keeps spamming pepe stickers, take the sticker permission away from them
let res = client
    .set_banned_rights(chat, user)
    .send_stickers(false)
    .await;

match res {
    Ok(_) => println!("No more sticker spam!"),
    Err(_) => println!("Ban failed! Are you sure you're admin?"),
};
Source

pub fn set_admin_rights<C: Into<PeerRef>, U: Into<PeerRef>>( &self, channel: C, user: U, ) -> AdminRightsBuilder<impl Future<Output = Result<(), InvocationError>>>

Set the administrator rights for a specific user.

Returns a new AdminRightsBuilder instance. Check out the documentation for that type to learn more about what rights can be given to administrators.

Nothing is done until it is awaited, at which point it might result in error if you do not have sufficient permissions to grant those rights to the other user.

By default, no permissions are granted, and you need to specify those you want to grant by setting the permissions to true. This means that not granting any permission will turn the user into a normal user again, and they will no longer be an administrator.

The change is applied forever and there is no way to set a specific duration. If the user should only be an administrator for a set period of time, the administrator permissions must be manually revoked at a later point in time.

§Example
// Let the user pin messages and ban other people
let res = client.set_admin_rights(chat, user)
    .load_current()
    .await?
    .pin_messages(true)
    .ban_users(true)
    .await?;
Source

pub fn iter_profile_photos<C: Into<PeerRef>>(&self, peer: C) -> ProfilePhotoIter

Iterate over the history of profile photos for the given peer.

Note that the current photo might not be present in the history, and to avoid doing more work when it’s generally not needed (the photo history tends to be complete but in some cases it might not be), it’s up to you to fetch this photo from the full channel.

Note that you cannot use these photos to send them as messages directly. They must be downloaded first, then uploaded, and finally sent.

§Examples
let mut photos = client.iter_profile_photos(peer);

while let Some(photo) = photos.next().await? {
    println!("Did you know peer has a photo with ID {}?", photo.id());
}
Source

pub async fn resolve_peer<C: Into<PeerRef>>( &self, peer: C, ) -> Result<Peer, InvocationError>

Convert a PeerRef back into a Peer.

§Example
let peer = client.resolve_peer(peer).await?;

println!("Found peer: {}", peer.name().unwrap_or(&peer.id().to_string()));
Source

pub async fn get_permissions<C: Into<PeerRef>, U: Into<PeerRef>>( &self, chat: C, user: U, ) -> Result<ParticipantPermissions, InvocationError>

Get permissions of participant user from chat chat.

§Panics

Panics if chat isn’t channel or chat, and if user isn’t user

Source

pub async fn join_chat<C: Into<PeerRef>>( &self, chat: C, ) -> Result<Option<Peer>, InvocationError>

Join a public group or channel.

A channel is public if it has a username. To join private chats, Client::accept_invite_link should be used instead.

Source

pub fn action<C: Into<PeerRef>>(&self, peer: C) -> ActionSender

Send a message action (such as typing, uploading photo, or viewing an emoji interaction)

§Examples

Do a one-shot pulse and let it fade away

use grammers_tl_types::enums::SendMessageAction;

client
    .action(peer)
    .oneshot(SendMessageAction::SendMessageTypingAction)
    .await?;

Repeat request until the future is done


use grammers_tl_types as tl;

let heavy_task = async {
    tokio::time::sleep(Duration::from_secs(10)).await;

    42
};

tokio::pin!(heavy_task);

let (task_result, _) = client
    .action(peer)
    .repeat(
        // most clients doesn't actually show progress of an action
        || tl::types::SendMessageUploadDocumentAction { progress: 0 },
        heavy_task
    )
    .await;

// Note: repeat function does not cancel actions automatically, they will just fade away

assert_eq!(task_result, 42);

Cancel any actions

client.action(peer).cancel().await?;
Source§

impl Client

Method implementations related to open conversations.

Source

pub fn iter_dialogs(&self) -> DialogIter

Returns a new iterator over the dialogs.

While iterating, the update state for any broadcast channel or megagroup will be set if it was unknown before. When the update state is set for these peers, the library can actively check to make sure it’s not missing any updates from them (as long as the queue limit for updates is larger than zero).

§Examples
let mut dialogs = client.iter_dialogs();

while let Some(dialog) = dialogs.next().await? {
    let peer = dialog.peer();
    println!("{} ({})", peer.name().unwrap_or_default(), peer.id());
}
Source

pub async fn delete_dialog<C: Into<PeerRef>>( &self, peer: C, ) -> Result<(), InvocationError>

Deletes a dialog, effectively removing it from your list of open conversations.

The dialog is only deleted for yourself.

Deleting a dialog effectively clears the message history and “kicks” you from it.

For groups and channels, this is the same as leaving said chat. This method does not delete the chat itself (the chat still exists and the other members will remain inside).

§Examples
// Consider making a backup before, you will lose access to the messages in peer!
client.delete_dialog(peer).await?;
Source

pub async fn mark_as_read<C: Into<PeerRef>>( &self, peer: C, ) -> Result<(), InvocationError>

Mark a peer as read.

If you want to get rid of all the mentions (for example, a voice note that you have not listened to yet), you need to also use Client::clear_mentions.

§Examples
client.mark_as_read(peer).await?;
Source

pub async fn clear_mentions<C: Into<PeerRef>>( &self, peer: C, ) -> Result<(), InvocationError>

Clears all pending mentions from a peer, marking them as read.

§Examples
client.clear_mentions(peer).await?;
Source§

impl Client

Method implementations related to uploading or downloading files.

Source

pub fn iter_download<D: Downloadable>(&self, downloadable: &D) -> DownloadIter

Returns a new iterator over the contents of a media document that will be downloaded.

§Examples
let mut file_bytes = Vec::new();
let mut download = client.iter_download(&downloadable);

while let Some(chunk) = download.next().await? {
    file_bytes.extend(chunk);
}

// The file is now downloaded in-memory, inside `file_bytes`!
Source

pub async fn download_media<D: Downloadable, P: AsRef<Path>>( &self, downloadable: &D, path: P, ) -> Result<(), Error>

Downloads a media file into the specified path.

If the file already exists, it will be overwritten.

This is a small wrapper around Client::iter_download for the common case of wanting to save the file locally.

§Examples
client.download_media(&downloadable, "/home/username/photos/holidays.jpg").await?;
Source

pub async fn upload_stream<S: AsyncRead + Unpin>( &self, stream: &mut S, size: usize, name: String, ) -> Result<Uploaded, Error>

Uploads an async stream to Telegram servers.

The file is not sent to any peer, but can be used as media when sending messages for a certain period of time (less than a day). You can use this uploaded file multiple times.

Refer to InputMessage to learn more uses for uploaded_file.

The stream size must be known beforehand. If this is not possible, you might need to process the entire async stream to determine its size, and then use the size and the downloaded buffer.

The stream size may be less or equal to the actual length of the stream, but not more. If it’s less, you may continue to read from the stream after the method returns. If it’s more, the method will fail because it does not have enough data to read.

Note that Telegram uses the file name in certain methods, for example, to make sure the file is an image when trying to use send the file as photo media, so it is important that the file name at least uses the right extension, even if the name is a dummy value. If the input file name is empty, the non-empty dummy value “a” will be used instead. Because it has no extension, you may not be able to use the file in certain methods.

§Examples
use grammers_client::InputMessage;

// In-memory `Vec<u8>` buffers can be used as async streams
let size = some_vec.len();
let mut stream = std::io::Cursor::new(some_vec);
let uploaded_file = client.upload_stream(&mut stream, size, "sleep.jpg".to_string()).await?;

client.send_message(peer, InputMessage::new().text("Zzz...").photo(uploaded_file)).await?;
Source

pub async fn upload_file<P: AsRef<Path>>( &self, path: P, ) -> Result<Uploaded, Error>

Uploads a local file to Telegram servers.

The file is not sent to any peer, but can be used as media when sending messages for a certain period of time (less than a day). You can use this uploaded file multiple times.

Refer to InputMessage to learn more uses for uploaded_file.

If you need more control over the uploaded data, such as performing only a partial upload or with a different name, use Client::upload_stream instead.

§Examples
use grammers_client::InputMessage;

let uploaded_file = client.upload_file("/home/username/photos/holidays.jpg").await?;

client.send_message(peer, InputMessage::new().text("Check this out!").photo(uploaded_file)).await?;
Source§

impl Client

Method implementations related to sending, modifying or getting messages.

Source

pub async fn send_message<C: Into<PeerRef>, M: Into<InputMessage>>( &self, peer: C, message: M, ) -> Result<Message, InvocationError>

Sends a message to the desired peer.

This method can also be used to send media such as photos, videos, documents, polls, etc.

If you want to send a local file as media, you will need to use Client::upload_file first.

Refer to InputMessage to learn more formatting options, such as using markdown or adding buttons under your message (if you’re logged in as a bot).

See also: Message::respond, Message::reply.

§Examples
client.send_message(peer, "Boring text message :-(").await?;

use grammers_client::InputMessage;

client.send_message(peer, InputMessage::new().text("Sneaky message").silent(true)).await?;
Source

pub async fn send_album<C: Into<PeerRef>>( &self, peer: C, medias: Vec<InputMedia>, ) -> Result<Vec<Option<Message>>, InvocationError>

Sends a album to the desired peer.

This method can also be used to send a bunch of media such as photos, videos, documents, polls, etc.

If you want to send a local file as media, you will need to use Client::upload_file first.

Refer to InputMedia to learn more formatting options, such as using markdown.

See also: Message::respond_album, Message::reply_album.

§Examples
use grammers_client::InputMedia;

client.send_album(peer, vec![InputMedia::new().caption("A album").photo_url("https://example.com/cat.jpg")]).await?;
Source

pub async fn edit_message<C: Into<PeerRef>, M: Into<InputMessage>>( &self, peer: C, message_id: i32, new_message: M, ) -> Result<(), InvocationError>

Edits an existing message.

Similar to Client::send_message, advanced formatting can be achieved with the options offered by InputMessage.

See also: Message::edit.

§Examples
let old_message_id = 123;
client.edit_message(peer, old_message_id, "New text message").await?;
Source

pub async fn delete_messages<C: Into<PeerRef>>( &self, peer: C, message_ids: &[i32], ) -> Result<usize, InvocationError>

Deletes up to 100 messages in a peer.

Warning: when deleting messages from small group peers or private conversations, this method cannot validate that the provided message IDs actually belong to the input peer due to the way Telegram’s API works. Make sure to pass correct Message::id’s.

The messages are deleted for both ends.

The amount of deleted messages is returned (it might be less than the amount of input message IDs if some of them were already missing). It is not possible to find out which messages were actually deleted, but if the request succeeds, none of the specified message IDs will appear in the message history from that point on.

See also: Message::delete.

§Examples
let message_ids = [123, 456, 789];

// Careful, these messages will be gone after the method succeeds!
client.delete_messages(peer, &message_ids).await?;
Source

pub async fn forward_messages<C: Into<PeerRef>, S: Into<PeerRef>>( &self, destination: C, message_ids: &[i32], source: S, ) -> Result<Vec<Option<Message>>, InvocationError>

Forwards up to 100 messages from source into destination.

For consistency with other methods, the peer upon which this request acts comes first (destination), and then the source peer.

Returns the new forwarded messages in a list. Those messages that could not be forwarded will be None. The length of the resulting list is the same as the length of the input message IDs, and the indices from the list of IDs map to the indices in the result so you can find which messages were forwarded and which message they became.

See also: Message::forward_to.

§Examples
let message_ids = [123, 456, 789];

let messages = client.forward_messages(destination, &message_ids, source).await?;
let fwd_count = messages.into_iter().filter(Option::is_some).count();
println!("Forwarded {} out of {} messages!", fwd_count, message_ids.len());
Source

pub async fn get_reply_to_message( &self, message: &Message, ) -> Result<Option<Message>, InvocationError>

Gets the Message to which the input message is replying to.

See also: Message::get_reply.

§Examples
if let Some(reply) = client.get_reply_to_message(&message).await? {
    println!("The reply said: {}", reply.text());
}
Source

pub fn iter_messages<C: Into<PeerRef>>(&self, peer: C) -> MessageIter

Iterate over the message history of a peer, from most recent to oldest.

§Examples
// Note we're setting a reasonable limit, or we'd print out ALL the messages in peer!
let mut messages = client.iter_messages(peer).limit(100);

while let Some(message) = messages.next().await? {
    println!("{}", message.text());
}
Source

pub fn search_messages<C: Into<PeerRef>>(&self, peer: C) -> SearchIter

Iterate over the messages that match certain search criteria.

This allows you to search by text within a peer or filter by media among other things.

§Examples
// Let's print all the people who think grammers is cool.
let mut messages = client.search_messages(peer).query("grammers is cool");

while let Some(message) = messages.next().await? {
    let sender = message.sender().unwrap();
    println!("{}", sender.name().unwrap_or(&sender.id().to_string()));
}
Source

pub fn search_all_messages(&self) -> GlobalSearchIter

Iterate over the messages that match certain search criteria, without being restricted to searching in a specific peer. The downside is that this global search supports less filters.

This allows you to search by text within a peer or filter by media among other things.

§Examples
// Let's print all the peers were people think grammers is cool.
let mut messages = client.search_all_messages().query("grammers is cool");

while let Some(message) = messages.next().await? {
    println!("{}", message.peer().unwrap().name().unwrap_or(&message.peer().unwrap().id().to_string()));
}
Source

pub async fn get_messages_by_id<C: Into<PeerRef>>( &self, peer: C, message_ids: &[i32], ) -> Result<Vec<Option<Message>>, InvocationError>

Get up to 100 messages using their ID.

Returns the new retrieved messages in a list. Those messages that could not be retrieved or do not belong to the input peer will be None. The length of the resulting list is the same as the length of the input message IDs, and the indices from the list of IDs map to the indices in the result so you can map them into the new list.

§Examples
let message_ids = [123, 456, 789];

let messages = client.get_messages_by_id(peer, &message_ids).await?;
let count = messages.into_iter().filter(Option::is_some).count();
println!("{} out of {} messages were deleted!", message_ids.len() - count, message_ids.len());
Source

pub async fn get_pinned_message<C: Into<PeerRef>>( &self, peer: C, ) -> Result<Option<Message>, InvocationError>

Get the latest pin from a peer.

§Examples
if let Some(message) = client.get_pinned_message(peer).await? {
    println!("There is a message pinned: {}", message.text());
} else {
    println!("There are no messages pinned");
}
Source

pub async fn pin_message<C: Into<PeerRef>>( &self, peer: C, message_id: i32, ) -> Result<(), InvocationError>

Pin a message in the peer. This will not notify any users.

§Examples
let message_id = 123;
client.pin_message(peer, message_id).await?;
Source

pub async fn unpin_message<C: Into<PeerRef>>( &self, peer: C, message_id: i32, ) -> Result<(), InvocationError>

Unpin a message from the peer.

§Examples
let message_id = 123;
client.unpin_message(peer, message_id).await?;
Source

pub async fn unpin_all_messages<C: Into<PeerRef>>( &self, peer: C, ) -> Result<(), InvocationError>

Unpin all currently-pinned messages from the peer.

§Examples
client.unpin_all_messages(peer).await?;
Source

pub async fn send_reactions<C: Into<PeerRef>, R: Into<InputReactions>>( &self, peer: C, message_id: i32, reactions: R, ) -> Result<(), InvocationError>

Send reaction.

§Examples

Via emoticon

let message_id = 123;

client.send_reactions(peer, message_id, "👍").await?;

Make animation big & Add to recent

use grammers_client::types::InputReactions;

let message_id = 123;
let reactions = InputReactions::emoticon("🤯").big().add_to_recent();

client.send_reactions(peer, message_id, reactions).await?;

Remove reactions

use grammers_client::types::InputReactions;

let message_id = 123;

client.send_reactions(peer, message_id, InputReactions::remove()).await?;
Source§

impl Client

Method implementations directly related with network connectivity.

Source

pub fn new(sender_pool: &SenderPool) -> Self

Creates and returns a new client instance upon successful connection to Telegram.

If the session in the configuration did not have an authorization key, a new one will be created and the session will be saved with it.

The connection will be initialized with the data from the input configuration.

The grammers_mtsender::SenderPoolHandle does not keep a reference to the grammers_session::Session or api_id, but the SenderPool itself does, so the latter is used as input to guarantee that the values are correctly shared between the pool and the client handles.

§Examples
use std::sync::Arc;
use grammers_client::Client;
use grammers_session::storages::TlSession;
use grammers_mtsender::SenderPool;

// Note: these are example values and are not actually valid.
//       Obtain your own with the developer's phone at https://my.telegram.org.
const API_ID: i32 = 932939;

let session = Arc::new(TlSession::load_file_or_create("hello-world.session")?);
let pool = SenderPool::new(Arc::clone(&session), API_ID);
let client = Client::new(&pool);
Source

pub fn with_configuration( sender_pool: &SenderPool, configuration: ClientConfiguration, ) -> Self

Like Self::new but with a custom ClientConfiguration.

Source

pub async fn invoke<R: RemoteCall>( &self, request: &R, ) -> Result<R::Return, InvocationError>

Invoke a raw API call. This directly sends the request to Telegram’s servers.

Using function definitions corresponding to a different layer is likely to cause the responses to the request to not be understood.

Warning: this method is not part of the stability guarantees of semantic versioning. It may break during minor version changes (but not on patch version changes). Use with care.

§Examples
use grammers_tl_types as tl;

dbg!(client.invoke(&tl::functions::Ping { ping_id: 0 }).await?);
Source

pub async fn invoke_in_dc<R: RemoteCall>( &self, dc_id: i32, request: &R, ) -> Result<R::Return, InvocationError>

Like Self::invoke, but in the specified DC.

Source§

impl Client

Source

pub fn stream_updates( &self, updates: UnboundedReceiver<UpdatesLike>, configuration: UpdatesConfiguration, ) -> UpdateStream

Returns an asynchronous stream of processed updates.

The updates are guaranteed to be in order, and any gaps will be resolved.

The updates are wrapped in crate::Update to make them more convenient to use, but their raw type is still accessible to bridge any missing functionality.

Trait Implementations§

Source§

impl Clone for Client

Source§

fn clone(&self) -> Client

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl Freeze for Client

§

impl !RefUnwindSafe for Client

§

impl Send for Client

§

impl Sync for Client

§

impl Unpin for Client

§

impl !UnwindSafe for Client

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.