概要
Qiita APIが便利でよく利用しているのですが、毎回curl
やスクリプトを組むのが面倒だったので、CLIツールを作ってみました。何番煎じか数えるのはやめましたw
インストール方法
さくっと作ったので、PyPiへの登録はしていません。GitHubからソースを取得してインストールします。
> git clone https://github.com/kai-kou/qiita-py-cli.git
> cd qiita-py-cli
> pip install -r requirements.txt
> python setup.py install
# ターミナルの再起動(bash)
> exec $SHELL -l
# ターミナルの再起動(fish)
> exec fish -l
アンインストールする場合は、以下のようにします。
> python setup.py install --record files.txt
> cat files.txt | xargs rm -rf
以下の記事を参考にさせてもらいました。
setup.pyを用いてインストールしたモジュールのアンインストール方法
https://qiita.com/orion46/items/dfe476067e499cca8535
使い方
Qiitaのアクセストークンが必要となります。アクセストークンはQiitaに認証していると以下のURLから取得できます。
POST系のコマンドを利用する場合にはスコープのwrite_qiita
が必要になります。情報取得だけで利用するのなら、read_qiita
があれば十分です。
取得できたらqiita init
コマンドでアクセストークンを設定します。
# アクセストークンの設定
> qiita init
Qiitaのアクセストークンを入力してください:
環境変数にアクセストークンを設定することもできます。
# bash
> export QIITA_PY_CLI_ACCESS_TOKEN=<Qiitaのアクセストークン>
# fish
> set -x QIITA_PY_CLI_ACCESS_TOKEN <Qiitaのアクセストークン>
アクセストークンが設定できたらコマンドを実行してみます。
> qiita get_user kai_kou
{"description": "2004-2011 フリーランス。2011-2018 株式会社グリーティングワークスでEC、バックヤード開発をプレイングマネージャーとしてAWSを超積極的に導入。サーバレス大好きっ子。Python、Ruby、TypeScript、C#とかが好み。2018/7からCloudpackにJoin。\r\n\r\nQiita記事は誰かひとりの琴線に触れたらそれでいい^^", "facebook_id": "kokaorz", "followees_count": 429, "followers_count": 79, "github_login_name": "kai-kou", "id": "kai_kou", "items_count": 79, "linkedin_id": "", "location": "Osaka, Japan", "name": "甲斐 甲", "organization": "アイレット株式会社", "permanent_id": 48549, "profile_image_url": "https://qiita-image-store.s3.amazonaws.com/0/48549/profile-images/1524132209", "twitter_screen_name": "k_aik_ou", "website_url": "https://twitter.com/k_aik_ou"}
取得結果はJSONとなりますので、jq
コマンドなどで整形する前提です。
> qiita get_user kai_kou | jq
{
"description": "2004-2011 フリーランス。2011-2018 株式会社グリーティングワークスでEC、バックヤード開発をプレイングマネージャーとしてAWSを超積極的に導入。サーバレス大好きっ子。Python、Ruby、TypeScript、C#とかが好み。2018/7からCloudpackにJoin。\r\n\r\nQiita記事は誰かひとりの琴線に触れたらそれでいい^^",
"facebook_id": "kokaorz",
"followees_count": 429,
"followers_count": 79,
"github_login_name": "kai-kou",
"id": "kai_kou",
"items_count": 79,
"linkedin_id": "",
"location": "Osaka, Japan",
"name": "甲斐 甲",
"organization": "アイレット株式会社",
"permanent_id": 48549,
"profile_image_url": "https://qiita-image-store.s3.amazonaws.com/0/48549/profile-images/1524132209",
"twitter_screen_name": "k_aik_ou",
"website_url": "https://twitter.com/k_aik_ou"
}
jq
コマンドについては下記が参考になります。
jq コマンドを使う日常のご紹介
https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af
実装
コマンドラインパーサー
パラメータ設定はdocoptを利用しています。パーサーを自動的に作成してくれるので、お手軽です。メソッド名をいちいち書くのが面倒だったので、下記を参考にメソッドを洗い出して、必要なものだけを記載するようにしました。パラメータは、、、自力でコツコツと。。。
Python: オブジェクトのメソッド一覧を取得する
https://qiita.com/suin/items/b15f908aaf8023a8a1fc
def main():
_USAGE = '''
Qiita API CLI
Usage:
qiita init
qiita create_access_token [--params=<kn> --headers=<kn>]
qiita create_item [--params=<kn> --headers=<kn>]
qiita create_item_comment <item_id> [--params=<kn> --headers=<kn>]
qiita delete_access_token <token> [--params=<kn> --headers=<kn>]
qiita delete_comment <id> [--params=<kn> --headers=<kn>]
qiita delete_item <id> [--params=<kn> --headers=<kn>]
qiita follow_tag <id> [--params=<kn> --headers=<kn>]
qiita follow_user <user_id> [--params=<kn> --headers=<kn>]
qiita get_authenticated_user [--params=<kn> --headers=<kn>]
qiita get_authenticated_user_items [--params=<kn> --headers=<kn>]
qiita get_comment <id> [--params=<kn> --headers=<kn>]
qiita get_item <id> [--params=<kn> --headers=<kn>]
qiita get_item_stock <item_id> [--params=<kn> --headers=<kn>]
qiita get_tag <id> [--params=<kn> --headers=<kn>]
qiita get_tag_following <id> [--params=<kn> --headers=<kn>]
qiita get_user <id> [--params=<kn> --headers=<kn>]
qiita get_user_following <user_id> [--params=<kn> --headers=<kn>]
qiita list_item_comments <item_id> [--params=<kn> --headers=<kn>]
qiita list_item_stockers <item_id> [--params=<kn> --headers=<kn>]
qiita list_items [--params=<kn> --headers=<kn>]
qiita list_tag_items <id> [--params=<kn> --headers=<kn>]
qiita list_tags [--params=<kn> --headers=<kn>]
qiita list_user_followees <user_id> [--params=<kn> --headers=<kn>]
qiita list_user_followers <user_id> [--params=<kn> --headers=<kn>]
qiita list_user_following_tags <user_id> [--params=<kn> --headers=<kn>]
qiita list_user_items <user_id> [--params=<kn> --headers=<kn>]
qiita list_user_stocks <user_id> [--params=<kn> --headers=<kn>]
qiita list_users [--params=<kn> --headers=<kn>]
qiita stock_item <item_id> [--params=<kn> --headers=<kn>]
qiita unfollow_tag <id> [--params=<kn> --headers=<kn>]
qiita unfollow_user <user_id> [--params=<kn> --headers=<kn>]
qiita unstock_item <item_id> [--params=<kn> --headers=<kn>]
qiita update_comment <id> [--params=<kn> --headers=<kn>]
qiita update_item <id> [--params=<kn> --headers=<kn>]
Options:
--help ヘルプを表示
--params=<kn> params [default: None]
--headers=<kn> headers [default: None]
'''
all_params = docopt(_USAGE)
docopt
http://docopt.org/
Pythonのdocopt使い方メモ
https://qiita.com/ymdymd/items/651245d80964393b12c5
PythonでCLIツールを作成するのにdocoptでパラメータのパーサー作成を自動化する
https://qiita.com/kai_kou/items/5ff0958264c56ecf0a17
Qiita APIへのアクセス
下記で紹介されているラッパーを利用させてもらいました。一部APIの実装が足りていなかったので、フォークしました。
Qiita API v2のPythonラッパー実装した
https://qiita.com/petitviolet/items/deda7b66852635264508
kai-kou/qiita_py: Python Wrapper for Qiita API v2
https://github.com/kai-kou/qiita_py
基本的にはラッパーで実装されているメソッドをパラメータとして引き渡し実行しているだけです。お手軽!
command = [k for k, v in all_params.items() if v == True]
params = [
v for k, v in all_params.items()
if re.match(r'\<.*\>', k) and v is not None]
options = [
json.loads(v) for k, v in all_params.items()
if re.match(r'^\-', k) and v != 'None']
params.extend(options)
(略)
client = QiitaClient(access_token=access_token)
res = getattr(client, command[0])(*params)
getattr
を利用して、メソッドを動的に呼んでいます。下記が詳しく参考になりました。
pythonで動的にクラスとメソッドをCallする
https://yuji0602.hatenablog.jp/entry/2018/03/21/225700
まとめ
CLIツールを初めて作ってみましたが、便利なライブラリが充実しているので、とても簡単に実装することができました。
さくっと実装したので、テストも書いてない状態なので、テストを書いたらPyPiに登録してみたいと思います^^
参考
docopt
http://docopt.org/
Pythonのdocopt使い方メモ
https://qiita.com/ymdymd/items/651245d80964393b12c5
Qiita API v2のPythonラッパー実装した
https://qiita.com/petitviolet/items/deda7b66852635264508
Pythonにおけるリフレクション
https://qiita.com/icoxfog417/items/bf04966d4e9706eb9e04
pythonで動的にクラスとメソッドをCallする
https://yuji0602.hatenablog.jp/entry/2018/03/21/225700
Python: オブジェクトのメソッド一覧を取得する
https://qiita.com/suin/items/b15f908aaf8023a8a1fc
Python: PyPI にないパッケージを依存パッケージにするには
https://blog.amedama.jp/entry/2016/02/18/221555
Pythonで関数の引数にリスト、タプル、辞書を展開して渡す
https://note.nkmk.me/python-argument-expand/
Pythonでリストとタプルを相互に変換するlist(), tuple()
https://note.nkmk.me/python-list-tuple-convert/
Pythonで対応する値に基づいて辞書型のキーをフィルターしたい
https://teratail.com/questions/3731
Python Prompt Toolkitで対話的な選択コマンドを作る
https://vaaaaaanquish.hatenablog.com/entry/2017/12/25/183927
Pythonでyamlファイルを設定ファイルとして使う
http://www.bokupy.com/detail/74
pythonでホームディレクトリの取得
https://qiita.com/sotetsuk/items/d7b32b12f94a341c79a5