Skip to content

feat: 引用メッセージのコンテキストへの取り込み#60

Merged
kaitoyama merged 12 commits intomainfrom
staging
Mar 6, 2026
Merged

feat: 引用メッセージのコンテキストへの取り込み#60
kaitoyama merged 12 commits intomainfrom
staging

Conversation

@kaitoyama
Copy link
Contributor

@kaitoyama kaitoyama commented Mar 5, 2026

ただし展開されるには次の条件のいずれかを満たす必要がある

引用メッセージの投稿者が自分
引用メッセージの投稿者がBot
引用メッセージのチャンネルが特定のチャンネル
#event / #random / #general / #services / #team/SysAd 以下全てのチャンネル
さらに1つの引用メッセージで10000文字を超えた分は省略される

Summary by CodeRabbit

新機能

  • メッセージ内のエンベッドを抽出・整形するフォーマット機能を追加
  • 引用メッセージをマークダウン形式で整形して表示する機能を実装
  • チャネル情報とユーザー情報をキャッシュすることでパフォーマンスが向上
  • ダイレクトメッセージと通常メッセージの表示品質が向上

テスト

  • フォーマット機能の信頼性を確保するユニットテストを追加

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

bot APIを通じてチャネルとユーザー情報をキャッシュする機構、メッセージ内の埋め込みと引用をフォーマットする機能を追加し、メッセージハンドラーでこれらの新しいフォーマッター機能を統合しました。

Changes

Cohort / File(s) Summary
キャッシング機構
go.mod, internal/bot/channel.go, internal/bot/user.go
GitHub依存関係github.com/motoki317/sc v1.8.2を追加。チャネルパスとユーザー情報をTTL 1時間でキャッシュするGetChannelPath()GetUser()を実装。
フォーマッター機能
internal/pkg/formatter/embed.go, internal/pkg/formatter/embed_test.go, internal/pkg/formatter/quotes.go
埋め込みJSON形式をクリーンするFormatEmbeds()、複数コンポーネント(チャネル、ユーザー、メッセージAPI)を組み合わせて引用メッセージをMarkdownフォーマットするFormatQuotedMessage()を追加。テスト3ケースを含む。
メッセージハンドラー更新
internal/handler/OnDirectMessageCreated.go, internal/handler/OnMessageCreated.go
テキスト処理フローを変更:埋め込みをフォーマット、botメンションを削除、引用メッセージをフォーマットし、フォーマット失敗時はフォールバック。messageReceived()呼び出しに新しいformattedMessageを渡す。

Sequence Diagram(s)

sequenceDiagram
    participant Handler as Message Handler
    participant Formatter as Formatter
    participant Cache as Cache (Channel/User/Message)
    participant API as TraQ API
    
    Handler->>Formatter: FormatEmbeds(message.text)
    Formatter-->>Handler: textWithEmbed
    
    Handler->>Formatter: FormatQuotedMessage(userID, textWithEmbed)
    
    Formatter->>Cache: Extract message IDs & search for quotes
    
    loop For each quoted message
        Formatter->>Cache: GetChannelPath(channelID)
        Cache->>API: Fetch channel if not cached
        API-->>Cache: Return channel path
        Cache-->>Formatter: Return cached path
        
        Formatter->>Cache: GetUser(userID)
        Cache->>API: Fetch user if not cached
        API-->>Cache: Return user detail
        Cache-->>Formatter: Return cached user
        
        Formatter->>Cache: GetMessage(messageID)
        Cache->>API: Fetch message if not cached
        API-->>Cache: Return message
        Cache-->>Formatter: Return cached message
        
        Formatter->>Formatter: Check if channel/user allows quoting
        Formatter->>Formatter: Build Markdown blockquote (truncate if needed)
    end
    
    Formatter-->>Handler: formattedMessage or error
    Handler->>Handler: messageReceived(text, formattedMessage)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

Review effort 3/5

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PRのタイトルは日本語で「feat: 引用メッセージのコンテキストへの取り込み」であり、変更セットの主要な目的である引用メッセージ機能の追加を明確に反映している。

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch staging

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Error Handling

The error handling for formatter.FormatQuotedMessage logs the error but continues with the unformatted message. Consider whether this is the desired behavior or if additional error handling is needed.

formattedMessage, err := formatter.FormatQuotedMessage(p.Message.User.ID, textWithoutMention)
if err != nil {
	log.Printf("Error formatting quoted message: %v\n", err)
	formattedMessage = textWithoutMention
Performance Concern

The function FormatQuotedMessage uses FindAllSubmatch which may be inefficient for large content. Consider optimizing the regex operation if performance issues arise.

	matches := quoteRegex.FindAllSubmatch([]byte(content), len(content))
	messageIDs := make([]string, 0, len(matches))
	for _, match := range matches {
		if len(match) < 2 {
			continue
		}
		messageID := string(match[1])
		messageIDs = append(messageIDs, messageID)
	}

	var formattedContent strings.Builder
	formattedContent.WriteString(quoteRegex.ReplaceAllString(content, ""))

	for _, messageID := range messageIDs {
		message := bot.GetMessage(messageID)
		if message == nil {
			continue
		}

		if utf8.RuneCountInString(message.Content) > maxQuoteLength {
			runes := []rune(message.Content)
			message.Content = string(runes[:maxQuoteLength]) + "(以下略)"
		}

		channelAllowed, err := isChannelAllowingQuotes(message.ChannelId)
		if err != nil {
			return "", err
		}
		userAllowed, err := isUserAllowingQuotes(userID, message.UserId)
		if err != nil {
			return "", err
		}
		if !channelAllowed && !userAllowed {
			continue
		}

		quote, err := getQuoteMarkdown(message)
		if err != nil {
			return "", err
		}
		formattedContent.WriteString("\n\n" + quote)
	}

	return formattedContent.String(), nil
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
internal/handler/OnMessageCreated.go (1)

21-27: 整形パイプラインがDM側と重複しているため、共通化を推奨します。

Line 21-27 の処理は internal/handler/OnDirectMessageCreated.go の同等ブロックと実質同一です。ヘルパー化して1か所に寄せると、今後のフォーマット仕様変更で差分不整合を防げます。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/handler/OnMessageCreated.go` around lines 21 - 27, The text
formatting pipeline (formatter.FormatEmbeds -> bot.RemoveFirstBotID ->
formatter.FormatQuotedMessage) is duplicated between OnMessageCreated.go and
OnDirectMessageCreated.go; extract this sequence into a single helper (e.g.,
FormatIncomingMessage or NormalizeAndFormatMessage) that returns the final
formattedMessage and any error, and replace the inline block in both handlers to
call that helper; ensure the helper accepts the original message text and user
ID and preserves the current fallback behavior (return the intermediate text
when FormatQuotedMessage fails) so callers keep existing semantics.
internal/pkg/formatter/embed_test.go (1)

5-35: エスケープ文字を含む raw のケースを1件追加すると、回帰耐性がさらに上がります。

Line 18/23 のような正常系に加えて、raw\"\\n を含む入力の期待値を固定しておくと、今後の正規表現変更時に壊れにくくなります。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/pkg/formatter/embed_test.go` around lines 5 - 35, Add a test case to
TestFormatEmbeds that covers a raw field containing escaped characters so we
catch regressions in JSON-unescaping; specifically, extend the tests slice used
by FormatEmbeds with an entry (e.g., name "Escaped raw") whose input is an embed
JSON containing raw with escaped quote and newline sequences (e.g., raw contains
\" and \\n) and set expected to the unescaped result (i.e., actual quote
character and a real newline where \\n was). This ensures FormatEmbeds correctly
unescapes JSON string contents like in the new test case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/bot/channel.go`:
- Around line 23-25: The current GetChannelPath uses context.Background() which
prevents callers from supplying timeouts; change GetChannelPath(channelID
string) to GetChannelPath(ctx context.Context, channelID string) and use ctx
when calling channelPathCache.Get; propagate the context through
isChannelAllowingQuotes(ctx context.Context, channelID string) and
FormatQuotedMessage(ctx context.Context, userID, content string) and update all
callers (including WebSocket event handlers MessageReceived and
DirectMessageReceived) to accept and forward the ctx so timeouts/cancellation
are honored; ensure channelPathCache.Get(ctx, channelID) is used and update any
tests and call sites accordingly.

In `@internal/bot/user.go`:
- Around line 24-26: Change the GetUser function to accept and propagate a
caller-provided context instead of using context.Background(): update the
signature from GetUser(userID string) to GetUser(ctx context.Context, userID
string), pass that ctx into userCache.Get and any internal helper like
getUserInternal(), and ensure all callers are adjusted to provide their upstream
context so cancellations/timeouts propagate correctly.

In `@internal/pkg/formatter/quotes.go`:
- Around line 16-26: The current isChannelAllowingQuotes uses allowingPrefixes
and strings.HasPrefix on channelPath which is too permissive; update
isChannelAllowingQuotes (and allowingPrefixes) so that "event", "general",
"random", and "services" are matched by exact equality with channelPath, while
"team/SysAd" is matched either by exact equality or by HasPrefix on
"team/SysAd/"; use bot.GetChannelPath to obtain channelPath as before and only
return true,nil when one of these stricter conditions is met.

---

Nitpick comments:
In `@internal/handler/OnMessageCreated.go`:
- Around line 21-27: The text formatting pipeline (formatter.FormatEmbeds ->
bot.RemoveFirstBotID -> formatter.FormatQuotedMessage) is duplicated between
OnMessageCreated.go and OnDirectMessageCreated.go; extract this sequence into a
single helper (e.g., FormatIncomingMessage or NormalizeAndFormatMessage) that
returns the final formattedMessage and any error, and replace the inline block
in both handlers to call that helper; ensure the helper accepts the original
message text and user ID and preserves the current fallback behavior (return the
intermediate text when FormatQuotedMessage fails) so callers keep existing
semantics.

In `@internal/pkg/formatter/embed_test.go`:
- Around line 5-35: Add a test case to TestFormatEmbeds that covers a raw field
containing escaped characters so we catch regressions in JSON-unescaping;
specifically, extend the tests slice used by FormatEmbeds with an entry (e.g.,
name "Escaped raw") whose input is an embed JSON containing raw with escaped
quote and newline sequences (e.g., raw contains \" and \\n) and set expected to
the unescaped result (i.e., actual quote character and a real newline where \\n
was). This ensures FormatEmbeds correctly unescapes JSON string contents like in
the new test case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4a900744-ef66-4c04-a9cd-c65a991516f1

📥 Commits

Reviewing files that changed from the base of the PR and between 95da448 and 6c3f4fc.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (8)
  • go.mod
  • internal/bot/channel.go
  • internal/bot/user.go
  • internal/handler/OnDirectMessageCreated.go
  • internal/handler/OnMessageCreated.go
  • internal/pkg/formatter/embed.go
  • internal/pkg/formatter/embed_test.go
  • internal/pkg/formatter/quotes.go

Comment on lines +23 to +25
func GetChannelPath(channelID string) (string, error) {
return channelPathCache.Get(context.Background(), channelID)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verification script from review comment
set -euo pipefail

echo "=== Checking context.Background() usage ==="
rg -n 'context\.Background\(\)' internal/bot/channel.go internal/bot/user.go -C2 2>/dev/null || echo "No matches in specified files"

echo -e "\n=== Checking GetChannelPath function definition ==="
rg -n 'func\s+GetChannelPath\s*\(' internal/bot/channel.go -C2 2>/dev/null || echo "No matches found"

echo -e "\n=== Checking all GetChannelPath call sites ==="
rg -n '\bGetChannelPath\s*\(' --type=go -C2 2>/dev/null | head -50 || echo "No matches found"

Repository: traPtitech/BOT_GPT

Length of output: 1801


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking isChannelAllowingQuotes call sites ==="
rg -n '\bisChannelAllowingQuotes\s*\(' --type=go -B2 -A2

echo -e "\n=== Checking function signatures that call GetChannelPath or isChannelAllowingQuotes ==="
rg -n 'func.*GetChannelPath|func.*isChannelAllowingQuotes|func.*quotes' --type=go -A1 | head -30

echo -e "\n=== Checking cache.Get method signature ==="
rg -n 'type.*Cache|func.*\.Get\(' --type=go internal/pkg/cache -A2 2>/dev/null || echo "Cache package info not found"

echo -e "\n=== Looking for cache implementation ==="
fd -t f '.*cache.*' --type=go 2>/dev/null || echo "No cache files found"

Repository: traPtitech/BOT_GPT

Length of output: 1393


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Function containing isChannelAllowingQuotes call at line 86 ==="
sed -n '75,95p' internal/pkg/formatter/quotes.go | cat -n

echo -e "\n=== Full function signature around line 86 ==="
sed -n '70,100p' internal/pkg/formatter/quotes.go | cat -n

echo -e "\n=== Search for cache package in internal/pkg ==="
find internal/pkg -name '*cache*' -o -name '*Cache*' 2>/dev/null

echo -e "\n=== Search for 'sc.' or cache-like pattern ==="
rg -n 'import|sc\.' internal/bot/channel.go | head -20

echo -e "\n=== Check imports in channel.go to find cache package ==="
head -20 internal/bot/channel.go

Repository: traPtitech/BOT_GPT

Length of output: 2410


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Find the function containing line 86 (isChannelAllowingQuotes call) ==="
rg -B50 'isChannelAllowingQuotes\(message.ChannelId\)' internal/pkg/formatter/quotes.go | head -60 | tail -20

echo -e "\n=== Get full function signature ==="
rg -n 'func.*Format.*Quote|^func' internal/pkg/formatter/quotes.go

echo -e "\n=== Check the actual formatter function with context ==="
sed -n '50,75p' internal/pkg/formatter/quotes.go | cat -n

echo -e "\n=== Check motoki317/sc package documentation or usage ==="
rg -n 'sc\.' internal/ -A1 -B1 | head -30

Repository: traPtitech/BOT_GPT

Length of output: 2381


🏁 Script executed:

#!/bin/bash
set -eulo pipefail

echo "=== Find all calls to FormatQuotedMessage ==="
rg -n '\bFormatQuotedMessage\s*\(' --type=go -B2 -A2

echo -e "\n=== Check the function signatures that call FormatQuotedMessage ==="
rg -B20 'FormatQuotedMessage\(' internal/ --type=go | grep -E 'func |ctx|context' | head -20

echo -e "\n=== Check if there's a handler function calling FormatQuotedMessage ==="
rg -n 'Handler|HandleMessage' internal/ --type=go -A3 | head -40

Repository: traPtitech/BOT_GPT

Length of output: 3466


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check full OnMessageCreated handler signature ==="
head -30 internal/handler/OnMessageCreated.go | cat -n

echo -e "\n=== Check full OnDirectMessageCreated handler signature ==="
head -30 internal/handler/OnDirectMessageCreated.go | cat -n

echo -e "\n=== Check where these handlers are registered/called ==="
rg -n 'MessageReceived|DirectMessageReceived' --type=go -B2 -A2 | grep -E '(main|func|Register|http|Handler)' | head -30

echo -e "\n=== Check if handlers are HTTP handlers or event handlers ==="
rg -n 'type.*Handler|func.*Handler' internal/handler/ --type=go

Repository: traPtitech/BOT_GPT

Length of output: 3610


context.Background() 固定では、外部API呼び出しのタイムアウト制御ができません。

Line 24 の実装は、呼び出し元がタイムアウトを設定しても反映できません。ネットワーク遅延時にハンドラが長時間ブロックされるリスクがあります。

ただし、修正には複数レイヤーの変更が必要です:

  • GetChannelPath(channelID string)GetChannelPath(ctx context.Context, channelID string)
  • isChannelAllowingQuotes(channelID string)isChannelAllowingQuotes(ctx context.Context, channelID string)
  • FormatQuotedMessage(userID, content string)FormatQuotedMessage(ctx context.Context, userID, content string)
  • WebSocket イベントハンドラ(MessageReceivedDirectMessageReceived)にも context を追加

現在のハンドラは WebSocket 接続に基づくイベントコールバックであり、context がないため、この変更は各レイヤーで実施が必要です。

💡 変更の概要
-func GetChannelPath(channelID string) (string, error) {
-	return channelPathCache.Get(context.Background(), channelID)
+func GetChannelPath(ctx context.Context, channelID string) (string, error) {
+	return channelPathCache.Get(ctx, channelID)
}

-func isChannelAllowingQuotes(channelID string) (bool, error) {
-	channelPath, err := bot.GetChannelPath(channelID)
+func isChannelAllowingQuotes(ctx context.Context, channelID string) (bool, error) {
+	channelPath, err := bot.GetChannelPath(ctx, channelID)
}

-func FormatQuotedMessage(userID string, content string) (string, error) {
+func FormatQuotedMessage(ctx context.Context, userID string, content string) (string, error) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/bot/channel.go` around lines 23 - 25, The current GetChannelPath
uses context.Background() which prevents callers from supplying timeouts; change
GetChannelPath(channelID string) to GetChannelPath(ctx context.Context,
channelID string) and use ctx when calling channelPathCache.Get; propagate the
context through isChannelAllowingQuotes(ctx context.Context, channelID string)
and FormatQuotedMessage(ctx context.Context, userID, content string) and update
all callers (including WebSocket event handlers MessageReceived and
DirectMessageReceived) to accept and forward the ctx so timeouts/cancellation
are honored; ensure channelPathCache.Get(ctx, channelID) is used and update any
tests and call sites accordingly.

Comment on lines +24 to +26
func GetUser(userID string) (*traq.UserDetail, error) {
return userCache.Get(context.Background(), userID)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's check the structure and find the relevant files
find . -name "user.go" -o -name "channel.go" | grep -E "(user|channel)\.go"

Repository: traPtitech/BOT_GPT

Length of output: 110


🏁 Script executed:

# Now let's examine the GetUser function in user.go at lines 24-26
cat -n internal/bot/user.go | head -35

Repository: traPtitech/BOT_GPT

Length of output: 754


🏁 Script executed:

# Let's also check the channel.go file to understand the similar pattern
cat -n internal/bot/channel.go | head -35

Repository: traPtitech/BOT_GPT

Length of output: 755


🏁 Script executed:

# Search for all usages of GetUser to understand the impact
rg "GetUser\(" -A 2 -B 2

Repository: traPtitech/BOT_GPT

Length of output: 1135


GetUser は context を非伝播のため、API遅延時の制御ができません。

Line 25で context.Background() が固定されているため、呼び出し元のキャンセルやタイムアウトが機能しません。GetUser(ctx context.Context, userID string) に変更し、上流の context を渡すようにしてください。これにより、内部の getUserInternal() に context が正しく伝播されます。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/bot/user.go` around lines 24 - 26, Change the GetUser function to
accept and propagate a caller-provided context instead of using
context.Background(): update the signature from GetUser(userID string) to
GetUser(ctx context.Context, userID string), pass that ctx into userCache.Get
and any internal helper like getUserInternal(), and ensure all callers are
adjusted to provide their upstream context so cancellations/timeouts propagate
correctly.

Comment on lines +16 to +26
var allowingPrefixes = []string{"event", "general", "random", "services", "team/SysAd"}

func isChannelAllowingQuotes(channelID string) (bool, error) {
channelPath, err := bot.GetChannelPath(channelID)
if err != nil {
return false, err
}

for _, prefix := range allowingPrefixes {
if strings.HasPrefix(channelPath, prefix) {
return true, nil
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

許可チャンネル判定が広すぎ、意図しないチャンネルを通す可能性があります。

Line 25 の HasPrefix 判定だと、general / random / event / services が前方一致で通るため、要件外チャンネルまで展開対象になるリスクがあります。
少なくとも event|random|general|services は厳密一致、team/SysAd のみ team/SysAd または team/SysAd/ 配下一致に分けるのが安全です。

🔧 判定ロジックの例
-var allowingPrefixes = []string{"event", "general", "random", "services", "team/SysAd"}
+var exactAllowingChannels = map[string]struct{}{
+	"event":    {},
+	"general":  {},
+	"random":   {},
+	"services": {},
+}

 func isChannelAllowingQuotes(channelID string) (bool, error) {
 	channelPath, err := bot.GetChannelPath(channelID)
 	if err != nil {
 		return false, err
 	}

-	for _, prefix := range allowingPrefixes {
-		if strings.HasPrefix(channelPath, prefix) {
-			return true, nil
-		}
-	}
+	if _, ok := exactAllowingChannels[channelPath]; ok {
+		return true, nil
+	}
+	if channelPath == "team/SysAd" || strings.HasPrefix(channelPath, "team/SysAd/") {
+		return true, nil
+	}

 	return false, nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var allowingPrefixes = []string{"event", "general", "random", "services", "team/SysAd"}
func isChannelAllowingQuotes(channelID string) (bool, error) {
channelPath, err := bot.GetChannelPath(channelID)
if err != nil {
return false, err
}
for _, prefix := range allowingPrefixes {
if strings.HasPrefix(channelPath, prefix) {
return true, nil
var exactAllowingChannels = map[string]struct{}{
"event": {},
"general": {},
"random": {},
"services": {},
}
func isChannelAllowingQuotes(channelID string) (bool, error) {
channelPath, err := bot.GetChannelPath(channelID)
if err != nil {
return false, err
}
if _, ok := exactAllowingChannels[channelPath]; ok {
return true, nil
}
if channelPath == "team/SysAd" || strings.HasPrefix(channelPath, "team/SysAd/") {
return true, nil
}
return false, nil
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/pkg/formatter/quotes.go` around lines 16 - 26, The current
isChannelAllowingQuotes uses allowingPrefixes and strings.HasPrefix on
channelPath which is too permissive; update isChannelAllowingQuotes (and
allowingPrefixes) so that "event", "general", "random", and "services" are
matched by exact equality with channelPath, while "team/SysAd" is matched either
by exact equality or by HasPrefix on "team/SysAd/"; use bot.GetChannelPath to
obtain channelPath as before and only return true,nil when one of these stricter
conditions is met.

@kaitoyama kaitoyama merged commit 3e9b0f7 into main Mar 6, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants