mirror of
https://github.com/sochix/TLSharp.git
synced 2025-12-06 08:02:00 +01:00
commit
7a6191871d
22
README.md
22
README.md
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
[](https://gitter.im/TLSharp/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://ci.appveyor.com/project/sochix/tlsharp)
|
||||
[](https://badge.fury.io/nu/TLSharp)
|
||||
|
||||
_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?
|
||||
|
||||
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. 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. GetFile
|
||||
1. UploadFile
|
||||
1. SendPingAsync
|
||||
|
||||
**What if you can't find needed method at the list?**
|
||||
|
||||
|
|
@ -187,9 +193,9 @@ Contributing is highly appreciated!
|
|||
### Release 1.0.0
|
||||
|
||||
* [DONE] Add PHONE_MIGRATE handling
|
||||
* Add FILE_MIGRATE handling
|
||||
* [DONE] Add FILE_MIGRATE handling
|
||||
* Add Updates handling
|
||||
* Add NuGet package
|
||||
* [DONE] Add NuGet package
|
||||
* [DONE] Add wrappers for media uploading and downloading
|
||||
* Store user session as JSON
|
||||
|
||||
|
|
@ -198,16 +204,16 @@ Contributing is highly appreciated!
|
|||
#### What API layer is supported?
|
||||
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.-
|
||||
|
||||
You should create a Telegram session. See [configuration guide](#sending-messages-set-up)
|
||||
|
||||
#### Why I get FLOOD_WAIT error?
|
||||
[It's Telegram restrictions](https://core.telegram.org/api/errors#420-flood)
|
||||
#### Why do I get a FloodException/FLOOD_WAIT error?
|
||||
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?
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,19 @@ namespace TLSharp.Core.Network
|
|||
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)
|
||||
{
|
||||
// TODO: check salt
|
||||
|
|
@ -169,7 +182,7 @@ namespace TLSharp.Core.Network
|
|||
return HandlePing(messageId, sequence, messageReader);
|
||||
case 0x347773c5: // pong
|
||||
//logger.debug("MSG pong");
|
||||
return HandlePong(messageId, sequence, messageReader);
|
||||
return HandlePong(messageId, sequence, messageReader, request);
|
||||
case 0xae500895: // future_salts
|
||||
//logger.debug("MSG future_salts");
|
||||
return HandleFutureSalts(messageId, sequence, messageReader);
|
||||
|
|
@ -272,14 +285,29 @@ namespace TLSharp.Core.Network
|
|||
{
|
||||
var resultString = Regex.Match(errorMessage, @"\d+").Value;
|
||||
var seconds = int.Parse(resultString);
|
||||
Debug.WriteLine($"Should wait {seconds} sec.");
|
||||
Thread.Sleep(1000 * seconds);
|
||||
throw new FloodException(TimeSpan.FromSeconds(seconds));
|
||||
}
|
||||
else if (errorMessage.StartsWith("PHONE_MIGRATE_"))
|
||||
{
|
||||
var resultString = Regex.Match(errorMessage, @"\d+").Value;
|
||||
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
|
||||
{
|
||||
|
|
@ -440,8 +468,16 @@ namespace TLSharp.Core.Network
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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 MigrationNeededException(int dc)
|
||||
: base ($"Your phone number is registered to a different DC: {dc}. Please migrate.")
|
||||
private const string REPORT_MESSAGE =
|
||||
" 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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
39
TLSharp.Core/Requests/PingRequest.cs
Normal file
39
TLSharp.Core/Requests/PingRequest.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -63,6 +63,7 @@
|
|||
<Compile Include="Network\TcpTransport.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Requests\AckRequest.cs" />
|
||||
<Compile Include="Requests\PingRequest.cs" />
|
||||
<Compile Include="Utils\UploadHelper.cs" />
|
||||
<Compile Include="Session.cs" />
|
||||
<Compile Include="TelegramClient.cs" />
|
||||
|
|
|
|||
28
TLSharp.Core/TLSharp.Core.nuspec
Normal file
28
TLSharp.Core/TLSharp.Core.nuspec
Normal 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>
|
||||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using TeleSharp.TL;
|
||||
using TeleSharp.TL.Account;
|
||||
using TeleSharp.TL.Auth;
|
||||
using TeleSharp.TL.Contacts;
|
||||
using TeleSharp.TL.Help;
|
||||
|
|
@ -14,6 +15,7 @@ using TLSharp.Core.MTProto.Crypto;
|
|||
using TLSharp.Core.Network;
|
||||
using TLSharp.Core.Requests;
|
||||
using TLSharp.Core.Utils;
|
||||
using TLAuthorization = TeleSharp.TL.Auth.TLAuthorization;
|
||||
|
||||
namespace TLSharp.Core
|
||||
{
|
||||
|
|
@ -29,16 +31,17 @@ namespace TLSharp.Core
|
|||
|
||||
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)
|
||||
store = new FileSessionStore();
|
||||
|
||||
TLContext.Init();
|
||||
_apiHash = apiHash;
|
||||
_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);
|
||||
_transport = new TcpTransport(_session.ServerAddress, _session.Port);
|
||||
|
|
@ -96,6 +99,9 @@ namespace TLSharp.Core
|
|||
|
||||
public async Task<bool> IsPhoneRegisteredAsync(string phoneNumber)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(phoneNumber))
|
||||
throw new ArgumentNullException(nameof(phoneNumber));
|
||||
|
||||
if (_sender == null)
|
||||
throw new InvalidOperationException("Not connected!");
|
||||
|
||||
|
|
@ -108,6 +114,9 @@ namespace TLSharp.Core
|
|||
|
||||
public async Task<string> SendCodeRequestAsync(string phoneNumber)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(phoneNumber))
|
||||
throw new ArgumentNullException(nameof(phoneNumber));
|
||||
|
||||
var completed = false;
|
||||
|
||||
TLRequestSendCode request = null;
|
||||
|
|
@ -122,7 +131,7 @@ namespace TLSharp.Core
|
|||
|
||||
completed = true;
|
||||
}
|
||||
catch (MigrationNeededException ex)
|
||||
catch (PhoneMigrationException ex)
|
||||
{
|
||||
await ReconnectToDcAsync(ex.DC);
|
||||
}
|
||||
|
|
@ -133,6 +142,15 @@ namespace TLSharp.Core
|
|||
|
||||
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 };
|
||||
await _sender.Send(request);
|
||||
await _sender.Receive(request);
|
||||
|
|
@ -152,12 +170,12 @@ namespace TLSharp.Core
|
|||
|
||||
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.Receive(methodtoExceute);
|
||||
await _sender.Send(methodToExecute);
|
||||
await _sender.Receive(methodToExecute);
|
||||
|
||||
var result = methodtoExceute.GetType().GetProperty("Response").GetValue(methodtoExceute);
|
||||
var result = methodToExecute.GetType().GetProperty("Response").GetValue(methodToExecute);
|
||||
|
||||
return (T)result;
|
||||
}
|
||||
|
|
@ -196,15 +214,15 @@ namespace TLSharp.Core
|
|||
return await SendRequestAsync<Boolean>(req);
|
||||
}
|
||||
|
||||
public async Task<TLDialogs> GetUserDialogsAsync()
|
||||
public async Task<TLAbsDialogs> GetUserDialogsAsync()
|
||||
{
|
||||
var peer = new TLInputPeerSelf();
|
||||
return await SendRequestAsync<TLDialogs>(
|
||||
return await SendRequestAsync<TLAbsDialogs>(
|
||||
new TLRequestGetDialogs() { offset_date = 0, offset_peer = peer, limit = 100 });
|
||||
}
|
||||
|
||||
public async Task<TLAbsUpdates> SendUploadedPhoto(TLAbsInputPeer peer, TLAbsInputFile file, string caption)
|
||||
{
|
||||
{
|
||||
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
|
||||
{
|
||||
random_id = Helpers.GenerateRandomLong(),
|
||||
|
|
@ -218,7 +236,7 @@ namespace TLSharp.Core
|
|||
public async Task<TLAbsUpdates> SendUploadedDocument(
|
||||
TLAbsInputPeer peer, TLAbsInputFile file, string caption, string mimeType, TLVector<TLAbsDocumentAttribute> attributes)
|
||||
{
|
||||
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
|
||||
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
|
||||
{
|
||||
random_id = Helpers.GenerateRandomLong(),
|
||||
background = false,
|
||||
|
|
@ -236,12 +254,48 @@ namespace TLSharp.Core
|
|||
|
||||
public async Task<TLFile> GetFile(TLAbsInputFileLocation location, int filePartSize)
|
||||
{
|
||||
return await SendRequestAsync<TLFile>(new TLRequestGetFile()
|
||||
TLFile result = null;
|
||||
try
|
||||
{
|
||||
location = location,
|
||||
limit = filePartSize
|
||||
});
|
||||
}
|
||||
result = await SendRequestAsync<TLFile>(new TLRequestGetFile()
|
||||
{
|
||||
location = location,
|
||||
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)
|
||||
{
|
||||
|
|
@ -256,9 +310,14 @@ namespace TLSharp.Core
|
|||
{
|
||||
public const string InfoUrl = "https://github.com/sochix/TLSharp#quick-configuration";
|
||||
|
||||
internal MissingApiConfigurationException(string invalidParamName):
|
||||
internal MissingApiConfigurationException(string invalidParamName) :
|
||||
base($"Your {invalidParamName} setting is missing. Adjust the configuration first, see {InfoUrl}")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class InvalidPhoneCodeException : Exception
|
||||
{
|
||||
internal InvalidPhoneCodeException(string msg) : base(msg) { }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ namespace TLSharp.Tests
|
|||
|
||||
private string NumberToAuthenticate { get; set; }
|
||||
|
||||
private string CodeToAuthenticate { get; set; }
|
||||
|
||||
private string NotRegisteredNumberToSignUp { get; set; }
|
||||
|
||||
private string UserNameToSendMessage { get; set; }
|
||||
|
|
@ -58,39 +60,41 @@ namespace TLSharp.Tests
|
|||
|
||||
private void GatherTestConfiguration()
|
||||
{
|
||||
string appConfigMsgWarning = "{0} not configured in app.config! Some tests may fail.";
|
||||
|
||||
ApiHash = ConfigurationManager.AppSettings[nameof(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)];
|
||||
if (string.IsNullOrEmpty(apiId))
|
||||
Debug.WriteLine("ApiId not configured in app.config! Some tests may fail.");
|
||||
Debug.WriteLine(appConfigMsgWarning, nameof(ApiId));
|
||||
else
|
||||
ApiId = int.Parse(apiId);
|
||||
|
||||
NumberToAuthenticate = ConfigurationManager.AppSettings[nameof(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)];
|
||||
if (string.IsNullOrEmpty(NotRegisteredNumberToSignUp))
|
||||
Debug.WriteLine("NotRegisteredNumberToSignUp not configured in app.config! Some tests may fail.");
|
||||
|
||||
NumberToSendMessage = ConfigurationManager.AppSettings[nameof(NumberToSendMessage)];
|
||||
if (string.IsNullOrEmpty(NumberToSendMessage))
|
||||
Debug.WriteLine("NumberToSendMessage not configured in app.config! Some tests may fail.");
|
||||
Debug.WriteLine(appConfigMsgWarning, nameof(NotRegisteredNumberToSignUp));
|
||||
|
||||
UserNameToSendMessage = ConfigurationManager.AppSettings[nameof(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)];
|
||||
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)];
|
||||
if (string.IsNullOrEmpty(NumberToAddToChat))
|
||||
Debug.WriteLine("NumberToAddToChat not configured in app.config! Some tests may fail.");
|
||||
Debug.WriteLine(appConfigMsgWarning, nameof(NumberToAddToChat));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
@ -101,9 +105,23 @@ namespace TLSharp.Tests
|
|||
await client.ConnectAsync();
|
||||
|
||||
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.IsTrue(client.IsUserAuthorized());
|
||||
|
|
@ -112,6 +130,15 @@ namespace TLSharp.Tests
|
|||
[TestMethod]
|
||||
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();
|
||||
|
||||
await client.ConnectAsync();
|
||||
|
|
@ -121,7 +148,7 @@ namespace TLSharp.Tests
|
|||
var user = result.users.lists
|
||||
.Where(x => x.GetType() == typeof(TLUser))
|
||||
.Cast<TLUser>()
|
||||
.FirstOrDefault(x => x.phone == NumberToSendMessage);
|
||||
.FirstOrDefault(x => x.phone == normalizedNumber);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
|
|
@ -131,7 +158,6 @@ namespace TLSharp.Tests
|
|||
await client.SendTypingAsync(new TLInputPeerUser() { user_id = user.id });
|
||||
Thread.Sleep(3000);
|
||||
await client.SendMessageAsync(new TLInputPeerUser() { user_id = user.id }, "TEST");
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
@ -141,7 +167,7 @@ namespace TLSharp.Tests
|
|||
|
||||
await client.ConnectAsync();
|
||||
|
||||
var dialogs = await client.GetUserDialogsAsync();
|
||||
var dialogs = (TLDialogs) await client.GetUserDialogsAsync();
|
||||
var chat = dialogs.chats.lists
|
||||
.Where(c => c.GetType() == typeof(TLChannel))
|
||||
.Cast<TLChannel>()
|
||||
|
|
@ -231,6 +257,36 @@ namespace TLSharp.Tests
|
|||
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]
|
||||
public async Task SignUpNewUser()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<add key="ApiHash" value="" />
|
||||
<add key="ApiId" value="" />
|
||||
<add key="NumberToAuthenticate" value="" />
|
||||
<add key="CodeToAuthenticate" value="" />
|
||||
<add key="NotRegisteredNumberToSignUp" value=""/>
|
||||
<add key="NumberToSendMessage" value=""/>
|
||||
<add key="UserNameToSendMessage" value=""/>
|
||||
|
|
|
|||
35
TLSharp.sln
35
TLSharp.sln
|
|
@ -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.Build.0 = Release|Any CPU
|
||||
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
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace TeleSharp.TL
|
|||
public class TLVector<T> : TLObject
|
||||
{
|
||||
[TLObject(481674261)]
|
||||
public List<T> lists = new List<T>() ;
|
||||
public List<T> lists = new List<T>();
|
||||
public override int Constructor
|
||||
{
|
||||
get
|
||||
|
|
@ -22,21 +22,21 @@ namespace TeleSharp.TL
|
|||
public override void DeserializeBody(BinaryReader br)
|
||||
{
|
||||
int count = br.ReadInt32();
|
||||
for(int i= 0;i< count;i++)
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
if (typeof(T) == typeof(int))
|
||||
{
|
||||
lists.Add((T)Convert.ChangeType(br.ReadInt32(),typeof(T)));
|
||||
lists.Add((T)Convert.ChangeType(br.ReadInt32(), typeof(T)));
|
||||
}
|
||||
else if (typeof(T)==typeof(long))
|
||||
else if (typeof(T) == typeof(long))
|
||||
{
|
||||
lists.Add((T)Convert.ChangeType(br.ReadInt64(), typeof(T)));
|
||||
}
|
||||
else if (typeof(T) ==typeof(string))
|
||||
else if (typeof(T) == typeof(string))
|
||||
{
|
||||
lists.Add((T)Convert.ChangeType(StringUtil.Deserialize(br), typeof(T)));
|
||||
}
|
||||
else if(typeof(T)==typeof(double))
|
||||
else if (typeof(T) == typeof(double))
|
||||
{
|
||||
lists.Add((T)Convert.ChangeType(br.ReadDouble(), typeof(T)));
|
||||
}
|
||||
|
|
@ -53,13 +53,38 @@ namespace TeleSharp.TL
|
|||
|
||||
public override void SerializeBody(BinaryWriter bw)
|
||||
{
|
||||
bw.Write(Constructor);
|
||||
bw.Write(Constructor);
|
||||
bw.Write(lists.Count());
|
||||
|
||||
foreach (var item in lists.Cast<TLObject>())
|
||||
{
|
||||
item.SerializeBody(bw);
|
||||
}
|
||||
foreach (var item in lists)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue