From 5ddac589402ee7e3f2c7a2f79f74b36d9c2c57bd Mon Sep 17 00:00:00 2001 From: Yousei Takahashi Date: Thu, 2 Apr 2026 16:22:21 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20file=5Fshare=E7=AD=89=E3=81=AE=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E6=8A=95=E7=A8=BFsubtype=E3=82=92?= =?UTF-8?q?=E8=BB=A2=E9=80=81=E5=AF=BE=E8=B1=A1=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit subtypeの一律除外からホワイトリスト方式に変更し、 file_share, me_message, thread_broadcastを転送対象とした。 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/lib/__tests__/messageFilter.test.ts | 50 +++++++++++++++++++++++-- src/lib/messageFilter.ts | 16 ++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/lib/__tests__/messageFilter.test.ts b/src/lib/__tests__/messageFilter.test.ts index 8ff12f9..f103690 100644 --- a/src/lib/__tests__/messageFilter.test.ts +++ b/src/lib/__tests__/messageFilter.test.ts @@ -30,7 +30,7 @@ describe('isForwardableMessage', () => { assert.equal(isForwardableMessage(message, timesAllChannelId), false); }); - it('subtypeを持つメッセージはfalseを返す (channel_join)', () => { + it('転送対象外のsubtypeはfalseを返す (channel_join)', () => { const message = { type: 'message', subtype: 'channel_join', @@ -41,7 +41,7 @@ describe('isForwardableMessage', () => { assert.equal(isForwardableMessage(message, timesAllChannelId), false); }); - it('subtypeを持つメッセージはfalseを返す (bot_message)', () => { + it('転送対象外のsubtypeはfalseを返す (bot_message)', () => { const message = { type: 'message', subtype: 'bot_message', @@ -52,7 +52,7 @@ describe('isForwardableMessage', () => { assert.equal(isForwardableMessage(message, timesAllChannelId), false); }); - it('subtypeを持つメッセージはfalseを返す (message_changed)', () => { + it('転送対象外のsubtypeはfalseを返す (message_changed)', () => { const message = { type: 'message', subtype: 'message_changed', @@ -63,4 +63,48 @@ describe('isForwardableMessage', () => { } as AllMessageEvents; assert.equal(isForwardableMessage(message, timesAllChannelId), false); }); + + it('file_shareは転送対象としてtrueを返す', () => { + const message = { + type: 'message', + subtype: 'file_share', + channel: 'C_OTHER', + channel_type: 'channel', + ts: '1234567890.123456', + } as AllMessageEvents; + assert.equal(isForwardableMessage(message, timesAllChannelId), true); + }); + + it('me_messageは転送対象としてtrueを返す', () => { + const message = { + type: 'message', + subtype: 'me_message', + channel: 'C_OTHER', + channel_type: 'channel', + ts: '1234567890.123456', + } as AllMessageEvents; + assert.equal(isForwardableMessage(message, timesAllChannelId), true); + }); + + it('thread_broadcastは転送対象としてtrueを返す', () => { + const message = { + type: 'message', + subtype: 'thread_broadcast', + channel: 'C_OTHER', + channel_type: 'channel', + ts: '1234567890.123456', + } as AllMessageEvents; + assert.equal(isForwardableMessage(message, timesAllChannelId), true); + }); + + it('未知のsubtypeは転送対象外としてfalseを返す', () => { + const message = { + type: 'message', + subtype: 'some_unknown_subtype', + channel: 'C_OTHER', + channel_type: 'channel', + ts: '1234567890.123456', + } as unknown as AllMessageEvents; + assert.equal(isForwardableMessage(message, timesAllChannelId), false); + }); }); diff --git a/src/lib/messageFilter.ts b/src/lib/messageFilter.ts index a8b2741..20b15bb 100644 --- a/src/lib/messageFilter.ts +++ b/src/lib/messageFilter.ts @@ -1,15 +1,25 @@ import type { AllMessageEvents } from '@slack/types'; +/** + * 転送対象のsubtype。 + * undefinedも転送対象(通常のメッセージ)。 + * https://api.slack.com/events/message#subtypes + */ +const forwardableSubtypes = new Set([ + undefined, + 'file_share', + 'me_message', + 'thread_broadcast', +]); + /** * 転送対象のメッセージかどうかを判定する。 - * subtypeを持つメッセージ(channel_join, message_changed, bot_message等)は - * すべて転送対象外とする。hidden判定も不要(hidden: trueを持つのはsubtype付きのみ)。 */ export function isForwardableMessage( message: AllMessageEvents, timesAllChannelId: string, ): boolean { - if (message.subtype !== undefined) return false; + if (!forwardableSubtypes.has(message.subtype)) return false; if (message.channel_type !== 'channel') return false; if (message.channel === timesAllChannelId) return false; return true;