diff --git a/EXAMPLES.md b/EXAMPLES.md
index 88bf1de..654e117 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -95,7 +95,7 @@ foreach (Dialog dialog in dialogs.dialogs)
Notes:
- The lists returned by Messages_GetAllDialogs contains the `access_hash` for those chats and users.
-- See also the `Main` method in [Examples/Program_ListenUpdates.cs](Examples/Program_ListenUpdates.cs).
+- See also the `Main` method in [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs#L20).
- To retrieve the dialog information about a specific [peer](README.md#terminology), use `client.Messages_GetPeerDialogs(inputPeer)`
@@ -114,7 +114,7 @@ Notes:
- The list returned by Messages_GetAllChats contains the `access_hash` for those chats. Read [FAQ #4](FAQ.md#access-hash) about this.
- If a basic chat group has been migrated to a supergroup, you may find both the old `Chat` and a `Channel` with different IDs in the `chats.chats` result,
but the old `Chat` will be marked with flag [deactivated] and should not be used anymore. See [Terminology in ReadMe](README.md#terminology).
-- You can find a longer version of this method call in [Examples/Program_GetAllChats.cs](Examples/Program_GetAllChats.cs)
+- You can find a longer version of this method call in [Examples/Program_GetAllChats.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_GetAllChats.cs#L32)
## List the members from a chat
@@ -189,14 +189,14 @@ Notes:
This is done through the `client.OnUpdate` callback event.
Your event handler implementation can either return `Task.CompletedTask` or be an `async Task` method.
-See [Examples/Program_ListenUpdates.cs](Examples/Program_ListenUpdates.cs).
+See [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs#L23).
## Monitor new messages being posted in chats in real-time
You have to handle `client.OnUpdate` events containing an `UpdateNewMessage`.
-See the `DisplayMessage` method in [Examples/Program_ListenUpdates.cs](Examples/Program_ListenUpdates.cs).
+See the `DisplayMessage` method in [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs#L23).
You can filter specific chats the message are posted in, by looking at the `Message.peer_id` field.
@@ -206,7 +206,7 @@ You can filter specific chats the message are posted in, by looking at the `Mess
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)*.
-See [Examples/Program_DownloadSavedMedia.cs](Examples/Program_DownloadSavedMedia.cs) that download all media files you forward to yourself (Saved Messages)
+See [Examples/Program_DownloadSavedMedia.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_DownloadSavedMedia.cs#L31) that download all media files you forward to yourself (Saved Messages)
## Upload a media file and post it with caption to a chat
@@ -448,7 +448,7 @@ You can automate the collection of `access_hash` for the various resources obtai
so that you don't have to remember them by yourself or ask the API about them each time.
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.
+See [Examples/Program_CollectAccessHash.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_CollectAccessHash.cs#L22) for how to enable it, and save/restore them for later use.
## Use a proxy or MTProxy to connect to Telegram
@@ -516,7 +516,7 @@ You can find an example for such custom session store in [Examples/Program_Herok
This can be done easily using the helper class `WTelegram.SecretChats` offering methods to manage/encrypt/decrypt secret chats & encrypted messages/files.
-You can view a full working example at [Examples/Program_SecretChats.cs](Examples/Program_SecretChats.cs).
+You can view a full working example at [Examples/Program_SecretChats.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_SecretChats.cs#L11).
Secret Chats have been tested successfully with Telegram Android & iOS official clients.
You can also check our [FAQ for more implementation details](FAQ.md#14-secret-chats-implementation-details).
\ No newline at end of file
diff --git a/Examples/Program_Heroku.cs b/Examples/Program_Heroku.cs
index cfdb551..70fffdf 100644
--- a/Examples/Program_Heroku.cs
+++ b/Examples/Program_Heroku.cs
@@ -8,7 +8,7 @@ using TL;
// This is an example userbot designed to run on a Heroku account with a PostgreSQL database for session storage
// This userbot simply answer "Pong" when someone sends him a "Ping" private message (or in Saved Messages)
-// To use/install/deploy this userbot, follow the steps at the end of this file
+// To use/install/deploy this userbot ➡️ follow the steps at the end of this file
// When run locally, close the window or type ALT-F4 to exit cleanly and save session (similar to Heroku SIGTERM)
namespace WTelegramClientTest
diff --git a/FAQ.md b/FAQ.md
index 2cd38db..4d388e9 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -243,7 +243,7 @@ and hosted online on any [VPS Hosting](https://www.google.com/search?q=vps+hosti
Pure WebApp hosts might not be adequate as they will recycle (stop) your app if there is no incoming HTTP requests.
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.
+See [Examples/Program_Heroku.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_Heroku.cs#L9) for such an implementation and the steps to host/deploy it.
## 14. Secret Chats implementation details
diff --git a/README.md b/README.md
index 88d7368..7aacdc3 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://dev.azure.com/wiz0u/WTelegramClient/_build?definitionId=7)
[](http://t.me/WTelegramBot?start=donate)
-## _Telegram Client API library written 100% in C# and .NET Standard_
+## _Telegram Client API library written 100% in C# and .NET_
This library allows you to connect to Telegram and control a user programmatically (or a bot, but [Telegram.Bot](https://github.com/TelegramBots/Telegram.Bot) is much easier for that).
All the Telegram Client APIs (MTProto) are supported so you can do everything the user could do with a full Telegram GUI client.
@@ -90,7 +90,7 @@ Since version 3.0.0, a new approach to login/configuration has been added. Some
```csharp
WTelegram.Client client = new WTelegram.Client(YOUR_API_ID, "YOUR_API_HASH");
-await DoLogin("+12025550156"); // user's phone_number
+await DoLogin("+12025550156"); // initial call with user's phone_number
async Task DoLogin(string loginInfo) // (add this method to your code)
{
@@ -150,7 +150,7 @@ await client.SendMessageAsync(target, "Hello, World");
➡️ You can find lots of useful code snippets in [EXAMPLES](https://wiz0u.github.io/WTelegramClient/EXAMPLES)
and in the [Examples subdirectory](https://github.com/wiz0u/WTelegramClient/tree/master/Examples).
-➡️ Check [the FAQ](https://wiz0u.github.io/WTelegramClient/FAQ#compile) if example codes doesn't compile correctly on your machine, or other troubleshooting.
+➡️ Check [the FAQ](https://wiz0u.github.io/WTelegramClient/FAQ#compile) if example codes don't compile correctly on your machine, or other troubleshooting.
# Terminology in Telegram Client API
@@ -189,7 +189,7 @@ as well as generic handling of chats/channels.
This library works best with **.NET 5.0+** (faster, no dependencies) and is also available for **.NET Standard 2.0** (.NET Framework 4.6.1+ & .NET Core 2.0+) and **Xamarin/Mono.Android**
# Library uses and limitations
-This library can be used for any Telegram scenarios including:
+This library can be used for any Telegram scenario including:
- Sequential or parallel automated steps based on API requests/responses
- Real-time [monitoring](https://wiz0u.github.io/WTelegramClient/EXAMPLES#updates) of incoming Updates/Messages
- Download/upload of files/media
diff --git a/src/Client.Helpers.cs b/src/Client.Helpers.cs
index 6fe1510..30da842 100644
--- a/src/Client.Helpers.cs
+++ b/src/Client.Helpers.cs
@@ -586,7 +586,7 @@ namespace WTelegram
public Task AddChatUser(InputPeer peer, InputUserBase user) => peer switch
{
InputPeerChat chat => this.Messages_AddChatUser(chat.chat_id, user, int.MaxValue),
- InputPeerChannel channel => this.Channels_InviteToChannel(channel, new[] { user }),
+ InputPeerChannel channel => this.Channels_InviteToChannel(channel, user),
_ => throw new ArgumentException(OnlyChatChannel),
};
@@ -620,7 +620,7 @@ namespace WTelegram
case InputPeerChat chat:
await this.Messages_EditChatAdmin(chat.chat_id, user, is_admin);
return new Updates { date = DateTime.UtcNow, users = new(), updates = Array.Empty(),
- chats = (await this.Messages_GetChats(new[] { chat.chat_id })).chats };
+ chats = (await this.Messages_GetChats(chat.chat_id)).chats };
case InputPeerChannel channel:
return await this.Channels_EditAdmin(channel, user,
new ChatAdminRights { flags = is_admin ? (ChatAdminRights.Flags)0x8BF : 0 }, null);
@@ -667,7 +667,7 @@ namespace WTelegram
case InputPeerChat chat:
await this.Messages_DeleteChat(chat.chat_id);
return new Updates { date = DateTime.UtcNow, users = new(), updates = Array.Empty(),
- chats = (await this.Messages_GetChats(new[] { chat.chat_id })).chats };
+ chats = (await this.Messages_GetChats(chat.chat_id)).chats };
case InputPeerChannel channel:
return await this.Channels_DeleteChannel(channel);
default:
diff --git a/src/Client.cs b/src/Client.cs
index 891764a..af5234e 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -310,7 +310,11 @@ namespace WTelegram
catch (Exception ex) // an exception in RecvAsync is always fatal
{
if (cts.IsCancellationRequested) return;
- Helpers.Log(5, $"{_dcSession.DcID}>An exception occured in the reactor: {ex}");
+ bool disconnectedAltDC = !IsMainDC && ex is ApplicationException { Message: ConnectionShutDown } or IOException { InnerException: SocketException };
+ if (disconnectedAltDC)
+ Helpers.Log(3, $"{_dcSession.DcID}>Alt DC disconnected: {ex.Message}");
+ else
+ Helpers.Log(5, $"{_dcSession.DcID}>An exception occured in the reactor: {ex}");
var oldSemaphore = _sendSemaphore;
await oldSemaphore.WaitAsync(cts.Token); // prevent any sending while we reconnect
var reactorError = new ReactorError { Exception = ex };
@@ -319,7 +323,7 @@ namespace WTelegram
lock (_msgsToAck) _msgsToAck.Clear();
Reset(false, false);
_reactorReconnects = (_reactorReconnects + 1) % MaxAutoReconnects;
- if (!IsMainDC && _pendingRpcs.Count <= 1 && ex is ApplicationException { Message: ConnectionShutDown } or IOException { InnerException: SocketException })
+ if (disconnectedAltDC && _pendingRpcs.Count <= 1)
if (_pendingRpcs.Values.FirstOrDefault() is not Rpc rpc || rpc.type == typeof(Pong))
_reactorReconnects = 0;
if (_reactorReconnects == 0)
diff --git a/src/TL.Helpers.cs b/src/TL.Helpers.cs
index dc68173..b0abb38 100644
--- a/src/TL.Helpers.cs
+++ b/src/TL.Helpers.cs
@@ -351,19 +351,11 @@ namespace TL
public static implicit operator InputGeoPoint(GeoPoint geo) => new() { lat = geo.lat, lon = geo.lon, accuracy_radius = geo.accuracy_radius, flags = (InputGeoPoint.Flags)geo.flags };
}
- partial class WallPaperBase
- {
- protected abstract InputWallPaperBase ToInputWallPaper();
- public static implicit operator InputWallPaperBase(WallPaperBase wp) => wp.ToInputWallPaper();
- }
- partial class WallPaper
- {
- protected override InputWallPaperBase ToInputWallPaper() => new InputWallPaper { id = id, access_hash = access_hash };
- }
- partial class WallPaperNoFile
- {
- protected override InputWallPaperBase ToInputWallPaper() => new InputWallPaperNoFile { id = id };
- }
+ partial class WallPaperBase { public static implicit operator InputWallPaperBase(WallPaperBase wp) => wp.ToInputWallPaper();
+ protected abstract InputWallPaperBase ToInputWallPaper(); }
+ partial class WallPaper { protected override InputWallPaperBase ToInputWallPaper() => new InputWallPaper { id = id, access_hash = access_hash }; }
+ partial class WallPaperNoFile { protected override InputWallPaperBase ToInputWallPaper() => new InputWallPaperNoFile { id = id }; }
+
partial class Contacts_Blocked { public IPeerInfo UserOrChat(PeerBlocked peer) => peer.peer_id?.UserOrChat(users, chats); }
partial class Messages_DialogsBase { public IPeerInfo UserOrChat(DialogBase dialog) => UserOrChat(dialog.Peer);
public abstract int TotalCount { get; } }
@@ -429,8 +421,8 @@ namespace TL
}, pts = pts, pts_count = pts_count
} }; }
- partial class InputEncryptedChat { public static implicit operator int(InputEncryptedChat chat) => chat.chat_id;
- public static implicit operator InputEncryptedChat(EncryptedChatBase chat) => new() { chat_id = chat.ID, access_hash = chat.AccessHash }; }
+ partial class InputEncryptedChat { public static implicit operator int(InputEncryptedChat chat) => chat.chat_id;
+ public static implicit operator InputEncryptedChat(EncryptedChatBase chat) => new() { chat_id = chat.ID, access_hash = chat.AccessHash }; }
partial class EncryptedFile
{
@@ -568,7 +560,7 @@ namespace TL
partial class Game { public static implicit operator InputGameID(Game game) => new() { id = game.id, access_hash = game.access_hash }; }
partial class WebDocument { public static implicit operator InputWebFileLocation(WebDocument doc) => new() { url = doc.url, access_hash = doc.access_hash }; }
- partial class PhoneCallBase { public static implicit operator InputPhoneCall(PhoneCallBase call) => new() { id = call.ID, access_hash = call.AccessHash }; }
+ partial class PhoneCallBase { public static implicit operator InputPhoneCall(PhoneCallBase call) => new() { id = call.ID, access_hash = call.AccessHash }; }
partial class InputMessage
{
@@ -587,11 +579,11 @@ namespace TL
}
partial class JsonObjectValue { public override string ToString() => $"{HttpUtility.JavaScriptStringEncode(key, true)}:{value}"; }
- partial class JSONValue { public abstract object ToNative(); }
- partial class JsonNull { public override object ToNative() => null; public override string ToString() => "null"; }
- partial class JsonBool { public override object ToNative() => value; public override string ToString() => value ? "true" : "false"; }
- partial class JsonNumber { public override object ToNative() => value; public override string ToString() => value.ToString(CultureInfo.InvariantCulture); }
- partial class JsonString { public override object ToNative() => value; public override string ToString() => HttpUtility.JavaScriptStringEncode(value, true); }
+ partial class JSONValue { public abstract object ToNative(); }
+ partial class JsonNull { public override object ToNative() => null; public override string ToString() => "null"; }
+ partial class JsonBool { public override object ToNative() => value; public override string ToString() => value ? "true" : "false"; }
+ partial class JsonNumber { public override object ToNative() => value; public override string ToString() => value.ToString(CultureInfo.InvariantCulture); }
+ partial class JsonString { public override object ToNative() => value; public override string ToString() => HttpUtility.JavaScriptStringEncode(value, true); }
partial class JsonArray
{
public override string ToString()
@@ -649,13 +641,6 @@ namespace TL
}
}
- partial class Theme
- {
- public static implicit operator InputTheme(Theme theme) => new() { id = theme.id, access_hash = theme.access_hash };
- }
-
- partial class GroupCallBase
- {
- public static implicit operator InputGroupCall(GroupCallBase call) => new() { id = call.ID, access_hash = call.AccessHash };
- }
+ partial class Theme { public static implicit operator InputTheme(Theme theme) => new() { id = theme.id, access_hash = theme.access_hash }; }
+ partial class GroupCallBase { public static implicit operator InputGroupCall(GroupCallBase call) => new() { id = call.ID, access_hash = call.AccessHash }; }
}
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index eccde27..3b1b4a8 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,7 +13,7 @@
WTelegramClient
0.0.0
Wizou
- Telegram Client API library written 100% in C# and .NET Standard | Latest MTProto & Telegram API layer version
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 149
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
Copyright © Olivier Marcoux 2021-2022
MIT
https://github.com/wiz0u/WTelegramClient
@@ -21,7 +21,7 @@
true
https://github.com/wiz0u/WTelegramClient.git
git
- Telegram;Client;Api;UserBot;MTProto;TLSharp;OpenTl
+ Telegram;MTProto;Client;Api;UserBot;TLSharp
README.md
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
IDE0079;0419;1573;1591;NETSDK1138