Merge pull request #4 from sochix/master

Update to HEAD
This commit is contained in:
Afshin Arani 2016-11-16 15:37:22 +03:30 committed by GitHub
commit 7a6191871d
10 changed files with 386 additions and 62 deletions

View file

@ -2,6 +2,7 @@
[![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) [![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) [![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)
_Unofficial_ Telegram (http://telegram.org) client library implemented in C#. Latest TL scheme supported, thanks to Afshin Arani _Unofficial_ Telegram (http://telegram.org) client library implemented in C#. Latest TL scheme supported, thanks to Afshin Arani
@ -29,9 +30,13 @@ It's a perfect fit for any developer who would like to send data directly to Tel
# How do I add this to my project? # How do I add this to my project?
Library _almost_ ready for production usage. We need contributors to make 1.0.0 release. Install via NuGet
To use TLSharp follow next steps: ```
> Install-Package TLSharp
```
or build from source
1. Clone TLSharp from GitHub 1. Clone TLSharp from GitHub
1. Compile source with VS2015 or MonoDevelop 1. Compile source with VS2015 or MonoDevelop
@ -155,6 +160,7 @@ For your convenience TLSharp have wrappers for several Telegram API methods. You
1. SendUploadedDocument 1. SendUploadedDocument
1. GetFile 1. GetFile
1. UploadFile 1. UploadFile
1. SendPingAsync
**What if you can't find needed method at the list?** **What if you can't find needed method at the list?**
@ -187,9 +193,9 @@ Contributing is highly appreciated!
### Release 1.0.0 ### Release 1.0.0
* [DONE] Add PHONE_MIGRATE handling * [DONE] Add PHONE_MIGRATE handling
* Add FILE_MIGRATE handling * [DONE] Add FILE_MIGRATE handling
* Add Updates handling * Add Updates handling
* Add NuGet package * [DONE] Add NuGet package
* [DONE] Add wrappers for media uploading and downloading * [DONE] Add wrappers for media uploading and downloading
* Store user session as JSON * Store user session as JSON
@ -198,16 +204,16 @@ Contributing is highly appreciated!
#### What API layer is supported? #### What API layer is supported?
The latest one - 57. Thanks to Afshin Arani for his TLGenerator The latest one - 57. Thanks to Afshin Arani for his TLGenerator
#### I get an error MIGRATE_X? #### I get a xxxMigrationException or a MIGRATE_X error!
TLSharp library should automatically handle this errors. If you see such errors, pls create a new issue. TLSharp library should automatically handle these errors. If you see such errors, please open a new Github issue with the details (include a stacktrace, etc.).
#### I get an exception: System.IO.EndOfStreamException: Unable to read beyond the end of the stream. All test methos except that AuthenticationWorks and TestConnection return same error. I did every thing including setting api id and hash, and setting server address.- #### I get an exception: System.IO.EndOfStreamException: Unable to read beyond the end of the stream. All test methos except that AuthenticationWorks and TestConnection return same error. I did every thing including setting api id and hash, and setting server address.-
You should create a Telegram session. See [configuration guide](#sending-messages-set-up) You should create a Telegram session. See [configuration guide](#sending-messages-set-up)
#### Why I get FLOOD_WAIT error? #### Why do I get a FloodException/FLOOD_WAIT error?
[It's Telegram restrictions](https://core.telegram.org/api/errors#420-flood) It's likely [Telegram restrictions](https://core.telegram.org/api/errors#420-flood), or a bug in TLSharp (if you feel it's the latter, please open a Github issue). You can know the time to wait by accessing the FloodException::TimeToWait property.
#### Why does TLSharp lacks feature XXXX? #### Why does TLSharp lacks feature XXXX?

View file

@ -148,6 +148,19 @@ namespace TLSharp.Core.Network
return null; return null;
} }
public async Task SendPingAsync()
{
var pingRequest = new PingRequest();
using (var memory = new MemoryStream())
using (var writer = new BinaryWriter(memory))
{
pingRequest.SerializeBody(writer);
await Send(memory.ToArray(), pingRequest);
}
await Receive(pingRequest);
}
private bool processMessage(ulong messageId, int sequence, BinaryReader messageReader, TeleSharp.TL.TLMethod request) private bool processMessage(ulong messageId, int sequence, BinaryReader messageReader, TeleSharp.TL.TLMethod request)
{ {
// TODO: check salt // TODO: check salt
@ -169,7 +182,7 @@ namespace TLSharp.Core.Network
return HandlePing(messageId, sequence, messageReader); return HandlePing(messageId, sequence, messageReader);
case 0x347773c5: // pong case 0x347773c5: // pong
//logger.debug("MSG pong"); //logger.debug("MSG pong");
return HandlePong(messageId, sequence, messageReader); return HandlePong(messageId, sequence, messageReader, request);
case 0xae500895: // future_salts case 0xae500895: // future_salts
//logger.debug("MSG future_salts"); //logger.debug("MSG future_salts");
return HandleFutureSalts(messageId, sequence, messageReader); return HandleFutureSalts(messageId, sequence, messageReader);
@ -272,14 +285,29 @@ namespace TLSharp.Core.Network
{ {
var resultString = Regex.Match(errorMessage, @"\d+").Value; var resultString = Regex.Match(errorMessage, @"\d+").Value;
var seconds = int.Parse(resultString); var seconds = int.Parse(resultString);
Debug.WriteLine($"Should wait {seconds} sec."); throw new FloodException(TimeSpan.FromSeconds(seconds));
Thread.Sleep(1000 * seconds);
} }
else if (errorMessage.StartsWith("PHONE_MIGRATE_")) else if (errorMessage.StartsWith("PHONE_MIGRATE_"))
{ {
var resultString = Regex.Match(errorMessage, @"\d+").Value; var resultString = Regex.Match(errorMessage, @"\d+").Value;
var dcIdx = int.Parse(resultString); var dcIdx = int.Parse(resultString);
throw new MigrationNeededException(dcIdx); throw new PhoneMigrationException(dcIdx);
}
else if (errorMessage.StartsWith("FILE_MIGRATE_"))
{
var resultString = Regex.Match(errorMessage, @"\d+").Value;
var dcIdx = int.Parse(resultString);
throw new FileMigrationException(dcIdx);
}
else if (errorMessage.StartsWith("USER_MIGRATE_"))
{
var resultString = Regex.Match(errorMessage, @"\d+").Value;
var dcIdx = int.Parse(resultString);
throw new UserMigrationException(dcIdx);
}
else if (errorMessage == "PHONE_CODE_INVALID")
{
throw new InvalidPhoneCodeException("The numeric code used to authenticate does not match the numeric code sent by SMS/Telegram");
} }
else else
{ {
@ -440,8 +468,16 @@ namespace TLSharp.Core.Network
return true; return true;
} }
private bool HandlePong(ulong messageId, int sequence, BinaryReader messageReader) private bool HandlePong(ulong messageId, int sequence, BinaryReader messageReader, TeleSharp.TL.TLMethod request)
{ {
uint code = messageReader.ReadUInt32();
ulong msgId = messageReader.ReadUInt64();
if (msgId == (ulong)request.MessageId)
{
request.ConfirmReceived = true;
}
return false; return false;
} }
@ -483,14 +519,52 @@ namespace TLSharp.Core.Network
} }
} }
internal class MigrationNeededException : Exception public class FloodException : Exception
{
public TimeSpan TimeToWait { get; private set; }
internal FloodException(TimeSpan timeToWait)
: base($"Flood prevention. Telegram now requires your program to do requests again only after {timeToWait.TotalSeconds} seconds have passed ({nameof(TimeToWait)} property)." +
" If you think the culprit of this problem may lie in TLSharp's implementation, open a Github issue please.")
{
TimeToWait = timeToWait;
}
}
internal abstract class DataCenterMigrationException : Exception
{ {
internal int DC { get; private set; } internal int DC { get; private set; }
internal MigrationNeededException(int dc) private const string REPORT_MESSAGE =
: base ($"Your phone number is registered to a different DC: {dc}. Please migrate.") " See: https://github.com/sochix/TLSharp#i-get-a-xxxmigrationexception-or-a-migrate_x-error";
protected DataCenterMigrationException(string msg, int dc) : base (msg + REPORT_MESSAGE)
{ {
DC = dc; DC = dc;
} }
} }
internal class PhoneMigrationException : DataCenterMigrationException
{
internal PhoneMigrationException(int dc)
: base ($"Phone number registered to a different DC: {dc}.", dc)
{
}
}
internal class FileMigrationException : DataCenterMigrationException
{
internal FileMigrationException(int dc)
: base ($"File located on a different DC: {dc}.", dc)
{
}
}
internal class UserMigrationException : DataCenterMigrationException
{
internal UserMigrationException(int dc)
: base($"User located on a different DC: {dc}.", dc)
{
}
}
} }

View file

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.IO;
using TeleSharp.TL;
using TLSharp.Core.Utils;
namespace TLSharp.Core.Requests
{
public class PingRequest : TeleSharp.TL.TLMethod
{
public PingRequest()
{
}
public override void SerializeBody(BinaryWriter writer)
{
writer.Write(Constructor);
writer.Write(Helpers.GenerateRandomLong());
}
public override void DeserializeBody(BinaryReader reader)
{
throw new NotImplementedException();
}
public override void deserializeResponse(BinaryReader stream)
{
throw new NotImplementedException();
}
public override int Constructor
{
get
{
return 0x7abe77ec;
}
}
}
}

View file

@ -63,6 +63,7 @@
<Compile Include="Network\TcpTransport.cs" /> <Compile Include="Network\TcpTransport.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Requests\AckRequest.cs" /> <Compile Include="Requests\AckRequest.cs" />
<Compile Include="Requests\PingRequest.cs" />
<Compile Include="Utils\UploadHelper.cs" /> <Compile Include="Utils\UploadHelper.cs" />
<Compile Include="Session.cs" /> <Compile Include="Session.cs" />
<Compile Include="TelegramClient.cs" /> <Compile Include="TelegramClient.cs" />

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>TLSharp</id>
<version>0.$APPVEYOR_BUILD_VERSION$</version>
<title>Telegram client library implemented in C#</title>
<authors>Ilya P</authors>
<owners>Ilya P</owners>
<projectUrl>http://sochix.github.io/TLSharp/</projectUrl>
<iconUrl>https://core.telegram.org/favicon.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Unofficial Telegram (http://telegram.org) client library implemented in C#. Latest TL scheme supported.
Consider donation to speed up development process.
Bitcoin wallet: 3K1ocweFgaHnAibJ3n6hX7RNZWFTFcJjUe
It's a perfect fit for any developer who would like to send data directly to Telegram users or write own custom Telegram client.</description>
<tags>telegram client, telegram API</tags>
<copyright>Copyright 2016</copyright>
</metadata>
<files>
<file src="bin\Debug\BigMath.dll" target="lib\net45\BigMath.dll" />
<file src="bin\Debug\Ionic.ZLib.dll" target="lib\net45\Ionic.ZLib.dll" />
<file src="bin\Debug\TeleSharp.TL.dll" target="lib\net45\TeleSharp.TL.dll" />
<file src="bin\Debug\TLSharp.Core.dll" target="lib\net45\TLSharp.Core.dll" />
</files>
</package>

View file

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using TeleSharp.TL; using TeleSharp.TL;
using TeleSharp.TL.Account;
using TeleSharp.TL.Auth; using TeleSharp.TL.Auth;
using TeleSharp.TL.Contacts; using TeleSharp.TL.Contacts;
using TeleSharp.TL.Help; using TeleSharp.TL.Help;
@ -14,6 +15,7 @@ using TLSharp.Core.MTProto.Crypto;
using TLSharp.Core.Network; using TLSharp.Core.Network;
using TLSharp.Core.Requests; using TLSharp.Core.Requests;
using TLSharp.Core.Utils; using TLSharp.Core.Utils;
using TLAuthorization = TeleSharp.TL.Auth.TLAuthorization;
namespace TLSharp.Core namespace TLSharp.Core
{ {
@ -29,16 +31,17 @@ namespace TLSharp.Core
public TelegramClient(int apiId, string apiHash, ISessionStore store = null, string sessionUserId = "session") public TelegramClient(int apiId, string apiHash, ISessionStore store = null, string sessionUserId = "session")
{ {
if (apiId == default(int))
throw new MissingApiConfigurationException("API_ID");
if (string.IsNullOrEmpty(apiHash))
throw new MissingApiConfigurationException("API_HASH");
if (store == null) if (store == null)
store = new FileSessionStore(); store = new FileSessionStore();
TLContext.Init(); TLContext.Init();
_apiHash = apiHash; _apiHash = apiHash;
_apiId = apiId; _apiId = apiId;
if (_apiId == default(int))
throw new MissingApiConfigurationException("API_ID");
if (string.IsNullOrEmpty(_apiHash))
throw new MissingApiConfigurationException("API_HASH");
_session = Session.TryLoadOrCreateNew(store, sessionUserId); _session = Session.TryLoadOrCreateNew(store, sessionUserId);
_transport = new TcpTransport(_session.ServerAddress, _session.Port); _transport = new TcpTransport(_session.ServerAddress, _session.Port);
@ -96,6 +99,9 @@ namespace TLSharp.Core
public async Task<bool> IsPhoneRegisteredAsync(string phoneNumber) public async Task<bool> IsPhoneRegisteredAsync(string phoneNumber)
{ {
if (String.IsNullOrWhiteSpace(phoneNumber))
throw new ArgumentNullException(nameof(phoneNumber));
if (_sender == null) if (_sender == null)
throw new InvalidOperationException("Not connected!"); throw new InvalidOperationException("Not connected!");
@ -108,6 +114,9 @@ namespace TLSharp.Core
public async Task<string> SendCodeRequestAsync(string phoneNumber) public async Task<string> SendCodeRequestAsync(string phoneNumber)
{ {
if (String.IsNullOrWhiteSpace(phoneNumber))
throw new ArgumentNullException(nameof(phoneNumber));
var completed = false; var completed = false;
TLRequestSendCode request = null; TLRequestSendCode request = null;
@ -122,7 +131,7 @@ namespace TLSharp.Core
completed = true; completed = true;
} }
catch (MigrationNeededException ex) catch (PhoneMigrationException ex)
{ {
await ReconnectToDcAsync(ex.DC); await ReconnectToDcAsync(ex.DC);
} }
@ -133,6 +142,15 @@ namespace TLSharp.Core
public async Task<TLUser> MakeAuthAsync(string phoneNumber, string phoneCodeHash, string code) public async Task<TLUser> MakeAuthAsync(string phoneNumber, string phoneCodeHash, string code)
{ {
if (String.IsNullOrWhiteSpace(phoneNumber))
throw new ArgumentNullException(nameof(phoneNumber));
if (String.IsNullOrWhiteSpace(phoneCodeHash))
throw new ArgumentNullException(nameof(phoneCodeHash));
if (String.IsNullOrWhiteSpace(code))
throw new ArgumentNullException(nameof(code));
var request = new TLRequestSignIn() { phone_number = phoneNumber, phone_code_hash = phoneCodeHash, phone_code = code }; var request = new TLRequestSignIn() { phone_number = phoneNumber, phone_code_hash = phoneCodeHash, phone_code = code };
await _sender.Send(request); await _sender.Send(request);
await _sender.Receive(request); await _sender.Receive(request);
@ -152,12 +170,12 @@ namespace TLSharp.Core
return ((TLUser)request.Response.user); return ((TLUser)request.Response.user);
} }
public async Task<T> SendRequestAsync<T>(TLMethod methodtoExceute) public async Task<T> SendRequestAsync<T>(TLMethod methodToExecute)
{ {
await _sender.Send(methodtoExceute); await _sender.Send(methodToExecute);
await _sender.Receive(methodtoExceute); await _sender.Receive(methodToExecute);
var result = methodtoExceute.GetType().GetProperty("Response").GetValue(methodtoExceute); var result = methodToExecute.GetType().GetProperty("Response").GetValue(methodToExecute);
return (T)result; return (T)result;
} }
@ -196,10 +214,10 @@ namespace TLSharp.Core
return await SendRequestAsync<Boolean>(req); return await SendRequestAsync<Boolean>(req);
} }
public async Task<TLDialogs> GetUserDialogsAsync() public async Task<TLAbsDialogs> GetUserDialogsAsync()
{ {
var peer = new TLInputPeerSelf(); var peer = new TLInputPeerSelf();
return await SendRequestAsync<TLDialogs>( return await SendRequestAsync<TLAbsDialogs>(
new TLRequestGetDialogs() { offset_date = 0, offset_peer = peer, limit = 100 }); new TLRequestGetDialogs() { offset_date = 0, offset_peer = peer, limit = 100 });
} }
@ -236,12 +254,48 @@ namespace TLSharp.Core
public async Task<TLFile> GetFile(TLAbsInputFileLocation location, int filePartSize) public async Task<TLFile> GetFile(TLAbsInputFileLocation location, int filePartSize)
{ {
return await SendRequestAsync<TLFile>(new TLRequestGetFile() TLFile result = null;
try
{
result = await SendRequestAsync<TLFile>(new TLRequestGetFile()
{ {
location = location, location = location,
limit = filePartSize limit = filePartSize
}); });
} }
catch (FileMigrationException ex)
{
var exportedAuth = await SendRequestAsync<TLExportedAuthorization>(new TLRequestExportAuthorization() { dc_id = ex.DC });
var authKey = _session.AuthKey;
var timeOffset = _session.TimeOffset;
var serverAddress = _session.ServerAddress;
var serverPort = _session.Port;
await ReconnectToDcAsync(ex.DC);
var auth = await SendRequestAsync<TLAuthorization>(new TLRequestImportAuthorization
{
bytes = exportedAuth.bytes,
id = exportedAuth.id
});
result = await GetFile(location, filePartSize);
_session.AuthKey = authKey;
_session.TimeOffset = timeOffset;
_transport = new TcpTransport(serverAddress, serverPort);
_session.ServerAddress =serverAddress;
_session.Port = serverPort;
await ConnectAsync();
}
return result;
}
public async Task SendPingAsync()
{
await _sender.SendPingAsync();
}
private void OnUserAuthenticated(TLUser TLUser) private void OnUserAuthenticated(TLUser TLUser)
{ {
@ -261,4 +315,9 @@ namespace TLSharp.Core
{ {
} }
} }
public class InvalidPhoneCodeException : Exception
{
internal InvalidPhoneCodeException(string msg) : base(msg) { }
}
} }

View file

@ -24,6 +24,8 @@ namespace TLSharp.Tests
private string NumberToAuthenticate { get; set; } private string NumberToAuthenticate { get; set; }
private string CodeToAuthenticate { get; set; }
private string NotRegisteredNumberToSignUp { get; set; } private string NotRegisteredNumberToSignUp { get; set; }
private string UserNameToSendMessage { get; set; } private string UserNameToSendMessage { get; set; }
@ -58,39 +60,41 @@ namespace TLSharp.Tests
private void GatherTestConfiguration() private void GatherTestConfiguration()
{ {
string appConfigMsgWarning = "{0} not configured in app.config! Some tests may fail.";
ApiHash = ConfigurationManager.AppSettings[nameof(ApiHash)]; ApiHash = ConfigurationManager.AppSettings[nameof(ApiHash)];
if (string.IsNullOrEmpty(ApiHash)) if (string.IsNullOrEmpty(ApiHash))
Debug.WriteLine("ApiHash not configured in app.config! Some tests may fail."); Debug.WriteLine(appConfigMsgWarning, nameof(ApiHash));
var apiId = ConfigurationManager.AppSettings[nameof(ApiId)]; var apiId = ConfigurationManager.AppSettings[nameof(ApiId)];
if (string.IsNullOrEmpty(apiId)) if (string.IsNullOrEmpty(apiId))
Debug.WriteLine("ApiId not configured in app.config! Some tests may fail."); Debug.WriteLine(appConfigMsgWarning, nameof(ApiId));
else else
ApiId = int.Parse(apiId); ApiId = int.Parse(apiId);
NumberToAuthenticate = ConfigurationManager.AppSettings[nameof(NumberToAuthenticate)]; NumberToAuthenticate = ConfigurationManager.AppSettings[nameof(NumberToAuthenticate)];
if (string.IsNullOrEmpty(NumberToAuthenticate)) if (string.IsNullOrEmpty(NumberToAuthenticate))
Debug.WriteLine("NumberToAuthenticate not configured in app.config! Some tests may fail."); Debug.WriteLine(appConfigMsgWarning, nameof(NumberToAuthenticate));
CodeToAuthenticate = ConfigurationManager.AppSettings[nameof(CodeToAuthenticate)];
if (string.IsNullOrEmpty(CodeToAuthenticate))
Debug.WriteLine(appConfigMsgWarning, nameof(CodeToAuthenticate));
NotRegisteredNumberToSignUp = ConfigurationManager.AppSettings[nameof(NotRegisteredNumberToSignUp)]; NotRegisteredNumberToSignUp = ConfigurationManager.AppSettings[nameof(NotRegisteredNumberToSignUp)];
if (string.IsNullOrEmpty(NotRegisteredNumberToSignUp)) if (string.IsNullOrEmpty(NotRegisteredNumberToSignUp))
Debug.WriteLine("NotRegisteredNumberToSignUp not configured in app.config! Some tests may fail."); Debug.WriteLine(appConfigMsgWarning, nameof(NotRegisteredNumberToSignUp));
NumberToSendMessage = ConfigurationManager.AppSettings[nameof(NumberToSendMessage)];
if (string.IsNullOrEmpty(NumberToSendMessage))
Debug.WriteLine("NumberToSendMessage not configured in app.config! Some tests may fail.");
UserNameToSendMessage = ConfigurationManager.AppSettings[nameof(UserNameToSendMessage)]; UserNameToSendMessage = ConfigurationManager.AppSettings[nameof(UserNameToSendMessage)];
if (string.IsNullOrEmpty(UserNameToSendMessage)) if (string.IsNullOrEmpty(UserNameToSendMessage))
Debug.WriteLine("UserNameToSendMessage not configured in app.config! Some tests may fail."); Debug.WriteLine(appConfigMsgWarning, nameof(UserNameToSendMessage));
NumberToGetUserFull = ConfigurationManager.AppSettings[nameof(NumberToGetUserFull)]; NumberToGetUserFull = ConfigurationManager.AppSettings[nameof(NumberToGetUserFull)];
if (string.IsNullOrEmpty(NumberToGetUserFull)) if (string.IsNullOrEmpty(NumberToGetUserFull))
Debug.WriteLine("NumberToGetUserFull not configured in app.config! Some tests may fail."); Debug.WriteLine(appConfigMsgWarning, nameof(NumberToGetUserFull));
NumberToAddToChat = ConfigurationManager.AppSettings[nameof(NumberToAddToChat)]; NumberToAddToChat = ConfigurationManager.AppSettings[nameof(NumberToAddToChat)];
if (string.IsNullOrEmpty(NumberToAddToChat)) if (string.IsNullOrEmpty(NumberToAddToChat))
Debug.WriteLine("NumberToAddToChat not configured in app.config! Some tests may fail."); Debug.WriteLine(appConfigMsgWarning, nameof(NumberToAddToChat));
} }
[TestMethod] [TestMethod]
@ -101,9 +105,23 @@ namespace TLSharp.Tests
await client.ConnectAsync(); await client.ConnectAsync();
var hash = await client.SendCodeRequestAsync(NumberToAuthenticate); var hash = await client.SendCodeRequestAsync(NumberToAuthenticate);
var code = "93463"; // you can change code in debugger var code = CodeToAuthenticate; // you can change code in debugger too
var user = await client.MakeAuthAsync(NumberToAuthenticate, hash, code); if (String.IsNullOrWhiteSpace(code))
{
throw new Exception("CodeToAuthenticate is empty in the app.config file, fill it with the code you just got now by SMS/Telegram");
}
TLUser user = null;
try
{
user = await client.MakeAuthAsync(NumberToAuthenticate, hash, code);
}
catch (InvalidPhoneCodeException ex)
{
throw new Exception("CodeToAuthenticate is wrong in the app.config file, fill it with the code you just got now by SMS/Telegram",
ex);
}
Assert.IsNotNull(user); Assert.IsNotNull(user);
Assert.IsTrue(client.IsUserAuthorized()); Assert.IsTrue(client.IsUserAuthorized());
@ -112,6 +130,15 @@ namespace TLSharp.Tests
[TestMethod] [TestMethod]
public async Task SendMessageTest() public async Task SendMessageTest()
{ {
NumberToSendMessage = ConfigurationManager.AppSettings[nameof(NumberToSendMessage)];
if (string.IsNullOrWhiteSpace(NumberToSendMessage))
throw new Exception($"Please fill the '{nameof(NumberToSendMessage)}' setting in app.config file first");
// this is because the contacts in the address come without the "+" prefix
var normalizedNumber = NumberToSendMessage.StartsWith("+") ?
NumberToSendMessage.Substring(1, NumberToSendMessage.Length - 1) :
NumberToSendMessage;
var client = NewClient(); var client = NewClient();
await client.ConnectAsync(); await client.ConnectAsync();
@ -121,7 +148,7 @@ namespace TLSharp.Tests
var user = result.users.lists var user = result.users.lists
.Where(x => x.GetType() == typeof(TLUser)) .Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>() .Cast<TLUser>()
.FirstOrDefault(x => x.phone == NumberToSendMessage); .FirstOrDefault(x => x.phone == normalizedNumber);
if (user == null) if (user == null)
{ {
@ -131,7 +158,6 @@ namespace TLSharp.Tests
await client.SendTypingAsync(new TLInputPeerUser() { user_id = user.id }); await client.SendTypingAsync(new TLInputPeerUser() { user_id = user.id });
Thread.Sleep(3000); Thread.Sleep(3000);
await client.SendMessageAsync(new TLInputPeerUser() { user_id = user.id }, "TEST"); await client.SendMessageAsync(new TLInputPeerUser() { user_id = user.id }, "TEST");
} }
[TestMethod] [TestMethod]
@ -141,7 +167,7 @@ namespace TLSharp.Tests
await client.ConnectAsync(); await client.ConnectAsync();
var dialogs = await client.GetUserDialogsAsync(); var dialogs = (TLDialogs) await client.GetUserDialogsAsync();
var chat = dialogs.chats.lists var chat = dialogs.chats.lists
.Where(c => c.GetType() == typeof(TLChannel)) .Where(c => c.GetType() == typeof(TLChannel))
.Cast<TLChannel>() .Cast<TLChannel>()
@ -231,6 +257,36 @@ namespace TLSharp.Tests
Assert.IsTrue(resFile.bytes.Length > 0); Assert.IsTrue(resFile.bytes.Length > 0);
} }
[TestMethod]
public async Task DownloadFileFromWrongLocationTest()
{
var client = NewClient();
await client.ConnectAsync();
var result = await client.GetContactsAsync();
var user = result.users.lists
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.id == 5880094);
var photo = ((TLUserProfilePhoto)user.photo);
var photoLocation = (TLFileLocation) photo.photo_big;
var resFile = await client.GetFile(new TLInputFileLocation()
{
local_id = photoLocation.local_id,
secret = photoLocation.secret,
volume_id = photoLocation.volume_id
}, 1024);
var res = await client.GetUserDialogsAsync();
Assert.IsTrue(resFile.bytes.Length > 0);
}
[TestMethod] [TestMethod]
public async Task SignUpNewUser() public async Task SignUpNewUser()
{ {

View file

@ -4,6 +4,7 @@
<add key="ApiHash" value="" /> <add key="ApiHash" value="" />
<add key="ApiId" value="" /> <add key="ApiId" value="" />
<add key="NumberToAuthenticate" value="" /> <add key="NumberToAuthenticate" value="" />
<add key="CodeToAuthenticate" value="" />
<add key="NotRegisteredNumberToSignUp" value=""/> <add key="NotRegisteredNumberToSignUp" value=""/>
<add key="NumberToSendMessage" value=""/> <add key="NumberToSendMessage" value=""/>
<add key="UserNameToSendMessage" value=""/> <add key="UserNameToSendMessage" value=""/>

View file

@ -34,6 +34,41 @@ Global
{DE5C0467-EE99-4734-95F2-EFF7A0B99924}.Release|Any CPU.ActiveCfg = Release|Any CPU {DE5C0467-EE99-4734-95F2-EFF7A0B99924}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE5C0467-EE99-4734-95F2-EFF7A0B99924}.Release|Any CPU.Build.0 = Release|Any CPU {DE5C0467-EE99-4734-95F2-EFF7A0B99924}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
$0.TextStylePolicy = $1
$1.inheritsSet = VisualStudio
$1.inheritsScope = text/plain
$1.scope = text/x-csharp
$0.CSharpFormattingPolicy = $2
$2.IndentSwitchBody = True
$2.IndentBlocksInsideExpressions = True
$2.AnonymousMethodBraceStyle = NextLine
$2.PropertyBraceStyle = NextLine
$2.PropertyGetBraceStyle = NextLine
$2.PropertySetBraceStyle = NextLine
$2.EventBraceStyle = NextLine
$2.EventAddBraceStyle = NextLine
$2.EventRemoveBraceStyle = NextLine
$2.StatementBraceStyle = NextLine
$2.ElseNewLinePlacement = NewLine
$2.CatchNewLinePlacement = NewLine
$2.FinallyNewLinePlacement = NewLine
$2.WhileNewLinePlacement = DoNotCare
$2.ArrayInitializerWrapping = DoNotChange
$2.ArrayInitializerBraceStyle = NextLine
$2.BeforeMethodDeclarationParentheses = False
$2.BeforeMethodCallParentheses = False
$2.BeforeConstructorDeclarationParentheses = False
$2.NewLineBeforeConstructorInitializerColon = NewLine
$2.NewLineAfterConstructorInitializerColon = SameLine
$2.BeforeDelegateDeclarationParentheses = False
$2.NewParentheses = False
$2.SpacesBeforeBrackets = False
$2.inheritsSet = Mono
$2.inheritsScope = text/x-csharp
$2.scope = text/x-csharp
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection

View file

@ -22,7 +22,7 @@ namespace TeleSharp.TL
public override void DeserializeBody(BinaryReader br) public override void DeserializeBody(BinaryReader br)
{ {
int count = br.ReadInt32(); int count = br.ReadInt32();
for(int i= 0;i< count;i++) for (var i = 0; i < count; i++)
{ {
if (typeof(T) == typeof(int)) if (typeof(T) == typeof(int))
{ {
@ -56,9 +56,34 @@ namespace TeleSharp.TL
bw.Write(Constructor); bw.Write(Constructor);
bw.Write(lists.Count()); bw.Write(lists.Count());
foreach (var item in lists.Cast<TLObject>()) foreach (var item in lists)
{ {
item.SerializeBody(bw); if (typeof(T) == typeof(int))
{
var res = (int)Convert.ChangeType(item, typeof(int));
bw.Write(res);
}
else if (typeof(T) == typeof(long))
{
var res = (long)Convert.ChangeType(item, typeof(long));
bw.Write(res);
}
else if (typeof(T) == typeof(string))
{
var res = (string)(Convert.ChangeType(item, typeof(string)));
StringUtil.Serialize(res, bw);
}
else if (typeof(T) == typeof(double))
{
var res = (double)Convert.ChangeType(item, typeof(double));
bw.Write(res);
}
else if (typeof(T).BaseType == typeof(TLObject))
{
var res = (TLObject)(object)item;
res.SerializeBody(bw);
}
} }
} }
} }