LINE Bot でカレンダーを表示する

LINE Messaging API の Flex Message を使う

> Flex Messageは、複数の要素を組み合わせてレイアウトを自由にカスタマイズできるメッセージです。

## 完成系

<img src="https://qiita-image-store.s3.amazonaws.com/0/4598/3e521219-aefd-7376-967f-002d55eacdc4.png" width=300>

- 今月のカレンダーがでる
- 日曜日、祝日は赤色、土曜日は青色、今日は緑色、その他は黒色

## JSON を組み立てる

Flex Message で表示させるための JSON を Ruby で組み立てる

```ruby:calendar.rb
require 'date'
require 'json'
require 'active_support'
require 'active_support/core_ext'
require 'holiday_jp'

# 今月のカレンダー
def this_month_calendar
  calendar = []
  contents = []
  # today = Time.zone.today
  today = Date.today
  holidays = ::HolidayJp.between(today.beginning_of_month, today.end_of_month).map(&:date)

  today.beginning_of_month.wday.times do
    contents << {
      type: "text",
      text: ' ',
      size: "sm",
      color: '#000000',
      align: "center"
    }
  end

  (today.beginning_of_month..today.end_of_month).each do |day|
    # today = Time.zone.today
    if day == Date.today
      color = "#1db446" # green
    elsif day.sunday? || holidays.include?(day)
      color = "#ff0000" # red
    elsif day.saturday?
      color = '#0000ff' # blue
    else
      color = '#000000'
    end

    day_contents = {
      type: "text",
      text: day.day.to_s,
      size: "sm",
      color: color,
      align: "center",
      gravity: "center"
    }

    contents << day_contents
    contents << { type: "separator" } unless day.saturday?

    if today.end_of_month == day
      (6 - today.end_of_month.wday).times do
        contents << {
          type: "text",
          text: ' ',
          size: "sm",
          color: '#000000',
          align: "center"
        }
      end
    end

    if day.saturday? || today.end_of_month == day
      calendar << {
        type: "box",
        layout: "horizontal",
        margin: "md",
        contents: contents
      }
      calendar << { type: "separator" }
      contents = []
    end
  end

  {
    type: "flex",
    altText: "カレンダー",
    contents: {
      type: "bubble",
      styles: {
        footer: {
          separator: true
        }
      },
      body: {
        type: "box",
        layout: "vertical",
        contents: [
          {
            type: "text",
            text: "#{today.month}月",
            weight: "bold",
            color: "#1db446", # green
            size: "md"
          },
          {
            type: "text",
            text: "ここになにか説明",
            size: "xs",
            color: "#aaaaaa", # gray
            wrap: true
          },
          {
            type: "box",
            layout: "vertical",
            margin: "md",
            spacing: "md",
            contents: [
              {
                type: "separator",
                margin: "md"
              },
              {
                type: "box",
                layout: "horizontal",
                margin: "md",
                contents: weekday_header
              },
              {
                type: "separator"
              },
              *calendar
            ]
          }
        ]
      }
    }
  }
end

# 曜日ヘッダー
def weekday_header
  weekdays = %w[日 月 火 水 木 金 土]
  weekdays.each_with_object [] do |weekday, header|
    if weekday == '日'
      color = "#ff0000" # red
    elsif weekday == '土'
      color = '#0000ff' # blue
    else
      color = '#000000'
    end

    header << {
      type: "text",
      text: weekday,
      size: "sm",
      color: color,
      align: "center"
    }
    header << { type: "separator" } if weekday != '土'
  end
end

puts this_month_calendar.to_json
```

## JSON をはきだす

```sh
$ ruby calendar.rb |jq .
```

## [Flex Message Simulator](https://developers.line.me/console/fx/) で確認する

生成された JSON をコピペすると、冒頭のキャプチャのようなカレンダーが確認できる

:warning: Flex Message Simulator で確認するときは、 contents 以下の `"type": "bubble"` からをコピペする


## REF

- https://developers.line.me/ja/docs/messaging-api/using-flex-messages/
- https://developers.line.me/console/fx/

## あわせて読みたい

https://qiita.com/7kaji/items/5d069636d4e5963967c4