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://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://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
|
_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?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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="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" />
|
||||||
|
|
|
||||||
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.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,15 +214,15 @@ 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 });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TLAbsUpdates> SendUploadedPhoto(TLAbsInputPeer peer, TLAbsInputFile file, string caption)
|
public async Task<TLAbsUpdates> SendUploadedPhoto(TLAbsInputPeer peer, TLAbsInputFile file, string caption)
|
||||||
{
|
{
|
||||||
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
|
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
|
||||||
{
|
{
|
||||||
random_id = Helpers.GenerateRandomLong(),
|
random_id = Helpers.GenerateRandomLong(),
|
||||||
|
|
@ -218,7 +236,7 @@ namespace TLSharp.Core
|
||||||
public async Task<TLAbsUpdates> SendUploadedDocument(
|
public async Task<TLAbsUpdates> SendUploadedDocument(
|
||||||
TLAbsInputPeer peer, TLAbsInputFile file, string caption, string mimeType, TLVector<TLAbsDocumentAttribute> attributes)
|
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(),
|
random_id = Helpers.GenerateRandomLong(),
|
||||||
background = false,
|
background = false,
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
location = location,
|
result = await SendRequestAsync<TLFile>(new TLRequestGetFile()
|
||||||
limit = filePartSize
|
{
|
||||||
});
|
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)
|
private void OnUserAuthenticated(TLUser TLUser)
|
||||||
{
|
{
|
||||||
|
|
@ -256,9 +310,14 @@ namespace TLSharp.Core
|
||||||
{
|
{
|
||||||
public const string InfoUrl = "https://github.com/sochix/TLSharp#quick-configuration";
|
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}")
|
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 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()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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=""/>
|
||||||
|
|
|
||||||
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.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
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace TeleSharp.TL
|
||||||
public class TLVector<T> : TLObject
|
public class TLVector<T> : TLObject
|
||||||
{
|
{
|
||||||
[TLObject(481674261)]
|
[TLObject(481674261)]
|
||||||
public List<T> lists = new List<T>() ;
|
public List<T> lists = new List<T>();
|
||||||
public override int Constructor
|
public override int Constructor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -22,21 +22,21 @@ 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))
|
||||||
{
|
{
|
||||||
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)));
|
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)));
|
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)));
|
lists.Add((T)Convert.ChangeType(br.ReadDouble(), typeof(T)));
|
||||||
}
|
}
|
||||||
|
|
@ -53,13 +53,38 @@ namespace TeleSharp.TL
|
||||||
|
|
||||||
public override void SerializeBody(BinaryWriter bw)
|
public override void SerializeBody(BinaryWriter bw)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue