diff options
Diffstat (limited to 'libs/tdlib/td/example/csharp')
-rw-r--r-- | libs/tdlib/td/example/csharp/.gitignore | 5 | ||||
-rw-r--r-- | libs/tdlib/td/example/csharp/README.md | 32 | ||||
-rw-r--r-- | libs/tdlib/td/example/csharp/TdExample.cs | 270 | ||||
-rw-r--r-- | libs/tdlib/td/example/csharp/TdExample.csproj | 85 |
4 files changed, 392 insertions, 0 deletions
diff --git a/libs/tdlib/td/example/csharp/.gitignore b/libs/tdlib/td/example/csharp/.gitignore new file mode 100644 index 0000000000..5266ecccc9 --- /dev/null +++ b/libs/tdlib/td/example/csharp/.gitignore @@ -0,0 +1,5 @@ +.vs/ +bin/ +obj/ +project.lock.json +TdExample.csproj.user diff --git a/libs/tdlib/td/example/csharp/README.md b/libs/tdlib/td/example/csharp/README.md new file mode 100644 index 0000000000..2faa15e12e --- /dev/null +++ b/libs/tdlib/td/example/csharp/README.md @@ -0,0 +1,32 @@ +# TDLib C# example + +This is an example of building TDLib with `C++/CLI` support and an example of TDLib usage from C#. + +## Building TDLib + +* Download and install Microsoft Visual Studio 2015 or later. +* Download and install [CMake](https://cmake.org/download/). +* Install [vcpkg](https://github.com/Microsoft/vcpkg#quick-start) or update it to the latest version using `vcpkg update` and following received instructions. +* Install `zlib` and `openssl` for using `vcpkg`: +``` +C:\src\vcpkg> .\vcpkg.exe install openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows +``` +* (Optional. For XML documentation generation.) Download [PHP](https://windows.php.net/download#php-7.2). Add the path to php.exe to the PATH environment variable. +* Download and install [gperf](https://sourceforge.net/projects/gnuwin32/files/gperf/3.0.1/). Add the path to gperf.exe to the PATH environment variable. +* Build `TDLib` with CMake enabling `.NET` support and specifying correct path to `vcpkg` toolchain file: +``` +cd <path to TDLib sources>/example/csharp +mkdir build +cd build +cmake -DTD_ENABLE_DOTNET=ON -DCMAKE_TOOLCHAIN_FILE=C:\src\vcpkg\scripts\buildsystems\vcpkg.cmake ../../.. +cmake --build . --config Release +cmake --build . --config Debug +``` + +## Example of usage + +After `TDLib` is built you can open and run TdExample project. +It contains a simple console C# application with implementation of authorization and message sending. +Just open it with Visual Studio 2015 or 2017 and run. + +Also see TdExample.csproj for example of including TDLib in C# project with all native shared library dependencies. diff --git a/libs/tdlib/td/example/csharp/TdExample.cs b/libs/tdlib/td/example/csharp/TdExample.cs new file mode 100644 index 0000000000..be98e1a758 --- /dev/null +++ b/libs/tdlib/td/example/csharp/TdExample.cs @@ -0,0 +1,270 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using Td = Telegram.Td; +using TdApi = Telegram.Td.Api; + +using System; +using System.Threading; + +namespace TdExample +{ + /// <summary> + /// Example class for TDLib usage from C#. + /// </summary> + class Example + { + private static Td.Client _client = null; + private readonly static Td.ClientResultHandler _defaultHandler = new DefaultHandler(); + + private static TdApi.AuthorizationState _authorizationState = null; + private static volatile bool _haveAuthorization = false; + private static volatile bool _quiting = false; + + private static volatile AutoResetEvent _gotAuthorization = new AutoResetEvent(false); + + private static readonly string _newLine = Environment.NewLine; + private static readonly string _commandsLine = "Enter command (gc <chatId> - GetChat, me - GetMe, sm <chatId> <message> - SendMessage, lo - LogOut, q - Quit): "; + private static volatile string _currentPrompt = null; + + private static Td.Client CreateTdClient() + { + Td.Client result = Td.Client.Create(new UpdatesHandler()); + new Thread(() => + { + Thread.CurrentThread.IsBackground = true; + result.Run(); + }).Start(); + return result; + } + + private static void Print(string str) + { + if (_currentPrompt != null) + { + Console.WriteLine(); + } + Console.WriteLine(str); + if (_currentPrompt != null) + { + Console.Write(_currentPrompt); + } + } + + private static string ReadLine(string str) + { + Console.Write(str); + _currentPrompt = str; + var result = Console.ReadLine(); + _currentPrompt = null; + return result; + } + + private static void OnAuthorizationStateUpdated(TdApi.AuthorizationState authorizationState) + { + if (authorizationState != null) + { + _authorizationState = authorizationState; + } + if (_authorizationState is TdApi.AuthorizationStateWaitTdlibParameters) + { + TdApi.TdlibParameters parameters = new TdApi.TdlibParameters(); + parameters.DatabaseDirectory = "tdlib"; + parameters.UseMessageDatabase = true; + parameters.UseSecretChats = true; + parameters.ApiId = 94575; + parameters.ApiHash = "a3406de8d171bb422bb6ddf3bbd800e2"; + parameters.SystemLanguageCode = "en"; + parameters.DeviceModel = "Desktop"; + parameters.SystemVersion = "Unknown"; + parameters.ApplicationVersion = "1.0"; + parameters.EnableStorageOptimizer = true; + + _client.Send(new TdApi.SetTdlibParameters(parameters), new AuthorizationRequestHandler()); + } + else if (_authorizationState is TdApi.AuthorizationStateWaitEncryptionKey) + { + _client.Send(new TdApi.CheckDatabaseEncryptionKey(), new AuthorizationRequestHandler()); + } + else if (_authorizationState is TdApi.AuthorizationStateWaitPhoneNumber) + { + string phoneNumber = ReadLine("Please enter phone number: "); + _client.Send(new TdApi.SetAuthenticationPhoneNumber(phoneNumber, false, false), new AuthorizationRequestHandler()); + } + else if (_authorizationState is TdApi.AuthorizationStateWaitCode) + { + string code = ReadLine("Please enter authentication code: "); + _client.Send(new TdApi.CheckAuthenticationCode(code, "", ""), new AuthorizationRequestHandler()); + } + else if (_authorizationState is TdApi.AuthorizationStateWaitPassword) + { + string password = ReadLine("Please enter password: "); + _client.Send(new TdApi.CheckAuthenticationPassword(password), new AuthorizationRequestHandler()); + } + else if (_authorizationState is TdApi.AuthorizationStateReady) + { + _haveAuthorization = true; + _gotAuthorization.Set(); + } + else if (_authorizationState is TdApi.AuthorizationStateLoggingOut) + { + _haveAuthorization = false; + Print("Logging out"); + } + else if (_authorizationState is TdApi.AuthorizationStateClosing) + { + _haveAuthorization = false; + Print("Closing"); + } + else if (_authorizationState is TdApi.AuthorizationStateClosed) + { + Print("Closed"); + if (!_quiting) + { + _client = CreateTdClient(); // recreate _client after previous has closed + } + } + else + { + Print("Unsupported authorization state:" + _newLine + _authorizationState); + } + } + + private static long GetChatId(string arg) + { + long chatId = 0; + try + { + chatId = Convert.ToInt64(arg); + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + return chatId; + } + + private static void GetCommand() + { + string command = ReadLine(_commandsLine); + string[] commands = command.Split(new char[] { ' ' }, 2); + try + { + switch (commands[0]) + { + case "gc": + _client.Send(new TdApi.GetChat(GetChatId(commands[1])), _defaultHandler); + break; + case "me": + _client.Send(new TdApi.GetMe(), _defaultHandler); + break; + case "sm": + string[] args = commands[1].Split(new char[] { ' ' }, 2); + sendMessage(GetChatId(args[0]), args[1]); + break; + case "lo": + _haveAuthorization = false; + _client.Send(new TdApi.LogOut(), _defaultHandler); + break; + case "q": + _quiting = true; + _haveAuthorization = false; + _client.Send(new TdApi.Close(), _defaultHandler); + break; + default: + Print("Unsupported command: " + command); + break; + } + } + catch (IndexOutOfRangeException) + { + Print("Not enough arguments"); + } + } + + private static void sendMessage(long chatId, string message) + { + // initialize reply markup just for testing + TdApi.InlineKeyboardButton[] row = { new TdApi.InlineKeyboardButton("https://telegram.org?1", new TdApi.InlineKeyboardButtonTypeUrl()), new TdApi.InlineKeyboardButton("https://telegram.org?2", new TdApi.InlineKeyboardButtonTypeUrl()), new TdApi.InlineKeyboardButton("https://telegram.org?3", new TdApi.InlineKeyboardButtonTypeUrl()) }; + TdApi.ReplyMarkup replyMarkup = new TdApi.ReplyMarkupInlineKeyboard(new TdApi.InlineKeyboardButton[][] { row, row, row }); + + TdApi.InputMessageContent content = new TdApi.InputMessageText(new TdApi.FormattedText(message, null), false, true); + _client.Send(new TdApi.SendMessage(chatId, 0, false, false, replyMarkup, content), _defaultHandler); + } + + static void Main() + { + // disable TDLib log + Td.Log.SetVerbosityLevel(0); + if (!Td.Log.SetFilePath("tdlib.log")) + { + throw new System.IO.IOException("Write access to the current directory is required"); + } + + // create Td.Client + _client = CreateTdClient(); + + // test Client.Execute + _defaultHandler.OnResult(_client.Execute(new TdApi.GetTextEntities("@telegram /test_command https://telegram.org telegram.me @gif @test"))); + + // main loop + while (!_quiting) + { + // await authorization + _gotAuthorization.Reset(); + _gotAuthorization.WaitOne(); + + _client.Send(new TdApi.GetChats(Int64.MaxValue, 0, 100), _defaultHandler); // preload chat list + while (_haveAuthorization) + { + GetCommand(); + } + } + } + + private class DefaultHandler : Td.ClientResultHandler + { + void Td.ClientResultHandler.OnResult(TdApi.BaseObject @object) + { + Print(@object.ToString()); + } + } + + private class UpdatesHandler : Td.ClientResultHandler + { + void Td.ClientResultHandler.OnResult(TdApi.BaseObject @object) + { + if (@object is TdApi.UpdateAuthorizationState) + { + OnAuthorizationStateUpdated((@object as TdApi.UpdateAuthorizationState).AuthorizationState); + } + else + { + // Print("Unsupported update: " + @object); + } + } + } + + private class AuthorizationRequestHandler : Td.ClientResultHandler + { + void Td.ClientResultHandler.OnResult(TdApi.BaseObject @object) + { + if (@object is TdApi.Error) + { + Print("Receive an error:" + _newLine + @object); + OnAuthorizationStateUpdated(null); // repeat last action + } + else + { + // result is already received through UpdateAuthorizationState, nothing to do + } + } + } + } +} diff --git a/libs/tdlib/td/example/csharp/TdExample.csproj b/libs/tdlib/td/example/csharp/TdExample.csproj new file mode 100644 index 0000000000..ea2ad56532 --- /dev/null +++ b/libs/tdlib/td/example/csharp/TdExample.csproj @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">x86</Platform> + <ProjectGuid>{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}</ProjectGuid> + <OutputType>Exe</OutputType> + <NoStandardLibraries>false</NoStandardLibraries> + <AssemblyName>ConsoleApplication</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <TargetFrameworkProfile>Client</TargetFrameworkProfile> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup> + <RootNamespace>TdExample</RootNamespace> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="Telegram.Td, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64"> + <SpecificVersion>False</SpecificVersion> + <HintPath Condition=" '$(Configuration)' == 'Debug' ">build\Debug\Telegram.Td.dll</HintPath> + <HintPath Condition=" '$(Configuration)' == 'Release' ">build\Release\Telegram.Td.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="TdExample.cs" /> + </ItemGroup> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <Content Include="build\Debug\LIBEAY32.dll"> + <Link>LIBEAY32.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Include="build\Debug\SSLEAY32.dll"> + <Link>SSLEAY32.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Include="build\Debug\zlibd1.dll"> + <Link>zlibd1.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + </ItemGroup> + <ItemGroup Condition=" '$(Configuration)' == 'Release' "> + <Content Include="build\Release\LIBEAY32.dll"> + <Link>LIBEAY32.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Include="build\Release\SSLEAY32.dll"> + <Link>SSLEAY32.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Include="build\Release\zlib1.dll"> + <Link>zlib1.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSHARP.Targets" /> + <ProjectExtensions> + <VisualStudio AllowExistingFolder="true" /> + </ProjectExtensions> +</Project>
\ No newline at end of file |