Have an amazing solution built in RAD Studio? Let us know. Looking for discounts? Visit our Special Offers page!
DelphiRAD Studio

DelphiでWindows/モバイル向けのTelegram Messengerアプリを作成してみる!

mockup_telegram

この記事は、Thierry Grassia氏のブログの抄訳です

Telegram Messengerとは?

Telegram Messengerは、人気の高いクラウドインスタントメッセージングアプリケーションです。 このアプリケーションは、エンドツーエンドで暗号化されたインスタントテキストメッセージングやビデオ通話など、複数のサービスを提供しています。またTelegramでは、安全なファイル共有や独自のコードで個別に実行するのが難しい多くの強力な機能も可能にします。

Telegram Messengerは、ユーザーに提供するセキュリティレベルが高いことで有名です。さらにTelegram Messengerは、Telegramのクラウド上で動作する独自のメッセージングアプリを誰でも作成可能な無料でオープンなTelegram APIを提供しています。またTelegram APIの統合を容易にするために、完全に無料のクロスプラットフォームライブラリも提供されています。このライブラリはTDLibライブラリとして知られています。

アプリケーションでTelegramクラウドを使用する理由は?

Telegram Messengerは、単なるインスタントメッセージングアプリケーションではなく、私たちが期待する機能や特徴を備えた真のソーシャルネットワークです。例えば、アプリケーションに通知機能が必要な場合、Telegramクラウドと統合することで、とても迅速にこの機能を取得して、すべてのTelegramユーザーと連絡を取ることができます。

TDLibライブラリについて

TDLibコンポーネントライブラリを使用する利点は、以下の通りです。

  • クロスプラットフォーム対応: Windows、Android、iOS、MacOS、Linux等の様々なプラットホームをサポート
  • 高性能: ドキュメントによると、TDLibの各インスタンスは約20000のボットの管理が可能
  • 一貫性: TDLibは、すべての着信メッセージと応答が正しい時間順序でディスパッチされていることを確認
  • 信頼性: TDLibは、低速で不安定なインターネット接続でも動作
  • 安全性: すべてのローカルデータは暗号化される
  • 非同期:  TDLibを呼び出す度に、メインスレッドがブロックされない

セキュリティと暗号化のためにOpenSSLを使用

このライブラリは、OpenSSLに依存しており、Zlib圧縮ライブラリも使用する必要があります。このため、これらのパッケージをダウンロードして、以下で示すサードパーティのバイナリをインクルードまたはリンクする必要があります。

  • tdjson.dll
  • libcrypto-1_1.dll
  • libssl-1_1.dll
  • zlib1.dll

またWindows向けのTDLibでは、Visual C++ランタイムライブラリも必要です。

https://www.microsoft.com/ja-jp/download/details.aspx?id=52685

Delphiで独自のTelegramクライアントを開発するには?

TDLibライブラリには多くの公開されたメソッドがあり、詳細なドキュメントがあるにもかかわらず、直接処理するのはそれほど簡単ではありません。しかし、ESEGECE社のコンポーネントスイートは、多くの困難な作業を代行し、独自にカスタマイズしたTelegramクライアントを開発するための主要なメソッドを提供しています。

以前、エンバカデロのブログでもESEGECE社のWebsocketsを紹介したことがあります。併せてこちらもチェックしてください。

Delphiで使用可能なTelegram Messengerコンポーネントは?

最初のステップは、ESEGECE社のWebsocketsコンポーネントスイートをこちらからダウンロードして、TsgcTDLib_Telegramコンポーネントを使用することです。(トライアル版も利用できます)

新しいTelegramアプリケーションを作成

Telegram Messengerのクラウドへの接続を許可するには、、PI IDとAPI Hash Keyが必要となります。以下の手順で取得できます。

  • TelegramクライアントでTelegramクラウドにサインアップする
  • https://my.telegram.orgのサイトにログインする
  • API開発ツールにアクセスし、フォームに必要事項を入力すると、ユーザー認証に必要なapi_idとapi_hashのパラメータが得られます。

TsgcTDLib_Telegramコンポーネントの使用

Delphiで新しいVCLまたはFireMonkey FMXプロジェクトを作成し、TsgcTDLib_Telegramコンポーネントをドラッグアンドドロップします。これで、独自のTelegramクライアントを作成する準備が整いました。

Messengerアプリの動作の仕組みは?

他のクライアント/サーバーアーキテクチャの場合と同様に、クライアントはデータを送受信する前にサーバーに接続する必要があり、安全性を保つために認証システムがあります。ここでは、認証メカニズムがどのように機能するかを見てみましょう。

Telegramアプリの認証手順

開発者は、Telegramクラウドに接続できるようにするために、いくつかの必須パラメータを入力する必要があります。my.telegram.orgにアクセスして、Telegram.APIプロパティグループにあるAPI認証キーを取得できます。 開発者がユーザーとして宣言したい場合は、電話番号を設定する必要があります。ボットとして宣言されたい場合は、ボットトークンを設定する必要があります。

