diff --git a/EXAMPLES.md b/EXAMPLES.md
index 2fcc816..88bf1de 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -1,4 +1,4 @@
-## Example programs using WTelegramClient
+# Example programs using WTelegramClient
For these examples to work as a fully-functional Program.cs, be sure to start with these lines:
```csharp
@@ -18,11 +18,12 @@ Remember that these are just simple example codes that you should adjust to your
In real production code, you might want to properly test the success of each operation or handle exceptions,
and avoid calling the same methods (like `Messages_GetAllChats`) repetitively.
-ℹ️ WTelegramClient covers 100% of Telegram Client API, much more than the examples below: check the [full API methods list](https://corefork.telegram.org/methods)!
-More examples can also be found in the [Examples folder](Examples) and in answers to [StackOverflow questions](https://stackoverflow.com/questions/tagged/wtelegramclient).
+➡️ Use Ctrl-F to search this page for the example matching your needs
+WTelegramClient covers 100% of Telegram Client API, much more than the examples below: check the [full API methods list](https://corefork.telegram.org/methods)!
+More examples can also be found in the [Examples folder](https://github.com/wiz0u/WTelegramClient/tree/master/Examples) and in answers to [StackOverflow questions](https://stackoverflow.com/questions/tagged/wtelegramclient).
-### Change logging settings
+## Change logging settings
By default, WTelegramClient logs are displayed on the Console screen.
If you are not in a Console app or don't want the logs on screen, you can redirect them as you prefer:
@@ -45,7 +46,7 @@ WTelegram.Helpers.Log = (lvl, str) => { };
The `lvl` argument correspond to standard [LogLevel values](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.loglevel#fields)
-### Send a message to someone by @username
+## Send a message to someone by @username
```csharp
var resolved = await client.Contacts_ResolveUsername("JsonDumpBot"); // username without the @
await client.SendMessageAsync(resolved, "/start");
@@ -55,7 +56,7 @@ If the username is invalid/unused, the API call raises an RpcException.*
-### Convert message to/from HTML or Markdown, and send it to ourself (Saved Messages)
+## Convert message to/from HTML or Markdown, and send it to ourself (Saved Messages)
```csharp
// HTML-formatted text:
var text = $"Hello dear {HtmlText.Escape(client.User.first_name)}\n" +
@@ -78,7 +79,7 @@ See [HTML formatting style](https://core.telegram.org/bots/api/#html-style) and
*Note: For the `tg://user?id=` notation to work, that user's access hash must have been collected first ([see below](#collect-access-hash))*
-### List all dialogs (chats/groups/channels/user chat) we are currently in
+## List all dialogs (chats/groups/channels/user chat) we are currently in
```csharp
var dialogs = await client.Messages_GetAllDialogs();
foreach (Dialog dialog in dialogs.dialogs)
@@ -98,7 +99,7 @@ Notes:
- To retrieve the dialog information about a specific [peer](README.md#terminology), use `client.Messages_GetPeerDialogs(inputPeer)`
-### List all chats (groups/channels NOT users) that we joined and send a message to one
+## List all chats (groups/channels NOT users) that we joined and send a message to one
```csharp
var chats = await client.Messages_GetAllChats();
foreach (var (id, chat) in chats.chats)
@@ -116,7 +117,7 @@ but the old `Chat` will be marked with flag [deactivated] and should not be used
- You can find a longer version of this method call in [Examples/Program_GetAllChats.cs](Examples/Program_GetAllChats.cs)
-### List the members from a chat
+## List the members from a chat
For a basic Chat: *(see Terminology in [ReadMe](README.md#terminology))*
```csharp
var chatFull = await client.Messages_GetFullChat(1234567890); // the chat we want
@@ -159,7 +160,7 @@ foreach (var participant in participants.participants) // This is the better way
*Note: It is not possible to list only the Deleted Accounts. Those will be automatically removed by Telegram from your group after a while*
-### Fetch all messages (history) from a chat
+## Fetch all messages (history) from a chat
```csharp
var chats = await client.Messages_GetAllChats();
InputPeer peer = chats.chats[1234567890]; // the chat we want
@@ -183,7 +184,7 @@ Notes:
- To mark the message history as read, use: `await client.ReadHistory(peer);`
-### Monitor all Telegram events happening for the user
+## Monitor all Telegram events happening for the user
This is done through the `client.OnUpdate` callback event.
Your event handler implementation can either return `Task.CompletedTask` or be an `async Task` method.
@@ -191,7 +192,7 @@ Your event handler implementation can either return `Task.CompletedTask` or be a
See [Examples/Program_ListenUpdates.cs](Examples/Program_ListenUpdates.cs).
-### Monitor new messages being posted in chats in real-time
+## Monitor new messages being posted in chats in real-time
You have to handle `client.OnUpdate` events containing an `UpdateNewMessage`.
@@ -200,7 +201,7 @@ See the `DisplayMessage` method in [Examples/Program_ListenUpdates.cs](Examples/
You can filter specific chats the message are posted in, by looking at the `Message.peer_id` field.
-### Downloading photos, medias, files
+## Downloading photos, medias, files
This is done using the helper method `client.DownloadFileAsync(file, outputStream)`
that simplifies the download of a photo/document/file once you get a reference to its location *(through updates or API calls)*.
@@ -208,7 +209,7 @@ that simplifies the download of a photo/document/file once you get a reference t
See [Examples/Program_DownloadSavedMedia.cs](Examples/Program_DownloadSavedMedia.cs) that download all media files you forward to yourself (Saved Messages)
-### Upload a media file and post it with caption to a chat
+## Upload a media file and post it with caption to a chat
```csharp
const int ChatId = 1234567890; // the chat we want
const string Filepath = @"C:\...\photo.jpg";
@@ -220,7 +221,7 @@ await client.SendMediaAsync(peer, "Here is the photo", inputFile);
```
-### Send a grouped media album using photos from various sources
+## Send a grouped media album using photos from various sources
```csharp
// Photo 1 already on Telegram: latest photo found in the user's Saved Messages
var history = await client.Messages_GetHistory(InputPeer.Self);
@@ -241,7 +242,7 @@ await client.SendAlbumAsync(InputPeer.Self, inputMedias, "My first album");
*Note: Don't mix Photos and file Documents in your album, it doesn't work well*
-### Forward or copy a message to another chat
+## Forward or copy a message to another chat
```csharp
// Determine which chats and message to forward/copy
var chats = await client.Messages_GetAllChats();
@@ -261,7 +262,7 @@ await client.SendMessageAsync(to_chat, msg.message, msg.media?.ToInputMedia(), e
```
-### Schedule a message to be sent to a chat
+## Schedule a message to be sent to a chat
```csharp
var chats = await client.Messages_GetAllChats();
InputPeer peer = chats.chats[1234567890]; // the chat we want
@@ -270,7 +271,7 @@ await client.SendMessageAsync(peer, "This will be posted in 3 minutes", schedule
```
-### Fun with stickers, GIFs, dice, and animated emojies
+## Fun with stickers, GIFs, dice, and animated emojies
```csharp
// • List all stickerSets the user has added to his account
var allStickers = await client.Messages_GetAllStickers();
@@ -319,7 +320,7 @@ await Task.Delay(5000);
```
-### Fun with custom emojies and reactions on pinned messages
+## Fun with custom emojies and reactions on pinned messages
```csharp
// • Sending a message with custom emojies in Markdown to ourself:
var text = "Vicksy says Hi! [👋](emoji?id=5190875290439525089)";
@@ -355,7 +356,7 @@ foreach (var msg in messages.Messages)
-### Join a channel/group by their public name or invite link
+## Join a channel/group by their public name or invite link
* For a public channel/group `@channelname`
If you have a link of the form `https://t.me/channelname`, you need to extract the `channelname` from the URL.
You can resolve the channel/group username and join it like this:
@@ -374,7 +375,7 @@ await client.Messages_ImportChatInvite("HASH"); // join the channel/group
```
-### Add/Invite/Remove someone in a chat
+## Add/Invite/Remove someone in a chat
```csharp
var chats = await client.Messages_GetAllChats();
var chat = chats.chats[1234567890]; // the target chat
@@ -403,7 +404,7 @@ await client.DeleteChatUser(chat, user);
```
-### Send a message to someone by phone number
+## Send a message to someone by phone number
```csharp
var contacts = await client.Contacts_ImportContacts(new[] { new InputPhoneContact { phone = "+PHONENUMBER" } });
if (contacts.imported.Length > 0)
@@ -412,7 +413,7 @@ if (contacts.imported.Length > 0)
*Note: Don't use this method too much. To prevent spam, Telegram may restrict your ability to add new phone numbers or ban your account.*
-### Retrieve the current user's contacts list
+## Retrieve the current user's contacts list
There are two different methods. Here is the simpler one:
```csharp
var contacts = await client.Contacts_GetContacts();
@@ -441,7 +442,7 @@ finally
```
-### Collect Access Hash and save them for later use
+## Collect Access Hash and save them for later use
You can automate the collection of `access_hash` for the various resources obtained in response to API calls or Updates,
so that you don't have to remember them by yourself or ask the API about them each time.
@@ -450,7 +451,7 @@ This is done by activating the experimental `client.CollectAccessHash` system.
See [Examples/Program_CollectAccessHash.cs](Examples/Program_CollectAccessHash.cs) for how to enable it, and save/restore them for later use.
-### Use a proxy or MTProxy to connect to Telegram
+## Use a proxy or MTProxy to connect to Telegram
SOCKS/HTTPS proxies can be used through the `client.TcpHandler` delegate and a proxy library like [StarkSoftProxy](https://www.nuget.org/packages/StarkSoftProxy/):
```csharp
using var client = new WTelegram.Client(Environment.GetEnvironmentVariable);
@@ -482,7 +483,7 @@ If your Telegram client is already connected to such MTPROTO proxy, you can also
*Note: WTelegramClient always uses transport obfuscation when connecting to Telegram servers, even without MTProxy*
-### Change 2FA password
+## Change 2FA password
```csharp
const string old_password = "password"; // current password if any (unused otherwise)
const string new_password = "new_password"; // or null to disable 2FA
@@ -500,7 +501,7 @@ await client.Account_UpdatePasswordSettings(password, new Account_PasswordInputS
```
-### Store session data to database or elsewhere, instead of files
+## Store session data to database or elsewhere, instead of files
If you don't want to store session data into files *(for example if your VPS Hosting doesn't allow that)*, or just for easier management,
you can choose to store the session data somewhere else, like in a database.
@@ -511,7 +512,7 @@ Use it to pass a custom Stream-derived class that will **read** (first initial c
You can find an example for such custom session store in [Examples/Program_Heroku.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_Heroku.cs#L61)
-### Send/receive end-to-end encrypted messages & files in Secret Chats
+## Send/receive end-to-end encrypted messages & files in Secret Chats
This can be done easily using the helper class `WTelegram.SecretChats` offering methods to manage/encrypt/decrypt secret chats & encrypted messages/files.
diff --git a/FAQ.md b/FAQ.md
index 36f03c5..2cd38db 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -1,11 +1,13 @@
-## FAQ
+# FAQ
Before asking questions, make sure to **[read through the ReadMe first](README.md)**,
take a look at the [example programs](EXAMPLES.md) or [StackOverflow questions](https://stackoverflow.com/questions/tagged/wtelegramclient),
and refer to the [API method list](https://corefork.telegram.org/methods) for the full range of Telegram services available in this library.
+➡️ Use Ctrl-F to search this page for the information you seek
+
-#### 1. How to remove the Console logs?
+## 1. How to remove the Console logs?
Writing the library logs to the Console is the default behavior of the `WTelegram.Helpers.Log` delegate.
You can change the delegate with the `+=` operator to **also** write them somewhere else, or with the `=` operator to prevent them from being printed to screen and instead write them somewhere (file, logger, ...).
@@ -14,7 +16,7 @@ In any case, it is not recommended to totally ignore those logs because you woul
Read the [example about logging settings](EXAMPLES.md#logging) for how to write logs to a file.
-#### 2. How to handle multiple user accounts
+## 2. How to handle multiple user accounts
The WTelegram.session file contains the authentication keys negociated for the current user.
@@ -32,7 +34,7 @@ Your api_id/api_hash represents your application, and shouldn't change with each
-#### 3. How to use the library in a WinForms, WPF or ASP.NET application
+## 3. How to use the library in a WinForms, WPF or ASP.NET application
The library should work without a problem in such applications.
The difficulty might be in your Config callback when the user must enter the verification code or password, as you can't use `Console.ReadLine` here.
@@ -48,7 +50,7 @@ calling `client.Login(...)` as the user provides the requested configuration ele
You can download such full example apps [for WinForms](Examples/WinForms_app.zip) and [for ASP.NET](Examples/ASPnet_webapp.zip)
-#### 4. How to use IDs? Where to get the access_hash? Why the error `CHANNEL_INVALID` or `USER_ID_INVALID`?
+## 4. How to use IDs? Where to get the access_hash? Why the error `CHANNEL_INVALID` or `USER_ID_INVALID`?
Having only the ID is **not enough**: An `access_hash` is required by Telegram when dealing with a channel, user, photo, document, etc...
This serves as a proof that the logged-in user is entitled to access it (otherwise, anybody with the ID could access it)
@@ -72,14 +74,14 @@ You can then retrieve it with `client.GetAccessHashFor
-#### 5. I need to test a feature that has been recently developed but seems not available in my program
+## 5. I need to test a feature that has been recently developed but seems not available in my program
The developmental versions of the library are now available as **pre-release** on Nuget (with `-dev` in the version number)
So make sure you tick the checkbox "Include prerelease" in Nuget manager and/or navigate to the Versions list then select the highest `x.x.x-dev.x` version to install in your program.
-#### 6. Telegram asks me to signup (firstname, lastname) even for an existing account
+## 6. Telegram asks me to signup (firstname, lastname) even for an existing account
This happens when you connect to Telegram Test servers instead of Production servers.
On these separate test servers, all created accounts and chats are periodically deleted, so you shouldn't use them under normal circumstances.
@@ -96,7 +98,7 @@ If you use the Github source project in an old .NET Framework 4.x or .NET Core x
To fix this, you should also switch to using the [WTelegramClient Nuget package](https://www.nuget.org/packages/WTelegramClient) as it will install the required dependencies for it to work.
-#### 7. I get errors FLOOD_WAIT_X or PEER_FLOOD, PHONE_NUMBER_BANNED, USER_DEACTIVATED_BAN. I can't import phone numbers.
+## 7. I get errors FLOOD_WAIT_X or PEER_FLOOD, PHONE_NUMBER_BANNED, USER_DEACTIVATED_BAN. I can't import phone numbers.
You can get these kind of problems if you abuse Telegram [Terms of Service](https://telegram.org/tos), or the [API Terms of Service](https://core.telegram.org/api/terms), or make excessive requests.
@@ -111,7 +113,7 @@ If you think your phone number was banned from Telegram for a wrong reason, you
In any case, WTelegramClient is not responsible for the bad usage of the library and we are not affiliated to Telegram teams, so there is nothing we can do.
-#### 8. How to NOT get banned from Telegram?
+## 8. How to NOT get banned from Telegram?
**Do not share publicly your app's ID and hash!** They cannot be regenerated and are bound to your Telegram account.
@@ -147,7 +149,7 @@ We don't support such use of the library, and will not help people asking for su
11. If your client displays Telegram channels to your users, you have to support and display [official sponsored messages](https://core.telegram.org/api/sponsored-messages).
-#### 9. Why the error `CHAT_ID_INVALID`?
+## 9. Why the error `CHAT_ID_INVALID`?
Most chat groups you see are likely of type `Channel`, not `Chat`.
This difference is important to understand. Please [read about the Terminology in ReadMe](README.md#terminology).
@@ -162,7 +164,7 @@ That object must be created with both fields `channel_id` and `access_hash` corr
-#### 10. `chats.chats[id]` fails. My chats list is empty or does not contain the chat I'm looking for.
+## 10. `chats.chats[id]` fails. My chats list is empty or does not contain the chat I'm looking for.
There can be several reasons why `chats.chats` doesn't contain the chat you expect:
- You're searching for a user instead of a chat ID.
@@ -182,7 +184,7 @@ To help determine if `chats.chats` is empty or does not contain a certain chat,
or simply use a debugger: Place a breakpoint after the `Messages_GetAllChats` call, run the program up to there, and use a Watch pane to display the content of the chats.chats dictionary.
-#### 11. I get "Connection shut down" errors in my logs
+## 11. I get "Connection shut down" errors in my logs
There are various reasons why you may get this error. Here are the explanation and how to solve it:
@@ -207,7 +209,7 @@ In this case, you can use the `PingInterval` property to increase the delay betw
5) If you're using an [MTProxy](EXAMPLES.md#proxy), some of them are known to be quite unstable. You may want to try switching to another MTProxy that is more stable.
-#### 12. How to migrate from TLSharp? How to sign-in/sign-up/register account properly?
+## 12. How to migrate from TLSharp? How to sign-in/sign-up/register account properly?
First, make sure you read the [ReadMe documentation](README.md) completely, it contains essential information and a quick tutorial to easily understand how to correctly use the library.
@@ -234,7 +236,7 @@ In particular, it will detect and handle automatically and properly the various
Contrary to TLSharp, WTelegramClient supports MTProto v2.0 (more secured), transport obfuscation, protocol security checks, MTProto [Proxy](EXAMPLES.md#proxy), real-time updates, multiple DC connections, API documentation in Intellisense...
-#### 13. How to host my userbot online?
+## 13. How to host my userbot online?
If you need your userbot to run 24/7, you would typically design your userbot as a Console program, compiled for Linux or Windows,
and hosted online on any [VPS Hosting](https://www.google.com/search?q=vps+hosting) (Virtual Private Server).
@@ -244,7 +246,7 @@ There are many cheap VPS Hosting offers available, for example Heroku:
See [Examples/Program_Heroku.cs](Examples/Program_Heroku.cs) for such an implementation and the steps to host/deploy it.
-#### 14. Secret Chats implementation details
+## 14. Secret Chats implementation details
The following choices were made while implementing Secret Chats in WTelegramClient:
- It may not support remote antique Telegram clients *(prior to 2018, still using insecure MTProto 1.0)*
@@ -260,7 +262,7 @@ If those missing messages are never obtained during the session, incoming messag
If remote client doesn't complete this negotiation before reaching 200 messages, the Secret Chat is aborted.
-#### 15. The example codes don't compile on my machine
+## 15. The example codes don't compile on my machine
The snippets of example codes found in the [ReadMe](README.md) or [Examples](EXAMPLES.md) pages were written for .NET 5 / C# 9 minimum.
If you're having compiler problem on code constructs such as `using`, `foreach`, `[^1]` or about "Deconstruct",
@@ -294,7 +296,7 @@ Here are the recommended actions to fix your problem:
Also, remember to add a `using TL;` at the top of your files to have access to all the Telegram API methods.
-## Troubleshooting guide
+# Troubleshooting guide
Here is a list of common issues and how to fix them so that your program work correctly:
1) Are you using the Nuget package or the library source code?