delikaのAPIを使う方法

# delikaとは？

おそろしくシンプルなトップページ。

https://delika.io/

何か、Qiitaで記事のキャンペーンやってるらしいです（〜2022年4月30日）

https://qiita.com/official-events/30be12dd14c0aad2c1c2

> delikaはデータ版「GitHub」を目指して開発されたデータ共有プラットフォームです。

何かしら自分が調べたデータや公開データを共有するためのサービスのようです。
確かに、カレンダーとか郵便番号とか個人情報が絡まないような公開情報でも収集するのが面倒なものとかありますね。

サイトがシンプル過ぎて怖いので、運営会社のリンクも貼っておきます。

https://connecto-data.com/about-us


# APIを使うには

使い方は以下にも書いてあるのですが、ちょっとシンプルすぎるし英語なので、試した方法を続けて書きます。

https://docs.delika.io/api/v1/authentication.html


## 実行ファイルを用意する

必要になるアクセストークンの有効期間が1時間と初めてのお試しには短いので、先にNode.jsを使った実装を書いておきます。
（有効期間が過ぎたら45日間の更新トークンを使ってアクセストークンを更新するAPIを使います）

まずテストフォルダを作って`cd`したら`init`して、`node-fetch`を入れます。
`init`の返答は適当にEnter連打で良いと思います。

```shell:テストフォルダを作ってinitしてnode-fetchをインストール
mkdir delikaAPI
cd delikaAPI
npm init
npm install node-fetch
```

今回は`import`で書きますので、package.jsonの最後に`"type": "module"`を追加します。

```json:package.jsonの最後
  },
  "type": "module"
}
```

index.jsに具体的に実装を書きます。

```javascript:index.js
import fs from 'fs';
import path from 'path';
import fetch from 'node-fetch';

const delikaAPI = (() => {
  // APIのルートパスは固定
  const API_ROOT = 'https://api.delika.io/';

  // アクセストークンのJSONファイルを探すためにユーザーのホームディレクトリを調べる（後述）
  const JSON_DIR = process.platform == 'win32' ? path.resolve(process.env.APPDATA, 'delika') : path.resolve(process.env.HOME, '.delika');

  // token.jsonを読み込む
  const JSON_FILE = path.resolve(JSON_DIR, 'token.json');
  const ACCESS_DATA = JSON.parse(fs.readFileSync(JSON_FILE, { encoding: 'utf8' }));
  
  return (api_path, method, option) => {
    // headersなどの処理
    const _options = Object.assign({}, option);
    _options.method = method || 'get';
    _options.headers = _options.headers || {};
    _options.headers.Authorization = _options.headers.Authorization || `${ACCESS_DATA.TokenType.toLowerCase()} ${ACCESS_DATA.AccessToken}`;
    if (method && method.toLowerCase() === 'post' && option.body) {
      _options.headers['Content-Type'] = 'application/json';
    }

    return new Promise((resolve, reject) => {
      // fetchする
      console.error('fetch: ' + API_ROOT + api_path);
      fetch(API_ROOT + api_path, _options)
        .then((res) => { return res.json(); })
        .then((data) => {
          // 正常系
          if (data.Status.Code === 200) {
            resolve(data);
            return;
          }

          // 異常系（node-fetchの場合）
          if (data.Status.Code === 401) {
            console.log('Token expired, try refresh.');
            fetch(API_ROOT + '/v1/auth/token', {
              method: 'post',
              body: JSON.stringify({ RefreshToken: ACCESS_DATA.RefreshToken }),
              headers: { 'Content-Type': 'application/json' }
            })
            .then((res) => { return res.json(); })
            .then((data) => {
              // 正常にトークンを更新できたらリトライ
              if (data.Status.Code === 200) {
                fs.writeFileSync(JSON_FILE, JSON.stringify(data.Data), { encoding: 'utf8' });
                for (const key in data) { ACCESS_DATA[key] = data[key] };
                delikaAPI(api_path, method, option).then((data)=>{ resolve(data); });
              }
              reject(data.Status.Message);
            })
          } else {
            reject(data);
          }
        })
      ;
    });
  };
})();

// 実行して受け取りデータを表示
// ちなみにqiita_delika_article_campaignさんは投稿キャンペーン用のダミーアカウントらしいです
delikaAPI('v1/account/qiita_delika_article_campaign/datasets', 'get')
  .then((data) => {
    console.log(data);
  })
;
```

お試しの場合は上記で十分かと思います。

順番が前後しますが、次はコードの途中に出てくるトークンの取得と保存についてです。

## トークンの取得

### アカウント作成

こちらは認証APIにブラウザでアクセスしてログインする、という手順なので、まずはdelikaにユーザーアカウントを作成してください。

https://delika.io/

