貼ったURLのプレビューができるQuip Live Appを作りました

こんにちは。co-meetingの木村です。

この記事は[Salesforce Platform Advent Calendar 2019](https://qiita.com/advent-calendar/2019/salesforce-platform)の10日目です。

今回はQuip Live Appを作りました。本当はもうちょっと便利なQuip Live Appを作ろうと思ったんですが、難しかったので断念し、緊急でちょいLive Appを作りました。

# できたもの

URLを貼るとOGP（Open Graph Protocol）をいい感じにプレビュー表示してくれるものです。[^1]

[^1]: そもそもなぜQuipはプレビューしてくれないのか。

![url-preview-quip-live-app](https://user-images.githubusercontent.com/877015/70464658-acba5a80-1b02-11ea-9843-35f372c351d9.gif)

ソースコードは以下に公開したのでご自由にお使いください。[^2]

[^2]: 緊急で作り使ってはいないのでバグはきっといっぱいあります。しかし、特にメンテする気はありません。サンプル的にお使いください。

https://github.com/atskimura/url-preview-quip-live-app

# Quip Live Appとは

[Quip](https://quip.com/)はSalesforceが買収した文書ベースのコミュニケーションツールです。Google DocumentやDropbox Paperが比較的近いでしょうか。

[Quip Live App](https://quip.com/about/live-apps)は、Quipの文書内にいろいろなアプリを追加できる機能です。標準でカンバンボード、カレンダー、draw.ioなどが提供されています。

一つ用意されているテンプレートをそのまま公開してみました。参照専用ですが、以下から見ることができます。この文書ではカンバンボードとdraw.ioのアプリが使われています。

https://quip.com/bb4rATaa9jaP

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27267/d6441686-3d77-f855-4cbd-68aaf472d5e2.png)

draw.ioのアプリなんかはなかなか便利です。あんまり使ってないですが、ふと思い出したときに使って、便利じゃないかと思っていたりします。

そして、このLive AppのAPIは公開されており、カスタムなLive Appも作ることができます。
Quip Live App自体は2017年に[公開](https://www.salesforce.com/jp/blog/2017/11/Introducing-Live-Apps-for-Quip.html)されましたが、結局Live Appを未だ公開できないし[^3]、残念なことにその後いまいち盛り上がっている感はないですね。

[^3]: 自組織のQuipのみで使用でき、他の組織では使えません。

私はDreamforceでこのセッション[Build Better Employee Experiences with Quip Live App & Real-Time Salesforce Data](https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJMHQA4)を聞いたのですが、そちらもがらがらでした。[^4]

[^4]: 今見ると動画見れますね。

# Quip Live Appの作り方

作り方はドキュメントがしっかりしているので、こちらを見てください。最初がチュートリアルになっているので、それをやるとイメージつくと思います。

[Quip Live Apps API Guide](https://co-meeting.quip.com/dev/liveapps/)

基本的にはReactで作れるようになっているので、とてもとっつきやすいです。

そして、 `npm start` して、Quip文書上で「ローカルリソースを使用」にするとローカルのコードでQuip上で動きますし、なかなかよくできています。ライブリロードはできず、この上のメニューの「再読み込み」をしないと反映されないのですが、アドオンの開発環境としてはとてもよくできています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27267/75b64d22-87a1-07c5-c4b4-f02a37562932.png)

# URL Previewの仕組み

入力されたURLのOGPを取得して、いい感じに表示するだけなのですが、[Content Security Policy（CSP）](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Security-Policy)周りでちょっと手こずったのでそこだけ記載しておきます。

Quip Live Appは基本的に外部へのリクエストを許可しません。Ajaxリクエストも画像の取得もです。リクエストを実行したい場合は、 `app/manifest.json` でCSPの設定ができるようになっています。

OGPの取得にはあらゆるサイトにリクエストを投げる必要がありますが、そんなゆるい設定はできないので、プロキシ的なサーバーを噛ますことにします。

今回は時間もないので、全部SaaSで済ましました。

OGPの取得には[OpenGraph.io](https://www.opengraph.io/)を使用、画像の取得には[Cloudimage](https://www.cloudimage.io/)を使用しました。

上記サービスを経由してOGP/画像を取得することで、以下のようにマニフェストファイルに設定すればLive Appからも取得できるようになりました。

```
    "csp_sources": {
        "connect_srcs": ["https://opengraph.io"],
        "img_srcs": ["https://<YOUR_CLOUDIMAGE_TOKEN_HERE>.cloudimg.io"]
    }
```

ちなみに、OpenGraph.ioは無料ライセンスは「100 requests monthly」で、Cloudimageの無料ライセンスは「個人利用のみ、25 GB Image Cache、25 GB Monthly Traffic」です。
ちゃんと使いたいときはお金を払うか、別サーバーを立ててください。

# URL Previewのセットアップ方法

セットアップ方法をこちらに日本語でも書いておきます。

## 1. Live Appを作成

[開発コンソール](https://quip.com/dev/console/)を開き、「Create a Live App」をクリックし、「アプリケーション ID」をコピーし、 `app/manifest.json` の `id` 項目に設定します。

## 2. OpenGraph.ioのAPIキーを追加

- OpenGraph.ioのAPIキーを[ここ](https://www.opengraph.io/)から取得
- `App.jsx` の `OPENGRAPH_IO_API_KEY` 変数に取得したAPIキーを設定

## 3. CloudimageのCustomer Tokenを追加

- Cloudimage Customer Tokenを[ここ](https://www.opengraph.io/)から取得
- `App.jsx` の `CLOUDIMAGE_TOKEN` 変数に取得したトークンを設定
- `app/manifest.json` の `csp_sources.img_srcs` にトークンを設定

## 4. ビルド

```bash
npm run build
```

## 5. アプリをアップロード

1. [開発コンソール](https://quip.com/dev/console)を開く
2. 作成したアプリをクリック
3. 「Upload Bundle」をクリックし、 `app/app.ele` を選択する。
4. 「Upload」をクリック

## 6. 以上でQuip上で使えるようになります

ただ、この時点では自分しか使えません。組織の他のユーザも使えるようにするには、開発コンソールで「リリース済みビルド」[^5]をクリックして、アプリをリリースする必要があります。

[^5]: 訳がおかしい。

# 終わりに

今回はネタがなくて苦しみました〜〜。あまり書かれないQuipネタを書いてみましたが、いかがでしたでしょうか？

最初はPackaging 2を書こうかと思ってたんですが、転送アップグレードがSpring'20までリリースされないということで自社プロダクトで使わないことになったのでやる気が失せてしまいました。