abot-info 0.1.1 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 127b62eb518c63d6b7ba0bbcccc85ef22964b44555d92a1dae386dd48dcae3ae
4
- data.tar.gz: b82f5cb6291ee3e612982fda79fb5430694f6fd0127f41ecaae9f9e1c57620af
3
+ metadata.gz: c356808904955eec165f429c9a0012bc095865983303853d48ff09239e988e19
4
+ data.tar.gz: 930de8a6a519242048f9e02603090cdd9560c8040866ec0d23f80b3affa2062e
5
5
  SHA512:
6
- metadata.gz: 03e4168d791452a1faccaa0ac91754101df5d9db3e7f1916dd116686cede9d4df51d9c89c71623c8c08804ab03c3726ce4b0579026e0ba9577c49162bdd165fe
7
- data.tar.gz: f74ff5924ec5bb3270e4503f5c30dacbda788837a48543deafc255a43e665c4b7211fed1a97d04e145480fb7364926697f084c6c804ef88edc10173dd321ef1c
6
+ metadata.gz: a5fbf25ee4fc34c87213f122de255590ae13e316741b0d049f6bde84dd3cacb52f10e8a002eafb6c4eb269b13f4396e8ea06d6d99acf6f2763d59f29dfbe448d
7
+ data.tar.gz: f833ee553da12be027dd6e72ebc2544527ec2e64e9080939b2bcbc15628675111e70c1caaf691cbfca2229540bb2778f64c0a0a7f46e3777ca129ebbe7ad35cb
data/Gemfile CHANGED
@@ -5,3 +5,4 @@ gem 'paint', '~> 2.2.1'
5
5
  gem 'sqlite3', '~> 1.4.2'
6
6
  gem 'terminal-table', '~> 3.0.1'
7
7
  gem 'binance-ruby', '~> 1.3.1'
8
+ gem 'telegram-bot-ruby', '~> 0.16.0'
data/abot-info.gemspec CHANGED
@@ -38,4 +38,5 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency "sqlite3", '~> 1.4.2'
39
39
  spec.add_dependency "terminal-table", '~> 3.0.1'
40
40
  spec.add_dependency "binance-ruby", '~> 1.3.1'
41
+ spec.add_dependency 'telegram-bot-ruby', '~> 0.16.0'
41
42
  end
@@ -79,6 +79,33 @@ module Abot
79
79
  symbol_info(symbol).try(:[], :highPrice).to_f
80
80
  end
81
81
 
82
+ def coins_without_order(quote_assets)
83
+ exception_coins = quote_assets + ['BNB'] + Coin::FIAT
84
+ balances = account_info[:balances]
85
+ result = balances.select do |s|
86
+ s[:free].to_f != 0 &&
87
+ !exception_coins.include?(s[:asset]) &&
88
+ symbol_info(s[:asset] + 'USDT').try(:[], :askPrice).to_f * s[:free].to_f > 5 &&
89
+ (
90
+ begin
91
+ btcusdt = get_symbols.find { |f| f[:symbol] == 'BTCUSDT' }[:askPrice].to_f
92
+ if s[:asset] == 'BTC'
93
+ symbol_info("#{s[:asset]}USDT").try(:[], :askPrice).to_f * s[:free].to_f > 5
94
+ elsif get_symbols.find { |f| f[:symbol] == "#{s[:asset]}USDT" }.nil?
95
+ coin = get_symbols.find { |f| f[:symbol] == "#{name}BTC" }
96
+ coin[:askPrice].to_f * s[:free].to_f * btcusdt > 5
97
+ else
98
+ coin = get_symbols.find { |f| f[:symbol] == "#{s[:asset]}USDT" }
99
+ coin[:askPrice].to_f * s[:free].to_f > 5
100
+ end
101
+ rescue StandardError
102
+ false
103
+ end
104
+ )
105
+ end
106
+ result.pluck(:asset)
107
+ end
108
+
82
109
  private
83
110
 
84
111
  def calculation_current_balance_btc
@@ -8,9 +8,11 @@ module Abot
8
8
  include Abot::Info::Coin::CoinDecorator
9
9
 
10
10
  attr_reader :base_asset, :quote_asset, :average_price, :current_price, :sell_price, :volume, :num_averaging,
11
- :total_quote, :buy_price, :step_averaging, :tick_size, :account, :timer, :trade_params
11
+ :total_quote, :buy_price, :step_averaging, :tick_size, :account, :timer, :trade_params,
12
+ :pump_detector
13
+
14
+ FIAT = %w[USDT BUSD AUD BIDR BRL EUR GBR RUB TRY TUSD USDC DAI IDRT PAX UAH NGN VAI BVND]
12
15
 
13
- FIAT = ['USDT', 'BUSD', 'AUD', 'BIDR', 'BRL', 'EUR', 'GBR', 'RUB', 'TRY', 'TUSD', 'USDC', 'DAI', 'IDRT', 'PAX', 'UAH', 'NGN', 'VAI', 'BVND']
14
16
 
15
17
  def initialize(options = {})
16
18
  @trade_params = options[:trade_params]
@@ -27,6 +29,7 @@ module Abot
27
29
  @step_averaging = options[:step_averaging]
28
30
  @tick_size = options[:tick_size]
29
31
  @timer = options[:timer]
32
+ @pump_detector = options[:pump_detector]
30
33
  end
31
34
 
32
35
  def self.current_coins(account, trade_params)
@@ -46,6 +49,7 @@ module Abot
46
49
  step_averaging: coin['stepAveraging'].to_f,
47
50
  tick_size: coin['tickSize'],
48
51
  timer: coin['timer'].to_s[0..9],
52
+ pump_detector: coin['pumpDetector'],
49
53
  )
50
54
  end
51
55
  end
@@ -74,6 +78,10 @@ module Abot
74
78
  @percent_to_order ||= ((sell_price / current_price - 1) * 100)
75
79
  end
76
80
 
81
+ def percent_from_order
82
+ @percent_from_order ||= ((1 - current_price / sell_price) * 100)
83
+ end
84
+
77
85
  def percent_from_min_to_average
78
86
  @percent_to_min ||= ((min_price / next_average_price - 1) * 100)
79
87
  end
@@ -82,6 +90,10 @@ module Abot
82
90
  @percent_to_max ||= ((sell_price / max_price - 1) * 100)
83
91
  end
84
92
 
93
+ def percent_from_max
94
+ @percent_from_max ||= ((1 - max_price / sell_price) * 100)
95
+ end
96
+
85
97
  def min_price
86
98
  @min_price ||= account.symbol_min_price(symbol)
87
99
  end
@@ -14,6 +14,8 @@ module Abot
14
14
  API_KEY_TABLE = BASE_CONNECTION.execute('SELECT * FROM api_key').freeze
15
15
  API_KEY = API_KEY_TABLE.first['api'].freeze
16
16
  SECRET_KEY = API_KEY_TABLE.first['secret'].freeze
17
+ TG_TOKEN = API_KEY_TABLE.first['tg_token'].freeze
18
+ TG_NAME = API_KEY_TABLE.first['tg_name'].freeze
17
19
 
18
20
  class << self
19
21
  def data_coins
@@ -25,7 +27,7 @@ module Abot
25
27
  end
26
28
 
27
29
  def data_daily_profit
28
- BASE_CONNECTION.execute("SELECT quote, sum(profit) FROM daily_profit GROUP BY quote")
30
+ BASE_CONNECTION.execute("SELECT quote, sum(profit) as sum, count(*) as count FROM daily_profit GROUP BY quote")
29
31
  end
30
32
  end
31
33
  end
@@ -5,15 +5,9 @@ module Abot
5
5
  class Coin
6
6
  module CoinDecorator
7
7
  def decorated_sell_up
