Skip to content

feat: Botが自分のメッセージについた他人のスタンプを削除する - #3079

Open
renkonmaster wants to merge 8 commits into
masterfrom
feat/bot-remove-stamp
Open

feat: Botが自分のメッセージについた他人のスタンプを削除する#3079
renkonmaster wants to merge 8 commits into
masterfrom
feat/bot-remove-stamp

Conversation

@renkonmaster

@renkonmaster renkonmaster commented Jun 21, 2026

Copy link
Copy Markdown

close: #3021

DELETE /messages/:messageID/stamps/:stampID にクエリパラメータを追加:

パラメータ デフォルト 説明
include-me boolean true 自分が押したスタンプを削除する
include-other boolean false 自分以外が押したスタンプを削除する

service/message/manager_impl.go

  • includeMe=true
    • 変更無し
  • includeOther=true
    • Botかつ自分のメッセージのときのみ削除できる。

Summary by CodeRabbit

  • New Features

    • Message stamp deletion now supports selective removal via include-me and include-other options, letting you delete your stamps, others’ stamps, or both.
  • Bug Fixes

    • Permission handling is stricter for removing others’ stamps: unauthorized attempts now return a forbidden response.
    • Deletion behavior now reliably removes only the selected stamp set and updates state accordingly.
  • Documentation

    • Updated API documentation for the stamp-deletion endpoint options and improved related endpoint text formatting.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The message stamp deletion flow now accepts include-me and include-other query flags, adds permission checks for removing other users’ stamps, and updates the repository and tests to support the new behavior.

Changes

Selective stamp removal

Layer / File(s) Summary
API contract and query binding
docs/v3-api.yaml, router/v3/messages.go, service/message/manager.go, repository/message.go
removeMessageStamp now documents selective deletion, the router binds the new query flags, and the manager/repository contracts add the new removal and error signatures. Minor Qall description formatting changes are also included.
Selective deletion and authorization
service/message/manager_impl.go
RemoveStamps now conditionally deletes self and other users' stamps, checks bot ownership before removing other users' stamps, and keeps cache invalidation after the removals.
Repository and test updates
repository/gorm/message.go, repository/mock_repository/mock_message.go, service/message/manager_test.go, service/message/manager_impl_test.go
RemoveOtherStampFromMessage is implemented and mocked, the shared test repo gains a user repository mock, and RemoveStamps tests cover the new flags and permission outcomes.

Sequence Diagram(s)

sequenceDiagram
  participant RemoveMessageStamp
  participant MessageManager
  participant UserRepository
  participant MessageRepository
  participant Cache
  RemoveMessageStamp->>MessageManager: RemoveStamps(includeMe, includeOther)
  alt includeOther is true
    MessageManager->>UserRepository: GetUser(userID)
    alt user is bot and owns the message
      MessageManager->>MessageRepository: RemoveOtherStampFromMessage
    else not permitted
      MessageManager-->>RemoveMessageStamp: ErrCannotRemoveStamp
    end
  end
  alt includeMe is true
    MessageManager->>MessageRepository: RemoveStampFromMessage
  end
  MessageManager->>Cache: Forget(id)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Hop hop, the stamps take flight,
Some stay left, some vanish right.
Bot ears twitch, the cache goes poof,
New flags dance beneath the roof.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds selective stamp deletion, but it still targets a single stampId and adds permission gating, so it doesn't fully meet the bulk-delete-all-types requirement. Support deletion across all stamp types on the specified message and align behavior with the issue's bulk-delete plus optional ignore-me requirement.
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 (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the main change: enabling a bot to delete other users' stamps from its own messages.
Out of Scope Changes check ✅ Passed The changes stay focused on stamp-deletion flow, API docs, repository, manager, router, and tests without unrelated feature work.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/bot-remove-stamp

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.

@renkonmaster
renkonmaster marked this pull request as ready for review June 25, 2026 01:18
@renkonmaster
renkonmaster requested a review from a team as a code owner June 25, 2026 01:18

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
docs/v3-api.yaml (1)

705-733: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Document the new 403 Forbidden response.

RemoveMessageStamp now maps message.ErrCannotRemoveStamp to herror.Forbidden (403) when a caller lacks permission to remove others' stamps, but this operation only documents 204 and 404. Add a 403 response so the contract reflects the new behavior.

📝 Proposed addition
         "404":
           description: |-
             Not Found
             メッセージ、またはスタンプが見つかりません。
+        "403":
+          description: |-
+            Forbidden
+            スタンプを削除する権限がありません。
       operationId: removeMessageStamp
🤖 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 `@docs/v3-api.yaml` around lines 705 - 733, The RemoveMessageStamp operation is
missing the new forbidden case in its API contract. Update the delete response
definitions for removeMessageStamp in the v3 API spec to include a 403 Forbidden
response alongside the existing 204 and 404 entries, matching the behavior where
message.ErrCannotRemoveStamp is mapped to herror.Forbidden when the caller lacks
permission to remove others’ stamps.
🧹 Nitpick comments (2)
router/v3/messages.go (1)

18-21: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer binding booleans directly instead of strings + manual defaults.

IncludeMe/IncludeOther are modeled as string and then coerced via isTrue, with empty-string defaulting done by hand. Binding to *bool (or bool with explicit default handling) lets the framework parse the boolean and removes the stringly-typed indirection, keeping the handler aligned with the OpenAPI boolean schema.

Also applies to: 298-303

🤖 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 `@router/v3/messages.go` around lines 18 - 21, Update DeleteStampsQuery to bind
IncludeMe and IncludeOther as booleans instead of strings, and adjust the
corresponding handler logic to use the parsed values directly rather than
calling isTrue or manually defaulting empty strings. Make the same change in the
other affected query struct mentioned by the review so the router types stay
aligned with the OpenAPI boolean schema and the existing query binding flow.
service/message/manager_impl_test.go (1)

558-731: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Thorough coverage of the permission matrix.

The subtests correctly exercise the bot-vs-non-bot × own-vs-other-message gating, the combined includeMe/includeOther path, and GetUser error propagation, matching the RemoveStamps implementation.

One gap worth considering: there is no subtest asserting that RemoveOtherStampFromMessage is not invoked when the permission check fails (the failing cases rely on gomock's absence of an expectation). gomock already fails on unexpected calls, so this is optional, but an explicit Times(0) would make intent clearer.

🤖 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 `@service/message/manager_impl_test.go` around lines 558 - 731, Add an explicit
negative assertion for the failing RemoveStamps permission paths so it is clear
that RemoveOtherStampFromMessage is never called when the bot/non-bot or
own/other-message check rejects the request. Update the relevant RemoveStamps
subtests in manager_impl_test.go to set a Times(0) expectation on
MockMessageRepository.RemoveOtherStampFromMessage for the cases that should
fail, while keeping the existing success-path expectations for the
includeMe/includeOther cases.
🤖 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 `@repository/gorm/message.go`:
- Line 556: Remove the leftover debug artifacts from the message repository
flow: the bare fmt.Println() in the affected function and the
repo.logger.Info(userID.String()) call that logs the caller UUID on every
invocation. Locate the cleanup in the message handling logic around the same
path as the existing userID and logger usage, and delete both statements without
changing the surrounding behavior.

In `@repository/message.go`:
- Line 128: The godoc above RemoveOtherStampFromMessage uses the wrong leading
symbol name, so update the comment to start with RemoveOtherStampFromMessage
instead of RemoveStampFromMessage. Keep the rest of the Japanese description
intact, and ensure the comment matches the method name exactly to satisfy Go
documentation conventions and align with the sibling method naming in
message.go.
- Line 133: Remove the debug artifact and privacy-unsafe logging from
RemoveOtherStampFromMessage in the repository/message.go implementation. Delete
the active fmt.Println call and replace the repo.logger.Info(userID.String())
usage with no user identifier logging at all, keeping only production-safe
context if needed. Make sure the cleanup is applied in the
RemoveOtherStampFromMessage flow and any related helper logic that currently
emits these messages.

In `@service/message/manager_impl.go`:
- Around line 325-328: The error wrapping in the includeOther branch uses the
wrong function name, which will mislead debugging in the
RemoveOtherStampFromMessage path. Update the fmt.Errorf message inside
manager_impl.go’s includeOther handling to match the actual repository call
m.R.RemoveOtherStampFromMessage, keeping the wrapped error context accurate for
that branch.

---

Outside diff comments:
In `@docs/v3-api.yaml`:
- Around line 705-733: The RemoveMessageStamp operation is missing the new
forbidden case in its API contract. Update the delete response definitions for
removeMessageStamp in the v3 API spec to include a 403 Forbidden response
alongside the existing 204 and 404 entries, matching the behavior where
message.ErrCannotRemoveStamp is mapped to herror.Forbidden when the caller lacks
permission to remove others’ stamps.

---

Nitpick comments:
In `@router/v3/messages.go`:
- Around line 18-21: Update DeleteStampsQuery to bind IncludeMe and IncludeOther
as booleans instead of strings, and adjust the corresponding handler logic to
use the parsed values directly rather than calling isTrue or manually defaulting
empty strings. Make the same change in the other affected query struct mentioned
by the review so the router types stay aligned with the OpenAPI boolean schema
and the existing query binding flow.

In `@service/message/manager_impl_test.go`:
- Around line 558-731: Add an explicit negative assertion for the failing
RemoveStamps permission paths so it is clear that RemoveOtherStampFromMessage is
never called when the bot/non-bot or own/other-message check rejects the
request. Update the relevant RemoveStamps subtests in manager_impl_test.go to
set a Times(0) expectation on MockMessageRepository.RemoveOtherStampFromMessage
for the cases that should fail, while keeping the existing success-path
expectations for the includeMe/includeOther cases.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a19549f4-28bc-4e98-b5a9-03c10aebe4a5

📥 Commits

Reviewing files that changed from the base of the PR and between 82eb129 and 5d2cf3c.

📒 Files selected for processing (9)
  • docs/v3-api.yaml
  • repository/gorm/message.go
  • repository/message.go
  • repository/mock_repository/mock_message.go
  • router/v3/messages.go
  • service/message/manager.go
  • service/message/manager_impl.go
  • service/message/manager_impl_test.go
  • service/message/manager_test.go

Comment thread repository/gorm/message.go Outdated
Comment thread repository/message.go Outdated
Comment thread repository/message.go
Comment thread service/message/manager_impl.go
@renkonmaster renkonmaster self-assigned this Jun 25, 2026

@Takeno-hito Takeno-hito left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

実装ありがとうございます!コメント確認お願いします

Comment thread docs/v3-api.yaml
in: query
name: include-me
description: "自分が押したスタンプを削除します"
- schema:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

q: パラメーターが2つある理由はある? (include-me, include-other 片方だけじゃだめ?)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

userIds?: uuid

Comment thread docs/v3-api.yaml
type: boolean
default: false
in: query
name: include-other

@Takeno-hito Takeno-hito Jul 1, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

imo: スキーマの部分事前に乗れなくてごめんだったけど、利用用途を考えるならどちらかというと "user_id" を指定して消せるようにする、の方が綺麗じゃないかなぁ…? ( include-me, include-other はちょっとむずかしそうな使い方に見える)

MUST: これ見てるだけだと Bot 以外も使えそうだけど Bot 以外も使えるようにするのは微妙な気もするから、Bot 限定ってしたいかも!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

命名でどうにかするとしたら "remove-mine" "remove-others" とかの方がいいかも (include って入ってるのが変かもと思いました)

}

// RemoveOtherStampFromMessage implements MessageRepository interface.
func (repo *Repository) RemoveOtherStampFromMessage(ctx context.Context, messageID, stampID, userID uuid.UUID) (err error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MUST* 命名が微妙かも せめて RemoveOtherUsersStamp と他の "USER" であることがわかるようにしてほしい!
もしくは、 API の形式を自分の提案通りにしたら、こういう例外処理を作る必要がそもそもなくなるはず!


if result.RowsAffected > 0 {
for _, stamp := range ms {
if stamp.UserID == userID {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

q: この条件要る?要らない気がする!

Comment thread router/v3/messages.go
return herror.BadRequest(err)
}

if len(q.IncludeMe) == 0 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

q: bindAndValidate でこのバインド処理ってできない?(デフォ値って設定できない?)ちょっと実装が不思議かも…?

せめて、 `q.IncludeMe == "" かな len==0 の書き方はちょっと見づらい

Comment on lines +320 to +328
if includeMe {
if err := m.R.RemoveStampFromMessage(ctx, id, stampID, userID); err != nil {
return fmt.Errorf("failed to RemoveStampFromMessage: %w", err)
}
}
if includeOther {
if err := m.R.RemoveOtherStampFromMessage(ctx, id, stampID, userID); err != nil {
return fmt.Errorf("failed to RemoveOtherStampFromMessage: %w", err)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

memo: transaction って traQ ないんだっけ

@ramdos0207 ramdos0207 moved this from Inbox to In review in traQ Server Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

botは自分のメッセージに付いた他人のスタンプを消せるようにする

3 participants