Telegram refactoring:

- Fixes #2289 - Added Telegram video support.
- Improved error handling via raise Exceptions.
- Removed unused methods.
- Fixed typos.
- Improved messages to client - return status: :ok even if the message could not be processed. This stops the Webhook loop for these message.
This commit is contained in:
Denny Korsukéwitz 2019-10-21 16:50:45 +02:00 committed by Thorsten Eckel
parent 8d16bcbfdd
commit 7c935655d5
43 changed files with 1034 additions and 1063 deletions

View file

@ -67,7 +67,11 @@ class ChannelsTelegramController < ApplicationController
end
telegram = Telegram.new(channel.options[:api_token])
telegram.to_group(params, channel.group_id, channel)
begin
telegram.to_group(params, channel.group_id, channel)
rescue Exceptions::UnprocessableEntity => e
Rails.logger.error e.message
end
render json: {}, status: :ok
end

View file

@ -17,7 +17,7 @@ check token and return bot attributes of token
begin
bot = api.getMe()
rescue
raise 'invalid api token'
raise Exceptions::UnprocessableEntity, 'invalid api token'
end
bot
end
@ -36,14 +36,14 @@ returns
def self.set_webhook(token, callback_url)
if callback_url.match?(%r{^http://}i)
raise 'webhook url need to start with https://, you use http://'
raise Exceptions::UnprocessableEntity, 'webhook url need to start with https://, you use http://'
end
api = TelegramAPI.new(token)
begin
api.setWebhook(callback_url)
rescue
raise 'Unable to set webhook at Telegram, seems to be a invalid url.'
raise Exceptions::UnprocessableEntity, 'Unable to set webhook at Telegram, seems to be a invalid url.'
end
true
end
@ -67,17 +67,17 @@ returns
if !channel
if Telegram.bot_duplicate?(bot['id'])
raise 'Bot already exists!'
raise Exceptions::UnprocessableEntity, 'Bot already exists!'
end
end
if params[:group_id].blank?
raise 'Group needed!'
raise Exceptions::UnprocessableEntity, 'Group needed!'
end
group = Group.find_by(id: params[:group_id])
if !group
raise 'Group invalid!'
raise Exceptions::UnprocessableEntity, 'Group invalid!'
end
# generate random callback token
@ -213,13 +213,22 @@ returns
=begin
client.message(chat_id, 'some message')
client.message(chat_id, 'some message', language_code)
=end
def message(chat_id, message)
def message(chat_id, message, language_code = 'en')
return if Rails.env.test?
locale = Locale.find_by(alias: language_code)
if !locale
locale = Locale.where('locale LIKE :prefix', prefix: "#{language_code}%").first
end
if locale
message = Translation.translate(locale[:locale], message)
end
@api.sendMessage(chat_id, message)
end
@ -390,14 +399,15 @@ returns
)
end
# add article
# add photo
if params[:message][:photo]
# find photo with best resolution for us
photo = nil
max_width = 650 * 2
last_width = 0
photo = nil
max_width = 650 * 2
last_width = 0
last_height = 0
params[:message][:photo].each do |file|
if !photo
photo = file
@ -406,8 +416,8 @@ returns
end
next if file['width'].to_i >= max_width || file['width'].to_i <= last_width
photo = file
last_width = file['width'].to_i
photo = file
last_width = file['width'].to_i
last_height = file['height'].to_i
end
if last_width > 650
@ -415,40 +425,40 @@ returns
last_height = (last_height / 2).to_i
end
# download image
result = download_file(photo['file_id'])
if !result.success? || !result.body
raise "Unable for download image from telegram: #{result.code}"
end
# download photo
photo_result = get_file(params, photo)
body = "<img style=\"width:#{last_width}px;height:#{last_height}px;\" src=\"data:image/png;base64,#{Base64.strict_encode64(photo_result.body)}\">"
body = "<img style=\"width:#{last_width}px;height:#{last_height}px;\" src=\"data:image/png;base64,#{Base64.strict_encode64(result.body)}\">"
if params[:message][:caption]
body += "<br>#{params[:message][:caption].text2html}"
end
article.content_type = 'text/html'
article.body = body
article.body = body
article.save!
return article
end
# add document
if params[:message][:document]
thumb = params[:message][:document][:thumb]
body = '&nbsp;'
if thumb
width = thumb[:width]
height = thumb[:height]
result = download_file(thumb['file_id'])
if !result.success? || !result.body
raise "Unable for download image from telegram: #{result.code}"
end
body = "<img style=\"width:#{width}px;height:#{height}px;\" src=\"data:image/png;base64,#{Base64.strict_encode64(result.body)}\">"
document = params[:message][:document]
thumb = params[:message][:document][:thumb]
body = '&nbsp;'
if thumb
width = thumb[:width]
height = thumb[:height]
thumb_result = get_file(params, thumb)
body = "<img style=\"width:#{width}px;height:#{height}px;\" src=\"data:image/png;base64,#{Base64.strict_encode64(thumb_result.body)}\">"
end
document_result = download_file(params[:message][:document][:file_id])
if params[:message][:caption]
body += "<br>#{params[:message][:caption].text2html}"
end
document_result = get_file(params, document)
article.content_type = 'text/html'
article.body = body
article.body = body
article.save!
Store.remove(
object: 'Ticket::Article',
o_id: article.id,
@ -457,24 +467,70 @@ returns
object: 'Ticket::Article',
o_id: article.id,
data: document_result.body,
filename: params[:message][:document][:file_name],
filename: document[:file_name],
preferences: {
'Mime-Type' => params[:message][:document][:mime_type],
'Mime-Type' => document[:mime_type],
},
)
return article
end
# voice
if params[:message][:voice]
# add video
if params[:message][:video]
video = params[:message][:video]
thumb = params[:message][:video][:thumb]
body = '&nbsp;'
if thumb
width = thumb[:width]
height = thumb[:height]
thumb_result = get_file(params, thumb)
body = "<img style=\"width:#{width}px;height:#{height}px;\" src=\"data:image/png;base64,#{Base64.strict_encode64(thumb_result.body)}\">"
end
if params[:message][:caption]
body += "<br>#{params[:message][:caption].text2html}"
end
video_result = get_file(params, video)
article.content_type = 'text/html'
article.body = body
article.save!
Store.remove(
object: 'Ticket::Article',
o_id: article.id,
)
# get video type
type = video[:mime_type].gsub(%r{(.+/)}, '')
Store.add(
object: 'Ticket::Article',
o_id: article.id,
data: video_result.body,
filename: video[:file_name] || "video-#{video[:file_id]}.#{type}",
preferences: {
'Mime-Type' => video[:mime_type],
},
)
return article
end
# add voice
if params[:message][:voice]
voice = params[:message][:voice]
body = '&nbsp;'
if params[:message][:caption]
body = "<br>#{params[:message][:caption].text2html}"
end
document_result = download_file(params[:message][:voice][:file_id])
document_result = get_file(params, voice)
article.content_type = 'text/html'
article.body = body
article.body = body
article.save!
Store.remove(
object: 'Ticket::Article',
o_id: article.id,
@ -483,37 +539,39 @@ returns
object: 'Ticket::Article',
o_id: article.id,
data: document_result.body,
filename: params[:message][:voice][:file_path] || "audio-#{params[:message][:voice][:file_id]}.ogg",
filename: voice[:file_path] || "audio-#{voice[:file_id]}.ogg",
preferences: {
'Mime-Type' => params[:message][:voice][:mime_type],
'Mime-Type' => voice[:mime_type],
},
)
return article
end
# add sticker
if params[:message][:sticker]
emoji = params[:message][:sticker][:emoji]
thumb = params[:message][:sticker][:thumb]
body = '&nbsp;'
if thumb
width = thumb[:width]
height = thumb[:height]
result = download_file(thumb['file_id'])
if !result.success? || !result.body
raise "Unable for download image from telegram: #{result.code}"
end
body = "<img style=\"width:#{width}px;height:#{height}px;\" src=\"data:image/webp;base64,#{Base64.strict_encode64(result.body)}\">"
sticker = params[:message][:sticker]
emoji = sticker[:emoji]
thumb = sticker[:thumb]
body = '&nbsp;'
if thumb
width = thumb[:width]
height = thumb[:height]
thumb_result = get_file(params, thumb)
body = "<img style=\"width:#{width}px;height:#{height}px;\" src=\"data:image/webp;base64,#{Base64.strict_encode64(thumb_result.body)}\">"
article.content_type = 'text/html'
elsif emoji
article.content_type = 'text/plain'
body = emoji
end
article.body = body
article.save!
if params[:message][:sticker][:file_id]
document_result = download_file(params[:message][:sticker][:file_id])
if sticker[:file_id]
document_result = get_file(params, sticker)
Store.remove(
object: 'Ticket::Article',
o_id: article.id,
@ -522,7 +580,7 @@ returns
object: 'Ticket::Article',
o_id: article.id,
data: document_result.body,
filename: params[:message][:sticker][:file_name] || "#{params[:message][:sticker][:set_name]}.webp",
filename: sticker[:file_name] || "#{sticker[:set_name]}.webp",
preferences: {
'Mime-Type' => 'image/webp', # mime type is not given from Telegram API but this is actually WebP
},
@ -531,14 +589,14 @@ returns
return article
end
# text
# add text
if params[:message][:text]
article.content_type = 'text/plain'
article.body = params[:message][:text]
article.save!
return article
end
raise 'invalid action'
raise Exceptions::UnprocessableEntity, 'invalid telegram message'
end
def to_group(params, group_id, channel)
@ -556,7 +614,7 @@ returns
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),
file_size: params.dig(:channel_post, :document, :file_size),
thumb: {
file_id: params.dig(:channel_post, :document, :thumb, :file_id),
file_size: params.dig(:channel_post, :document, :thumb, :file_size),
@ -564,6 +622,20 @@ returns
height: params.dig(:channel_post, :document, :thumb, :height)
}.compact
}.delete_if { |_, v| v.blank? },
video: {
duration: params.dig(:channel_post, :video, :duration),
width: params.dig(:channel_post, :video, :width),
height: params.dig(:channel_post, :video, :height),
mime_type: params.dig(:channel_post, :video, :mime_type),
file_id: params.dig(:channel_post, :video, :file_id),
file_size: params.dig(:channel_post, :video, :file_size),
thumb: {
file_id: params.dig(:channel_post, :video, :thumb, :file_id),
file_size: params.dig(:channel_post, :video, :thumb, :file_size),
width: params.dig(:channel_post, :video, :thumb, :width),
height: params.dig(:channel_post, :video, :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),
@ -577,11 +649,12 @@ returns
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),
file_size: params.dig(:channel_post, :sticker, :file_size),
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),
height: params.dig(:channel_post, :sticker, :thumb, :height),
file_path: params.dig(:channel_post, :sticker, :thumb, :file_path)
}.compact
}.delete_if { |_, v| v.blank? },
@ -649,7 +722,7 @@ returns
# send welcome message and don't create ticket
text = params[:message][:text]
if text.present? && text =~ %r{^/start}
message(params[:message][:chat][:id], channel.options[:welcome] || 'You are welcome! Just ask me something!')
message(params[:message][:chat][:id], channel.options[:welcome] || 'You are welcome! Just ask me something!', params[:message][:from][:language_code])
return
# find ticket and close it
@ -660,12 +733,15 @@ returns
state_ids = Ticket::State.where(name: %w[closed merged removed]).pluck(:id)
possible_tickets = Ticket.where(customer_id: user.id).where.not(state_id: state_ids).order(:updated_at)
ticket = possible_tickets.find_each.find { |possible_ticket| possible_ticket.preferences[:channel_id] == channel.id }
ticket.state = Ticket::State.find_by(name: 'closed')
return if !ticket
ticket.state = Ticket::State.find_by(name: 'closed')
ticket.save!
return if !channel.options[:goodbye]
message(params[:message][:chat][:id], channel.options[:goodbye])
message(params[:message][:chat][:id], channel.options[:goodbye], params[:message][:from][:language_code])
return
end
@ -693,23 +769,25 @@ returns
message
end
def get_state(channel, telegram_update, ticket = nil)
message = telegram_update['message']
message_user = user(message)
def get_file(params, file)
# no changes in post is from page user it self
if channel.options[:bot][:id].to_s == message_user[:id].to_s
if !ticket
return Ticket::State.find_by(name: 'closed') if !ticket
end
return ticket.state
# telegram bot files are limited up to 20MB
# https://core.telegram.org/bots/api#getfile
if !validate_file_size(file)
message_text = 'Telegram file is to big. (Maximum 20mb)'
message(params[:message][:chat][:id], "Sorry, we could not handle your message. #{message_text}", params[:message][:from][:language_code])
raise Exceptions::UnprocessableEntity, message_text
end
state = Ticket::State.find_by(default_create: true)
return state if !ticket
return ticket.state if ticket.state.id == state.id
result = download_file(file[:file_id])
Ticket::State.find_by(default_follow_up: true)
if !validate_download(result)
message_text = 'Unable to get you file from bot.'
message(params[:message][:chat][:id], "Sorry, we could not handle your message. #{message_text}", params[:message][:from][:language_code])
raise Exceptions::UnprocessableEntity, message_text
end
result
end
def download_file(file_id)
@ -725,4 +803,18 @@ returns
)
end
def validate_file_size(file)
Rails.logger.error 'validate_file_size'
Rails.logger.error file[:file_size]
return false if file[:file_size] >= 20.megabytes
true
end
def validate_download(result)
return false if !result.success? || !result.body
true
end
end

