mirror of
https://github.com/sochix/TLSharp.git
synced 2025-12-06 08:02:00 +01:00
Merge branch 'master' of https://github.com/sochix/TLSharp into netstandard
This commit is contained in:
commit
b343c51723
49
README.md
49
README.md
|
|
@ -1,12 +1,13 @@
|
||||||
TLSharp
|
TLSharp
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
[](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)
|
[](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
|
||||||
|
|
||||||
|
🚩 Check out [TeleJS](https://github.com/RD17/TeleJS) - a pure JavaScript implementation of Telegram MTP protocol
|
||||||
|
|
||||||
It's a perfect fit for any developer who would like to send data directly to Telegram users or write own custom Telegram client.
|
It's a perfect fit for any developer who would like to send data directly to Telegram users or write own custom Telegram client.
|
||||||
|
|
||||||
:star2: If you :heart: library, please star it! :star2:
|
:star2: If you :heart: library, please star it! :star2:
|
||||||
|
|
@ -20,9 +21,10 @@ It's a perfect fit for any developer who would like to send data directly to Tel
|
||||||
- [First requests](#first-requests)
|
- [First requests](#first-requests)
|
||||||
- [Working with files](#working-with-files)
|
- [Working with files](#working-with-files)
|
||||||
- [Available Methods](#available-methods)
|
- [Available Methods](#available-methods)
|
||||||
- [Contributing](#contributing)
|
- [Contributors](#contributors)
|
||||||
- [FAQ](#faq)
|
- [FAQ](#faq)
|
||||||
- [Donations](#donations)
|
- [Donations](#donations)
|
||||||
|
- [Support](#support)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
# How do I add this to my project?
|
# How do I add this to my project?
|
||||||
|
|
@ -81,13 +83,13 @@ You can call any method on authenticated user. For example, let's send message t
|
||||||
var result = await client.GetContactsAsync();
|
var result = await client.GetContactsAsync();
|
||||||
|
|
||||||
//find recipient in contacts
|
//find recipient in contacts
|
||||||
var user = result.Users.lists
|
var user = result.Users
|
||||||
.Where(x => x.GetType() == typeof (TLUser))
|
.Where(x => x.GetType() == typeof (TLUser))
|
||||||
.Cast<TLUser>()
|
.Cast<TLUser>()
|
||||||
.FirstOrDefault(x => x.phone == "<recipient_phone>");
|
.FirstOrDefault(x => x.Phone == "<recipient_phone>");
|
||||||
|
|
||||||
//send message
|
//send message
|
||||||
await client.SendMessageAsync(new TLInputPeerUser() {user_id = user.id}, "OUR_MESSAGE");
|
await client.SendMessageAsync(new TLInputPeerUser() {UserId = user.Id}, "OUR_MESSAGE");
|
||||||
```
|
```
|
||||||
|
|
||||||
Full code you can see at [SendMessage test](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L87)
|
Full code you can see at [SendMessage test](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L87)
|
||||||
|
|
@ -95,16 +97,16 @@ Full code you can see at [SendMessage test](https://github.com/sochix/TLSharp/bl
|
||||||
To send message to channel you could use the following code:
|
To send message to channel you could use the following code:
|
||||||
```csharp
|
```csharp
|
||||||
//get user dialogs
|
//get user dialogs
|
||||||
var dialogs = await client.GetUserDialogsAsync();
|
var dialogs = (TLDialogsSlice) await client.GetUserDialogsAsync();
|
||||||
|
|
||||||
//find channel by title
|
//find channel by title
|
||||||
var chat = dialogs.chats.lists
|
var chat = dialogs.Chats
|
||||||
.Where(c => c.GetType() == typeof(TLChannel))
|
.Where(c => c.GetType() == typeof(TLChannel))
|
||||||
.Cast<TLChannel>()
|
.Cast<TLChannel>()
|
||||||
.FirstOrDefault(c => c.title == "<channel_title>");
|
.FirstOrDefault(c => c.Title == "<channel_title>");
|
||||||
|
|
||||||
//send message
|
//send message
|
||||||
await client.SendMessageAsync(new TLInputPeerChannel() { channel_id = chat.id, access_hash = chat.access_hash.Value }, "OUR_MESSAGE");
|
await client.SendMessageAsync(new TLInputPeerChannel() { ChannelId = chat.Id, AccessHash = chat.AccessHash.Value }, "OUR_MESSAGE");
|
||||||
```
|
```
|
||||||
Full code you can see at [SendMessageToChannel test](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L107)
|
Full code you can see at [SendMessageToChannel test](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L107)
|
||||||
## Working with files
|
## Working with files
|
||||||
|
|
@ -117,9 +119,9 @@ Telegram separate files to two categories -> big file and small file. File is Bi
|
||||||
TLSharp provides two wrappers for sending photo and document
|
TLSharp provides two wrappers for sending photo and document
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
await client.SendUploadedPhoto(new TLInputPeerUser() { user_id = user.id }, fileResult, "kitty");
|
await client.SendUploadedPhoto(new TLInputPeerUser() { UserId = user.Id }, fileResult, "kitty");
|
||||||
await client.SendUploadedDocument(
|
await client.SendUploadedDocument(
|
||||||
new TLInputPeerUser() { user_id = user.id },
|
new TLInputPeerUser() { UserId = user.Id },
|
||||||
fileResult,
|
fileResult,
|
||||||
"some zips", //caption
|
"some zips", //caption
|
||||||
"application/zip", //mime-type
|
"application/zip", //mime-type
|
||||||
|
|
@ -132,11 +134,11 @@ To download file you should call **GetFile** method
|
||||||
await client.GetFile(
|
await client.GetFile(
|
||||||
new TLInputDocumentFileLocation()
|
new TLInputDocumentFileLocation()
|
||||||
{
|
{
|
||||||
access_hash = document.access_hash,
|
AccessHash = document.AccessHash,
|
||||||
id = document.id,
|
Id = document.Id,
|
||||||
version = document.version
|
Version = document.Version
|
||||||
},
|
},
|
||||||
document.size); //size of fileChunk you want to retrieve
|
document.Size); //size of fileChunk you want to retrieve
|
||||||
```
|
```
|
||||||
|
|
||||||
Full code you can see at [DownloadFileFromContactTest](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L167)
|
Full code you can see at [DownloadFileFromContactTest](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L167)
|
||||||
|
|
@ -169,12 +171,12 @@ Don't panic. You can call any method with help of `SendRequestAsync` function. F
|
||||||
//Create request
|
//Create request
|
||||||
var req = new TLRequestSetTyping()
|
var req = new TLRequestSetTyping()
|
||||||
{
|
{
|
||||||
action = new TLSendMessageTypingAction(),
|
Action = new TLSendMessageTypingAction(),
|
||||||
peer = peer
|
Peer = new TLInputPeerUser() { UserId = user.Id }
|
||||||
};
|
};
|
||||||
|
|
||||||
//run request, and deserialize response to Boolean
|
//run request, and deserialize response to Boolean
|
||||||
return await SendRequestAsync<Boolean>(req);
|
return await client.SendRequestAsync<Boolean>(req);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Where you can find a list of requests and its params?**
|
**Where you can find a list of requests and its params?**
|
||||||
|
|
@ -211,10 +213,10 @@ It's likely [Telegram restrictions](https://core.telegram.org/api/errors#420-flo
|
||||||
|
|
||||||
#### Why does TLSharp lacks feature XXXX?
|
#### Why does TLSharp lacks feature XXXX?
|
||||||
|
|
||||||
Now TLSharp is basic realization of Telegram protocol, you can be a contributor or a sponsor to speed-up developemnt of any feature.
|
TLSharp only covers basic functionality of the Telegram protocol, you can be a contributor or a sponsor to speed-up developemnt of any more new features.
|
||||||
|
|
||||||
#### Nothing helps
|
#### Where else to ask for help?
|
||||||
Ask your question at gitter or create an issue in project bug tracker.
|
If you think you have found a bug in TLSharp, create a github issue. But if you just have questions about how to use TLSharp, use our gitter channel (https://gitter.im/TLSharp/Lobby) or our Telegram channel (https://t.me/joinchat/AgtDiBEqG1i-qPqttNFLbA).
|
||||||
|
|
||||||
**Attach following information**:
|
**Attach following information**:
|
||||||
|
|
||||||
|
|
@ -231,6 +233,11 @@ Thanks for donations! It's highly appreciated.
|
||||||
List of donators:
|
List of donators:
|
||||||
* [mtbitcoin](https://github.com/mtbitcoin)
|
* [mtbitcoin](https://github.com/mtbitcoin)
|
||||||
|
|
||||||
|
# Support
|
||||||
|
If you have troubles while using TLSharp, I can help you for an additional fee.
|
||||||
|
|
||||||
|
My pricing is **219$/hour**. I accept PayPal. To request a paid support write me at Telegram @sochix, start your message with phrase [PAID SUPPORT].
|
||||||
|
|
||||||
# Contributors
|
# Contributors
|
||||||
* [Afshin Arani](http://aarani.ir) - TLGenerator, and a lot of other usefull things
|
* [Afshin Arani](http://aarani.ir) - TLGenerator, and a lot of other usefull things
|
||||||
* [Knocte](https://github.com/knocte)
|
* [Knocte](https://github.com/knocte)
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ namespace TLSharp.Core.Network
|
||||||
{
|
{
|
||||||
//private ulong sessionId = GenerateRandomUlong();
|
//private ulong sessionId = GenerateRandomUlong();
|
||||||
|
|
||||||
private TcpTransport _transport;
|
private readonly TcpTransport _transport;
|
||||||
private Session _session;
|
private readonly Session _session;
|
||||||
|
|
||||||
public List<ulong> needConfirmation = new List<ulong>();
|
public readonly List<ulong> needConfirmation = new List<ulong>();
|
||||||
|
|
||||||
public MtProtoSender(TcpTransport transport, Session session)
|
public MtProtoSender(TcpTransport transport, Session session)
|
||||||
{
|
{
|
||||||
|
|
@ -29,11 +29,6 @@ namespace TLSharp.Core.Network
|
||||||
_session = session;
|
_session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeTransport(TcpTransport transport)
|
|
||||||
{
|
|
||||||
_transport = transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GenerateSequence(bool confirmed)
|
private int GenerateSequence(bool confirmed)
|
||||||
{
|
{
|
||||||
return confirmed ? _session.Sequence++ * 2 + 1 : _session.Sequence * 2;
|
return confirmed ? _session.Sequence++ * 2 + 1 : _session.Sequence * 2;
|
||||||
|
|
|
||||||
|
|
@ -84,21 +84,21 @@ namespace TLSharp.Core.Network
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TcpMessage(seq, body);
|
return new TcpMessage(seq, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsConnected
|
public bool IsConnected
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this._tcpClient.Connected;
|
return this._tcpClient.Connected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_tcpClient.Connected)
|
if (_tcpClient.Connected)
|
||||||
_tcpClient.Close();
|
_tcpClient.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ namespace TLSharp.Core
|
||||||
if (store == null)
|
if (store == null)
|
||||||
store = new FileSessionStore();
|
store = new FileSessionStore();
|
||||||
|
|
||||||
TLContext.Init();
|
|
||||||
_apiHash = apiHash;
|
_apiHash = apiHash;
|
||||||
_apiId = apiId;
|
_apiId = apiId;
|
||||||
_handler = handler;
|
_handler = handler;
|
||||||
|
|
@ -50,7 +49,7 @@ namespace TLSharp.Core
|
||||||
_transport = new TcpTransport(_session.ServerAddress, _session.Port, _handler);
|
_transport = new TcpTransport(_session.ServerAddress, _session.Port, _handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> ConnectAsync(bool reconnect = false)
|
public async Task ConnectAsync(bool reconnect = false)
|
||||||
{
|
{
|
||||||
if (_session.AuthKey == null || reconnect)
|
if (_session.AuthKey == null || reconnect)
|
||||||
{
|
{
|
||||||
|
|
@ -77,21 +76,19 @@ namespace TLSharp.Core
|
||||||
await _sender.Receive(invokewithLayer);
|
await _sender.Receive(invokewithLayer);
|
||||||
|
|
||||||
dcOptions = ((TLConfig)invokewithLayer.Response).DcOptions.ToList();
|
dcOptions = ((TLConfig)invokewithLayer.Response).DcOptions.ToList();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ReconnectToDcAsync(int dcId)
|
private async Task ReconnectToDcAsync(int dcId)
|
||||||
{
|
{
|
||||||
if (dcOptions == null || !dcOptions.Any())
|
if (dcOptions == null || !dcOptions.Any())
|
||||||
throw new InvalidOperationException($"Can't reconnect. Establish initial connection first.");
|
throw new InvalidOperationException($"Can't reconnect. Establish initial connection first.");
|
||||||
|
|
||||||
TLExportedAuthorization exported = null;
|
TLExportedAuthorization exported = null;
|
||||||
if (_session.TLUser != null)
|
if (_session.TLUser != null)
|
||||||
{
|
{
|
||||||
TLRequestExportAuthorization exportAuthorization = new TLRequestExportAuthorization() { DcId = dcId };
|
TLRequestExportAuthorization exportAuthorization = new TLRequestExportAuthorization() { DcId = dcId };
|
||||||
exported = await SendRequestAsync<TLExportedAuthorization>(exportAuthorization);
|
exported = await SendRequestAsync<TLExportedAuthorization>(exportAuthorization);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dc = dcOptions.First(d => d.Id == dcId);
|
var dc = dcOptions.First(d => d.Id == dcId);
|
||||||
|
|
||||||
|
|
@ -99,18 +96,21 @@ namespace TLSharp.Core
|
||||||
_session.ServerAddress = dc.IpAddress;
|
_session.ServerAddress = dc.IpAddress;
|
||||||
_session.Port = dc.Port;
|
_session.Port = dc.Port;
|
||||||
|
|
||||||
await ConnectAsync(true);
|
await ConnectAsync(true);
|
||||||
|
|
||||||
if (_session.TLUser != null)
|
if (_session.TLUser != null)
|
||||||
{
|
{
|
||||||
TLRequestImportAuthorization importAuthorization = new TLRequestImportAuthorization() { Id = exported.Id, Bytes = exported.Bytes };
|
TLRequestImportAuthorization importAuthorization = new TLRequestImportAuthorization() { Id = exported.Id, Bytes = exported.Bytes };
|
||||||
var imported = await SendRequestAsync<TLAuthorization>(importAuthorization);
|
var imported = await SendRequestAsync<TLAuthorization>(importAuthorization);
|
||||||
OnUserAuthenticated(((TLUser)imported.User));
|
OnUserAuthenticated(((TLUser)imported.User));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RequestWithDcMigration(TLMethod request)
|
private async Task RequestWithDcMigration(TLMethod request)
|
||||||
{
|
{
|
||||||
|
if (_sender == null)
|
||||||
|
throw new InvalidOperationException("Not connected!");
|
||||||
|
|
||||||
var completed = false;
|
var completed = false;
|
||||||
while(!completed)
|
while(!completed)
|
||||||
{
|
{
|
||||||
|
|
@ -126,7 +126,7 @@ namespace TLSharp.Core
|
||||||
// prepare the request for another try
|
// prepare the request for another try
|
||||||
request.ConfirmReceived = false;
|
request.ConfirmReceived = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsUserAuthorized()
|
public bool IsUserAuthorized()
|
||||||
|
|
@ -139,9 +139,6 @@ namespace TLSharp.Core
|
||||||
if (String.IsNullOrWhiteSpace(phoneNumber))
|
if (String.IsNullOrWhiteSpace(phoneNumber))
|
||||||
throw new ArgumentNullException(nameof(phoneNumber));
|
throw new ArgumentNullException(nameof(phoneNumber));
|
||||||
|
|
||||||
if (_sender == null)
|
|
||||||
throw new InvalidOperationException("Not connected!");
|
|
||||||
|
|
||||||
var authCheckPhoneRequest = new TLRequestCheckPhone() { PhoneNumber = phoneNumber };
|
var authCheckPhoneRequest = new TLRequestCheckPhone() { PhoneNumber = phoneNumber };
|
||||||
|
|
||||||
await RequestWithDcMigration(authCheckPhoneRequest);
|
await RequestWithDcMigration(authCheckPhoneRequest);
|
||||||
|
|
@ -172,8 +169,8 @@ namespace TLSharp.Core
|
||||||
if (String.IsNullOrWhiteSpace(code))
|
if (String.IsNullOrWhiteSpace(code))
|
||||||
throw new ArgumentNullException(nameof(code));
|
throw new ArgumentNullException(nameof(code));
|
||||||
|
|
||||||
var request = new TLRequestSignIn() { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = code };
|
var request = new TLRequestSignIn() { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = code };
|
||||||
|
|
||||||
await RequestWithDcMigration(request);
|
await RequestWithDcMigration(request);
|
||||||
|
|
||||||
OnUserAuthenticated(((TLUser)request.Response.User));
|
OnUserAuthenticated(((TLUser)request.Response.User));
|
||||||
|
|
@ -314,21 +311,21 @@ namespace TLSharp.Core
|
||||||
public async Task SendPingAsync()
|
public async Task SendPingAsync()
|
||||||
{
|
{
|
||||||
await _sender.SendPingAsync();
|
await _sender.SendPingAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TLAbsMessages> GetHistoryAsync(TLAbsInputPeer peer, int offset, int max_id, int limit)
|
public async Task<TLAbsMessages> GetHistoryAsync(TLAbsInputPeer peer, int offset, int max_id, int limit)
|
||||||
{
|
{
|
||||||
if (!IsUserAuthorized())
|
if (!IsUserAuthorized())
|
||||||
throw new InvalidOperationException("Authorize user first!");
|
throw new InvalidOperationException("Authorize user first!");
|
||||||
|
|
||||||
var req = new TLRequestGetHistory()
|
var req = new TLRequestGetHistory()
|
||||||
{
|
{
|
||||||
Peer = peer,
|
Peer = peer,
|
||||||
AddOffset = offset,
|
AddOffset = offset,
|
||||||
MaxId = max_id,
|
MaxId = max_id,
|
||||||
Limit = limit
|
Limit = limit
|
||||||
};
|
};
|
||||||
return await SendRequestAsync<TLAbsMessages>(req);
|
return await SendRequestAsync<TLAbsMessages>(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -354,18 +351,18 @@ namespace TLSharp.Core
|
||||||
_session.SessionExpires = int.MaxValue;
|
_session.SessionExpires = int.MaxValue;
|
||||||
|
|
||||||
_session.Save();
|
_session.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsConnected
|
public bool IsConnected
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_transport == null)
|
if (_transport == null)
|
||||||
return false;
|
return false;
|
||||||
return _transport.IsConnected;
|
return _transport.IsConnected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_transport != null)
|
if (_transport != null)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace TeleSharp.TL
|
||||||
{
|
{
|
||||||
private static Dictionary<int, Type> Types;
|
private static Dictionary<int, Type> Types;
|
||||||
|
|
||||||
public static void Init()
|
static TLContext()
|
||||||
{
|
{
|
||||||
Types = new Dictionary<int, Type>();
|
Types = new Dictionary<int, Type>();
|
||||||
Types = (from t in Assembly.GetExecutingAssembly().GetTypes()
|
Types = (from t in Assembly.GetExecutingAssembly().GetTypes()
|
||||||
|
|
@ -22,6 +22,7 @@ namespace TeleSharp.TL
|
||||||
select t).ToDictionary(x => ((TLObjectAttribute)x.GetCustomAttribute(typeof(TLObjectAttribute))).Constructor, x => x);
|
select t).ToDictionary(x => ((TLObjectAttribute)x.GetCustomAttribute(typeof(TLObjectAttribute))).Constructor, x => x);
|
||||||
Types[481674261] = typeof(TLVector<>);
|
Types[481674261] = typeof(TLVector<>);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type getType(int Constructor)
|
public static Type getType(int Constructor)
|
||||||
{
|
{
|
||||||
return Types[Constructor];
|
return Types[Constructor];
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace TeleSharp.TL
|
||||||
Serialize(bw);
|
Serialize(bw);
|
||||||
bw.Close();
|
bw.Close();
|
||||||
m.Close();
|
m.Close();
|
||||||
return m.GetBuffer();
|
return m.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Serialize(BinaryWriter writer)
|
public void Serialize(BinaryWriter writer)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue