diff --git a/app/models/observer/ticket/article/communicate_telegram/background_job.rb b/app/models/observer/ticket/article/communicate_telegram/background_job.rb
index 48791ee50..55d7dd0c0 100644
--- a/app/models/observer/ticket/article/communicate_telegram/background_job.rb
+++ b/app/models/observer/ticket/article/communicate_telegram/background_job.rb
@@ -30,6 +30,7 @@ class Observer::Ticket::Article::CommunicateTelegram::BackgroundJob
api = TelegramAPI.new(channel.options[:api_token])
chat_id = ticket.preferences[:telegram][:chat_id]
result = api.sendMessage(chat_id, article.body)
+ me = api.getMe()
article.attachments.each do |file|
parts = file.filename.split(/^(.*)(\..+?)$/)
t = Tempfile.new([parts[1], parts[2]])
@@ -43,16 +44,32 @@ class Observer::Ticket::Article::CommunicateTelegram::BackgroundJob
return
end
- # fill article with message info
- article.from = "@#{result['from']['username']}"
- article.to = "@#{result['chat']['username']}"
+ Rails.logger.debug "result info: #{result}"
- article.preferences['telegram'] = {
- date: result['date'],
- from_id: result['from']['id'],
- chat_id: result['chat']['id'],
- message_id: result['message_id']
- }
+ # only private, group messages. channel messages do not have from key
+ if result['from'] && result['chat']
+ # fill article with message info
+ article.from = "@#{result['from']['username']}"
+ article.to = "@#{result['chat']['username']}"
+
+ article.preferences['telegram'] = {
+ date: result['date'],
+ from_id: result['from']['id'],
+ chat_id: result['chat']['id'],
+ message_id: result['message_id']
+ }
+ else
+ # fill article with message info (telegram channel)
+ article.from = "@#{me['username']}"
+ article.to = "#{result['chat']['title']} Channel"
+
+ article.preferences['telegram'] = {
+ date: result['date'],
+ from_id: me['id'],
+ chat_id: result['chat']['id'],
+ message_id: result['message_id']
+ }
+ end
# set delivery status
article.preferences['delivery_status_message'] = nil
diff --git a/app/models/transaction/trigger.rb b/app/models/transaction/trigger.rb
index 66e8cb468..e0d96b3fc 100644
--- a/app/models/transaction/trigger.rb
+++ b/app/models/transaction/trigger.rb
@@ -30,9 +30,9 @@ class Transaction::Trigger
return if @item[:object] != 'Ticket'
triggers = if Rails.configuration.db_case_sensitive
- Trigger.where(active: true).order('LOWER(name)')
+ ::Trigger.where(active: true).order('LOWER(name)')
else
- Trigger.where(active: true).order(:name)
+ ::Trigger.where(active: true).order(:name)
end
return if triggers.blank?
diff --git a/lib/telegram.rb b/lib/telegram.rb
index 159e5a66e..017770980 100644
--- a/lib/telegram.rb
+++ b/lib/telegram.rb
@@ -470,7 +470,7 @@ returns
object: 'Ticket::Article',
o_id: article.id,
data: document_result.body,
- filename: params[:message][:voice][:file_path] || 'audio',
+ filename: params[:message][:voice][:file_path] || "audio-#{params[:message][:voice][:file_id]}.ogg",
preferences: {
'Mime-Type' => params[:message][:voice][:mime_type],
},
@@ -489,7 +489,7 @@ returns
if !result.success? || !result.body
raise "Unable for download image from telegram: #{result.code}"
end
- body = "
"
+ body = "
"
article.content_type = 'text/html'
elsif emoji
article.content_type = 'text/plain'
@@ -508,9 +508,9 @@ returns
object: 'Ticket::Article',
o_id: article.id,
data: document_result.body,
- filename: params[:message][:sticker][:file_name] || 'sticker',
+ filename: params[:message][:sticker][:file_name] || "#{params[:message][:sticker][:set_name]}.webp",
preferences: {
- 'Mime-Type' => params[:message][:sticker][:mime_type],
+ 'Mime-Type' => 'image/webp', # mime type is not given from Telegram API but this is actually WebP
},
)
end
@@ -528,8 +528,93 @@ returns
end
def to_group(params, group_id, channel)
+ # begin import
Rails.logger.debug 'import message'
+ # map channel_post params to message
+ if params[:channel_post]
+ return if params[:channel_post][:new_chat_title] # happens when channel title is renamed, we use [:chat][:title] already, safely ignore this.
+ # note: used .blank? which is a rails method. empty? does not work on integers (values like date, width, height) to check.
+ # need delete_if to remove any empty hashes, .compact only removes keys with nil values.
+ params[:message] = {
+ document: {
+ file_name: params.dig(:channel_post, :document, :file_name),
+ mime_type: params.dig(:channel_post, :document, :mime_type),
+ file_id: params.dig(:channel_post, :document, :file_id),
+ file_size: params.dig(:channel_post, :document, :filesize),
+ thumb: {
+ file_id: params.dig(:channel_post, :document, :thumb, :file_id),
+ file_size: params.dig(:channel_post, :document, :thumb, :file_size),
+ width: params.dig(:channel_post, :document, :thumb, :width),
+ height: params.dig(:channel_post, :document, :thumb, :height)
+ }.compact
+ }.delete_if { |_, v| v.blank? },
+ voice: {
+ duration: params.dig(:channel_post, :voice, :duration),
+ mime_type: params.dig(:channel_post, :voice, :mime_type),
+ file_id: params.dig(:channel_post, :voice, :file_id),
+ file_size: params.dig(:channel_post, :voice, :file_size)
+ }.compact,
+ sticker: {
+ width: params.dig(:channel_post, :sticker, :width),
+ height: params.dig(:channel_post, :sticker, :height),
+ emoji: params.dig(:channel_post, :sticker, :emoji),
+ set_name: params.dig(:channel_post, :sticker, :set_name),
+ file_id: params.dig(:channel_post, :sticker, :file_id),
+ file_path: params.dig(:channel_post, :sticker, :file_path),
+ thumb: {
+ file_id: params.dig(:channel_post, :sticker, :thumb, :file_id),
+ file_size: params.dig(:channel_post, :sticker, :thumb, :file_size),
+ width: params.dig(:channel_post, :sticker, :thumb, :width),
+ height: params.dig(:channel_post, :sticker, :thumb, :file_id),
+ file_path: params.dig(:channel_post, :sticker, :thumb, :file_path)
+ }.compact
+ }.delete_if { |_, v| v.blank? },
+ chat: {
+ id: params.dig(:channel_post, :chat, :id),
+ first_name: params.dig(:channel_post, :chat, :title),
+ last_name: 'Channel',
+ username: "channel#{params.dig(:channel_post, :chat, :id)}"
+ },
+ from: {
+ id: params.dig(:channel_post, :chat, :id),
+ first_name: params.dig(:channel_post, :chat, :title),
+ last_name: 'Channel',
+ username: "channel#{params.dig(:channel_post, :chat, :id)}"
+ },
+ caption: (params.dig(:channel_post, :caption) ? params.dig(:channel_post, :caption) : {}),
+ date: params.dig(:channel_post, :date),
+ message_id: params.dig(:channel_post, :message_id),
+ text: params.dig(:channel_post, :text),
+ photo: (params[:channel_post][:photo].map { |photo| { file_id: photo[:file_id], file_size: photo[:file_size], width: photo[:width], height: photo[:height] } } if params.dig(:channel_post, :photo))
+ }.delete_if { |_, v| v.blank? }
+ params.delete(:channel_post) # discard unused :channel_post hash
+ end
+
+ # checks if the channel post is being edited, and map it when it is
+ if params[:edited_channel_post]
+ # updates on telegram can only be on messages, no attachments
+ params[:edited_message] = {
+ chat: {
+ id: params.dig(:edited_channel_post, :chat, :id),
+ first_name: params.dig(:edited_channel_post, :chat, :title),
+ last_name: 'Channel',
+ username: "channel#{params.dig(:edited_channel_post, :chat, :id)}"
+ },
+ from: {
+ id: params.dig(:edited_channel_post, :chat, :id),
+ first_name: params.dig(:edited_channel_post, :chat, :title),
+ last_name: 'Channel',
+ username: "channel#{params.dig(:edited_channel_post, :chat, :id)}"
+ },
+ date: params.dig(:edited_channel_post, :date),
+ edit_date: params.dig(:edited_channel_post, :edit_date),
+ message_id: params.dig(:edited_channel_post, :message_id),
+ text: params.dig(:edited_channel_post, :text)
+ }
+ params.delete(:edited_channel_post) # discard unused :edited_channel_post hash
+ end
+
# prevent multible update
if !params[:edited_message]
return if Ticket::Article.find_by(message_id: Telegram.message_id(params))
diff --git a/test/fixtures/telegram/channel1_message_content1.json b/test/fixtures/telegram/channel1_message_content1.json
new file mode 100644
index 000000000..48b7539d7
--- /dev/null
+++ b/test/fixtures/telegram/channel1_message_content1.json
@@ -0,0 +1,22 @@
+{
+ "update_id":10001,
+ "channel_post":{
+ "date":1441645532,
+ "chat":{
+ "last_name":"Test Lastname",
+ "id":1111111,
+ "type":"channel",
+ "username":"Testusername"
+ },
+ "message_id":1365,
+ "text":"Hello, I need your Help",
+ "bid":"12345678",
+ "callback_token":"AbcDefG",
+ "entities": [
+ {"offset": 0,
+ "length": 6,
+ "type": "bot_command"
+ }
+ ]
+ }
+}
diff --git a/test/fixtures/telegram/channel1_message_content2.json b/test/fixtures/telegram/channel1_message_content2.json
new file mode 100644
index 000000000..bb1cd4dd2
--- /dev/null
+++ b/test/fixtures/telegram/channel1_message_content2.json
@@ -0,0 +1,27 @@
+{
+ "update_id": 30003,
+ "channel_post": {
+ "message_id": 3367,
+ "chat": {
+ "title": "Zammad Bot",
+ "id":1111112,
+ "type": "channel"
+ },
+ "date": 1486036832,
+ "document": {
+ "file_name": "blockposter-162412.pdf",
+ "mime_type": "application/pdf",
+ "thumb": {
+ "file_id": "AAQCABO0I4INAATATQAB5HWPq4XgxQACAg",
+ "file_size": 8752,
+ "width": 200,
+ "height": 200
+ },
+ "caption": "test",
+ "file_id": "BQADAgADDgAD7x6ZSC_-1LMkOEmoAg",
+ "file_size": 3622849,
+ "bid": "435791794",
+ "callback_token": "z5N_uxY_Fut81g"
+ }
+ }
+}
diff --git a/test/fixtures/telegram/channel1_message_content3.json b/test/fixtures/telegram/channel1_message_content3.json
new file mode 100644
index 000000000..22c5a8965
--- /dev/null
+++ b/test/fixtures/telegram/channel1_message_content3.json
@@ -0,0 +1,34 @@
+{
+ "update_id": 30002,
+ "channel_post": {
+ "message_id": 3366,
+ "chat": {
+ "title":"Zammad Bot",
+ "id":1111112,
+ "type": "channel"
+ },
+ "date": 1486036832,
+ "photo": [
+ {
+ "file_id": "ABC-123VabcOcv123w0ABBL_aoY-F849YYABC",
+ "file_size": 1016,
+ "width": 90,
+ "height": 82
+ },
+ {
+ "file_id": "ABC-123VabcOcv123w0ABPlhIiVSfO9TYoABC",
+ "file_size": 7378,
+ "width": 320,
+ "height": 291
+ },
+ {
+ "file_id": "ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC",
+ "file_size": 16433,
+ "width": 720,
+ "height": 654
+ }
+ ],
+ "bid":"435791794",
+ "callback_token":"z5N_uxY_Fut81g"
+ }
+}
diff --git a/test/fixtures/telegram/channel1_message_content4.json b/test/fixtures/telegram/channel1_message_content4.json
new file mode 100644
index 000000000..4b92f9d79
--- /dev/null
+++ b/test/fixtures/telegram/channel1_message_content4.json
@@ -0,0 +1,20 @@
+{
+ "update_id":30005,
+ "channel_post":{
+ "message_id":3368,
+ "chat":{
+ "title": "Zammad Bot",
+ "id":1111112,
+ "type": "channel"
+ },
+ "date":1487119496,
+ "voice":{
+ "duration":1,
+ "mime_type":"audio/ogg",
+ "file_id":"AwADAgADVQADCEIYSZwyOmSZK9iZAg",
+ "file_size":6030
+ },
+ "bid": "435791794",
+ "callback_token":"z5N_uxY_Fut81g"
+ }
+}
diff --git a/test/fixtures/telegram/channel1_message_content5.json b/test/fixtures/telegram/channel1_message_content5.json
new file mode 100644
index 000000000..a5d476009
--- /dev/null
+++ b/test/fixtures/telegram/channel1_message_content5.json
@@ -0,0 +1,30 @@
+{
+ "update_id":40000,
+ "channel_post":{
+ "message_id":273,
+ "chat":{
+ "id":3310000,
+ "type":"channel",
+ "title":"Zammad Bot"
+ },
+ "date":1487161566,
+ "sticker":{
+ "width":512,
+ "height":512,
+ "emoji":"💻",
+ "set_name": "ChristmasGoose",
+ "thumb":{
+ "file_id":"AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC",
+ "file_size":4584,
+ "width":128,
+ "height":128,
+ "file_path": "thumbnails/file57.jpg"
+ },
+ "file_id":"BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C",
+ "file_size":25974,
+ "file_path": "stickers/file_58.webp"
+ },
+ "callback_token":"z5N_uxY_Fut81g",
+ "bid":"435791794"
+ }
+}
diff --git a/test/fixtures/telegram/channel2_message_content1.json b/test/fixtures/telegram/channel2_message_content1.json
new file mode 100644
index 000000000..2a7c8435e
--- /dev/null
+++ b/test/fixtures/telegram/channel2_message_content1.json
@@ -0,0 +1,22 @@
+{
+ "update_id":10001,
+ "edited_channel_post":{
+ "date":1441645532,
+ "chat":{
+ "last_name":"Test Lastname",
+ "id":1111111,
+ "type":"channel",
+ "username":"Testusername"
+ },
+ "message_id":1365,
+ "text":"Hello, I need your Help",
+ "bid":"12345678",
+ "callback_token":"AbcDefG",
+ "entities": [
+ {"offset": 0,
+ "length": 6,
+ "type": "bot_command"
+ }
+ ]
+ }
+}
diff --git a/test/integration/telegram_controller_test.rb b/test/integration/telegram_controller_test.rb
index b9adae6b7..1ab2c9370 100644
--- a/test/integration/telegram_controller_test.rb
+++ b/test/integration/telegram_controller_test.rb
@@ -105,6 +105,28 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest
assert_equal('Hello, I need your Help', ticket.articles.first.body)
assert_equal('text/plain', ticket.articles.first.content_type)
+ # send channel message1
+ post callback_url, params: read_messaage('channel1_message_content1'), headers: @headers
+ assert_response(200)
+ assert_equal(1, Ticket.count)
+ ticket = Ticket.last
+ assert_equal('Hello, I need your Help', ticket.title)
+ assert_equal('new', ticket.state.name)
+ assert_equal(1, ticket.articles.count)
+ assert_equal('Hello, I need your Help', ticket.articles.first.body)
+ assert_equal('text/plain', ticket.articles.first.content_type)
+
+ # edit channel message1
+ post callback_url, params: read_messaage('channel2_message_content1'), headers: @headers
+ assert_response(200)
+ assert_equal(1, Ticket.count)
+ ticket = Ticket.last
+ assert_equal('Hello, I need your Help', ticket.title)
+ assert_equal('new', ticket.state.name)
+ assert_equal(1, ticket.articles.count)
+ assert_equal('Hello, I need your Help', ticket.articles.first.body)
+ assert_equal('text/plain', ticket.articles.first.content_type)
+
# send same message again, ignore it
post callback_url, params: read_messaage('personal1_message_content1'), headers: @headers
assert_response(200)
@@ -193,6 +215,17 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest
assert_match(/
'AAQCABO0I4INAATATQAB5HWPq4XgxQACAg' })
@@ -214,6 +247,18 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest
assert_equal('text/html', ticket.articles.last.content_type)
assert_equal(1, ticket.articles.last.attachments.count)
+ # isend channel message 2
+ post callback_url, params: read_messaage('channel1_message_content2'), headers: @headers
+ assert_response(200)
+ assert_equal(3, Ticket.count)
+ ticket = Ticket.last
+ assert_equal('Can you help me with my feature?', ticket.title)
+ assert_equal('new', ticket.state.name)
+ assert_equal(3, ticket.articles.count)
+ assert_match(/
'AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC' })
@@ -267,6 +323,22 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest
assert_equal('text/html', ticket.articles.last.content_type)
assert_equal(1, ticket.articles.last.attachments.count)
+ # send channel message #5 with sticker
+ post callback_url, params: read_messaage('channel1_message_content5'), headers: @headers
+ assert_response(200)
+ assert_equal(4, Ticket.count)
+ ticket = Ticket.last
+ if Rails.application.config.db_4bytes_utf8
+ assert_equal('💻', ticket.title)
+ else
+ assert_equal('', ticket.title)
+ end
+ assert_equal('new', ticket.state.name)
+ assert_equal(1, ticket.articles.count)
+ assert_match(/
'AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC' })