トップページにアクセスして右上の「Sign up」から新規登録できます。
いわゆる規約系のダイアログが出るので、読んだら「Proceed」を押してください。

アカウントはGitHub連携かメールで作成できます。
僕はGitHub連携にしましたが、途中で携帯でSMSの認証コードを受け取るアレもあります。
（ちなみに新規登録のSMSはMicrosoftから送られてきました）

登録後はプロフィールの編集画面に行けますので、ユーザー名をちゃんとつけて保存しておきましょう。


### トークンを取得しに行く

アカウントを作った人は以下にアクセスしてください。

https://api.delika.io/v1/auth

認証APIなのですが、ここでAPIサーバーへのログイン画面にリダイレクトされます。
先ほど作ったアカウントでログインすると、びっくりするほど白い画面にトークン情報が並んでいます。
下にJSONになっているものがありますので、それをコピーしておきます。

### ファイルに保存する

ここに、ファイル保存する時の推奨の場所が書かれています。

https://docs.delika.io/api/v1/authentication.html

Windowsとそれ以外で違いますので、以下のように調べて、先ほどのトークンをtoken.jsonというファイルで保存してください。
（説明ページでは`{"Default":コピーした内容}`のようにラップしているようですが、今回はそのまま書き込みます）

```sh:Windowsの場合（%APPDATA%\delika\token.jsonに保存）
echo %APPDATA%
```

```sh:その他の場合（$HOME/.delika/token.jsonに保存）
echo ${HOME}
```

保存できたら、いよいよ実行します。


## APIにアクセスする

最初に作ったNode.js用のスクリプトを以下のコマンドで実行します。

```shell:実行
node index.js

# ちょっと時間がかかって、出力される
{
  Status: { Code: 200, Message: 'Found 1 datasets.' },
  Data: { DatasetCount: 1, DatasetList: [ [Object] ] }
}
```

これでアクセス完了です。

先述のスクリプトはAPIのURLにアクセスする時に`Authorization`ヘッダを追加して、認証方式`bearer`と先ほど取得した`AccessToken`の内容を送信しています。
（`bearer`の後に半角スペースがひとつあるので忘れないでください）

```javascript:該当箇所のコード
    _options.headers.Authorization = _options.headers.Authorization || `${ACCESS_DATA.TokenType.toLowerCase()} ${ACCESS_DATA.AccessToken}`;
```

```http:ヘッダーにトークンを追加
Authorization: bearer アクセストークン
```

仕組みとしてはこれだけなので単純ではありますが、最初のアクセストークンの取得は（今のところ？）ブラウザベースでやる必要があるみたいです。
公式に用意されたPythonのライブラリを見てもリファレンスの最初は`delika.new_token(host, open_browser)`でした。

https://docs.delika.io/python/

# delika APIでできること

今はまだ「delika API version 1 (preview)」となっていて機能は少ないですが、以下の「Basics > API Response」でレスポンスデータの構造、「Endpoints」でAPIの一覧と詳細を見ることができます。

https://docs.delika.io/api/v1/

* トークンの発行（ブラウザベース）と更新
* 自分が投稿したデータセットのリスト（Githubで言えばリポジトリのリスト）
* 他のユーザーが投稿したデータセットのリストやデータに関する詳細情報の取得
* delika SQLの実行と状況確認、結果の取得

おそらく最後のdelika SQLが目玉なのだと思います。
投稿されているデータをDBのテーブルと見なしてSQLを実行できるようですが、今は意味のあるデータセットが少ないのでこれからに期待したいところです。
delika SQLの詳細は以下。

https://docs.delika.io/sql/

```sql:delika SQLの例文を抜粋
SELECT
  t1.date,
  t1.value AS new_value,
  t2.value AS old_value
FROM
  [delika-examples/weather/tokyo.csv@1] t1
INNER JOIN [delika-examples/weather/tokyo.csv@2] t2 ON
  t1.date = t2.date
  AND t1.value <> t2.value
```

# 最後に

なんだかすごくステマっぽい記事になってしまったのですが、ステマでもダイマでもなく、久しぶりにWebサービスのAPIにアクセスしたかっただけです。
本当です。
むしろ賞とかください。

ともかく、サイト内を見てもAPIを見てもこれからという感じがしますので、みんなで育てて後年「オレはあのバンドをインディーズの頃から応援してた」とか言うチャンスだと思います。

以上です。

:::note info
5月18日追記
「むしろ賞とかください。」とか書いていたら、参加賞ですが本当にいただきました。

https://zine.qiita.com/event/202204-qiitadelika/

参加賞は「ご参加いただいた方から、抽選で」ということなので純粋に運かもしれませんが、とにかく嬉しいです。
企画・選考していただいた皆様、ありがとうございます。
:::