WTelegramClient Documentation

repository·master·Indexed 23 days ago

https://github.com/wiz0u/wtelegramclient

A 100% C# and .NET implementation of the Telegram MTProto API. WTelegramClient allows developers to programmatically control user accounts with the same capabilities as a full Telegram GUI client. It supports .NET 5.0+, .NET Standard 2.0, and Xamarin/Mono.Android. The library provides tools for handling authentication, calling Telegram API methods via the TL namespace, managing updates through UpdateManager, and performing common tasks like sending messages, downloading media, and fetching chat history.

Tokens
17.8K
Snippets
29
Records
64
Agent score
79%

What's inside WTelegramClient

  1. Monitor Telegram events and new messages

    master
    You can monitor real-time updates using the client.OnUpdates callback event or the UpdateManager class. To monitor new messages specifically, look for updates containing UpdateNewMessage and check the Message.peer_id field to filter for specific chats.
  2. Implement Secret Chats

    master

    WTelegramClient supports Secret Chats with the following characteristics:

    • Compatibility: May not support very old Telegram clients (pre-2018 using MTProto 1.0).
    • Storage: Outgoing messages are not stored by the library. Incoming messages are not stored on disk by default (storage is the user's responsibility).
    • Message Ordering: By default, DecryptMessage uses fillGaps: true, which ensures messages are delivered in the correct order by keeping them in memory until missing messages are obtained. If missing messages are never received, incoming messages may get stuck.
    • Session Files: Secret Chat file data is specific to the logged-in user. Use a unique file name if switching users.
    • Filtering Requests: To accept Secret Chat requests only from a specific user, check the OnUpdates handler:
    await Secrets.HandleUpdate(ue, ue.chat is EncryptedChatRequested ecr && ecr.admin_id == EXPECTED_USER_ID);
    • Key Negotiation: New encryption keys are negotiated every 100 messages or every week. If negotiation fails to complete by 200 messages, the chat is aborted.
    await Secrets.HandleUpdate(ue, ue.chat is EncryptedChatRequested ecr && ecr.admin_id == EXPECTED_USER_ID);
  3. How to resolve Peers into Users or Chats

    master

    Many API responses (including UpdatesBase) contain users and chats dictionaries. These dictionaries provide the necessary details and access_hash required to interact with specific entities.

    To work with these entities effectively:

    1. Use IPeerResolver: Root structures that contain these dictionaries implement IPeerResolver. You can call .UserOrChat(peer) to resolve a Peer object into a User or a ChatBase (like Chat or Channel).
    2. Use CollectUsersChats: Use this helper method to aggregate users and chats into your own local dictionaries. This is crucial for handling Updates where Telegram might send incomplete structures.
    3. Handle Missing Data: If you receive an UpdateShortMessage or UpdateShortChatMessage for a user not in your local dictionaries, use Updates_GetDifference to fetch the missing information.
    private Dictionary<long, User> _users = new();
    private Dictionary<long, ChatBase> _chats = new();
    
    // Collecting from dialogs
    var dialogs = await client.Messages_GetAllDialogs();
    dialogs.CollectUsersChats(_users, _chats);
    
    // Collecting from updates
    private async Task OnUpdates(UpdatesBase updates)
    {
        updates.CollectUsersChats(_users, _chats);
        
        // Resolving a peer
        var firstPeer = dialogs.UserOrChat(dialogs.dialogs[0].Peer);
        if (firstPeer is User firstUser) Console.WriteLine($"First dialog is with user {firstUser}");
        else if (firstPeer is ChatBase firstChat) Console.WriteLine($"First dialog is {firstChat}");
    }
    
    // Recovering gaps for short messages
    if (updates is UpdateShortMessage usm && !_users.ContainsKey(usm.user_id))
    {
        var fullDiff = await client.Updates_GetDifference(usm.pts - usm.pts_count, usm.date, 0);
        fullDiff.CollectUsersChats(_users, _chats);
    }
  4. Handle multiple user accounts

    master

    To manage multiple Telegram accounts on the same machine, do not attempt to log out and log in with different credentials using a single session file, as this requires manual verification codes each time.

    Instead, use a unique session file for each user. You can achieve this by providing a different filename or folder for the session_pathname within your Config callback.

    To run multiple accounts in parallel, create multiple instances of WTelegram.Client, each with a Config callback that selects its own specific session file.

  5. Handle Telegram updates and notifications

    master

    The Client class provides two primary events to handle asynchronous notifications sent by Telegram servers (such as new messages or status changes) that occur independently of your direct API requests:

    • OnUpdates: Triggered when Telegram sends Updates.
    • OnOther: Triggered when Telegram sends other notifications.

    For a more streamlined experience, you can use the UpdateManager class to simplify the handling of these updates.

  6. Understand Telegram Client API terminology

    master

    The library uses specific terminology that may differ from the standard Telegram user interface:

    • Channel: A large or public chat group (often called a supergroup) or a broadcast channel.
    • Chat: A private basic chat group with fewer than 200 members. Note that most groups you interact with are actually Channel types.
    • chats: A general term referring to either Chat or Channel objects (excludes private user DMs).
    • Peer: An abstraction representing a Chat, Channel, or User.
    • Dialog: The status of a chat with a Peer (includes last message, unread count, etc.), representing a single line in a chat list.
    • Access Hash: A required security token used when interacting with users, channels, or other resources.
    • DC (DataCenter): Regional servers used by Telegram.
    • Session / Authorization: The pairing between a specific device and a phone number.
    • Participant: A member or subscriber of a chat group or channel.
  7. Store session data in a database or custom location

    master
    By default, WTelegramClient uses files for session storage. To use a database or any other storage mechanism, pass a custom Stream-derived class to the WTelegram.Client constructor via the sessionStore parameter. This custom stream must implement both reading (for the initial call to Length and Read) and writing (for subsequent Write calls) of the session data.
  8. How to use IDs and access_hash to avoid invalid peer errors

    master

    Unlike the Telegram Bot API, the Telegram Client API requires an access_hash to interact with channels, users, and other entities. Using only an ID will result in errors like CHANNEL_INVALID or USER_ID_INVALID.

    An access_hash is a proof that the logged-in user is authorized to access that specific resource.

    How to obtain an access_hash:

    Obtain description structures (such as Channel, User, Photo, or Document) through:

    • Receiving updates.
    • Querying API methods like Messages_GetAllDialogs or Contacts_ResolveUsername.
    • Using helper methods like UserOrChat or CollectUsersChats.

    How to use it in API calls:

    When calling an API method that requires an Input... structure (like InputPeer, InputChannel, or InputUser):

    • Recommended: Pass the description structure (e.g., the User or Channel object) directly. The library uses implicit conversion operators to automatically create the required Input... structure.
    • Manual: Extract the access_hash from the description structure and manually construct the Input... object.
  9. Quickstart: Basic Login with LoginUserIfNeeded

    master

    The simplest way to connect to Telegram is using LoginUserIfNeeded(). This method handles the interactive login process, including prompting for api_id, api_hash, phone_number, and verification_code in the console.

    Note: You must obtain your api_id and api_hash from the Telegram API development tools page.

    static async Task Main(string[] _)
    {
        using var client = new WTelegram.Client();
        var myself = await client.LoginUserIfNeeded();
        Console.WriteLine($"We are logged-in as {myself} (id {myself.id})");
    }
  10. Use the simplified Login loop pattern

    master

    For more control over the login flow (e.g., in GUI apps like WinForms or web apps like ASP.NET), use the simplified constructor and the Login method. This allows you to handle each step of the authentication process manually by checking the string returned by client.Login(loginInfo).

    Common return values from client.Login:

    • "verification_code": Next step is providing the code.
    • "name": Next step is providing first/last name for sign-up.
    • "password": Next step is providing the 2FA password.
    • default: No specific config needed, continue loop.
    WTelegram.Client client = new WTelegram.Client(YOUR_API_ID, "YOUR_API_HASH");
    await DoLogin("+12025550156");
    
    async Task DoLogin(string loginInfo)
    {
       while (client.User == null)
          switch (await client.Login(loginInfo))
          {
             case "verification_code": Console.Write("Code: "); loginInfo = Console.ReadLine(); break;
             case "name": loginInfo = "John Doe"; break;
             case "password": loginInfo = "secret!"; break;
             default: loginInfo = null; break;
          }
       Console.WriteLine($"We are logged-in as {client.User} (id {client.User.id})");
    }
  11. Retrieve the current user's contacts list

    master

    You can retrieve contacts using two different approaches:

    1. Simple Method: Use Contacts_GetContacts() to get a list of contacts currently in the account.
    2. GDPR Export (Takeout) Method: For a more comprehensive export, use the Account_InitTakeoutSession system. This involves initializing a session, invoking methods via InvokeWithTakeout, and finally finishing the session with Account_FinishTakeoutSession.
    // Simple Method
    var contacts = await client.Contacts_GetContacts();
    foreach (User contact in contacts.users.Values)
        Console.WriteLine($"{contact} {contact.phone}");
    
    // Takeout Method
    using TL.Methods;
    var takeout = await client.Account_InitTakeoutSession(contacts: true);
    var finishTakeout = new Account_FinishTakeoutSession();
    try
    {
        var savedContacts = await client.InvokeWithTakeout(takeout.id, new Contacts_GetSaved());
        foreach (SavedPhoneContact contact in savedContacts)
            Console.WriteLine($"{contact.first_name} {contact.last_name} {contact.phone}, added on {contact.date}");
        finishTakeout.flags = Account_FinishTakeoutSession.Flags.success;
    }
    finally
    {
        await client.InvokeWithTakeout(takeout.id, finishTakeout);
    }
  12. Migrate from TLSharp to WTelegramClient

    master

    WTelegramClient provides a simpler and more secure approach than TLSharp.

    Key Migration Points:

    • Method Calling: All API methods have dedicated async methods. Use the pattern await client.Method_Name(params). Note that in the method name, dots are replaced with underscores (e.g., Auth_SendCode becomes Auth_SendCode).
    • Session Management: Sessions are created or resumed automatically on startup. WTelegramClient session files are incompatible with TLSharp .dat files; you must create new sessions.
    • Simplified Login: Do not manually call Auth_SendCode, SignIn, or SignUp. Instead, call await client.LoginUserIfNeeded() after creating the client. The library automatically handles:
      • Resuming existing sessions.
      • 2FA password requests.
      • Email registration and verification.
      • Account sign-up (first/last name).
      • Resending verification codes.
    • Features: WTelegramClient supports MTProto v2.0, transport obfuscation, protocol security checks, MTProto Proxy, and real-time updates.