mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-22 16:35:20 +08:00
fix(pipeline): enforce group response rules after routing
Stop treating an explicit Pipeline route as permission to bypass group response rules. Routed group messages must still satisfy the configured mention or prefix matchers. Preserve the bypass for verified interaction submissions that resume an existing run. Cover ordinary messages, mentions, prefixes, and interaction callbacks with regression tests.
This commit is contained in:
@@ -37,8 +37,10 @@ class GroupRespondRuleCheckStage(stage.PipelineStage):
|
||||
if query.launcher_type.value != 'group': # 只处理群消息
|
||||
return entities.StageProcessResult(result_type=entities.ResultType.CONTINUE, new_query=query)
|
||||
|
||||
# 通过路由规则明确指定的流水线,跳过群响应规则检查
|
||||
if query.variables and query.variables.get('_routed_by_rule', False):
|
||||
# Verified interaction callbacks resume the original run without a new
|
||||
# mention or prefix. Routing ordinary messages only selects a pipeline;
|
||||
# it must not bypass that pipeline's group response rules.
|
||||
if query.variables and query.variables.get('_interaction_submission'):
|
||||
return entities.StageProcessResult(result_type=entities.ResultType.CONTINUE, new_query=query)
|
||||
|
||||
rules = query.pipeline_config['trigger']['group-respond-rules']
|
||||
|
||||
@@ -138,3 +138,42 @@ async def test_atbot_rule_no_match(mock_app, sample_query):
|
||||
result = await atbot_rule.match(str(message_chain), message_chain, {}, sample_query)
|
||||
|
||||
assert result.matching is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize('routed', [False, True])
|
||||
@pytest.mark.parametrize('kind', ['plain', 'mention', 'prefix'])
|
||||
async def test_routed_group_messages_still_obey_response_rules(mock_app, sample_query, routed, kind):
|
||||
resprule, entities, _, _ = get_modules()
|
||||
sample_query.launcher_type = provider_session.LauncherTypes.GROUP
|
||||
sample_query.adapter.bot_account_id = '999'
|
||||
sample_query.variables = {'_routed_by_rule': routed}
|
||||
sample_query.pipeline_config = {
|
||||
'trigger': {'group-respond-rules': {'at': True, 'prefix': ['!bot '], 'regexp': [], 'random': 0}}
|
||||
}
|
||||
parts = [platform_message.Plain(text='!bot hello' if kind == 'prefix' else 'hello')]
|
||||
if kind == 'mention':
|
||||
parts.insert(0, platform_message.At(target='999'))
|
||||
sample_query.message_chain = platform_message.MessageChain(parts)
|
||||
stage = resprule.GroupRespondRuleCheckStage(mock_app)
|
||||
await stage.initialize(sample_query.pipeline_config)
|
||||
|
||||
result = await stage.process(sample_query, 'GroupRespondRuleCheckStage')
|
||||
|
||||
expected = entities.ResultType.INTERRUPT if kind == 'plain' else entities.ResultType.CONTINUE
|
||||
assert result.result_type == expected
|
||||
if kind != 'plain':
|
||||
assert str(sample_query.message_chain) == 'hello'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_interaction_submission_does_not_require_another_mention(mock_app, sample_query):
|
||||
resprule, entities, _, _ = get_modules()
|
||||
sample_query.launcher_type = provider_session.LauncherTypes.GROUP
|
||||
sample_query.variables = {'_routed_by_rule': True, '_interaction_submission': {'interaction_id': 'form-1'}}
|
||||
stage = resprule.GroupRespondRuleCheckStage(mock_app)
|
||||
stage.rule_matchers = []
|
||||
|
||||
result = await stage.process(sample_query, 'GroupRespondRuleCheckStage')
|
||||
|
||||
assert result.result_type == entities.ResultType.CONTINUE
|
||||
|
||||
Reference in New Issue
Block a user