BlogカードShortcodeを実装した

例えば、はてなブログだとブログカードと呼ばれるこういうの: が有ったり、wordpressだとプラグインでこういうの: が有り、リンクをなんだか良い感じに表示してくれます。このブログでつい先日まで使っていたGhostでも、こういうの: が有りました。 一方、現在使っているHugoには標準機能でこういったものを表示する機能はありません(twitterとかYoutubeはあるんですけど・・・)。しかし、無ければ作れば良いじゃない、ができるのがHugoの良いところです。 Hugoにはshortcode という機能があり、例えば標準のtwitter shortcodeだと、 {{< tweet user="nasa9084" id="1519598305554362370" >}} と書くと 牛乳はさ、牛乳-like飲物よりうまいんだよな — nasa9084@某某某某(0x1e) (@nasa9084) April 28, 2022 の様に展開されます。なので今回は {{< web-embed url="https://example.com" >}} というshortcodeを作ってみようと思います。調べてみると同様の実装をしている人もいましたので、それを参考にしつつ実装していきます。 まず、URLからデータを取得してくるにはHugoのgetJSON を使うと良さそうです。残念ながらOGP情報などを取得する方法は用意されていないようなので、指定したURLからOGP情報をとってきてJSONとして返す様なプロキシ的なサーバが必要そうです。cloud functions for firebase + javascript で実装している人もいれば、Netlify Functions + javascript でやっている人もいるという感じでしたが、やはり個人的にはGoがシュッと読み書きできて早いし、Cloud Functionsなどで常時稼働させておくには認証とかのことも考える必要がありありそう(まぁ無くてもいいっちゃいいけど、よくわからん踏み台にされても面白くない)で面倒だな、ということでちょっと困ったんですが、OGPプロキシサーバは特に状態を持っておらず、hugo buildする間だけ存在してくれればいいので、GitHub Actionsのサービスコンテナとしてプロキシを動かすことにしました。ローカルでテストビルドするときもdocker runすれば良いだけなので簡単です。 ハンドラの実装は次の通りです: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 url := r.URL.Query().Get("url") if url == "" { http.Error(w, `{"message": "url parameter is required"}`, http.StatusBadRequest) return } log.Printf("request URL: %s", url) ogp, err := opengraph.Fetch(url) if err != nil { http.Error(w, fmt.Sprintf(`{"message": "error fetching OGP", "error": "%s"}`, err.Error()), http.StatusInternalServerError) return } if err := ogp.ToAbs(); err != nil { http.Error(w, fmt.Sprintf(`{"message": "error converting relative URLs to absolute URLs", "error": "%s"}`, err.Error()), http.StatusInternalServerError) return } var body bytes.Buffer if err := json.NewEncoder(&body).Encode(ogp); err != nil { http.Error(w, fmt.Sprintf(`{"message": "error encoding OGP info to JSON", "error": "%s"}`, err.Error()), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) body.WriteTo(w) コード全体はここ にあります。リポジトリを作ったときにhugo用のディレクトリをルートディレクトリではなく一段掘ったサブディレクトリにしておいたおかげで気軽にディレクトリを追加できたので良かったですね。 ...

2022-04-29 · nasa9084

Migrate Ghost to Hugo

いつの頃からだったか、もう記憶もあやふやではあるけれど、ブログプラットフォームとしてGhost を使っていた。twitter を見る限り、2017年の11月頃には既にGhostを使っていて、確かこの時はDockerでセットアップしていた様な記憶がある。 Ghost、すごい勢いでアップデートされてってて結構アプデが手間 — nasa9084@某某某某(0x1e) (@nasa9084) November 9, 2017 Ghostは結構更新が頻繁で、特にdocker-composeとかも使わずに運用していたので(使っても良かったんだけど、当時はDBもsqliteを使っていてコンテナ一つと永続ボリューム一つ、という単純な構成だったので使わなくて良いか、と思っていた)微妙にイメージの更新が面倒で、container-up というツールを書いてみたりもした。 その後自宅にKubernetesクラスタをセットアップしてKubernetes管理になり、データベースもMySQLに切り替え、最終的にはGCPのfree tierを使ってon VMで運用していた。 Ghostを使い始めた頃はバージョンもまだ1系だったけど、今となっては4系になって、相も変わらず活発に開発され、admin UIも大分変化した。 時代の流れとしては当然といえば当然なのだけれど、Ghost 5.0ではMySQL 8が必須となるということで、最近MySQLの更新をしたところ、頻繁に外形監視がfailする様になった。どうやらリソース不足でレスポンスを返せなくなっていたようだった。free tierのVMなのでe2-microインスタンスを使っているため、さもありなんといった感じ。 もちろん多少のお金を払ってもう少し良いVMにしても良いのだけれど、それほど頻繁に書いているわけでもないブログを運用するためだけに月数千円の出費はいかがなものか、大して書いてもいないのだから静的ページ生成でも良いのではないか、静的ページ生成ならデータベースもいらないしGitHub pagesで配信できて無料ではないか、などと思い、k8s.io でも使っているHugo に乗り換えることにした。 参考にしたのはこのページ 。多少古い記事だけど多少調整すればなんとかなるだろう、と思い見切り発車した。結果なんとか移行はうまくいき、このページが表示されています。 移行手順 まず、ghostToHugo をダウンロードして、Ghostから出力したjsonファイルをHugoにインポート。(ghostToHugoはDarwin_x86_64のバイナリを使ったけど、apple siliconのmacOSでもrosettaで普通に問題無く動いた) 1 $ ./ghostToHugo -p blog.web-apps.tech something-tech.ghost.2022-04-22-02-57-56.json Google Cloud Storageにアップロードしていたバックアップから画像ファイルを取り出してimagesディレクトリに配置した。 1 $ cp ${PATH_TO_BACKUP}/content/images ./blog.web-apps.tech/images イメージのパスをちょっと調整。 1 2 $ find . -name '*.md' | xargs sed -ie 's/__GHOST_URL__//g' $ find . -name '*.md' | xargs sed -ie 's/\/content\/images\//\/images\//g' front-matterをYAMLに変更。 1 2 3 $ cd blog.web-apps.tech $ hugo convert toYAML $ cd ../ そのままではすべての記事が年のディレクトリ以下にまとまって入っていて画像管理が大変そうなので次のスクリプトで構成変更。 ...

2022-04-23 · nasa9084

GitHubがgit://を無効にした件

TL;DR GitHubからgitプロトコル(git://github.comで始まるURL)でgit cloneする設定になっている人が居たらSSHプロトコル(git@github.comで始まるURL)を使うように設定変更しましょう wez/weztermという端末エミュレータを知って、使ってみようかと思い、ドキュメントに従ってbrew tapしたときのことでした。次の様なエラーが発生して、tapできません。 $ brew tap wez/wezterm ==> Tapping wez/wezterm Cloning into '/opt/homebrew/Library/Taps/wez/homebrew-wezterm'... fatal: remote error: The unauthenticated git protocol on port 9418 is no longer supported. Please see https://github.blog/2021-09-01-improving-git-protocol-security-github/ for more information. Error: Failure while executing; `git clone https://github.com/wez/homebrew-wezterm /opt/homebrew/Library/Taps/wez/homebrew-wezterm --origin=origin --template=` exited with 128. 指定された記事 を見てみると、git://で始まるURLでのアクセス==gitプロトコルでのアクセスを無効化したようです。 自分の.gitconfigを見てみると 、確かに https://github.com の代わりに git://github.com を使うという設定がされています。 [url "git@github.com:"] pushInsteadOf = git://github.com/ pushInsteadOf = https://github.com/ [url "git://github.com/"] insteadOf = https://github.com/ GitHubによるとこれまでもgitプロトコルでのアクセスは読み取り専用だったようですが、ご丁寧にpushInsteadOfで git@github.com を使用するという設定まで書かれているので、これまで問題無く使えてしまっていたようです。自分でもなぜこういう設定にしたのか記憶にないのですが、これは単にSSHプロトコルを使用すれば良いだけ、ということのようでしたので修正しました 。 [url "git@github.com:"] insteadOf = https://github.com/ GitHubの想定としてもどうせread-onlyだから使っている人なんてほとんどいないだろう、ということで引っかかる人も居ないでしょうが、メモとして残しておきます。 ...

2022-03-20 · nasa9084

Retrospective: 2021

1月 動画編集がちょっと楽しくなってきた頃で、毎日AmongUsの動画を作って上げてた。AmongUsやるDiscord鯖を作ったのもこのあたり。DaVinci Resolveでモーショングラフィックスやり始めてみてめっちゃ楽しかった。 案外それっぽいモーショングラフィックスとか作れるもんだなーと思うなど https://t.co/mhuQFVErv4 — nasa9084@某某某某(0x1b) (@nasa9084) January 23, 2021 この時期に買ったコミックスでまどろみバーメイド が面白いです。kindle unlimited加入者は5巻まで読めるので読んでください。特にお酒が好きな人。 nasa9084/broadcast-memo リポジトリを作った。 2月 Switchbot APIを発見したのでnasa9084/go-switchbot を作った。相変わらず動画は毎日アップしてた。 それ以外はまぁ特になし 3月 オフィス移転して、新宿から四谷になった。まぁ、目下リモートワークであんまり影響はなし。 異動乃至転職をしよう、と割と真剣に考え始めた。チーム内で真面目にやろうとしてる人を見て面倒だなって感じてしまったので、チームから心が離れてるな、と強く自覚したのが理由。 ergodash2台目(bluetooth化)を作った。今も使ってます。 nasa9084/switchbot-exporter を書いたけど、あんまり見てない。 この辺で動画投稿ペースは落ちてきた。 4月 笑顔のたえない職場です というコミックスが面白いです。 スピーカーを買い、モニタを増設し、大体今のデスク環境が整ったのがこの辺。 5月 バイオリンを買った。結局練習は続いていません。Ankerの新製品であるところのwebカメラを買って、最近のwebカメラってこんなに画質いいんだ!と驚いたり。 社でやったゴールデンウィーク自由研究発表会で良かった発表ランキング1位を獲得した。なお内容は各社の牛乳でヨーグルトを作って比較してみたという内容でした。 LINE MOBILEからLINEMOに乗り換えた。メイン回線は変わらずiij mio。 6月 UNDERTALEめっちゃ面白かった。 7月 1回目の新型コロナウイルスワクチンを接種した。 8月 2回目の新型コロナウイルスワクチンを接種した。 異世界失格 が面白いです。 Huawei Band 6を買って、割と満足はしてた。が、今はapple watchに乗り換えてしまったので使ってない。南無。プール行ったときだけ使ってます。 なんだかんだ真面目に仕事をしてました。 9月 iPhone 13 miniとiPad miniを買いました。iPhoneは9年ぶりです。 10月 Engineering Infrastructure室からLINE Platform Developmentセンター1 Communication and Service Integration室のSREチームに異動しました。使ってる技術も、業務知識もガラッと変わったので何も分からなくなりました。今も何も分からん。 社内のエンジニアレベルも上がり、昇給し、異動前にやってた業務がきちんと評価してもらえた事がわかりめでたしめでたし。 あとはapple watch買いました。 11月 LINEスタンプを作り始めた。iPad Proはこのために買った(が1年放置してた)。皆さんスタンプ買って下さい。 かんたんないきもの - LINE スタンプ | LINE STORE たまに使えるかも知れない、ゆるふわかんたんな形の生き物(?)です まぁまぁ使えそう - LINE スタンプ | LINE STORE たぶん、まぁまぁ使えそうなスタンプです とにかく帰りたい - LINE スタンプ | LINE STORE とにかく帰りたい人の為のスタンプ うちでよく使いそうなスタンプ - LINE スタンプ | LINE STORE 我が家では割とよく使われそうな雰囲気のスタンプ 丸い目をした奴ら - LINE スタンプ | LINE STORE 奴らは丸い目をしている 初めてエアコンの清掃業者を頼んだりした。正直思ってたよりきれいになってかび臭さも一切なくなったので、清掃頼んだことない人はやった方が良い。 ...

2021-12-30 · nasa9084

ansible.builtin.fileのmodeパラメータは頭に0が必要

多分ほとんどのケースでは気にすることもなく0755とか0644とか書くと思うんですが、特殊な属性を付ける必要があるときに困るよ、という話。 世の中にはSUIDとかSGIDとかスティッキービットとかいう、特殊な属性がありまして、例えば基本のファイルパーミッションが0755でSUIDを指定したいという場合はchmodで言うとchmod 4755 path/to/fileといった感じになるんですけれども、ansible.builtin.fileのmodeパラメータでは以下の様に書くとパーサが10進数として解釈して訳の分からんことになってしまいます。 1 2 3 ansible.builtin.file: path: path/to/file mode: 4755 これはこう書く必要があります: 1 2 3 ansible.builtin.file: path: path/to/file mode: 04755 もしくはこう: 1 2 3 ansible.builtin.file: path: path/to/file mode: '4755' これは例えば、結構古いAnsible playbookなんかで、 1 file: path=path/to/file mode=4755 とか書いていたやつを書き直したりしたときに注意が必要です。 まぁ、公式ドキュメントに書いてある んですけど、そうは言ってもみんなそんなに細かいところまで読んでないでしょ、という。 You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like ‘644’ or ‘1777’) so Ansible receives a string and can do its own conversion from string into number. ...

2021-12-13 · nasa9084

人生初Apple Watch (series 7)

これまで私は基本的にAndroid端末を使うことが多く、初めて持ったスマートフォンであるGalaxy Sを始め、ほとんどのスマホ人生をAndroid端末とともに歩んできました。これまで最初で最後のiPhone端末はiPhone 5のみで、今回iPhone 13 miniを購入した のは8年ぶりの事です。 Androidユーザであったために買えなかったAppleデバイス、それがApple Watchです。Androidデバイスでも使えるスマートウォッチはもちろんあります。私もfitbit Versa を使っていました。しかし、Apple Watchには遠く及びません。iDでの決裁もできない(現行のfitbit Versa 3/Senseはsuicaには対応している)し、何よりソロループがありません。 一日の大半をPCに向かってキーボードをカチャカチャするという虚業に従事していますから、時計のバックルというのは結構いづい(注:大半の人に伝わらない表現なのは理解しているけど他の表現がない)のです。 そんな私もiPhoneを買ったことによりApple Watchが買える!という事でApple Watch series 7を購入しました。

2021-10-19 · nasa9084

iPad mini 6を買って1週間半経った

みんなが待ってたiPad。そうiPad miniです。私は過去に会社のお下がりでもらったiPad mini第2世代を使っていたことがありますが、その後iPad Pro 第一世代(2018)に買い換え、今に至ります。Youtubeや読書に使用するにはちょっと大きいな、と思いつつ、なんだかんだ便利に使ったり使わなかったりしていました。iPad miniは良いサイズだったな、なんて思いながら。 とはいえ、iPad Proのベゼルレスデザインを体感すると、(ちょっとダサい)従来のiPad miniに戻る気にはなれず、ベゼルレスデザインのiPad miniがでたら買おうと思っていました。 そして今年、第六世代iPad miniとしてベゼルレスデザインのモノが発売されたので購入しました。なんだかんだ安くはないので、一晩悩んだ結果発売日に入手することはできず、10月9日到着でした。 今回購入したのはスペースグレイのiPad mini 第六世代 Wi-Fi + Cellularモデル、ストレージは256GBです。iPad Proも256GBのモノを使用していて、ストレージが大きく余っているので正直256GBは多すぎると思ったのですが、64GBか256GBという二つの選択肢を考えたとき、64GBは流石に小さすぎるだろう、と考え256GBを選択しました。MacBook Proですら256でストレージが余っている(最近ゲーム実況動画編集をするようになって、動画の為に外付けSSDを買ったけど)ため、iPad miniのストレージも枯渇することはおそらく無いと思います。 ケースは安定の公式Smart Folioを購入。iPad Pro用のモノとは異なり、アップルのロゴがエンボス加工されています。これはこれで良いですね。 iPad Proとサイズを比較するとこんな感じ。ざっくり半分くらいの大きさです。身長176センチ(最近1センチほど伸びました)の私だと片手でホールドできるくらいのサイズ感です。 著作権的なアレをアレするためモザイクをかけていますが、マンガを読むのに非常にちょうど良いサイズです。おそらく小説やビジネス書など、他の書籍にも良いでしょう(技術書は大判の事も多いしiPad Proの方が読みやすいかも知れない) 本機はiPad Airと同じくtouch IDですが、個人的にはiPadはface IDの方が良いかな、という気がしました。家の中で使うことが多い端末ですから、マスクをしている事も無いため、face IDの方がボタンに指を持っていくという動作が不要なため便利です。 また、これは慣れの問題もあるとは思いますが、ボリュームボタンが画面左上部(ランドスケープでは左下)というのは少し操作しづらいように感じました。これはiPad Proとボタンの位置が違うから戸惑っているだけかも知れません。画面の向きによってボタンの方向が変わる(右側、上側が+になる)のは直感的で良いので、iPad Proにもバックポート(?)してほしいものです。

2021-10-19 · nasa9084

DroneCIでパイプライン全体をfailさせずに後続のジョブを停止する

例えばmono repoで特定のディレクトリに変更があったときにだけジョブを実行したい、という様なケース。DroneCIのconditionはディレクトリ単位での変更でステップを実行するかという分岐はできません。かといってfailさせてしまうと、対象のディレクトリに変更がない場合はいつもfailする事になり、実際に問題があってfailしているのかどうなのか分からない、という事態に陥ります。 そんなときは exit 78 すると良いようです。 exit 78 したステップはsuccess、後続のステップは実行されず、(depends_on で設定しているような)後続のパイプラインは実行されます。 Reference How to exit a Pipeline early without Failing

2021-10-18 · nasa9084

iPhone 13 miniを買った

新型コロナウイルス感染症ワクチンの副反応(ということにした)で、iPhone 13 miniを購入しました。色はミッドナイトで、128GBのモデルです。 日々のご飯の写真くらいしか写真は撮らないし、大きいスマホは好きになれないのでminiを選択しました。これまで使用していたPixel 4が64GBのモデルだったので、ストレージは倍になったことになります。AppleCare+ 盗難・紛失プラン for iPhone 13 miniもつけて、107,600円でした。 最後にiPhoneを使っていたのはiPhone 5なので、実に8年ぶりくらいのiPhoneです。 iPad miniも買いましたが、買うかどうか一晩悩んだ結果発売日に届きませんでした。 以下開封写真です:

2021-09-26 · nasa9084

bashのhere-documentは一時ファイルを作成するらしい

皆さん使ってますか、here-document。bashでいうとこういう奴: 1 2 3 4 5 6 cat <<EOF this is here document EOF 出力はこう: this is here document 複数行に渡るテキストをリテラルとして表現したい場合に便利ですね。で、shellscriptからREST APIにリクエストを投げたくて、here-documentを使ってJSONをべたっとスクリプト内で書いてたんですけど、こんなエラーが出てました(パスはもちろん違いますよ。念のため。): /path/to/shellscript/using/here-document.sh: line 179: cannot create temp file for here-document: No space left on device 全然知らなかったけど、here-documentって一時ファイルを作成するんですね。確かめてみます。 $ docker run -it --rm centos:7 bash [root@8017e5e28d6e /]# yum install -y strace (中略) [root@8017e5e28d6e /]# cat <<EOF > script.sh > cat <<EOS > foo > bar > baz > EOS > EOF [root@8017e5e28d6e /]# strace -f bash script.sh |& grep tmp [pid 61] stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0 [pid 61] faccessat(AT_FDCWD, "/tmp", W_OK) = 0 [pid 61] statfs("/tmp", {f_type=OVERLAYFS_SUPER_MAGIC, f_bsize=4096, f_blocks=6159700, f_bfree=4601655, f_bavail=4282999, f_files=1572864, f_ffree=1414766, f_fsid={val=[3003212711, 622231591]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_RELATIME}) = 0 [pid 61] open("/tmp/sh-thd-1631118709", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3 [pid 61] open("/tmp/sh-thd-1631118709", O_RDONLY) = 4 [pid 61] unlink("/tmp/sh-thd-1631118709") = 0 /tmp/sh-thd-1631118709 に書き込みをしている様子が見て取れます。 ...

2021-09-08 · nasa9084