便利ページ：トレンドキーワードを取得してみた

前回までに、なにかと便利なページを作成しました。

　[便利ページ：Javascriptでちょっとした便利な機能を作ってみた](https://qiita.com/poruruba/items/6c67c7eef34ed302feb3)
　[便利ページ：自分のQiita記事を一覧表示](https://qiita.com/poruruba/items/f68455b2d937d2f052f4)
　[便利ページ：元号を変換してみた](https://qiita.com/poruruba/items/8aea492473a029a3865a)

今回は巷で噂のトレンドキーワードを取得するするページを追加しました。
とは言っても、以下の以前の投稿内容と同じで、お便利ページに移植しただけです。
　[Dialogflowと連携してLINE Botを作る](https://qiita.com/poruruba/items/09563e251adef1e1e8af)

毎度の通り、デモページとGitHubです。

GitHub
　https://github.com/poruruba/utilities

デモページ
　https://poruruba.github.io/utilities/

# サーバ側の実装

トレンドキーワードを収集するために、「Twitter REST API」を使います。
Twitter Developerアカウントに登録されている必要があります。

```swagger.yaml
  /trendword:
    post:
      x-swagger-router-controller: routing
      operationId: trendword
      parameters:
        - in: body
          name: body
          schema:
            type: object
      responses:
        200:
          description: Success
          schema:
            type: object
```

```index.js
var fetch = require('node-fetch');
const { URLSearchParams } = require('url');

const TWITTER_API_KEY = process.env.TWITTER_API_KEY || 【TwitterアプリのAPI key】;
const TWITTER_API_SECRET_KEY = process.env.TWITTER_API_SECRET_KEY || 【TwitterアプリのAPI secret key】;
const YAHOO_WOEID = process.env.YAHOO_WOEID || 【トレンドを取得したい場所のWOEID】; 
const NUM_OF_PICKUP = 10;

exports.handler = async (event, context, callback) => {
    if( event.path == '/trendword' ){
        var body = JSON.parse(event.body);
        if( body.apikey != SERVER_APIKEY )
            throw 'apikey mismatch';
        
        var trends = await get_trendlist();
        return new Response({ result: 'OK', trends: pickup_list(array_shuffle(trends.trends)) });
    }
};

function array_shuffle(array){
    for(var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

    return array;
}

function pickup_list(list){
    var pickup = [];
    for( var i = 0 ; i < NUM_OF_PICKUP ; i++ ){
        var name = list[i].name;
        if( name.slice(0, 1) == '#' || name.slice(0, 1) == '?' )
            name = name.slice(1);
        
        pickup.push(name);
    }

    return pickup;
}

function get_trendlist(){
    var body = {
        grant_type: 'client_credentials'
    };
    return do_post_secret('https://api.twitter.com/oauth2/token', body, TWITTER_API_KEY, TWITTER_API_SECRET_KEY)
    .then(result =>{
        var body = {
            id: YAHOO_WOEID
        };
        return do_get_token_text('https://api.twitter.com/1.1/trends/place.json', body, result.access_token);
    })
    .then(result =>{
        var list = JSON.parse(result);
//        console.log(list);

        return list[0];
    });
}

function do_post_secret(url, body, client_id, client_secret){
    var data = new URLSearchParams();
    for( var name in body )
        data.append(name, body[name]);

    var basic = new Buffer(client_id + ':' + client_secret).toString('base64');
    
    return fetch(url, {
        method : 'POST',
        body : data,
        headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization' : 'Basic ' + basic }
    })
    .then((response) => {
        if( response.status != 200 )
            throw 'status is not 200';
        return response.json();
    });
}

function do_get_token_text(url, qs, token){
    var params = new URLSearchParams();
    for( var key in qs )
        params.set(key, qs[key] );

    console.log(url + '?' + params.toString());
    return fetch(url + '?' + params.toString(), {
        method : 'GET',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization' : 'Bearer ' + token }
    })
    .then((response) => {
        if( response.status != 200 )
            throw 'status is not 200';
        return response.text();
    });
}
```

以下の部分を環境に合わせて書き換えます。

【TwitterアプリのAPI key】
【TwitterアプリのAPI secret key】
【トレンドを取得したい場所のWOEID】

#動作確認

ブラウザにはこんな感じに表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/49e32e89-040a-5293-ef63-903190716342.png)

以上