Skip to content

Commit c0c34ae

Browse files
committed
fix: slack section limiting
Signed-off-by: Uroš Marolt <uros@marolt.me>
1 parent fde44d2 commit c0c34ae

1 file changed

Lines changed: 25 additions & 19 deletions

File tree

services/libs/slack/src/notify.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const log = getServiceLogger()
1010
// Slack message size limit (keeping it conservative at 30KB)
1111
const MAX_MESSAGE_SIZE = 30 * 1024 // 30KB in bytes
1212
const MAX_BLOCKS = 50
13+
const MAX_SECTION_TEXT = 2900 // Slack hard limit is 3000 chars per section block
1314

1415
interface SlackBlock {
1516
type: string
@@ -25,32 +26,37 @@ interface SlackBlock {
2526
}
2627

2728
/**
28-
* Build content blocks from either a simple string or an array of sections
29+
* Build content blocks from either a simple string or an array of sections.
30+
* Splits text that exceeds Slack's 3000 char per-section limit at line boundaries.
2931
*/
3032
function buildContentBlocks(content: string | SlackMessageSection[]): SlackBlock[] {
3133
if (typeof content === 'string') {
32-
// Simple string content - single section
33-
return [
34-
{
35-
type: 'section',
36-
text: {
37-
type: 'mrkdwn',
38-
text: content,
39-
},
40-
},
41-
]
34+
return [{ type: 'section', text: { type: 'mrkdwn', text: content } }]
4235
}
4336

44-
// Multiple sections - create a block for each section
4537
const blocks: SlackBlock[] = []
4638
for (const section of content) {
47-
blocks.push({
48-
type: 'section',
49-
text: {
50-
type: 'mrkdwn',
51-
text: `*${section.title}*\n${section.text}`,
52-
},
53-
})
39+
const fullText = `*${section.title}*\n${section.text}`
40+
if (fullText.length <= MAX_SECTION_TEXT) {
41+
blocks.push({ type: 'section', text: { type: 'mrkdwn', text: fullText } })
42+
continue
43+
}
44+
45+
// Split at line boundaries into multiple blocks
46+
const lines = fullText.split('\n')
47+
let current = ''
48+
for (const line of lines) {
49+
const candidate = current ? `${current}\n${line}` : line
50+
if (candidate.length > MAX_SECTION_TEXT && current) {
51+
blocks.push({ type: 'section', text: { type: 'mrkdwn', text: current } })
52+
current = line
53+
} else {
54+
current = candidate
55+
}
56+
}
57+
if (current) {
58+
blocks.push({ type: 'section', text: { type: 'mrkdwn', text: current } })
59+
}
5460
}
5561
return blocks
5662
}

0 commit comments

Comments
 (0)