View file

@ -1,454 +1,424 @@
require 'rails_helper'
RSpec.describe 'Telegram', type: :request do
RSpec.describe 'Telegram Webhook Integration', type: :request do
let!(:token) { 'valid_token' }
let!(:token2) { 'valid_token2' }
let!(:bot_id) { 123_456_789 }
let!(:bot_id2) { 987_654_321 }
let!(:group_id) { Group.find_by(name: 'Users').id }
let!(:group_id2) { create(:group).id }
describe 'request handling' do
it 'does basic call' do
Ticket.destroy_all
describe 'check_token' do
it 'invalid token' do
stub_request(:post, 'https://api.telegram.org/botinvalid_token/getMe')
.to_return(status: 404, body: '{"ok":false,"error_code":404,"description":"Not Found"}', headers: {})
# configure telegram channel
token = 'valid_token'
bot_id = 123_456_789
group_id = Group.find_by(name: 'Users').id
UserInfo.current_user_id = 1
Channel.where(area: 'Telegram::Bot').destroy_all
# try with invalid token
stub_request(:post, 'https://api.telegram.org/botnot_existing/getMe')
.to_return(status: 404, body: '{"ok":false,"error_code":404,"description":"Not Found"}', headers: {})
expect do
Telegram.check_token('not_existing')
end.to raise_error(RuntimeError)
# try valid token
stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
bot = Telegram.check_token(token)
expect(bot['id']).to eq(bot_id)
stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
Setting.set('http_type', 'http')
expect do
Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
end.to raise_error(RuntimeError)
# try invalid port
stub_request(:post, "https://api.telegram.org:443/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
.with(body: { 'url' => "https://somehost.example.com:12345/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
.to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443"}', headers: {})
Setting.set('http_type', 'https')
Setting.set('fqdn', 'somehost.example.com:12345')
expect do
Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
end.to raise_error(RuntimeError)
# try invalid host
stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
.with(body: { 'url' => "https://somehost.example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
.to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: getaddrinfo: Name or service not known"}', headers: {})
Setting.set('fqdn', 'somehost.example.com')
expect do
Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
end.to raise_error(RuntimeError)
# valid token, host and port
stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
.with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
.to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
Setting.set('fqdn', 'example.com')
channel = Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
UserInfo.current_user_id = nil
# start communication #1
post '/api/v1/channels/telegram_webhook', params: read_message('personal1_message_start'), as: :json
expect(response).to have_http_status(:not_found)
post '/api/v1/channels_telegram_webhook/not_existing', params: read_message('personal1_message_start'), as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response['error']).to eq('bot id is missing')
callback_url = "/api/v1/channels_telegram_webhook/not_existing?bid=#{channel.options[:bot][:id]}"
post callback_url, params: read_message('personal1_message_start'), as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response['error']).to eq('invalid callback token')
callback_url = "/api/v1/channels_telegram_webhook/#{channel.options[:callback_token]}?bid=#{channel.options[:bot][:id]}"
post callback_url, params: read_message('personal1_message_start'), as: :json
expect(response).to have_http_status(:ok)
# send message1
post callback_url, params: read_message('personal1_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(1)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
# send channel message1
post callback_url, params: read_message('channel1_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(1)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
# edit channel message1
post callback_url, params: read_message('channel2_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(1)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
# send same message again, ignore it
post callback_url, params: read_message('personal1_message_content1'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
# send message2
post callback_url, params: read_message('personal1_message_content2'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(2)
expect(ticket.articles.last.body).to eq('Hello, I need your Help 2')
expect(ticket.articles.last.content_type).to eq('text/plain')
# send end message
post callback_url, params: read_message('personal1_message_end'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('closed')
expect(ticket.articles.count).to eq(2)
expect(ticket.articles.last.body).to eq('Hello, I need your Help 2')
expect(ticket.articles.last.content_type).to eq('text/plain')
# start communication #2
post callback_url, params: read_message('personal2_message_start'), as: :json
expect(response).to have_http_status(:ok)
# send message1
post callback_url, params: read_message('personal2_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(2)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Can you help me with my feature?')
expect(ticket.articles.first.content_type).to eq('text/plain')
# send message2
post callback_url, params: read_message('personal2_message_content2'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(2)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(2)
expect(ticket.articles.last.body).to eq('Yes of course! <b>lalal</b>')
expect(ticket.articles.last.content_type).to eq('text/plain')
# start communication #3
post callback_url, params: read_message('personal3_message_start'), as: :json
expect(response).to have_http_status(:ok)
# send message1
post callback_url, params: read_message('personal3_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to eq('Can you help me with my feature?')
expect(ticket.articles.last.content_type).to eq('text/plain')
# send message2
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => 'ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC' })
.to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC","file_path":"abc123"}}', headers: {})
stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123")
.to_return(status: 200, body: 'ABC1', headers: {})
post callback_url, params: read_message('personal3_message_content2'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(2)
expect(ticket.articles.last.body).to match(/<img style="width:360px;height:327px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
# send channel message 3
post callback_url, params: read_message('channel1_message_content3'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(2)
expect(ticket.articles.last.body).to match(/<img style="width:360px;height:327px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
# send message3
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => 'AAQCABO0I4INAATATQAB5HWPq4XgxQACAg' })
.to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQCABO0I4INAATATQAB5HWPq4XgxQACAg","file_path":"abc123"}}', headers: {})
stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123")
.to_return(status: 200, body: 'ABC2', headers: {})
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => 'BQADAgADDgAD7x6ZSC_-1LMkOEmoAg' })
.to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAgADDgAD7x6ZSC_-1LMkOEmoAg","file_path":"abc123"}}', headers: {})
post callback_url, params: read_message('personal3_message_content3'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(3)
expect(ticket.articles.last.body).to match(/<img style="width:200px;height:200px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
# send channel message 2
post callback_url, params: read_message('channel1_message_content2'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(3)
expect(ticket.articles.last.body).to match(/<img style="width:200px;height:200px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
# update message1
post callback_url, params: read_message('personal3_message_content4'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(3)
expect(ticket.articles.last.body).to match(/<img style="width:200px;height:200px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(ticket.articles.first.body).to eq('UPDATE: 1231444')
expect(ticket.articles.first.content_type).to eq('text/plain')
# send voice5
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => 'AwADAgADVQADCEIYSZwyOmSZK9iZAg' })
.to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AwADAgADVQADCEIYSZwyOmSZK9iZAg","file_path":"abc123"}}', headers: {})
post callback_url, params: read_message('personal3_message_content5'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(4)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
# send channel message 4 with voice
post callback_url, params: read_message('channel1_message_content4'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(3)
ticket = Ticket.last
expect(ticket.title).to eq('Can you help me with my feature?')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(4)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
# start communication #4 - with sticker
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => 'AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC' })
.to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC","file_path":"abc123"}}', headers: {})
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => 'BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C' })
.to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C","file_path":"abc123"}}', headers: {})
post callback_url, params: read_message('personal4_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(4)
ticket = Ticket.last
if Rails.application.config.db_4bytes_utf8
expect(ticket.title).to eq('💻')
else
expect(ticket.title).to eq('')
expect do
Telegram.check_token('invalid_token')
end.to raise_error(Exceptions::UnprocessableEntity)
end
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to match(/<img style="/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
# send channel message #5 with sticker
post callback_url, params: read_message('channel1_message_content5'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(4)
ticket = Ticket.last
if Rails.application.config.db_4bytes_utf8
expect(ticket.title).to eq('💻')
else
expect(ticket.title).to eq('')
it 'valid token' do
stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
bot = Telegram.check_token(token)
expect(bot['id']).to eq(bot_id)
end
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to match(/<img style="/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
# start communication #5 - with photo
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => 'AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC' })
.to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC","file_path":"abc123"}}', headers: {})
post callback_url, params: read_message('personal5_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(5)
ticket = Ticket.last
expect(ticket.title).to eq('-')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to match(/<img style="/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(0)
post callback_url, params: read_message('personal5_message_content2'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(5)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(2)
expect(ticket.articles.last.body).to match(/Hello, I need your Help/i)
expect(ticket.articles.last.content_type).to eq('text/plain')
expect(ticket.articles.last.attachments.count).to eq(0)
end
it 'with two bots and different groups' do
Ticket.destroy_all
describe 'create_or_update_channel' do
# configure telegram channel
token1 = 'valid_token1'
token2 = 'valid_token2'
it 'via http' do
bot_id1 = 123_456_789
bot_id2 = 987_654_321
Setting.set('http_type', 'http')
group1 = create(:group)
group2 = create(:group)
stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
UserInfo.current_user_id = 1
Channel.where(area: 'Telegram::Bot').destroy_all
expect do
Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
end.to raise_error(Exceptions::UnprocessableEntity)
end
Setting.set('http_type', 'https')
Setting.set('fqdn', 'example.com')
it 'via https and invalid port' do
# channel 1 - try valid token
stub_request(:post, "https://api.telegram.org/bot#{token1}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id1},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot1\"}}", headers: {})
UserInfo.current_user_id = 1
Setting.set('http_type', 'https')
Setting.set('fqdn', 'somehost.example.com:12345')
bot1 = Telegram.check_token(token1)
expect(bot1['id']).to eq(bot_id1)
stub_request(:post, "https://api.telegram.org:443/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
.with(body: { 'url' => "https://somehost.example.com:12345/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
.to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443"}', headers: {})
# channel 1 - valid token, host and port
stub_request(:post, "https://api.telegram.org:443/bot#{token1}/setWebhook")
.with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id1}" })
.to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
expect do
Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
end.to raise_error(Exceptions::UnprocessableEntity)
end
channel1 = Telegram.create_or_update_channel(token1, { group_id: group1.id, welcome: 'hi!', goodbye: 'goodbye' })
it 'via https and invalid host' do
# start communication #1
callback_url1 = "/api/v1/channels_telegram_webhook/#{channel1.options[:callback_token]}?bid=#{channel1.options[:bot][:id]}"
post callback_url1, params: read_message('personal1_message_start'), as: :json
expect(response).to have_http_status(:ok)
Setting.set('http_type', 'https')
Setting.set('fqdn', 'somehost.example.com')
# send message1
post callback_url1, params: read_message('personal1_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(1)
ticket1 = Ticket.last
expect(ticket1.title).to eq('Hello, I need your Help')
expect(ticket1.state.name).to eq('new')
expect(ticket1.articles.count).to eq(1)
expect(ticket1.articles.first.body).to eq('Hello, I need your Help')
expect(ticket1.articles.first.content_type).to eq('text/plain')
stub_request(:post, "https://api.telegram.org:443/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
expect(ticket1.articles.first.from).to eq('Test Firstname Test Lastname')
expect(ticket1.articles.first.to).to eq('@ChrispressoBot1')
stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
.with(body: { 'url' => "https://somehost.example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
.to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: getaddrinfo: Name or service not known"}', headers: {})
# channel 2 - try valid token
UserInfo.current_user_id = 1
stub_request(:post, "https://api.telegram.org/bot#{token2}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id2},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot2\"}}", headers: {})
expect do
Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
end.to raise_error(Exceptions::UnprocessableEntity)
end
bot2 = Telegram.check_token(token2)
expect(bot2['id']).to eq(bot_id2)
it 'with https, valid token, host and port' do
# channel 2 - valid token, host and port
stub_request(:post, "https://api.telegram.org:443/bot#{token2}/setWebhook")
.with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id2}" })
.to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
Setting.set('http_type', 'https')
Setting.set('fqdn', 'example.com')
UserInfo.current_user_id = 1
channel2 = Telegram.create_or_update_channel(token2, { group_id: group2.id, welcome: 'hi!', goodbye: 'goodbye' })
stub_request(:post, "https://api.telegram.org:443/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
# start communication #1
callback_url2 = "/api/v1/channels_telegram_webhook/#{channel2.options[:callback_token]}?bid=#{channel2.options[:bot][:id]}"
post callback_url2, params: read_message('personal3_message_start'), as: :json
expect(response).to have_http_status(:ok)
stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
.with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
.to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
# send message2
post callback_url2, params: read_message('personal3_message_content1'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(2)
ticket2 = Ticket.last
expect(ticket2.title).to eq('Can you help me with my feature?')
expect(ticket2.state.name).to eq('new')
expect(ticket2.articles.count).to eq(1)
expect(ticket2.articles.first.body).to eq('Can you help me with my feature?')
expect(ticket2.articles.first.content_type).to eq('text/plain')
expect(ticket2.articles.first.from).to eq('Test Firstname2 Test Lastname2')
expect(ticket2.articles.first.to).to eq('@ChrispressoBot2')
channel = Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' })
expect(channel).to be_truthy
end
end
def read_message(file)
JSON.parse(File.read(Rails.root.join('test', 'data', 'telegram', "#{file}.json")))
describe 'communication' do
before do
UserInfo.current_user_id = 1
Channel.where(area: 'Telegram::Bot').destroy_all
Setting.set('http_type', 'https')
Setting.set('fqdn', 'example.com')
stub_request(:post, "https://api.telegram.org:443/bot#{token}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
.with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
.to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
stub_request(:post, "https://api.telegram.org:443/bot#{token2}/getMe")
.to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id2},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot2\"}}", headers: {})
stub_request(:post, "https://api.telegram.org:443/bot#{token2}/setWebhook")
.with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id2}" })
.to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
end
let!(:channel) { Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!', goodbye: 'goodbye' }) }
let!(:channel2) { Telegram.create_or_update_channel(token2, { group_id: group_id2, welcome: 'hi!', goodbye: 'goodbye' }) }
let!(:callback_url) { "/api/v1/channels_telegram_webhook/#{channel.options[:callback_token]}?bid=#{channel.options[:bot][:id]}" }
let!(:callback_url2) { "/api/v1/channels_telegram_webhook/#{channel2.options[:callback_token]}?bid=#{channel2.options[:bot][:id]}" }
describe 'private' do
before do
init_mocks
end
it 'no found message' do
post '/api/v1/channels_telegram_webhook', params: read_message('private', 'start'), as: :json
expect(response).to have_http_status(:not_found)
end
it 'bot id is missing' do
post '/api/v1/channels_telegram_webhook/not_existing', params: read_message('private', 'start'), as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response['error']).to eq('bot id is missing')
end
it 'invalid callback token' do
callback_url = "/api/v1/channels_telegram_webhook/not_existing?bid=#{channel.options[:bot][:id]}"
post callback_url, params: read_message('private', 'start'), as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response['error']).to eq('invalid callback token')
end
it 'start message' do
post callback_url, params: read_message('private', 'start'), as: :json
expect(response).to have_http_status(:ok)
end
it 'text message' do
post callback_url, params: read_message('private', 'text'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
end
it 'ignore same text message' do
post callback_url, params: read_message('private', 'text'), as: :json
expect(response).to have_http_status(:ok)
post callback_url, params: read_message('private', 'text'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
end
it 'document message' do
post callback_url, params: read_message('private', 'document'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.last.body).to match(/<img style="width:200px;height:200px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('document.pdf')
end
it 'photo message' do
post callback_url, params: read_message('private', 'photo'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.last.body).to match(/<img style="width:360px;height:327px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
end
it 'video message' do
post callback_url, params: read_message('private', 'video'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to match(/<img style="/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('video-videofileid.mp4')
end
it 'sticker message' do
post callback_url, params: read_message('private', 'sticker'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
if Rails.application.config.db_4bytes_utf8
expect(ticket.title).to eq('😄')
else
expect(ticket.title).to eq('')
end
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to match(/<img style="/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('HotCherry.webp')
end
it 'voice message' do
post callback_url, params: read_message('private', 'voice'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('audio-voicefileid.ogg')
end
it 'end message' do
post callback_url, params: read_message('private', 'text'), as: :json
expect(response).to have_http_status(:ok)
post callback_url, params: read_message('private', 'end'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.state.name).to eq('closed')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to eq('Hello, I need your Help')
expect(ticket.articles.last.content_type).to eq('text/plain')
end
end
describe 'channel' do
before do
init_mocks
end
it 'start message' do
post callback_url, params: read_message('channel', 'start'), as: :json
expect(response).to have_http_status(:ok)
end
it 'text message' do
post callback_url, params: read_message('channel', 'text'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
end
it 'ignore same text message' do
post callback_url, params: read_message('channel', 'text'), as: :json
expect(response).to have_http_status(:ok)
post callback_url, params: read_message('channel', 'text'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.title).to eq('Hello, I need your Help')
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.first.body).to eq('Hello, I need your Help')
expect(ticket.articles.first.content_type).to eq('text/plain')
end
it 'document message' do
post callback_url, params: read_message('channel', 'document'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.last.body).to match(/<img style="width:200px;height:200px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('document.pdf')
end
it 'photo message' do
post callback_url, params: read_message('channel', 'photo'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.last.body).to match(/<img style="width:360px;height:327px;"/i)
expect(ticket.articles.last.content_type).to eq('text/html')
end
it 'video message' do
post callback_url, params: read_message('channel', 'video'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to match(/<img style="/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('video-videofileid.mp4')
end
it 'sticker message' do
post callback_url, params: read_message('channel', 'sticker'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
if Rails.application.config.db_4bytes_utf8
expect(ticket.title).to eq('😄')
else
expect(ticket.title).to eq('')
end
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to match(/<img style="/i)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('HotCherry.webp')
end
it 'voice message' do
post callback_url, params: read_message('channel', 'voice'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.content_type).to eq('text/html')
expect(ticket.articles.last.attachments.count).to eq(1)
expect(Store.last.filename).to eq('audio-voicefileid.ogg')
end
it 'end message' do
post callback_url, params: read_message('channel', 'text'), as: :json
expect(response).to have_http_status(:ok)
post callback_url, params: read_message('channel', 'end'), as: :json
expect(response).to have_http_status(:ok)
ticket = Ticket.last
expect(ticket.state.name).to eq('closed')
expect(ticket.articles.count).to eq(1)
expect(ticket.articles.last.body).to eq('Hello, I need your Help')
expect(ticket.articles.last.content_type).to eq('text/plain')
end
end
it 'with two bots and different groups' do
Ticket.destroy_all
# send start message
post callback_url, params: read_message('private', 'start'), as: :json
expect(response).to have_http_status(:ok)
# send text message
post callback_url, params: read_message('private', 'text'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(1)
ticket1 = Ticket.last
expect(ticket1.title).to eq('Hello, I need your Help')
expect(ticket1.state.name).to eq('new')
expect(ticket1.articles.count).to eq(1)
expect(ticket1.articles.first.body).to eq('Hello, I need your Help')
expect(ticket1.articles.first.content_type).to eq('text/plain')
expect(ticket1.articles.first.from).to eq('Test Firstname Test Lastname')
expect(ticket1.articles.first.to).to eq('@ChrispressoBot')
# send start2 message
post callback_url2, params: read_message('private', 'start2'), as: :json
expect(response).to have_http_status(:ok)
# send text2 message
post callback_url2, params: read_message('private', 'text2'), as: :json
expect(response).to have_http_status(:ok)
expect(Ticket.count).to eq(2)
ticket2 = Ticket.last
expect(ticket2.title).to eq('Can you help me with my feature?')
expect(ticket2.state.name).to eq('new')
expect(ticket2.articles.count).to eq(1)
expect(ticket2.articles.first.body).to eq('Can you help me with my feature?')
expect(ticket2.articles.first.content_type).to eq('text/plain')
expect(ticket2.articles.first.from).to eq('Test Firstname2 Test Lastname2')
expect(ticket2.articles.first.to).to eq('@ChrispressoBot2')
end
end
def read_message(type, file)
JSON.parse(File.read(Rails.root.join('test', 'data', 'telegram', type, "#{file}.json")))
end
def init_mocks
# create mocks for every file type
%w[document documentthumb voice sticker stickerthumb video videothumb photo].each do |file|
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => "#{file}fileid" })
.to_return(status: 200, body: "{\"result\":{\"file_size\":123456,\"file_id\":\"#{file}fileid\",\"file_path\":\"documentfile\"}}", headers: {})
stub_request(:get, "https://api.telegram.org/file/bot#{token}/#{file}file")
.to_return(status: 200, body: "#{file}file", headers: {})
end
[1, 2, 3].each do |id|
stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
.with(body: { 'file_id' => "photofileid#{id}" })
.to_return(status: 200, body: "{\"result\":{\"file_size\":3622849,\"file_id\":\"photofileid#{id}\",\"file_path\":\"photofile\"}}", headers: {})
stub_request(:get, "https://api.telegram.org/file/bot#{token}/photofile")
.to_return(status: 200, body: 'photofile', headers: {})
end
end
end
end

View file

@ -0,0 +1,26 @@
{
"update_id": 954691816,
"channel_post": {
"chat": {
"id": 123456789,
"title": "Bot Channel",
"type": "channel"
},
"message_id": 10,
"date": 1566318707,
"document": {
"file_name": "document.pdf",
"mime_type": "application/pdf",
"thumb": {
"file_id": "documentthumbfileid",
"file_size": 123456,
"width": 200,
"height": 200
},
"file_id": "documentfileid",
"file_size": 123456
}
},
"bid": "0987654321",
"callback_token": "FidczWOKOLysIQ"
}

View file

@ -0,0 +1,22 @@
{
"update_id": 10002,
"channel_post": {
"chat": {
"id": 123456789,
"title": "Bot Channel",
"type": "channel"
},
"entities": [
{
"offset": 0,
"length": 6,
"type": "bot_command"
}
],
"date": 1566317999,
"message_id": 7,
"text": "/end"
},
"bid": "0987654321",
"callback_token": "FidczWOKOLysIQ"
}

View file

@ -0,0 +1,34 @@
{
"update_id": 954691815,
"channel_post": {
"chat": {
"id": 123456789,
"title": "Bot Channel",
"type": "channel"
},
"message_id": 9,
"date": 1566318591,
"photo": [
{
"file_id": "photofileid1",
"file_size": 123456,
"width": 90,
"height": 82
},
{
"file_id": "photofileid2",
"file_size": 123456,
"width": 320,
"height": 291
},
{
"file_id": "photofileid3",
"file_size": 123456,
"width": 720,
"height": 654
}
]
},
"bid": "0987654321",
"callback_token": "FidczWOKOLysIQ"
}

View file

@ -0,0 +1,22 @@
{
"update_id": 10001,
"channel_post": {
"chat": {
"id": 123456789,
"title": "Bot Channel",
"type": "channel"
},
"entities": [
{
"offset": 0,
"length": 6,
"type": "bot_command"
}
],
"date": 1566317998,
"message_id": 7,
"text": "/start"
},
"bid": "0987654321",
"callback_token": "FidczWOKOLysIQ"
}

View file

@ -0,0 +1,29 @@
{
"update_id": 954691817,
"channel_post": {
"chat": {
"id": 123456789,
"title": "Bot Channel",
"type": "channel"
},
"message_id": 11,
"date": 1566318766,
"sticker": {
"width": 512,
"height": 512,
"emoji": "😄",
"set_name": "HotCherry",
"is_animated": true,
"file_id": "stickerfileid",
"file_size": 15455,
"thumb": {
"file_id": "stickerthumbfileid",
"file_size": 4622,
"width": 128,
"height": 128
}
}
},
"bid": "0987654321",
"callback_token": "FidczWOKOLysIQ"
}

View file

@ -0,0 +1,15 @@
{
"update_id":10001,
"channel_post":{
"chat":{
"id": 123456789,
"title":"ZBotChannel",
"type":"channel"
},
"message_id":1365,
"date":1441645532,
"text":"Hello, I need your Help"
},
"bid":"12345678",
"callback_token":"AbcDefG"
}

View file

@ -0,0 +1,29 @@
{
"update_id": 954691820,
"channel_post": {
"chat": {
"id": 123456789,
"title": "Bot Channel",
"type": "channel"
},
"message_id": 14,
"date": 1566319040,
"video":{
"duration":1,
"width":360,
"height":640,
"mime_type":"video/mp4",
"file_id":"videofileid",
"file_size":123456,
"thumb": {
"file_id": "videothumbfileid",
"file_size": 123456,
"width": 180,
"height": 320
}
},
"caption": "caption"
},
"bid": "0987654321",
"callback_token": "FidczWOKOLysIQ"
}

View file

@ -0,0 +1,20 @@
{
"update_id": 954691818,
"channel_post": {
"chat": {
"id": 123456789,
"title": "Bot Channel",
"type": "channel"
},
"message_id": 12,
"date": 1566318851,
"voice": {
"duration": 1,
"mime_type": "audio/ogg",
"file_id": "voicefileid",
"file_size": 1280
}
},
"bid": "0987654321",
"callback_token": "FidczWOKOLysIQ"
}

View file

@ -1,22 +0,0 @@
{
"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"
}
]
}
}

View file

@ -1,27 +0,0 @@
{
"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"
}
}
}

View file

@ -1,34 +0,0 @@
{
"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"
}
}

View file

@ -1,20 +0,0 @@
{
"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"
}
}

View file

@ -1,30 +0,0 @@
{
"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"
}
}

View file

@ -1,22 +0,0 @@
{
"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"
}
]
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":10001,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":1365,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"Hello, I need your Help"
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":10002,
"message":{
"date":1441645535,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":1366,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"Hello, I need your Help 2"
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":10003,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":1367,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"/end"
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":10000,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":1365,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"/start"
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":20001,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":2365,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"Can you help me with my feature?"
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":20002,
"message":{
"date":1441645536,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":2366,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"Yes of course! <b>lalal</b>"
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":20000,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname",
"id":1111111,
"type": "private",
"first_name":"Test Firstname",
"username":"Testusername"
},
"message_id":2364,
"from":{
"last_name":"Test Lastname",
"id":1111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"text":"/start"
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":30001,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname2",
"id":1111112,
"type": "private",
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"message_id":3365,
"from":{
"last_name":"Test Lastname2",
"id":1111112,
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"text":"Can you help me with my feature?"
}
}

View file

@ -1,42 +0,0 @@
{
"update_id": 30002,
"message": {
"message_id": 3366,
"from": {
"last_name":"Test Lastname2",
"id":1111112,
"type": "private",
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"chat": {
"last_name":"Test Lastname2",
"id":1111112,
"first_name":"Test Firstname2",
"username":"Testusername2",
"type": "private"
},
"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
}
],
"caption": "caption 123<b>abc</b>"
}
}

View file

@ -1,33 +0,0 @@
{
"update_id": 30003,
"message": {
"message_id": 3367,
"from": {
"last_name":"Test Lastname2",
"id":1111112,
"type": "private",
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"chat": {
"last_name":"Test Lastname2",
"id":1111112,
"first_name":"Test Firstname2",
"username":"Testusername2",
"type": "private"
},
"date": 1486036832,
"document": {
"file_name": "blockposter-162412.pdf",
"mime_type": "application/pdf",
"thumb": {
"file_id": "AAQCABO0I4INAATATQAB5HWPq4XgxQACAg",
"file_size": 8752,
"width": 200,
"height": 200
},
"file_id": "BQADAgADDgAD7x6ZSC_-1LMkOEmoAg",
"file_size": 3622849
}
}
}

View file

@ -1,22 +0,0 @@
{
"update_id":30004,
"edited_message": {
"message_id":3365,
"from": {
"last_name":"Test Lastname2",
"id":1111112,
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"chat": {
"last_name":"Test Lastname2",
"id":1111112,
"type": "private",
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"date": 1487116688,
"edit_date": 1487116889,
"text": "UPDATE: 1231444"
}
}

View file

@ -1,26 +0,0 @@
{
"update_id":30005,
"message":{
"message_id":3368,
"from":{
"last_name":"Test Lastname2",
"id":1111112,
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"chat":{
"last_name":"Test Lastname2",
"id":1111112,
"type": "private",
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"date":1487119496,
"voice":{
"duration":1,
"mime_type":"audio/ogg",
"file_id":"AwADAgADVQADCEIYSZwyOmSZK9iZAg",
"file_size":6030
}
}
}

View file

@ -1,21 +0,0 @@
{
"update_id":30000,
"message":{
"date":1441645532,
"chat":{
"last_name":"Test Lastname2",
"id":1111112,
"type": "private",
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"message_id":3364,
"from":{
"last_name":"Test Lastname2",
"id":1111112,
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"text":"/start start"
}
}

View file

@ -1,31 +0,0 @@
{
"update_id":40000,
"message":{
"message_id":273,
"from":{
"id":3310000,
"first_name":"Roberto",
"last_name":"Blanco"
},
"chat":{
"id":3310000,
"first_name":"Roberto",
"last_name":"Blanco",
"type":"private"
},
"date":1487161566,
"sticker":{
"width":512,
"height":512,
"emoji":"💻",
"thumb":{
"file_id":"AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC",
"file_size":4584,
"width":128,
"height":128
},
"file_id":"BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C",
"file_size":25974
}
}
}

View file

@ -1,50 +0,0 @@
{
"update_id":50000,
"message":{
"message_id":15,
"from":{
"id":294302174,
"first_name":"Martin",
"username":"martini42"
},
"chat":{
"id":294302174,
"first_name":"Martin",
"username":"martini42",
"type":"private"
},
"date":1487295982,
"photo":[
{
"file_id":"AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABFq_5qQydQSuAAFkBQABAg",
"file_size":1265,
"width":90,
"height":79
},
{
"file_id":"AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABEvfeiPeNricAWQFAAEC",
"file_size":17208,
"width":320,
"height":282
},
{
"file_id":"AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABG1U3brRukt_AmQFAAEC",
"file_size":62404,
"width":800,
"height":705
},
{
"file_id":"AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC",
"file_size":122459,
"width":1280,
"height":1128
},
{
"file_id":"AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABPxEqfVm-QlI_mMFAAEC",
"file_size":171271,
"width":2000,
"height":1762
}
]
}
}

View file

@ -1,19 +0,0 @@
{
"update_id":50001,
"message":{
"message_id":16,
"from":{
"id":294302174,
"first_name":"Martin",
"username":"martini42"
},
"chat":{
"id":294302174,
"first_name":"Martin",
"username":"martini42",
"type":"private"
},
"date":1487295982,
"text":"Hello, I need your Help"
}
}

View file

@ -0,0 +1,32 @@
{
"update_id": 2,
"message": {
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"message_id": 2,
"date": 1486036832,
"document": {
"file_name": "document.pdf",
"mime_type": "application/pdf",
"thumb": {
"file_id": "documentthumbfileid",
"file_size": 123456,
"width": 200,
"height": 200
},
"file_id": "documentfileid",
"file_size": 123456
}
}
}

View file

@ -0,0 +1,21 @@
{
"update_id":10,
"message":{
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"message_id":10,
"date":1441645532,
"text":"/end"
}
}

View file

@ -0,0 +1,41 @@
{
"update_id": 3,
"message": {
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"message_id": 3,
"date": 1486036832,
"photo": [
{
"file_id": "photofileid1",
"file_size": 123456,
"width": 90,
"height": 82
},
{
"file_id": "photofileid2",
"file_size": 123456,
"width": 320,
"height": 291
},
{
"file_id": "photofileid3",
"file_size": 123456,
"width": 720,
"height": 654
}
],
"caption": "caption 123<b>abc</b>"
}
}

View file

@ -0,0 +1,21 @@
{
"update_id":1,
"message":{
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"message_id":1,
"date":1441645532,
"text":"/start"
}
}

View file

@ -0,0 +1,21 @@
{
"update_id":1001,
"message":{
"from": {
"last_name":"Test Lastname2",
"id":222222,
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"chat": {
"last_name":"Test Lastname2",
"id":222222,
"first_name":"Test Firstname2",
"username":"Testusername2",
"type": "private"
},
"message_id":1001,
"date":1441645532,
"text":"/start"
}
}

View file

@ -0,0 +1,37 @@
{
"update_id":4,
"channel_post":{
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"message_id":273,
"date":1441645532,
"sticker": {
"width": 512,
"height": 512,
"emoji": "😄",
"set_name": "HotCherry",
"is_animated": true,
"file_id": "stickerfileid",
"file_size": 15455,
"thumb": {
"file_id": "stickerthumbfileid",
"file_size": 4622,
"width": 128,
"height": 128
}
},
"callback_token":"z5N_uxY_Fut81g",
"bid":"435791794"
}
}

View file

@ -0,0 +1,21 @@
{
"update_id":5,
"message":{
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"date":1441645532,
"message_id":5,
"text":"Hello, I need your Help"
}
}

View file

@ -0,0 +1,21 @@
{
"update_id":1002,
"message":{
"from": {
"last_name":"Test Lastname2",
"id":222222,
"first_name":"Test Firstname2",
"username":"Testusername2"
},
"chat": {
"last_name":"Test Lastname2",
"id":222222,
"first_name":"Test Firstname2",
"username":"Testusername2",
"type": "private"
},
"message_id":1002,
"date":1441645532,
"text":"Can you help me with my feature?"
}
}

View file

@ -0,0 +1,34 @@
{
"update_id":6,
"message":{
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"message_id":6,
"date":1487119496,
"video":{
"duration":1,
"width":360,
"height":640,
"mime_type":"video/mp4",
"file_id":"videofileid",
"file_size":123456,
"thumb": {
"file_id": "videothumbfileid",
"file_size": 123456,
"width": 180,
"height": 320
}
}
}
}

View file

@ -0,0 +1,26 @@
{
"update_id":7,
"message":{
"from": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername"
},
"chat": {
"last_name":"Test Lastname",
"id":111111,
"first_name":"Test Firstname",
"username":"Testusername",
"type": "private"
},
"message_id":7,
"date":1487119496,
"voice":{
"duration":1,
"mime_type":"audio/ogg",
"file_id":"voicefileid",
"file_size":123456
}
}
}