🖼️

LGTM画像を作成するSlack Appを作ったお話

2021/12/21に公開

モチベーション

皆んな大好きLGTMですが、作成するサービスがいっぱいありますよね。
自分も幾つかのサービスを使い分けてLGTM画像をPRのapprove時に貼り付けています。

何番煎じだよって感じですが、Slack App(bot)で作成できたら、チャットでも使えるんじゃないかなーと思い作成してみました。

はじめに

今回作成しようとしたbotの前に、以下のGoogle Apps Script(以下GAS)で動く簡単な画像検索のbotを実装していました。
https://github.com/k2tzumi/pic-search-slash-command

Custom Search APIを使ってSlashコマンドで指定されたワードから適当な画像のURLを一つレスポンスするというものです。
簡単な処理をさくっと動かすにはGASは楽でいいです。[1]
画像検索はできているので後は画像加工が実現できれば良さそうです。
サーバーレスで画像変換を行っている事例はいくつか見かけていたので、GASでも出来るのか?という興味本位でやってみました。

3行まとめ

長くなるので、結論から先に3行まとめます。

  • GAS単体では画像変換は難しい
  • GASはライブラリ使えないので自分でなんとかする必要がある
  • 画像変換サービスのCloudinaryが神

既に出落ち感が漂っていますが、興味があれば続けて読んで頂ければと思います。

Take1

画像変換ライブラリの結構の割合でImageMagickに依存しています。
GASは完全に実行環境がブラックボックス化されていて、外部ライブラリに依存したものは使えなさそうです。

そこでJimpというpure jsなライブラリがあったので、こちらが使えないか?と思案しました。
https://github.com/oliver-moran/jimp

GASはGAS向けの専用のライブラリでないと使えません。
npmライブラリは、そのままでは使えないのですが、webpackで無理くりトランスパイルして使う事例を見かけたのでダメ元で試してみました。

結果あえなく惨敗しましたw
トランスパイルしてGASにpushする所までできましたが、そこから先が。。

残骸をおいておきます
https://github.com/k2tzumi/lgtm-slash-command-npm-library-based

webpack周りに苦戦しながら色々調べてみましたが、駄目でした。

なぜ駄目なのか?こちらの記事にまとめてくれていますが
https://kenchan0130.github.io/post/2019-12-25-1

使用するライブラリの内部にPromiseが使われていた場合、GASでは動作しないため実行時エラーになってしまいます。Babelを使用したとしても、Promiseをトランスパイルできるわけではないため、Promoseが使用されていないライブラリを探すか自身で実装する必要があります。

Promiseを使っているので駄目でした。。

Take2

GAS上でイメージライブラリを使えないことがわかったので、サクッと方針転換しました。
GAS上ではなく、外部APIを使えばいけるのでは?と考えました。
まず考えたのは、Google謹製のAPI群です。GASとの親和性も高いしマッチするのであればいいなと。
ざっと調べた感じでは、簡単な画像切り抜きとかはできそうですが、今回のやりたいことにはマッチしなさそうでした。
次に調べたのはクラウドサービスです。調べていた所、 Cloudinaryが良さそうでした。
調べた結果、色々できそうでした。何より無料枠で遊べるのが素敵でした。

というわけで、できたコマンドがこちらです。

https://github.com/k2tzumi/lgtm-slash-command


ヨシ!

色々工夫している所

  • SlackAPIの3秒ルールを回避した
    画像変換処理はどうやっても3秒以内にレスポンスできないので、非同期化してレスポンスするようにしました。
    非同期化の仕組みはこちらを利用しています
    https://zenn.dev/articles/58354fb4d05038
  • GASでイメージをレスポンスできないので、Slackにアップロードして外部リンク化して公開
    GitHub等にそのまま貼り付けられる様に、加工した画像を参照できるようにしました。
    pub_secret 付きにすることでSlack自体の認証も不要になっています。
  • Cloudinaryのクレジットを使いすぎないように制御
    変換のみを行うようにして、変換後はストレージから削除するようにしています。
    画像配信自体もSlackから行われるので、ネットワークの使用量は増えないです。
  • 画像にオーバレイするテキストが読みやすくする工夫
    レイヤーテキストのスタイルを色々頑張って調整しています。レイヤーテキストに影をつけて浮かび上がらせたり、オーバーレイする画像のカラーをpickして [2] 中間色でレンダリングしたり。。
    初めてCloudinaryのAPIを使いましたが、本当に使いやすく神でした!

最後に

こちらの記事は書きかけで放置していたものを供養する意味でアドベントカレンダーに掲載させて頂きました。
1つの記事で2度美味しい感じになればと思います。

「Cloudinaryはいいぞ」ということで興味がある方向けにスターターアカウント用の招待コードもお知らせしておきます。

https://cloudinary.com/invites/lpov9zyyucivvxsnalc5/w9frhigoqsj7nhf3umug

今年もこちらのBot以外にもGASでSlackBotをいくつか作成していますが、無料でここまで出来るのは本当にありがたいことです。
ただ先月にSlackのホスティング環境ができたみたい なので来年からはそちらでも遊んでみたいと思います。

脚注
  1. 実装が楽という訳ではなく、他のサーバーレス環境を使い始めるまでのステップが格段に少ないという意味です。エンジニアなら殆ど持っているであろうGoogleアカウントだけがあればいい ↩︎

  2. upload時に colors:true するだけで、使われているカラーコードの割合がレスポンスされます。なんと至れり尽くせりなんでしょう! ↩︎

Discussion