LINEBOTからGoogleカレンダーを取得する
完成物
「スケジュール教えて!」って言ったら,今日から1週間のイベントを教える
が完成しました.
厳密には「スケジュール」だけで教えてくれるようになりましたが,細かいことは気にしない!
スケジュールがある時の動作が↓
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ついに、曜ちゃんがスケジュールを教えてくれる様になりました <a href="https://t.co/bxS3ZUPl0w">pic.twitter.com/bxS3ZUPl0w</a></p>— ルナ・チェバリー (@Luna_Chevalier) <a href="https://twitter.com/Luna_Chevalier/status/953854171546988544?ref_src=twsrc^tfw">2018年1月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ない時の動作が↓です.
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">予定がない時もきっちり教えてくれます <a href="https://t.co/9wFgNrabbw">pic.twitter.com/9wFgNrabbw</a></p>— ルナ・チェバリー (@Luna_Chevalier) <a href="https://twitter.com/Luna_Chevalier/status/953854534643736576?ref_src=twsrc^tfw">2018年1月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ちなみに,「スケジュール」ではなくても,文字ならランダムで何か返事してくれます.
開発環境
- Ruby(2.4.1)
- google-api-client(0.13.6)
- line-bot-api(1.2.0)
- Sinatra(2.0.0)
- Apache(2.4.6)
- passenger(5.1.8)
主なお話
Google周りの設定が中心です.
現在の実装完了機能
- 文字を送信したら,ランダムで何か返事してくれる
- 「スケジュール」と送信したら,今日から1週間のスケジュールを教えてくれる←new!
- ベースはGoogleカレンダー
今回の作業
Googleカレンダーからスケジュール取得
今回はプライベートのカレンダーから取得するので,まずは認証してそれに成功してからスケジュールを取得しに行きます.
サービスアカウントの作成
Google APIsで,下準備を行います.
右側の認証情報に移動して,「認証情報を作成」ボタンから作成します.
投稿時点では
- APIキー
- OAuthクライアントID
- サービスアカウントキー
の3種類がありますが,今回はサービスアカウントキーを使って認証情報を作成しました.
サービスアカウントの「新しいサービスアカウント」を選択して,「サービスアカウント名」と「役割」を設定しました.
「サービスアカウント名」 はわかりやすければなんでも大丈夫です.
「役割」 は初回のサービスアカウントキーを作成したので,「Project」の「オーナー」にしました.
「サービスアカウントID」 は勝手に入力されるので,今は特に何もしなくても大丈夫です.
「キーのタイプ」 は自分が扱い慣れているJSONにして,いざ作成!
無事に成功したら,認証情報に移動すると「サービスアカウントキー」の欄に作成したキーが表示されています.
このファイルを使って取得するので,ファイルはダウンロードしておきましょう.
サービスアカウントとGoogleカレンダーの連携
さっき作ったサービスアカウントはその名の通り「アカウント」でしか無いので,まだカレンダーの情報を取得できません.
「サービスアカウントID」を取得したい非公開のGoogleカレンダーに連携させる必要があります.
「サービスアカウントの管理」に移動すると,さっき作成した「サービスアカウントID」があるので,これをメモ帳か何かにコピペしておきます.
次にブラウザからGoogleカレンダーを開いて,設定画面を開きます.
左側にある「マイカレンダーの設定」の自分のユーザー名を開くと,「特定のユーザーとの共有」という欄があるので,さっきコピペしたIDを追加します.
権限は「閲覧権限(すべての予定の詳細)」に設定しました.
これで,取得できるようになりました.
実際に取得する
ここまでくれば,ダウンロードしたファイルを使って実際に取得する処理を書けば終わりです.
require 'google/apis/calendar_v3'
require 'googleauth'
require 'fileutils'
require 'json'
APPLICATION_NAME = 'GOOGLE_CALENDAR_EXAMPLE'
MY_CALENDAR_ID = 'さっき連携したカレンダーID'
CLIENT_SECRET_PATH = 'ダウンロードしたJSONファイルのパス'
class Calendar
def initialize
@service = Google::Apis::CalendarV3::CalendarService.new
@service.client_options.application_name = APPLICATION_NAME
@service.authorization = authorize
@calendar_id = MY_CALENDAR_ID
end
def authorize
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: File.open(CLIENT_SECRET_PATH),
scope: Google::Apis::CalendarV3::AUTH_CALENDAR)
authorizer.fetch_access_token!
authorizer
end
# 実際にスケジュールを取得するメソッド
# 今から丁度1週間後までのスケジュールを取ってくれる
def get_schedule(time_min = Time.now.iso8601, time_max = (Time.now + 24*60*60*7*0).iso8601, max_results = 256)
response = @service.list_events(@calendar_id,
max_results: max_results,
single_events: true,
order_by: 'startTime',
time_min: Time.now.iso8601)
response.items
end
end
↑がスケジュールを取得するソースです.
Calendar
のインスタンスを生成してget_schedule
を呼び出せば,スケジュールを取得できます.
LINEBOTに処理を追加する
↑の動作確認が完了したら,後はLINEBOTにこの処理を組み込むだけ!
今回は「スケジュール」と言ったときに教える様にするため,その時に取得するようにしました.
今後の予定
当日にイベントがあったら,朝にそれを教える機能を実装しようと思います.
GASを利用して,設定したURLにPOSTすれば実装できるかなと思ってますが・・・
しかし,ルート設定されたファイルとクラスが混在して混沌としているので,先にリファクタリングですね・・・
Discussion