毎朝起こしてくれる彼女ができた。

### 唐突ですが、彼女ができました。
はい。嘘です。ごめんなさい。

今回は、[Line Notify](https://notify-bot.line.me/ja/)を使って毎朝指定した時間に、その日の予定を教えてくれる『彼女みたいな存在』のBotを作りました。
![IMG_8606.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/2d7ac38e-d21f-0706-67a0-f4ddf0a7a078.jpeg)

# 0. アイディアと開発について。
アイディアに関しては、スタバから家に帰ってる途中に思いつきました。
帰宅してそのまま（手洗いうがいはしました！！）開発をはじめました。

### プログラミング言語
言語に関しては、Pythonを採用しました。
採用理由としては、サーバレス（Lambda）で実装したかったのと前日にPythonを書いており、気分がPythonだったからです。

### 使用したサービス
開発環境: [Cloud9](https://aws.amazon.com/jp/cloud9/)
実行環境: [Lambda](https://aws.amazon.com/jp/lambda/), [CloudWatch Events](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/WhatIsCloudWatchEvents.html)
カレンダー: [Google Calendar API](https://developers.google.com/calendar)
クライアント: [Line Notify](https://notify-bot.line.me/ja/)

![route.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/b311a536-c0e5-0a2f-3f88-4862ad2a5e13.png)

# 1. Line Notify
まず、はじめにLine Notifyの設定をしたいと思います。

Line Notifyのマイページに行き、トークンを発行するを押しましょう！！！

![Screen Shot 2020-11-26 at 11.04.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/8b5217e6-bf24-c8d8-8c86-a8ebc6122174.png)

次に必要な情報を記入・選択していきます。
![Screen Shot 2020-11-26 at 11.05.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/0e8da180-240f-1001-b1f1-9a6363f5c49e.png)

トークン名は好きな言葉を入れましょう。
今回は『彼女（？）』にしてみましたが、適当に付けちゃって大丈夫です！！
（あとから変更できないので気をつけてください）

次に発行されたトークンを保存します。
![Screen Shot 2020-11-26 at 11.10.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/50c02f0a-0cde-f560-f4b1-9b8348c0163c.png)
トークンの再発行はできないので、トークンを安全な場所に保存するといいと思います。

これで、Line Notifyの設定は終わりました。

Line Notifyはすごく簡単に試せるので、以下のコードを実行して、試しに動かしてみてください。

```python
import requests

line_token = 'ここにLineで発行したトークン'
request_header = {"Authorization": "Bearer %s" % line_token}

message_data = {'message': 'This is test message.'}
requests.post("https://notify-api.line.me/api/notify", headers=request_header, data=message_data)
```

# 2. Google Calendar API
次はGoogle Calendarから情報を取得したいと思います！！

Lineと同じでGoogleの設定から行なっていきます。

### プロジェクト作成
最初にGoogle APIを使用するプロジェクトの作成を行います。
![Screen Shot 2020-11-26 at 11.26.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/001a0966-d18e-d5f3-8218-2c8bd69a49f0.png)
※プロジェクト名はなんでも大丈夫です。

次にGoogle Calendar API検索し有効にしましょう。
![Screen Shot 2020-11-26 at 11.30.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/75e0e842-7b07-bb9d-b18b-247f29956b24.png)

### 認証情報の作成

今回は、サービスアカウントの認証情報を作成します。

サービスのアカウント名やIDなどは適当に記入してもらって大丈夫です。
ロールに関しては、Projectのオーナーを使いました。（ちゃんと設定しましょう）

![Screen Shot 2020-11-26 at 11.32.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/044bf461-fc67-47b4-afdc-07404fe40f18.png)

### キーの発行
サービス アカウントの詳細の中の下の方に鍵を追加という項目があるので、そこからキーの発行を行います。
今回はJson形式のキーを使うので、Jsonを選択してください。（Jsonファイルはあとで使うので無くさないように保存を行なってください）

### 動かしてみる。

```python
import json
import datetime
import httplib2
from apiclient import discovery
import oauth2client
from oauth2client.service_account import ServiceAccountCredentials

ServiceAccount_Json = 'GoogleからダウンロードしたJsonファイルのパス'
CalendarId = '表示したいカレンダーのID'

start_time = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9)))
end_time = start_time.replace(hour=23, minute=59, second=59)

credentials = ServiceAccountCredentials.from_json_keyfile_name(ServiceAccount_Json, 'https://www.googleapis.com/auth/calendar')
http = credentials.authorize(httplib2.Http())
service = discovery.build('calendar', 'v3', http=http)
events = service.events().list(
    calendarId=CalendarId, 
    timeMin=start_time.isoformat(), 
    timeMax=end_time.isoformat(), 
    singleEvents=True, 
    orderBy='startTime'
).execute()

print(events['items'])
```
このコードを実行することで、その日の予定が出力されると思います。
出力されない場合は、設定を間違える可能性があります....

# 3. メッセージの作成
今回はメッセージの内容を3ブロックに分けました。
![Screen Shot 2020-11-26 at 12.18.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/b572f6e6-01bb-ef47-3fb9-4e42e5ec2ced.png)

まず、一番最初と最後のメッセージは、random.choiceとlistを使ってランダムに表示されるようにしました。
これで毎日同じテンプレが来る心配はありません！！！

```python
random.choice(['\nおはよ〜\n朝だよ。起きてる〜？？\n\n','\n朝だよ、起きて！！\n\n'])
```

次に、真ん中の今日の予定を表示する部分ですが、結構大変でした....
カレンダーの予定は一つではない可能性もあるので、ifを使って文字を作成するようにしました。

```python
# calendarsの中にはGoogle calendarのevents['items']が入ります。
calendars_num = 0
calendars_len = len(calendars) - 1
for calendar in calendars:
    if 'OneDay' in calendar['time']:
        message_content = calendar['summary'] + 'が1日'
    else:
        message_content = calendar['summary'] + 'が' + calendar['time']['start'] + 'から' + calendar['time']['end'] + 'まで'
                
    if calendars_num == 0 and calendars_num != calendars_len:
        calendar_message.append('今日は、' + message_content)
    if calendars_num == 0 and calendars_num == calendars_len:
        calendar_message.append('今日は、' + message_content + 'あるみたいね。')
    elif calendars_num != 0 and calendars_num < calendars_len:
        calendar_message.append('と' + message_content)
    elif calendars_num == calendars_len:
        calendar_message.append('と' + message_content + 'あるみたいね。')
                
    calendars_num+=1
```

# 4. デプロイ
はじめに今回のコードを僕の[Githubリポジトリ](https://github.com/lra21711214/girl-friend-Line-bot)からクローンしてください。

```
git clone https://github.com/lra21711214/girl-friend-Line-bot
```

次にGoogleからダウンロードしたService Accountの認証情報ファイル(Json)をlambda_function.pyと同じ階層にドラッグアンドドロップしてください。

同じ階層にlambda_function.pyとService Accountの認証情報ファイルが置けたら、lambda_function.pyの8行目の編集を行います。

```python
import os
import requests
import random
from lib import create_message


line_token = os.environ['LINE_TOKEN']
Service_account_json_file = 'ここを同じ階層にある認証情報ファイルの名前に変えてください。'
calendarId = os.environ['CALENDARID']
            

def lambda_handler(event, context):
    message_data = {'message': create_message(Service_account_json_file, calendarId)}
    return_data = requests.post("https://notify-api.line.me/api/notify", headers={"Authorization": "Bearer %s" % line_token}, data=message_data)
```

これで、コードは完了なのですが、コードを動かすための外部ライブラリがまだインストールをされていないので、していきます。


### Lambda
ローカルのパソコンであれば、PIPを使ってインストールを行えばいいのですが、今回はLambdaなので、PIPで指定したディレクトリに外部ライブラリを保存し、コードと外部ライブラリをZIPにまとめてLambdaにアップロードしたいと思います。

以下のコマンドを実行すると今いるディレクトリに必要なライブラリがダウンロードされます。
以下のコマンドはlambda_function.pyと同じ階層で行なってください。

```
sudo pip install requests httplib2 google-api-python-client oauth2client -t ./
```

次に、コードとライブラリを全てZipファイルにまとめてください。
ZipにまとめられたらLambdaの関数を作成していきます！！
![Screen Shot 2020-11-26 at 13.39.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/7fd01f17-3bee-183c-e96d-7ebb61545123.png)

関数名はなんでも大丈夫です。
ランタイムはPython3.8
ロールはデフォルトを使用しました。

関数が作成できたら、アクション→.zipファイルをアップロードというところから先ほど作成した、コードとライブラリを含んでいるzipをアップロードを行い、アップロードが完了したら右上にあるテストを行なってください。（テストが成功するとLineにメッセージが飛びます。）

### CloudWatch Events
CloudWatch Eventsは指定した時刻にLambda（Lambda以外も）を実行してくれるサービスです。
今回は、毎朝7時30分にメッセージが来るように設定しました。

![Screen Shot 2020-11-26 at 13.52.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/9b6465ca-8ca1-300f-933a-731960b40e1e.png)

Lambdaのデザイナーのトリガーを追加の部分からCloudWatch Eventsの設定を行なっていきます。
![Screen Shot 2020-11-26 at 13.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415015/e1cf21ce-b653-9b1c-1041-fcf16ac88030.png)

ここでも、ルール名はなんでも大丈夫です！！
スケジュール式は今回はcronを使用しました。
書き方に関しては、Google先生なので調べると出てくるので、調べて自分の好きな時間に設定してみてください！（UTC時間で実行されます。）

# 5. プログラムに関して。
このプログラムは数時間で作ったので、書き方が汚かったりすると思いますが、使ってもらえると嬉しいです。
今回は、7時30分にメッセージが来るようにしたのですが、時間を変えたりメッセージの内容を変えると別の物にもなるので、ぜひ改造してみてください。
[※コードはここにあります](https://github.com/lra21711214/girl-friend-Line-bot)

# 6. 最後に。
いま彼女は募集していないのですが、インターンをさせていただける企業様を探しています...
もし、興味を持っていただけたら[Twitter](https://twitter.com/oreo_Leo_code)のDMなどにメッセージを送ってもらえると嬉しいです。