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: 10 months 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 (about 8 years ago)
- Default Branch: master
- Last Pushed: 2022-12-08T03:50:13.000Z (over 3 years ago)
- Last Synced: 2025-08-21T22:51:40.955Z (11 months ago)
- Topics: csharp, dotnet, dotnet-core, dotnet-framework, dotnetcore, dotnetframework, teams, webex, webex-teams, webexteams
- Language: C#
- Homepage:
- Size: 570 KB
- Stars: 6
- 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
[](https://www.nuget.org/packages/Thrzn41.WebexTeams) [](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("your_webex_teams_account@example.com", 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("your_webex_teams_account@example.com",
"[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("your_webex_teams_account@example.com",
"[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("your_webex_teams_account@example.com", "こんにちは、私はゲストユーザです!!")).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("targetuser@example.com", "こんにちは, 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();
```