Skip to content

Commit

Permalink
Merge pull request #43 from southbridgeio/develop
Browse files Browse the repository at this point in the history
Release 0.4.0
  • Loading branch information
vladislav-yashin authored Jan 10, 2020
2 parents 796c0cf + fa1acdd commit 0b24544
Show file tree
Hide file tree
Showing 25 changed files with 246 additions and 44 deletions.
12 changes: 9 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
language: ruby
rvm:
- 2.3.8
- 2.6.0
- 2.4.9
- 2.6.5
- 2.7.0

branches:
only:
Expand All @@ -13,7 +14,12 @@ addons:

env:
- REDMINE_VER=3.4-stable
- REDMINE_VER=4.0-stable
- REDMINE_VER=4.1-stable

matrix:
exclude:
- env: REDMINE_VER=3.4-stable
rvm: 2.7.0

install: "echo skip bundle install"

Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
# 0.4.0

* Handle Faraday::ClientError in MessageSender
* Handle deactivated user error in message sender
* Force ipv4 when using proxy
* Improve proxy availability check
* Close supergroups properly
* Rescue from chat not found errors
* Increase sleep time for flood error
* Handle forbidden errors in message sender
* Use sleep time from error data
* Add zh-TW locale
* Handle "message not modified errors"
* Increase rate limits, add exponential retry
* Support tdlib 1.6

# 0.3.1

* Fix Rails 4 support
Expand Down
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ gem 'sidekiq-cron'
gem 'sidekiq-rate-limiter', git: 'https://github.com/centosadmin/sidekiq-rate-limiter', branch: 'master',
require: 'sidekiq-rate-limiter/server'

gem 'telegram-bot-ruby', '~> 0.8.6'
gem 'telegram-bot-ruby', '>= 0.11', '< 1.0'
gem 'slack-ruby-bot'
gem 'celluloid-io'
gem 'tdlib-ruby', '2.0.0'
gem 'tdlib-ruby', '2.2.0'
gem 'jwt'
gem 'filelock'
gem 'patron'
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This plugin provides common stuff to build redmine plugins that involve Slack/Te

## Requirements

