diff --git a/README.md b/README.md index 0046d2b..6382910 100644 --- a/README.md +++ b/README.md @@ -140,250 +140,215 @@ Full code you can see at [DownloadFileFromContactTest](https://github.com/sochix # Events Sample code ```csharp using System; - using System.Threading.Tasks; - using TeleSharp.TL; - using TLSharp.Core; - using System.Linq; - using TeleSharp.TL.Messages; - using System.Collections.Generic; +using System.Threading.Tasks; +using TeleSharp.TL; +using TLSharp.Core; +using System.Linq; +using TeleSharp.TL.Messages; - namespace TLSharpPOC - { - class MainClass - { - const int APIId = 0; - const string APIHash = "???"; - const string phone = "???"; - public static void Main(string[] args) - { - new MainClass().MainAsync(args).Wait(); - } +namespace TLSharpPOC +{ + class MainClass + { + const int APIId = 0; + const string APIHash = "???"; + const string phone = "???"; + public static void Main(string[] args) + { + new MainClass().MainAsync(args).Wait(); + } - private async Task MainAsync(string[] args) - { - TelegramClient client = null; - - // -- if necessary, IP can be changed so the client can connect to the test network. - Session session = null; - // new Session(new FileSessionStore(), "session") - //{ - // ServerAddress = "149.154.175.10", - // Port = 443 - //}; - //Console.WriteLine($"{session.ServerAddress}:{session.Port} {phone}"); - client = new TelegramClient(APIId, APIHash, session); - // subscribe an event to receive live messages - client.Updates += Client_Updates; - await client.ConnectAsync(); - Console.WriteLine($"Authorised: {client.IsUserAuthorized()}"); - TLUser user = null; - // -- If the user has already authenticated, this step will prevent account from being blocked as it - // -- reuses the data from last authorisation. - if (client.IsUserAuthorized()) - user = client.Session.TLUser; - else - { - var registered = await client.IsPhoneRegisteredAsync(phone); - var hash = await client.SendCodeRequestAsync(phone); - Console.Write("Code: "); - var code = Console.ReadLine(); - if (!registered) - { - Console.WriteLine($"Sign up {phone}"); - user = await client.SignUpAsync(phone, hash, code, "First", "Last"); - } - Console.WriteLine($"Sign in {phone}"); - user = await client.MakeAuthAsync(phone, hash, code); - } + private async Task MainAsync(string[] args) + { + TelegramClient client = null; - var contacts = await client.GetContactsAsync(); - Console.WriteLine("Contacts:"); - foreach (var contact in contacts.Users.OfType()) - { - var contactUser = contact as TLUser; - Console.WriteLine($"\t{contact.Id} {contact.Phone} {contact.FirstName} {contact.LastName}"); - } + client = new TelegramClient(APIId, APIHash); + // subscribe an event to receive live messages + client.Updates += ClientUpdates; + await client.ConnectAsync(); + Console.WriteLine($"Authorised: {client.IsUserAuthorized()}"); + TLUser user = null; + // -- If the user has already authenticated, this step will prevent account from being blocked as it + // -- reuses the data from last authorisation. + if (client.IsUserAuthorized()) + user = client.Session.TLUser; + else + { + var registered = await client.IsPhoneRegisteredAsync(phone); + var hash = await client.SendCodeRequestAsync(phone); + Console.Write("Code: "); + var code = Console.ReadLine(); + if (!registered) + { + Console.WriteLine($"Sign up {phone}"); + user = await client.SignUpAsync(phone, hash, code, "First", "Last"); + } + Console.WriteLine($"Sign in {phone}"); + user = await client.MakeAuthAsync(phone, hash, code); + } + + var contacts = await client.GetContactsAsync(); + Console.WriteLine("Contacts:"); + foreach (var contact in contacts.Users.OfType()) + { + var contactUser = contact as TLUser; + Console.WriteLine($"\t{contact.Id} {contact.Phone} {contact.FirstName} {contact.LastName}"); + } - var dialogs = (TLDialogs) await client.GetUserDialogsAsync(); - Console.WriteLine("Channels: "); - foreach (var channelObj in dialogs.Chats.OfType()) - { - var channel = channelObj as TLChannel; - Console.WriteLine($"\tChat: {channel.Title}"); - } + var dialogs = (TLDialogs) await client.GetUserDialogsAsync(); + Console.WriteLine("Channels: "); + foreach (var channelObj in dialogs.Chats.OfType()) + { + var channel = channelObj as TLChannel; + Console.WriteLine($"\tChat: {channel.Title}"); + } - Console.WriteLine("Groups:"); - TLChat chat = null; - foreach (var chatObj in dialogs.Chats.OfType()) - { - chat = chatObj as TLChat; - Console.WriteLine($"Chat name: {chat.Title}"); - var request = new TLRequestGetFullChat() { ChatId = chat.Id }; - var fullChat = await client.SendRequestAsync(request); + Console.WriteLine("Groups:"); + TLChat chat = null; + foreach (var chatObj in dialogs.Chats.OfType()) + { + chat = chatObj as TLChat; + Console.WriteLine($"Chat name: {chat.Title}"); + var request = new TLRequestGetFullChat() { ChatId = chat.Id }; + var fullChat = await client.SendRequestAsync(request); - var participants = (fullChat.FullChat as TeleSharp.TL.TLChatFull).Participants as TLChatParticipants; - foreach (var p in participants.Participants) - { - if (p is TLChatParticipant) - { - var participant = p as TLChatParticipant; - Console.WriteLine($"\t{participant.UserId}"); - } - else if (p is TLChatParticipantAdmin) - { - var participant = p as TLChatParticipantAdmin; - Console.WriteLine($"\t{participant.UserId}**"); - } - else if (p is TLChatParticipantCreator) - { - var participant = p as TLChatParticipantCreator; - Console.WriteLine($"\t{participant.UserId}**"); - } - } + var participants = (fullChat.FullChat as TeleSharp.TL.TLChatFull).Participants as TLChatParticipants; + foreach (var p in participants.Participants) + { + if (p is TLChatParticipant chatParticipant) + { + Console.WriteLine($"\t{chatParticipant.UserId}"); + } + else if (p is TLChatParticipantAdmin chatParticipantAdmin) + { + Console.WriteLine($"\t{chatParticipantAdmin.UserId}**"); + } + else if (p is TLChatParticipantCreator chatParticipantCreator) + { + Console.WriteLine($"\t{chatParticipantCreator.UserId}**"); + } + } - var peer = new TLInputPeerChat() { ChatId = chat.Id }; - var m = await client.GetHistoryAsync(peer, 0, 0, 0); - Console.WriteLine(m); - if (m is TLMessages) - { - var messages = m as TLMessages; + var peer = new TLInputPeerChat() { ChatId = chat.Id }; + var msg = await client.GetHistoryAsync(peer, 0, 0, 0); + Console.WriteLine(msg); + if (msg is TLMessages messages) + { + foreach (var message in messages.Messages) + { + if (message is TLMessage m1) + { + Console.WriteLine($"\t\t{m1.Id} {m1.Message}"); + } + else if (message is TLMessageService msgService) + { + Console.WriteLine($"\t\t{msgService.Id} {msgService.Action}"); + } + } + } + else if (msg is TLMessagesSlice messagesSlice) + { + bool done = false; + int total = 0; + while (!done) + { + foreach (var m1 in messagesSlice.Messages) + { + if (m1 is TLMessage message) + { + Console.WriteLine($"\t\t{message.Id} {message.Message}"); + ++total; + } + else if (m1 is TLMessageService messageService) + { + Console.WriteLine($"\t\t{messageService.Id} {messageService.Action}"); + ++total; + done = messageService.Action is TLMessageActionChatCreate; + } + } + msg = await client.GetHistoryAsync(peer, total, 0, 0); + } + } + } + // -- Wait in a loop to handle incoming updates. No need to poll. + for (; ; ) + { + await client.WaitEventAsync(TimeSpan.FromSeconds(1)); + } + } - foreach (var message in messages.Messages) - { - if (message is TLMessage) - { - var m1 = message as TLMessage; - Console.WriteLine($"\t\t{m1.Id} {m1.Message}"); - } - else if (message is TLMessageService) - { - var m1 = message as TLMessageService; - Console.WriteLine($"\t\t{m1.Id} {m1.Action}"); - } - } - } - else if (m is TLMessagesSlice) - { - bool done = false; - int total = 0; - while (!done) - { - var messages = m as TLMessagesSlice; + private void ClientUpdates(TelegramClient client, TLAbsUpdates updates) + { + Console.WriteLine($"Got update: {updates}"); + if (updates is TLUpdateShort updateShort) + { + Console.WriteLine($"Short: {updateShort.Update}"); + if (updateShort.Update is TLUpdateUserStatus status) + { + Console.WriteLine($"User {status.UserId} is {status.Status}"); + if (status.Status is TLUserStatusOnline) + { + var peer = new TLInputPeerUser() { UserId = status.UserId }; + client.SendMessageAsync(peer, "Você está online.").Wait(); + } + } + } + else if (updates is TLUpdateShortMessage message) + { + Console.WriteLine($"Message: {message.Message}"); + MarkMessageRead(client, new TLInputPeerUser() { UserId = message.UserId }, message.Id); + } + else if (updates is TLUpdateShortChatMessage shortChatMessage) + { + Console.WriteLine($"Chat Message: {shortChatMessage.Message}"); + MarkMessageRead(client, new TLInputPeerChat() { ChatId = shortChatMessage.ChatId }, shortChatMessage.Id); + } + else if (updates is TLUpdates allUpdates) + { + foreach (var update in allUpdates.Updates) + { + Console.WriteLine($"\t{update}"); + if (update is TLUpdateNewChannelMessage metaMessage) + { + var channelMsg = metaMessage.Message as TLMessage; + Console.WriteLine($"Channel message: {channelMsg.Message}"); + var channel = allUpdates.Chats[0] as TLChannel; + MarkMessageRead(client, + new TLInputPeerChannel() { ChannelId = channel.Id, AccessHash = channel.AccessHash.Value }, + channelMsg.Id); + } + } - foreach (var m1 in messages.Messages) - { - if (m1 is TLMessage) - { - var message = m1 as TLMessage; - Console.WriteLine($"\t\t{message.Id} {message.Message}"); - ++total; - } - else if (m1 is TLMessageService) - { - var message = m1 as TLMessageService; - Console.WriteLine($"\t\t{message.Id} {message.Action}"); - ++total; - done = message.Action is TLMessageActionChatCreate; - } - } - m = await client.GetHistoryAsync(peer, total, 0, 0); - } - } - } - - // -- Wait in a loop to handle incoming updates. No need to poll. - for (;;) - { - await client.WaitEventAsync(); - } - } + foreach (var user in allUpdates.Users) + { + Console.WriteLine($"{user}"); + } - private void Client_Updates(TelegramClient client, TLAbsUpdates updates) - { - Console.WriteLine($"Got update: {updates}"); - if (updates is TLUpdateShort) - { - var updateShort = updates as TLUpdateShort; - Console.WriteLine($"Short: {updateShort.Update}"); - if (updateShort.Update is TLUpdateUserStatus) - { - var status = updateShort.Update as TLUpdateUserStatus; - Console.WriteLine($"User {status.UserId} is {status.Status}"); - if (status.Status is TLUserStatusOnline) - { - try - { - var peer = new TLInputPeerUser() { UserId = status.UserId }; - client.SendMessageAsync(peer, "Você está online.").Wait(); - } - catch (Exception e) - { - Console.WriteLine(e); - } - } - } - } - else if (updates is TLUpdateShortMessage) - { - var message = updates as TLUpdateShortMessage; - Console.WriteLine($"Message: {message.Message}"); - MarkMessageRead(client, new TLInputPeerUser() { UserId = message.UserId }, message.Id); - } - else if (updates is TLUpdateShortChatMessage) - { - var message = updates as TLUpdateShortChatMessage; - Console.WriteLine($"Chat Message: {message.Message}"); - MarkMessageRead(client, new TLInputPeerChat() { ChatId = message.ChatId }, message.Id); - } - else if (updates is TLUpdates) - { - var allUpdates = updates as TLUpdates; - foreach (var update in allUpdates.Updates) - { - Console.WriteLine($"\t{update}"); - if (update is TLUpdateNewChannelMessage) - { - var metaMessage = update as TLUpdateNewChannelMessage; - var message = metaMessage.Message as TLMessage; - Console.WriteLine($"Channel message: {message.Message}"); - var channel = allUpdates.Chats[0] as TLChannel; - MarkMessageRead(client, - new TLInputPeerChannel() { ChannelId = channel.Id, AccessHash = channel.AccessHash.Value }, - message.Id ); - } - } + foreach (var chat in allUpdates.Chats) + { + Console.WriteLine($"{chat}"); + } + } + } - foreach(var user in allUpdates.Users) - { - Console.WriteLine($"{user}"); - } - - foreach (var chat in allUpdates.Chats) - { - Console.WriteLine($"{chat}"); - } - } - } - - private void MarkMessageRead(TelegramClient client, TLAbsInputPeer peer, int id) - { - // An exception happens here but it's not fatal. - try - { - var request = new TLRequestReadHistory(); - request.MaxId = id; - request.Peer = peer; - client.SendRequestAsync(request).Wait(); - } - catch (InvalidOperationException e){ - System.Console.WriteLine($"MarkMessageRead Error: {e.getMessage()}") - } - - } - } - } + private void MarkMessageRead(TelegramClient client, TLAbsInputPeer peer, int id) + { + try + { + var request = new TLRequestReadHistory(); + request.MaxId = id; + request.Peer = peer; + client.SendRequestAsync(request).Wait(); + } + catch (InvalidOperationException e) + { + Console.WriteLine($"MarkMessageRead Error: {e.Message}"); + } + } + } +} ``` # Available Methods diff --git a/TLSharp.Core/Network/MtProtoSender.cs b/TLSharp.Core/Network/MtProtoSender.cs index a2de927..c99e289 100644 --- a/TLSharp.Core/Network/MtProtoSender.cs +++ b/TLSharp.Core/Network/MtProtoSender.cs @@ -42,7 +42,7 @@ namespace TLSharp.Core.Network return confirmed ? session.Sequence++ * 2 + 1 : session.Sequence * 2; } - public async Task Send(TLMethod request, CancellationToken token = default(CancellationToken)) + public async Task Send(TeleSharp.TL.TLMethod request, CancellationToken token = default(CancellationToken)) { token.ThrowIfCancellationRequested(); @@ -69,7 +69,7 @@ namespace TLSharp.Core.Network session.Save(); } - public async Task Send(byte[] packet, TLMethod request, CancellationToken token = default(CancellationToken)) + public async Task Send(byte[] packet, TeleSharp.TL.TLMethod request, CancellationToken token = default(CancellationToken)) { token.ThrowIfCancellationRequested(); @@ -156,7 +156,7 @@ namespace TLSharp.Core.Network return new Tuple(message, remoteMessageId, remoteSequence); } - public async Task Receive(TLMethod request, CancellationToken token = default(CancellationToken)) + public async Task Receive(TeleSharp.TL.TLMethod request, CancellationToken token = default(CancellationToken)) { while (!request.ConfirmReceived) { @@ -269,17 +269,17 @@ namespace TLSharp.Core.Network private bool HandleUpdate(uint code, int sequence, BinaryReader messageReader, TLMethod request) { - try - { - var update = ParseUpdate (code, messageReader); - if (update != null && UpdatesEvent != null) + try + { + var update = ParseUpdate(code, messageReader); + if (update != null && UpdatesEvent != null) { - UpdatesEvent (update); + UpdatesEvent(update); } return true; - } - catch (Exception e) - { + } + catch (Exception e) + { return false; } } @@ -338,7 +338,7 @@ namespace TLSharp.Core.Network return true; } - private bool HandleRpcResult(ulong messageId, int sequence, BinaryReader messageReader, TLMethod request) + private bool HandleRpcResult(ulong messageId, int sequence, BinaryReader messageReader, TeleSharp.TL.TLMethod request) { uint code = messageReader.ReadUInt32(); ulong requestId = messageReader.ReadUInt64(); @@ -561,7 +561,7 @@ namespace TLSharp.Core.Network return true; } - private bool HandlePong(ulong messageId, int sequence, BinaryReader messageReader, TLMethod request) + private bool HandlePong(ulong messageId, int sequence, BinaryReader messageReader, TeleSharp.TL.TLMethod request) { uint code = messageReader.ReadUInt32(); ulong msgId = messageReader.ReadUInt64(); diff --git a/TLSharp.Core/Network/TcpTransport.cs b/TLSharp.Core/Network/TcpTransport.cs index 5cac252..0433df3 100644 --- a/TLSharp.Core/Network/TcpTransport.cs +++ b/TLSharp.Core/Network/TcpTransport.cs @@ -113,7 +113,8 @@ namespace TLSharp.Core.Network try { bytes = stream.Read(packetLengthBytes, 0, 4); - } catch (System.IO.IOException io) + } + catch (System.IO.IOException io) { var socketError = io.InnerException as SocketException; if (socketError != null && socketError.SocketErrorCode == SocketError.TimedOut) diff --git a/TLSharp.Core/TelegramClient.cs b/TLSharp.Core/TelegramClient.cs index 6a23399..666f430 100644 --- a/TLSharp.Core/TelegramClient.cs +++ b/TLSharp.Core/TelegramClient.cs @@ -25,16 +25,16 @@ namespace TLSharp.Core public class TelegramClient : IDisposable { private MtProtoSender sender; - private AuthKey _key; + private AuthKey key; private TcpTransport transport; - private string apiHash = ""; + private string apiHash = String.Empty; private int apiId = 0; private Session session; private List dcOptions; private TcpClientConnectionHandler handler; private DataCenterIPVersion dcIpVersion; - private bool _looping = true; + private bool looping = true; public delegate void UpdatesEvent (TelegramClient source, TLAbsUpdates updates); public delegate void ClientEvent(TelegramClient source); @@ -162,14 +162,14 @@ namespace TLSharp.Core public void Close() { - _looping = false; + looping = false; } public async Task MainLoopAsync(TimeSpan timeToWait, CancellationToken token = default(CancellationToken)) { var lastPing = DateTime.UtcNow; await SendPingAsync(); - while (_looping) + while (looping) { try { diff --git a/TLSharp.Tests/TLSharpTests.cs b/TLSharp.Tests/TLSharpTests.cs index c73bcec..9cad26a 100644 --- a/TLSharp.Tests/TLSharpTests.cs +++ b/TLSharp.Tests/TLSharpTests.cs @@ -12,6 +12,7 @@ using TeleSharp.TL; using TeleSharp.TL.Messages; using TLSharp.Core; using TLSharp.Core.Exceptions; +using TLSharp.Core.Network.Exceptions; using TLSharp.Core.Utils; namespace TLSharp.Tests @@ -285,7 +286,7 @@ namespace TLSharp.Tests .FirstOrDefault(x => x.Id == 5880094); var photo = ((TLUserProfilePhoto)user.Photo); - var photoLocation = (TLFileLocation)photo.PhotoBig; + var photoLocation = (TLFileLocation) photo.PhotoBig; var resFile = await client.GetFile(new TLInputFileLocation() { @@ -332,7 +333,7 @@ namespace TLSharp.Tests { await CheckPhones(); } - catch (Core.Network.Exceptions.FloodException floodException) + catch (FloodException floodException) { Console.WriteLine($"FLOODEXCEPTION: {floodException}"); Thread.Sleep(floodException.TimeToWait); @@ -369,7 +370,7 @@ namespace TLSharp.Tests if (user == null) { - throw new Exception("Username was not found: " + UserNameToSendMessage); + throw new System.Exception("Username was not found: " + UserNameToSendMessage); } await client.SendTypingAsync(new TLInputPeerUser() { UserId = user.Id }); @@ -413,13 +414,16 @@ namespace TLSharp.Tests } } + // Things to note:- If the updates are not getting triggered, please re-authenticate the user + // Would trigger the updates on a seperate thread if possible + client.Updates += (TelegramClient tclient, TLAbsUpdates updates) => { if (updates is TLUpdates) { - var allupdates = updates as TLUpdates; + var allUpdates = updates as TLUpdates; - foreach (var update in allupdates.Updates) + foreach (var update in allUpdates.Updates) { if (update is TLUpdateNewMessage) { @@ -431,9 +435,10 @@ namespace TLSharp.Tests } }; - await client.MainLoopAsync(new TimeSpan(0, 0, 1)); + Console.WriteLine("Send yourself an UPDATE_1 message to trigger update during loop"); + Debug.WriteLine("Send yourself an UPDATE_1 message to trigger update during loop"); - // At this point you would send yourself a UPDATE_1 message to trigger update + await client.MainLoopAsync(new TimeSpan(0, 0, 1)); Assert.IsTrue(newMsgs.Count == 1); Assert.IsTrue(newMsgs.First().Message.Equals("UPDATE_1"));