TwitterでSlackみたいな絵文字リアクションができるアプリを作った

遅ればせながら [クソアプリ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/kuso-app) に空きが出たので参加します！遅（執筆日:12/31）

▼過去作品も見てね
[2019年作品: ジャンケンが弱い僕はタブレットと合体した](https://qiita.com/okumura_daiki/items/43a00dfc2527cf0f6665)
[2018年作品: 「通知止まらんwww」を体験できるアプリを作った](https://qiita.com/okumura_daiki/items/ed6398c06c1b40d10c6c)

## はじめに
Slack便利！Slackみたいなカスタム絵文字をTwitterでも使いたい！
![Slack絵文字.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49696/a28c468b-2a86-3e1f-30df-d517937a07a0.png)

そうだ！こんな風に↓Twitterカードで画像を表示すればできそう！
という思いつきで作ってみました。
![オクムラダイキ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49696/4777e6c8-5685-3ace-f626-d50fadba8a51.png)


## 作ったもの
🔻文字リアクション
**🔗 https://moji-reaction.vercel.app/**

文字画像を生成して、URLをツイートするだけで、Slack絵文字風の画像が表示されます。
![文字リアクション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49696/881988c6-1d02-d89d-f237-a64cbb13c92b.png)
これで人に5000兆円を送れる
![スクリーンショット 2020-12-31 2.00.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49696/fb516a55-f1d3-496f-9acd-adcbf47e9540.png)

すでに様々な使われ方がされてて面白い・・・
![名称未設定 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49696/679dcbda-96ab-42e4-a194-d9ca35222533.png)

ぜひ使ってみてください〜！

## 仕組み
### 画像の動的生成
URLのパラメータによって画像を動的に生成しています。

[https://moji-reaction.vercel.app/api/image?text=いいね](https://moji-reaction.vercel.app/api/image?text=%E3%81%84%E3%81%84%E3%81%AD)
というURLでは「いいね」の文字画像を生成しますし、

[https://moji-reaction.vercel.app/api/image?text=👍](https://moji-reaction.vercel.app/api/image?text=%F0%9F%91%8D)
というURLでは「👍」の絵文字画像を生成します。

加えて「フォント」や「文字色」などもURLパラメータに追加することで、様々な画像を生成できるようにしています。

### Twitterカード表示
いわゆるOGP(Open Graph Protocol)というやつです。

ツイート画面にURLを貼ったタイミングで、Twitter botがURLにアクセスしてくるのですが、HTMLにOGタグを設定（下記参照）しておくと、そのタグの情報を元にTwitterカードを表示してくれる仕組みです。

先ほどの「👍」の画像を表示したいページ([https://moji-reaction.vercel.app/?text=👍](https://moji-reaction.vercel.app/?text=%F0%9F%91%8D))の場合、下記のようなOGタグを設定しておきます。

```「👍」の場合のOGタグ.html
<meta property="og:title" content="👍">
<meta property="og:image" content="https://moji-reaction.vercel.app/api/image?text=👍">
<!-- 実際には他のパラメータもついて、パラメータはエンコードしています -->
```

Twitterは上記の og:image に指定された [https://moji-reaction.vercel.app/api/image?text=👍](https://moji-reaction.vercel.app/api/image?text=%F0%9F%91%8D) の画像を表示してくれるわけです。

## 技術的な話
Next.js (Reactのフレームワーク) を採用して、Vercel にホスティングしてます。

2020年は Next.js が日本でもだいぶ普及してきた気がします。便利。
Vercel は Next.js 製アプリのデプロイが楽すぎるのと、非商用でアクセスが少なければ無料で使えるのでクソアプリにもってこいです。

### 画像生成のライブラリ選定
画像の生成には、 Canvas API を Node.js で使えるようにする [node-canvas](https://github.com/Automattic/node-canvas) というライブラリを使いました。

最初は [Puppeteer](https://github.com/puppeteer/puppeteer) (ヘッドレス Chrome Node.js API ) を使ってHTMLのスクリーンショットを画像にする予定だったのですが、

→文字の幅を狭める方法をどうするか
→CSS Transform 使えばできそうだけど計算が面倒そう
→Canvas API の fillText を使えば文字の幅を自動で狭めてくれるので楽そう
→サーバー側で Canvas を使うなら node-canvas
→node-canvas で画像生成できるなら Puppeteer を挟む必要がない

ということで Puppeteer は不採用になりました。

ちなみに Node.js × Puppeteer で画像を生成したい方は [vercel/og-image](https://github.com/vercel/og-image) がとても参考になります。

### 絵文字対応
Twitterに表示するなら [Twemoji](https://twemoji.twitter.com/) でしょ。

でも、文字とTwemoji画像を並べてCanvasに表示するのめちゃくちゃ大変じゃん・・・。（あれ・・・ CSS Transform の計算する方が楽だったんじゃ・・・）

そんな時に救世主的なライブラリを見つけました！
[cagpie/node-canvas-with-twemoji](https://github.com/cagpie/node-canvas-with-twemoji)
そのまま使うとTwemoji画像を拡大して使う時に画質が荒くなってしまったので改変して使わせてもらってます。

### 画面UIの方
・CSS: [TailwindCSS](https://tailwindcss.com/)
普段から使い慣れてるので。便利なのでおすすめです。

・フォーム: [react-hooks-form](https://react-hook-form.com/jp)
今まで formik を使ってたのですが、ドキュメントを見れば普通のことは簡単にできました。formik でも hooks で書けますが、元から hooks で設計されてるのが良さそうかなと思いました。よくわかりませんが（普通に使いやすかった）。 ドキュメントが日本語対応してて神ですね。

・カラーピッカー: [react-colorful](https://github.com/omgovich/react-colorful)
カラーピッカーはReactの有名どころのが使い勝手微妙だったので react-colorful 使ってみました。シンプルで軽量でよかったです。

## コード
GitHubで公開してます
https://github.com/okmr-d/moji-reaction
（4日間で書いたので汚いのはご容赦ください🙏）

## おわりに
クソアプリ思いついた！と思って作ってみたものの、若干便利かもしれない微妙なものを生み出してしまいました・・・が、クソアプリアドベントカレンダーに3年連続で参加できてよかったです！クソアプリはいいぞ！（勉強にもなるし楽しい）

それでは皆さま、（執筆時大晦日なので）
https://twitter.com/okumura_daiki/status/1344373241339543553
![よいお年を.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49696/5c1d74c8-0b38-97d0-54b8-9ef2cde61b38.png)