Skip to content

Commit 183fb87

Browse files
committed
Add tests for DingTalk adapter content processing and markdown formatting
- Updated the assertion in `test_dingtalk_completed_input_lines_include_text_and_select_values` to remove unnecessary markdown formatting. - Added new tests to verify that `_dingtalk_clean_form_content` maintains the order of prompts and completed values in various scenarios. - Introduced `test_dingtalk_card_markdown_preserves_internal_line_breaks` to ensure internal line breaks are correctly converted to HTML line breaks.
1 parent 56b3c15 commit 183fb87

4 files changed

Lines changed: 100 additions & 18 deletions

File tree

scripts/build_dingtalk_card_template.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,9 +602,9 @@ def build_editor_data():
602602
'conditionGroup': '',
603603
'children': [
604604
avatar('node_avatar', name='LangBot'),
605+
markdown_block('node_text_content', variable='content'),
605606
input_block('node_input'),
606607
select_block('node_select'),
607-
markdown_block('node_text_content', variable='content'),
608608
button_group('node_btn_group'),
609609
],
610610
}

src/langbot/pkg/platform/sources/dingtalk.py

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,45 @@ def _dingtalk_pending_input_defs(form_data: dict) -> list[dict]:
213213

214214

215215
def _dingtalk_clean_form_content(form_data: dict) -> str:
216-
content = form_data.get('raw_form_content') or form_data.get('form_content') or ''
217-
field_names = {
218-
str(field.get('output_variable_name') or '').strip()
219-
for field in _dingtalk_form_input_defs(form_data)
220-
if str(field.get('output_variable_name') or '').strip()
221-
}
216+
is_field_step = bool(form_data.get('_current_input_field')) and not form_data.get('_action_select_only')
217+
raw_content = str(form_data.get('raw_form_content') or '')
218+
content = raw_content or form_data.get('form_content') or ''
219+
input_defs = _dingtalk_form_input_defs(form_data)
220+
field_names = {_dingtalk_field_name(field) for field in input_defs if _dingtalk_field_name(field)}
221+
222+
if is_field_step and raw_content:
223+
current_field = str(form_data.get('_current_input_field') or '').strip()
224+
current_placeholder = next(
225+
(
226+
match
227+
for match in re.finditer(r'\{\{#\$output\.([^#{}]+)#\}\}', raw_content)
228+
if match.group(1).strip() == current_field
229+
),
230+
None,
231+
)
232+
content = (
233+
raw_content[: current_placeholder.end()] if current_placeholder else form_data.get('form_content') or ''
234+
)
235+
236+
if form_data.get('_action_select_only') or is_field_step:
237+
fields = {_dingtalk_field_name(field): field for field in input_defs if _dingtalk_field_name(field)}
238+
inputs = form_data.get('inputs') or {}
239+
240+
def replace_placeholder(match: re.Match[str]) -> str:
241+
field_name = match.group(1).strip()
242+
field = fields.get(field_name)
243+
if not field or inputs.get(field_name) in (None, '', []):
244+
return ''
245+
lines = _dingtalk_completed_input_lines(
246+
{
247+
'input_defs': [field],
248+
'inputs': {field_name: inputs[field_name]},
249+
}
250+
)
251+
return lines[0] if lines else ''
252+
253+
content = re.sub(r'\{\{#\$output\.([^#{}]+)#\}\}', replace_placeholder, str(content))
254+
222255
kept_lines: list[str] = []
223256
for line in str(content).splitlines():
224257
placeholder = re.fullmatch(r'\s*\{\{#\$output\.([^#{}]+)#\}\}\s*', line)
@@ -228,6 +261,11 @@ def _dingtalk_clean_form_content(form_data: dict) -> str:
228261
return re.sub(r'\n{3,}', '\n\n', '\n'.join(kept_lines).strip())
229262

230263

264+
def _dingtalk_card_markdown(content: str) -> str:
265+
"""Preserve line breaks inside DingTalk card-template markdown slots."""
266+
return '<br>'.join(str(content or '').splitlines())
267+
268+
231269
def _dingtalk_form_input_defs(form_data: dict) -> list[dict]:
232270
return list(form_data.get('all_input_defs') or form_data.get('input_defs') or [])
233271

@@ -261,11 +299,11 @@ def _dingtalk_completed_input_lines(form_data: dict) -> list[str]:
261299
field_type = _dingtalk_field_type(field)
262300
display_value = _dingtalk_display_input_value(field, value)
263301
if field_type == 'select':
264-
lines.append(f'✅ 已选择 {field_name}**{display_value}**')
302+
lines.append(f'✅ 已选择 {field_name}{display_value}')
265303
elif field_type in {'file', 'file-list'}:
266-
lines.append(f'✅ 已上传 {field_name}**{display_value}**')
304+
lines.append(f'✅ 已上传 {field_name}{display_value}')
267305
else:
268-
lines.append(f'✅ 已填写 {field_name}**{display_value}**')
306+
lines.append(f'✅ 已填写 {field_name}{display_value}')
269307
return lines
270308

271309

@@ -915,9 +953,9 @@ async def _paint_form_on_card(
915953
if node_title:
916954
parts.append(f'**{node_title}**')
917955
if form_content:
918-
parts.append(form_content)
956+
parts.append(_dingtalk_card_markdown(form_content))
919957
completed_lines = _dingtalk_completed_input_lines(form_data)
920-
if completed_lines:
958+
if completed_lines and not all(line in form_content for line in completed_lines):
921959
parts.append('<hr>' + '<br>'.join(completed_lines))
922960
input_hint_lines = [] if native_field else _dingtalk_input_hint_lines(form_data)
923961
if input_hint_lines:
@@ -1017,9 +1055,9 @@ async def _send_form_card(
10171055
if node_title:
10181056
parts.append(f'**{node_title}**')
10191057
if form_content:
1020-
parts.append(form_content)
1058+
parts.append(_dingtalk_card_markdown(form_content))
10211059
completed_lines = _dingtalk_completed_input_lines(form_data)
1022-
if completed_lines:
1060+
if completed_lines and not all(line in form_content for line in completed_lines):
10231061
parts.append('<hr>' + '<br>'.join(completed_lines))
10241062
input_hint_lines = [] if native_field else _dingtalk_input_hint_lines(form_data)
10251063
if input_hint_lines:
@@ -1457,14 +1495,14 @@ async def _mark_card_resolved(
14571495
if node_title:
14581496
parts.append(f'**{node_title}**')
14591497
if form_content:
1460-
parts.append(form_content)
1498+
parts.append(_dingtalk_card_markdown(form_content))
14611499
completed_lines = _dingtalk_completed_input_lines(
14621500
{
14631501
'input_defs': input_defs or [],
14641502
'inputs': inputs or {},
14651503
}
14661504
)
1467-
if completed_lines:
1505+
if completed_lines and not all(line in form_content for line in completed_lines):
14681506
parts.append('<hr>' + '<br>'.join(completed_lines))
14691507
parts.append(f'<hr>✅ 已选择:**{action_title}**')
14701508
content = '<br><br>'.join(parts)

0 commit comments

Comments
 (0)