8
- rounded_sell_up = sell_up.round(2)
9
- case num_averaging
10
- when 1, 2
11
- rounded_sell_up > 2 ? Paint[rounded_sell_up, :red] : rounded_sell_up
12
- when 3, 4, 5
13
- rounded_sell_up > 2 ? rounded_sell_up : Paint[rounded_sell_up, :red]
14
- else
15
- rounded_sell_up
16
- end
8
+ return '-' if sell_up == Float::INFINITY
9
+
10
+ sell_up.round(2)
17
11
  end
18
12
 
19
13
  def decorated_current_profit
@@ -38,22 +32,19 @@ module Abot
38
32
  end
39
33
 
40
34
  def decorated_next_average_price
41
- "#{next_average_price} (#{decorated_next_average_price_percent})"
35
+ next_average_price.zero? ? '-' : "#{next_average_price} (#{decorated_next_average_price_percent})"
42
36
  end
43
37
 
44
38
  def decorated_name
45
- arrow = if account.symbol_info(symbol).try(:[], :lastPrice).to_f < account.symbol_info(symbol).try(:[], :askPrice).to_f
46
- Paint[' ↑', :green]
47
- elsif account.symbol_info(symbol).try(:[], :lastPrice).to_f > account.symbol_info(symbol).try(:[], :askPrice).to_f
48
- Paint[' ↓', :red]
49
- else
50
- ''
51
- end
52
- "#{name}(#{account.symbol_info(symbol).try(:[], :priceChangePercent)}%)#{arrow}"
39
+ "#{name} (#{account.symbol_info(symbol).try(:[], :priceChangePercent)}%)#{pump}"
40
+ end
41
+
42
+ def pump
43
+ pump_detector == 'True' ? Paint[' (P)', :blue] : ''
53
44
  end
54
45
 
55
46
  def decorated_name_mobile
56
- name
47
+ "#{name} #{pump}"
57
48
  end
58
49
 
59
50
  def decorated_sell_price
@@ -64,6 +55,10 @@ module Abot
64
55
  "#{current_price} (#{percent_to_order.round(2)}%)"
65
56
  end
66
57
 
58
+ def decorated_current_price_perc_of_order
59
+ "#{current_price} (#{percent_from_order.round(2)}%)"
60
+ end
61
+
67
62
  def decorated_min_price
68
63
  "#{min_price} (#{percent_from_min_to_average.round(2)}%)"
69
64
  end
@@ -72,6 +67,10 @@ module Abot
72
67
  "#{max_price} (#{percent_to_max.round(2)}%)"
73
68
  end
74
69
 
70
+ def decorated_max_price_perc_of_order
71
+ "#{max_price} (#{percent_from_max.round(2)}%)"
72
+ end
73
+
75
74
  def decorated_current_quote
76
75
  current_quote.round(2)
77
76
  end
@@ -97,7 +96,7 @@ module Abot
97
96
  sec = timer.to_s[0..9].to_f
98
97
  return '-' if sec < 1_577_836_800 # 2020-01-01 00:00:00 +0000
99
98
 
100
- medidas = ["г", "мес", "д", "ч", "м", "c"]
99
+ medidas = %w[г мес д ч м c]
101
100
  array = [1970, 1, 1, 0, 0, 0]
102
101
  text = ''
103
102
  Time.at(Time.now.to_i - sec).utc.to_a.take(6).reverse.each_with_index do |k, i|
@@ -12,13 +12,18 @@ module Abot
12
12
  magenta
13
13
  ].freeze
14
14
 
15
- def self.daily_profit_str
15
+ def self.today_info_str
16
+ profit_array = DatabaseTable.data_daily_profit
17
+ return "Сегодня сделок не было \n" if profit_array.blank?
18
+
16
19
  profit = 'Профит сегодня:'
17
- DatabaseTable.data_daily_profit.each do |c|
20
+ transactions_count = 'Сделок '
21
+ profit_array.each do |c|
18
22
  tick_size = (c['quote'] == 'BTC' ? 7 : 2)
19
- profit += Paint[" #{c['sum(profit)'].round(tick_size)} #{c['quote']};", :green]
23
+ profit += "#{Paint[" #{c['sum'].round(tick_size)} #{c['quote']}", :green]};"
24
+ transactions_count += "#{c['quote']}: #{Paint[c['count'], :green]}; "
20
25
  end
