Goで今月上映予定の映画一覧をLINEに通知する　

# 作成したプログラムの説明
無料のAPIを使って今後公開予定の映画情報を通知する処理を作成したので、
その内容について記載します。(※全て無料で実現可能です。)


以下例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271464/a96c2439-e348-a354-84a1-c2e864fdc2c0.png)


# ソフトウェアバージョン
| ソフトウェア | バージョン | 
|:-----------:|:------------:|
| Go  | 1.13.6 | 
| Docker  | 19.03.4 | 
| docker-compose | 1.24.1 | 

# 処理概要
構成で下図の通り、GitHub actionsでスケジューリングして定期的に通知がくるように設定しています。

![movie_upcoming.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271464/b85d3f09-6be4-c976-d9da-bc0909cba669.png)



# 事前準備
### TMDBのAPIKeyの取得
今回は無料でかつオープンAPIである[TMDB](https://www.themoviedb.org/?language=ja)を利用します。
利用するためにはアカウント登録をしてAPIキーの払い出しを行うする必要があります。
APIキーの払い出す方法は[こちら](https://weblion303.net/1262)をご参考下さい。

**以下手順**
- TMDBの無料アカウントを作成
- 利用規約を確認してAPIキーを登録

[こちらのページ](https://developers.themoviedb.org/4/getting-started/authorization)でAPIの基本的な仕様や利用方法について記しています。
また、GoではTMDBの[パッケージ](https://pkg.go.dev/github.com/cyruzin/golang-tmdb)が用意されているので、コードに記載する場合はこっちを利用します。

### LINE Notifyの登録
GoでのLINE Notifyの使い方は[こちら](https://cipepser.hatenablog.com/entry/go-line-notify)を参考にしました。

**以下手順**
- LINE Notifyを利用するためのアクセストークンを発行
- LINE NotifyとのグループLINEを作成
- curl等でPOSTして通知がくることを確認

# 機能一覧
- APIから今後公開予定情報を取得
- Getした情報からメッセージを整形
- LINE Notifyに通知

### APIから今後公開予定情報を取得

tmdbパッケージをインストール

```
import  tmdb "github.com/cyruzin/golang-tmdb"
```

作成したAPIキーを利用して公開予定の映画情報を取得

```
・・・
	// tmdbインスタンス化
	tmdbClient, err := tmdb.Init("APIキー")
	if err != nil {
		fmt.Println(err)
	}

	// 言語、リージョンを日本に設定
	options := map[string]string{
		"language": "ja",
		"region":   "JP",
	}

	// 今後公開予定の映画情報を取得
	movieUpcoming, err := tmdbClient.GetMovieUpcoming(options)
	if err != nil {
		fmt.Println(err)
	}
・・・
```

### Getした情報からメッセージを整形

```
・・・
	// 期間、レスポンス情報の初期化
	today := time.Now().Format("2006-01-02")
	addDays := time.Now().Add(24 * 数値を記載(X日以内に公開予定の映画) * time.Hour).Format("2006-01-02")
	var itemSlice movieUpcomingInfo

	// 本日からX日以内に公開予定の映画のみを抽出
	for i := 0; i < len(movieUpcoming.Results); i++ {
		movieItem := movieUpcoming.Results[i]
		if today <= movieItem.ReleaseDate && movieItem.ReleaseDate <= addDays {
			itemSlice.Results = append(itemSlice.Results, movieItem)
		} else if addDays < movieItem.ReleaseDate {
			continue
		}
	}

	// 通知するメッセージを整形
	msg := ""
	for i := 0; i < len(itemSlice.Results); i++ {
		title := itemSlice.Results[i].Title
		releaseDate := itemSlice.Results[i].ReleaseDate
		baseUrl := confData.Settings.BaseUrl
		url := baseUrl + itemSlice.Results[i].PosterPath
		msg += "\r\n" + "【タイトル】" + "\r\n" + title + "\r\n" + "【公開日】" + "\r\n" + releaseDate + "\r\n" + "【ポスターURL】" + "\r\n" + url + "\r\n"
	}
・・・
```

`movieUpcoingInfo`の定義

```
type movieUpcomingInfo struct {
	Results []struct {
		PosterPath  string `json:"poster_path"`
		Adult       bool   `json:"adult"`
		Overview    string `json:"overview"`
		ReleaseDate string `json:"release_date"`
		Genres      []struct {
			ID   int64  `json:"id"`
			Name string `json:"name"`
		} `json:"genres"`
		ID               int64   `json:"id"`
		OriginalTitle    string  `json:"original_title"`
		OriginalLanguage string  `json:"original_language"`
		Title            string  `json:"title"`
		BackdropPath     string  `json:"backdrop_path"`
		Popularity       float32 `json:"popularity"`
		VoteCount        int64   `json:"vote_count"`
		Video            bool    `json:"video"`
		VoteAverage      float32 `json:"vote_average"`
	} `json:"results"`
}
```

### LINE Notifyに通知

```
・・・

	accessToken := "LINE Notify アクセストークン"
	URL := "LINE APIのURL"

	urlRequest, err := url.ParseRequestURI(URL)
	if err != nil {
	　　log.Fatal(err)
	}

	lineClient := &http.Client{}
	form := url.Values{}
	form.Add("message", msg)
	body := strings.NewReader(form.Encode())
	req, err := http.NewRequest("POST", urlRequest.String(), body)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", "Bearer "+accessToken)

	lineClient.Do(req)
・・・
```

# Github Actionsで設定
Github Actionsの使い方の詳細については[こちら](https://qiita.com/HeRo/items/935d5e268208d411ab5a)を参考

* `.github/workflows/` ディレクトリ以下に配置されるYAMLファイルを配置(`movie_upcoming.yml`)

#### movie_upcoming.yml例

```
name: <任意の実行ジョブ名>

on:
    push:
        branches: [ master ]
    schedule:
      - cron: '00 10 * * 1'　　# 毎週月曜に実行
    
jobs:
    notify_job:
        runs-on: ubuntu-18.04
        name: Notify
        steps:
            - name: Checkout
              uses: actions/checkout@v2
              with:
                repository: <アカウント名/リポジトリ名>
                path: ./
            - name: docker exec
              run: |
                docker exec echo go run movie_upcoming.go
```


### 実行結果
以下のように設定した時間でLINEに通知が届きます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271464/a96c2439-e348-a354-84a1-c2e864fdc2c0.png)

# まとめ
今回は今後公開予定の映画について通知する処理を作成しました。
本当はあらすじ等を記載した買ったのですが、LINEの文字数制限により断念しました。
良い方法あれば教えていただけると幸いです。

# 参考
[TMDb](https://www.themoviedb.org/?language=ja)
[TMDb登録方法](https://weblion303.net/1262)
[LINE Notify](https://notify-bot.line.me/ja/)
[LINE Notifyの設定方法](https://cipepser.hatenablog.com/entry/go-line-notify)
[golang_tmdbパッケージ](https://pkg.go.dev/github.com/cyruzin/golang-tmdb)
[Github Actionsの使い方メモ](https://qiita.com/HeRo/items/935d5e268208d411ab5a)