https://github.com/thrzn41/ciscosparkapiclient
[Obsoleted] Cisco Spark API Client for .NET
https://github.com/thrzn41/ciscosparkapiclient
cisco-spark ciscospark csharp dotnet dotnet-core dotnet-framework dotnet-standard
Last synced: 2 months ago
JSON representation
[Obsoleted] Cisco Spark API Client for .NET
- Host: GitHub
- URL: https://github.com/thrzn41/ciscosparkapiclient
- Owner: thrzn41
- License: mit
- Created: 2017-12-04T09:34:13.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2018-06-04T08:16:22.000Z (about 8 years ago)
- Last Synced: 2025-04-08T13:23:00.808Z (over 1 year ago)
- Topics: cisco-spark, ciscospark, csharp, dotnet, dotnet-core, dotnet-framework, dotnet-standard
- Language: C#
- Homepage:
- Size: 219 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.ja-JP.md
- License: LICENSE
Awesome Lists containing this project
README
# ※重要な告知※
Cisco Sparkに別れを告げて、**Cisco Webex Teams**を始めてみよう。
Cisco Sparkは、**Cisco Webex Teams**になりました。
`Thrzn41.CiscoSpark`も、`Thrzn41.WebexTeams`になりました。
リポジトリは、 [WebexTeamsAPIClient](https://github.com/thrzn41/WebexTeamsAPIClient)へ移行しています。
https://github.com/thrzn41/WebexTeamsAPIClient
> branchやforkではなく、完全に移行することにしました。
# [Obsoleted] Cisco Spark API Client for .NET
[](https://www.nuget.org/packages/Thrzn41.CiscoSpark) [](https://github.com/thrzn41/CiscoSparkAPIClient/blob/master/LICENSE)
`Cisco Spark API Client`は、`Cisco Spark REST API`を利用しやすくしたライブラリです。
基本的な機能のほかに、Cisco SparkのAPIを使いやすくするための機能を実装しています。
#### ほかの言語のREADME
* [English README](https://github.com/thrzn41/CiscoSparkAPIClient/blob/master/README.md) ([英語のREADME](https://github.com/thrzn41/CiscoSparkAPIClient/blob/master/README.md))
---
## 利用可能なプラットフォーム
* .NET Standard 1.3以降
* .NET Core 1.0以降
* .NET Framework 4.5.2以降
> 注記: 簡易Webhookサーバ機能を利用する場合は、
> .NET Stardard 2.0+, .NET Core 2.0+, .NET Framework 4.5.2+が必要です。
---
## 利用可能な機能
* Cisco Sparkの基本的なAPI(List/Get/Create Message, Spaceなど)。
* Cisco SparkのAdmin API(List/Get Event, Licenseなど)。
* ストレージに保存するTokenの暗号化と復号。
* List API用のPagination機能。
* Retry-after値の処理とRetry executor。
* Markdown builder
* エラーコードや詳細の取得。
* Webhook secretの検証とWebhook notification manager、Webhook event handler。
* OAuth2 helper
* 簡易Webhookサーバ機能(.NET Standard 2.0+, .NET Core 2.0+, .NET Framework 4.5.2+)。
### 基本機能
| Sparkのリソース名 | 利用可能な機能 | 説明 |
| :-------------------------------- | :---------------------------- | :---------------------------------- |
| Person/People | List/Get | 利用可能。Get Meも利用可能 |
| Space(Room) | List/Create/Get/Update/Delete | 利用可能。Roomは、API Clientでは、Spaceと呼ばれる。 |
| SpaceMembership(Membership) | List/Create/Get/Update/Delete | 利用可能。Membershipは、API Clientでは、SpaceMembershipと呼ばれる。 |
| Message | List/Create/Get/Delete | 利用可能。ローカルのstreamからファイル添付も可能 |
| Team | List/Create/Get/Update/Delete | 利用可能。 |
| TeamMembership | List/Create/Get/Update/Delete | 利用可能。 |
| Webhook | List/Create/Get/Update/Delete | 利用可能。 |
| File | GetInfo/GetData/Upload | 利用可能。 |
### Admin機能
| Sparkのリソース名 | 利用可能な機能 | 説明 |
| :-------------- | :---------------------------- | :---------------------------------------------- |
| Person/People | Create/Update/Delete | 利用可能。 |
| Event | List/Get | 利用可能。 |
| Organization | List/Get | 利用可能。 |
| License | List/Get | 利用可能。 |
| Role | List/Get | 利用可能。 |
### ストレージのTokenの暗号化と復号
`ProtectedString`が、Token保存時の暗号化と、読み込み時の復号の機能を提供します。
詳細は後述。
### Pagination機能
Cisco Spark APIのpaginationに関しては、[ここ](https://developer.ciscospark.com/pagination.html)を参照。
`result.HasNext`と`result.ListNextAsync()`が、Cisco Spark API Clientで利用可能です。
詳細は後述。
### Retry-Afterの取得
`result.HasRetryAfter`と `result.RetryAfter`が、Cisco Spark API Clientで利用可能です。
また、 `RetryExecutor`が利用可能です。
詳細は後述。
### HTTP Statusコードの取得
`result.HttpStatusCode`が、Cisco Spark API Clientで利用可能です。
詳細は後述。
### エラーコードと詳細の取得
Cisco Spark APIは、エラーコードと詳細を返す場合があります。
`result.Data.HasErrors`と`result.Data.GetErrors()`が、Cisco Spark API Clientで利用可能です。
### 部分エラーの取得
Cisco Spark APIは、部分的なエラーを返す場合があります。
部分エラーの詳細に関しては、[ここ](https://developer.ciscospark.com/errors.html)を参照。
`Item.HasErrors`と`Item.GetPartialErrors()`が、Cisco Spark API Clientで利用可能です。
### trackingIdの取得
trackingIdは、Cisco Spark APIのテクニカルサポートで利用される可能性があります。
`result.TrackingId`が、Cisco Spark API Clientで利用可能です。
詳細は後述。
### Validates webhook secret
`Webhook.CreateEventValidator()`が、Cisco Spark API Clientで利用可能です。
詳細は後述。
Cisco Spark API Clientの`CreateWebhookAsync()`メソッドはデフォルトでは、webhook secretを動的に生成します。
### Webhook listener(.NET Standard 2.0+, .NET Core 2.0+, .NET Framework 4.5.2+)
Webhook listener機能は、簡易的なWebhookのサーバ機能を提供します。
> **注記: この機能は、簡単なテスト時の利用を想定しています。
> 運用環境等では、より信頼性のあるサーバをご利用ください。**
`WebhookListener`が、Cisco Spark API Clientで利用可能です。
詳細は後述。
---
## 基本的な使い方
### Cisco Spark API Clientのインストール
`Cisco Spark API Client`は、以下のいずれかの方法で、`NuGet` package manager経由で入手できます。
* NuGet Package ManagerのGUI
"`Thrzn41.CiscoSpark`"を検索してインストール。
* NuGet Package ManagerのCLI
```
PM> Install-Package Thrzn41.CiscoSpark
```
* .NET Client
```
> dotnet add package Thrzn41.CiscoSpark
```
### Cisco Spark API Client関連のusingディレクティブ
usingディレクティブを利用する場合は、以下の名前空間を指定します。
``` csharp
using Thrzn41.Util
using Thrzn41.CiscoSpark
using Thrzn41.CiscoSpark.Version1
```
必要に応じて、`Thrzn41.CiscoSpark.Version1.Admin`も利用可能です。
### Cisco Spark API Clientインスタンスの作成
Cisco Spark API Clientのインスタンスは可能な限り長い期間使いまわすようにします。
``` csharp
/// 基本API利用時。
SparkAPIClient spark = SparkAPI.CreateVersion1Client(token);
```
Admin APIを利用する場合は、Admin API用のインスタンスを作成する必要があります。
`SparkAdminAPIClient`は、`SparkAPIClient`の全機能に加えて、Adminの機能が利用できます。
``` csharp
/// Admin API利用時。
SparkAdminAPIClient spark = SparkAPI.CreateVersion1AdminClient(token);
```
> **注記: 'token'は、Cisco Spark APIでは、非常にセンシティブな情報です。
> 'token'は、慎重に保護する必要があります。
> ソースコード中に直接記載したり、安全ではない方法で保存しないようにします。
> `Cisco Spark 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をストレージから読み込んで、Cisco Spark API Clientのインスタンスを作成する
``` csharp
byte[] encryptedData = Load("token.dat");
byte[] entropy = Load("entropy.dat");
var protectedToken = LocalProtectedString.FromEncryptedData(encryptedData, entropy);
/// 基本API利用時。
SparkAPIClient spark = SparkAPI.CreateVersion1Client(protectedToken);
```
> **注記: オプションに応じて、暗号化されたデータは、暗号化したときと同じローカルユーザまたはローカルマシン上でのみ復号できます。**
### Cisco Sparkのスペースにメッセージを投稿する
``` csharp
var result = await spark.CreateMessageAsync("xyz_space_id", "こんにちは, Spark!");
if(result.IsSuccessStatus)
{
Console.WriteLine("メッセージが投稿されました: id = {0}", result.Data.Id);
}
```
### 成功, 失敗, エラーのハンドリング
`result.IsSuccessStatus`を使って成功したかどうか確認できます。
`result.Data.HasErrors`や`result.Data.GetErrorMessage()`を使ってCisco Spark APIサービスからエラーコード、エラーメッセージを受け取ることができます。
``` csharp
var result = await spark.CreateMessageAsync("xyz_space_id", "こんにちは, Spark!");
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()`は、リクエスト失敗時に`SparkResultException`をスローします。
(一方、`result.Data`は、`SparkResultException`を送出しません。)
``` csharp
try
{
var result = await spark.CreateMessageAsync("xyz_space_id", "こんにちは, Spark!");
var message = result.GetData();
Console.WriteLine("メッセージが投稿されました: id = {0}", message.Id);
}
catch(SparkResultException sre)
{
Console.WriteLine("メッセージの投稿に失敗しました: status = {0}, trackingId = {1}, description = {2}",
sre.HttpStatusCode, sre.TrackingId, sre.Message);
}
```
### Cisco Sparkのスペースに添付ファイル付きでメッセージを投稿する
``` csharp
using (var fs = new FileStream("path/myfile.png", FileMode.Open, FileAccess.Read, FileShare.Read))
using (var data = new SparkFileData(fs, "imagefile.png", SparkMediaType.ImagePNG))
{
var result = await spark.CreateMessageAsync("xyz_space_id", "添付ファイル付き", data);
if(result.IsSuccessStatus)
{
Console.WriteLine("添付ファイル付きでメッセージが投稿されました: id = {0}", result.Data.Id);
}
}
```
### Cisco Sparkの1:1スペースにメッセージを投稿する
``` csharp
var result = await spark.CreateDirectMessageAsync("targetuser@example.com", "こんにちは, Spark!");
if(result.IsSuccessStatus)
{
Console.WriteLine("メッセージが投稿されました: id = {0}", result.Data.Id);
}
```
### スペースの一覧を取得する
``` csharp
var result = await spark.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 spark.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);
}
```
ファイルをダウンロードする。
``` csharp
var result = await spark.GetFileDataAsync(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);
using(var stream = file.Stream)
{
// streamにファイルのデータが含まれる。
}
}
```
### Pagenation機能を利用する
``` csharp
var result = await spark.ListSpacesAsync();
if(result.IsSuccessStatus)
{
//
// ここで何か処理する...
//
if(result.HasNext)
{
// 続きのリストがあれば取得する。
result = await result.ListNextAsync();
if(result.IsSuccessStatus)
{
// ...
}
}
}
```
### Http status codeを取得する
``` csharp
var result = await spark.ListSpacesAsync();
Console.WriteLine("Status is {0}", result.HttpStatusCode);
```
### Retry afterを取得する.
``` csharp
var result = await spark.ListSpacesAsync();
if(result.IsSuccessStatus)
{
//
// ここで何かする...
//
}
else if(result.HasRetryAfter)
{
Console.WriteLine("{0}後にリトライしなきゃ!!", result.RetryAfter.Delta);
}
```
### Retry Executor
`RetryExecutor`を利用してリトライ処理を容易にします。
``` csharp
// RetryExecutor.Oneは最大で1回のリトライを試みます。
var result = RetryExecutor.One.ListAsync(
() =>
{
// このメソッドは必要に応じて、リトライされます。
return spark.ListSpacesAsync();
},
(r, retryCount) =>
{
// ここは、リトライが実行される前に呼び出されます。
// ここでリトライ時のログの出力等の処理が可能です。
Log.Info("Retry is required: delta = {0}, counter = {1}", r.RetryAfter.Delta, retryCount);
// 'true'を返すとリトライが実行されます。
return true;
}
);
```
### TrackingIdを取得する
``` csharp
var result = await spark.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 spark.CreateMessageAsync("xyz_space_id", md.ToString());
```
### Webhookに通知されたデータを検証する
``` csharp
var webhook = await spark.GetWebhookAsync("xyz_webhook_id");
var validator = webhook.CreateEventValidator();
```
イベントがWebhookのURIに通知された際には、
x-Spark-Signatureがハッシュ値を持っています。
validatorを利用して、データの整合性を確認できます。
``` csharp
byte[] webhookEventData = GetWebhookEventData();
if( validator.Validate(webhookEventData, "xyz_x_spark_signature_value") )
{
Console.WriteLine("通知されたイベントデータの検証に成功!");
}
```
### Webhookの通知管理
Webhook notification managerを使ってWebhookへの通知を管理します。
* インスタンスを作成する。
``` csharp
var notificationManager = new WebhookNotificationManager();
```
* 通知用のfunctionを登録します。
``` csharp
var webhook = await spark.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_spark_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 spark.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.Resouce == EventResouce.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 spark.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.Resouce == EventResouce.Message)
{
Console.WriteLine("Message, id = {0}", eventData.MessageData.Id);
}
}
);
```
* Listenerの開始。
Listenerを開始すると、イベント発生時に登録したfunctionに通知されます。
``` csharp
listener.Start();
```