21
- profit
26
+ "#{profit} #{transactions_count}\n"
22
27
  end
23
28
 
24
29
  def self.balance_str(account, current_coins, trade_params)
@@ -55,8 +60,54 @@ module Abot
55
60
  "#{symbol_name}: " + Paint["#{symbol[:askPrice].to_f} (#{symbol[:priceChangePercent]}%)", percent_color]
56
61
  end
57
62
 
58
- def self.check_abot
59
- Paint['WARNING: ПРОВЕРЬТЕ БОТА !!!', :black, :red] + "\n" if (Time.now - File.mtime(DatabaseTable::DB_PATH)) > 10
63
+ def self.check_abot(current_coins, telegram)
64
+ if (Time.now - File.mtime(DatabaseTable::DB_PATH)) > 40
65
+ if TelegramSender::SENDED_ERROR.blank?
66
+ TelegramSender::SENDED_ERROR[:warn_send] = true
67
+ telegram.send_message('WARNING: ПРОВЕРЬТЕ БОТА !!!') if telegram.present?
68
+ end
69
+ return Paint['WARNING: ПРОВЕРЬТЕ БОТА !!!', :black, :red] + "\n"
70
+ elsif TelegramSender::SENDED_ERROR
71
+ TelegramSender::SENDED_ERROR.clear
72
+ end
73
+
74
+ error_coins = current_coins.map { |c| c.current_price > c.sell_price ? c.name : nil }.compact
75
+ TelegramSender::SENDED_SELL_ERROR.delete_if { |key, _| !error_coins.include?(key) }
76
+
77
+ error_coins.each do |c|
78
+ if TelegramSender::SENDED_SELL_ERROR[c].to_i < 4
79
+ TelegramSender::SENDED_SELL_ERROR[c] = TelegramSender::SENDED_SELL_ERROR[c].to_i + 1
80
+ end
81
+ end
82
+
83
+ error_coins.select! { |s| TelegramSender::SENDED_SELL_ERROR[s].to_i > 2 }
84
+
85
+ return nil if error_coins.blank?
86
+
87
+ if telegram.present? &&
88
+ error_coins.find { |c| TelegramSender::SENDED_SELL_ERROR[c] == 3 }.present? &&
89
+ error_coins.find { |c| TelegramSender::SENDED_SELL_ERROR[c] == 4 }.blank?
90
+ telegram.send_message('WARNING: ПРОВЕРЬТЕ БОТА, ВОЗМОЖНО НУЖЕН РЕБУТ')
91
+ end
92
+ Paint['WARNING: ПРОВЕРЬТЕ БОТА, ВОЗМОЖНО НУЖЕН РЕБУТ', :black, :red] + "\n"\
93
+ end
94
+
95
+ def self.check_coins(account, quote_assets, telegram)
96
+ coins_without_order = account.coins_without_order(quote_assets)
97
+ TelegramSender::SENDED_LOST_COINS.delete_if { |key, _| !coins_without_order.include?(key) }
98
+
99
+ coins_without_order.each do |c|
100
+ if TelegramSender::SENDED_LOST_COINS[c].to_i < 4
101
+ TelegramSender::SENDED_LOST_COINS[c] = TelegramSender::SENDED_LOST_COINS[c].to_i + 1
102
+ end
103
+ end
104
+
105
+ coins_without_order.select! { |s| TelegramSender::SENDED_LOST_COINS[s].to_i > 2 }
106
+
107
+ return nil if coins_without_order.blank?
108
+
109
+ telegram.send_lost_coins(coins_without_order) if telegram.present?
110
+ Paint["Монеты без ордера: #{coins_without_order.join(', ')}", :black, :red] + "\n"\
60
111
  end
61
112
  end
62
113
  end
@@ -6,7 +6,7 @@ module Abot
6
6
  class Table < Terminal::Table
7
7
  include Abot::Info::Helpers
8
8
 
