LOB Advent Calendar Advent Calendar 2018 - Qiitaカレンダー18日の記事です。
我が社のCTOことmojibkoさんが、TypeScript で書いた Slack Slash Command を Firebase で動かしたらめちゃくちゃ簡単だった件について でTypeScriptでslash commandを作っていたので、対抗して私はGoでslash commandを作ってみました。(firebaseだとめっちゃ簡単だよ的な所はご紹介できないのですが、すみません。)
何作ったんや
/big :custom絵文字:
を打つとmigawari(slack bot)が画像として大きく表示してくれる
どうやって作ったの
-
slash commandの設定をする
- [CTOの記事] slack側で slash commandを設定するを参考になさってください
-
Goの実装
実装はこんな感じになります。
func main() {
logger.Infof("Start big-stamp server.")
http.HandleFunc("/", handle)
log.Fatal(http.ListenAndServe(":" + os.Getenv("PORT"), nil))
}
func handle(w http.ResponseWriter, r *http.Request) {
token := os.Getenv("SLASHCOMMAND")
if err := r.ParseForm(); err != nil {
http.Error(w, "Error parsing form.", http.StatusBadRequest)
return
}
channelID := r.Form.Get("channel_id")
texts := strings.Split(r.Form.Get("text"), " ")
stampMap := map[string]bool{}
for _, text := range texts {
stampMap[text] = false
}
sendMsgUrl := "https://slack.com/api/chat.postMessage"
emojiMsg := emojiList(w, token)
for k, imgUrl := range emojiMsg {
ek := fmt.Sprintf(":%s:", k)
if _, ok := stampMap[ek]; ok {
sendMsgUrlOption := url.Values{}
sendMsgUrlOption.Add("token", token)
sendMsgUrlOption.Add("channel", channelID)
sendMsgUrlOption.Add("attachments", "[{\"\": \"\", \"text\": \"\", \"image_url\": \""+imgUrl.(string)+"\"}]")
_, err := http.Post(sendMsgUrl+"?"+sendMsgUrlOption.Encode(), "", nil)
if err != nil {
http.Error(w, "can't http post.", http.StatusBadRequest)
}
}
}
}
func emojiList(w http.ResponseWriter, token string) (map[string]interface{}) {
urlOption := url.Values{}
urlOption.Add("token", token)
url := "https://slack.com/api/emoji.list?" + urlOption.Encode()
resp, err := http.Post(url, "", nil)
if err != nil {
http.Error(w, "can not get emoji list.", http.StatusBadRequest)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
http.Error(w, "cnan not response read.", http.StatusBadRequest)
}
var result interface{}
if err = json.Unmarshal(b, &result); err != nil {
http.Error(w, "Error parse json.", http.StatusBadRequest)
}
msg := result.(map[string]interface{})
var emoji interface{}
eb, err := json.Marshal(msg["emoji"])
if err != nil {
logger.Errorf("can not emoji marshal err: %v", err)
http.Error(w, "can not emoji.list.", http.StatusBadRequest)
}
if eb == nil {
logger.Error("not set emoji.")
}
json.Unmarshal(eb, &emoji)
emojiMsg := emoji.(map[string]interface{})
return emojiMsg
}
3.サーバーにデプロイ
これは個人的に作ったものなので(*所属している団体、企業とは関係ありません)、AWSのec2インスタンスにデプロイして使用しています。
local環境での開発時は、Slack APIで薦められているngrokを使えば、localhostで動いているサーバーを、LANの外からアクセスできるようにできるようになるので、それをRequest URL
に設定すれば、簡単に開発することができます。
まとめ
今回作ったslash commandはLineのスタンプ感覚で使いたい時などに活躍します。
これからも色々slash commandで遊んでいこうかな〜と思っています。
我が社では、サーバーサイドはGo, フロントエンドはReactとTypeScriptで開発を行なっています。
興味がある方はぜひ我が社へ〜〜〜💨