くりにっき

フルスタックキュアエンジニアです

feed_squeezerを作った

これなに?

RSSフィードを任意のキーワードで絞り込んだ結果をさらに別のフィードとして返すためのproxy的なウェブアプリです。

github.com

モチベーション

僕はSlackで色々なRSSフィードを購読しています。

YouTubeのチャンネルにもRSSフィードが存在しているのでSlackで購読しています。

例えば 東映アニメーション公式YouTubeチャンネル - YouTube にはプリキュアをはじめとして様々な動画が公開されています。その中でプリキュアに関係する動画だけをSlackで購読したいってことがよくあるため作りました。

2〜3年前くらいに作って個人Slack内でほそぼそと運用していたのですが、OSS化する機運が高まったのでOSS化しました。

2024/06/21 19:59 追記

個人slackだとこういうクエリでfeedをsubscribeしています

使った技術

  • Go
  • Bootstrap
  • Vue.js

工夫ポイント

配布形式をどうするか

Webサービスとして公開するのも考えたのですが、色んなところで使われだすとGoogle Cloudの個人アカウントのCloud RunやCloud Functionsの無料枠が一瞬で吹き飛びそうな気がしたのでDockerイメージやバイナリでの配布にしています。

ちなみにこの画面はローカルで動かしているのを撮影したのでlocalhostになってますが、実際はSlackbotからアクセスできる場所に置く必要があるので自分の好きな場所にDockerイメージやバイナリを動かして利用してください。

僕のおすすめはCloud Runで、Terraformのサンプルコードも置いています。 https://github.com/sue445/feed_squeezer/tree/main/_examples/gcp_cloud_run_terraform

GoでGoogleライクな検索クエリで文字列マッチするような関数を作った

  • AAA BBB : AND検索
  • AAA | BBB : OR検索
  • (AAA BBB) | CCC, (AAA | BBB) CCC : 括弧をつけて検索条件の優先順位付け

具体的には https://github.com/alecthomas/participle というパーサーライブラリを用いて実装しました。

github.com

participleは汎用的なパーサーライブラリなので使うのが難しかったのですが、ChatGPTに助けてもらいながら実装できました。

取得したフィードを一瞬だけキャッシュする

Slackでフィードを購読する時は /feed subscribe *1 を使います。

登録されたフィードは10〜15分おきくらいにSlackbotによる購読チェックが実行されます。

この時にSlackbotは同一のURLに対してほぼ同時にHEADとGETを実行します。

YouTubeチャンネルのフィードには短時間ながらRateLimitが設定されているため、瞬間的にたくさん呼び出すと429エラー(Too Many Requests)になります。

この429エラーを回避するためにキャッシュを導入しました。

バイナリにviewを同梱する

feed_squeezerに渡すurlやqueryなどのパラメータはURLエンコーディングする必要があります。

手でURLエンコーディングするのは大変なのでいい感じに変換するためのフォームをトップページに用意しています。

Goの https://pkg.go.dev/embed を用いてHTMLファイルをバイナリに含めています。

ただしjsやcssなどもバイナリに含めるとバイナリサイズが大きくなりそうだったのでHTMLファイルで利用しているBootstrapやVue.jsなどはCDN経由で参照するようにしました。

ちなみにこれがOSS化する前のfeed_squeezerの画面です。Bootstrapを入れるだけで全然違うなw

最近のエコシステムに乗っかる

今までGo製のツールを作る時はバイナリリリースとかCIでのlint実行とかはオレオレ実装を流用してたのですが、この機会に https://github.com/goreleaser/goreleaserhttps://github.com/golangci/golangci-lint にも初挑戦しました。

2024/06/14 13:28 追記:ブコメレス

id:igrep

絞るのに特化したYahoo! Pipesみたいな

なるほど。Yahoo! Pipesは全然知らなかったです