pr review updates

This commit is contained in:
mark 2020-05-10 18:19:52 +01:00
parent 43d9d12167
commit f258b6ede8
5 changed files with 228 additions and 257 deletions

427
README.md
View file

@ -140,250 +140,215 @@ Full code you can see at [DownloadFileFromContactTest](https://github.com/sochix
# Events Sample code # Events Sample code
```csharp ```csharp
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using TeleSharp.TL; using TeleSharp.TL;
using TLSharp.Core; using TLSharp.Core;
using System.Linq; using System.Linq;
using TeleSharp.TL.Messages; using TeleSharp.TL.Messages;
using System.Collections.Generic;
namespace TLSharpPOC namespace TLSharpPOC
{ {
class MainClass class MainClass
{ {
const int APIId = 0; const int APIId = 0;
const string APIHash = "???"; const string APIHash = "???";
const string phone = "???"; const string phone = "???";
public static void Main(string[] args) public static void Main(string[] args)
{ {
new MainClass().MainAsync(args).Wait(); new MainClass().MainAsync(args).Wait();
} }
private async Task MainAsync(string[] args) private async Task MainAsync(string[] args)
{ {
TelegramClient client = null; 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);
}
var contacts = await client.GetContactsAsync(); client = new TelegramClient(APIId, APIHash);
Console.WriteLine("Contacts:"); // subscribe an event to receive live messages
foreach (var contact in contacts.Users.OfType<TLUser>()) client.Updates += ClientUpdates;
{ await client.ConnectAsync();
var contactUser = contact as TLUser; Console.WriteLine($"Authorised: {client.IsUserAuthorized()}");
Console.WriteLine($"\t{contact.Id} {contact.Phone} {contact.FirstName} {contact.LastName}"); 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<TLUser>())
{
var contactUser = contact as TLUser;
Console.WriteLine($"\t{contact.Id} {contact.Phone} {contact.FirstName} {contact.LastName}");
}
var dialogs = (TLDialogs) await client.GetUserDialogsAsync(); var dialogs = (TLDialogs) await client.GetUserDialogsAsync();
Console.WriteLine("Channels: "); Console.WriteLine("Channels: ");
foreach (var channelObj in dialogs.Chats.OfType<TLChannel>()) foreach (var channelObj in dialogs.Chats.OfType<TLChannel>())
{ {
var channel = channelObj as TLChannel; var channel = channelObj as TLChannel;
Console.WriteLine($"\tChat: {channel.Title}"); Console.WriteLine($"\tChat: {channel.Title}");
} }
Console.WriteLine("Groups:"); Console.WriteLine("Groups:");
TLChat chat = null; TLChat chat = null;
foreach (var chatObj in dialogs.Chats.OfType<TLChat>()) foreach (var chatObj in dialogs.Chats.OfType<TLChat>())
{ {
chat = chatObj as TLChat; chat = chatObj as TLChat;
Console.WriteLine($"Chat name: {chat.Title}"); Console.WriteLine($"Chat name: {chat.Title}");
var request = new TLRequestGetFullChat() { ChatId = chat.Id }; var request = new TLRequestGetFullChat() { ChatId = chat.Id };
var fullChat = await client.SendRequestAsync<TeleSharp.TL.Messages.TLChatFull>(request); var fullChat = await client.SendRequestAsync<TeleSharp.TL.Messages.TLChatFull>(request);
var participants = (fullChat.FullChat as TeleSharp.TL.TLChatFull).Participants as TLChatParticipants; var participants = (fullChat.FullChat as TeleSharp.TL.TLChatFull).Participants as TLChatParticipants;
foreach (var p in participants.Participants) foreach (var p in participants.Participants)
{ {
if (p is TLChatParticipant) if (p is TLChatParticipant chatParticipant)
{ {
var participant = p as TLChatParticipant; Console.WriteLine($"\t{chatParticipant.UserId}");
Console.WriteLine($"\t{participant.UserId}"); }
} else if (p is TLChatParticipantAdmin chatParticipantAdmin)
else if (p is TLChatParticipantAdmin) {
{ Console.WriteLine($"\t{chatParticipantAdmin.UserId}**");
var participant = p as TLChatParticipantAdmin; }
Console.WriteLine($"\t{participant.UserId}**"); else if (p is TLChatParticipantCreator chatParticipantCreator)
} {
else if (p is TLChatParticipantCreator) Console.WriteLine($"\t{chatParticipantCreator.UserId}**");
{ }
var participant = p as TLChatParticipantCreator; }
Console.WriteLine($"\t{participant.UserId}**");
}
}
var peer = new TLInputPeerChat() { ChatId = chat.Id }; var peer = new TLInputPeerChat() { ChatId = chat.Id };
var m = await client.GetHistoryAsync(peer, 0, 0, 0); var msg = await client.GetHistoryAsync(peer, 0, 0, 0);
Console.WriteLine(m); Console.WriteLine(msg);
if (m is TLMessages) if (msg is TLMessages messages)
{ {
var messages = m as TLMessages; 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) private void ClientUpdates(TelegramClient client, TLAbsUpdates updates)
{ {
if (message is TLMessage) Console.WriteLine($"Got update: {updates}");
{ if (updates is TLUpdateShort updateShort)
var m1 = message as TLMessage; {
Console.WriteLine($"\t\t{m1.Id} {m1.Message}"); Console.WriteLine($"Short: {updateShort.Update}");
} if (updateShort.Update is TLUpdateUserStatus status)
else if (message is TLMessageService) {
{ Console.WriteLine($"User {status.UserId} is {status.Status}");
var m1 = message as TLMessageService; if (status.Status is TLUserStatusOnline)
Console.WriteLine($"\t\t{m1.Id} {m1.Action}"); {
} var peer = new TLInputPeerUser() { UserId = status.UserId };
} client.SendMessageAsync(peer, "Você está online.").Wait();
} }
else if (m is TLMessagesSlice) }
{ }
bool done = false; else if (updates is TLUpdateShortMessage message)
int total = 0; {
while (!done) Console.WriteLine($"Message: {message.Message}");
{ MarkMessageRead(client, new TLInputPeerUser() { UserId = message.UserId }, message.Id);
var messages = m as TLMessagesSlice; }
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) foreach (var user in allUpdates.Users)
{ {
if (m1 is TLMessage) Console.WriteLine($"{user}");
{ }
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();
}
}
private void Client_Updates(TelegramClient client, TLAbsUpdates updates) foreach (var chat in allUpdates.Chats)
{ {
Console.WriteLine($"Got update: {updates}"); Console.WriteLine($"{chat}");
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 user in allUpdates.Users) private void MarkMessageRead(TelegramClient client, TLAbsInputPeer peer, int id)
{ {
Console.WriteLine($"{user}"); try
} {
var request = new TLRequestReadHistory();
foreach (var chat in allUpdates.Chats) request.MaxId = id;
{ request.Peer = peer;
Console.WriteLine($"{chat}"); client.SendRequestAsync<bool>(request).Wait();
} }
} catch (InvalidOperationException e)
} {
Console.WriteLine($"MarkMessageRead Error: {e.Message}");
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<bool>(request).Wait();
}
catch (InvalidOperationException e){
System.Console.WriteLine($"MarkMessageRead Error: {e.getMessage()}")
}
}
}
}
``` ```
# Available Methods # Available Methods

View file

@ -42,7 +42,7 @@ namespace TLSharp.Core.Network
return confirmed ? session.Sequence++ * 2 + 1 : session.Sequence * 2; 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(); token.ThrowIfCancellationRequested();
@ -69,7 +69,7 @@ namespace TLSharp.Core.Network
session.Save(); 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(); token.ThrowIfCancellationRequested();
@ -156,7 +156,7 @@ namespace TLSharp.Core.Network
return new Tuple<byte[], ulong, int>(message, remoteMessageId, remoteSequence); return new Tuple<byte[], ulong, int>(message, remoteMessageId, remoteSequence);
} }
public async Task<byte[]> Receive(TLMethod request, CancellationToken token = default(CancellationToken)) public async Task<byte[]> Receive(TeleSharp.TL.TLMethod request, CancellationToken token = default(CancellationToken))
{ {
while (!request.ConfirmReceived) while (!request.ConfirmReceived)
{ {
@ -269,17 +269,17 @@ namespace TLSharp.Core.Network
private bool HandleUpdate(uint code, int sequence, BinaryReader messageReader, TLMethod request) private bool HandleUpdate(uint code, int sequence, BinaryReader messageReader, TLMethod request)
{ {
try try
{ {
var update = ParseUpdate (code, messageReader); var update = ParseUpdate(code, messageReader);
if (update != null && UpdatesEvent != null) if (update != null && UpdatesEvent != null)
{ {
UpdatesEvent (update); UpdatesEvent(update);
} }
return true; return true;
} }
catch (Exception e) catch (Exception e)
{ {
return false; return false;
} }
} }
@ -338,7 +338,7 @@ namespace TLSharp.Core.Network
return true; 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(); uint code = messageReader.ReadUInt32();
ulong requestId = messageReader.ReadUInt64(); ulong requestId = messageReader.ReadUInt64();
@ -561,7 +561,7 @@ namespace TLSharp.Core.Network
return true; 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(); uint code = messageReader.ReadUInt32();
ulong msgId = messageReader.ReadUInt64(); ulong msgId = messageReader.ReadUInt64();

View file

@ -113,7 +113,8 @@ namespace TLSharp.Core.Network
try try
{ {
bytes = stream.Read(packetLengthBytes, 0, 4); bytes = stream.Read(packetLengthBytes, 0, 4);
} catch (System.IO.IOException io) }
catch (System.IO.IOException io)
{ {
var socketError = io.InnerException as SocketException; var socketError = io.InnerException as SocketException;
if (socketError != null && socketError.SocketErrorCode == SocketError.TimedOut) if (socketError != null && socketError.SocketErrorCode == SocketError.TimedOut)

View file

@ -25,16 +25,16 @@ namespace TLSharp.Core
public class TelegramClient : IDisposable public class TelegramClient : IDisposable
{ {
private MtProtoSender sender; private MtProtoSender sender;
private AuthKey _key; private AuthKey key;
private TcpTransport transport; private TcpTransport transport;
private string apiHash = ""; private string apiHash = String.Empty;
private int apiId = 0; private int apiId = 0;
private Session session; private Session session;
private List<TLDcOption> dcOptions; private List<TLDcOption> dcOptions;
private TcpClientConnectionHandler handler; private TcpClientConnectionHandler handler;
private DataCenterIPVersion dcIpVersion; private DataCenterIPVersion dcIpVersion;
private bool _looping = true; private bool looping = true;
public delegate void UpdatesEvent (TelegramClient source, TLAbsUpdates updates); public delegate void UpdatesEvent (TelegramClient source, TLAbsUpdates updates);
public delegate void ClientEvent(TelegramClient source); public delegate void ClientEvent(TelegramClient source);
@ -162,14 +162,14 @@ namespace TLSharp.Core
public void Close() public void Close()
{ {
_looping = false; looping = false;
} }
public async Task MainLoopAsync(TimeSpan timeToWait, CancellationToken token = default(CancellationToken)) public async Task MainLoopAsync(TimeSpan timeToWait, CancellationToken token = default(CancellationToken))
{ {
var lastPing = DateTime.UtcNow; var lastPing = DateTime.UtcNow;
await SendPingAsync(); await SendPingAsync();
while (_looping) while (looping)
{ {
try try
{ {

View file

@ -12,6 +12,7 @@ using TeleSharp.TL;
using TeleSharp.TL.Messages; using TeleSharp.TL.Messages;
using TLSharp.Core; using TLSharp.Core;
using TLSharp.Core.Exceptions; using TLSharp.Core.Exceptions;
using TLSharp.Core.Network.Exceptions;
using TLSharp.Core.Utils; using TLSharp.Core.Utils;
namespace TLSharp.Tests namespace TLSharp.Tests
@ -285,7 +286,7 @@ namespace TLSharp.Tests
.FirstOrDefault(x => x.Id == 5880094); .FirstOrDefault(x => x.Id == 5880094);
var photo = ((TLUserProfilePhoto)user.Photo); var photo = ((TLUserProfilePhoto)user.Photo);
var photoLocation = (TLFileLocation)photo.PhotoBig; var photoLocation = (TLFileLocation) photo.PhotoBig;
var resFile = await client.GetFile(new TLInputFileLocation() var resFile = await client.GetFile(new TLInputFileLocation()
{ {
@ -332,7 +333,7 @@ namespace TLSharp.Tests
{ {
await CheckPhones(); await CheckPhones();
} }
catch (Core.Network.Exceptions.FloodException floodException) catch (FloodException floodException)
{ {
Console.WriteLine($"FLOODEXCEPTION: {floodException}"); Console.WriteLine($"FLOODEXCEPTION: {floodException}");
Thread.Sleep(floodException.TimeToWait); Thread.Sleep(floodException.TimeToWait);
@ -369,7 +370,7 @@ namespace TLSharp.Tests
if (user == null) 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 }); 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) => client.Updates += (TelegramClient tclient, TLAbsUpdates updates) =>
{ {
if (updates is TLUpdates) 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) 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.Count == 1);
Assert.IsTrue(newMsgs.First().Message.Equals("UPDATE_1")); Assert.IsTrue(newMsgs.First().Message.Equals("UPDATE_1"));