fix to feedback
This commit is contained in:
parent
f66ee8f306
commit
3efadac453
2 changed files with 23 additions and 53 deletions
|
|
@ -207,56 +207,15 @@ func (c *TelegramChannel) Send(ctx context.Context, msg bus.OutboundMessage) err
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek a natural break point (space or newline) to avoid splitting mid-word.
|
// Use the estimated smaller length as a guide for SplitMessage.
|
||||||
splitIdx := smallerLen
|
// SplitMessage will find natural break points (newlines/spaces) and respect code blocks.
|
||||||
foundBreak := false
|
subChunks := channels.SplitMessage(chunk, smallerLen)
|
||||||
|
|
||||||
// Scan backwards from the target point to find the nearest whitespace.
|
// Safety fallback: If SplitMessage failed to shorten the chunk, force a manual hard split.
|
||||||
for i := smallerLen; i >= 0; i-- {
|
|
||||||
if runeChunk[i] == ' ' || runeChunk[i] == '\n' || runeChunk[i] == '\t' || runeChunk[i] == '\r' {
|
|
||||||
splitIdx = i
|
|
||||||
foundBreak = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no space was found behind, scan forward to find the next word boundary.
|
|
||||||
if !foundBreak {
|
|
||||||
for i := smallerLen; i < len(runeChunk); i++ {
|
|
||||||
if runeChunk[i] == ' ' || runeChunk[i] == '\n' || runeChunk[i] == '\t' || runeChunk[i] == '\r' {
|
|
||||||
splitIdx = i
|
|
||||||
foundBreak = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to a hard split if the entire block is monolithic (no spaces found).
|
|
||||||
if !foundBreak {
|
|
||||||
splitIdx = smallerLen
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure we split at a valid index to guarantee forward progress.
|
|
||||||
if splitIdx <= 0 {
|
|
||||||
splitIdx = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to split using the determined index, ensuring code block integrity is maintained.
|
|
||||||
subChunks := channels.SplitMessage(chunk, splitIdx)
|
|
||||||
|
|
||||||
// Safety fallback: If SplitMessage failed to shorten the chunk, force a manual split.
|
|
||||||
if len(subChunks) == 1 && subChunks[0] == chunk {
|
if len(subChunks) == 1 && subChunks[0] == chunk {
|
||||||
part1 := string(runeChunk[:splitIdx])
|
part1 := string(runeChunk[:smallerLen])
|
||||||
subChunks = []string{part1}
|
part2 := string(runeChunk[smallerLen:])
|
||||||
|
subChunks = []string{part1, part2}
|
||||||
nextStart := splitIdx
|
|
||||||
if foundBreak && nextStart < len(runeChunk) {
|
|
||||||
nextStart++
|
|
||||||
}
|
|
||||||
if nextStart < len(runeChunk) {
|
|
||||||
part2 := string(runeChunk[nextStart:])
|
|
||||||
subChunks = append(subChunks, part2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter out empty chunks to avoid sending empty messages to Telegram.
|
// Filter out empty chunks to avoid sending empty messages to Telegram.
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,10 @@ func (s *stubCaller) Call(ctx context.Context, url string, data *ta.RequestData)
|
||||||
type stubConstructor struct{}
|
type stubConstructor struct{}
|
||||||
|
|
||||||
func (s *stubConstructor) JSONRequest(parameters any) (*ta.RequestData, error) {
|
func (s *stubConstructor) JSONRequest(parameters any) (*ta.RequestData, error) {
|
||||||
b, _ := json.Marshal(parameters)
|
b, err := json.Marshal(parameters)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &ta.RequestData{
|
return &ta.RequestData{
|
||||||
ContentType: "application/json",
|
ContentType: "application/json",
|
||||||
BodyRaw: b,
|
BodyRaw: b,
|
||||||
|
|
@ -247,14 +250,21 @@ func TestSend_HTMLOverflow_WordBoundary(t *testing.T) {
|
||||||
}
|
}
|
||||||
ch := newTestChannel(t, caller)
|
ch := newTestChannel(t, caller)
|
||||||
|
|
||||||
// We want to force a split near index ~2600.
|
// We want to force a split near index ~2600 while keeping markdown length <= 4000.
|
||||||
// Prefix of 430 bold units (6 chars each) = 2580 chars.
|
// Prefix of 430 bold units (6 chars each) = 2580 chars.
|
||||||
// Expansion per unit is 3 chars. 2580 + 430*3 = 3870.
|
// Expansion per unit is +3 chars when converted to HTML, so 2580 + 430*3 = 3870.
|
||||||
prefix := strings.Repeat("**a** ", 430)
|
prefix := strings.Repeat("**a** ", 430)
|
||||||
targetWord := "TARGETWORDTHATSTAYSTOGETHER"
|
targetWord := "TARGETWORDTHATSTAYSTOGETHER"
|
||||||
suffix := strings.Repeat(" **b**", 250)
|
// Suffix of 230 bold units (6 chars each) = 1380 chars.
|
||||||
|
// Total markdown length: 2580 (prefix) + 27 (target word) + 1380 (suffix) = 3987 <= 4000.
|
||||||
|
// HTML expansion adds ~3 chars per bold unit: (430 + 230)*3 = 1980 extra chars,
|
||||||
|
// so total HTML length comfortably exceeds 4096.
|
||||||
|
suffix := strings.Repeat(" **b**", 230)
|
||||||
content := prefix + targetWord + suffix
|
content := prefix + targetWord + suffix
|
||||||
|
|
||||||
|
// Ensure the test content matches the intended boundary conditions.
|
||||||
|
assert.LessOrEqual(t, len([]rune(content)), 4000, "markdown content must not exceed chunk size for this test")
|
||||||
|
|
||||||
err := ch.Send(context.Background(), bus.OutboundMessage{
|
err := ch.Send(context.Background(), bus.OutboundMessage{
|
||||||
ChatID: "123456",
|
ChatID: "123456",
|
||||||
Content: content,
|
Content: content,
|
||||||
|
|
@ -265,7 +275,8 @@ func TestSend_HTMLOverflow_WordBoundary(t *testing.T) {
|
||||||
foundFullWord := false
|
foundFullWord := false
|
||||||
for i, call := range caller.calls {
|
for i, call := range caller.calls {
|
||||||
var params map[string]any
|
var params map[string]any
|
||||||
_ = json.Unmarshal(call.Data.BodyRaw, ¶ms)
|
err := json.Unmarshal(call.Data.BodyRaw, ¶ms)
|
||||||
|
require.NoError(t, err)
|
||||||
text, _ := params["text"].(string)
|
text, _ := params["text"].(string)
|
||||||
|
|
||||||
hasWord := strings.Contains(text, targetWord)
|
hasWord := strings.Contains(text, targetWord)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue