Skip to content

RSSモジュールを追加#252

Open
yuito-it wants to merge 14 commits into
feat/gofrom
feat/rss
Open

RSSモジュールを追加#252
yuito-it wants to merge 14 commits into
feat/gofrom
feat/rss

Conversation

@yuito-it

@yuito-it yuito-it commented Jun 12, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

リリースノート

  • New Features

    • RSS フィード購読機能を追加。Discord のスラッシュコマンドで RSS フィードを登録でき、新規記事が自動的にチャンネルに投稿されるようになりました。
  • Chores

    • ビルド環境の依存関係とベースイメージを最新化しました。
    • CI/CD パイプラインを拡張し、複数のコンテナイメージを効率的にビルドできるよう改善しました。

@yuito-it yuito-it requested a review from a team June 12, 2026 12:08
@yuito-it yuito-it requested review from a team as code owners June 12, 2026 12:08
@yuito-it yuito-it requested a review from sibapybot June 12, 2026 12:08
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yuito-it, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 26 minutes. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ca724019-a2d3-444b-b18f-5b81492a11f3

📥 Commits

Reviewing files that changed from the base of the PR and between bc6d4b1 and 1008af4.

📒 Files selected for processing (4)
  • Dockerfile.main
  • Dockerfile.rss_cron
  • src/go.mod
  • src/internal/bot/handlers/interaction/command/general/rss/subscribe.go
📝 Walkthrough

Walkthrough

このプルリクエストは、Discord ボットに RSS フィード監視機能を追加し、複数アプリケーション対応ビルドシステムを構築する変更を実装しています。新規 rss_cron アプリケーション、購読管理コマンド、データモデル更新、動的化された Docker・ビルドパイプラインを含みます。

Changes

RSS フィード監視機能

Layer / File(s) Summary
RSSSetting データモデルとリポジトリ
src/internal/model/rss_setting.go, src/internal/repository/guild.go
RSSSettingTitle を nullable に変更、IsFailedLastItemTitleDescriptionHash を追加。GuildRepository.GetOrCreate で存在確認→作成フローを実装。
RSS Cron アプリケーション実装
src/cmd/rss_cron/main.go
Discord ボットとして起動し、Ready イベント時に RSS 設定を列挙。各フィードを gofeed で解析し、新規記事を Discord へ投稿。失敗時は IsFailed 更新、成功時は最新ハッシュを保存。
Discord スラッシュコマンド登録と購読処理
src/internal/bot/handlers/interaction/command/general/rss.go, src/internal/bot/handlers/interaction/command/general/rss/subscribe.go, src/internal/bot/handlers/interaction/registry.go
/rss subscribe コマンドを定義・実装。url(必須)と title(任意)を入力、gofeed で RSS 取得・解析。DM は拒否、成功時はギルド・チャンネル・URL・タイトル・記事ハッシュを DB に保存。

複数アプリケーション対応ビルド・デプロイシステム

Layer / File(s) Summary
GitHub Actions ワークフロー トリガーと環境変数抽出
.github/workflows/docker-tag.yaml
タグトリガーを v* から bot/v*rss-cron/v* に変更。タグから IMAGE_NAME・DOCKERFILE・TAG_NAME を抽出・環境変数に設定。
Docker メタデータと build/push 設定
.github/workflows/docker-tag.yaml
docker/metadata-actioninfra/${{ env.IMAGE_NAME }} 宛に semver タグ生成。docker/build-push-actionfile と cache 参照を動的に設定。
ビルドスクリプト TARGET 変数と go build 統一化
scripts/_build.sh
--rss-cron フラグで TARGET を cmd/rss_cron/main.go または cmd/bot/main.go に切り替え。go rungo build で TARGET を使用し、単一スクリプトで複数アプリをサポート。
RSS Cron アプリケーション用 Dockerfile
Dockerfile.rss_cron
マルチステージビルド。ビルダーステージで Go 1.26.4-alpine3.24 でビルド、ランタイムステージで alpine 3.24.0 に ca-certificates を導入して実行。OCI メタデータラベルを付与。
ベースイメージ・依存ライブラリ更新
Dockerfile.main, src/go.mod
Dockerfile.main の Go ビルダーを 1.26.4-alpine3.24 に、ランタイム alpine を 3.24.0 に更新。go.mod に gofeed と関連間接依存を追加。

