Go言語でQiitaの人気記事のリンクをSlackに送信する

前回、QiitaのAPIで一週間分の人気記事を取得するというプログラムを作成したという記事を投稿しましたが、今回はそのプログラムを利用してSlackに通知させるプログラムを作成しました。
API Tokenの取得
Slack botのAPIトークンの取得は以下のページから行えます。
画面の右上でSlackのワークスペースを選択してbotの名前を入力してボタンを押すと、作成されます。
その後の画面で、APIトークンが表示されるので、保管しておきましょう。
プログラムの作成
以前の一週間分の人気記事を取得するプログラムから、前日だけの記事を取得するように変更して、チャンネルにメッセージを送るというプログラムを作成します。
Slackにメッセージを送るのは次のパッケージを用います。
GitHub – nlopes/slack: Slack API in Go
構成としては以下のようになります。
$ tree -L 2
.
├── qiita
│ └── qiita.go
└── send.go
1 directory, 2 files
以前作成したファイルをqiita
ディレクトリに格納して、ファイルで指定するパッケージ名をqiita
に変えて、パッケージ化して他のフォルダからも呼び出せるようにしました。
qiita.go
package qiita
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"time"
)
// jsonのパース用に構造体を定義
type Data struct {
Url string `json:"url"`
Title string `json:"title"`
LikesCount int `json:"likes_count"`
ReactionsCount int `json:"reactions_count"`
PageViewsCount int `json:"page_views_count"`
}
// Qiitaからデータを取得
func FetchQiitaData(accessToken string, targetDate time.Time) []Data {
baseUrl := "https://qiita.com/api/v2/"
action := "items"
// 1リクエストあたり最大30件取得
baseParam := "?page=1&per_page=30"
// monthだけintではなくMonth型のため型変換が必要
year, month, day := targetDate.Date()
targetDay := dateNum2String(year, int(month), day)
year, month, day = targetDate.AddDate(0, 0, 1).Date()
nextDay := dateNum2String(year, int(month), day)
// 投稿の検索クエリを作成
// 検索クエリ stocks:>NUM created:<YYYY-MM-DD created:>YYYY-MM-DD
// 指定日に投稿されたストック数20以上の記事を取得
varParam := "&query=stocks:>20+created:>=" + targetDay + "+created:<" + nextDay
endpointURL, err := url.Parse(baseUrl + action + baseParam + varParam)
if err != nil {
panic(err)
}
b, err := json.Marshal(Data{})
if err != nil {
panic(err)
}
var resp = &http.Response{}
// qiitaのアクセストークンがない場合はAuthorizationを付与しない
if len(accessToken) > 0 {
resp, err = http.DefaultClient.Do(&http.Request{
URL: endpointURL,
Method: "GET",
Header: http.Header{
"Content-Type": {"application/json"},
"Authorization": {"Bearer " + accessToken},
},
})
} else {
resp, err = http.DefaultClient.Do(&http.Request{
URL: endpointURL,
Method: "GET",
Header: http.Header{
"Content-Type": {"application/json"},
},
})
}
defer resp.Body.Close()
if err != nil {
panic(err)
}
b, err = ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
var datas []Data
if err := json.Unmarshal(b, &datas); err != nil {
fmt.Println("JSON Unmarshal error:", err)
return nil
}
return datas
}
// データの出力
func QiitaData2String(datas []Data) string {
result := ""
for _, val := range datas {
result += fmt.Sprintln(val.Title, "(", val.LikesCount, ")", "\n",val.Url)
}
return result
}
// 年月日の数値を文字列に変換
func dateNum2String(year int, month int, day int) string {
return fmt.Sprintf("%d-%d-%d", year, month, day)
}
func FetchQiitaArticles(targetDate time.Time) string {
// アクセストークン取得
qiitaToken := os.Getenv("QIITA_TOKEN")
data := FetchQiitaData(qiitaToken, targetDate)
return QiitaData2String(data)
}
そして、このパッケージを利用して前日に投稿された人気記事の取得を行ない、nlopes/slack パッケージを用いてメッセージの送信を行うプログラムを作成します。
パッケージのインストール
$ go get -u github.com/nlopes/slack
今回は、generalのチャンネルに送るようなプログラムなので、複数人で利用しているワークスペースにbotを追加した場合は、プログラムを変更して送り先を変更しましょう。
package main
import (
"fmt"
"time"
"os"
"github.com/nlopes/slack"
// 作成したパッケージをインポート
"./qiita"
)
func main() {
baseDate := time.Now()
// 一前の日付を取得
targetDate := baseDate.AddDate(0, 0, -1)
qiitaArticles := qiita.FetchQiitaArticles(targetDate)
// 対象の日付から一週間分のデータを取得
dateText := fmt.Sprintf("%d-%d-%d", targetDate.Year(), int(targetDate.Month()), targetDate.Day())
slackToken := os.Getenv("SLACK_TOKEN")
// slackのアクセストークンがない場合はエラー
if !(len(slackToken) > 0) {
fmt.Println("Please Set Slack Access Token.")
os.Exit(1)
}
api := slack.New(slackToken)
params := slack.PostMessageParameters{}
attachment := slack.Attachment{
Pretext: qiitaArticles,
}
message := fmt.Sprintf("%s 話題の記事",dateText)
params.Attachments = []slack.Attachment{attachment}
channelID, timestamp, err := api.PostMessage("general", message, params)
if err != nil {
fmt.Printf("%s\n", err)
return
}
fmt.Printf("Message successfully sent to channel %s at %s", channelID, timestamp)
}
実行
Qiitaのトークンと先ほど取得したのトークンを環境変数に設定している場合
$ go run main.go
環境変数に追加していない場合は、実行の際に指定します。
$ SLACK_TOKEN=YOUR-SLACK-TOKEN QIITA_TOKEN=YOUR-QIITA-TOKEN go run send.go
実行結果
以下のように、generalに送信されました。
まとめ
今回は実行して取得してきたデータを用いてそのまま送信させるというシンプルな内容でした。
今回利用したパッケージにまだまだ機能がありそうなので、他の機能を使ってみたり、ソースコードを見てどう実装されているのかを見てみるのも面白いと思います。