TsgcTDLib_Telegramクラスのインスタンスを初期化するコード例は以下の通りです。

 //sgcTelegram was drag dropped on a form no need to create
sgcTelegram.Telegram.API.ApiHash := apiHash;
sgcTelegram.Telegram.API.ApiId := apiID;
sgcTelegram.Telegram.PhoneNumber := ''+0155512345678';
sgcTelegram.ApplicationVersion := '1.0';
sgcTelegram.DeviceModel := 'Desktop';
sgcTelegram.LanguageCode := 'en';
sgcTelegram.SystemVersion := 'Windows';
//here Active = True means the connection is queried
sgcTelegram.Active := true;

Active プロパティが True に設定されるとすぐに、認証手順を完了するためにいくつかのイベントが発生します。

OnConnectionStatusイベント

このイベントは、接続ステータスが変更されるたびに発生します。 接続ステータスは、以下の通りです。

  • connectionStateConnecting
  • connectionStateUpdating
  • connectionStateReady

OnAuthenticationCodeイベント

電話番号がTelegramクラウドに登録されている場合は、Telegramアプリケーションを介して認証コードが送信されます。電話番号がTelegramクラウドに登録されていない場合は、SMSを介して認証コードが送信されます。 

シンプルなInputBoxを実装して、受信したコードを入力するだけで、認証プロセスを完了できます。

procedure TFormTelegram.sgcTelegramAuthenticationCode(Sender: TObject; var Code:
string);
begin
  Code := InputBox('Telegram', 'Introduce Telegram Code', '');
end;

Telegram Messagerアプリは、OnRegisterUserイベントによって新規ユーザーを登録

使用した電話番号がTelegramシステムに登録されていない場合は、自動的にサインアッププロセスが開始されます。このサインアッププロセスでは、ユーザーの姓と名が必要です。それらを取得するために、イベントOnRegisterUserが発生します。このイベントの非常にシンプルな実装コード例は、以下の通りです。

procedure TFormTelegram.sgcTelegramRegisterUser(Sender: TObject;
var FirstName, LastName: string);
begin
  FirstName := InputBox('Telegram', 'Your FirstName', '');
  LastName := InputBox('Telegram', 'Your LastName', '');
end;

OnAuthorizationStatusイベント

これらの認証ステップ中に、OnAuthorizationStatusイベントが発生し、このプロセスでどのステップに達しているか確認できます。そのステータスの種類は、以下の通りです。

  • authorizationStateWaitTdlibParameters
  • authorizationStateWaitEncryptionKey
  • authorizationStateWaitPhoneNumber
  • authorizationStateWaitCode
  • authorizationStateLoggingOut
  • authorizationStateClosed
  • authorizationStateReady

認証が完了すると、アプリケーションは他のTelegramユーザーとメッセージを送受信できるようになります。

Telegramクラウドでのメッセージ交換方法

schema

Telegram APIを使用したインスタントメッセージングアプリケーションは、チャットルームを中心に構築され、ユーザーはそのチャットルームに登録します。文字通り、ユーザーはチャットルームに参加し、メッセージを交換します。同じチャットルームにいる複数のユーザーに公開メッセージを送信するには、チャットルームの識別子のみが必要です。Telegramクラウドは、このチャットルームに関連付けられたすべてのユーザーにメッセージを発信します。最終的に、このチャットアプリケーションの目的は、メッセージをグループに対して公開および非公開で送受信することです。それでは、TsgcTDLib_Telegramコンポーネントを使用して、その仕組みを確認してみましょう。

DelphiのWindowsおよびモバイルアプリでTelegramユーザーからのメッセージを受信するには?

一番シンプルな部分です。イベント OnMessageText(Sender: TObject; MessageText: TsgcTelegramMessageText); を実装するだけで、Telegramの他のユーザーがあなたにメッセージを送信すると、このイベントがあなたのアプリケーションで発生します。TsgcTelegramMessageTextクラスは、どのチャットルームでどのユーザーがメッセージを送信したかを識別できるChatIDとSenderUserIDというプロパティを持っています。メッセージの内容は、このクラスのTextプロパティに設定されています。

アプリからTelegramユーザーにメッセージを送信するには?

メッセージの送信に使用されるTsgcTDLib_Telegramクラスのメソッドは、SendTextMessage(aChatID:integer; aMessageText:string);です。 つまり、メッセージの送信先であるチャットルームのChatIDを知っている必要があります。

この場合、このチャットルームのすべてのメンバーがメッセージを受信します。チャットルームがすでに開かれていて、メッセージの交換がすでに開始されている場合、ChatIDはイベントOnMessageTextを通じて既にに認識されています。ただし、アプリケーションのユーザーがチャットを開始したい場合、この問題はもう少し厄介なものになります。チャットルームを作成し、そのChatIDを取得するには、CreateNewBasicGroupChat(aUserIds array of Int64;const aTitle:string)というメソッドを使用します。

グループチャットを作成する場合は、CreatePrivateChat(userId:integer);によって作成します。

ユーザー識別子(aUserIds)のリストは、ルームチャットのタイトルと共に渡されます このリストは、チャットの参加者のリストを表します。 ChatIDは、OnNewChat(Sender:TObject; Chat:TsgcTelegramChat);イベントで返されます。

チャットの識別子(ChatId)は、TsgcTelegramChatクラスのプロパティChatIdから取得できます。チャットルームを作成し、他のユーザーにメッセージを送信するためには、メッセージ対象のユーザー識別子(UserID)を知る必要があります。

電話番号からTelegramのユーザーIDを取得するには?

UserIDは、Telegramクラウドでのみ認識される番号ですが、電話番号は、あらゆるユーザーの現実の世界での公開識別子です。

TDLibでは、ユーザーがTelegramクラウドに登録している場合に、電話番号からユーザーのUserIDを取得するメソッドを公開しています。Telegram APIのリストはこちらをご覧ください。

Json形式のAPIを直接使用するには、TDLibSendメソッドを使用する必要があります。このメソッドはTDLibライブラリにコマンドを送信し、このコマンドの結果は、OnEvent(Sender: TObject; const Event,Text: string);イベントを通じて確認できます。 文字列としてのパラメータEventはイベントタイプをカテゴリ化することができ、パラメータTextはJSON形式の全データです。TDLibで公開されているAPIの数は非常に多いのですが、ここでは電話番号からユーザーIDを取得するためのAPIを見てみましょう。電話番号からUserIDを取得するためのTDLib APIは、importContactsです。ドキュメントは以下の通りです。

importcontacts

typeは importedContacts構造体を返す関数です。importContacts関数の入力パラメータは、contact構造の配列です。それでは、contact構造を見てみましょう。

contact-2

電話番号のみを使用してTelegramで連絡先をプログラムで定義する方法

これは連絡先を電話番号、名前、姓、vcard、user_idで記述できることを意味します。 ここでは、電話番号のみで連絡先を定義してみましょう。JSONの’importContacts’メソッドを呼び出すコード例は、以下の通りです。

sgcTelegram.TDLibSend('{"@type": "importContacts", "contacts": [{"phone_number": "+01555678945"}]);

ドキュメントによると、結果は以下のようなimportedContactsになります。

importedcontacts-3

OnEventイベントで受信されます。

受信したJSON文字列の例は、以下の通りです。 

 {“@type”: “importedContacts”, “user_ids”:[15138448729], “importer_count”:[0]}

この例では、電話番号+01555678945の所有者はTelegramクラウドに登録されており、UserID : 15138448729を持っています。電話番号が登録されていない場合、importedContactsコールバックのuser_idは0です。受信したイベントをすべてログに記録して、どのように解釈すべきかを把握しておくことを強くお勧めします。次に、電話番号のリストからUserIDを解析する手順は以下の通りです。

procedure TFRMTelegramFMX.sgcTelegramEvent(Sender: TObject; const Event, Text: string);
begin
  if Event ='importedContacts' then
  begin
    FUserIDList := ParseImportedContacts(Text);
  end;
end;

ParseImportedContactsメソッドを使用して importedContactsのJSON構造を解析します。

function TFRMTelegramFMX.ParseImportedContacts(aText: string):TStringList;
var aJson:TJsonValue;
    userIdArray:TJsonArray;
    iter:integer;
begin
    Result := TStringList.Create;
    aJson := TJSONObject.ParseJSONValue(aText);
    userIdArray := aJson.P['user_ids'] as TJsonArray;
    for iter := 0 to userIdArray.Count-1 do
    begin
      Result.Add(userIdArray.Items[iter].ToJSON);
    end;
    aJson.Free;
end;

スパムやスキャマーを回避するには

TsgcTDLib_TelegramクラスのメソッドGetUserを使用すると、ユーザーは、OnEventイベントで受け取ったJSON文字列を解析するのと同じ方法で、対象ユーザーのcivilityを取得することができます。 GetUserメソッドの呼び出し後に受信したJSON文字列は、以下の通りです。

{
   "@type":"user",
   "id":15138448729,
   "first_name":"John",
   "last_name":"",
   "username":"",
   "phone_number":"01555678945",
   "status":{
      "@type":"userStatusOffline",
      "was_online":1626193501
   },
   "is_contact":true,
   "is_mutual_contact":true,
   "is_verified":false,
   "is_support":false,
   "restriction_reason":"",
   "is_scam":false,
   "have_access":true,
   "type":{
      "@type":"userTypeRegular"
   },
   "language_code":""
}

この方法では、ユーザーが対象ユーザーの電話番号しか知らないときにチャットを開始したい場合、公式のTelegramの動作をコピーすることができます。承認された後、TelegramはOnEventイベントを介して、電話番号の所有者のTelegram内のすべての既知の連絡先をアプリケーションに送信することに注意してください。

Messagerアプリのデモプログラムについて

このブログで紹介したデモプログラムは、こちらからダウンロードできます。

RAD Studio 13.2 Florence Now Available! Kai 1.1.1 Now Available! What's Coming in RAD Studio 13.2 Florence

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.

Start Free Trial   Upgrade Today

   Free Delphi Community Edition   Free C++Builder Community Edition

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

IN THE ARTICLES