Loïc Guitaut c68fde5d2b FIX: Don’t process commands when 'text' is missing
This patch concerns the Telegram integration. Currently, we always try
to process commands when we receive a hook from Telegram. To do so we
rely on the `text` parameters from a Telegram message but the
API documentation tells us this parameters is actually optional. It
means sometimes it’s not present in the payload we receive but we still
try to access it resulting in a crash.

This patch addresses the issue by simply returning early from the
`#process_command` method when `text` is missing from the payload since
we don’t have anything to process then.
2022-07-18 18:11:22 +02:00

115 lines
3.4 KiB
Ruby

# frozen_string_literal: true
module DiscourseChatIntegration::Provider::TelegramProvider
class TelegramCommandController < DiscourseChatIntegration::Provider::HookController
requires_provider ::DiscourseChatIntegration::Provider::TelegramProvider::PROVIDER_NAME
before_action :telegram_token_valid?, only: :command
skip_before_action :check_xhr,
:preload_json,
:verify_authenticity_token,
:redirect_to_login_if_required,
only: :command
def command
# If it's a new message (telegram also sends hooks for other reasons that we don't care about)
if params.key?('message')
chat_id = params['message']['chat']['id']
message_text = process_command(params['message'])
if message_text.present?
message = {
chat_id: chat_id,
text: message_text,
parse_mode: "html",
disable_web_page_preview: true,
}
DiscourseChatIntegration::Provider::TelegramProvider.sendMessage(message)
end
elsif params.dig('channel_post', 'text')&.include?('/getchatid')
chat_id = params['channel_post']['chat']['id']
message_text = I18n.t(
"chat_integration.provider.telegram.unknown_chat",
site_title: CGI::escapeHTML(SiteSetting.title),
chat_id: chat_id,
)
message = {
chat_id: chat_id,
text: message_text,
parse_mode: "html",
disable_web_page_preview: true,
}
DiscourseChatIntegration::Provider::TelegramProvider.sendMessage(message)
end
# Always give telegram a success message, otherwise we'll stop receiving webhooks
data = {
success: true
}
render json: data
end
def process_command(message)
return unless message['text'] # No command to be processed
chat_id = params['message']['chat']['id']
provider = DiscourseChatIntegration::Provider::TelegramProvider::PROVIDER_NAME
channel = DiscourseChatIntegration::Channel.with_provider(provider).with_data_value('chat_id', chat_id).first
text_key = if channel.nil?
"unknown_chat"
elsif !SiteSetting.chat_integration_telegram_enable_slash_commands || !message['text'].start_with?('/')
"silent"
else
""
end
return "" if text_key == "silent"
if text_key.present?
return I18n.t(
"chat_integration.provider.telegram.#{text_key}",
site_title: CGI::escapeHTML(SiteSetting.title),
chat_id: chat_id,
)
end
tokens = message['text'].split(" ")
tokens[0][0] = '' # Remove the slash from the first token
tokens[0] = tokens[0].split('@')[0] # Remove the bot name from the command (necessary for group chats)
::DiscourseChatIntegration::Helper.process_command(channel, tokens)
end
def telegram_token_valid?
params.require(:token)
if SiteSetting.chat_integration_telegram_secret.blank? ||
SiteSetting.chat_integration_telegram_secret != params[:token]
raise Discourse::InvalidAccess.new
end
end
end
class TelegramEngine < ::Rails::Engine
engine_name DiscourseChatIntegration::PLUGIN_NAME + "-telegram"
isolate_namespace DiscourseChatIntegration::Provider::TelegramProvider
end
TelegramEngine.routes.draw do
post "command/:token" => "telegram_command#command"
end
end