* Ruby 2.3+
* Ruby 2.4+
* Redmine 3.4+
* [redmine_sidekiq](https://github.com/southbridgeio/redmine_sidekiq) (also requires Redis)

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/telegram_login_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def context
def handle_auth_result(auth, user)
if auth.success?
if user != User.current
user.update!(two_fa_id: AuthSource.find_by_name('Telegram').id)
user.update!(two_fa: 'telegram')
successful_authentication(user)
else
redirect_to my_page_path, notice: t('redmine_bots.telegram.bot.login.success')
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/telegram_proxies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ def update
proxy.save
end

TelegramProxyMonitoringWorker.perform_async

respond_to do |format|
format.js
end
Expand Down
5 changes: 4 additions & 1 deletion app/models/telegram_proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ def check!

def connection
Faraday.new('https://telegram.org') do |conn|
conn.adapter(:patron) { |adapter| adapter.proxy = url }
conn.adapter(:patron) do |adapter|
adapter.proxy = url
adapter.force_ipv4 = true
end
end
end
end
3 changes: 3 additions & 0 deletions app/views/telegram_proxies/_item.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<%= hidden_field_tag 'proxies[][id]', proxy.id %>
<%= text_field_tag 'proxies[][url]', proxy.url, style: 'width: 50%' %>

<% icon, locale = proxy.alive? ? %w[icon-ok proxy_alive] : %w[icon-error proxy_dead] %>

<% unless proxy.new_record? %>
<span class="icon <%= icon %>" title="<%= t locale, scope: 'redmine_bots.settings.telegram' %>"></span>
<%= link_to l(:button_delete), telegram_proxy_destroy_path(id: proxy.id), remote: true, method: :delete %>
<% end %>
</p>
2 changes: 2 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ en:
bot_use_proxy: Use proxy for bot
proxy_settings: Proxy settings
proxy_list: Proxy list
proxy_alive: Proxy is accessible
proxy_dead: Proxy is not accessible
requirements:
title: Requirements
telegram:
Expand Down
2 changes: 2 additions & 0 deletions config/locales/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ ru:
bot_use_proxy: Использовать прокси для бота
proxy_settings: Настройки прокси
proxy_list: Список прокси
proxy_alive: Прокси доступен
proxy_dead: Прокси недоступен
requirements:
title: Требования
telegram:
Expand Down
86 changes: 86 additions & 0 deletions config/locales/zh-TW.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
zh-TW:
redmine_bots:
label:
slack: Slack
telegram: Telegram
settings:
deprecated_plugins: '警告!安裝了棄用的外掛:'
slack_oauth_token: OAuth Access Token
slack_bot_oauth_token: Bot User OAuth Access Token
slack_client_id: Client ID
slack_client_secret: Client Secret
slack_verification_token: 驗證 Token
telegram:
phone_number: "電話號碼"
phone_number_hint: "以台灣手機 0912-345-678 為例,需輸入:886912345678"
phone_code: "Telegram 代碼"
authorize_button_code: "接收代碼"
authorize_button: "授權"
authorize_client: "授權給 Telegram 用戶端"
authorize_hint: "請按下面的按鈕授權給 Telegram。目前的授權則會被清除。"
plugin_link: "回到外掛設定"
auth_step_1: "接收 Telegram 代碼"
auth_step_2: "授權"
reset: "重設快取及授權"
bot_init: 初始化機器人
bot_deinit: 停用機器人
get_updates_hint: bundle exec rake redmine_bots:telegram
web_hooks_warning: 設定 WebHooks 需要 HTTPS
tdlib_use_proxy: tdlib 使用 Proxy
bot_use_proxy: 機器人使用 Proxy
proxy_settings: Proxy 設定
proxy_list: Proxy 列表
proxy_alive: Proxy 可用
proxy_dead: Proxy 不可用
requirements:
title: 需求
telegram:
valid: 有效
description: 說明
no:
yes:
rails_env: "請確定您的 RAILS_ENV 環境變數設定為 production(目前為:%{rails_env})"
redmine_host: "請確定您在 Redmine 的設定中有正確設定 Host(目前為:%{host})"
tdlib_installation: "您應該安裝 libtdjson 到 Redmine 目錄下的 vendor 目錄,或者安裝到 ldconfig。<a href='https://core.telegram.org/tdlib/docs/#building' target='_blank'>安裝教學</a>。"
telegram:
authorize:
success: 驗證完成!
bot:
start:
instruction_html: |
現在我們必須連結您的 Redmine 和 Telegram 帳號。
請輸入 /connect 指令。
hello: 您好!
connect:
already_connected: 您的帳戶已經連結。
wait_for_email: 我們寄了一封 Email 到 "%{email}",請依照信中的指示操作。
wrong_email: 錯誤的信箱!找不到信箱對應的使用者。再失敗 %{attempts} 次之後,這個帳號將被鎖定一個小時。
blocked: 您的帳號已被鎖定,請於 %{unblock} 分鐘後再嘗試。
login_link: "使用這個連結來連結這個帳號 和 Redmine:%{link}"
group:
no_commands: "沒有群組聊天用的指令。私聊指令:"
private_command: '這個指令只能用在私聊。'
private:
group_command: '這個指令只能用在群組聊天。'
help:
start: "開始使用機器人"
connect: "連結 Redmine 和 Telegram 帳號"
help: "指令的幫助"
token: 取得驗證連結
login:
success: 驗證成功
errors:
not_logged: 您尚未登入
hash_invalid: Hash 不合法
hash_outdated: 請求已過期
wrong_account: 錯誤的 Telegram 帳號
not_persisted: Failed to persist Telegram account data
invalid_token: Token 不合法
follow_link: 請根據連結
send_to_telegram: 傳送驗證連結到 Telegram
widget_not_visible: 如果小工具沒有顯示
write_to_bot: "如果小工具沒有顯示,請發送 /token 訊息給機器人 @%{bot}。"
slack:
commands:
connect: 連結 Slack 帳號和 Redmine
help: 指令的幫助訊息
2 changes: 1 addition & 1 deletion init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
name 'Redmine Bots'
url 'https://github.com/southbridgeio/redmine_bots'
description 'This is a platform for building Redmine bots'
version '0.3.1'
version '0.4.0'
author 'Southbridge'
author_url 'https://github.com/southbridgeio'

Expand Down
2 changes: 1 addition & 1 deletion lib/redmine_bots/telegram/bot/authenticate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def call

case @context
when '2fa_connection'
telegram_account = prepare_telegram_account(model_class: Redmine2FA::TelegramConnection)
telegram_account = prepare_telegram_account(model_class: RedmineTwoFa::TelegramConnection)
return failure(I18n.t('redmine_bots.telegram.bot.login.errors.wrong_account')) unless telegram_account
when 'account_connection'
telegram_account = prepare_telegram_account(model_class: TelegramAccount)
Expand Down
14 changes: 12 additions & 2 deletions lib/redmine_bots/telegram/bot/authenticate_by_token.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
module RedmineBots
module Telegram
class Bot::AuthenticateByToken
class MessageNotModifiedError
def self.===(e)
e.is_a?(::Telegram::Bot::Exceptions::ResponseError) && e.message.include?('message is not modified')
end
end

def self.call(*args)
new(*args).call
end
Expand All @@ -14,7 +20,7 @@ def call

case @context
when '2fa_connection'
telegram_account = prepare_telegram_account(model_class: Redmine2FA::TelegramConnection)
telegram_account = prepare_telegram_account(model_class: RedmineTwoFa::TelegramConnection)
when 'account_connection'
telegram_account = prepare_telegram_account(model_class: TelegramAccount)
else
Expand All @@ -24,7 +30,11 @@ def call
return failure(I18n.t('redmine_bots.telegram.bot.login.errors.wrong_account')) unless telegram_account

if telegram_account.save
::RedmineBots::Telegram::Bot::UpdateSignInMessage.(telegram_account, @sign_in_message_id) if @sign_in_message_id
begin
::RedmineBots::Telegram::Bot::UpdateSignInMessage.(telegram_account, @sign_in_message_id) if @sign_in_message_id
rescue MessageNotModifiedError
# skip
end
success(telegram_account)
else
failure(I18n.t('redmine_bots.telegram.bot.login.errors.not_persisted'))
Expand Down
1 change: 1 addition & 0 deletions lib/redmine_bots/telegram/bot/faraday_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def call(env)

if settings['bot_use_proxy'] && proxy = TelegramProxy.alive.first
session.proxy = proxy.url
session.force_ipv4 = true
end
end

Expand Down
51 changes: 45 additions & 6 deletions lib/redmine_bots/telegram/bot/message_sender.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module RedmineBots::Telegram
class Bot
class MessageSender
SLEEP_TIME = 30
SLEEP_TIME = 60
FARADAY_SLEEP_TIME = 10
TRIES = 5

class BotKickedError
def self.===(e)
Expand All @@ -15,6 +17,30 @@ def self.===(e)
end
end

class UserDeactivatedError
def self.===(e)
e.is_a?(Telegram::Bot::Exceptions::ResponseError) && e.message.include?('user is deactivated')
end
end

class BotBlockedError
def self.===(e)
e.is_a?(Telegram::Bot::Exceptions::ResponseError) && e.message.include?('bot was blocked')
end
end

class ForbiddenError
def self.===(e)
e.is_a?(Telegram::Bot::Exceptions::ResponseError) && e.message.include?("bot can't initiate conversation with a user")
end
end

class ChatNotFoundError
def self.===(e)
e.is_a?(Telegram::Bot::Exceptions::ResponseError) && e.message.include?('chat not found')
end
end

def self.call(params)
new(params).call
end
Expand All @@ -24,12 +50,12 @@ def self.call(params)
def initialize(params)
@message = params.fetch(:message)
@chat_id = params.fetch(:chat_id)
@bot_token = params.fetch(:bot_token)
@bot_token = params.fetch(:bot_token) { RedmineBots::Telegram.bot_token }
@params = params.except(:message, :chat_id, :bot_token)
end

def call
tries ||= 3
tries ||= TRIES
message_params = {
chat_id: chat_id,
text: message,
Expand All @@ -40,9 +66,22 @@ def call
bot.api.send_message(message_params)
rescue BotKickedError
logger.warn("Bot was kicked from chat. Chat Id: #{chat_id}, params: #{params.inspect}")
rescue BotBlockedError
logger.warn("Bot is blocked by user. Chat Id: #{chat_id}, params: #{params.inspect}")
rescue UserDeactivatedError
logger.warn("User is deactivated: #{chat_id}, params: #{params.inspect}")
rescue ChatNotFoundError
logger.warn("Chat not found: #{chat_id}, params: #{params.inspect}")
rescue ForbiddenError
logger.warn("Bot can't initiate conversation with a user. Chat Id: #{chat_id}, params: #{params.inspect}")
rescue FloodError => e
logger.warn("Too many requests. Sleeping #{SLEEP_TIME} seconds...")
sleep SLEEP_TIME
sleep_time = (e.send(:data).dig('parameters', 'retry_after') || SLEEP_TIME) * (TRIES - tries + 1)
logger.warn("Too many requests. Sleeping #{sleep_time} seconds...")
sleep sleep_time
(tries -= 1).zero? ? raise(e) : retry
rescue Faraday::ClientError => e
logger.warn("Faraday client error. Sleeping #{FARADAY_SLEEP_TIME} seconds...")
sleep FARADAY_SLEEP_TIME * (TRIES - tries + 1)
(tries -= 1).zero? ? raise(e) : retry
end

Expand All @@ -54,7 +93,7 @@ def bot

def logger
@logger ||= Logger.new(Rails.root.join('log/redmine_bots',
'message-sender.log'))
'message-sender.log'))
end
end
end
Expand Down
Empty file.
2 changes: 1 addition & 1 deletion lib/redmine_bots/telegram/tdlib/add_bot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def call(bot_name)
message = TD::Types::InputMessageContent::Text.new(text: TD::Types::FormattedText.new(text: '/start', entities: []),
disable_web_page_preview: true,
clear_draft: false)
client.send_message(chat.id, message)
client.send_message(chat.id, 0, nil, nil, message)
end.flat
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/redmine_bots/telegram/tdlib/authenticate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def call(params)

case update.authorization_state
when AuthorizationState::WaitPhoneNumber
promise = client.set_authentication_phone_number(params[:phone_number])
promise = client.set_authentication_phone_number(params[:phone_number], nil)
when AuthorizationState::WaitCode
promise = client.check_authentication_code(params[:phone_code]) if params[:phone_code]
when AuthorizationState::Ready
Expand Down
Loading

0 comments on commit 0b24544

Please sign in to comment.