9
- attr_reader :current_coins, :account, :rate_coins, :columns, :trade_params
9
+ attr_reader :current_coins, :account, :rate_coins, :columns, :trade_params, :telegram
10
10
 
11
11
  ALL_HEADINGS = {
12
12
  name: 'Coin',
@@ -22,6 +22,8 @@ module Abot
22
22
  potential_profit: "Пот.\nпрофит",
23
23
  buy_date: "Дата покупки",
24
24
  timer: 'Время',
25
+ current_price_perc_of_order: 'Тек.цена',
26
+ max_price_perc_of_order: 'Максимум 24h',
25
27
  }.freeze
26
28
  HEADINGS_COINS_TABLE_DEFAULT = %i[
27
29
  name
@@ -55,12 +57,13 @@ module Abot
55
57
  @rate_coins = options.fetch(:rate_coins, [])
56
58
  @trade_params ||= DatabaseTable.data_settings
57
59
  @current_coins = Coin.current_coins(account, trade_params)
58
-
60
+ @telegram = Info::TelegramSender.new if options[:telegram_enable] == 'true'
59
61
 
60
62
  options = {
61
63
  headings: columns.map { |h| { value: ALL_HEADINGS[h], alignment: :center } },
62
64
  style: { border_x: '=' }
63
65
  }
66
+
64
67
  super options
65
68
  end
66
69
 
@@ -95,11 +98,12 @@ module Abot
95
98
  end
96
99
 
97
100
  def info_str
98
- "#{Helpers.check_abot}" \
99
- "#{Helpers.daily_profit_str}\n" \
100
- "#{Helpers.balance_str(account, current_coins, trade_params)}\n" \
101
- "#{Helpers.potential_balance_str(account, current_coins, trade_params)}\n" \
102
- "#{rate_coins_str}"
101
+ "#{Helpers.check_coins(account, trade_params["quote_asset"].split(' '), telegram)}" \
102
+ "#{Helpers.check_abot(current_coins, telegram)}" \
103
+ "#{Helpers.today_info_str}" \
104
+ "#{Helpers.balance_str(account, current_coins, trade_params)}\n" \
105
+ "#{Helpers.potential_balance_str(account, current_coins, trade_params)}\n" \
106
+ "#{rate_coins_str}"
103
107
  end
104
108
 
105
109
  def rate_coins_str
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abot
4
+ module Info
5
+ class TelegramSender
6
+ attr_reader :chat_id, :token
7
+ SENDED_LOST_COINS = {}
8
+ SENDED_ERROR = {}
9
+ SENDED_SELL_ERROR = {}
10
+
11
+ def initialize
12
+ @chat_id = DatabaseTable::TG_NAME
13
+ @token = DatabaseTable::TG_TOKEN
14
+ end
15
+
16
+ def send_message(text)
17
+ Telegram::Bot::Client.run(token) do |bot|
18
+ message = bot.api.send_message(chat_id: chat_id, text: text)
19
+ if message['ok'] == true
20
+ bot.api.pin_chat_message(chat_id: chat_id, message_id: message.dig('result', 'message_id'))
21
+ end
22
+ end
23
+ end
24
+
25
+ def send_lost_coins(coins_without_order)
26
+ coins_without_order.each do |coin|
27
+ send_message("WARNING обнаружена монета без ордера: #{coin}") if SENDED_LOST_COINS[coin].to_i == 3
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Abot
4
4
  module Info
5
- VERSION = '0.1.1'
5
+ VERSION = '0.2.8'
6
6
  end
7
7
  end
data/lib/abot/info.rb CHANGED
@@ -5,12 +5,14 @@ require 'sqlite3'
5
5
  require 'terminal-table'
6
6
  require 'paint'
7
7
  require 'binance-ruby'
8
+ require 'telegram/bot'
8
9
 
9
10
  require_relative 'info/option_parser'
10
11
  require_relative 'info/coin'
11
12
  require_relative 'info/binance_account'
12
13
  require_relative 'info/table'
13
14
  require_relative 'info/version'
15
+ require_relative 'info/telegram_sender'
14
16
 
15
17
  module Abot
16
18
  module Info
@@ -43,6 +45,8 @@ module Abot
43
45
  " timer: Время с покупки\n" \
44
46
  " current_profit: Текущая прибыль\n" \
45
47
  " potential_profit: Потенциальная прибыль\n",
48
+ " current_price_perc_of_order: Текущая цена (подсчет процента от ордера за продажу)\n" \
49
+ " max_price_perc_of_order: Максимальная цена за 24ч (подсчет процента от ордера за продажу)\n" \
46
50
  )
