🔖

LINEBOTからGoogleカレンダーを取得する

2020/09/22に公開

完成物

前回の投稿

「スケジュール教えて!」って言ったら,今日から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>

ちなみに,「スケジュール」ではなくても,文字ならランダムで何か返事してくれます.

開発環境

主なお話

Google周りの設定が中心です.

現在の実装完了機能

  • 文字を送信したら,ランダムで何か返事してくれる
  • 「スケジュール」と送信したら,今日から1週間のスケジュールを教えてくれる←new!
    • ベースはGoogleカレンダー

今回の作業

Googleカレンダーからスケジュール取得

今回はプライベートのカレンダーから取得するので,まずは認証してそれに成功してからスケジュールを取得しに行きます.

サービスアカウントの作成

Google APIsで,下準備を行います.
右側の認証情報に移動して,「認証情報を作成」ボタンから作成します.
投稿時点では

  • APIキー
  • OAuthクライアントID
  • サービスアカウントキー

の3種類がありますが,今回はサービスアカウントキーを使って認証情報を作成しました.
サービスアカウントの「新しいサービスアカウント」を選択して,「サービスアカウント名」と「役割」を設定しました.
「サービスアカウント名」 はわかりやすければなんでも大丈夫です.
「役割」 は初回のサービスアカウントキーを作成したので,「Project」の「オーナー」にしました.
「サービスアカウントID」 は勝手に入力されるので,今は特に何もしなくても大丈夫です.
「キーのタイプ」 は自分が扱い慣れているJSONにして,いざ作成!
無事に成功したら,認証情報に移動すると「サービスアカウントキー」の欄に作成したキーが表示されています.
このファイルを使って取得するので,ファイルはダウンロードしておきましょう.

サービスアカウントとGoogleカレンダーの連携

さっき作ったサービスアカウントはその名の通り「アカウント」でしか無いので,まだカレンダーの情報を取得できません.
「サービスアカウントID」を取得したい非公開のGoogleカレンダーに連携させる必要があります.
「サービスアカウントの管理」に移動すると,さっき作成した「サービスアカウントID」があるので,これをメモ帳か何かにコピペしておきます.
次にブラウザからGoogleカレンダーを開いて,設定画面を開きます.
左側にある「マイカレンダーの設定」の自分のユーザー名を開くと,「特定のユーザーとの共有」という欄があるので,さっきコピペしたIDを追加します.
権限は「閲覧権限(すべての予定の詳細)」に設定しました.
これで,取得できるようになりました.

実際に取得する

ここまでくれば,ダウンロードしたファイルを使って実際に取得する処理を書けば終わりです.

calendar.rb
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