telegram-bot_manager 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 72a16b3a2858985bb5158cc0625079a4770e2347d9e1f1c383bf67db3798098e
4
+ data.tar.gz: 701456b69e5edb1bb9b5a0a94c110866e663e3c6f1956e1b6c6d125220ec351e
5
+ SHA512:
6
+ metadata.gz: 8b1a91c440e7d2693f1087329e5f059b57c522541c7ccadbfe659df8ad051558cc4faf7a32c33e5b40c96e24b5d6078a0b6715d42ec997b4c072e80cce3b7767
7
+ data.tar.gz: f23240db6bf9dcf96b28bbbae74891a2e7c314b69673774da61142d3a822e199338c5f6a54e7012db89ea97b2f2874f981d2d3a32a8c885548193146dd51586e
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at v.rtsev@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in telegram-bot_manager.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,90 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ telegram-bot_manager (0.1.2)
5
+ colorize (~> 0.8.1)
6
+ i18n (~> 0.7)
7
+ logger
8
+ telegram-bot (~> 0.14.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (6.0.0)
14
+ actionview (= 6.0.0)
15
+ activesupport (= 6.0.0)
16
+ rack (~> 2.0)
17
+ rack-test (>= 0.6.3)
18
+ rails-dom-testing (~> 2.0)
19
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
20
+ actionview (6.0.0)
21
+ activesupport (= 6.0.0)
22
+ builder (~> 3.1)
23
+ erubi (~> 1.4)
24
+ rails-dom-testing (~> 2.0)
25
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
26
+ activesupport (6.0.0)
27
+ concurrent-ruby (~> 1.0, >= 1.0.2)
28
+ i18n (>= 0.7, < 2)
29
+ minitest (~> 5.1)
30
+ tzinfo (~> 1.1)
31
+ zeitwerk (~> 2.1, >= 2.1.8)
32
+ builder (3.2.3)
33
+ colorize (0.8.1)
34
+ concurrent-ruby (1.1.5)
35
+ crass (1.0.4)
36
+ diff-lcs (1.3)
37
+ erubi (1.8.0)
38
+ httpclient (2.8.3)
39
+ i18n (0.9.5)
40
+ concurrent-ruby (~> 1.0)
41
+ logger (1.4.1)
42
+ loofah (2.2.3)
43
+ crass (~> 1.0.2)
44
+ nokogiri (>= 1.5.9)
45
+ mini_portile2 (2.4.0)
46
+ minitest (5.11.3)
47
+ nokogiri (1.10.4)
48
+ mini_portile2 (~> 2.4.0)
49
+ rack (2.0.7)
50
+ rack-test (1.1.0)
51
+ rack (>= 1.0, < 3)
52
+ rails-dom-testing (2.0.3)
53
+ activesupport (>= 4.2.0)
54
+ nokogiri (>= 1.6)
55
+ rails-html-sanitizer (1.2.0)
56
+ loofah (~> 2.2, >= 2.2.2)
57
+ rake (10.5.0)
58
+ rspec (3.8.0)
59
+ rspec-core (~> 3.8.0)
60
+ rspec-expectations (~> 3.8.0)
61
+ rspec-mocks (~> 3.8.0)
62
+ rspec-core (3.8.2)
63
+ rspec-support (~> 3.8.0)
64
+ rspec-expectations (3.8.4)
65
+ diff-lcs (>= 1.2.0, < 2.0)
66
+ rspec-support (~> 3.8.0)
67
+ rspec-mocks (3.8.1)
68
+ diff-lcs (>= 1.2.0, < 2.0)
69
+ rspec-support (~> 3.8.0)
70
+ rspec-support (3.8.2)
71
+ telegram-bot (0.14.3)
72
+ actionpack (>= 4.0, < 6.1)
73
+ activesupport (>= 4.0, < 6.1)
74
+ httpclient (~> 2.7)
75
+ thread_safe (0.3.6)
76
+ tzinfo (1.2.5)
77
+ thread_safe (~> 0.1)
78
+ zeitwerk (2.1.9)
79
+
80
+ PLATFORMS
81
+ ruby
82
+
83
+ DEPENDENCIES
84
+ bundler (~> 1.16)
85
+ rake (~> 10.0)
86
+ rspec (= 3.8.0)
87
+ telegram-bot_manager!
88
+
89
+ BUNDLED WITH
90
+ 1.16.6
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 vrtsev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,329 @@
1
+ # Telegram::BotManager
2
+ [![Gem Version](https://img.shields.io/badge/gem%20version-0.1.0-brightgreen)](https://img.shields.io/badge/gem%20version-0.1.0-brightgreen)
3
+
4
+ This gem is based on https://github.com/telegram-bot-rb/telegram-bot. Follow this link for advanced usage of this gem
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'telegram-bot_manager'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install telegram-bot_manager
21
+
22
+ Require if necessary:
23
+ ```ruby
24
+ require 'telegram/bot_manager'
25
+ ```
26
+
27
+ ## Usage
28
+ ### Configuration
29
+
30
+ Configure you gem in `config/telegram_bot_manager.rb` for example
31
+
32
+ ```ruby
33
+ Telegram::BotManager.configure do |config|
34
+ config.controller_logging = true
35
+ config.show_config_message = true
36
+ config.telegram_app_owner_id = ENV['TELEGRAM_APP_OWNER_ID']
37
+ end
38
+ ```
39
+
40
+ ### Bot configuration
41
+
42
+ You can configure you main bot file with basic configuration
43
+ Create file 'my_bot.rb' in `libs/` folder:
44
+
45
+ ```ruby
46
+ require_relative 'you lib module dependencies here'
47
+
48
+ module MyBot
49
+ include Telegram::BotManager::BotClassMethods
50
+
51
+ configure do |config|
52
+ config.app_name = 'MyBot'
53
+ config.locale = 'my_bot' # Do not forget to create 'locales/my_bot.yml' file
54
+ config.localizer = Telegram::BotManager::Localizer.new(locale)
55
+ config.logger = Telegram::BotManager::BotLogger.new(app_name)
56
+ config.bot = Telegram.bots[:my_bot] # Place here your bot using 'telegram-bot' gem
57
+ end
58
+ end
59
+ ```
60
+
61
+ All this config methods will be available for calling on your module
62
+
63
+ ```ruby
64
+ MyBot.app_name # => 'MyBot'
65
+ MyBot.localizer.pick('start_message.greeting', some_param: some_value)
66
+ MyBot.logger.info('Info message that will be shown in console and writed to log file')
67
+ MyBot.bot.send_message(...)
68
+ ```
69
+
70
+ ### Application file
71
+
72
+ Create your application file in `apps/my_bot/application.rb` and inherit it from `Telegram::BotManager::Application`
73
+
74
+ ```ruby
75
+ module MyBot
76
+ class Application < Telegram::BotManager::Application
77
+
78
+ def configure
79
+ # Configure your app here
80
+ # And don't forget to call 'super'
81
+ super
82
+ end
83
+
84
+ private
85
+
86
+ def controller
87
+ # specify your bot controller
88
+ MyBot::Controller
89
+ end
90
+
91
+ def configuration_message
92
+ # Change config message here
93
+
94
+ # By default, it will show you main bot configuration info
95
+ # such as app name, telegram bot username and specified locale file
96
+ end
97
+
98
+ def startup_message
99
+ # by default will be shown '[MyBot] Application is listening messages...'
100
+ end
101
+
102
+ def handle_exception(exception)
103
+ # Any exception handling here
104
+ # You can send telegram message with exception if you want
105
+
106
+ # Telegram::BotManager::Message
107
+ # .new(Telegram.bots[:my_bot], exception.full_message.truncate(4000))
108
+ # .send_to_app_owner
109
+
110
+ # By default gem will raise exception
111
+ end
112
+ end
113
+ end
114
+ ```
115
+
116
+ ### Init and run application
117
+ Create `my_bot` file in `bin/` directory and init the application. Then run
118
+
119
+ ```ruby
120
+ MyBot::Application.new(MyBot.configuration).run
121
+ ```
122
+
123
+
124
+ ### Controller
125
+ All methods reused from `telegram-bot` gem. Basic example:
126
+
127
+ ```ruby
128
+ module MyBot
129
+ class Controller < Telegram::BotManager::Controller
130
+
131
+ # Specify redis url if you want to use 'session' feature like `session[:user_id] = user_id`
132
+ self.session_store = :redis_cache_store, { url: REDIS.id, namespace: MyBot.bot.username }
133
+
134
+ # use callbacks like in any other controllers
135
+ around_action :with_locale
136
+ before_action :sync_chat
137
+
138
+ # Every update can have one of: message, inline_query, chosen_inline_result,
139
+ # callback_query, etc.
140
+ # Define method with same name to respond to this updates.
141
+ def message(message)
142
+ message == self.payload # true
143
+ end
144
+
145
+ # Specify telegram bot commands
146
+ # Do not forget to use '!' at the end of method name
147
+ def start!
148
+ end
149
+
150
+ private
151
+
152
+ def with_locale
153
+ # 'around_action' callback code
154
+ # Use 'throw :abort' to exit from action
155
+ end
156
+
157
+ def sync_chat
158
+ # 'before_action' callback code
159
+ # Use 'throw :abort' to exit from action
160
+ end
161
+ end
162
+ ```
163
+
164
+ ### Views
165
+
166
+ Create folder `apps/my_bot/views` and place here files that is responsible for building telegram message
167
+
168
+ ```ruby
169
+ module MyBot
170
+ module Views
171
+ class StartMessage < Telegram::BotManager::View
172
+
173
+ def main_keyboard
174
+ # Specify your telegram bot keyboard data here
175
+ # Also you can use method `callback_data` to automaticaly build your callback string
176
+
177
+ markup = { inline_keyboard: [[
178
+ { text: 'First button', callback_data: callback_data(bot: 'my_bot', action: 'start!') },
179
+ { text: 'Second button', callback_data: callback_data(any_key: 'any value') }
180
+ ]]
181
+ }
182
+ end
183
+
184
+ def text
185
+ # Add message parts to 'content' attribute
186
+ content << title
187
+ end
188
+
189
+ def title
190
+ # Place any string here you want to add to message content
191
+ 'Hello, this is start message'
192
+ end
193
+
194
+ def username
195
+ # Also you can append string to base content here
196
+ # all content will be shown if you call '#message' method
197
+ content << 'some string'
198
+ end
199
+
200
+ def greeting
201
+ # You can use translations based on I18n gem here
202
+ ::MyBot.localizer.pick('start_message.greeting', user: params[:user])
203
+ end
204
+
205
+ def useful_links
206
+ callback_data(any_key: 'any value')
207
+ end
208
+
209
+ end
210
+ end
211
+ ```
212
+
213
+ And then use it in your controller actions:
214
+
215
+ ```ruby
216
+ def start!
217
+ start_message_view = MyBotBot::Views::StartMessage.new(any_key: any_value)
218
+
219
+ # start_message_view.content => Will return 'content' attribute and all appended strings
220
+ # start_message_view.text => Will call 'text' method of your view
221
+ # start_message_view.markup => Will return data from 'markup' attribute
222
+ end
223
+ ```
224
+
225
+ ### Localizer
226
+
227
+ Use localizer to pick some sample message for different variations by translator key.
228
+ By default, this gem uses 'I18n' gem with some wrapper-methods
229
+
230
+ The main convention is to write hyphenated translations so that an array of strings will be accessible by translation key. Follow this example:
231
+
232
+ Create file `my_bot.yml` in `locales/` folder of your project. Then define main key with name of your bot (the same as your file name) and write translator key with array of strings, so localizer will choose random variant:
233
+
234
+ ```yaml
235
+ my_bot:
236
+ start_message:
237
+ - "First variant %{param}"
238
+ - "Second variat %{param}"
239
+ - "Third variant %{param}"
240
+ title:
241
+ - "Translation #1"
242
+ - "..."
243
+ ```
244
+
245
+ And then you can get random translation from your locale file by using
246
+
247
+ ```ruby
248
+ ::MyBot.localizer.pick('start_message', param: some_value) # Will pick random translation
249
+ ::MyBot.localizer.samples('start_message', param: some_value) # Will return array with all translations by this key
250
+ ```
251
+
252
+ ### Logger
253
+
254
+ This gem includes custom logger with ability to write log entries both to console and log file
255
+
256
+ ```ruby
257
+ # Use BotLogger to write bot logs
258
+ logger = Telegram::BotManager::BotLogger.new('MyBot', **args) # => Will create 'MyBot.log' file in 'log/' folder and will write to STDOUT
259
+ logger.info('Bot info log message')
260
+
261
+ # Use Logger if you just want to have ability to write to STDOUT and file
262
+ logger = Telegram::BotManager::Logger.new(log_file: 'custom_logfile', **args)
263
+ ```
264
+
265
+ ### Messages
266
+
267
+ Here is present a `Message` class that gives you ability to choose destionation of message by calling corresponding method
268
+
269
+ ```ruby
270
+ message = Telegram::BotManager::Message.new(Telegram.bots[:my_bot], 'Any message text here')
271
+
272
+ message.send_to_app_owner # will send message to user whose telegram id is specified in `Telegram::BotManager.configuration.telegram_app_owner_id`
273
+ message.edit(message_id: 123, chat_id: 456, **params)
274
+ message.edit_inline(inline_message_id: 123, **params) # => Will update message with inline keyboard
275
+ message.reply(to_message_id: 123, chat_id: 456, **params)
276
+ message.send_to_chat(123, **params)
277
+ ```
278
+
279
+ ### Callback query
280
+
281
+ Its just JSON parser and JSON generator for your params that you pass in `initialize` method as hash
282
+ All your hash keys and values will be transformed to JSON string like `'{"first_key":"first_value","second_key":"second_value"}'` because telegram allows to pass only strings between actions on inline keyboards
283
+
284
+ ```ruby
285
+ new_query = Telegram::BotManager::CallbackQuery.new(first_key: 'first_value', second_key: 'second_value')
286
+ new_query.build # => 'first_key:first_value,second_key:second_value'
287
+
288
+ received_query = Telegram::BotManager::CallbackQuery.parse('{"first_key":"first_value"}"')
289
+ received_query.params # => { first_key: first_value }
290
+ ```
291
+
292
+ You can use callback query objects in your controller. Example:
293
+
294
+ ```ruby
295
+ # controller:
296
+ def callback_query(query)
297
+ query = Telegram::BotManager::CallbackQuery.parse(query)
298
+
299
+ case query.params[:bot]
300
+ when 'first_bot' then first_bot(query)
301
+ when 'second_bot' then second_bot(query)
302
+ end
303
+ end
304
+
305
+ def first_bot(query)
306
+ case query.params[:action]
307
+ when 'start!' then first_bot_start!
308
+ when 'author!' then first_bot_author!
309
+ end
310
+ end
311
+ ```
312
+
313
+ ## Development
314
+
315
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
316
+
317
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
318
+
319
+ ## Contributing
320
+
321
+ Bug reports and pull requests are welcome on GitHub at https://github.com/vrtsev/Gem-Telegram-Bot-Manager. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
322
+
323
+ ## License
324
+
325
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
326
+
327
+ ## Code of Conduct
328
+
329
+ Everyone interacting in the BotManager project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/bot_manager/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "telegram/bot_manager"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ require 'telegram/bot'
3
+ require 'colorize'
4
+
5
+ # Load main application dependencies
6
+ require "telegram/bot_manager/version.rb"
7
+ require "telegram/bot_manager/configuration.rb"
8
+ require "telegram/bot_manager/bot_configuration.rb"
9
+ require "telegram/bot_manager/logger.rb"
10
+ require "telegram/bot_manager/localizer.rb"
11
+ require "telegram/bot_manager/view.rb"
12
+ require "telegram/bot_manager/message.rb"
13
+ require "telegram/bot_manager/application.rb"
14
+ require "telegram/bot_manager/callback_query.rb"
15
+ require "telegram/bot_manager/controller.rb"
16
+ require "telegram/bot_manager/bot_class_methods.rb"
17
+
18
+ module Telegram
19
+ module BotManager
20
+
21
+ class << self
22
+ attr_accessor :configuration
23
+ end
24
+
25
+ def self.configuration
26
+ @configuration ||= Configuration.new
27
+ end
28
+
29
+ def self.configure
30
+ yield(configuration)
31
+ end
32
+
33
+ end
34
+ end
35
+
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class Application
6
+
7
+ def initialize(configuration)
8
+ @configuration = configuration
9
+ @bot = @configuration.bot
10
+
11
+ configure
12
+ configuration_message if BotManager.configuration.show_config_message
13
+ end
14
+
15
+ def configure
16
+ rescue => exception
17
+ handle_exception(exception)
18
+ end
19
+
20
+ def run
21
+ startup_message
22
+
23
+ Telegram::Bot::UpdatesPoller.start(
24
+ @bot,
25
+ controller
26
+ )
27
+ rescue => exception
28
+ handle_exception(exception)
29
+ end
30
+
31
+ private
32
+
33
+ def controller
34
+ raise "Implement method #{__method__} in your app file"
35
+ end
36
+
37
+ def configuration_message
38
+ puts <<~INFO
39
+ Application is initialized and configured
40
+ =========================================================
41
+ Configuration
42
+
43
+ App name: #{@configuration.app_name.to_s.bold.cyan}
44
+ Telegram bot username: #{@configuration.bot.username}
45
+ Locale: #{@configuration.locale}
46
+ =========================================================\n
47
+ INFO
48
+ end
49
+
50
+ def startup_message
51
+ puts "[#{@configuration.app_name}] Application is listening messages...".bold.green
52
+ end
53
+
54
+ def handle_exception(exception)
55
+ puts "[#{@configuration.app_name}] Application raised exception...".bold.red
56
+ raise exception
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ module BotClassMethods
6
+
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ attr_writer :localizer, :logger
14
+
15
+ def configuration
16
+ @configuration ||= BotConfiguration.new
17
+ end
18
+
19
+ def configure
20
+ yield(configuration)
21
+ end
22
+
23
+ def app_name
24
+ @app_name ||= configuration.app_name
25
+ end
26
+
27
+ def locale
28
+ @locale ||= configuration.locale
29
+ end
30
+
31
+ def localizer
32
+ @localizer ||= configuration.localizer
33
+ end
34
+
35
+ def logger
36
+ @logger ||= configuration.logger
37
+ end
38
+
39
+ def bot
40
+ @bot ||= configuration.bot
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class BotConfiguration
6
+
7
+ attr_accessor \
8
+ :app_name,
9
+ :locale,
10
+ :localizer,
11
+ :bot,
12
+ :logger
13
+
14
+ def initialize
15
+ @app_name = nil
16
+ @locale = nil
17
+ @localizer = nil
18
+ @logger = BotLogger.new(@app_name)
19
+ @bot = nil
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class CallbackQuery
6
+
7
+ attr_reader :params, :query
8
+
9
+ def self.parse(query_string)
10
+ params = JSON.parse(query_string)
11
+ params = params.inject(Hash.new) do |hash,(key, value)|
12
+ hash[key.to_sym] = value;
13
+ hash
14
+ end
15
+
16
+ new(params)
17
+ end
18
+
19
+ def initialize(params)
20
+ raise 'You need to pass hash to new callback query' unless params.is_a?(Hash)
21
+ @params = params
22
+ end
23
+
24
+ def build
25
+ @query = JSON.generate(@params)
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class Configuration
6
+
7
+ attr_accessor \
8
+ :controller_logging,
9
+ :show_config_message,
10
+ :telegram_app_owner_id
11
+
12
+ def initialize
13
+ @controller_logging = true
14
+ @show_config_message = true
15
+ @telegram_app_owner_id = nil
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class Controller < Telegram::Bot::UpdatesController
6
+ include Telegram::Bot::UpdatesController::MessageContext
7
+ include Telegram::Bot::UpdatesController::Session
8
+
9
+ # DO NOT FORGET TO SET SESSION STORE IN YOUR CONTROLLER
10
+ # TO USE METHODS LIKE 'session[:user_id] = user_id'
11
+ # self.session_store = :redis_cache_store, { url: redis_url }
12
+
13
+ around_action :log_action
14
+
15
+ def initialize(bot, controller, **options)
16
+ super(bot, controller, **options)
17
+ rescue => exception
18
+ rescue_with_handler(exception)
19
+ end
20
+
21
+ private
22
+
23
+ def log_action(&block)
24
+ if Telegram::BotManager.configuration.controller_logging
25
+ timer_start = Time.now
26
+
27
+ payload_data = payload['text'] || payload['data']
28
+
29
+ logger.info "\nProcessing '#{payload_data.to_s.bold.cyan}' from user #{from['id'].to_s.bold.magenta} for chat id #{chat['id']}"
30
+ logger.info "* Recognized action #{self.action_name.to_s.bold.green}"
31
+ yield
32
+ logger.info "Processing completed in #{Time.now - timer_start} sec\n"
33
+ else
34
+ yield
35
+ end
36
+ end
37
+
38
+ def rescue_with_handler(exception)
39
+ logger.error "\nException caught...".bold.red
40
+ logger.error exception.full_message
41
+
42
+ raise exception
43
+ end
44
+
45
+ def logger
46
+ unless Telegram::BotManager.configuration.controller_logging
47
+ raise 'Implement logger method in controller'
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class Localizer
6
+
7
+ attr_accessor :locale
8
+
9
+ def initialize(locale)
10
+ @locale = locale
11
+ ::I18n.locale = locale
12
+ end
13
+
14
+ def samples(path, params={})
15
+ ::I18n.t(path, params.merge(default_params))
16
+ end
17
+
18
+ def pick(path, params={})
19
+ samples(path, params).sample
20
+ end
21
+
22
+ private
23
+
24
+ def default_params
25
+ {
26
+ locale: @locale
27
+ }
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ require 'logger'
3
+
4
+ module Telegram
5
+ module BotManager
6
+ class Logger < ::Logger
7
+
8
+ LOG_DIR = 'log'
9
+
10
+ class MultiIO
11
+ def initialize(*targets)
12
+ @targets = targets.compact
13
+ end
14
+
15
+ def write(*args)
16
+ @targets.each do |target|
17
+ if target.is_a?(File)
18
+ # Remove colorization
19
+ args.map! { |a| a.gsub(/\e\[(\d+)(;\d+)*m/, '') }
20
+
21
+ target.write(*args)
22
+ target.rewind
23
+ else
24
+ target.write(*args)
25
+ end
26
+ end
27
+ end
28
+
29
+ def close
30
+ @targets.each(&:close)
31
+ end
32
+ end
33
+
34
+ class DefaultFormatter < ::Logger::Formatter
35
+ def call(severity, time, progname, msg)
36
+ "#{msg2str(msg)}\n"
37
+ end
38
+ end
39
+
40
+ def initialize(log_file: nil, **args)
41
+ $stdout.sync = true
42
+
43
+ if log_file
44
+ Dir.mkdir(LOG_DIR) unless Dir.exist?(LOG_DIR)
45
+ file = File.open("#{LOG_DIR}/#{log_file}", "a")
46
+ end
47
+
48
+ super(MultiIO.new(STDOUT, file), args)
49
+ @default_formatter = DefaultFormatter.new
50
+ end
51
+ end
52
+
53
+ class BotLogger < Logger
54
+ def initialize(app_name, **args)
55
+ super(log_file: "#{app_name}.log")
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class Message
6
+
7
+ def initialize(bot, text)
8
+ @bot = bot
9
+ @text = text
10
+
11
+ raise 'Telegram Message is blank' unless text.present?
12
+ end
13
+
14
+ def edit(message_id:, chat_id:, **params)
15
+ @bot.public_send "edit_message_text", params.merge({
16
+ text: @text,
17
+ message_id: message_id,
18
+ chat_id: chat_id
19
+ })
20
+ end
21
+
22
+ def edit_inline(inline_message_id:, **params)
23
+ @bot.public_send "edit_message_text", params.merge({
24
+ text: @text,
25
+ inline_message_id: message_id
26
+ })
27
+ end
28
+
29
+ def reply(to_message_id:, chat_id:, **params)
30
+ @bot.public_send "send_message", params.merge({
31
+ text: @text,
32
+ reply_to_message_id: to_message_id,
33
+ chat_id: chat_id
34
+ })
35
+ end
36
+
37
+ def send_to_chat(chat_id, **params)
38
+ @bot.send_message params.merge({
39
+ chat_id: chat_id,
40
+ text: @text
41
+ })
42
+ end
43
+
44
+ def send_to_app_owner(**params)
45
+ unless BotManager.configuration.telegram_app_owner_id
46
+ raise 'Telegram app owner id not defined. Check bot manager config'
47
+ end
48
+
49
+ @bot.send_message params.merge({
50
+ chat_id: BotManager.configuration.telegram_app_owner_id,
51
+ text: "[#{@bot.username}] " + @text
52
+ })
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+
6
+ VERSION = '0.1.2'.freeze
7
+
8
+ def self.gem_version
9
+ Gem::Version.new VERSION
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module BotManager
5
+ class View
6
+
7
+ attr_reader :params, :content
8
+
9
+ def initialize(params={})
10
+ raise 'You need to pass hash to new view' unless params.is_a?(Hash)
11
+
12
+ @params = params
13
+ @content = String.new
14
+ @markup = Hash.new
15
+ end
16
+
17
+ private
18
+
19
+ def callback_data(**params)
20
+ CallbackQuery.new(params).build
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "telegram/bot_manager/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "telegram-bot_manager"
8
+ spec.version = Telegram::BotManager::VERSION
9
+ spec.authors = ["Vadim Riazantsev"]
10
+ spec.email = ["v.rtsev@gmail.com"]
11
+
12
+ spec.summary = %q{Advanced instruments for building applications with multiple telegram bots}
13
+ spec.homepage = "https://github.com/vrtsev/telegram-bot-manager-ruby"
14
+ spec.license = "MIT"
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.16"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "3.8.0"
28
+ spec.add_dependency "telegram-bot", "~> 0.14.1"
29
+ spec.add_dependency "logger"
30
+ spec.add_dependency "i18n", "~> 0.7"
31
+ spec.add_dependency "colorize", "~> 0.8.1"
32
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: telegram-bot_manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Vadim Riazantsev
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-09-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 3.8.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.8.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: telegram-bot
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.14.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.14.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: logger
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: i18n
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.7'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.7'
97
+ - !ruby/object:Gem::Dependency
98
+ name: colorize
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.8.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.8.1
111
+ description:
112
+ email:
113
+ - v.rtsev@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - CODE_OF_CONDUCT.md
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bin/console
126
+ - bin/setup
127
+ - lib/telegram/bot_manager.rb
128
+ - lib/telegram/bot_manager/application.rb
129
+ - lib/telegram/bot_manager/bot_class_methods.rb
130
+ - lib/telegram/bot_manager/bot_configuration.rb
131
+ - lib/telegram/bot_manager/callback_query.rb
132
+ - lib/telegram/bot_manager/configuration.rb
133
+ - lib/telegram/bot_manager/controller.rb
134
+ - lib/telegram/bot_manager/localizer.rb
135
+ - lib/telegram/bot_manager/logger.rb
136
+ - lib/telegram/bot_manager/message.rb
137
+ - lib/telegram/bot_manager/version.rb
138
+ - lib/telegram/bot_manager/view.rb
139
+ - telegram-bot_manager.gemspec
140
+ homepage: https://github.com/vrtsev/telegram-bot-manager-ruby
141
+ licenses:
142
+ - MIT
143
+ metadata: {}
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 2.7.8
161
+ signing_key:
162
+ specification_version: 4
163
+ summary: Advanced instruments for building applications with multiple telegram bots
164
+ test_files: []