Webhookを使ってQiita:Teamのデータをバックアップする方法


「もしも」に備えてバックアップがあると安心。

# 設定方法

Qiita:TeamのWebhookを受け取るHTTPサーバを設置する

```php:qiita-webhook.php
<?php
const DBNAME = 'qiita_webhook';
const HOST = '127.0.0.1';
const USER = 'root';
const PASS = 'root';

$input = file_get_contents("php://input");
$pdo = new PDO(sprintf('mysql:dbname=%s;host=%s;charset=utf8', DBNAME, HOST), USER, PASS, array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES => false,
));
$insert = $pdo->prepare('INSERT INTO event (data, occurred_on) VALUES (?, NOW())');
$insert->execute(array($input));
```

Webhookで受け取ったデータを保存するテーブルをMySQLに作る

```sql:qiita-webhook.sql
CREATE TABLE `event` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `data` longtext NOT NULL,
  `occurred_on` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

管理画面に行ってWebhookを設定する

![Webhook_Setting___Qiita_Team.png](https://qiita-image-store.s3.amazonaws.com/0/889/09977289-d84c-655c-68fc-11927a12d984.png "Webhook_Setting___Qiita_Team.png")

Event Received URLには先ほど設置したHTTPサーバのURLを設定する。受け取るイベントはとりあえず全部にチェックを入れておく。


# どんなデータが送られてくるか？

ドキュメントが見当たらなかったので、試しに記事を投稿してみたりして、HTTPリクエストをキャプチャしてみた。

管理画面にあるように、記事の新規投稿・変更・削除、コメントの新規投稿・変更・削除、メンバの追加・削除のイベントが飛んでくることを確認できた。

HTTPリクエストはどれもPOSTメソッドで、データはJSON形式で送られてくる。以下にサンプルデータを挙げる。JSONは見やすいようにフォーマットしたが、実際はインデントなしの1行のデータになっている。

## サンプル1: HTTPヘッダ


X-Qiita-Event-Modelというのが、設定画面のチェックボックスに対応しているらしく、item, comment, memberの三種類。これで判定しなくても、JSONデータの中にmodelというキーで同じデータがあるので、それを使ってもいいかもしれない。

```http
POST /qiita-webhook.php HTTP/1.1
Host:example.com
Connection:close
X-Qiita-Event-Model:item
Content-Type:application/json
User-Agent:Qiita:Team
Accept-Encoding:gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:*/*
X-Newrelic-Id:VQQAUFNUGwEGV1FWAwg=
X-Newrelic-Transaction:PxQAVVBaWgMFXVcHDwYGXgEFFB8EBw8RVT8=
Content-Length:1041
```

## サンプル2: 記事

`action` キーでイベントの種類がわかる。

* created: 新規作成
* updated: 変更
* destroyed: 削除

ストック、ストック解除のイベントは飛んで来ない様子。共同編集モードに切り替えたときはupdatedイベントが飛んでくる。

プロジェクトページについては、記事に関するイベントは飛んでこなかった。

```json
{
  "action": "created",
  "item": {
    "id": 80221,
    "uuid": "336ccd83a6e08417eae0",
    "user": {
      "id": 889,
      "url_name": "suin",
      "profile_image_url": "https://secure.gravatar.com/avatar/152ead2a935d1c21b585286d7587b183"
    },
    "title": "Webhookテスト",
    "created_at": "2014-06-16 18:27:38 +0900",
    "updated_at": "2014-06-16 18:27:38 +0900",
    "created_at_in_words": "less than a minute",
    "updated_at_in_words": "less than a minute",
    "tags": [
      {
        "name": "PHP",
        "url_name": "php",
        "icon_url": "/icons/medium/missing.png",
        "versions": [
          "5.4"
        ]
      },
      {
        "name": "JavaScript",
        "url_name": "javascript",
        "icon_url": "/icons/medium/missing.png",
        "versions": []
      }
    ],
    "stock_count": 0,
    "comment_count": 0,
    "url": "https://xxxx.qiita.com/suin/items/336ccd83a6e08417eae0",
    "created_at_as_seconds": 1402910858,
    "team_url_name": "xxxx",
    "lgtm_count": 0,
    "private": false,
    "coediting": false,
    "raw_body": "# Markdown\n\n本文・・・\n",
    "body": "<h1>\n        <span id=\"1-1\" class=\"fragment\"></span>\n        <a href=\"#1-1\"><i class=\"fa fa-link\"></i></a>Markdown\n      </h1><p>本文・・・</p>\n",
    "stock_users": []
  },
  "model": "item"
}
```

## サンプル3: コメント

`action` キーでイベントの種類がわかる。

* created: 新規作成
* updated: 変更
* destroyed: 削除

コメントはプロジェクトページへのものもイベントが飛んできた。

```json
{
  "action": "created",
  "comment": {
    "id": 42405,
    "uuid": "1f4297a4d3db4b78937d",
    "user": {
      "id": 889,
      "url_name": "suin",
      "profile_image_url": "https://secure.gravatar.com/avatar/152ead2a935d1c21b585286d7587b183"
    },
    "body": "<p>コメントテスト</p>\n",
    "url": "https://xxxx.qiita.com/suin/items/336ccd83a6e08417eae0#comment-1f4297a4d3db4b78937d"
  },
  "model": "comment"
}
```

## サンプル4: メンバー

`action` キーでイベントの種類がわかるが、記事・コメントと違い、

* added: 追加
* removed: 削除

addedイベントは、メール招待した時点はイベントは発生せず、ユーザが登録したときに発生した。また、管理権限付与などの状態変化に対してはイベントが発生しなかった。

```json
{
  "action": "added",
  "user": {
    "id": 123456,
    "url_name": "suin",
    "profile_image_url": "https://secure.gravatar.com/avatar/b1e5bbf0065f97f5534d9722fea8fef4",
    "name": "",
    "url": "http://qiita.com/suin",
    "description": null,
    "website_url": null,
    "organization": null,
    "location": null,
    "facebook": null,
    "linkedin": null,
    "twitter": null,
    "github": null,
    "followers": 0,
    "following_users": 0,
    "items": 0,
    "teams": [],
    "image_upload": {
      "limit": 2097152,
      "used": 0
    }
  },
  "model": "member"
}
```

# おわりに

Qiita:TeamではSlackと統合できるようになったり、プロジェクトページができたりとどんどん便利になってますね。Webhookについては、まだブログ等で紹介がないようですが、ちょっとした工夫で業務が楽になっていきそうで楽しみです。