はじめに
githubにあげてるんでめんどくさい方はこちらからソースを見てください。画像を多めに使用しているため見にくいかとは思いますがご了承ください。本記事はGoogleカスタム検索エンジンを用いて画像の取得部分の実装をしています。
今回のゴール

環境
go 1.10.0
実装の前に
1. Slack Botの設定
こちらからbotの作成をしてください。赤く塗りつぶされている箇所がTokenになります。このTokenは後にチャンネルの情報取得のため後に使用します。
2. Googleカスタム検索エンジンの設定
2.1 プロジェクトの作成
Googleアカウントにログイン後、こちらからプロジェクトの作成を行ってください。
2.2 Custom Search APIの有効化
こちらに移動し検索欄にcustom search
と入力Custom Search APIを選択してください。
選択すると下記のような画面になると思うためAPI有効にしてください。(プロジェクトの作成を求められた場合は指示に従って作成してください。)
2.2 APIキーの作成
こちらから認証情報の作成し、APIキーの作成を行ってください。APIキーは後に使います。
2.3 カスタム検索エンジンの追加
こちらからカスタム検索エンジンの追加を行います。
検索エンジンの欄にwww.google.com
と入力し、言語を設定してください。(僕は日本語にしました)
2.4 カスタム検索エンジンの設定・ID取得
カスタム検索エンジンの追加完了後、コントロールパネルに移動し画像検索をオンにしてください。また、検索するサイトをウェブ全体に設定してください。これでカスタム検索エンジンの設定は完了です。詳細から検索エンジンIDを取得してください。検索エンジンIDは後に使います。
実装
1. 画像検索
ベースとなるURLです。
https://www.googleapis.com/customsearch/v1?key=APIキー&cx=検索エンジンID&searchType=image&num=1&q=検索したい文字列
今回は画像のみの取得ということでserchTypeを画像のみ(searchType=image
)としています。また、画像の取得件数を1件だけ(num=1
)にしてあります。先ほど取得したAPIキーと検索エンジンIDを入れ、検索したい文字列を入れてみてください。JSON形式で画像URLが1件取得できると思います。リクエストパラメーターを詳しく見たいという方はこちらからドキュメントを参照してください。
それでは、botディレクトリ
を作成し画像を検索するimage.go
を作成し、以下のように書いていきましょう。
package main
import (
"log"
"io/ioutil"
"encoding/json"
"fmt"
"strings"
"net/http"
"os"
)
type Search struct {
Key string
EngineId string
Type string
Count string
}
type Result struct {
Items []struct {
Link string `json:"link"`
} `json:"items"`
}
func SearchImage(word string) string {
baseUrl := "https://www.googleapis.com/customsearch/v1"
s := Search{os.Getenv("CUSTOM_SEARCH_KEY"), os.Getenv("CUSTOM_SEARCH_ENGINE_ID"), "image", "1"}
word = strings.TrimSpace(word)
url := baseUrl + "?key=" + s.Key + "&cx=" + s.EngineId + "&searchType=" + s.Type + "&num=" + s.Count + "&q=" + word
log.Println(url)
imageUrl := ParseJson(url)
return imageUrl
}
func ParseJson(url string) string {
var imageUrl = "not search image"
response, err := http.Get(url)
if err != nil {
log.Println("get error:", err)
}
defer response.Body.Close()
byteArray, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Println(err)
}
jsonBytes := ([]byte)(byteArray)
data := new(Result)
if err := json.Unmarshal(jsonBytes, data); err != nil {
fmt.Println("json error:", err)
}
if data.Items != nil {
imageUrl = data.Items[0].Link
log.Println(imageUrl)
}
return imageUrl
}
ParseJson
メソッドはurlを受け取りjsonをUnmarshalでparseし、画像URLを返しています。SearchImage
メソッドでは検索したい文字列を受け取りURLを生成しParseJsonに渡して画像URLを受け取る感じです。Resultの構造体...のなった方はいると思いますが、JSON-to-GOというツールを使って生成しました。JSONオブジェクトを入れると構造体をいい感じで生成してくれるやつです。
2. slackのコメント監視、画像URLの送信
次にslackへ画像URLを送信やメンションの受け取りなどの行うslack.go
を以下のように書いていきましょう。
package main
import (
"log"
"regexp"
"github.com/nlopes/slack"
"strings"
)
func Run(api *slack.Client) int {
var image string
rtm := api.NewRTM()
go rtm.ManageConnection()
for {
select {
case msg := <-rtm.IncomingEvents:
switch ev := msg.Data.(type) {
case *slack.HelloEvent:
log.Println("====Start====")
case *slack.MessageEvent:
fmt.Printf("Message: %v\n", ev)
if strings.Contains(ev.Text, "botのユーザーID") { // ex: <@U9U7Z06CV>
rep := regexp.MustCompile(`botのユーザーID`) // ex: <@U9U7Z06CV>
image = rep.ReplaceAllString(ev.Text, "")
image = SearchImage(image)
rtm.SendMessage(rtm.NewOutgoingMessage(image, ev.Channel))
}
case *slack.InvalidAuthEvent:
log.Println("Invalid credentials")
return 1
}
}
}
}
slackの情報を取得はnlopes/slackパッケージを用いて実装しています。今回はメッセージ機能を用いて画像のURLを送りたいという事でcase *slack.MessageEvent
を見てください。こちらではbotに対してメンションでメッセージを送信された際に先ほど作成したSearchImage
メソッドを使い画像URLを取得しslack上に送信する感じになっています。起動するまではユーザーIDがわからないです。
3. とりあえず起動
最後にmain.goを作成します。
package main
import (
"github.com/nlopes/slack"
"os"
)
func main() {
token := slack.New("slackのAPIトークン")
os.Exit(Run(token))
}
maing.goを作成後、go run main.go
で起動してみてください。====Start====
と表示されれば起動成功です。
4. ユーザーIDの設定
起動後、botに対してメンションを送ってください。今回はbotに対してメンションで「りんご」と送ってみたいと思います。
その際にログで以下のようなものが表示されると思います。
りんごの前に赤枠で囲ってある<@U9U7Z06CV>
がbotのユーザーIDになります。slack.go
のbotのユーザーID
と書いてる箇所を自分のbotのユーザーIDに変更しましょう。
5. 完成
botに対してメンションを送って画像のURLが返ってくれば完成です。
今回作成したbotを各チャンネルで使いたい場合は、使いたいチャンネルに追加して行って下さい。
まとめ
無事に画像が取得できましたか?何かあればこちらにもソースコードをあげてあるのでぜひ見て下さい。
golangで初めてbotを開発して見ましたがJsonのparse処理など慣れない部分は多々ありました。現状slackでは.svgの画像を表示することができないため.png, .jpgの画像をのみ取得する必要があるかもしれません。今後
、and検索or検索にも対応したいです!