diff options
Diffstat (limited to 'protocols/Telegram/tdlib/td/example/csharp')
4 files changed, 392 insertions, 0 deletions
diff --git a/protocols/Telegram/tdlib/td/example/csharp/.gitignore b/protocols/Telegram/tdlib/td/example/csharp/.gitignore new file mode 100644 index 0000000000..5266ecccc9 --- /dev/null +++ b/protocols/Telegram/tdlib/td/example/csharp/.gitignore @@ -0,0 +1,5 @@ +.vs/ +bin/ +obj/ +project.lock.json +TdExample.csproj.user diff --git a/protocols/Telegram/tdlib/td/example/csharp/README.md b/protocols/Telegram/tdlib/td/example/csharp/README.md new file mode 100644 index 0000000000..2faa15e12e --- /dev/null +++ b/protocols/Telegram/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/protocols/Telegram/tdlib/td/example/csharp/TdExample.cs b/protocols/Telegram/tdlib/td/example/csharp/TdExample.cs new file mode 100644 index 0000000000..be98e1a758 --- /dev/null +++ b/protocols/Telegram/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/protocols/Telegram/tdlib/td/example/csharp/TdExample.csproj b/protocols/Telegram/tdlib/td/example/csharp/TdExample.csproj new file mode 100644 index 0000000000..ea2ad56532 --- /dev/null +++ b/protocols/Telegram/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  | 