47
51
  parser.add_option(
48
52
  :del, '--del=COLUMN1,COLUMN2,COLUMN3',
@@ -60,6 +64,8 @@ module Abot
60
64
  " timer: Время с покупки\n" \
61
65
  " current_profit: Текущая прибыль\n" \
62
66
  " potential_profit: Потенциальная прибыль\n",
67
+ " current_price_perc_of_order: Текущая цена (подсчет процента от ордера за продажу)\n" \
68
+ " max_price_perc_of_order: Максимальная цена за 24ч (подсчет процента от ордера за продажу)\n"
63
69
  )
64
70
  parser.add_option(
65
71
  :db_path, '--db_path=DB_PATH',
@@ -70,11 +76,19 @@ module Abot
70
76
  :symbols, '--symbols=SYMBOL1,SYMBOL2,SYMBOL3',
71
77
  'Пары для отображения курсов',
72
78
  )
79
+ parser.add_option(
80
+ :telegram_enable, '--telegram_enable=true',
81
+ 'Отправка в телеграм канал справочной информации',
82
+ )
83
+ parser.add_option(
84
+ :update_time, '--update_time=SECONDS',
85
+ 'Период обновления информации, секунд, мин. 10',
86
+ )
73
87
  end.final!
74
88
 
75
89
  require_relative 'info/database_table'
76
90
 
77
- start_stats({ rate_coins: rate_coins, columns: columns })
91
+ start_stats({ rate_coins: rate_coins, columns: columns, telegram_enable: telegram_enable, update_time: update_time })
78
92
  end
79
93
 
80
94
  def start_stats(opts)
@@ -88,7 +102,7 @@ module Abot
88
102
  puts "ERROR: #{e.message}"
89
103
  end
90
104
 
91
- sleep 10
105
+ sleep update_time
92
106
  end
93
107
  end
94
108
 
@@ -102,6 +116,10 @@ module Abot
102
116
  @template ||= Info::OptionParser.instance.options[:template]
103
117
  end
104
118
 
119
+ def telegram_enable
120
+ @telegram_enable ||= Info::OptionParser.instance.options[:telegram_enable]
121
+ end
122
+
105
123
  def columns
106
124
  add = Info::OptionParser.instance.options[:add]&.split(',')&.map { |m| m.to_sym } || []
107
125
  del = Info::OptionParser.instance.options[:del]&.split(',')&.map { |m| m.to_sym } || []
@@ -121,6 +139,11 @@ module Abot
121
139
  def binance_account
122
140
  BinanceAccount.new(DatabaseTable::API_KEY, DatabaseTable::SECRET_KEY)
123
141
  end
142
+
143
+ def update_time
144
+ sec = Info::OptionParser.instance.options[:update_time].to_i
145
+ sec > 10 ? sec : 10
146
+ end
124
147
  end
125
148
  end
126
149
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abot-info
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - w_dmitrii
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-21 00:00:00.000000000 Z
11
+ date: 2021-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 1.3.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: telegram-bot-ruby
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.16.0
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.16.0
125
139
  description:
126
140
  email:
127
141
  - wiz.work2021@gmail.com
@@ -146,6 +160,7 @@ files:
146
160
  - lib/abot/info/helpers.rb
147
161
  - lib/abot/info/option_parser.rb
148
162
  - lib/abot/info/table.rb
163
+ - lib/abot/info/telegram_sender.rb
149
164
  - lib/abot/info/version.rb
150
165
  - spec/abot/statistics_spec.rb
151
166
  homepage: