チラシ裏日記上等!!新館

Webアプリケーションエンジニアの雑記帳。映画とかアニメとかの記事も書きます。

golangでesaのクライアントを作っています。

これは Go Advent Calendar 2018の11日目の記事です。

去年はgolangTwitterクライアント「tt」を作りました。その tt は今でも気軽にツイートするときに使用しています。最近あまりメンテをしていないので近いうちに機能を追加していきたいところです。

www.chirashiura.com

今回もコマンドラインツールを作りました。esaコマンドラインツール myesa です。

myesa

esaコマンドラインツール myesaesaのドキュメントの検索と作成、更新が出来るコマンドラインツールです。

github.com

tt と同様 go getgo install でインストールできます。インストール後は myesarc.json$HOME 直下に作ります。次のようなjsonファイルを作成します。

{
    "ACCESS_TOKEN" : "access token",
    "TEAM" : "team name"
}

検索

myesa でドキュメントを検索してみます。 myesa search test と打ち込みます。

$ myesa search test
https://example.esa.io/posts/1021        2018-12-10T18:37:20+09:00       Others/nasumノート/testtest
https://example.esa.io/posts/1004        2018-12-06T13:14:06+09:00       Others/nasumノート/test (1)
https://example.esa.io/posts/1003        2018-12-06T13:13:03+09:00       Others/nasumノート/test

記事のタイトルに test がついている記事が検索されます。今は記事のタイトルを検索対象にしていますがこれだけだとちょっと検索の機能としては微妙なのでもう少し修正したいところです。

表示

記事を表示してみます。 myesa show /カテゴリ/記事名 と打ち込みます。

$ myesa show Others/nasumノート/testtest
## hogehoge

fugafuga

記事のテキストがマークダウンで表示されます。

記事の作成・更新

記事を作成してみます。 myesa edit /カテゴリ名/記事名 と打ち込みます。実行するとデフォルトのエディタが起動しテキストを編集できます。マークダウンでテキストを作成したあとエディタを終了すると記事が作成されます。

$ myesa edit Others/nasumノート/testtest 
https://scouty.esa.io/posts/1021

終了した後は記事のURLが出力されます。

編集に関しても同様に myesa edit /カテゴリ名/記事名 と打ち込むことで記事をesaから取得し編集できます。

使用したライブラリ等

使用したライブラリは以下です。

golang製のAPIライブラリは go-esa が使いやすいです。あまりメンテはされていないのですがesaAPI自体それほど変わっていないため問題なく使用することが出来ます。

ほかの cobra color viper コマンドラインツールを作る際の鉄板ライブラリです。この3つと他のAPIライブラリを使えばコマンドラインでクライアントが簡単に作れます。

工夫したところ

記事の編集

esaから記事を取得し編集する時、一時ファイルを作成しそこに一度テキストを流し込んでから編集するようにしています。

func execEditor(editor string, body string) string {
    file, err := os.OpenFile("__tmp__", os.O_WRONLY|os.O_CREATE, 0666)

    if err != nil {
        log.Fatal(err)
        return ""
    }

    if body != "" {
        fmt.Fprintln(file, body)
    }

    defer os.Remove(file.Name())

    cmdstr := fmt.Sprintf("%s __tmp__", editor)
    cmd := exec.Command("/bin/bash", "-c", cmdstr)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    err = cmd.Run()

    if err != nil {
        log.Fatal(err)
        return ""
    }

    data, err := ioutil.ReadFile("./__tmp__")

    if err != nil {
        log.Fatal(err)
        return ""
    }

    return string(data)
}

一時ファイルは記事編集後に削除しています。

ここのあたり工夫したと書きましたが正直いけていない気がしていて、一時ファイルなど作らずにうまいことやる方法があるんじゃないかと思ったりしています。力及ばずごり押しで作っています。git commit --amend のような動作イメージだったのですが動きだけ見ればうまくいった感じです。

esaの記事を名前で取得

esaAPIで、記事はidを指定すれば特定の記事を取得できるのですが、カテゴリとタイトル指定では取れません。今回のコマンドラインツールでは記事を検索した結果を使って記事の編集を行いたかったので、カテゴリとタイトルで記事を取得できる必要がありました。

なので記事の検索機能をうまく使って特定します。esaの検索クエリには inname でカテゴリとタイトルを指定することが出来ます。

次のコマンドで記事を取得し編集することが出来ます。

$ myesa edit Others/nasumノート/testtest 

Others/nasumノート/testtestOthers/nasumノート/ testtest にパースされ、in:Others/nasumノート/ name:testtestで検索されます。これでも前方一致の検索なので特定の1記事にはならないのですが、必要には足りると判断していったんこのままにしています。

まとめ

まだ実装や挙動がこなれていないのですが、必要最低限の動作はするように出来ました。

まだやりたいことはいっぱいあります。さしあたって検索から記事の編集までインタラクティブに出来るようにしたり、dockerのコマンドのように出力のフォーマットをオプションで指定できるようにしたいですね。

何かまずそうなことがあればプルリクなどしてもらえるとありがたいです。