mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-31 19:17:48 +00:00
feat: Use Telegram HTML Parsemode (#8731)
- this ensures that the markdown formatted messages from the Chatwoot dashboard will render consistently in telegram UI for the supported types like bold, italics, links etc
This commit is contained in:
@@ -149,24 +149,32 @@ class Channel::Telegram < ApplicationRecord
|
||||
})
|
||||
end
|
||||
|
||||
def convert_markdown_to_telegram(text)
|
||||
## supported characters : https://core.telegram.org/bots/api#markdown-style
|
||||
## To implement MarkdownV2, we will need to do a lot of escaping
|
||||
def convert_markdown_to_telegram_html(text)
|
||||
# ref: https://core.telegram.org/bots/api#html-style
|
||||
|
||||
# Convert bold - double asterisks to single asterisk in Telegram
|
||||
# Chatwoot uses double asterisks for bold, while telegram used single asterisk
|
||||
text.gsub!(/\*\*(.*?)\*\*/, '*\1*')
|
||||
text
|
||||
# escape html tags in text. We are subbing \n to <br> since commonmark will strip exta '\n'
|
||||
text = CGI.escapeHTML(text.gsub("\n", '<br>'))
|
||||
|
||||
# convert markdown to html
|
||||
html = CommonMarker.render_html(text).strip
|
||||
|
||||
# remove all html tags except b, strong, i, em, u, ins, s, strike, del, a, code, pre, blockquote
|
||||
stripped_html = Rails::HTML5::SafeListSanitizer.new.sanitize(html, tags: %w[b strong i em u ins s strike del a code pre blockquote],
|
||||
attributes: %w[href])
|
||||
|
||||
# converted escaped br tags to \n
|
||||
stripped_html.gsub('<br>', "\n")
|
||||
end
|
||||
|
||||
def message_request(chat_id, text, reply_markup = nil, reply_to_message_id = nil)
|
||||
text_to_md = convert_markdown_to_telegram(text)
|
||||
text_payload = convert_markdown_to_telegram_html(text)
|
||||
|
||||
HTTParty.post("#{telegram_api_url}/sendMessage",
|
||||
body: {
|
||||
chat_id: chat_id,
|
||||
text: text_to_md,
|
||||
text: text_payload,
|
||||
reply_markup: reply_markup,
|
||||
parse_mode: 'Markdown',
|
||||
parse_mode: 'HTML',
|
||||
reply_to_message_id: reply_to_message_id
|
||||
})
|
||||
end
|
||||
|
||||
@@ -3,6 +3,58 @@ require 'rails_helper'
|
||||
RSpec.describe Channel::Telegram do
|
||||
let(:telegram_channel) { create(:channel_telegram) }
|
||||
|
||||
describe '#convert_markdown_to_telegram_html' do
|
||||
subject { telegram_channel.send(:convert_markdown_to_telegram_html, text) }
|
||||
|
||||
context 'when text contains multiple newline characters' do
|
||||
let(:text) { "Line one\nLine two\n\nLine four" }
|
||||
|
||||
it 'preserves multiple newline characters' do
|
||||
expect(subject).to eq("Line one\nLine two\n\nLine four")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when text contains broken markdown' do
|
||||
let(:text) { 'This is a **broken markdown with <b>HTML</b> tags.' }
|
||||
|
||||
it 'does not break and properly converts to Telegram HTML format and escapes html tags' do
|
||||
expect(subject).to eq('This is a **broken markdown with <b>HTML</b> tags.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when text contains markdown and HTML elements' do
|
||||
let(:text) { "Hello *world*! This is <b>bold</b> and this is <i>italic</i>.\nThis is a new line." }
|
||||
|
||||
it 'converts markdown to Telegram HTML format and escapes other html' do
|
||||
expect(subject).to eq("Hello <em>world</em>! This is <b>bold</b> and this is <i>italic</i>.\nThis is a new line.")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when text contains unsupported HTML tags' do
|
||||
let(:text) { 'This is a <span>test</span> with unsupported tags.' }
|
||||
|
||||
it 'removes unsupported HTML tags' do
|
||||
expect(subject).to eq('This is a <span>test</span> with unsupported tags.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when text contains special characters' do
|
||||
let(:text) { 'Special characters: & < >' }
|
||||
|
||||
it 'escapes special characters' do
|
||||
expect(subject).to eq('Special characters: & < >')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when text contains markdown links' do
|
||||
let(:text) { 'Check this [link](http://example.com) out!' }
|
||||
|
||||
it 'converts markdown links to Telegram HTML format' do
|
||||
expect(subject).to eq('Check this <a href="http://example.com">link</a> out!')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a valid message and empty attachments' do
|
||||
it 'send message' do
|
||||
message = create(:message, message_type: :outgoing, content: 'test',
|
||||
@@ -10,7 +62,7 @@ RSpec.describe Channel::Telegram do
|
||||
|
||||
stub_request(:post, "https://api.telegram.org/bot#{telegram_channel.bot_token}/sendMessage")
|
||||
.with(
|
||||
body: 'chat_id=123&text=test&reply_markup=&parse_mode=Markdown&reply_to_message_id='
|
||||
body: 'chat_id=123&text=test&reply_markup=&parse_mode=HTML&reply_to_message_id='
|
||||
)
|
||||
.to_return(
|
||||
status: 200,
|
||||
@@ -21,13 +73,15 @@ RSpec.describe Channel::Telegram do
|
||||
expect(telegram_channel.send_message_on_telegram(message)).to eq('telegram_123')
|
||||
end
|
||||
|
||||
it 'send message with markdown converted to telegram markdown' do
|
||||
it 'send message with markdown converted to telegram HTML' do
|
||||
message = create(:message, message_type: :outgoing, content: '**test** *test* ~test~',
|
||||
conversation: create(:conversation, inbox: telegram_channel.inbox, additional_attributes: { 'chat_id' => '123' }))
|
||||
|
||||
stub_request(:post, "https://api.telegram.org/bot#{telegram_channel.bot_token}/sendMessage")
|
||||
.with(
|
||||
body: "chat_id=123&text=#{ERB::Util.url_encode('*test* *test* ~test~')}&reply_markup=&parse_mode=Markdown&reply_to_message_id="
|
||||
body: "chat_id=123&text=#{
|
||||
ERB::Util.url_encode('<strong>test</strong> <em>test</em> ~test~')
|
||||
}&reply_markup=&parse_mode=HTML&reply_to_message_id="
|
||||
)
|
||||
.to_return(
|
||||
status: 200,
|
||||
@@ -49,7 +103,7 @@ RSpec.describe Channel::Telegram do
|
||||
.with(
|
||||
body: 'chat_id=123&text=test' \
|
||||
'&reply_markup=%7B%22one_time_keyboard%22%3Atrue%2C%22inline_keyboard%22%3A%5B%5B%7B%22text%22%3A%22test%22%2C%22' \
|
||||
'callback_data%22%3A%22test%22%7D%5D%5D%7D&parse_mode=Markdown&reply_to_message_id='
|
||||
'callback_data%22%3A%22test%22%7D%5D%5D%7D&parse_mode=HTML&reply_to_message_id='
|
||||
)
|
||||
.to_return(
|
||||
status: 200,
|
||||
@@ -66,7 +120,7 @@ RSpec.describe Channel::Telegram do
|
||||
|
||||
stub_request(:post, "https://api.telegram.org/bot#{telegram_channel.bot_token}/sendMessage")
|
||||
.with(
|
||||
body: 'chat_id=123&text=test&reply_markup=&parse_mode=Markdown&reply_to_message_id='
|
||||
body: 'chat_id=123&text=test&reply_markup=&parse_mode=HTML&reply_to_message_id='
|
||||
)
|
||||
.to_return(
|
||||
status: 403,
|
||||
|
||||
Reference in New Issue
Block a user