From 05eb65708f4d027484747d6ef9dc4457ec206f26 Mon Sep 17 00:00:00 2001 From: taki73 Date: Fri, 10 Apr 2026 17:01:59 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20++/--/=3D=3D=20=E3=81=AE=E5=BE=8C?= =?UTF-8?q?=E3=81=AB=E6=96=87=E5=AD=97=E5=88=97=E3=81=8C=E7=B6=9A=E3=81=8F?= =?UTF-8?q?=E5=A0=B4=E5=90=88=E3=81=AF=E5=8F=8D=E5=BF=9C=E3=81=97=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit オペレーターの後に別の単語が続く場合(例: `:neko: -- Settings`)は 意図的な操作ではなく文章の一部である可能性が高いため、 ++/--/== の直後がスペースのみ・行末・改行の場合のみ反応するよう正規表現を修正した。 Co-Authored-By: Claude Sonnet 4.6 --- bot/bot.go | 4 ++-- bot/bot_test.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/bot/bot.go b/bot/bot.go index 6046130..43a2685 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -84,9 +84,9 @@ const ( // Pre-compiled regexes for detecting point operations with targets var ( // User mention pattern: <@U123456> ++ (captures user ID and operator) - userOperationPattern = regexp.MustCompile(`<@([A-Z0-9]+)>[  ]*(\+\+|-{2}|={2})`) + userOperationPattern = regexp.MustCompile(`<@([A-Z0-9]+)>[  ]*(\+\+|-{2}|={2})[  ]*($|\n)`) // Emoji pattern: :emoji: ++ (captures emoji name and operator) - emojiOperationPattern = regexp.MustCompile(`:([a-zA-Z0-9_+-]+):[  ]*(\+\+|-{2}|={2})`) + emojiOperationPattern = regexp.MustCompile(`:([a-zA-Z0-9_+-]+):[  ]*(\+\+|-{2}|={2})[  ]*($|\n)`) ) // parseOperator converts an operator string to a PointOperation diff --git a/bot/bot_test.go b/bot/bot_test.go index 5e87772..e422621 100644 --- a/bot/bot_test.go +++ b/bot/bot_test.go @@ -383,6 +383,70 @@ func TestDetectOperationAndTarget(t *testing.T) { wantTarget: "U123456", wantIsUser: true, }, + // Operator must be at end of line or followed by newline + { + name: "Emoji operator followed by text", + text: ":nya-nya: -- Settings", + wantOp: NoOperation, + wantTarget: "", + wantIsUser: false, + }, + { + name: "Emoji operator followed by text (plus)", + text: ":neko: ++ foo", + wantOp: NoOperation, + wantTarget: "", + wantIsUser: false, + }, + { + name: "Emoji operator followed by text (equals)", + text: ":neko: == foo", + wantOp: NoOperation, + wantTarget: "", + wantIsUser: false, + }, + { + name: "Emoji operator followed by trailing spaces", + text: ":neko: ++ ", + wantOp: PointUp, + wantTarget: "neko", + wantIsUser: false, + }, + { + name: "Emoji operator followed by newline", + text: ":neko: ++\n", + wantOp: PointUp, + wantTarget: "neko", + wantIsUser: false, + }, + { + name: "Emoji operator followed by newline and text", + text: ":neko: ++\nsome text", + wantOp: PointUp, + wantTarget: "neko", + wantIsUser: false, + }, + { + name: "User operator followed by text", + text: "<@U123456> ++ foo", + wantOp: NoOperation, + wantTarget: "", + wantIsUser: false, + }, + { + name: "User operator followed by trailing spaces", + text: "<@U123456> ++ ", + wantOp: PointUp, + wantTarget: "U123456", + wantIsUser: true, + }, + { + name: "User operator followed by newline and text", + text: "<@U123456> ++\nsome text", + wantOp: PointUp, + wantTarget: "U123456", + wantIsUser: true, + }, } for _, tt := range tests {