目次
概要
GraphAPIを使ってTeamsのカレンダー登録・一覧の方法を解説します。
はじめに
仕事でTeamsのチャットボットを作成する機会があったので、その整理をするために今回記事にしました。
作成したチャットボットでは、
GraphAPIを使用して、
カレンダーから指定した日の予定を取得してチャット上に表示したり、
ユーザがチャットで発話した日時にカレンダーをセットするということを実装しました。
その際、GraphAPIを使用するのは初めてで調べながら実装しました。
MicroSoftにドキュメントはたくさん載っているのですが、
逆に多すぎて、どこを見ていいか、どう実装したらよいのか分かりずらくなっており調べるのに時間がかかりました。
なので、今回は簡単にカレンダーの取得・登録にフォーカスして簡単に解説したいと思います。
アーキテクチャ
Node.js等で実装されたWebアプリのChatBotAppを想定し、
requestなどのライブラリを使用して、
RestAPI方式でGraphAPIにリクエストを送信します。
APIにリクエストを送信する流れとしては、以下になります。
-
トークン取得(https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token)
GraphAPIにアクセスするためのトークンを取得します。
事前に登録したAzureのテナントIDとGraphAPIのIDとシークレットキーをPostします。 -
ユーザ情報取得(https://graph.microsoft.com/v1.0/users/${mail})
ユーザのメールアドレスから登録に使用するためのユーザIDを取得します。 -
カレンダー取得(https://graph.microsoft.com/v1.0/users/${userId}/calendarView)
ユーザIDをもとに指定された開始終了日時間のスケジュール一覧を取得します。 -
カレンダー登録(https://graph.microsoft.com/v1.0/users/${userId}/calendar/events)
タイトルや開始終了時間に加え、参加者や概要などをPostして、Outlookのカレンダーに予定を登録します。
トークンとユーザIDを取得して、カレンダーの取得・登録をします。
IDの確認
GraphAPIを使用するためには、
事前にAzureにログインしGraphAPIを使えるように登録しておく必要があります。
登録方法については、今回割愛させていただきます。
登録したら、テナントID、クライアントID、シークレットキーをメモしておきます。
テナントID
クライアントID
シークレットキー
API
それぞれのAPIをたたいていきます。
APIをたたくためには、
トークンが必要になりますので、
まずは、トークン取得から説明していきます。
トークン取得
リクエスト
{ url: `https://login.microsoftonline.com/${テナントID headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, form: { grant_type: 'client_credentials', client_id: クライアントID, client_secret: シークレットキー, scope: 'https://graph.microsoft.com/.default', response_type: 'code', }, json: true, }
レスポンス
{ "token_type": "Bearer", "expires_in": 3599, "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBP..." }
ユーザ情報取得
メールアドレスからユーザIDを取得します。
レスポンスの「id」がユーザIDになります。
リクエスト
{ url: <code>https://graph.microsoft.com/v1.0/users/${メール@アドレス}</code>, headers: { Authorization: Bearer ${accessToken}, }, json: true }
レスポンス
{ "businessPhones": [ "businessPhones-value" ], "displayName": "displayName-value", "givenName": "givenName-value", "jobTitle": "jobTitle-value", "mail": "mail-value", "mobilePhone": "mobilePhone-value", "officeLocation": "officeLocation-value", "preferredLanguage": "preferredLanguage-value", "surname": "surname-value", "userPrincipalName": "userPrincipalName-value", "id": "id-value" }
カレンダー取得
開始日時、終了日時、ユーザIDを指定してOutlookのカレンダーから予定を取得します。
時間範囲の開始日時は、ISO 8601 形式で表されます。例: "2019-11-08T19:00:00-08:00"
リクエスト
{ url:https://graph.microsoft.com/v1.0/users/${ユーザID}/calendarView?startDateTime=${startDatetime}&endDateTime=${endDatetime , headers: { Authorization: Bearer ${accessToken}, }, json: true, }
レスポンス
{ "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups('02bd9fd6-8f93-4758-87c3-1fb73740a315')/calendarView", "@odata.nextLink":"https://graph.microsoft.com/v1.0/groups/02bd9fd6-8f93-4758-87c3-1fb73740a315/calendarView?startDateTime=2017-01-01T19%3a00%3a00.0000000&endDateTime=2017-10-01T19%3a00%3a00.00&$skip=10", "value":[ { "@odata.etag":"W/\"xPZF2y46pEiVBni87OnrpgAAFq78Xw==\"", "id":"AAMkAGI5MWYJOwAAEA==", "createdDateTime":"2017-07-31T18:59:01.982289Z", "lastModifiedDateTime":"2017-09-06T04:29:38.6647687Z", "changeKey":"xPZF2y46pEiVBni87OnrpgAAFq78Xw==", "categories":[ ], "originalStartTimeZone":"Eastern Standard Time", "originalEndTimeZone":"Eastern Standard Time", "iCalUId":"040000008200E00074C5B7101A82E00807E1080E824DDB122F0AD301000000000000000010000000824A8905B038D54AA7735F117B3442ED", "reminderMinutesBeforeStart":15, "isReminderOn":true, "hasAttachments":false, "subject":"New Training Plans", "bodyPreview":"Meeting to plan new trainings.\r\n\r\n\r\n\r\nJoin Microsoft Teams Online Meeting<https://teams.microsoft.com/l/meetup-join/19%3a900876baa3134907b0dcb41a0d220e31%40thread.skype/1501527539926?tenantId=dcd219dd-bc68-4b9b-bf0b-4a33a796be35>", "importance":"normal", "sensitivity":"normal", "isAllDay":false, "isCancelled":false, "isOrganizer":true, "responseRequested":true, "seriesMasterId":null, "showAs":"busy", "type":"singleInstance", "webLink":"https://outlook.office365.com/owa/?itemid=AAMkAGI5MWYJOwAAEA%3D%3D&exvsurl=1&path=/calendar/item", "onlineMeetingUrl":null, "responseStatus":{ "response":"organizer", "time":"0001-01-01T00:00:00Z" }, "body":{ "contentType":"text", "content":"Meeting to plan new trainings.\r\n\r\n\r\n\r\nJoin Microsoft Teams Online Meeting<https://teams.microsoft.com/l/meetup-join/19%3a900876baa3134907b0dcb41a0d220e31%40thread.skype/1501527539926?tenantId=dcd219dd-bc68-4b9b-bf0b-4a33a796be35>\r\n" }, "start":{ "dateTime":"2017-08-14T21:00:00.0000000", "timeZone":"UTC" }, "end":{ "dateTime":"2017-08-14T22:00:00.0000000", "timeZone":"UTC" }, "location":{ "displayName":"HR Taskforce / Facilities" }, "recurrence":null, "attendees":[ { "type":"required", "status":{ "response":"none", "time":"0001-01-01T00:00:00Z" }, "emailAddress":{ "name":"HR Taskforce", "address":"HRTaskforce@contoso.onmicrosoft.com" } }, { "type":"required", "status":{ "response":"none", "time":"0001-01-01T00:00:00Z" }, "emailAddress":{ "name":"Megan Bowen", "address":"MeganB@contoso.onmicrosoft.com" } } ], "organizer":{ "emailAddress":{ "name":"HR Taskforce", "address":"HRTaskforce@contoso.onmicrosoft.com" } } }, { "@odata.etag":"W/\"xPZF2y46pEiVBni87OnrpgAAFq78Xw==\"", "id":"AAMkAGI5MWYJOwAAEA==", "createdDateTime":"2017-07-31T18:59:01.982289Z", "lastModifiedDateTime":"2017-09-06T04:29:38.6647687Z", "changeKey":"xPZF2y46pEiVBni87OnrpgAAFq78Xw==", "categories":[ ], "originalStartTimeZone":"Eastern Standard Time", "originalEndTimeZone":"Eastern Standard Time", "iCalUId":"040000008200E00074C5B7101A82E00807E10810824DDB122F0AD301000000000000000010000000824A8905B038D54AA7735F117B3442ED", "reminderMinutesBeforeStart":15, "isReminderOn":true, "hasAttachments":false, "subject":"New Training Plans", "bodyPreview":"Follow-up meeting to plan new trainings.\r\n\r\n\r\n\r\nJoin Microsoft Teams Online Meeting<https://teams.microsoft.com/l/meetup-join/19%3a900876baa3134907b0dcb41a0d220e31%40thread.skype/1501527539926?tenantId=dcd219dd-bc68-4b9b-bf0b-4a33a796be35>", "importance":"normal", "sensitivity":"normal", "isAllDay":false, "isCancelled":false, "isOrganizer":true, "responseRequested":true, "seriesMasterId":null, "showAs":"busy", "type":"singleInstance", "webLink":"https://outlook.office365.com/owa/?itemid=AAMkAGI5MWYJOwAAEA%3D%3D&exvsurl=1&path=/calendar/item", "onlineMeetingUrl":null, "responseStatus":{ "response":"organizer", "time":"0001-01-01T00:00:00Z" }, "body":{ "contentType":"text", "content":"Meeting to plan new trainings.\r\n\r\n\r\n\r\nJoin Microsoft Teams Online Meeting<https://teams.microsoft.com/l/meetup-join/19%3a900876baa3134907b0dcb41a0d220e31%40thread.skype/1501527539926?tenantId=dcd219dd-bc68-4b9b-bf0b-4a33a796be35>\r\n" }, "start":{ "dateTime":"2017-08-16T21:00:00.0000000", "timeZone":"UTC" }, "end":{ "dateTime":"2017-08-16T22:00:00.0000000", "timeZone":"UTC" }, "location":{ "displayName":"HR Taskforce / Facilities" }, "recurrence":null, "attendees":[ { "type":"required", "status":{ "response":"none", "time":"0001-01-01T00:00:00Z" }, "emailAddress":{ "name":"HR Taskforce", "address":"HRTaskforce@contoso.onmicrosoft.com" } }, { "type":"required", "status":{ "response":"none", "time":"0001-01-01T00:00:00Z" }, "emailAddress":{ "name":"Megan Bowen", "address":"MeganB@contoso.onmicrosoft.com" } } ], "organizer":{ "emailAddress":{ "name":"HR Taskforce", "address":"HRTaskforce@contoso.onmicrosoft.com" } } } ] }
カレンダー登録
ユーザID、タイトル、開始終了時間を指定してカレンダーを登録します。
リクエスト
{ url:https://graph.microsoft.com/v1.0/users/${ユーザID}/calendar/events, headers: { Authorization: Bearer ${accessToken}, }, subject: "Lets go for lunch", body: { contentType: "HTML", content: "Does late morning work for you?" }, start: { dateTime: "2019-06-16T12:00:00", timeZone: "Pacific Standard Time" }, end: { dateTime: "2019-06-16T14:00:00", timeZone: "Pacific Standard Time" }, location:{ displayName:"Harrys Bar" }, attendees: [ { emailAddress: { "address:adelev@contoso.onmicrosoft.com", name: "Adele Vance" }, type: "required" } ] }
レスポンス
{ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups('01d4ee64-15ce-491e-bad1-b91aa3223df4')/events/$entity", "@odata.etag": "W/\"Na8DfbsBGUG8JeyvlwNi5wAAHMK0vA==\"", "id": "AAMkADZlEZQbwl7K_XA2LnAAAcwiSBAAA=ZQbwl7K_XA2LnAAAcwiSDAAA=", "createdDateTime": "2019-05-20T02:20:45.3057043Z", "lastModifiedDateTime": "2019-05-20T02:20:45.5639203Z", "changeKey": "Na8DfbsBGUG8JeyvlwNi5wAAHMK0vA==", "categories": [], "originalStartTimeZone": "Pacific Standard Time", "originalEndTimeZone": "Pacific Standard Time", "iCalUId": "040000008200E00074C5B7101A82E008000000005D5775A1B20ED50100000000000000001000000072FA001DBB385A45B6AE65DB0E356105", "reminderMinutesBeforeStart": 15, "isReminderOn": true, "hasAttachments": false, "subject": "Let's go for lunch", "bodyPreview": "Does late morning work for you?", "importance": "normal", "sensitivity": "normal", "isAllDay": false, "isCancelled": false, "isOrganizer": true, "responseRequested": true, "seriesMasterId": null, "showAs": "busy", "type": "singleInstance", "webLink": "https://outlook.office365.com/owa/?itemid=AAMkADZN9uwEZQbwl7K%2BXA2LnAAAAAAENAAA1rwN9uwEZQbwl7K%2BXA2LnAAAcwiSDAAA%3D&exvsurl=1&path=/calendar/item", "onlineMeetingUrl": null, "recurrence": null, "responseStatus": { "response": "organizer", "time": "0001-01-01T00:00:00Z" }, "body": { "contentType": "html", "content": "<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta content=\"text/html; charset=us-ascii\">\r\n</head>\r\n<body>\r\nDoes late morning work for you?\r\n</body>\r\n</html>\r\n" }, "start": { "dateTime": "2019-06-16T12:00:00.0000000", "timeZone": "Pacific Standard Time" }, "end": { "dateTime": "2019-06-16T14:00:00.0000000", "timeZone": "Pacific Standard Time" }, "location": { "displayName": "Harry's Bar", "locationType": "default", "uniqueId": "Harry's Bar", "uniqueIdType": "private" }, "locations": [ { "displayName": "Harry's Bar", "locationType": "default", "uniqueId": "Harry's Bar", "uniqueIdType": "private" } ], "attendees": [ { "type": "required", "status": { "response": "none", "time": "0001-01-01T00:00:00Z" }, "emailAddress": { "name": "Adele Vance", "address": "adelev@contoso.onmicrosoft.com" } } ], "organizer": { "emailAddress": { "name": "Retail", "address": "Retail@contoso.onmicrosoft.com" } } }
おわりに
GraphAPIを使ってのカレンダーの取得・登録を解説しました。
Azureは、あまり好きじゃないです。