コロナ禍を乗り切るSlackアプリを開発してコミュニケーション向上

本記事で紹介しているサービスは費用の都合でサービスを休止しています。

# 作ったもの

Slackのテキストメッセージの代わりに漫画でコミュニケーションする「[comawari](https://slack.com/apps/A01CJ8CHWGL-comawari)」というSlackアプリです。
[<img width = 139 src = "https://platform.slack-edge.com/img/add_to_slack.png">](https://slack.com/oauth/v2/authorize?client_id=225541342901.1426284608564&scope=commands&user_scope=chat:write)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250158/c0a8225f-4e3b-92e0-1335-859588768b3c.png)

Slack上でモーダルを開いてどの画像にセリフを乗せるか選んで投稿できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250158/47ed4d85-af3c-b9cc-04ef-dbc1e493fd2f.png)

2020年11月現在、以下のサイトから画像データを利用させて頂いています。
[ブラックジャックによろしく](https://www.tadapic.com/blackjack.php)
[ジブリ](http://www.ghibli.jp/info/013344/)

# 仕組み

SlackのOAuth認証を経て、Slash CommandsとInteractivityという仕組みを利用して漫画を投稿します。

## OAuth
リダイレクトURLで渡されたcodeを[SlackAPI](https://api.slack.com/methods/oauth.v2.access)に問い合わせるとアクセストークンを取得できるので安全なストレージに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250158/c45b65d9-6994-0c27-0f31-71300e96fda6.png)
リダイレクトURLはSlackアプリ管理画面で指定できます。

## Slash Commands
Slashコマンドが実行されると叩かれるcomawariのAPIが[モーダルを開くSlackのAPI](https://api.slack.com/methods/views.open)を叩きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250158/b39b1b09-f30d-4725-9dd0-76053d77d6ac.png)

## 投稿
ユーザがモーダルで送信ボタンをクリックするとSlack管理画面のInteractivityで指定したAPIが叩かれます。送信したユーザのアクセストークンを利用し、ユーザに成り代わり漫画を表示する投稿を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250158/4257ee79-cd17-29e6-47e8-3992d862866a.png)

# プログラム

comawariサーバはGo言語で書かれています。

## API
Ginというフレームワークを利用してAPIを構築しています。
https://github.com/gin-gonic/gin
軽量で使いやすい印象です。

## Slack連携
Ginで受け取ったリクエストデータからgolang標準ライブラリのhttpでSlackAPIにリクエストを送っています。
例えば、アクセストークンを取得する箇所はこんな感じです。

```golang
// 送られてきたコードをアクセストークンに変換
values := url.Values{}
values.Set("code", code)
values.Add("client_id", SlackClientID)
values.Add("client_secret", SlackClientSecret)

req, err := http.NewRequest(
	"POST",
	"https://slack.com/api/oauth.v2.access",
	strings.NewReader(values.Encode()),
)
```

## 画像描画
このサービスのキモの画像描画もgolang標準ライブラリのimageを使って描画しています。
文字の描画は比較的簡単にできるのですが縦書きにする機能はありませんので文字を一文字ずつ分解してX,Y座標指定で描画するようにしています。

こちらの画像はリアルタイム描画ですがGCPの低スペックVirtualMachineでも100msを切るスピードで描画できます。
![image.png](https://comawari.rspepe.com/image?m=%E7%B8%A6%E6%9B%B8%E3%81%8D%E5%A4%A7%E5%A4%89%E3%81%A7%E3%81%97%E3%81%9F&b=serious%2Fbjyoroshiku%2Fbj01_ja-208)
_ブラックジャックによろしく / 佐藤秀峰_

## 元画像データ
漫画の元となる元画像はフリーで利用しても良い画像を選びテキストエリアを定義したJSONと一緒にgithubに保存しています。
comawari立ち上げ時にgithubからCloneしてgolangオンメモリに配置して利用しています。
その内、リポジトリをオープンにして自由にプルリクで画像を追加できるようにしたいです。

## インフラ

サーバはGCPのComputeEngine(n1-standard-1)を利用して、Dockerでcomawariサービスを立ち上げています。
Dockerfileはこんなです。

```dockerfile
FROM golang:1.15.2

ENV TZ Asia/Tokyo

RUN go get github.com/cespare/reflex

WORKDIR /root
RUN mkdir /root/.ssh
COPY ssh /root/.ssh/
RUN chmod 600 /root/.ssh/id_rsa
RUN touch /root/.ssh/known_hosts
RUN ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts

WORKDIR /data
RUN git clone git@github.com:rspepe/comawari-data.git

WORKDIR /go/src/github.com/rspepe/comawari
COPY src .

EXPOSE 80 443

CMD ["/usr/local/go/bin/go", "run", "/go/src/github.com/rspepe/comawari/main.go"]
```

サーバは立ち上げて数週間ですので無料枠で稼働しています。無料枠が終わってもポケットマネーで何とかなりそうですが仮にトラフィックが増えてきて費用が捻出できなくなったら困っちゃいます。

## ローカル開発
Slackからローカルマシンをコールしてもらうため[ngrok](https://ngrok.com/)を利用しています。
利用方法については別の方の記事を参考にいたしました。
https://qiita.com/mininobu/items/b45dbc70faedf30f484e

# Slack審査
Slackアプリとして公開するためにはAppleStoreと同じように審査が必要です。
[ランディングページ](https://comawari.rspepe.com/slack/landing)を作ってプライバシーポリシー宣言やユーザサポートを考えなきゃいけなかったりとなかなか大変でした。

## 指摘事項

### OAuthで要求するSlackパーミッション多すぎ
サービス実現に不要なパーミッションを要求パーミッションから外す。

### アクセストークンをユーザが消せるように
/deauth_coma コマンドを新設し、実行するとアクセストークンを削除するように対応。メールでの対応だとなりすまして認証解除の恐れがあるため。

### ユーザサポート
/support_coma コマンドを新設し、メッセージを私に送られる機構を構築。メールでの連絡だとスパム扱いになって見過ごす可能性があるため。

# 残った課題

## 費用
楽しいサービスが作れたのでなるべく維持していきたいのですがサーバ運用費が高くなると維持が難しくなっていきそうです。そうなった場合、マネタイズも考えないといけません。Dockerコンテナで動いているのでDockerが動く安い環境であればどこへでも持っていけます。

## 括弧対応

「」や【】みたいな括弧に対応していません。漫画のコマにはなかなか出てこないので対応しなくても良さそうですがなんか良い対応方法がないか検討しています。

## フォント
アラビア語とか中国語とかの言語には対応しておらず文字が豆腐になってしまいます。フリーのフォントを探していろいろな使い方ができるように改善したい。

## 国外輸出
日本語だけの対応ですがせっかくSlackが全世界で使われているので海外の方にも使っていただきたいところです。版権的に難しそうですがアイアンマンとかできればいいのに。

# 感想
このサービスは数年くらい前からやりたかったことなので実現できて凄い達成感。
以前、チャレンジしたときはHTMLとJSで画像の上にテキストを縦書きにした程度でした。
Slackという優れたコミュニケーションツールとgolangの開発力を地道に上げたことが功を奏しました。
少しずつ改善を続けてもっと良いものができると信じ、開発を続けます。

# 謝辞
このサービスを作るにあたり二次利用を許可してくださった佐藤秀峰さん（本記事公開時点では未事後報告）、常識の範囲での利用を許可して頂いたスタジオジブリさんには感謝しかありません。
本当にありがとうございます。