(Qiita API v2 活用) 記事を「効率的」に Qiita に投稿する方法

# 背景

コーディング時に調査を行うと、Qiita から良質な情報を取得することが多くなっていると感じていた。

自身のノウハウを整理するために Qiita に投稿してみようとしたが、早速ウェブベースのエディタで記事を編集することに挫折してしまった。

(そもそも、Markdown 記法を覚える気もない。。)

そんな私でも、楽しく Qiita を活用する方法を模索した過程を記録として残す。

まずは、「やりたいこと」を考えた。

# やりたいこと

テキストファイルで編集した記事を「効率的」に Qiita に投稿したい。

この「やりたいこと」が実現できれば、記事の中身を充実することに注力できると考えた。

効率を高めるためには、どうすればよいか？

  - 「効率」を高めるポイント
      - Emacs で記事を編集
          - Org-mode の記法を最大限活用
      - make コマンドでアップロード
          - 記事作成もコーディングも同じ

Sphinx のプロジェクトをベースに楽に投稿できる仕組みを考案した。

# 実現する方法の概要

  - 複数の記事はドキュメントとして Sphinx でビルド
      - 記事は Emacs の Org-mode で編集
      - Makefile で更新した記事を選別
  - Qiita API v2 を使って Qiita へ投稿を自動化
      - Pandoc を用いてテキストファイルを markdown に変換
      - タイトルや本文の情報を取得してリクエスト用 JSON の生成
      - CURL コマンドを利用し Qiita API v2 経由で投稿を実行

# 課題とその対応方針

前述のやりたいことを実現する際に以下の三点が課題となった。

1.  新規投稿と更新投稿をどうやって見分けるのか？
      - 投稿された記事の中に同じタイトルの記事が存在すれば更新記事とみなす
2.  記事の本文の Markdown 内の改行は JSON でどう表現すればよいか？
      - 改行コードを「エスケープ+n」に置換する
      - curl の data オプションを利用したら、改行が消えることが問題かと思って混乱した
3.  ソースコード内のバックスラッシュとダブルクオーテーションは JSON でどう表現すればよいか？
      - バックスラッシュとダブルクオーテーションの前にエスケープを追加する

この記事では課題 1 の対応方針を実現したサンプルコードを紹介する。

# (事前準備) Qiita のトークンを取得

  - 取得ページ
      - <https://qiita.com/settings/applications>

取得できたトークンは、「QIITA_TOKEN」という環境変数に設定すること。

# Qiita 投稿するためのサンプルコード

  - トークンが取得できた前提で、記事を投稿するサンプルコードを示す。
      - 複数の記事を投稿するために、事前に 3s のスリープを追加

<!-- end list -->

``` bash
# すでに登録されている記事の一覧取得
POSTED_TITLES=$(curl --silent \
  --header "Authorization: Bearer ${QIITA_TOKEN}" \
  "https://qiita.com/api/v2/authenticated_user/items?page=1&per_page=20" \
  | jq -c '.[] | [.id, .title]')
if echo "${POSTED_TITLES}" | grep "${QIITA_TITLE}" > /dev/null ; then
    echo "## 更新投稿 ##"
    QIITA_ITEMID=$(echo "${POSTED_TITLES}" | grep "${QIITA_TITLE}" | jq -r .[] | head -n 1)
    curl "https://qiita.com/api/v2/items/${QIITA_ITEMID}" \
         --request PATCH \
         --header 'Content-Type: application/json' \
         --header "Authorization: Bearer ${QIITA_TOKEN}" \
         --data-binary @post/post.json
else
    echo "## 新規投稿 ##"
    curl "https://qiita.com/api/v2/items" \
         --request POST \
         --header 'Content-Type: application/json' \
         --header "Authorization: Bearer ${QIITA_TOKEN}" \
         --data-binary @post/post.json
fi
```

## 理解のためのポイント

``` bash
curl --silent \
  --header "Authorization: Bearer ${QIITA_TOKEN}" \
  "https://qiita.com/api/v2/authenticated_user/items?page=1&per_page=20" \
  | jq -c '.[] | [.id, .title]'
```

上記のコードを実行すると、自分の投稿した記事の ID とタイトルの配列が以下のように列挙される。

``` example
["0237be30dc6537677b30","(Qiita API v2 活用) 記事を「効率的」に Qiita に投稿する方法"]
```

  - grep を実行して一致する行が存在するかを確認
      - 存在しない場合は、初投稿の記事なので記事作成 API を投げる
      - 存在する場合は、投稿済の記事なので、 記事更新 API を投げる
          - URL に記事の ID を含める

# Sphinx のスクリーンキャプチャ

できあがったのが、こんな感じのウェブサイトである。

![](https://qiita-image-store.s3.amazonaws.com/0/84349/3333e473-2667-ddb3-9523-fa5a52f7ff0c.png)

(画像は、ウェブ画面から投稿したら S3 にアップロードされることが分かった)

# 今後に向けて

投稿用の JSON ファイルを用意して Makefile をいい感じに調整する。これで簡易自動投稿システムの完成する。

  - 投稿コマンド
      - make qiita

make clean しても中間生成物の markdown と json ファイルを削除しないように注意する。

このシステムの大事なところは、タイトルが変わると新しい記事とみなすので、タイトルだけはよく考えてからつけるところである。

気になるのは、記事件数が増えてきたときに、すでに投稿した記事の一覧をページングで取得できるようにしないといけない点である(100 件までは、考えないようにする)。

現在は、記事の ID をファイル内で埋め込んでおき、存在する場合は記事の一覧を取得しないで更新できるように対応。こうすることで、タイトルの変更も気にしないで投稿できるようになるので。

次は、記事の文字数をカウントできるようにしようと検討中。

# 参考情報

  - <https://qiita.com/api/v2/docs#認証許可>