qiisync

package module
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2020 License: MIT Imports: 18 Imported by: 0

README

Qiisync

GitHub release Go Report Card Actions Status Coverage Status

Qiisync は Qiita(https://qiita.com/) への記事の投稿や更新に便利な CLI クライアントです。

何ができるか

Qiisync では以下の 3 つの操作をサポートしています。

  • Qiita から記事のダウンロード
  • Qiita へ記事を投稿
  • Qiita へ記事を更新
記事のダウンロード (qiisync pull)
$ qiisync pull

下記の TOML ファイルの設定後、上記のコマンドで Qiita の記事を base_dir で指定したディレクトリ配下にダウンロードできます。

base_dir"./testdata/output/pull" に設定して qiisync pull を実行したときは以下のようにダウンロードされます。 base_dir 配下に記事を作成した日付ごとにディレクトリが作成されて、その中に記事が保存されます。なお、同じ日付に同一記事のタイトルが複数存在する場合、2番目以降のファイルのタイトルには連番が自動的に付与されます。

$ ./qiisync pull
     fresh remote=2020-04-14 11:26:38 +0900 JST > local=0001-01-01 00:00:00 +0000 UTC
     store /mnt/c/Users/dramt/go/src/github.com/d-tsuji/qiisync/testdata/output/pull/20200413/改行コードって難しいっ.md
     ...
     fresh remote=2019-12-05 07:01:29 +0900 JST > local=0001-01-01 00:00:00 +0000 UTC
     store /mnt/c/Users/dramt/go/src/github.com/d-tsuji/qiisync/testdata/output/pull/20191124/GoでシンプルなHTTPサーバを自作する.md
     fresh remote=2019-12-10 07:00:25 +0900 JST > local=0001-01-01 00:00:00 +0000 UTC
     store /mnt/c/Users/dramt/go/src/github.com/d-tsuji/qiisync/testdata/output/pull/20191118/GoのFormatterの書式における'+'フラグと独自実装.md
     fresh remote=2019-11-20 10:33:03 +0900 JST > local=0001-01-01 00:00:00 +0000 UTC
     ...

filename_mode"id" を指定しているとダウンロードしたときのファイル名は以下のようになります。

$ ./qiisync pull
     fresh remote=2020-04-14 11:26:38 +0900 JST > local=0001-01-01 00:00:00 +0000 UTC
     store /mnt/c/Users/dramt/go/src/github.com/d-tsuji/qiisync/testdata/output/pull/20200413/1234567890abcdefghij.md
記事の投稿 (qiisync post)
$ qiisync post <filepath>

まだ Qiita に存在しない記事を投稿する場合は qiisync post で記事を投稿します。引数に任意のファイルパスを指定します。 投稿に成功するとメタデータが付与されたファイルが base_dir で指定したディレクトリ配下にダウンロードされます。以降はダウンロードされたファイルを更新し、qiisync update を実行することで Qiita に変更内容を反映することができます。

qiisync post を実行したときの実行例を記載します。投稿時に、タイトル、タグ、限定公開にするかどうかを確認します。これらは標準入力から受け取ります。

$ ./qiisync post ./testdata/qiita/post/test_article.md

Please enter the "title" of the article you want to post.
はじめてのGo

Please enter the "tag" of the article you want to post.
Tag is like "React,redux,TypeScript" or "Go" or "Python:3.7". To specify more than one, separate them with ",".
Go:1.14

Do you make the article you post private? "true" is private, "false" is public.
true
      post article ---> https://qiita.com/tutuz/items/private/1234567890abcdefghij
     store /mnt/c/Users/dramt/go/src/github.com/d-tsuji/qiisync/testdata/output/pull/20200423/はじめてのGo.md
記事の更新 (qiisync update)
$ qiisync update <filepath>

qiisync update を実行したときの実行例を記載します。qiisync pull でローカルにダウンロードしたメタデータが付与されているファイルを指定します。

$ qiisync update ./testdata/output/pull/20200423/はじめてのGo.md
      post fresh article ---> https://qiita.com/tutuz/private/1234567890abcdefghij

ファイルがリモートの記事よりも新しくない場合は、更新は行われません。ローカルファイルの更新日時と Qiita 上の記事の更新日時を比較して判定します。

$ qiisync update ./testdata/output/pull/20200423/はじめてのGo.md
           article is not updated. remote=2020-04-23 13:34:50 +0900 JST > local=2020-04-23 13:33:10.8990083 +0900 JST
ファイルのフォーマット

ローカルにダウンロードした記事のフォーマットは以下の YAML 形式のメタデータを含んでいます。記事を更新する際に、このメタデータを修正して記事を更新すると、更新した内容が反映されます。なお IDAuthor は更新できません。

---
ID: 1234567890abcdefghij
Title: はじめてのGo
Tags: Go,はじめて
Author: Tsuji Daishiro
Private: false
---

## はじめに

...

各メタデータの説明です。

# 項目 説明
1 ID Qiita 上の記事を一意に特定する ID
2 Title Qiita の記事のタイトル
3 Tags Qiita 上の記事に付与するタグ
4 Author 記事を投稿したユーザ名
5 Private 記事が限定公開かどうか。true の場合は限定公開、false の場合は一般公開

使い方

設定

Qiisync を使うためには Qiita の API トークンが必要です。こちらから取得できます。

次に設定ファイルを書きます。ホームディレクトリ配下の ~/.config/qiisync/config に、以下のような TOML ファイルを置いてください。

[qiita]
api_token = "1234567890abcdefghijklmnopqrstuvwxyz1234"

[local]
base_dir = "./testdata/output"
filename_mode = "title"

設定ファイルのおける各項目の説明です。

[qiita]
# 項目 説明 デフォルト値
1 api_token Qiita の API トークンを設定します。 <必須>
[local]
# 項目 説明 デフォルト値
1 base_dir 記事を格納するパスのルートです。 <必須>
2 filename_mode 記事をローカルに取得する際のファイル名です。"title""id" を指定できます。
"title" はファイル名に、Qiita の記事のファイル名を、"id" の場合は記事のファイル名に Qiita の記事の ID を用います。
"title"

インストール

Binary

Binary が必要な場合は Releases ページから欲しいバージョンの zip ファイルをダウンロードしてください。 zip ファイルを解凍し、パスが通る場所に Binary を配置します。

macOS
$ brew tap d-tsuji/qiisync
$ brew install qiisync
CentOS
$ sudo rpm -ivh https://github.com/d-tsuji/qiisync/releases/download/v0.0.5/qiisync_0.0.5_Tux-64-bit.rpm
Debian, Ubuntu
$ wget https://github.com/d-tsuji/qiisync/releases/download/v0.0.5/qiisync_0.0.5_Tux-64-bit.deb
$ sudo dpkg -i qiisync_0.0.5_Tux-64-bit.deb
go get
$ go get -u github.com/d-tsuji/qiisync/cmd/qiisync
制限事項
Winodws
  • Windows 環境でも動作しますが、今のところ Qiisync が Windows の改行コード CRLF(\r\n) をサポートしていないため、qiisync post でファイルを投稿する際のファイルの改行コードは LF(\r) である必要があります。
  • また、~/.config/qiisync/config に記述する base_dir"testdata\\output\\pull\\" といったように \ をエスケープする必要があります。

ライセンス

このソフトウェアは MIT ライセンスの下でライセンスされています。

Documentation

Index

Constants

View Source
const Version = "0.0.5"

Version is the version to be displayed in the command line help message.

Variables

This section is empty.

Functions

func Logf added in v0.0.2

func Logf(prefix, pattern string, args ...interface{})

Logf is a logger that displays logs colorfully.

Types

type Article added in v0.0.2

type Article struct {
	*ArticleHeader
	Item     *Item
	FilePath string
}

Article is a structure that holds the metadata of a file and the contents of an article.

func ArticleFromFile added in v0.0.2

func ArticleFromFile(filepath string) (*Article, error)

ArticleFromFile extracts an article from local filesysytem.

type ArticleHeader

type ArticleHeader struct {
	ID      string `yaml:"ID"`
	Title   string `yaml:"Title"`
	Tags    string `yaml:"Tags"`
	Author  string `yaml:"Author"`
	Private bool   `yaml:"Private"`
}

ArticleHeader is a structure that represents the metadata of a Article.

type Broker

type Broker struct {
	*Config
	BaseURL *url.URL
}

Broker is the core structure of qiisync that handles Qiita and the local filesystem with each other.

func NewBroker

func NewBroker(c *Config) *Broker

NewBroker create a Broker.

func (*Broker) FetchLocalArticles added in v0.0.2

func (b *Broker) FetchLocalArticles() (articles map[string]*Article, err error)

FetchLocalArticles searches base_dir of local filesystem and extracts articles.

func (*Broker) FetchRemoteArticles added in v0.0.2

func (b *Broker) FetchRemoteArticles() ([]*Article, error)

FetchRemoteArticles extracts articles from Qiita.

func (*Broker) NewRequest

func (b *Broker) NewRequest(method, urlStr string, body interface{}) (*http.Request, error)

NewRequest is a testable NewRequest that wraps http.NewRequest.

func (*Broker) PostArticle

func (b *Broker) PostArticle(body *PostItem) error

PostArticle post the article on Qiita.

func (*Broker) StoreFresh

func (b *Broker) StoreFresh(localArticles map[string]*Article, remoteArticle *Article) (bool, error)

StoreFresh compares the files in the local filesystem with the articles retrieved from Qiita and updates the files in the local filesystem.

func (*Broker) UploadFresh

func (b *Broker) UploadFresh(a *Article) (bool, error)

UploadFresh posts articles to Qiita. If an article on Qiita is newer than the one you have locally, we will not update it.

type Config added in v0.0.2

type Config struct {
	Qiita qiitaConfig `toml:"qiita"`
	Local localConfig `toml:"local"`
}

Config stores Qiita's configuration and local environment settings.

func LoadConfiguration added in v0.0.2

func LoadConfiguration() (*Config, error)

LoadConfiguration gets its configuration from "~/.config/qiisync/config".

type Item

type Item struct {
	ID           string    `json:"id"`
	URL          string    `json:"url"`
	User         User      `json:"user"`
	Title        string    `json:"title"`
	Body         string    `json:"body"`
	RenderedBody string    `json:"rendered_body"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
	Tags         []*Tag    `json:"tags"`
	Private      bool      `json:"private"`
}

Item is a structure that represents the QiitaAPI.

See also https://qiita.com/api/v2/docs#%E6%8A%95%E7%A8%BF.

type PostItem

type PostItem struct {
	Body     string `json:"body"`
	Private  bool   `json:"private"`
	Tags     []*Tag `json:"tags"`
	Title    string `json:"title"`
	ID       string
	URL      string
	FilePath string
}

PostItem is a structure that represents the Qiita API required to post an Article to Qiita.

See also https://qiita.com/api/v2/docs#post-apiv2items.

type PostItemResult

type PostItemResult struct {
	Body      string    `json:"body"`
	CreatedAt time.Time `json:"created_at"`
	ID        string    `json:"id"`
	Private   bool      `json:"private"`
	Tags      []*Tag    `json:"tags"`
	Title     string    `json:"title"`
	UpdatedAt time.Time `json:"updated_at"`
	URL       string    `json:"url"`
	User      User      `json:"user"`
}

PostItemResult is a structure that represents the response body when an Article is posted to Qiita.

See also https://qiita.com/api/v2/docs#post-apiv2items.

type Tag

type Tag struct {
	Name     string   `json:"name"`
	Versions []string `json:"versions"`
}

Tag is a structure that represents the QiitaAPI.

See also https://qiita.com/api/v2/docs#%E6%8A%95%E7%A8%BF.

func MarshalTag

func MarshalTag(tagString string) []*Tag

MarshalTag converts a string to a Tag.

type User

type User struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

User is a structure that represents the QiitaAPI.

See also https://qiita.com/api/v2/docs#%E6%8A%95%E7%A8%BF.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL