From 4ce0f72d6d85bca0a94e68fc9248838bc298bdbd Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Wed, 28 Feb 2018 08:43:28 +0800 Subject: [PATCH 01/13] TelegramClient: move the _sender null check to RequestWithDcMigration() The method IsPhoneRegisteredAsync() was calling RequestWithDcMigration() which was the real method that made use of the _sender field, so we can move the null check to there. This will also help track down possible NullReferenceExceptions that could happen when other callers of this method arrive with a bad _sender, which might aid us trying to fix #706. --- TLSharp.Core/TelegramClient.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TLSharp.Core/TelegramClient.cs b/TLSharp.Core/TelegramClient.cs index 0692486..0a7b070 100644 --- a/TLSharp.Core/TelegramClient.cs +++ b/TLSharp.Core/TelegramClient.cs @@ -111,6 +111,9 @@ namespace TLSharp.Core private async Task RequestWithDcMigration(TLMethod request) { + if (_sender == null) + throw new InvalidOperationException("Not connected!"); + var completed = false; while(!completed) { @@ -139,9 +142,6 @@ namespace TLSharp.Core if (String.IsNullOrWhiteSpace(phoneNumber)) throw new ArgumentNullException(nameof(phoneNumber)); - if (_sender == null) - throw new InvalidOperationException("Not connected!"); - var authCheckPhoneRequest = new TLRequestCheckPhone() { PhoneNumber = phoneNumber }; await RequestWithDcMigration(authCheckPhoneRequest); From bf568d80cc05b69b30532dd650974d2bbb80a684 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Thu, 1 Mar 2018 23:41:35 +0800 Subject: [PATCH 02/13] TelegramClient: change Connect() to return void instead of always true If a method that returns bool is never returning false, it's essentially not giving any information at all, which means that it should return void. This will help the consumers of this API to stop thinking that the result of this function means if the connection was succesful (which it is, actually, but it was never returning false because if there's any problem connecting, the result would be an exception instead). --- TLSharp.Core/TelegramClient.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/TLSharp.Core/TelegramClient.cs b/TLSharp.Core/TelegramClient.cs index 0a7b070..45d15af 100644 --- a/TLSharp.Core/TelegramClient.cs +++ b/TLSharp.Core/TelegramClient.cs @@ -50,7 +50,7 @@ namespace TLSharp.Core _transport = new TcpTransport(_session.ServerAddress, _session.Port, _handler); } - public async Task ConnectAsync(bool reconnect = false) + public async Task ConnectAsync(bool reconnect = false) { if (_session.AuthKey == null || reconnect) { @@ -77,8 +77,6 @@ namespace TLSharp.Core await _sender.Receive(invokewithLayer); dcOptions = ((TLConfig)invokewithLayer.Response).DcOptions.ToList(); - - return true; } private async Task ReconnectToDcAsync(int dcId) From c1ce5e25baac5d05d4a447c5c563d7a063b4dd14 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Fri, 2 Mar 2018 11:35:21 +0800 Subject: [PATCH 03/13] README.md: add link to gitter channel et-al --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cbee7f0..34f97e3 100644 --- a/README.md +++ b/README.md @@ -211,10 +211,10 @@ It's likely [Telegram restrictions](https://core.telegram.org/api/errors#420-flo #### Why does TLSharp lacks feature XXXX? -Now TLSharp is basic realization of Telegram protocol, you can be a contributor or a sponsor to speed-up developemnt of any feature. +TLSharp only covers basic functionality of the Telegram protocol, you can be a contributor or a sponsor to speed-up developemnt of any more new features. -#### Nothing helps -Ask your question at gitter or create an issue in project bug tracker. +#### Where else to ask for help? +If you think you have found a bug in TLSharp, create a github issue. But if you just have questions about how to use TLSharp, use our gitter channel (https://gitter.im/TLSharp/Lobby) or our Telegram channel (https://t.me/joinchat/AgtDiBEqG1i-qPqttNFLbA). **Attach following information**: From 3762664c149a8a1d587d59ce203a9a61bde709b9 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Sun, 4 Mar 2018 00:38:51 +0800 Subject: [PATCH 04/13] Normalize line endings --- TLSharp.Core/Network/TcpTransport.cs | 24 +++---- TLSharp.Core/TelegramClient.cs | 96 ++++++++++++++-------------- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/TLSharp.Core/Network/TcpTransport.cs b/TLSharp.Core/Network/TcpTransport.cs index 31bd6b4..e0f6e1f 100644 --- a/TLSharp.Core/Network/TcpTransport.cs +++ b/TLSharp.Core/Network/TcpTransport.cs @@ -84,21 +84,21 @@ namespace TLSharp.Core.Network } return new TcpMessage(seq, body); - } - - public bool IsConnected - { - get - { - return this._tcpClient.Connected; - } - } - - + } + + public bool IsConnected + { + get + { + return this._tcpClient.Connected; + } + } + + public void Dispose() { if (_tcpClient.Connected) _tcpClient.Close(); - } + } } } diff --git a/TLSharp.Core/TelegramClient.cs b/TLSharp.Core/TelegramClient.cs index 45d15af..dd0593d 100644 --- a/TLSharp.Core/TelegramClient.cs +++ b/TLSharp.Core/TelegramClient.cs @@ -83,13 +83,13 @@ namespace TLSharp.Core { if (dcOptions == null || !dcOptions.Any()) throw new InvalidOperationException($"Can't reconnect. Establish initial connection first."); - - TLExportedAuthorization exported = null; - if (_session.TLUser != null) - { - TLRequestExportAuthorization exportAuthorization = new TLRequestExportAuthorization() { DcId = dcId }; - exported = await SendRequestAsync(exportAuthorization); - } + + TLExportedAuthorization exported = null; + if (_session.TLUser != null) + { + TLRequestExportAuthorization exportAuthorization = new TLRequestExportAuthorization() { DcId = dcId }; + exported = await SendRequestAsync(exportAuthorization); + } var dc = dcOptions.First(d => d.Id == dcId); @@ -97,21 +97,21 @@ namespace TLSharp.Core _session.ServerAddress = dc.IpAddress; _session.Port = dc.Port; - await ConnectAsync(true); - - if (_session.TLUser != null) - { - TLRequestImportAuthorization importAuthorization = new TLRequestImportAuthorization() { Id = exported.Id, Bytes = exported.Bytes }; - var imported = await SendRequestAsync(importAuthorization); - OnUserAuthenticated(((TLUser)imported.User)); + await ConnectAsync(true); + + if (_session.TLUser != null) + { + TLRequestImportAuthorization importAuthorization = new TLRequestImportAuthorization() { Id = exported.Id, Bytes = exported.Bytes }; + var imported = await SendRequestAsync(importAuthorization); + OnUserAuthenticated(((TLUser)imported.User)); } } - private async Task RequestWithDcMigration(TLMethod request) - { + private async Task RequestWithDcMigration(TLMethod request) + { if (_sender == null) - throw new InvalidOperationException("Not connected!"); - + throw new InvalidOperationException("Not connected!"); + var completed = false; while(!completed) { @@ -127,7 +127,7 @@ namespace TLSharp.Core // prepare the request for another try request.ConfirmReceived = false; } - } + } } public bool IsUserAuthorized() @@ -170,8 +170,8 @@ namespace TLSharp.Core if (String.IsNullOrWhiteSpace(code)) throw new ArgumentNullException(nameof(code)); - var request = new TLRequestSignIn() { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = code }; - + var request = new TLRequestSignIn() { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = code }; + await RequestWithDcMigration(request); OnUserAuthenticated(((TLUser)request.Response.User)); @@ -312,21 +312,21 @@ namespace TLSharp.Core public async Task SendPingAsync() { await _sender.SendPingAsync(); - } - - public async Task GetHistoryAsync(TLAbsInputPeer peer, int offset, int max_id, int limit) - { - if (!IsUserAuthorized()) - throw new InvalidOperationException("Authorize user first!"); - - var req = new TLRequestGetHistory() - { - Peer = peer, - AddOffset = offset, - MaxId = max_id, - Limit = limit - }; - return await SendRequestAsync(req); + } + + public async Task GetHistoryAsync(TLAbsInputPeer peer, int offset, int max_id, int limit) + { + if (!IsUserAuthorized()) + throw new InvalidOperationException("Authorize user first!"); + + var req = new TLRequestGetHistory() + { + Peer = peer, + AddOffset = offset, + MaxId = max_id, + Limit = limit + }; + return await SendRequestAsync(req); } /// @@ -352,18 +352,18 @@ namespace TLSharp.Core _session.SessionExpires = int.MaxValue; _session.Save(); - } - - public bool IsConnected - { - get - { - if (_transport == null) - return false; - return _transport.IsConnected; - } - } - + } + + public bool IsConnected + { + get + { + if (_transport == null) + return false; + return _transport.IsConnected; + } + } + public void Dispose() { if (_transport != null) From e6250b1234c82e664c015a1bd698c70f73eaa55a Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Mon, 5 Mar 2018 03:53:11 +0800 Subject: [PATCH 05/13] Core(MtProtoSender): remove mutation-based dangerous API It wasn't being used internally, and the use-case to be used externally is too intricated. There's already a way to change the handler at contructor time[1] so that should be enough customization. [1] https://github.com/sochix/TLSharp/commit/48077961ae730f84f1624f131dd42eb70db18cb6 --- TLSharp.Core/Network/MtProtoSender.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/TLSharp.Core/Network/MtProtoSender.cs b/TLSharp.Core/Network/MtProtoSender.cs index 795e878..5ba75b3 100644 --- a/TLSharp.Core/Network/MtProtoSender.cs +++ b/TLSharp.Core/Network/MtProtoSender.cs @@ -29,11 +29,6 @@ namespace TLSharp.Core.Network _session = session; } - public void ChangeTransport(TcpTransport transport) - { - _transport = transport; - } - private int GenerateSequence(bool confirmed) { return confirmed ? _session.Sequence++ * 2 + 1 : _session.Sequence * 2; From bd7f5f09eb901275f4b5aaec95d2d2a263f4fade Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Mon, 5 Mar 2018 03:50:09 +0800 Subject: [PATCH 06/13] Core(MtProtoSender): mark immutable fields as readonly To make sure they are kept immutable when upcoming devs make changes to this file. --- TLSharp.Core/Network/MtProtoSender.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TLSharp.Core/Network/MtProtoSender.cs b/TLSharp.Core/Network/MtProtoSender.cs index 5ba75b3..4bc8e84 100644 --- a/TLSharp.Core/Network/MtProtoSender.cs +++ b/TLSharp.Core/Network/MtProtoSender.cs @@ -18,10 +18,10 @@ namespace TLSharp.Core.Network { //private ulong sessionId = GenerateRandomUlong(); - private TcpTransport _transport; - private Session _session; + private readonly TcpTransport _transport; + private readonly Session _session; - public List needConfirmation = new List(); + public readonly List needConfirmation = new List(); public MtProtoSender(TcpTransport transport, Session session) { From 27fcd8242c1cc1f463ff17774c09fc19a5efe8e3 Mon Sep 17 00:00:00 2001 From: Masih Akbari Date: Mon, 19 Mar 2018 07:57:59 +0330 Subject: [PATCH 07/13] update README.md to support new PascalCase changes of API and some other fixes --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 34f97e3..107480b 100644 --- a/README.md +++ b/README.md @@ -81,13 +81,13 @@ You can call any method on authenticated user. For example, let's send message t var result = await client.GetContactsAsync(); //find recipient in contacts - var user = result.Users.lists + var user = result.Users .Where(x => x.GetType() == typeof (TLUser)) .Cast() - .FirstOrDefault(x => x.phone == ""); + .FirstOrDefault(x => x.Phone == ""); //send message - await client.SendMessageAsync(new TLInputPeerUser() {user_id = user.id}, "OUR_MESSAGE"); + await client.SendMessageAsync(new TLInputPeerUser() {UserId = user.Id}, "OUR_MESSAGE"); ``` Full code you can see at [SendMessage test](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L87) @@ -95,16 +95,16 @@ Full code you can see at [SendMessage test](https://github.com/sochix/TLSharp/bl To send message to channel you could use the following code: ```csharp //get user dialogs - var dialogs = await client.GetUserDialogsAsync(); + var dialogs = (TLDialogs) await client.GetUserDialogsAsync(); //find channel by title - var chat = dialogs.chats.lists + var chat = dialogs.Chats .Where(c => c.GetType() == typeof(TLChannel)) .Cast() - .FirstOrDefault(c => c.title == ""); + .FirstOrDefault(c => c.Title == ""); //send message - await client.SendMessageAsync(new TLInputPeerChannel() { channel_id = chat.id, access_hash = chat.access_hash.Value }, "OUR_MESSAGE"); + await client.SendMessageAsync(new TLInputPeerChannel() { ChannelId = chat.Id, AccessHash = chat.AccessHash.Value }, "OUR_MESSAGE"); ``` Full code you can see at [SendMessageToChannel test](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L107) ## Working with files @@ -117,9 +117,9 @@ Telegram separate files to two categories -> big file and small file. File is Bi TLSharp provides two wrappers for sending photo and document ```csharp - await client.SendUploadedPhoto(new TLInputPeerUser() { user_id = user.id }, fileResult, "kitty"); + await client.SendUploadedPhoto(new TLInputPeerUser() { UserId = user.Id }, fileResult, "kitty"); await client.SendUploadedDocument( - new TLInputPeerUser() { user_id = user.id }, + new TLInputPeerUser() { UserId = user.Id }, fileResult, "some zips", //caption "application/zip", //mime-type @@ -132,11 +132,11 @@ To download file you should call **GetFile** method await client.GetFile( new TLInputDocumentFileLocation() { - access_hash = document.access_hash, - id = document.id, - version = document.version + AccessHash = document.AccessHash, + Id = document.Id, + Version = document.Version }, - document.size); //size of fileChunk you want to retrieve + document.Size); //size of fileChunk you want to retrieve ``` Full code you can see at [DownloadFileFromContactTest](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L167) @@ -169,12 +169,12 @@ Don't panic. You can call any method with help of `SendRequestAsync` function. F //Create request var req = new TLRequestSetTyping() { - action = new TLSendMessageTypingAction(), - peer = peer + Action = new TLSendMessageTypingAction(), + Peer = new TLInputPeerUser() { UserId = user.Id } }; //run request, and deserialize response to Boolean - return await SendRequestAsync(req); + return await client.SendRequestAsync(req); ``` **Where you can find a list of requests and its params?** From 0ff9980cc974b3d5a457cff82f0860c002907f3b Mon Sep 17 00:00:00 2001 From: Masih Akbari Date: Wed, 21 Mar 2018 01:53:48 +0330 Subject: [PATCH 08/13] fix compilation error for getting dialogs in README.md file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 107480b..f6540c5 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ Full code you can see at [SendMessage test](https://github.com/sochix/TLSharp/bl To send message to channel you could use the following code: ```csharp //get user dialogs - var dialogs = (TLDialogs) await client.GetUserDialogsAsync(); + var dialogs = (TLDialogsSlice) await client.GetUserDialogsAsync(); //find channel by title var chat = dialogs.Chats From fdcb195fbb21e5195e660403814be6e162ce4ad8 Mon Sep 17 00:00:00 2001 From: Afshin Arani Date: Fri, 13 Apr 2018 01:27:26 +0430 Subject: [PATCH 09/13] Use ToArray instead of GetBuffer Buffer normally contain lots of extra zero bytes --- TeleSharp.TL/TLObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TeleSharp.TL/TLObject.cs b/TeleSharp.TL/TLObject.cs index 3bc1476..f398ddf 100644 --- a/TeleSharp.TL/TLObject.cs +++ b/TeleSharp.TL/TLObject.cs @@ -31,7 +31,7 @@ namespace TeleSharp.TL Serialize(bw); bw.Close(); m.Close(); - return m.GetBuffer(); + return m.ToArray(); } } public void Serialize(BinaryWriter writer) From 28b83aaec34539a361c3f1593e613d5c1dca6e5a Mon Sep 17 00:00:00 2001 From: Ilya Pirozhenko Date: Tue, 24 Apr 2018 10:47:03 +0300 Subject: [PATCH 10/13] Update README.md Removed gitter as it too noisy --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index f6540c5..7209ccb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ TLSharp ------------------------------- -[![Join the chat at https://gitter.im/TLSharp/Lobby](https://badges.gitter.im/TLSharp/Lobby.svg)](https://gitter.im/TLSharp/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build status](https://ci.appveyor.com/api/projects/status/95rl618ch5c4h2fa?svg=true)](https://ci.appveyor.com/project/sochix/tlsharp) [![NuGet version](https://badge.fury.io/nu/TLSharp.svg)](https://badge.fury.io/nu/TLSharp) From faf129e6367114ddfea14791f2c775c9456fe52a Mon Sep 17 00:00:00 2001 From: Ilya Pirozhenko Date: Wed, 25 Apr 2018 13:23:29 +0300 Subject: [PATCH 11/13] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7209ccb..8159448 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,10 @@ It's a perfect fit for any developer who would like to send data directly to Tel - [First requests](#first-requests) - [Working with files](#working-with-files) - [Available Methods](#available-methods) -- [Contributing](#contributing) +- [Contributors](#contributors) - [FAQ](#faq) - [Donations](#donations) +- [Support](#support) - [License](#license) # How do I add this to my project? @@ -230,6 +231,11 @@ Thanks for donations! It's highly appreciated. List of donators: * [mtbitcoin](https://github.com/mtbitcoin) +# Support +If you have troubles while using TLSharp, I can help you for an additional fee. + +My pricing is **219$/hour**. I accept PayPal. To request a paid support write me at Telegram @sochix, start your message with phrase [PAID SUPPORT]. + # Contributors * [Afshin Arani](http://aarani.ir) - TLGenerator, and a lot of other usefull things * [Knocte](https://github.com/knocte) From 1aa63e565a27a21b0dab14b84f7a8588467e89ae Mon Sep 17 00:00:00 2001 From: Ilya Pirozhenko Date: Wed, 25 Apr 2018 19:02:57 +0300 Subject: [PATCH 12/13] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8159448..9d89a90 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ TLSharp _Unofficial_ Telegram (http://telegram.org) client library implemented in C#. Latest TL scheme supported, thanks to Afshin Arani +🚩 Check out [TeleJS](https://github.com/RD17/TeleJS) - a pure JavaScript implementation of Telegram MTP protocol + It's a perfect fit for any developer who would like to send data directly to Telegram users or write own custom Telegram client. :star2: If you :heart: library, please star it! :star2: From 47e973823a0c0695cde4c70e0ab3da27b611d280 Mon Sep 17 00:00:00 2001 From: vlad_neg Date: Wed, 30 May 2018 01:50:44 +0300 Subject: [PATCH 13/13] issue#768 fix exception 'Constructor Invalid Or Context.Init Not Called !' --- TLSharp.Core/TelegramClient.cs | 1 - TeleSharp.TL/TLContext.cs | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TLSharp.Core/TelegramClient.cs b/TLSharp.Core/TelegramClient.cs index dd0593d..3406ee9 100644 --- a/TLSharp.Core/TelegramClient.cs +++ b/TLSharp.Core/TelegramClient.cs @@ -41,7 +41,6 @@ namespace TLSharp.Core if (store == null) store = new FileSessionStore(); - TLContext.Init(); _apiHash = apiHash; _apiId = apiId; _handler = handler; diff --git a/TeleSharp.TL/TLContext.cs b/TeleSharp.TL/TLContext.cs index db686aa..be43936 100644 --- a/TeleSharp.TL/TLContext.cs +++ b/TeleSharp.TL/TLContext.cs @@ -12,7 +12,7 @@ namespace TeleSharp.TL { private static Dictionary Types; - public static void Init() + static TLContext() { Types = new Dictionary(); Types = (from t in Assembly.GetExecutingAssembly().GetTypes() @@ -22,6 +22,7 @@ namespace TeleSharp.TL select t).ToDictionary(x => ((TLObjectAttribute)x.GetCustomAttribute(typeof(TLObjectAttribute))).Constructor, x => x); Types.Add(481674261, typeof(TLVector<>)); } + public static Type getType(int Constructor) { return Types[Constructor];