Integromat で Facebook ページの新規投稿を WordPress サイトに記事として投稿する

## 背景

WordPress サイト構築の仕事をしている友人の手伝いとして、「顧客が運用している Facebook ページを構築する WordPress サイトに同期して欲しい」というものがありました。

> 目的が、Facebook ページのアーカイブだったのか、構築するサイトの記事を少しでも増やすためなのか、その辺は私には分かりませんでした。（Facebook ページのダウンロード機能はおせじにも良いものとは言えないので両方の目的があったのかなと思っています）

### 当時の解決方法

要件として、「新規の Facebook ページの投稿を、WordPress サイトの新規投稿にする」だけでなく、「過去の全投稿を WordPress サイトに投稿する」というものがありました。

当時も友人（WordPress のカスタマイズはするが、プログラミングをやる訳ではない）との議論の中で、「Zapier を使って新規投稿分だけはなんとかできないか？」などの話しも出たのですが、 [rnsk/wp-facebook-portal](https://github.com/rnsk/wp-facebook-portal) という WordPress プラグインを早い段階で見つけていたので、それを魔改造して対応しました。

魔改造という通りで、上記のプラグインは Facebook ページの投稿に対して、単純な同期を実現するのに対して、顧客の要望は以下のようなものがどんどんでてきて、正直 Zapier での対応は無理だなというのもあり、過去記事も新規記事もプラグインで済ませました。

- 画像が複数枚あれば、一つはアイキャッチにして残りは記事の中に埋め込み
- 動画があれば、動画のスナップショットをアイキャッチにして、動画は記事中に再生できるように埋め込み
- 記事のタイトルは「yyyy年MM月dd日の日記」とする
    - リリース後にプラグインの元の仕様と同じで良いと変更
- 画像に description があれば、それも画像の下に表示する
- 後は忘れました。。

過去記事も 1000 近くあった上に、顧客もどういう記事のパターンがあるか分からんという状況だったので、初回の同期後はかなりドキドキ。。

## Integromat

https://www.integromat.com/

Zapier も職場でカスタマーサクセスの部門で使っているのを手伝っていたので使いやすいなと思っていましたが、Integromat はさらにかゆい所に手が届く感じで良いです。

> 個別の App に関しては Zapier の方が作り込まれているなと思うものもありますし、Zapier の「いざとなれば Python とか書けるぜ」というのも好きなので甲乙つけがたいですが、無料の範囲でできることが多いのも Integromat の魅力の一つです。

今回は、魔改造プラグインまではいかないものの、Facebook ページの投稿を　WordPress にも投稿したいという要求をある程度満たせる部分まで Integromat で書いてみました。

### 今回の割り切り

- 対象にするのは画像付きの投稿だけ
  - `video`, `audio`, `file` のようなものは今回は対象外
- アイキャッチ等の設定はしない
- １日一回以下の投稿スケジュールぐらいを想定
    - 不定期に１日何度も更新されるようなケースは想定しない

最後以外はできなくも無いのですが、ボリュームがだいぶ増えてしまうので、これぐらいにしておきます :sweat_smile: 

### 注意点

Integromat の　WordPress App は XML-RPC の機能を利用します。ここが許容できない場合には利用ができません。 REST API & OAuth に対応してくれるといいんですが。

## 全体像

<img width="677" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/8f6d6328-9bb1-d848-662f-2e8691478eaa.png">

ちょっと分かりにくいですが、以下に上記のシナリオの流れを上から下に流れる形で表にしてみました。（番号は後述の個別の際に出てきます。)

|メイン|分岐A<br>attachement 複数|分岐B<br>attachement 一つ|
|:--|:--|:--|
|(`7`) Facebook Pages<br>Watch posts|||
|(`5`) Facebook Pages<br>Get post attachments|||
|(`19`) Router|||
||(`16`) Iterator||
||(`18`) HTTP<br>Get a File|(`20`) HTTP<br>Get a File|
||(`8`) WordPress<br>Upload a File|(`21`) WordPress<br>Upload a File|
||(`29`) Tools<br>Text aggregator||
||(`1`) WordPress<br>Create a Post|(`33`) WordPress<br>Create a Post|

簡単には Facebook ページの post に紐付いている attachement が 1 つか複数かによってフローを分けています。

> もちろんですが、実運用を考えると、これに加えて「attachement が存在しない」というケースも考慮する必要があります。

## 個別

### Facebook Pages Watch posts

<img width="198" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/3f5d7c61-9292-7a17-81ef-85c38346f3ee.png">

この辺は、実際の対象 Facebook ページに合わせてという部分が多々あります。（私は運用する Facebook ページを持っていないので、誰かのページの ID を指定してテストさせてもらっていました。もちろん WordPress への投稿は下書き状態にしています。）

今回は `Maximum number of returned posts` は `1` にしています。その後のフローで `attachments` を収集する際に、複数の投稿の複数の `attachments` を上手く捌く方法が分からず、しかたなく 1 にしています。

