記事公開日
最終更新日
Teams データを取得してみた(1)

第1回 | Teams データを取得してみた(1) | Teams API利用のための基本設定やプログラム(C#)からのチャネルメッセージの取得等を試しています。 |
第2回 | Teams データを取得してみた(2) | チャネルメッセージ、リプライメッセージやリアクション情報の取得や解析を試しています。 |
第3回 | Teams データを取得してみた(3) | Teamsに登録されたファイルの一覧の取得を試しています。 |
番外編 | Power Platform で Teams データを取得してみた | Power Platformでデータ取得を試しています。 |
Teamsを使用していると、そのデータを活用してみたいという要望は、少なからずあると思います。活用方法は、いろいろあると思いますが、今回は、Teams APIを使用してどのようなことができるかを試してみます。
Teams APIとは?
Teams APIは、Microsoft Graph API で実装されている APIになります。概要については、公式ページをご確認ください。
Teams API の概要
Teams APIでは、チームの情報を得るだけでなく、チャネルへの投稿を取得する、チャットメッセージを送信するなど、様々なアクションを実現できます。
それ、Power Platform で簡単にできるじゃんという突っ込みがあるかもしれませんが、あえてプログラムからの操作を試してみます、という位置づけで見て頂ければと思います。
権限さえあれば、プライベートなチャットメッセージでさえも取得できてしまうことは、理解しておくと良いかもしれません。といっても、今回は私的チャットを覗くような操作は行いません。機密的な情報を取得するには、それなりの権限が必要になってきますし、、、
まずは、ユーザー自身が参加しているチームの一覧を取得する [joinedTeams] を試してみます。
GET /users/{id | user-principal-name}/joinedTeams
2種類の問い合わせがありますが、ログインユーザー自身の参加しているチームを確認するには、[me/joinedTeamd] で取得できます。
プログラムを作らずに手っ取り早く Teams API を試すのであれば、Graph Explorer を使用すると便利です。
プログラム実装前に、APIの戻り値の確認するなどに利用できます。
(Teams APIに限らず、Microsoft Graph API全般に使用できます。 )
右上のアイコンから、サインインします。

サインインができたら、
※アクセス許可が無い場合は、以下のようなエラーが返ることがあります。
アクセス許可の修正で、必要な権限に同意をしてみてください。
{ "error": { "code": "Forbidden", "message": "Missing scope permissions on the request. API requires one of 'Team.ReadBasic.All, TeamSettings.Read.All, TeamSettings.ReadWrite.All, User.Read.All, Directory.Read.All, User.ReadWrite.All, Directory.ReadWrite.All'. Scopes on the request 'Files.Read.All, openid, profile, Sites.Read.All, email, User.Read'", "innerError": { "date": "2022-07-25T10:20:42", "request-id": "5a0f70c5-8eb5-481e-accb-32b20fb36488", "client-request-id": "c53debae-a9a9-c88f-aef5-f2f452bae185" } } }
上記エラーメッセージにも、必要な権限が記載されていますが、
[joinedTeams] の仕様ページに記載されている「アクセス許可」の項目を見ると一番弱い権限で [Team.ReadBasic.All] のようです。
同意していないようでしたら、同意してから再度試してみます。
画面下部に、チーム名等の情報が取得できれば成功です。
アクセス許可を同意すれば、何でもデータを取得できるというわけではありません。
重要度の高い情報へのアクセスは、管理者の同意が必要となりますし、機密データとされる情報にアクセスするAPIは、「保護されたAPI」として Microsoft社への申請が必要となってきます。
全てのチャネルのメッセージ取得する強力なAPI(channel: getAllMessages)も用意されていますが、膨大なデータ取得になりそうです。
⇒ 保護されたAPIとは
プログラムから Teams APIを呼び出す
単発のAPI実行であれば、Graph Explorer は便利です。連続したデータ取得や、取得したデータをもとに別のAPIを呼び出すといったような操作には不便です。その場合は、プログラムからの呼び出した方が楽でしょう。Teams APIは、様々なプログラム言語から呼び出すことができますが、C# から試してみます。API呼び出しの準備
Azure系の認証まわりの処理を実装したことがある人には、お馴染みの Azure ADのアプリ登録が必要になってきます。ここでは、詳細な手順は記載しませんが、以下の流れでアプリ登録をします。
Graph Explorer のところでも説明した通り、
joinedTeams を呼び出すには、最低でも Microsoft.Graph の [Team.ReadBasic.All] が必要になりますので、
こちらの権限を付与します。付与した後は、管理者の同意も与えておきます。
※今回は、ログインユーザーの権限でアクセスするため「委任されたアクセス許可」の権限を付与しています。

プログラムの作成
任意の Visual Studio を使用し、C#コンソールアプリを作成します。続けて、NuGetパッケージの管理から、[Azure.Identity] と [Microsoft.Graph] をインストールします。
Graph APIへのアクセスは、GraphServiceClient を用います。API仕様に近い形で、使用できます。
↓
graphClient.Me.JoinedTeams
今回用意したテストユーザーの「テスト太郎」は、以下の3つのチームに参加しています。

以下のようなコードを入力し、実行します。テナント情報やユーザー情報は、環境に合わせて修正します。
実際の業務プログラムでは、ID/パスワードを含めこのようにベタ書きすることはありませんが、以下の例はサンプルとして実行するためのものです。
※本実装の際には、ID/パスワードを入力するインターフェースを用意するか、アプリケーションの許可による権限で対応してください。
using System; using System.Threading.Tasks; using Azure.Identity; using Microsoft.Graph; namespace SampleTeamsAPI { class Program { static async Task Main(string[] args) { var scopes = new[] { "User.Read" }; var tenantId = "あなたのテナントID"; var clientId = "あなたのクライアントID"; // using Azure.Identity; var options = new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud }; var userName = "ログオンユーザ"; var password = "パスワード"; // https://docs.microsoft.com/dotnet/api/azure.identity.usernamepasswordcredential var userNamePasswordCredential = new UsernamePasswordCredential( userName, password, tenantId, clientId, options); var graphClient = new GraphServiceClient(userNamePasswordCredential, scopes); var teams = await graphClient.Me.JoinedTeams.Request().GetAsync(); foreach (var team in teams) { Console.WriteLine($"team-id:{team.Id} チーム名:{team.DisplayName}"); } } } }
参加している3つのチーム情報が取得できました。

チャネルのメッセージを取得してみる
C# からの Teams APIへの基本アクセスができましたので、チャネルメッセージの取得をしてみます。チャネルメッセージの取得は、以下のAPIを呼び出すことで取得できそうです。
⇒ messages
アクセス許可を見ると、[ChannelMessage.Read.All] 権限が必要で、呼び出し仕様は以下のように記載されています。
チーム ⇒ チャネル ⇒ メッセージ
の階層構造になっています。
{team-id] は、joinedTeams で取得したチームのIDが使えそうですが、{channel-id} は・・・?
先にチャネルの一覧を取得した方が良さそうです。
チャネルの一覧表示は、以下のAPIで取得できます。
⇒ channels
同様にアクセス許可を見ると、[Channel.ReadBasic.All] 権限で必要で、呼び出し仕様は、以下の通りでした。
※[ChannelMessage.Read.All] は、管理者の同意が必要なアクセス許可です。
チーム情報を取得するループ部分を以下のように修正して、実行します。
メッセージ部分は、投稿日時とメッセージ本体を取得しています。
var teams = await graphClient.Me.JoinedTeams.Request().GetAsync(); foreach (var team in teams) { Console.WriteLine($"team-id:{team.Id} チーム名:{team.DisplayName}"); var channels = await graphClient.Teams[team.Id].Channels.Request().GetAsync(); foreach (var channel in channels) { Console.WriteLine($" channel-id:{channel.Id} チャネル名:{channel.DisplayName}"); var messages = await graphClient.Teams[team.Id].Channels[channel.Id].Messages.Request().GetAsync(); foreach (var message in messages) { Console.WriteLine($"{message.CreatedDateTime}"); Console.WriteLine($"{message.Body.Content}"); Console.WriteLine("---"); } } }取得できました!!

※チャネル名が General と表示されているものは、日本語では「一般」と表示されるデフォルトのチャネルになります。
もし、取得したいチャネルが特定できているのであれば、ループせずに以下のように指定できます。
毎回全ての参加チーム&チャネルを検索せず、特定のチャネルを監視するなどの場合は、チームやチャネルを狙い撃ちで取得します。
string teamId = "{team-id}"; string channelId = "{channel-id}"; var messages = await graphClient.Teams[teamId].Channels[channelId].Messages.Request().GetAsync();では、このチームに参加していない別のユーザーでアクセスした場合にどうなるか試してみます。
foreach (var message in messages) { Console.WriteLine($"{message.CreatedDateTime}"); Console.WriteLine($"{message.Body.Content}"); Console.WriteLine("---"); }
「Private_Taro」チームには、以下のメンバーが登録されています。
・テスト太郎
・テスト四郎
・テスト五郎

メンバーでは無い「テスト次郎」で試してみます。
参加していないチームなので「テスト次郎」で joinedTeams を実行しても、チーム情報を取得できません。
そのため「テスト太郎」で取得した、team-id を使用して無理やり呼び出してみます。
プログラムを修正して実行してみると、ちゃんとエラーになりました。

会社の Teams に対して、アプリケーションの許可権限で保護されたAPIも含めてアクセスさせてくれと頼んだ場合、多くの企業ではおそらく拒否されるでしょう。組織が大きくなればなるほど、ハードルが上がりそうです。
まずは、ユーザー自身の権限でのアクセスするところから始めてみると良さそうです。
(とはいえ、管理者の同意が必要な権限を使用する場合は、管理者の同意処理が必要になりますけど、、、)
今回は、Teams APIの初歩を試してみました。チャネルのメッセージも取得できましたが、メッセージ中に [<systemEventMessage/>] と出ていたり、HTMLタグのメッセージがあったりしました。
他にもいろいろな情報が含まれていますが、次回以降で、もう少し深追いしてみます。
次回の記事は、こちら ⇒ Teams データを取得してみた(2)
最後に
本記事は、ローコードでは無い話になっておりますが、弊社は現在、Power Platform関連ソリューションに力を入れており、
この度、「マイクロソフト ジャパン パートナー オブ ザ イヤー 2022 」におけるBusiness Applications・Power Apps アワードを受賞致しました!!!
(※ちゃんと、コードをゴリゴリ書く部隊も在籍しておりますので、Power Platform だけでは手の届かない細かい対応もできます。)
弊社が提供するPower Platform関連のソリューションに関しては、こちらをご覧ください。

QESでは様々なアプリケーションの開発・導入を行っております。
私共が提供するサービス・ソリューションにつきましてはこちらに掲載しております。
システム開発・構築でお困りの問題や弊社が提供するサービス・ソリューションにご興味を抱かれましたら、是非一度お問い合わせください。
その他の技術ブログについてはこちら
QESではクラウドエンジニアを募集しております。
※このブログで参照されている、Microsoft、Windows、Azure、PowerApps、Application Insightsその他のマイクロソフト製品およびサービスは、米国およびその他の国におけるマイクロソフトの商標または登録商標です。