💬

モスクワの天気に詳しい彼女botが欲しい

2021/03/28に公開

はじめに

モスクワの天気に精通した彼女風LINE BOTを作成しました

Image from Gyazo

QRコード

Image from Gyazo

使用技術

事前準備

LINE BOT 作成手順は、以下記事にまとめましたので、参考にして頂けますと幸いです。
LINE BOTで彼女botを作りたい

リッチメニュー 作成

LINE Official Account Manager ログイン

「アカウント名選択」 > 「トークルーム管理」 > 「リッチメニュー」 選択

Image from Gyazo

「作成」 > 「コンテンツ設定」 > 「テンプレート選択」 > 「画像を作成」

Image from Gyazo

任意の画像・テキストを設定し、右上の「適用」をクリック

Image from Gyazo

「アクション」 で「テキスト」を選択し、任意の文字を設定 > 右上の「保存」で完了

Image from Gyazo

openWeather API 設定

openWeather API > API Key 取得

Image from Gyazo

Bot作成

Goプロジェクト準備

$ mkdir sample-bot && cd sample-bot
$ go mod init github.com/GitHubユーザ名/GitHubリポジトリ名

Goライブラリインストール

$ go get github.com/line/line-bot-sdk-go/linebot
$ go get github.com/gin-gonic/gin

コーディング

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/line/line-bot-sdk-go/linebot"
)

type Wdata struct {
	Weather []Weather `json:"weather"`
	Info    Info      `json:"main"`
}

type Weather struct {
	Main string `json:"main"`
	Icon string `json:"icon"`
}

type Info struct {
	Temp     float32 `json:"temp"`
	Humidity float32 `json:"humidity"`
}

func main() {
	port := os.Getenv("PORT")

	if port == "" {
		log.Fatal("$PORT must be set")
	}
	bot, err := linebot.New(
		"LINE シークレット",
		"LINE アクセストークン",
	)
	if err != nil {
		log.Fatal(err)
	}

	router := gin.New()
	router.Use(gin.Logger())

	// LINE Messaging API ルーティング
	router.POST("/callback", func(c *gin.Context) {
		events, err := bot.ParseRequest(c.Request)
		if err != nil {
			if err == linebot.ErrInvalidSignature {
				log.Print(err)
			}
			return
		}

		// モスクワ
		var moskwaWeather string
		moskwaWeather = "モスクワ"

		for _, event := range events {
			// イベントがメッセージの受信だった場合
			if event.Type == linebot.EventTypeMessage {
				switch message := event.Message.(type) {
				// メッセージがテキスト形式の場合
				case *linebot.TextMessage:
					replyMessage := message.Text
					// モスクワ
					if strings.Contains(replyMessage, moskwaWeather) {
						moskwasWeather(bot, event)
					}
					// 上記意外は、おうむ返しで返信
					_, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(replyMessage)).Do()
					if err != nil {
						log.Print(err)
					}
				}
			}
		}
	})
	router.Run(":" + port)
}

// モスクワ
func moskwasWeather(bot *linebot.Client, e *linebot.Event) {
	lat := "55.755826" // モスクワの緯度
	lon := "37.6173" // モスクワの経度
	url := "http://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&APPID=XXXXXXXXXX" // openWeather:API Keyを設定
	//天気情報を取得
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	byteArray, _ := ioutil.ReadAll(resp.Body)
	jsonBytes := ([]byte)(string(byteArray[:]))
	if err != nil {
		log.Fatal(err)
	}

	wdata := new(Wdata)
	if err := json.Unmarshal(jsonBytes, wdata); err != nil {
		fmt.Println("JSON Unmarshal error:", err)
		return
	}
	var resWeather string
	resWeather = fmt.Sprintf(wdata.Weather[0].Main)

	// 日本語変換
	if resWeather == "Clouds" {
		resWeather = "曇り"
	} else if resWeather == "Clear" {
		resWeather = "晴れ"
	} else if resWeather == "Rain" {
		resWeather = "雨"
	} else if resWeather == "Drizzle" {
		resWeather = "霧雨"
	} else if resWeather == "Thunderstorm" {
		resWeather = "雷雨"
	} else if resWeather == "Snow" {
		resWeather = "雪"
	}

	var temp string
	temp = fmt.Sprintf("%.2f", (wdata.Info.Temp - 273.15))
	var humidity string
	humidity = fmt.Sprintf("%.2f", wdata.Info.Humidity)
	var res string
	res = fmt.Sprintf("天気:%s\n気温:%s℃\n湿度:%s%", resWeather, temp, humidity)

	_, err = bot.ReplyMessage(e.ReplyToken, linebot.NewTextMessage(res)).Do()
	if err != nil {
		log.Fatal(err)
	}
}

参考文献

Discussion