> ですので最終的に Integromat のシナリオをスケジュール実行する際に、そのスケジュール間隔で複数の投稿が行われるケースでは、投稿の同期漏れが生じるかもしれません。

### Facebook Pages Get post attachments

<img width="199" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/88bc88cd-7474-228d-c3c8-c01e584cb2fa.png">

> `7` は一つ前の Watch posts に割り当てられた番号です。表も参照してください。

ここで、一つの post に紐づく `attachments` を全て取得してきます。Watch post の結果にも、画像リンクが付いてきますが、全部では無いのと、サイズが小さいのでこちらで収集します。

### Router 

#### attachments が複数ある

<img width="283" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/a44a3ae1-7327-e2f4-7b68-9b21b3a4b1f7.png">

attachements が複数ある場合は配列として返ってきます。よって、配列が存在すればこちらです。

#### attachments が一つ

<img width="278" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/2b45b060-9675-2db1-ac88-2be2c677de84.png">

逆に一つの場合は `attachments` の配列は存在せず、複数の場合に　 `attachments` 配列に含まれる
 `media` が同じ階層に登場するので、そちらの存在を確認します。

> つまり attachments も media も存在しなければ画像等の無い post である可能性が高いです。そういう分岐も Router から生やしておけばいいでしょう。
> ただ、WordPress のプラグインとして書いていた時もだいぶ Facebook の公式ページを参照しつつ書いていましたが、実運用を考えるなら最新の公式ドキュメントを読んで、もう少し細かい条件設定が必要になるかもしれません。
> プラグイン書いてた時は `subattachments` とかも参照してたので、その辺が、この　Integromat Facebook App でどういう扱いなのかはよく分かっていません。

### Iterator

<img width="199" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/d45f07ff-6f46-0089-c75f-9448ee63951a.png">

単純に `attachments` の配列でイテレートします。

### HTTP Get a file

<img width="199" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/3631d2fd-1ff1-ca2a-a2b9-1d2f54406ff5.png">

`attachments` として紐づく `media` ファイルをダウンロードします。想定としては `image`, `video` です。（`audio` や `file` の場合は WordPress 側でどういう扱いになるかというのがあるので、そういう Facebook ページを同期対象にする場合は要テストです）

上記は Iterator の方の `HTTP Get a file` ですが、単一ファイルを対象にする方は `5` の方を直接参照すれば良いです。（`5. Media: Image: Download link` となる）

> ここで Image 決め打ちにしているので、video 等も対応するなら、手前で分岐を挟む等する必要があります。

### WordPress Upload a file

<img width="197" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/b3951c5d-f1e0-0eea-2fbb-6e3b7060261a.png">

これはどちらの分岐でも同様になります。HTTP Get a file で取得したリンクをアップロードします。

### Text aggregator

<img width="198" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/44aae75d-e836-4164-0ed3-b555d6b357e9.png">

ここでやっていることは、`Iterator` で複数の `attachments` のファイルをダウンロード/アップロードした結果を集約し、最終的に WordPress の記事投稿の際に貼り付ける img タグの一覧を作ることです。

> ここで集約をしないと、`attachments` の数だけ WordPress の記事が投稿されてしまいます :scream: 

ここのタグは WordPress サイトに合わせてカスタマイズすれば良いと思います。

> video の対応をするなら `[video]` のようなタグが WordPress 側で使えるので Integromat の `switch` などで、拡張子で分岐してタグを書き分けるなどの方法が考えられます。

### WordPress Create a post

<img width="199" alt="Integration_Facebook_Pages__WordPress___Integromat.png" src="https://qiita-image-store.s3.amazonaws.com/0/904/aacb584a-07fc-c2dc-96ba-64c9844d32f6.png">

`Content` に先程の `Text aggregator` で生成した `img` タグ群を入れています。もちろん単一の attachment の場合には、ここは `WordPress Upload a file` の戻り値をそのまま使えば良いです。(つまり `<img src="{{21.link}}" alt="" width="300" height="300" class="alignnone size-medium wp-image-26" />` ですね)

`Title` ですが、内容としては「Facebook ページの投稿内容を改行で切って、1 つ目をタイトルにする」というものです。画像のみの投稿があったりすると機能しませんが、そこは自分のページの運用なので上手くやればいいでしょう。もちろん、 `if` を使って投稿内容の有り無しで分岐することもできます。

## 最後に

今回は、Facebook ページの新規投稿を WordPress にも投稿するという事を Integromat を使って、不完全ながらも自動化するという事をやってみました。

エンジニアではない方にはもちろんですが、エンジニアの方であっても WordPress 案件は、一度作って終わりになりがちなので、手離れよくするためにもお客様の方で（多少勉強してもらってでも）メンテナンスができる状態にできた方が双方にとって気持ちのいいものになるのではと思います。その一つの方法として Integromat は良いのではと思います。

個人的には、社内システム系も割りと kintone/Salesforce/Zendesk をバリバリカスタマイズして使おうとする人も非エンジニアでもいらっしゃったりするので、そういう方にできる部分はやってもらおうという中で、こういうグルー的なアプリは役に立つのではと思っています。