2021年は日記を3日坊主にしないために

# はじめに

『一年の計は元旦にあり』と言う通り、年始というのは何かを新しく始めるのに適した時期である。
かくいう私も、まだコロナが流行り始める前、2020年の元日より、もう何度目の挑戦かもわからない「日記を書く」というタスクにチャレンジし始めた。

だが、大方の予想を裏切ることなく、日記を書くという行為はものの1週間ほどで途絶えてしまった。文字通りの3日坊主にこそならなかったものの、3日も1週間も大きくは変わらない。1月の7日を最期に途絶えた日記は、その後断続的に復活や消滅を繰り返し、4月中旬まで書いたり書かなかったりする日が続いたものの、そこを最期にパッタリと止まってしまった。

# 日記の内容

自分が書いていた日記の内容は、その日の出来事を自由に記述するものというよりは、一昔前に流行ったライフログのようなものだった。
具体的には以下の内容を、Googleのスプレッドシートに記録していた。

- 睡眠関係(起床時刻、就寝時刻、睡眠時間)
- 朝食・昼食・夕食の内容
- 飲酒量
- その日の肉体的/精神的なパフォーマンスの点数(100点満点)
- その日あったポジティブな出来事(良かったこと)
- その日あったネガティブな出来事(反省点、改善点)
- 自由記述

![スプレッドシートに記載されたライフログ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48175/cdc6a9e7-9180-cbae-6c53-2792227f77c2.png)


これらを毎日記録し(ようとし)ていたのにはいくつか理由がある。

1. 自分は胃痛やお腹を下したりと体調不良になることが多いのだが、脂っこいものや辛いものを食べ過ぎた後など不調の原因が分かる時と、原因がよく分からない時があった。毎日の食事内容やネガティブな出来事(=ストレッサー)を記録することで、体調不良の原因特定がやりやすくなるのではないかと考えたため。
2. その日あった失敗や反省点をデイリーで振り返り、再発防止案を考えることで、同じ失敗を繰り返さないようにするため。
3. 肉体の不調やメンタルの落ち込みが長期にわたり続いた際に、検知や改善をしやすくするため。

上記のような目的のため、まずは「毎日の記録を残して分析を行える環境を作る」ことが必要だったのだが、残念ながら冒頭の通り、7日坊主で途絶えてしまったのだった。

# 記録方法の改善

日記が7日坊主で途絶えた理由として、

- 単純に記録を忘れることが多かった
- 記録が面倒だった
  - 記録のためにPCを起動したり、操作しづらいスマートフォンのスプレッドシートアプリを使ったりするのが面倒だった。
  - 「明日まとめて記録すればいいや」となったまま、翌日になると前日の食事内容や出来事をなかなか思い出せず、放置してしまっていた。

あたりが考えられる。今回はこれを改善する方法を考えた。

- リマインダーを設定する
  - 生活習慣の一部となるまでは、特に忙しい日や疲れている日は素で忘れてしまうので、リマインダーで防ぐ。
- 記録を楽にする
  - 自動で記録できれば一番良いが、自由文で入力する必要がある項目が多いので、記録の手間を楽にする。


これらを実現するために、当初からChatOpsな仕組みにしようと考えていたのだが、TwitterやLINE、Slackあたりのどれにしようと考えた結果、bot開発に慣れたSlackでやることにした。
  
# 作ったものの概要

現状使用しているスプレッドシートをデータベースとして利用したまま、記録やリマインドをSlackから行うようにした。
Slackからの操作を受け取るため、`@LifelogBot`を作成した。

## スプレッドシートから情報を取得する

[公式リファレンス](https://developers.google.com/sheets/api/quickstart/go)にほぼそのままで動くコードがあるので、 `spreadsheetId` や `readRange` を書き換えるだけで簡単に取得できる。

```go

func main() {
    // "12月"というシートのA2セル~N列までを取得する
    readRange := "12月!A2:N"
    getRange(readRange)
}

func getRange(readRange string) {
	b, err := ioutil.ReadFile("credentials.json")
	if err != nil {
		log.Fatalf("Unable to read client secret file: %v", err)
	}

	config, err := google.ConfigFromJSON(b, "https://www.googleapis.com/auth/spreadsheets")
	if err != nil {
		log.Fatalf("Unable to parse client secret file to config: %v", err)
	}
	client := getClient(config)

	srv, err := sheets.New(client)
	if err != nil {
		log.Fatalf("Unable to retrieve Sheets client: %v", err)
	}

    // スプレッドシート固有のID
	spreadsheetId := "maKiMAsaNNosYoUgAYaKi_tAbEtAIna"
	resp, err := srv.Spreadsheets.Values.Get(spreadsheetId, readRange).Do()
	if err != nil {
		log.Fatalf("Unable to retrieve data from sheet: %v", err)
	}

	if len(resp.Values) == 0 {
		fmt.Println("No data found.")
		return nil
	} else {
		for _, v := range resp.Values[0] {
		    fmt.Printf("%v\n", v)
		}
	}
}
```


slackの操作にはおなじみの[slack-go/slack](https://github.com/slack-go/slack)を使用した。(詳細は省略)

`today` コマンドを作り、スプレッドシートから取得してきた値を上手いこと整形して表示した。
![@lifelogbot today した画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48175/9d62097c-1fa9-730d-575f-d52a1d4fe8e9.png)



## スプレッドシートのセルを編集する

セルの編集には、[spreadsheets.valus/update](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/update)を使用した。

```go
func updateCell(updateRange string, s string) {
	// 省略

	var vr sheets.ValueRange
	vr.Values = append(vr.Values, []interface{}{s})

	resp, err := srv.Spreadsheets.Values.Update(spreadsheetId, updateRange, &vr).ValueInputOption("RAW").Do()
	if err != nil {
		log.Fatalf("Unable to retrieve data from sheet: %v", err)
	}
}
```

`@LifelogBot 項目名 val`で当日の項目を編集できるようにした。
![@LifelogBot 飲酒 ハイボール した画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48175/ba99558a-64e0-f908-029f-dbe26e2986e5.png)


## リマインド

リマインダーには[carlescere/scheduler](https://github.com/carlescere/scheduler)を使用した。
毎日、深夜2時にその日の記録がされているかをチェックし、埋まっていない項目があるとSlackにメンションが送られ、スマホに通知が来るようにした。

```go
import "github.com/carlescere/scheduler"

func remind() {
	job := func() {
		// 入力忘れがないかチェック
		if !checkTodayLog() {
			sendMention("今日のログを記録しましょう。")
		}
	}

    // 毎日深夜2時にリマインド
    scheduler.Every().Day().At("2:00").Run(job)
}
```

## 終わりに

とりあえず使いはじめたものの、まだ使いにくさや機能の足りなさを感じるので、[interactive message](https://api.slack.com/legacy/interactive-messages)を使ったり、記録が途絶えた際にパブリックな場(Twitter等)で**過激な**リマインドを始めるようにして、改善していきたい。

さて、2021年は毎日忘れずに日記をつけられるのか、はたまた再び3日坊主となってしまうのか。
結果は来年のアドベントカレンダーをお楽しみに！