自分の Qiita 記事の閲覧数を取得して報告する BOT を作ってみた

ようやく記事が 10 件を超えたので、Qiita API を使って閲覧数を取得してみようと思います。
そんでもって、LINEWORKS BOT で簡単に確認できるようにしたいと思います！

＜完成図＞
![qiitabot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363367/ba6d318f-14f2-bdbf-c45f-1f071c94c9e1.png)

右下の固定メニューから `Qiita Report` をクリックするとレポートを送信してくれる感じ。
マイページからだと、いいねの数しかわからないから、実はかなり便利なのでは？と思っています。

# 全体の流れ

1. LINEWORKS BOT を設置
2. BOT に固定メニューを登録
3. Qiita のアクセストークンを取得
4. Qiita の記事を取得する関数を作る
5. BOT にレポートを送信させる

割と今回は長くなりそうですね。
長文駄文にて大変恐縮なのですが、お付き合い願いますね！(*‘∀‘)

## 1. LINEWORKS BOT の設置

まずは、LINEWORKS BOT を設置します。
もう作ってある方は飛ばしちゃってください。

作り方については以下の記事を参考にしてください。
[GoogleAppsScript で LINEWORKS のチャット BOT を作る](https://qiita.com/kunihiros/items/a94221ad7c9f4de84cf8)

## 2. BOT に固定メニューを登録

GoogleAppsScript に固定メニューを登録する `function` を作ります。
[固定メニューの登録 API](https://developers.worksmobile.com/jp/document/1005012?lang=ja)

```js:regMenu.gs
function regMenu(){
  const options = setOptions();
  const uri = "https://apis.worksmobile.com/r/" + options.apiId + "/message/v1/bot/" + options.botNo + "/persistentmenu";
  const json = {
      "content": {
          "actions": [{
              "type": "message",
              "label": "Qiita Report",
              "postback": "qiita"
          }]
      }
  };
  const req_options = {
    "method": "post",
    "headers": LINEWORKS.setHeaders(options),
    "payload": JSON.stringify(json)
  };
  Logger.log(UrlFetchApp.fetch(uri, req_options));  
}

```
`function` ができあがったら、ブラウザ上で実行します。
![regMenu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363367/8fdaeaaa-dbf0-af9b-00f3-543629ef3bc9.png)

これで、BOT とのトーク画面の右下に、固定メニューが登録されます。

## 3. Qiita のアクセストークンを取得

Qiita にログインして、右上のメニューから `設定` を選びます。
![qiita_conf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363367/ff99124e-09a7-33d0-fe30-8d4e5fdd2b56.png)

設定のページで `アプリケーション` を選んで `新しくトークンを発行する` をクリックします。
![qiita_token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363367/96628b2f-be30-411f-fedb-9c553015ff7e.png)

スコープが 4種類出てくるので、取り敢えず `read_qiita` にはチェックを入れてください。
`発行する` をクリックするとトークンが発行されます。

発行されたトークンは必ずどこかに控えておいてください。
あとで再確認することができないのでー。

## 4. Qiita の記事を取得する関数を作る

トークンが手に入ったので、GoogleAppsScript で自分の記事を取得して、閲覧数やいいね数を GET していきましょう！

公式ドキュメントに載っている、[認証中のユーザ記事一覧取得 API](https://qiita.com/api/v2/docs#get-apiv2authenticated_useritems) を利用します。


```js:getMyQiita.gs
function getMyQiita() {
  const token = "発行したアクセストークン";
  const uri = "http://qiita.com/api/v2/authenticated_user/items/";
  const options = {
    headers : {
      'Authorization' : 'Bearer ' + Token
    },
    method : 'get'
  }
  const res = JSON.parse(UrlFetchApp.fetch(uri, options));
  return res;
}
```

これで、自分の記事内容のすべてが GET できました！
・・・そう、すべて、です。
`res` の中身を見てみるとこんなことに！

```
[{rendered_body=<p>今度は <a href="https://docs.atlassian.com/software/jira/docs/api/REST/8.2.4/" rel="nofollow noopener" target="_blank">JIRA Server platform REST API</a> を使用することになりました。</p>

<p>とりあえず基本認証をすれば使えるとのことで、英語のドキュメントを読み漁ることに。<br>
<a href="https://developer.atlassian.com/server/jira/platform/basic-authentication/" rel="nofollow noopener" target="_blank">Basic authentication</a></p>

<p>さぁ Google 翻訳さんの出番ですよ！<br>
いつもありがとうございます。m(_ _)m</p>

（以下略）
```

一番最初が `rendered_body`、つまり記事内容なので、長々と HTML が続いております。
なので、欲しい情報だけを抜き出していきます。

```js:getMyQiita.gs
function getMyQiita() {
  const token = "発行したアクセストークン";
  const uri = "http://qiita.com/api/v2/authenticated_user/items/";
  const options = {
    headers : {
      'Authorization' : 'Bearer ' + Token
    },
    method : 'get'
  }
  const res = JSON.parse(UrlFetchApp.fetch(uri, options));
  const reports = res.map( function(report) {
    return { "title" : report.title, "likes_count" : report.likes_count, "page_views_count" : report.page_views_count };
  });
  return reports;
}
```

タイトルといいね数とページビュー数を取得して、配列に格納しました。
`いいね` は `likes_count` なんですねー。
ちょっとほっこりしました(*‘∀‘)

さてさて、中身を確認すると・・・

```
[{likes_count=0, page_views_count=null, title=初めて JIRA RestAPI を使ったよ},
 {likes_count=1, page_views_count=null, title=LINEWORKS のリッチメニューを使う},
 {likes_count=1, page_views_count=null, title=request をループ処理する},
 {likes_count=0, page_views_count=null, title=node.js で定時に処理を実行する},
 {likes_count=0, page_views_count=null, title=トーク bot に送信した画像をダウンロードする},
 {likes_count=1, page_views_count=null, title=LINEWORKS のコンテンツアップロード API を使う},
 {likes_count=1, page_views_count=null, title=Callback で受け取ったトーク情報から botNo を取得する},
 {likes_count=0, page_views_count=null, title=Callback 使いから Promise マスターにクラスチェンジするぞ！},
 {likes_count=2, page_views_count=null, title=API を使って LINEWORKS BOT を登録する},
 {likes_count=3, page_views_count=null, title=ケルベロス認証について勉強してみた},
 {likes_count=6, page_views_count=null, title=LINEWORKS BOT とのやり取りを Google スプレッドシートに残す},
 {likes_count=57, page_views_count=null, title=GoogleAppsScript で LINEWORKS のチャット BOT を作る}]
```

・・・あっるぇぇぇ？？( ﾟДﾟ)
`page_views_count=null` ってどゆこと？？
誰も私の記事を見ていないことに・・・orz

### 記事一覧の取得では view 数は取得できない！

どうしてなのかはサッパリわからないのですが、一覧では view 数は取得できない様子。
【参考記事】[【Qiita API】いいね！閲覧数の自動集計](https://qiita.com/Naoto9282/items/252c4b386aeafc0052ba)

なんというトラップ。
しかし、記事をひとつひとつ取得していけば閲覧数も取得できるらしい。
面倒ですが、やるしかない！
むしろ、先輩たちの知見があって助かりましたわー。
たぶん、一人だったら「なんで！？(´；ω；`)」って泣いてました。感謝。

気を取り直してコードを書き替えます。

```js:getMyQiita.gs
function getMyQiita() {
  const token = "発行したアクセストークン";
  const uri = "http://qiita.com/api/v2/authenticated_user/items/";
  const options = {
    headers : {
      'Authorization' : 'Bearer ' + Token
    },
    method : 'get'
  }
  const res = JSON.parse(UrlFetchApp.fetch(uri, options));
  const id = res.map( function(report) {
    return report.id
  });
  const reports = id.map( function(id) {
    const uri = "http://qiita.com/api/v2/items/";
    return JSON.parse(UrlFetchApp.fetch(uri + id, options));
  });
  return reports.map( function(report) {
    return { "title" : report.title, "likes_count" : report.likes_count, "page_views_count" : report.page_views_count };
  });
}
```

一度、記事一覧から `id` だけ取得します。
それから、`id` の数だけ [記事取得 API](https://qiita.com/api/v2/docs#get-apiv2itemsitem_id) を使用して、記事一覧の配列 `reports` を作成します。
`reports` の中から、タイトル、いいね数、閲覧数を抜き出します。

取得したデータを表示してみると・・・

```
[{likes_count=0, page_views_count=123, title=初めて JIRA RestAPI を使ったよ},
 {likes_count=1, page_views_count=103, title=LINEWORKS のリッチメニューを使う},
 {likes_count=1, page_views_count=206, title=request をループ処理する},
 {likes_count=0, page_views_count=268, title=node.js で定時に処理を実行する},
 {likes_count=0, page_views_count=160, title=トーク bot に送信した画像をダウンロードする},
 {likes_count=1, page_views_count=234, title=LINEWORKS のコンテンツアップロード API を使う},
 {likes_count=1, page_views_count=107, title=Callback で受け取ったトーク情報から botNo を取得する},
 {likes_count=0, page_views_count=186, title=Callback 使いから Promise マスターにクラスチェンジするぞ！},
 {likes_count=2, page_views_count=261, title=API を使って LINEWORKS BOT を登録する},
 {likes_count=3, page_views_count=541, title=ケルベロス認証について勉強してみた},
 {likes_count=6, page_views_count=458, title=LINEWORKS BOT とのやり取りを Google スプレッドシートに残す},
 {likes_count=57, page_views_count=2870, title=GoogleAppsScript で LINEWORKS のチャット BOT を作る}]

```

ちゃんと view 数が表示されました！良かったー。

## 5. BOT にレポートを送信させる

最後に、BOT で送信するために配列から見やすいテキストに成形します。

```js:getMyQiita.gs
function getMyQiita() {
  const token = "発行したアクセストークン";
  const uri = "http://qiita.com/api/v2/authenticated_user/items/";
  const options = {
    headers : {
      'Authorization' : 'Bearer ' + Token
    },
    method : 'get'
  }
  const res = JSON.parse(UrlFetchApp.fetch(uri, options));
  const id = res.map( function(report) {
    return report.id
  });
  const reports = id.map( function(id) {
    const uri = "http://qiita.com/api/v2/items/";
    return JSON.parse(UrlFetchApp.fetch(uri + id, options));
  });
  const report_array = reports.map( function(report) {
    return { "title" : report.title, "likes_count" : report.likes_count, "page_views_count" : report.page_views_count };
  });
  var msg = "";
  report_array.map( function(array) {
    msg += array.title.slice(0,30) + "\n / いいね : " + array.likes_count + " / view : " + array.page_views_count + "\n";
  });
  return msg;
}
```

こんな感じに成形してみました。

```実行結果
初めて JIRA RestAPI を使ったよ
 / いいね : 0 / view : 133
LINEWORKS のリッチメニューを使う
 / いいね : 1 / view : 112
request をループ処理する
 / いいね : 1 / view : 211
node.js で定時に処理を実行する
 / いいね : 0 / view : 278
トーク bot に送信した画像をダウンロードする
 / いいね : 0 / view : 162
LINEWORKS のコンテンツアップロード API を使う
 / いいね : 2 / view : 241
Callback で受け取ったトーク情報から botNo を
 / いいね : 1 / view : 108
Callback 使いから Promise マスターにクラス
 / いいね : 0 / view : 187
API を使って LINEWORKS BOT を登録する
 / いいね : 2 / view : 271
ケルベロス認証について勉強してみた
 / いいね : 3 / view : 560
LINEWORKS BOT とのやり取りを Google ス
 / いいね : 6 / view : 464
GoogleAppsScript で LINEWORKS の
 / いいね : 57 / view : 2899
```

記事を書いている間も View 数が増えています！ヾ(*´∀｀*)ﾉ
ありがたやたや（＾ω＾）

それでは、メインプログラムを書き変えてレポートを送信できるようにしちゃいましょう！(*'▽')

```js:app.gs
function doPost(e) {
  if (e == null || e.postData == null || e.postData.contents == null) return;
  const requestJSON = e.postData.contents;
  const requestObj = JSON.parse(requestJSON);
  var sendMsg = "";
  const accountId = requestObj.source.accountId;
  const options {
    "apiId" : "",
    "consumerKey" : "",
    "serverId" : "",
    "privateKey" : "",
    "botNo" : ""
  };  
  // postback 対応
  const postback = requestObj.content.postback;
  if(postback) {
    switch(postback){
      case "qiita" :
        sendMsg = getMyQiita();
        break;
      default :
        sendMsg = "何か変だ";
        break;
    }
  }
  // LINEWORKS にメッセージを送信
  LINEWORKS.sendMsg(options, accountId, sendMsg);
}
```

これで、ボタンを押したら閲覧数といいね数のレポートを返してくれるようになりました！
さっそくやってみましょう！

![1566795215.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363367/3849e7e9-2ed9-727c-588b-cf7c36273fec.png)


無事にレポートが送られてきましたねー。
完成です！(*‘∀‘)

#おわりに
ここまでお付き合いいただきありがとうございました。
いや、ほんと、予想よりだいーぶ長々とした記事になってしまいました。
読むの疲れましたよね？読みやすい構成になるよう、精進します。

いやー、でも、閲覧数が増えていくのを見ると、頑張ろうって気になります。
見てくださる人がいるから頑張れる。
モチベーションあげて、頑張っていきたいと思います。

ではまた！(^^)/

#参考にさせていただきましたm(_ _)m
[LINEWORKS Developers](https://developers.worksmobile.com/jp/document?lang=ja)
[Qiita API v2 ドキュメント](https://qiita.com/api/v2/docs)
[【Qiita API】いいね！閲覧数の自動集計](https://qiita.com/Naoto9282/items/252c4b386aeafc0052ba)