Merge remote-tracking branch 'refs/remotes/origin/master' into pr/258

# Conflicts:
#	TLSharp.Tests/TLSharpTests.cs
This commit is contained in:
Ilya P 2016-10-23 14:09:16 +03:00
commit a53800ba16
5 changed files with 330 additions and 135 deletions

View file

@ -20,6 +20,7 @@ It's a perfect fit for any developer who would like to send data directly to Tel
- [Starter Guide](#starter-guide)
- [Quick configuration](#quick-configuration)
- [First requests](#first-requests)
- [Working with files](#working-with-files)
- [Available Methods](#available-methods)
- [Contributing](#contributing)
- [FAQ](#faq)
@ -104,8 +105,41 @@ To send message to channel you could use the following code:
await client.SendMessageAsync(new TLInputPeerChannel() { channel_id = chat.id, access_hash = chat.access_hash.Value }, "OUR_MESSAGE");
```
Full code you can see at [SendMessageToChannel test](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L107)
## Working with files
Telegram separate files to two categories -> big file and small file. File is Big if its size more than 10 Mb. TLSharp tries to hide this complexity from you, thats why we provide one method to upload files **UploadFile**.
## Available Methods
```csharp
var fileResult = await client.UploadFile("cat.jpg", new StreamReader("data/cat.jpg"));
```
TLSharp provides two wrappers for sending photo and document
```csharp
await client.SendUploadedPhoto(new TLInputPeerUser() { user_id = user.id }, fileResult, "kitty");
await client.SendUploadedDocument(
new TLInputPeerUser() { user_id = user.id },
fileResult,
"some zips", //caption
"application/zip", //mime-type
new TLVector<TLAbsDocumentAttribute>()); //document attributes, such as file name
```
Full code you can see at [SendPhotoToContactTest](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L125) and [SendBigFileToContactTest](https://github.com/sochix/TLSharp/blob/master/TLSharp.Tests/TLSharpTests.cs#L143)
To download file you should call **GetFile** method
```csharp
await client.GetFile(
new TLInputDocumentFileLocation()
{
access_hash = document.access_hash,
id = document.id,
version = document.version
},
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)
# Available Methods
For your convenience TLSharp have wrappers for several Telegram API methods. You could add your own, see details below.
@ -117,6 +151,10 @@ For your convenience TLSharp have wrappers for several Telegram API methods. You
1. SendMessageAsync
1. SendTypingAsync
1. GetUserDialogsAsync
1. SendUploadedPhoto
1. SendUploadedDocument
1. GetFile
1. UploadFile
**What if you can't find needed method at the list?**
@ -140,18 +178,19 @@ Don't panic. You can call any method with help of `SendRequestAsync` function. F
The only way is [Telegram API docs](https://core.telegram.org/methods). Yes, it's outdated. But there is no other source.
Latest scheme in JSON format you can find [here](https://gist.github.com/aarani/b22b7cda024973dff68e1672794b0298)
## Contributing
# Contributing
Contributing is highly appreciated!
### What things can I Implement (Project Roadmap)?
## What things can I Implement (Project Roadmap)?
#### Release 1.0.0
### Release 1.0.0
* [DONE] Add PHONE_MIGRATE handling
* Add FILE_MIGRATE handling
* Add Updates handling
* Add NuGet package
* [WIP] Add wrappers for media uploading
* [DONE] Add wrappers for media uploading and downloading
* Store user session as JSON
# FAQ

View file

@ -7,112 +7,130 @@ using System.Text;
using System.Threading.Tasks;
using TeleSharp.TL;
using TeleSharp.TL.Upload;
using TLSharp.Core.Utils;
namespace TLSharp.Core.Requests
{
public class UploadHelper
public static class UploadHelper
{
public static async Task<TLAbsInputFile> Uploader(string name,StreamReader reader,TelegramClient client)
private static string GetFileHash(byte[] data)
{
if (reader.BaseStream.Length < 10 * 1024 * 1024)
return await SmallFileUpload(name, reader, client);
else
return await BigFileUpload(name, reader, client);
string md5_checksum;
using (var md5 = MD5.Create())
{
var hash = md5.ComputeHash(data);
var hashResult = new StringBuilder(hash.Length * 2);
foreach (byte t in hash)
hashResult.Append(t.ToString("x2"));
md5_checksum = hashResult.ToString();
}
private static async Task<TLInputFile> SmallFileUpload(string name, StreamReader reader, TelegramClient client)
return md5_checksum;
}
public static async Task<TLAbsInputFile> UploadFile(this TelegramClient client, string name, StreamReader reader)
{
const long tenMb = 10 * 1024 * 1024;
return await UploadFile(name, reader, client, reader.BaseStream.Length >= tenMb);
}
private static byte[] GetFile(StreamReader reader)
{
var file = new byte[reader.BaseStream.Length];
using (reader)
{
reader.BaseStream.Read(file, 0, (int)reader.BaseStream.Length);
string hash;
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
hash = Convert.ToBase64String(md5.ComputeHash(file));
}
reader = null;
var stream = new MemoryStream(file);
Queue<byte[]> parts = new Queue<byte[]>();
while (!(stream.Position == stream.Length))
return file;
}
private static Queue<byte[]> GetFileParts(byte[] file)
{
if ((stream.Length - stream.Position) > 512 *1024)
var fileParts = new Queue<byte[]>();
const int maxFilePart = 512 * 1024;
using (var stream = new MemoryStream(file))
{
byte[] temp = new byte[512];
stream.Read(temp, 0, 512 * 1024);
parts.Enqueue(temp);
while (stream.Position != stream.Length)
{
if ((stream.Length - stream.Position) > maxFilePart)
{
var temp = new byte[maxFilePart];
stream.Read(temp, 0, maxFilePart);
fileParts.Enqueue(temp);
}
else
{
byte[] temp = new byte[512];
stream.Read(temp, 0, (int)(stream.Length - stream.Position));
parts.Enqueue(temp);
var length = stream.Length - stream.Position;
var temp = new byte[length];
stream.Read(temp, 0, (int)(length));
fileParts.Enqueue(temp);
}
}
stream = null;
int partnumber = 0;
long file_id = BitConverter.ToInt64(RandomByteArray(8), 0);
while (parts.Count != 0)
{
var part = parts.Dequeue();
TLRequestSaveFilePart save = new TLRequestSaveFilePart();
save.file_id = file_id;
save.file_part = partnumber;
save.bytes = part;
await client.SendRequestAsync<bool>(save);
partnumber++;
}
TLInputFile returnFile = new TLInputFile();
returnFile.id = file_id;
returnFile.name = name;
returnFile.parts = parts.Count;
returnFile.md5_checksum = hash;
return returnFile;
return fileParts;
}
private static async Task<TLInputFileBig> BigFileUpload(string name, StreamReader reader, TelegramClient client)
private static async Task<TLAbsInputFile> UploadFile(string name, StreamReader reader,
TelegramClient client, bool isBigFileUpload)
{
var file = new byte[reader.BaseStream.Length];
reader.BaseStream.Read(file, 0, (int)reader.BaseStream.Length);
reader = null;
var stream = new MemoryStream(file);
Queue<byte[]> parts = new Queue<byte[]>();
while (!(stream.Position == stream.Length))
var file = GetFile(reader);
var fileParts = GetFileParts(file);
int partNumber = 0;
int partsCount = fileParts.Count;
long file_id = BitConverter.ToInt64(Helpers.GenerateRandomBytes(8), 0);
while (fileParts.Count != 0)
{
if ((stream.Length - stream.Position) > 512 * 1024)
var part = fileParts.Dequeue();
if (isBigFileUpload)
{
byte[] temp = new byte[512];
stream.Read(temp, 0, 512 * 1024);
parts.Enqueue(temp);
await client.SendRequestAsync<bool>(new TLRequestSaveBigFilePart
{
file_id = file_id,
file_part = partNumber,
bytes = part,
file_total_parts = partsCount
});
}
else
{
byte[] temp = new byte[512];
stream.Read(temp, 0, (int)(stream.Length - stream.Position));
parts.Enqueue(temp);
}
}
stream = null;
int partnumber = 0;
long file_id = BitConverter.ToInt64(RandomByteArray(8), 0);
while (parts.Count != 0)
await client.SendRequestAsync<bool>(new TLRequestSaveFilePart
{
var part = parts.Dequeue();
TLRequestSaveBigFilePart save = new TLRequestSaveBigFilePart();
save.file_id = file_id;
save.file_part = partnumber;
save.bytes = part;
save.file_total_parts = parts.Count;
await client.SendRequestAsync<bool>(save);
partnumber++;
file_id = file_id,
file_part = partNumber,
bytes = part
});
}
TLInputFileBig returnFile = new TLInputFileBig();
returnFile.id = file_id;
returnFile.name = name;
returnFile.parts = parts.Count;
return returnFile;
partNumber++;
}
private static byte[] RandomByteArray(int count)
if (isBigFileUpload)
{
var temp = new byte[count];
Random random = new Random();
random.NextBytes(temp);
return temp;
return new TLInputFileBig
{
id = file_id,
name = name,
parts = partsCount
};
}
else
{
return new TLInputFile
{
id = file_id,
name = name,
parts = partsCount,
md5_checksum = GetFileHash(file)
};
}
}
}
}

View file

@ -2,14 +2,18 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using TeleSharp.TL;
using TeleSharp.TL.Auth;
using TeleSharp.TL.Contacts;
using TeleSharp.TL.Help;
using TeleSharp.TL.Messages;
using TeleSharp.TL.Upload;
using TLSharp.Core.Auth;
using TLSharp.Core.MTProto.Crypto;
using TLSharp.Core.Network;
using TLSharp.Core.Requests;
using TLSharp.Core.Utils;
namespace TLSharp.Core
{
@ -53,7 +57,15 @@ namespace TLSharp.Core
//set-up layer
var config = new TLRequestGetConfig();
var request = new TLRequestInitConnection() { api_id = _apiId, app_version = "1.0.0", device_model = "PC", lang_code = "en", query = config, system_version = "Win 10.0" };
var request = new TLRequestInitConnection()
{
api_id = _apiId,
app_version = "1.0.0",
device_model = "PC",
lang_code = "en",
query = config,
system_version = "Win 10.0"
};
var invokewithLayer = new TLRequestInvokeWithLayer() { layer = 57, query = request };
await _sender.Send(invokewithLayer);
await _sender.Receive(invokewithLayer);
@ -165,14 +177,12 @@ namespace TLSharp.Core
if (!IsUserAuthorized())
throw new InvalidOperationException("Authorize user first!");
long uniqueId = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds);
return await SendRequestAsync<TLAbsUpdates>(
new TLRequestSendMessage()
{
peer = peer,
message = message,
random_id = uniqueId
random_id = Helpers.GenerateRandomLong()
});
}
@ -193,6 +203,46 @@ namespace TLSharp.Core
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(),
background = false,
clear_draft = false,
media = new TLInputMediaUploadedPhoto() { file = file, caption = caption },
peer = peer
});
}
public async Task<TLAbsUpdates> SendUploadedDocument(
TLAbsInputPeer peer, TLAbsInputFile file, string caption, string mimeType, TLVector<TLAbsDocumentAttribute> attributes)
{
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
{
random_id = Helpers.GenerateRandomLong(),
background = false,
clear_draft = false,
media = new TLInputMediaUploadedDocument()
{
file = file,
caption = caption,
mime_type = mimeType,
attributes = attributes
},
peer = peer
});
}
public async Task<TLFile> GetFile(TLAbsInputFileLocation location, int filePartSize)
{
return await SendRequestAsync<TLFile>(new TLRequestGetFile()
{
location = location,
limit = filePartSize
});
}
private void OnUserAuthenticated(TLUser TLUser)
{
_session.TLUser = TLUser;

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -68,6 +68,11 @@
<Name>TLSharp.Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="data\cat.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>

View file

@ -8,7 +8,10 @@ using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TeleSharp.TL;
using TeleSharp.TL.Upload;
using TLSharp.Core;
using TLSharp.Core.Requests;
using TLSharp.Core.Utils;
namespace TLSharp.Tests
{
@ -96,12 +99,12 @@ namespace TLSharp.Tests
var result = await client.GetContactsAsync();
var user = result.users.lists
.Where(x => x.GetType() == typeof (TLUser))
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.phone == NumberToSendMessage);
await client.SendTypingAsync(new TLInputPeerUser() {user_id = user.id});
await client.SendTypingAsync(new TLInputPeerUser() { user_id = user.id });
Thread.Sleep(3000);
await client.SendMessageAsync(new TLInputPeerUser() {user_id = user.id}, "TEST");
await client.SendMessageAsync(new TLInputPeerUser() { user_id = user.id }, "TEST");
}
@ -121,6 +124,87 @@ namespace TLSharp.Tests
await client.SendMessageAsync(new TLInputPeerChannel() { channel_id = chat.id, access_hash = chat.access_hash.Value }, "TEST MSG");
}
[TestMethod]
public async Task SendPhotoToContactTest()
{
var client = new TelegramClient(apiId, apiHash);
await client.ConnectAsync();
var result = await client.GetContactsAsync();
var user = result.users.lists
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.phone == NumberToSendMessage);
var fileResult = (TLInputFile)await client.UploadFile("cat.jpg", new StreamReader("data/cat.jpg"));
await client.SendUploadedPhoto(new TLInputPeerUser() { user_id = user.id }, fileResult, "kitty");
}
[TestMethod]
public async Task SendBigFileToContactTest()
{
var client = new TelegramClient(apiId, apiHash);
await client.ConnectAsync();
var result = await client.GetContactsAsync();
var user = result.users.lists
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.phone == NumberToSendMessage);
var fileResult = (TLInputFileBig)await client.UploadFile("some.zip", new StreamReader("<some big file path>"));
await client.SendUploadedDocument(
new TLInputPeerUser() { user_id = user.id },
fileResult,
"some zips",
"application/zip",
new TLVector<TLAbsDocumentAttribute>());
}
[TestMethod]
public async Task DownloadFileFromContactTest()
{
var client = new TelegramClient(apiId, apiHash);
await client.ConnectAsync();
var result = await client.GetContactsAsync();
var user = result.users.lists
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.phone == NumberToSendMessage);
var inputPeer = new TLInputPeerUser() { user_id = user.id };
var res = await client.SendRequestAsync<TLMessagesSlice>(new TLRequestGetHistory() { peer = inputPeer });
var document = res.messages.lists
.Where(m => m.GetType() == typeof(TLMessage))
.Cast<TLMessage>()
.Where(m => m.media != null && m.media.GetType() == typeof(TLMessageMediaDocument))
.Select(m => m.media)
.Cast<TLMessageMediaDocument>()
.Where(md => md.document.GetType() == typeof(TLDocument))
.Select(md => md.document)
.Cast<TLDocument>()
.First();
var resFile = await client.GetFile(
new TLInputDocumentFileLocation()
{
access_hash = document.access_hash,
id = document.id,
version = document.version
},
document.size);
Assert.IsTrue(resFile.bytes.Length > 0);
}
[TestMethod]
public async Task SignUpNewUser()
{
@ -147,6 +231,5 @@ namespace TLSharp.Tests
var result = await client.IsPhoneRegisteredAsync(NumberToAuthenticate);
Assert.IsTrue(result);
}
}
}