Qiita/Zennの投稿をGitHubプロフィールに自動反映するためのツールを作った
概要
こんなツイートを見ました。
天才か! かっこいい!こういうことをシュッと出来るの尊敬しかない。自分でもまねっこしてみたかったので Go でツール化してみました ╭( ・ㅂ・)و ̑̑。
インストール
go install github.com/ikawaha/feedsnippet@latest
コマンド
$ feedsnippet --help
Usage of feedsnippet:
-config string
config file
-debug
print raw fees for debug (optional)
-diff
replace snippets only when there is a difference (optional)
-file string
target file (optional)
-verbose
print snippets to stdout (optional)
使い方
config にフィードの取得設定を書いていきます。config は yaml ファイルになってます。
項目 | 内容 |
---|---|
urls | フィードのURL。複数指定可能 |
template | フィードを表示するためのテンプレート。省略可能。省略時はデフォルトのテンプレートが利用されます |
sort_by_published |
true のとき、フィードを作成日時でソートします。省略可能 |
reverse |
true のとき、フィードを逆順に並べ直します。省略可能 |
limit | 上位何件を表示対象にするかを指定できます。0の場合は全てを対象とします。省略可能 |
template
は Go のテンプレートの記法を利用します。
最小構成
Zenn と Qiita のフィードをそれぞれ5件ずつ取得して並べる最小構成の設定は次のように書けます。
- urls:
- https://zenn.dev/ikawaha/feed
limit: 5
- urls:
- https://qiita.com/ikawaha/feed
limit: 5
この設定での出力はこんな感じです。
テンプレートを利用してフィードの表示をカスタマイズする
テンプレートを使えば出力する項目を整形できます。テンプレートは Go のテンプレート記法です。テンプレートでは、対象レポジトリにアイコン用の画像ファイルを用意しておいてフィード元ごとにアイコンを指定しています。アイコンはレポジトリの適当なところに先に置いておきました(画像は @mikkame san のレポジトリからいただきました。)
- urls:
- https://zenn.dev/ikawaha/feed
template: |-
**Zenn**
{{range . -}}
* ![](./icon/zenn.png) [{{ .Title }}]({{ .Link }})
{{ end }}
limit: 5
- urls:
- https://qiita.com/ikawaha/feed
template: |-
**Qiita**
{{range . -}}
* ![](./icon/qiita.png) [{{ .Title }}]({{ .Link }})
{{ end }}
limit: 5
出力例:
複数のフィードを混ぜ合わせて表示する
Zenn と Qiita のフィードを混ぜ合わせて更新日でソートして上位10件を取り出します。
- urls:
- https://zenn.dev/ikawaha/feed
- https://qiita.com/ikawaha/feed
template: |-
{{range . -}}
* {{ if eq .Header.FeedLink "https://zenn.dev/ikawaha/feed" -}}
![](./icon/zenn.png)
{{- else }}{{ if eq .Header.FeedLink "https://qiita.com/ikawaha/feed" -}}
![](./icon/qiita.png)
{{- end }}{{ end -}}
[{{ .Title }}]({{ .Link }})
{{ end }}
limit: 10
sort_by_published: true
出力例:
テンプレートの設定方法
フィードのアイテムが与えられるので、基本的にはそれらを range
で回して表示していきます。テンプレートの書き方は Go のドキュメント を参考にして下さい。ちょっと結構クセがあります。フィードのアイテムのフィールドは gofeed.Item の項目になります。Header
という項目に gofeed.Feed へのリンクがあります。
ファイル内の Feed Snippet を置き換える
コマンドの file
オプションにファイルを指定すると、ファイルの Feed の該当位置を新しいもので置き換えます。仕組みとしては
<!--[START github.com/ikawaha/feedsnippet]-->
<!--[END github.com/ikawaha/feedsnippet]-->
というタグを目印にこの範囲を置き換えます。正規表現でマッチさせて置き換えるだけなので、入れ子にしたりとか出来ません。更新すると日付を一緒に埋め込むので、フィードが更新された日時を知ることが出来ます(コミットの日時を見ればいい気もしますが)。新規に埋め込むときは埋め込む範囲に上の START
〜END
を埋め込んでおいて下さい。
GitHub Actions で README.md の更新を自動化
name: Update feed snippet
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16
- name: Install feedsnippet
run: go install github.com/ikawaha/feedsnippet@latest
- name: Update README.md
run: feedsnippet -config feedsnippet.yml -diff -file README.md
- name: git commit
run: |
git config --local user.email "ikawaha@users.noreply.github.com"
git config --local user.name "ikawaha"
git add README.md
git diff --cached --quiet || (git commit -m "Update feed snippet" && git push origin main)
こういう感じで仕掛けておくと1日に1回差分があるときだけ更新してくれます(これも mikkame san) のを参考にさせていただきました。)。差分がなくても更新してしまいますが、そこは愛嬌です。 追記(2021-02-27 18:12):修正されています -diff
オプションを追加しました
付録
feedsnippet でいうところのフィードは、gofeed でいうところの gofeed.Item に相当します。フィード全体の情報はフィードから Header
として参照できます。
type Feed struct {
Header *gofeed.Feed
*gofeed.Item
}
以下に gofeed で扱えるフィールドをツールのフィードの項目と対応させて転記しておきます。gofeed ホントにすばらしいライブラリ!
フィード情報
gofeed.Item |
RSS | Atom | JSON |
---|---|---|---|
Title | /rss/channel/item/title /rdf:RDF/item/title /rdf:RDF/item/dc:title /rss/channel/item/dc:title |
/feed/entry/title | /items/title |
Description | /rss/channel/item/description /rdf:RDF/item/description /rss/channel/item/dc:description /rdf:RDF/item/dc:description |
/feed/entry/summary | /items/summary |
Content | /rss/channel/item/content:encoded | /feed/entry/content | /items/content_html |
Link | /rss/channel/item/link /rdf:RDF/item/link |
/feed/entry/link[@rel=”alternate”]/@href /feed/entry/link[not(@rel)]/@href |
/items/url |
Updated | /rss/channel/item/dc:date /rdf:RDF/rdf:item/dc:date |
/feed/entry/modified /feed/entry/updated |
/items/date_modified |
Published | /rss/channel/item/pubDate /rss/channel/item/dc:date |
/feed/entry/published /feed/entry/issued |
/items/date_published |
Author | /rss/channel/item/author /rss/channel/item/dc:author /rdf:RDF/item/dc:author /rss/channel/item/dc:creator /rdf:RDF/item/dc:creator /rss/channel/item/itunes:author |
/feed/entry/author | /items/author/name |
GUID | /rss/channel/item/guid | /feed/entry/id | /items/id |
Image | /rss/channel/item/itunes:image /rss/channel/item/media:image |
/items/image /items/banner_image |
|
Categories | /rss/channel/item/category /rss/channel/item/dc:subject /rss/channel/item/itunes:keywords /rdf:RDF/channel/item/dc:subject |
/feed/entry/category | /items/tags |
Enclosures | /rss/channel/item/enclosure | /feed/entry/link[@rel=”enclosure”] | /items/attachments |
ヘッダ情報
gofeed.Feed |
RSS | Atom | JSON |
---|---|---|---|
Title | /rss/channel/title /rdf:RDF/channel/title /rss/channel/dc:title /rdf:RDF/channel/dc:title |
/feed/title | /title |
Description | /rss/channel/description /rdf:RDF/channel/description /rss/channel/itunes:subtitle |
/feed/subtitle /feed/tagline |
/description |
Link | /rss/channel/link /rdf:RDF/channel/link |
/feed/link[@rel=”alternate”]/@href /feed/link[not(@rel)]/@href |
/home_page_url |
FeedLink | /rss/channel/atom:link[@rel="self"]/@href /rdf:RDF/channel/atom:link[@rel="self"]/@href |
/feed/link[@rel="self"]/@href | /feed_url |
Updated | /rss/channel/lastBuildDate /rss/channel/dc:date /rdf:RDF/channel/dc:date |
/feed/updated /feed/modified |
/items[0]/date_modified |
Published | /rss/channel/pubDate | /items[0]/date_published | |
Author | /rss/channel/managingEditor /rss/channel/webMaster /rss/channel/dc:author /rdf:RDF/channel/dc:author /rss/channel/dc:creator /rdf:RDF/channel/dc:creator /rss/channel/itunes:author |
/feed/author | /author/name |
Language | /rss/channel/language /rss/channel/dc:language /rdf:RDF/channel/dc:language |
/feed/@xml:lang | |
Image | /rss/channel/image /rdf:RDF/image /rss/channel/itunes:image |
/feed/logo | /icon |
Copyright | /rss/channel/copyright /rss/channel/dc:rights /rdf:RDF/channel/dc:rights |
/feed/rights /feed/copyright |
|
Generator | /rss/channel/generator | /feed/generator | |
Categories | /rss/channel/category /rss/channel/itunes:category /rss/channel/itunes:keywords /rss/channel/dc:subject /rdf:RDF/channel/dc:subject |
/feed/category |
Happy hacking!
Discussion
差分があるときだけ更新できるようにコマンドに
-diff
オプションを追加して、GitHub Workflow の例を修正しましたGitHub Workflow の記述に間違いがあって、差分があるのに push されないというバグを修正しました。
正:
誤:
記事中の上の修正箇所を微調整して、cron の更新頻度を1日1回に修正
修正