Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/thrzn41/webexteamsapiclient
Webex Teams API Client for .NET
https://github.com/thrzn41/webexteamsapiclient
csharp dotnet dotnet-core dotnet-framework dotnetcore dotnetframework teams webex webex-teams webexteams
Last synced: 3 days ago
JSON representation
Webex Teams API Client for .NET
- Host: GitHub
- URL: https://github.com/thrzn41/webexteamsapiclient
- Owner: thrzn41
- License: mit
- Created: 2018-05-31T07:11:37.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2022-12-08T03:50:13.000Z (about 2 years ago)
- Last Synced: 2024-12-01T00:31:37.997Z (about 1 month ago)
- Topics: csharp, dotnet, dotnet-core, dotnet-framework, dotnetcore, dotnetframework, teams, webex, webex-teams, webexteams
- Language: C#
- Homepage:
- Size: 570 KB
- Stars: 5
- Watchers: 1
- Forks: 4
- Open Issues: 17
-
Metadata Files:
- Readme: README.ja-JP.md
- Changelog: CHANGELOG.ja-JP.md
- License: LICENSE
Awesome Lists containing this project
README
# Webex Teams API Client for .NET
[![nuget](https://img.shields.io/nuget/v/Thrzn41.WebexTeams.svg)](https://www.nuget.org/packages/Thrzn41.WebexTeams) [![MIT license](https://img.shields.io/github/license/thrzn41/WebexTeamsAPIClient.svg)](https://github.com/thrzn41/WebexTeamsAPIClient/blob/master/LICENSE)
`Webex Teams API Client`は、`Cisco Webex Teams REST API`を利用しやすくしたライブラリです。
基本的な機能のほかに、Cisco Webex TeamsのAPIを使いやすくするための機能を実装しています。#### ほかの言語のREADME
* [English README is here](https://github.com/thrzn41/WebexTeamsAPIClient/blob/master/README.md) ([英語のREADMEはこちら](https://github.com/thrzn41/WebexTeamsAPIClient/blob/master/README.md))---
`Webex Teams API Client`を使って、`Cisco Webex Teams REST API`を簡単に実行できます。* Markdownでメッセージを投稿する簡単な例
``` csharp
// 暗号化されたトークンをストレージから読み込む。
ProtectedString token = LoadEncryptedBotToken();// TeamsAPIClientのインスタンスを作成する(リトライ機能付き)。
var teams = TeamsAPI.CreateVersion1Client(token, new TeamsRetryHandler(4));// Markdownを構成します。
var markdown = new MarkdownBuilder();
markdown.Append("こんにちは、").AppendBold("Webex Teams").Append("!!");// メッセージを投稿します。
var message = (await teams.CreateDirectMessageAsync("[email protected]", markdown.ToString())).GetData();Console.WriteLine("メッセージが投稿されました: ID = {0}", message.Id);
```* AdaptiveCardをJson文字列やobjectから生成して投稿する簡単な例
``` csharp
// Json文字列から生成。
var card = AdaptiveCardAttachment.FromJsonString(
@"
{
""type"": ""AdaptiveCard"",
""version"": ""1.0"",
""body"": [
{
""type"": ""TextBlock"",
""text"": ""Adaptive Cards"",
""size"": ""large""
}
],
""actions"": [
{
""type"": ""Action.OpenUrl"",
""url"": ""http://adaptivecards.io"",
""title"": ""Learn More""
}
]
}
");// カード付きでメッセージを投稿。
var message = (await teams.CreateDirectMessageAsync("[email protected]",
"[Learn More](http://adaptivecards.io) about Adaptive Card.",
card)).GetData();Console.WriteLine("Message was posted: ID = {0}", message.Id);
// 匿名型やクラスのインスタンスからも生成できます。
var cardObj = new
{
type = "AdaptiveCard",
version = "1.0",
body = new []
{
new
{
type = "TextBlock",
text = "Adaptive Cards",
size = "large",
}
},
actions = new []
{
new
{
type = "Action.OpenUrl",
url = "http://adaptivecards.io",
title = "Learn More"
}
},
};// objectから生成。
card = AdaptiveCardAttachment.FromObject(cardObj);// カード付きでメッセージを投稿。
message = (await teams.CreateDirectMessageAsync("[email protected]",
"[Learn More](http://adaptivecards.io) about Adaptive Card.",
card)).GetData();Console.WriteLine("Message was posted: ID = {0}", message.Id);
// teams.GetAttachmentActionAsync()でユーザからの入力を受け取れます。
// 本APIClientのWebhook listner, event handlerには、これらの入力を受け取る機能があります。
```* ゲストユーザ用のアカウントを発行して投稿する例
Webex Teamsの[Guest Issuer機能](https://developer.webex.com/guest-issuer.html)を利用する例です。
``` csharp
// 暗号化されたGuest Issuer secretをストレージから読み込む。
ProtectedString secret = LoadEncryptedGuestIssuerSecret();// GuestIssuerClientのインスタンスを作成する。
var guestIssuer = TeamsAPI.CreateVersion1GuestIssuerClient(secret, "your_guest_issuer_id");// Guest Userを作成する。
var guest = (await guestIssuer.CreateGuestUserAsync("my-guest-id", "ゲストユーザ名")).GetData();// ゲストユーザ用のTeamsAPIClientインスタンスを作成する(リトライ機能付き)。
var teams = TeamsAPI.CreateVersion1Client(guest, new TeamsRetryHandler(4));// ゲストユーザからメッセージを投稿する。
var message = (await teams.CreateDirectMessageAsync("[email protected]", "こんにちは、私はゲストユーザです!!")).GetData();Console.WriteLine("メッセージが投稿されました: ID = {0}", message.Id);
```* Pagination機能を利用する例
Webex Temas REST APIの[Pagination機能](https://developer.webex.com/pagination.html)の例が以下になります。
スペースを50個ずつ取得していって、特定の名前のスペースへ「こんにちは」を投稿します。``` csharp
// すべてのGroupスペースを取得するためにEnumeratorを取得します。
var e = (await teams.ListSpacesAsync(
type: SpaceType.Group,
max: 50)
).GetListResultEnumerator();// すべてのスペースを取得するまで繰り返します。
while (await e.MoveNextAsync())
{
var r = e.CurrentResult;if (r.IsSuccessStatus && r.Data.HasItems)
{
// それぞれの結果にスペースのリストが含まれます。
foreach (var space in r.Data.Items)
{
// 特定の名前のスペースに、「こんにちは」と投稿します。
if (space.Title == "Webex Teams API Client(Thrzn41.WebexTeams)のデモ用スペース")
{
await teams.CreateMessageAsync(space, "こんにちは、Webex Teams!!");
}
}}
}
```ほかのサンプルは、 [こちら](https://github.com/thrzn41/WebexTeamsAPIClientSamples)。
---
## 利用可能なプラットフォーム
* .NET Standard 1.3以降
* .NET Core 1.0以降
* .NET Framework 4.5.2以降> 注記: 簡易Webhookサーバ機能を利用する場合は、
> .NET Standard 2.0+, .NET Core 2.0+, .NET Framework 4.5.2+が必要です。---
## サンプルWebex Teams API Clientのサンプルは、 [こちらをクリック](https://github.com/thrzn41/WebexTeamsAPIClientSamples)。
---
## 利用可能な機能* Webex Teamsの基本的なAPI(List/Get/Create Message, Spaceなど)。
* Webex TeamsのAdmin API(List/Get Event, Licenseなど)。
* ストレージに保存するTokenの暗号化と復号。
* AdaptiveCardsの添付(カードの作成やユーザ入力の取得)。
* List API用のPagination機能。Paginationを簡単にするためのEnumerator。
* Retry-after値の処理とRetry handler。
* Markdown builder。
* エラーコードや詳細の取得。
* Webhook secretの検証とWebhook notification manager、Webhook event handler。
* Guest Issuer helper。
* OAuth2 helper。
* 簡易Webhookサーバ機能(.NET Standard 2.0+, .NET Core 2.0+, .NET Framework 4.5.2+)。### 基本機能
| Teamsのリソース名 | 利用可能な機能 | 説明 |
| :-------------------------------- | :---------------------------- | :---------------------------------- |
| Person/People | List/Get | v1.2.2から利用可能。Get Meも利用可能 |
| Space(Room) | List/Create/Get/Update/Delete | v1.2.2から利用可能。Roomは、API Clientでは、Spaceと呼ばれる。 |
| Space(Room) Meeting Info | Get | v1.7.1から利用可能。 |
| SpaceMembership(Membership) | List/Create/Get/Update/Delete | v1.2.2から利用可能。Membershipは、API Clientでは、SpaceMembershipと呼ばれる。 |
| Message | List/Create/Get/Delete | v1.2.2から利用可能。ローカルのstreamからファイル添付も可能 |
| AdaptiveCards | List/Create/Get/Delete | v1.7.1から利用可能。 |
| AttachmentActions | Create/Get | v1.7.1から利用可能。 |
| Team | List/Create/Get/Update/Delete | v1.2.2から利用可能。 |
| TeamMembership | List/Create/Get/Update/Delete | v1.2.2から利用可能。 |
| Webhook | List/Create/Get/Update/Delete | v1.2.2から利用可能。 |
| File | GetInfo/GetData/Upload | v1.2.2から利用可能。 |
| Place/Device/xAPI | - | v1.8.1で計画中。 |### Admin機能
| Teamsのリソース名 | 利用可能な機能 | 説明 |
| :-------------- | :---------------------------- | :---------------------------------------------- |
| Person/People | Create/Update/Delete | v1.2.2から利用可能。 |
| Event | List/Get | v1.2.2から利用可能。 |
| Organization | List/Get | v1.2.2から利用可能。 |
| License | List/Get | v1.2.2から利用可能。 |
| Role | List/Get | v1.2.2から利用可能。 |
| GroupResource | List/Get | v1.2.2から利用可能。 |
| GroupResourceMembership | List/Get/Update | v1.2.2から利用可能。 |### ストレージのTokenの暗号化と復号
`ProtectedString`が、Token保存時の暗号化と、読み込み時の復号の機能を提供します。
詳細は後述。### Pagination機能
Cisco Webex Teams APIのpaginationに関しては、[ここ](https://developer.webex.com/pagination.html)を参照。
`result.HasNext`と`result.ListNextAsync()`が、Webex Teams API Clientで利用可能です。
詳細は後述。### Retry-Afterの取得
`result.HasRetryAfter`と `result.RetryAfter`が、Webex Teams API Clientで利用可能です。
また、 `TeamsRetryHandler`と`TeamsRetryOnErrorHandler`が利用可能です。
詳細は後述。### HTTP Statusコードの取得
`result.HttpStatusCode`が、Webex Teams API Clientで利用可能です。
詳細は後述。### エラーコードと詳細の取得
Cisco Webex Teams APIは、エラーコードと詳細を返す場合があります。
`result.Data.HasErrors`と`result.Data.GetErrors()`が、Webex Teams API Clientで利用可能です。### 部分エラーの取得
Cisco Webex Teams APIは、部分的なエラーを返す場合があります。
部分エラーの詳細に関しては、[ここ](https://developer.webex.com/errors.html)を参照。
`Item.HasErrors`と`Item.GetPartialErrors()`が、Webex Teams API Clientで利用可能です。### trackingIdの取得
trackingIdは、Cisco Webex Teams APIのテクニカルサポートで利用される可能性があります。
`result.TrackingId`が、Webex Teams API Clientで利用可能です。
詳細は後述。### Validates webhook secret
`Webhook.CreateEventValidator()`が、Webex Teams API Clientで利用可能です。
詳細は後述。Webex Teams API Clientの`CreateWebhookAsync()`メソッドはデフォルトでは、webhook secretを動的に生成します。
### Webhook listener(.NET Standard 2.0+, .NET Core 2.0+, .NET Framework 4.5.2+)
Webhook listener機能は、簡易的なWebhookのサーバ機能を提供します。
> **注記: この機能は、簡単なテスト時の利用を想定しています。
> 運用環境等では、より信頼性のあるサーバをご利用ください。**`WebhookListener`が、Webex Teams API Clientで利用可能です。
詳細は後述。---
## 基本的な使い方### Webex Teams API Clientのインストール
`Webex Teams API Client`は、以下のいずれかの方法で、`NuGet` package manager経由で入手できます。
* NuGet Package ManagerのGUI
"`Thrzn41.WebexTeams`"を検索してインストール。* NuGet Package ManagerのCLI
```
PM> Install-Package Thrzn41.WebexTeams
```* .NET Client
```
> dotnet add package Thrzn41.WebexTeams
```### Webex Teams API Client関連のusingディレクティブ
usingディレクティブを利用する場合は、以下の名前空間を指定します。
``` csharp
using Thrzn41.Util
using Thrzn41.WebexTeams
using Thrzn41.WebexTeams.Version1
```必要に応じて、以下も利用可能です。
* Guest Issuer helper利用時、`Thrzn41.WebexTeams.Version1.GuestIssuer`
* OAuth2 helper利用時、`Thrzn41.WebexTeams.Version1.OAuth2`
* Admin API利用時、`Thrzn41.WebexTeams.Version1.Admin`### Webex Teams API Clientインスタンスの作成
Webex Teams API Clientのインスタンスは可能な限り長い期間使いまわすようにします。
``` csharp
/// 基本API利用時。
TeamsAPIClient teams = TeamsAPI.CreateVersion1Client(token);
```Admin APIを利用する場合は、Admin API用のインスタンスを作成する必要があります。
`TeamsAdminAPIClient`は、`TeamsAPIClient`の全機能に加えて、Adminの機能が利用できます。
``` csharp
/// Admin API利用時。
TeamsAdminAPIClient teams = TeamsAPI.CreateVersion1AdminClient(token);
```> **注記: 'token'は、Cisco Webex Teams APIでは、非常にセンシティブな情報です。
> 'token'は、慎重に保護する必要があります。
> ソースコード中に直接記載したり、安全ではない方法で保存しないようにします。
> `Webex Teams API Client`では、トークンを暗号化したり復号する方法を、いくつか提供しています。
> 独自の方法で暗号化や復号、保護を実装する場合は、インスタンス作成時に、復号されたトークン文字列を利用することができます。**### 暗号化したTokenをストレージに保存する
``` csharp
char[] tokens = GetBotTokenFromBotOwner();var protectedToken = LocalProtectedString.FromChars(tokens);
LocalProtectedString.ClearChars(tokens);Save("token.dat", protectedToken.EncryptedData);
Save("entropy.dat", protectedToken.Entropy);
```**注記: LocalProtectedStringはメモリ内での保護は提供していません。
Tokenを保存する際の、暗号化と復号での利用を想定しています。**### 暗号化したTokenをストレージから読み込んで、Webex Teams API Clientのインスタンスを作成する
``` csharp
byte[] encryptedData = Load("token.dat");
byte[] entropy = Load("entropy.dat");var protectedToken = LocalProtectedString.FromEncryptedData(encryptedData, entropy);
/// 基本API利用時。
TeamsAPIClient teams = TeamsAPI.CreateVersion1Client(protectedToken);
```> **注記: オプションに応じて、暗号化されたデータは、暗号化したときと同じローカルユーザまたはローカルマシン上でのみ復号できます。**
### Cisco Webex Teamsのスペースにメッセージを投稿する
``` csharp
var result = await teams.CreateMessageAsync("xyz_space_id", "こんにちは, Teams!");if(result.IsSuccessStatus)
{
Console.WriteLine("メッセージが投稿されました: id = {0}", result.Data.Id);
}
```### 成功, 失敗, エラーのハンドリング
`result.IsSuccessStatus`を使って成功したかどうか確認できます。
`result.Data.HasErrors`や`result.Data.GetErrorMessage()`を使ってCisco Webex Teams APIサービスからエラーコード、エラーメッセージを受け取ることができます。``` csharp
var result = await teams.CreateMessageAsync("xyz_space_id", "こんにちは, Teams!");if(result.IsSuccessStatus)
{
Console.WriteLine("メッセージが投稿されました: id = {0}", result.Data.Id);
}
else
{
Console.WriteLine("メッセージの投稿に失敗しました: status = {0}, trackingId = {1}", result.HttpStatusCode, result.TrackingId);if(result.Data.HasErrors)
{
Console.WriteLine( result.Data.GetErrorMessage() );
}
}
```例外を捕捉したい場合は、データ取得時に、`result.GetData()`を利用することができます。
`result.GetData()`は、リクエスト失敗時に`TeamsResultException`をスローします。
(一方、`result.Data`は、`TeamsResultException`を送出しません。)``` csharp
try
{
var result = await teams.CreateMessageAsync("xyz_space_id", "こんにちは, Teams!");var message = result.GetData();
Console.WriteLine("メッセージが投稿されました: id = {0}", message.Id);
}
catch(TeamsResultException tre)
{
Console.WriteLine("メッセージの投稿に失敗しました: status = {0}, trackingId = {1}, description = {2}",
tre.HttpStatusCode, tre.TrackingId, tre.Message);
}
```### Cisco Webex Teamsのスペースに添付ファイル付きでメッセージを投稿する
``` csharp
using (var fs = new FileStream("path/myfile.png", FileMode.Open, FileAccess.Read, FileShare.Read))
using (var data = new TeamsFileData(fs, "imagefile.png", TeamsMediaType.ImagePNG))
{
var result = await teams.CreateMessageAsync("xyz_space_id", "添付ファイル付き", data);if(result.IsSuccessStatus)
{
Console.WriteLine("添付ファイル付きでメッセージが投稿されました: id = {0}", result.Data.Id);
}
}
```### Cisco Webex Teamsの1:1スペースにメッセージを投稿する
``` csharp
var result = await teams.CreateDirectMessageAsync("[email protected]", "こんにちは, Teams!");if(result.IsSuccessStatus)
{
Console.WriteLine("メッセージが投稿されました: id = {0}", result.Data.Id);
}
```### スペースの一覧を取得する
``` csharp
var result = await teams.ListSpacesAsync();if(result.IsSuccessStatus && result.Data.HasItems)
{
foreach (var item in result.Data.Items) {
Console.WriteLine("Space: title = {0}", item.Title);
}
}
```### ファイルの情報やデータを取得する
ダウンロードせずにファイルの情報だけ入手する。
``` csharp
var result = await teams.GetFileInfoAsync(new Uri("https://api.example.com/path/to/file.png"));if(result.IsSuccessStatus)
{
var file = result.Data;Console.WriteLine("File: Name = {0}, Size = {1}, Type = {2}", file.Name, file.Size?.Value, file.MediaType?.Name);
}
```ファイルをダウンロードする。
この例では、ファイルのデータがMemoryStreamにコピーされます。
``` csharp
using(var stream = new MemoryStream())
{
var result = await teams.CopyFileDataToStreamAsync(new Uri("https://api.example.com/path/to/file.png"), stream);if(result.IsSuccessStatus)
{
var file = result.Data;Console.WriteLine("File: Name = {0}, Size = {1}, Type = {2}", file.Name, file.Size?.Value, file.MediaType?.Name);
}
}
```### Pagination機能を利用する
``` csharp
var result = await teams.ListSpacesAsync();if(result.IsSuccessStatus)
{
//
// ここで何か処理する...
//if(result.HasNext)
{
// 続きのリストがあれば取得する。
result = await result.ListNextAsync();if(result.IsSuccessStatus)
{
// ...
}
}
}
```### Enumeratorを使ってPaginaionを利用する
``` csharp
// すべてのGroupスペースを取得するためにEnumeratorを取得します。
var e = (await teams.ListSpacesAsync(
type: SpaceType.Group,
max: 50)
).GetListResultEnumerator();// すべてのスペースを取得するまで繰り返します。
while (await e.MoveNextAsync())
{
var r = e.CurrentResult;if (r.IsSuccessStatus && r.Data.HasItems)
{
// それぞれの結果にスペースのリストが含まれます。
foreach (var space in r.Data.Items)
{
Console.WriteliLine("Title = {0}", space.Title);
}}
}
```### Http status codeを取得する
``` csharp
var result = await teams.ListSpacesAsync();Console.WriteLine("Status is {0}", result.HttpStatusCode);
```### Retry afterを取得する.
``` csharp
var result = await teams.ListSpacesAsync();if(result.IsSuccessStatus)
{
//
// ここで何かする...
//
}
else if(result.HasRetryAfter)
{
Console.WriteLine("{0}後にリトライしなきゃ!!", result.RetryAfter.Delta);
}
```### Retry Handler
`TeamsRetryHandler`と`TeamsRetryOnErrorHandler`を利用してリトライ処理を容易にします。
``` csharp
// リトライ機能付きでインスタンスを作成(この場合は、最大4回のリトライ)。
var teams = TeamsAPI.CreateVersion1Client(token, new TeamsRetryHandler(4));// リクエスト時に、HTTP 429のレスポンスがあると、リトライが行われます。
var result = await teams.GetMeAsync();//HTTP 500, 502, 503, 504レスポンス時にもリトライしたい場合は、TeamsRetryOnErrorHandlerを利用します。
// Retry-Afterヘッダがない場合は、この例の場合は、15秒後にリトライが行われます。
var teams = TeamsAPI.CreateVersion1Client(token, new TeamsRetryOnErrorHandler(4, TimeSpan.FromSeconds(15.0f)));
```### TrackingIdを取得する
``` csharp
var result = await teams.ListSpacesAsync();Console.WriteLine("Tracking id: {0}", result.TrackingId);
```### Markdown Builder.
``` csharp
var md = new MarkdownBuilder();// メンションと番号付きリストでMarkdownを作成。
md.Append("こんにちは、").AppendMentionToPerson("xyz_person_id", "〇〇さん").AppendLine();
md.AppendOrderedList("Item1");
md.AppendOrderedList("Item2");
md.AppendOrderedList("Item3");var result = await teams.CreateMessageAsync("xyz_space_id", md.ToString());
```### Webhookに通知されたデータを検証する
``` csharp
var webhook = await teams.GetWebhookAsync("xyz_webhook_id");var validator = webhook.CreateEventValidator();
```イベントがWebhookのURIに通知された際には、
X-Spark-Signatureがハッシュ値を持っています。validatorを利用して、データの整合性を確認できます。
``` csharp
byte[] webhookEventData = GetWebhookEventData();if( validator.Validate(webhookEventData, "xyz_x_teams_signature_value") )
{
Console.WriteLine("通知されたイベントデータの検証に成功!");
}
```### Webhookの通知管理
Webhook notification managerを使ってWebhookへの通知を管理します。
* インスタンスを作成する。
``` csharp
var notificationManager = new WebhookNotificationManager();
```* 通知用のfunctionを登録します。
``` csharp
var webhook = await teams.GetWebhookAsync("xyz_webhook_id");notificationManager.AddNotification(
webhook,
(eventData) =>
{
Console.WriteLine("イベントを受信, id = {0}", eventData.Id);
}
);
```* イベントの受信時。
``` csharp
byte[] webhookEventData = GetWebhookEventData();// Signatureが確認され登録したfunctionにイベントデータが通知されます。
notificationManager.ValidateAndNotify(webhookEventData, "xyz_x_teams_signature_value", encodingOfData);
```### Webhook Listener
* Webhook listenerのインスタンスの作成。
``` csharp
var listener = new WebhookListener();
```* 待ち受けする、ホストとポートを登録する。
待ち受けには、TLS/httpsを利用すべきです。
そのためには、まず、実行環境側で`netsh`ツールなどを利用して、有効な証明書をバインドしておく必要があります。バインドされたアドレスとポート番号で、エンドポイントを追加します。
``` csharp
var endpointUri = listener.AddListenerEndpoint("yourwebhookserver.example.com", 8443);
```* Webhook listener用のWebhookを作成します。
`listener.AddListenerEndpoint()`が返す`endpointUri`がWebhookの通知先Uriになります。
``` csharp
var result = await teams.CreateWebhookAsync(
"my webhook for test",
endpointUri,
EventResource.Message,
EventType.Created);
```* Webhook listenerにWebhookと通知先funcを登録します。
``` csharp
var webhook = result.Data;listener.AddNotification(
webhook,
async (eventData) =>
{
Console.WriteLine("Eventが通知されました, id = {0}", eventData.Id);if(eventData.Resource == EventResource.Message)
{
Console.WriteLine("Message, id = {0}", eventData.MessageData.Id);
}
}
);
```* Listenerの開始。
Listenerを開始すると、イベント発生時に登録したfunctionに通知されます。
``` csharp
listener.Start();
```### Webhook listenerをngrokと共に利用する
グローバルIPアドレスが利用できない場合、
[ngrok](https://ngrok.com/)などのトンネリングサービスが便利な場合があります。* ngrokの入手と起動。
ngrokのコマンドラインツールは、[ここから入手](https://ngrok.com/)できます。
以下のコマンドで、トンネリングサービスを起動して、localhostの8080ポートにフォワードされます。
```
prompt> ngrok http 8080 --bind-tls=true
```* Webhook listenerのインスタンスの作成。
``` csharp
var listener = new WebhookListener();
```* 待ち受けする、ホストとポートを登録する。
ngrokは、`localhost`へフォワードします。
``` csharp
var endpointUri = listener.AddListenerEndpoint("localhost", 8080, false);
```* Webhook listener用のWebhookを作成します。
この例では、ngronのトンネリングサービスを利用しています。
`listener.AddListenerEndpoint()`が返したUriは、フォワード先のUriです。Webhookには、ngrok側のUriを指定する必要があります。
ngrokが、`https://ngrok-xyz.example.com`を割り当てた場合、
`String.Format("https://ngrok-xyz.example.com{0}", endpointUri.AbsolutePath)`をWebhookの宛先として指定します。``` csharp
var result = await teams.CreateWebhookAsync(
"テスト用のWebhook",
new Uri(String.Format("https://ngrok-xyz.example.com{0}", endpointUri.AbsolutePath)),
EventResource.Message,
EventType.Created);
```* Webhook listenerにWebhookと通知先funcを登録します。
``` csharp
var webhook = result.Data;listener.AddNotification(
webhook,
async (eventData) =>
{
Console.WriteLine("Eventが通知されました, id = {0}", eventData.Id);if(eventData.Resource == EventResource.Message)
{
Console.WriteLine("Message, id = {0}", eventData.MessageData.Id);
}
}
);
```* Listenerの開始。
Listenerを開始すると、イベント発生時に登録したfunctionに通知されます。
``` csharp
listener.Start();
```