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)
[![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
@ -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?

View file

@ -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)
{
}
}
}

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="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" />

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.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) { }
}
}

View file

@ -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()
{

View file

@ -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=""/>

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.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

View file

@ -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);
}
}
}
}
}