キズナアイがおはようツイートしたら通知を送るBOTを作った


おはようございます。最近起きれてますか？
私はコロナで完全に生活リズムが狂ってしまって、4時寝11時起きの生活をしています。
![](https://gyazo.com/3fa9e6233a4c0820e31a22a9928c93b9/raw)

アラームはかけているのですがなかなか起きれない理由として、朝起きる理由がない、刺激がないのではと思い、それを解決する方法を考えてました。

その中で見つけました！それはキズナアイのおはようツイートです！！

https://twitter.com/aichan_nel/status/1377735546487762944

だいたい6時から11時までの間にツイートがされていて、平日の朝は我々を励ます動画を毎日投稿してます。(じゃんけん勝負をしています)

これがツイートされるタイミングで起きれば、起きれるのでは？？と思い、slackやdiscordに通知を入れてくれるBOTを作りました。

ちなみにwebhookのurlをGoogle フォームに入力したらみなさんのslackにも通知が入ります！！
![](https://gyazo.com/42663e297b80b1e9538e3c6a6f8800c3/raw)


# 完成したもの

### googleフォームにwebhookURLを入力すれば使えます！
https://docs.google.com/forms/d/e/1FAIpQLScrBF_1cD_vNB3E18jl-2FWkd8REe6OMfvs5YeIG_DsQ6vcyg/viewform

### 仕様技術
- Heroku Scheduler
- Python
- Tweety
- Google SheetsAPI
- Google form(入力側)


### 設計図
![image](https://gyazo.com/ac7885f95aa0171c777337f509f4d624/raw)


githubのリポジトリ

https://github.com/kurikinton105/MorningKizunaAI

また、このQiitaの内容は、2021/4/28に行われた#技育CAMPのLT大会で発表したアプリケーションです。

https://speakerdeck.com/kurikinton105/morningkizunaai



## ステップ1 ツイートの取得

Heroku Schedulerは10分おきに実行をできるので、10分おきにキズナアイの新しいツイートがないかtweetyを使って検索をします。

https://devcenter.heroku.com/articles/scheduler

https://qiita.com/nsuhara/items/fac20adb6b0a122a3709

![](https://gyazo.com/f0dd646694dca3dcf39c65a77ce0d77e/raw)

肝となる部分は、リツイートを含まず、外部に保存しているtweetedより大きいキズナアイのツイートがあったら取得という形を取っています。

```GetUserTweet.py
 def GetUserTweet_data( Account,tweet_id,option_time=10):   
    ...   
    tweets = api.user_timeline(Account, count=20, page=1)
    BaseURL = f"https://twitter.com/{ Account }/status/"
    tweet_data =[]
 
    for tweet in tweets:
        if tweet_id < tweet.id:
            TweetURL = BaseURL+str(tweet.id)
            tweet_text = f"{tweet.text}\n{TweetURL}"
            tweet:dict ={"id":tweet.id , "data":tweet_text}
            tweet_data.append(tweet)
    return tweet_data
```

https://github.com/kurikinton105/MorningKizunaAI/blob/main/MorningKizunaAI.py



### webhookで通知を送信する

```WebhookAction.py
 def WebhookApp(webhook_url,comment, username,image_URL):
     if "discord" in webhook_url:
         # Discord
         main_content = {
                         'username': username,
                         'avatar_url': image_URL,
                         'content':comment
                     }
         headers = {'Content-Type': 'application/json'}
 
         response  = requests.post(webhook_url, json.dumps(main_content), headers=headers)
         print(response.status_code)
         return response.status_code
     elif "slack" in webhook_url:
         # Slack
         response = requests.post(webhook_url, data = json.dumps({
         'text': comment,  # 通知内容
         'username': username,  # ユーザー名
         'icon_url': image_URL
         }))
         print(response.status_code)
         return response.status_code
     else:
         return Exception("Not found:Webuook")
```

https://github.com/kurikinton105/MorningKizunaAI/blob/main/WebhookAction.py


## データベースはスプレットシート

今回、自分以外の人が支えるようにしたかったのと、フロントエンドの作成がめんどくさかったという理由からフロントエンドはGoogleフォームを使うことにしました。googleフォームに入力された結果はスプレットシートに保存することができるので、スプレットシートをデータベースみたいに利用しました。

https://qiita.com/y_a_m_a/items/b4eeb6079e14ee58d737

Googleフォームを使うことで、URLの更新などもできるため、新規フォーム、更新フォームを個別に作る必要もないため簡単に作る時は便利です。

```sheets.py
 def Auth_Sheet(credentials_name,SPREADSHEET_KEY,sheet_name,isTest=False):
     #2つのAPIを記述しないとリフレッシュトークンを3600秒毎に発行し続けなければならない
     scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
 
     #ダウンロードしたjsonファイル名をクレデンシャル変数に設定（秘密鍵、Pythonファイルから読み込みしやすい位置に置く）
     credentials = ServiceAccountCredentials.from_json_keyfile_name(credentials_name, scope)
 
     #OAuth2の資格情報を使用してGoogle APIにログインします。
     gc = gspread.authorize(credentials)
 
     #共有設定したスプレッドシートキーを変数[SPREADSHEET_KEY]に格納する。
     if isTest == True:
         SPREADSHEET_KEY = config.SPREADSHEET_TEST_KEY
     else:
         SPREADSHEET_KEY = config.SPREADSHEET_KEY
     #共有設定したスプレッドシートのシート1を開く
     Sheet = gc.open_by_key(SPREADSHEET_KEY).worksheet(sheet_name)
     return Sheet
```

上のコードは認証部分のコードです。

## 
おはようツイートかどうかを判別する

ここはそこそこ悩みました。

### 何も添付されていない系

https://twitter.com/aichan_nel/status/1343703270808666113

### おはよう！の進化系

https://twitter.com/aichan_nel/status/1332806976850411521

https://twitter.com/aichan_nel/status/1323747817538510848


### げつようび系

https://twitter.com/i/web/status/1333161311341985793

https://twitter.com/aichan_nel/status/1335698153857720321

https://twitter.com/aichan_nel/status/1350920380383338500



総じて「おはよう」の変形なのですが、一貫性がなかったり文章なしの場合があるためおはようツイートをツイート内容から判別するのは確実ではないと感じました(機械学習で判定したかった…)

そこで、他に気がついた法則性として、6時から11時までの「その日にはじめてツイートされた内容」をおはようツイートとして判別することにしました。


プログラムを起動した時間が5時代だったら、その日のツイートカウントを0にして、ツイートがあったら+1する原始的な方法を使いました。

この判定の数値もスプレットシート内に置いています。

```isMorning.py
 def isMorningTweet(tweet,time_now,isTest=False):
     isMorningTweet = False
     #time_now = datetime.datetime.now()
     print(int(time_now.hour))
     # 5時にリセットする！
     if int(time_now.hour)== 5:
         Auth = SheetsAPI.sheet.Auth_Sheet(config.SheetAuthKeyName,config.SPREADSHEET_KEY,"Num",isTest)
         Auth.update_cell(2,1,0)
         Log = SheetsAPI.sheet.Auth_Sheet(config.SheetAuthKeyName,config.SPREADSHEET_KEY,"Log",isTest)
         Log.append_row([str(time_now.strftime("%Y/%m/%d %H:%M:%S")),f"5時代:0"])
     elif 6 <= int(time_now.hour) and int(time_now.hour) < 12: # 時間での判別
         print("朝時間")
         if tweet['data'].find("https://t.co") != -1 and tweet['data'] not in "RT": # 動画のツイート&RTじゃない
             Auth = SheetsAPI.sheet.Auth_Sheet(config.SheetAuthKeyName,config.SPREADSHEET_KEY,"Num",isTest)
             num :int = Auth.get_all_records()[0]['Num']
             print(num)
             # その日の始まりのツイートを取得
             if num == 0:
                 isMorningTweet = True
                 num += 1
                 Auth.update_cell(2, 1, num)
                 Log = SheetsAPI.sheet.Auth_Sheet(config.SheetAuthKeyName,config.SPREADSHEET_KEY,"Log",isTest)
                 Log.append_row([str(time_now.strftime("%Y/%m/%d %H:%M:%S")),f"最初のツイート{num}",True])
             else:
                 num += 1
                 Auth.update_cell(2, 1, num)
                 Log = SheetsAPI.sheet.Auth_Sheet(config.SheetAuthKeyName,config.SPREADSHEET_KEY,"Log",isTest)
                 Log.append_row([str(time_now.strftime("%Y/%m/%d %H:%M:%S")),f"その日の2個以上:{num}",False])
     return isMorningTweet
```

# ログを取る
一応、確認のためにスプレットシート上にログを取るようにしました。
6月までに作ったファイルは無料で無制限なので、スプレットシート最強！！

![](https://gyazo.com/f32f9f9cbe3dbaf40957d2815d61f72c/raw)


という感じでキズナアイのおはようツイートを通知するBOTを作りました。
webhook URLを取得しGoogleフォームに入力することで、皆さんも使うことができます！

(ちなみに、これを作っても生活習慣は改善しなかったので、次はBOTではなくアラームアプリでも作ればなんとかなる？？？と思いました)


https://docs.google.com/forms/d/e/1FAIpQLScrBF_1cD_vNB3E18jl-2FWkd8REe6OMfvs5YeIG_DsQ6vcyg/viewform

ということで是非使ってみてください