Sequence Diagram(s)

sequenceDiagram
  participant Ready as Ready Handler
  participant DB as Database
  participant Repo as RSS Repo
  participant Parser as gofeed
  participant Discord as Discord API
  participant Update as DB Update
  Ready->>Repo: List RSS Settings
  Repo->>DB: Query all settings
  DB-->>Repo: Settings array
  Repo-->>Ready: Settings array
  loop Each RSS Setting
    Ready->>Parser: ParseURL(url)
    alt Parse Failed
      Ready->>Update: IsFailed = true
      Update->>DB: Update setting
    else Parse Success
      Parser-->>Ready: Feed data
      Ready->>Ready: Sort items by PublishedParsed
      Ready->>Ready: Collect target items by hash
      loop Each target item
        Ready->>Discord: CreateMessage(title, description, link)
        Discord-->>Ready: Message created
      end
      Ready->>Ready: Compute new hash from first item
      Ready->>Update: LastItemTitleDescriptionHash, IsFailed = false
      Update->>DB: Update setting
    end
  end
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed RSSモジュールの追加という主要な変更を簡潔に表現しており、大規模な変更セット全体を適切に要約しています。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rss

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@yuito-it yuito-it changed the base branch from main to feat/go June 12, 2026 12:08
@yuito-it yuito-it removed the request for review from sibapybot June 12, 2026 12:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/go.mod (2)

3-3: ⚠️ Potential issue | 🟡 Minor

go.mod の go 1.24.4 は有効だが、Docker の Go バージョンと整合させてください

  • src/go.modgo 1.24.4 は公式に存在する有効なリリースです
  • ただし Dockerfile.main / Dockerfile.rss_crongolang:1.26.4-alpine3.24 を使用しているため、意図したターゲットランタイムに合わせて go.mod と統一(1.24.x に固定するか、1.26.x へ更新)してください
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/go.mod` at line 3, Update the Go version to be consistent between
src/go.mod and your Dockerfiles: change the module directive "go 1.24.4" in
src/go.mod to match the Docker images (or update the Dockerfiles to match the
module), e.g., set src/go.mod to "go 1.26.4" if you keep
golang:1.26.4-alpine3.24 in Dockerfile.main and Dockerfile.rss_cron; ensure the
version string in the go directive exactly matches the intended toolchain so
builds inside Docker and local `go` behave identically.

20-46: ⚠️ Potential issue | 🟠 Major

間接依存(RSS側)の既知脆弱性が検出されました(更新必須)

  • golang.org/x/net v0.49.0(// indirect): GO-2026-5025/5027/5028/5029/5030(固定: v0.55.0
  • github.com/jackc/pgx/v5 v5.8.0(// indirect): GO-2026-4771/4772(固定: v5.9.0
  • 標準ライブラリ(Go 1.26.3): net/textproto / mime / crypto/x509(固定: go1.26.4。Goツールチェーン更新が必要)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/go.mod` around lines 20 - 46, The go.mod contains indirect dependencies
with known vulnerabilities; update the versions and toolchain: bump
golang.org/x/net from v0.49.0 to v0.55.0 and github.com/jackc/pgx/v5 from v5.8.0
to v5.9.0, and update the Go toolchain directive to go1.26.4 (or the project's
Go version to 1.26.4) to pick up standard-library fixes; then run go get
golang.org/x/net@v0.55.0 and go get github.com/jackc/pgx/v5@v5.9.0 (or edit
go.mod and run go mod tidy) and re-run tests/build to ensure no breakage.
🧹 Nitpick comments (2)
Dockerfile.rss_cron (2)

20-22: ⚡ Quick win

コンテナが root ユーザーで実行されます。

セキュリティのベストプラクティスとして、コンテナは非特権ユーザーで実行すべきです。現在のイメージは root ユーザーで実行されるため、コンテナが侵害された場合の影響範囲が広がります。

🛡️ 修正案: 非特権ユーザーを追加
 FROM alpine:3.24.0
 WORKDIR /root/
 
+RUN addgroup -g 1000 appuser && \
+    adduser -D -u 1000 -G appuser appuser
+
 RUN apk update && apk add --no-cache \
     opus \
     opus-dev \
     opusfile \
     opusfile-dev \
     ffmpeg
 
 ENV PKG_CONFIG_PATH=/root/.local/lib/pkgconfig
 ENV LD_LIBRARY_PATH=/root/.local/lib/
 COPY --from=builder /root/.local/ /root/.local/
 RUN chmod -R 755 /root/.local
 
+WORKDIR /home/appuser
 COPY --from=builder /app/src/main .
-RUN chmod 755 ./main
+RUN chown appuser:appuser ./main && chmod 755 ./main
 
+USER appuser
 CMD ["/root/main"]

注: CMD のパスも /home/appuser/main に変更する必要があります。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile.rss_cron` around lines 20 - 22, コンテナが root で実行されているので、Dockerfile
のイメージ設定を非特権ユーザーで動くように修正してください: ベースの WORKDIR を /home/appuser に変更し、Dockerfile
内でユーザー appuser を作成(例: group/user 作成と HOME 設定)、該当ワークディレクトリとバイナリに対して所有権を chown
し、最後に USER appuser を追加してコンテナを非 root で実行するようにし、合わせて CMD のパスを /home/appuser/main
に更新してください(命名参照: WORKDIR, CMD, USER, appuser)。

Source: Linters/SAST tools


35-36: 💤 Low value

実行権限が過剰です。

chmod 777 は書き込み権限を全ユーザーに付与しますが、実行ファイルには不要です。chmod 755 で十分です。

♻️ 修正案
-RUN chmod 777 ./main
+RUN chmod 755 ./main
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile.rss_cron` around lines 35 - 36, 実行バイナリの権限設定が過剰です:現在の RUN chmod 777
./main(直後の COPY --from=builder /app/src/main .
にある実行ファイル)を実行ファイルに必要な最小権限に下げるよう修正してください。具体的には chmod 777 を chmod 755
に変更して、所有者に書き込みを残しつつグループ/その他には実行・読み取りのみ与えるようにしてください。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/docker-tag.yaml:
- Around line 28-45: The rss-cron image is built without passing the --rss-cron
flag to scripts/_build.sh, so Dockerfile.rss_cron ends up embedding the bot
binary; update Dockerfile.rss_cron to invoke ../scripts/_build.sh with the
--rss-cron argument (ensure the RUN line passes "--rss-cron"), and verify
scripts/_build.sh still recognizes that flag and sets TARGET appropriately (the
scripts/_build.sh entry handling --rss-cron and the Dockerfile.rss_cron RUN
invocation are the symbols to change).

In `@Dockerfile.main`:
- Line 19: The RUN instruction "RUN apk add build-base cmake ninja zip pkgconfig
perl nasm" leaves APK cache in the image; update that command to include the
--no-cache flag (i.e., "apk add --no-cache ...") so the package cache is not
stored in the layer, matching the existing pattern used earlier in the
Dockerfile.
- Line 33: Dockerfile のベースイメージ指定 "FROM alpine:3.24.0" は存在しないタグになっているため、実在する
Alpine のタグに置き換えてください(例: alpine:3.18 or alpine:latest); 変更後にローカル/CI 環境で docker
pull <タグ> または docker manifest inspect <タグ> を実行してタグが有効であることを確認し、Dockerfile の
"FROM alpine:3.24.0" 行をその有効なタグに更新してください。
- Line 3: Replace the non-existent base image tag "golang:1.26.4-alpine3.24" in
the Dockerfile's FROM instruction with a real, published tag (e.g.,
"golang:1.26.4-alpine" or another alpine variant confirmed via `docker manifest
inspect`); update the FROM line to use that verified tag so the builder stage
(FROM golang:1.26.4-alpine3.24) pulls successfully.

In `@Dockerfile.rss_cron`:
- Line 18: The Dockerfile currently invokes the build script without the target
flag, causing the default bot binary to be built; update the RUN invocation of
../scripts/_build.sh to pass the --rss-cron flag so the script builds the
rss_cron target (refer to the _build.sh script and the --rss-cron flag).
- Around line 30-33: Dockerfile の rss_cron イメージでビルダーステージに存在しない /root/.local
を参照している ENV PKG_CONFIG_PATH=/root/.local/lib/pkgconfig、ENV
LD_LIBRARY_PATH=/root/.local/lib/、COPY --from=builder /root/.local/
/root/.local/、RUN chmod -R 755 /root/.local
の各命令は不要なのでこれらの行を削除してビルド失敗や空ディレクトリのコピーを防いでください(rss_cron 用には /root/.local
を作成・利用していないため、該当する ENV/COPY/CHMOD 行を取り除くだけで問題ありません)。
- Around line 23-28: The Dockerfile's apk add includes audio packages (opus,
opus-dev, opusfile, opusfile-dev, ffmpeg) that are only needed by the Discord
voice code (voice/player.go) but not by rss_cron (rss_cron/main.go); remove
those packages from the RUN apk add line so the rss_cron image doesn't carry
unnecessary binaries and size/attack-surface. Locate the RUN apk update && apk
add --no-cache block and delete opus, opus-dev, opusfile, opusfile-dev and
ffmpeg from that list, then rebuild and verify rss_cron/main.go still builds
without audio deps.

In `@src/cmd/rss_cron/main.go`:
- Around line 111-146: The loop that builds targetItems incorrectly dereferences
rssSetting.LastItemTitleDescriptionHash and collects only the matching item; fix
by treating LastItemTitleDescriptionHash as nullable, iterating feed.Items from
newest to oldest and collecting each item into targetItems until you encounter a
computed hash equal to the saved hash (stop when matched) so that first-run (nil
saved hash) collects all items; keep using the existing hash computation
(base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", item.Title,
item.Description)))) and slices.Reverse(targetItems) so older-to-newer order is
preserved; after successfully sending messages via client.Rest.CreateMessage,
persist the newest item's hash into rssSetting.LastItemTitleDescriptionHash and
set rssSetting.IsFailed=false (and only mark failure on send error) so state
advances correctly.
- Around line 88-100: When fp.ParseURL(url) returns an error, you currently mark
rssSetting.IsFailed and call repo.Update(rssSetting) but then continue to use
feed (e.g., feed.Title and feed.Items) causing a panic; after successfully
updating the failed rssSetting you must skip further processing for that item
(i.e., continue the loop). Locate the ParseURL error branch around
fp.ParseURL(url), rssSetting.IsFailed and repo.Update and add a control flow
break (continue) after the update so no code references feed when parse failed.

In `@src/internal/bot/handlers/interaction/command/general/rss/subscribe.go`:
- Around line 80-95: responseEmbed の成功メッセージが TTS 用の文言になっているため、discord.Embed
を作成している箇所(変数 responseEmbed、discord.Embed の Title/Description フィールド)を修正して RSS
購読完了を正しく案内する文言に置き換えてください(例: Title を「RSS購読を開始しました」、Description
を「指定されたフィードの購読を開始しました」等)。CreateFollowupMessage /
discord.NewMessageCreate().WithEmbeds の呼び出しはそのまま使い、Footer や Timestamp は維持してください。
- Around line 70-78: The RSSSetting being saved lacks ChannelID and ignores DB
errors; update the logic around repository.NewGuildRepository/
guildRepo.GetOrCreate and repository.NewRSSSettingRepository/ rssRepo.Create to
(1) pass and persist the current channel ID into the model.RSSSetting.ChannelID
field, and (2) check and handle returned errors from GetOrCreate and Create (and
any DB ops via ctx.DB), ensuring that if any of these calls fail you do not
return a success response. Locate uses of GetOrCreate, Create, and the
RSSSetting struct to add ChannelID and propagate/handle errors appropriately so
cron code (snowflake.MustParse(rssSetting.ChannelID)) receives a valid saved
ChannelID.

In `@src/internal/bot/handlers/interaction/registry.go`:
- Around line 68-70: The "/rss" route currently only applies
DeferReplyMiddleware and has no execution handler, so the SlashCommand
registered in LoadRssCommandContext() never gets invoked; update the route
registration in registry.go to attach the actual handler by calling
rss.Subscribe(ctxData) (or the appropriate Subscribe handler function) inside
r.Route("/rss", ...) so the SlashCommand has an execution path while keeping
DeferReplyMiddleware applied.

---

Outside diff comments:
In `@src/go.mod`:
- Line 3: Update the Go version to be consistent between src/go.mod and your
Dockerfiles: change the module directive "go 1.24.4" in src/go.mod to match the
Docker images (or update the Dockerfiles to match the module), e.g., set
src/go.mod to "go 1.26.4" if you keep golang:1.26.4-alpine3.24 in
Dockerfile.main and Dockerfile.rss_cron; ensure the version string in the go
directive exactly matches the intended toolchain so builds inside Docker and
local `go` behave identically.
- Around line 20-46: The go.mod contains indirect dependencies with known
vulnerabilities; update the versions and toolchain: bump golang.org/x/net from
v0.49.0 to v0.55.0 and github.com/jackc/pgx/v5 from v5.8.0 to v5.9.0, and update
the Go toolchain directive to go1.26.4 (or the project's Go version to 1.26.4)
to pick up standard-library fixes; then run go get golang.org/x/net@v0.55.0 and
go get github.com/jackc/pgx/v5@v5.9.0 (or edit go.mod and run go mod tidy) and
re-run tests/build to ensure no breakage.

---

Nitpick comments:
In `@Dockerfile.rss_cron`:
- Around line 20-22: コンテナが root で実行されているので、Dockerfile
のイメージ設定を非特権ユーザーで動くように修正してください: ベースの WORKDIR を /home/appuser に変更し、Dockerfile
内でユーザー appuser を作成(例: group/user 作成と HOME 設定)、該当ワークディレクトリとバイナリに対して所有権を chown
し、最後に USER appuser を追加してコンテナを非 root で実行するようにし、合わせて CMD のパスを /home/appuser/main
に更新してください(命名参照: WORKDIR, CMD, USER, appuser)。
- Around line 35-36: 実行バイナリの権限設定が過剰です:現在の RUN chmod 777 ./main(直後の COPY
--from=builder /app/src/main . にある実行ファイル)を実行ファイルに必要な最小権限に下げるよう修正してください。具体的には
chmod 777 を chmod 755 に変更して、所有者に書き込みを残しつつグループ/その他には実行・読み取りのみ与えるようにしてください。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 01912ca8-56f4-456a-89ed-411fffa004cc

📥 Commits

Reviewing files that changed from the base of the PR and between c48231c and cfcac61.

⛔ Files ignored due to path filters (1)
  • src/go.sum is excluded by !**/*.sum
📒 Files selected for processing (11)
  • .github/workflows/docker-tag.yaml
  • Dockerfile.main
  • Dockerfile.rss_cron
  • scripts/_build.sh
  • src/cmd/rss_cron/main.go
  • src/go.mod
  • src/internal/bot/handlers/interaction/command/general/rss.go
  • src/internal/bot/handlers/interaction/command/general/rss/subscribe.go
  • src/internal/bot/handlers/interaction/registry.go
  • src/internal/model/rss_setting.go
  • src/internal/repository/guild.go

Comment thread .github/workflows/docker-tag.yaml
Comment thread Dockerfile.main
Comment thread Dockerfile.main Outdated
Comment thread Dockerfile.main
Comment thread Dockerfile.rss_cron Outdated
Comment thread src/cmd/rss_cron/main.go Outdated
Comment thread src/cmd/rss_cron/main.go Outdated
Comment thread src/internal/bot/handlers/interaction/command/general/rss/subscribe.go Outdated
Comment thread src/internal/bot/handlers/interaction/registry.go
yuito-it and others added 11 commits June 12, 2026 21:39
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yuito Akatsuki (Tani Yutaka) <yuito@yuito-it.jp>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yuito Akatsuki (Tani Yutaka) <yuito@yuito-it.jp>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yuito Akatsuki (Tani Yutaka) <yuito@yuito-it.jp>
…cribe.go

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yuito Akatsuki (Tani Yutaka) <yuito@yuito-it.jp>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yuito Akatsuki (Tani Yutaka) <yuito@yuito-it.jp>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yuito Akatsuki (Tani Yutaka) <yuito@yuito-it.jp>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/internal/bot/handlers/interaction/command/general/rss/subscribe.go (1)

126-146: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

成功レスポンスが公開メッセージになっており、購読 URL をチャンネルに漏らします。

このルートは DeferReplyMiddleware(ctxData, true, false) でエフェメラル応答にしているのに、成功時だけ WithEphemeral(false) を明示して URL フィールドも返しています。確認メッセージはエフェメラルに統一してください。PR objective では確認メッセージをエフェメラルで返す要件です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/internal/bot/handlers/interaction/command/general/rss/subscribe.go`
around lines 126 - 146, The success response is being sent as a public message
and leaks the subscription URL; change the follow-up create call to send the
embed ephemerally by replacing the explicit WithEphemeral(false) on the discord
message builder used in the CreateFollowupMessage call with WithEphemeral(true)
(or remove the explicit flag so it inherits DeferReplyMiddleware(ctxData, true,
false)), keeping the responseEmbed (including the URL field) and the
CreateFollowupMessage invocation unchanged otherwise so the confirmation remains
ephemeral.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/internal/bot/handlers/interaction/command/general/rss/subscribe.go`:
- Around line 97-108: feed.Items[0] will panic on empty feeds and the current
sort comparator mishandles nil PublishedParsed and stable ties; instead,
explicitly check for zero-length feed.Items and return/handle accordingly, then
perform a single-pass scan to pick the latest item (compare
PublishedParsed.UnixNano when both non-nil, treat nil as older, and fall back to
a deterministic tie-breaker like original index or non-empty Title/Description)
and compute the hash from that chosen item (the code around sort.Slice,
feed.Items, PublishedParsed, and the hash assignment should be updated).
- Around line 73-76: The code currently calls fp.ParseURL(url) and persists url
into RSSSetting without validation, enabling SSRF; before any network fetch or
persisting in Subscribe handler (and similarly in rss_cron paths referenced at
lines 116-121), validate the input: parse the URL and require scheme == "http"
or "https", resolve the host with net.LookupIP (or equivalent) and reject any
resolved IPs that are loopback, link-local, multicast or private
(RFC1918/AF_INET6 unique local) or unspecified; only after the URL passes that
whitelist may you call gofeed.NewParser().ParseURL(url) and save to RSSSetting;
apply the same validation function for rss_cron re-fetch to prevent saved
entries from causing SSRF later.

---

Outside diff comments:
In `@src/internal/bot/handlers/interaction/command/general/rss/subscribe.go`:
- Around line 126-146: The success response is being sent as a public message
and leaks the subscription URL; change the follow-up create call to send the
embed ephemerally by replacing the explicit WithEphemeral(false) on the discord
message builder used in the CreateFollowupMessage call with WithEphemeral(true)
(or remove the explicit flag so it inherits DeferReplyMiddleware(ctxData, true,
false)), keeping the responseEmbed (including the URL field) and the
CreateFollowupMessage invocation unchanged otherwise so the confirmation remains
ephemeral.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 75a73f9f-7dc6-4a21-9d2e-9cf3e92727e3

📥 Commits

Reviewing files that changed from the base of the PR and between cfcac61 and bc6d4b1.

📒 Files selected for processing (5)
  • Dockerfile.main
  • Dockerfile.rss_cron
  • src/cmd/rss_cron/main.go
  • src/internal/bot/handlers/interaction/command/general/rss/subscribe.go
  • src/internal/bot/handlers/interaction/registry.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • Dockerfile.main
  • src/cmd/rss_cron/main.go

Comment thread src/internal/bot/handlers/interaction/command/general/rss/subscribe.go Outdated
Comment thread src/internal/bot/handlers/interaction/command/general/rss/subscribe.go Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant