tramway-bots 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/tramway_bots_manifest.js +1 -0
  6. data/app/assets/stylesheets/tramway/bots/application.css +15 -0
  7. data/app/controllers/tramway/bots/application_controller.rb +6 -0
  8. data/app/helpers/tramway/bots/application_helper.rb +6 -0
  9. data/app/jobs/tramway/bots/application_job.rb +6 -0
  10. data/app/mailers/tramway/bots/application_mailer.rb +8 -0
  11. data/app/models/tramway/bots/application_record.rb +7 -0
  12. data/app/models/tramway/bots/bot.rb +50 -0
  13. data/app/models/tramway/bots/telegram/channel.rb +4 -0
  14. data/app/models/tramway/bots/telegram/chat.rb +12 -0
  15. data/app/models/tramway/bots/telegram/message.rb +15 -0
  16. data/app/models/tramway/bots/telegram/user.rb +37 -0
  17. data/app/models/tramway/bots/telegram/users/state.rb +6 -0
  18. data/app/models/tramway/bots/telegram/users.rb +7 -0
  19. data/app/views/layouts/tramway/bots/application.html.erb +15 -0
  20. data/config/routes.rb +2 -0
  21. data/lib/tramway/bots/engine.rb +7 -0
  22. data/lib/tramway/bots/generates/install_generator.rb +45 -0
  23. data/lib/tramway/bots/generates/templates/create_tramway_bots_bots.rb +17 -0
  24. data/lib/tramway/bots/generates/templates/create_tramway_bots_telegram_channels.rb +15 -0
  25. data/lib/tramway/bots/generates/templates/create_tramway_bots_telegram_chats.rb +17 -0
  26. data/lib/tramway/bots/generates/templates/create_tramway_bots_telegram_messages.rb +19 -0
  27. data/lib/tramway/bots/generates/templates/create_tramway_bots_telegram_users.rb +17 -0
  28. data/lib/tramway/bots/generates/templates/create_tramway_bots_telegram_users_states.rb +15 -0
  29. data/lib/tramway/bots/telegram/custom/message.rb +42 -0
  30. data/lib/tramway/bots/telegram/custom/notify/file.rb +22 -0
  31. data/lib/tramway/bots/telegram/custom/notify/text.rb +29 -0
  32. data/lib/tramway/bots/telegram/custom/notify.rb +12 -0
  33. data/lib/tramway/bots/telegram/custom/scenario.rb +17 -0
  34. data/lib/tramway/bots/telegram/custom.rb +6 -0
  35. data/lib/tramway/bots/telegram/info.rb +50 -0
  36. data/lib/tramway/bots/telegram/message.rb +42 -0
  37. data/lib/tramway/bots/telegram/messages_manager.rb +100 -0
  38. data/lib/tramway/bots/telegram.rb +6 -0
  39. data/lib/tramway/bots/version.rb +5 -0
  40. data/lib/tramway/bots.rb +10 -0
  41. metadata +82 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d462c8140b6b03f7886b70a4cd4c6149701bfc4de48ff6216d24d654a655a15c
4
+ data.tar.gz: fc46a58321fba4a96af57e7b5e68e9ac9204699f07da2ce7cdef700c3882c682
5
+ SHA512:
6
+ metadata.gz: 58c561c068af69ed6b9aa05953a89b5f5388ba49e8180e4ad6b4c92c0a0b5872958b14348f9b47e79c10e9da25435e58e6f874a19106df8275e07c58bd178562
7
+ data.tar.gz: 8dff845aef42cd104405ae3b1e3b7ffed207bab999fba665ca39c6f5d43098b8a268e4e6763b84bc7e2f7be48475232c4175215abb75fd4406da6404e8c83ed1
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Pavel Kalashnikov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Tramway::Bots
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem "tramway-bots"
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install tramway-bots
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/tramway/bots .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,6 @@
1
+ module Tramway
2
+ module Bots
3
+ class ApplicationController < ActionController::Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Tramway
2
+ module Bots
3
+ module ApplicationHelper
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Tramway
2
+ module Bots
3
+ class ApplicationJob < ActiveJob::Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ module Tramway
2
+ module Bots
3
+ class ApplicationMailer < ActionMailer::Base
4
+ default from: "from@example.com"
5
+ layout "mailer"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Tramway
2
+ module Bots
3
+ class ApplicationRecord < Tramway::Core::ApplicationRecord
4
+ self.abstract_class = true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::Bots::Bot < ApplicationRecord
4
+ has_many :scenario_steps, -> { order(:name) }, class_name: 'BotTelegram::Scenario::Step'
5
+ has_many :progress_records, through: :scenario_steps, class_name: 'BotTelegram::Scenario::ProgressRecord'
6
+ has_many :attenders, through: :progress_records, class_name: 'BotTelegram::User', source: :user
7
+ has_many :messages, class_name: 'BotTelegram::Message'
8
+ has_many :users, through: :messages, class_name: 'BotTelegram::User'
9
+
10
+ TEAMS = %i[rsm night purple_magic benchkiller].freeze
11
+
12
+ enumerize :team, in: TEAMS
13
+
14
+ TEAMS.each do |team|
15
+ scope "#{team}_scope".to_sym, lambda { |_user_id|
16
+ where team: team
17
+ }
18
+ end
19
+
20
+ store_accessor :options, :custom
21
+ store_accessor :options, :scenario
22
+
23
+ def start_step
24
+ # scenario_steps.find_by name: :start did not work for some reason. Think it's about step word in Rails
25
+ scenario_steps.select { |s| s.name == 'start' }.first
26
+ end
27
+
28
+ def finish_step
29
+ return unless team.night?
30
+
31
+ scenario_steps.finish_step
32
+ end
33
+
34
+ def finished_users
35
+ return [] unless finish_step.present?
36
+
37
+ progress_records.where(bot_telegram_scenario_step_id: finish_step.id).uniq(&:bot_telegram_user_id)
38
+ end
39
+
40
+ def new_users_between(begin_date, end_date)
41
+ users.uniq.map do |user|
42
+ first_message_created_at = user.messages.order(created_at: :asc).first.created_at
43
+ user if first_message_created_at.between?(begin_date, end_date)
44
+ end.compact
45
+ end
46
+
47
+ def uniq_users_between(begin_date, end_date)
48
+ messages.where('created_at >= ? AND created_at <= ?', begin_date, end_date).map(&:user).uniq
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::Bots::Telegram::Channel < ApplicationRecord
4
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::Bots::Telegram::Chat < ApplicationRecord
4
+ self.table_name = 'tramway_bots_telegram_chats'
5
+
6
+ has_many :messages, class_name: 'Tramway::Bots::Telegram::Message'
7
+ belongs_to :bot, class_name: 'Bot'
8
+
9
+ def private?
10
+ chat_type == 'private'
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::Bots::Telegram::Message < ApplicationRecord
4
+ self.table_name = 'tramway_bots_telegram_messages'
5
+
6
+ belongs_to :user, class_name: 'Tramway::Bots::Telegram::User', optional: true
7
+ belongs_to :bot, class_name: 'Tramway::Bots::Bot', optional: true
8
+ belongs_to :chat, class_name: 'Tramway::Bots::Telegram::Chat', optional: true
9
+
10
+ enumerize :message_type, in: %i[regular callback], default: :regular
11
+
12
+ validates :telegram_message_id, uniqueness: { scope: [ :bot_id, :chat_id ] }, allow_nil: true
13
+
14
+ search_by :text, user: %i[username first_name]
15
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::Bots::Telegram::User < ApplicationRecord
4
+ self.table_name = 'tramway_bots_telegram_users'
5
+
6
+ has_many :messages, class_name: 'Tramway::Bots::Telegram::Message'
7
+ has_many :bots, class_name: 'Tramway::Bots::Bot', through: :steps
8
+ has_many :states, class_name: 'Tramway::Bots::Telegram::Users::State'
9
+
10
+ validates :telegram_id, uniqueness: true
11
+ validates :username, uniqueness: true, allow_blank: true, allow_nil: true
12
+
13
+ search_by :first_name, :username, :last_name
14
+
15
+ scope :partner_scope, ->(_user_id) { all }
16
+ %i[rsm night purple_magic].each do |team|
17
+ scope "#{team}_scope".to_sym, lambda { |_user_id|
18
+ step_ids = Bot.where(team: team).map(&:steps).flatten.map(&:id)
19
+ records = BotTelegram::Scenario::ProgressRecord.where(bot_telegram_scenario_step_id: step_ids)
20
+ BotTelegram::User.where id: records.map(&:bot_telegram_user_id)
21
+ }
22
+ end
23
+
24
+ def current_state(bot)
25
+ states.where(bot_id: bot.id).last&.current_state
26
+ end
27
+
28
+ # rubocop:disable Naming/AccessorMethodName
29
+ def set_finished_state_for(bot:)
30
+ states.create! bot_id: bot.id, current_state: :finished
31
+ end
32
+ # rubocop:enable Naming/AccessorMethodName
33
+
34
+ def finished_state_for?(bot:)
35
+ states.empty? || states.where(bot_id: bot.id).last&.current_state == 'finished'
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::Bots::Telegram::Users::State < ApplicationRecord
4
+ belongs_to :user, class_name: 'Tramway::Bots::Telegram::User'
5
+ belongs_to :bot, class_name: 'Tramway::Bots::Bot'
6
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Bots::Telegram::Users
4
+ def self.table_name_prefix
5
+ 'tramway_bots_telegram_users_'
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Tramway bots</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "tramway/bots/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Tramway::Bots::Engine.routes.draw do
2
+ end
@@ -0,0 +1,7 @@
1
+ module Tramway
2
+ module Bots
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Tramway::Bots
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'tramway/core/generators/install_generator'
5
+
6
+ module Tramway::Bots::Generators
7
+ class InstallGenerator < ::Tramway::Core::Generators::InstallGenerator
8
+ include Rails::Generators::Migration
9
+ source_root File.expand_path('templates', __dir__)
10
+
11
+ def self.next_migration_number(path)
12
+ next_migration_number = current_migration_number(path) + 1
13
+ ActiveRecord::Migration.next_migration_number next_migration_number
14
+ end
15
+
16
+ def copy_migrations
17
+ migrations = %i[
18
+ create_tramway_bots_bots
19
+ create_tramway_bots_telegram_channels
20
+ create_tramway_bots_telegram_chats
21
+ create_tramway_bots_telegram_messages
22
+ create_tramway_bots_telegram_users
23
+ create_tramway_bots_telegram_users_states
24
+ ]
25
+
26
+ migrations.each do |migration|
27
+ migration_template "#{migration}.rb", "db/migrate/#{migration}.rb"
28
+ end
29
+ end
30
+
31
+ def copy_factories
32
+ factories = [
33
+ 'tramway/bots/telegram/messages',
34
+ 'tramway/bots/telegram/chats',
35
+ 'tramway/bots/telegram/users',
36
+ 'tramway/bots/bots'
37
+ ]
38
+
39
+ factories.each do |factory|
40
+ # TODO write generator for minitest
41
+ create_file "spec/factories/#{factory}.rb", File.read("#{File.dirname(__dir__)}/../../../spec/factories/#{factory}.rb")
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateTramwayBotsBots < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :tramway_bots_bots do |t|
6
+ t.text :name
7
+ t.text :state
8
+ t.text :team
9
+ t.text :token
10
+ t.jsonb :options
11
+ t.text :slug
12
+ t.datetime :deleted_at
13
+
14
+ t.timestamps
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateTramwayBotsTelegramChannels < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :tramway_bot_engine_telegram_channels do |t|
6
+ t.integer :bot_id
7
+ t.text :title
8
+ t.text :state
9
+ t.text :telegram_channel_id
10
+ t.datetime :deleted_at
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateTramwayBotsTelegramChats < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :tramway_bots_telegram_chats do |t|
6
+ t.text :title
7
+ t.text :chat_type
8
+ t.jsonb :options
9
+ t.text :state
10
+ t.text :telegram_chat_id
11
+ t.integer :bot_id
12
+ t.datetime :deleted_at
13
+
14
+ t.timestamps
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateTramwayBotsTelegramMessages < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :tramway_bots_telegram_messages do |t|
6
+ t.integer :chat_id
7
+ t.integer :user_id
8
+ t.text :text
9
+ t.jsonb :options
10
+ t.text :state
11
+ t.integer :bot_id
12
+ t.text :message_type, default: "regular"
13
+ t.datetime :deleted_at
14
+ t.integer :telegram_message_id
15
+
16
+ t.timestamps
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateTramwayBotsTelegramUsers < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :tramway_bots_telegram_users do |t|
6
+ t.text "first_name"
7
+ t.text "last_name"
8
+ t.text "username"
9
+ t.jsonb "options"
10
+ t.text "state"
11
+ t.text "telegram_id"
12
+ t.datetime "deleted_at"
13
+
14
+ t.timestamps
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateTramwayBotsTelegramUsersStates < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :tramway_bots_telegram_users_states do |t|
6
+ t.integer "user_id"
7
+ t.integer "bot_id"
8
+ t.text "current_state"
9
+ t.text "state"
10
+ t.datetime "deleted_at"
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'telegram/bot'
4
+
5
+ class Tramway::Bots::Telegram::Custom::Message
6
+ attr_reader :file
7
+
8
+ def initialize(text: nil, file: nil, reply_markup: nil, inline_keyboard: nil)
9
+ raise 'You set text: argument for message' unless text.present?
10
+
11
+ @text = text
12
+ @file = file
13
+ @reply_markup = reply_markup
14
+ @inline_keyboard = inline_keyboard
15
+ end
16
+
17
+ def build_options(button)
18
+ button_options = { text: button[0] }
19
+ button_options.merge! callback_data: button[1][:data].to_json if button[1][:data].present?
20
+ Telegram::Bot::Types::InlineKeyboardButton.new(**button_options)
21
+ end
22
+
23
+ def options
24
+ arguments = {}
25
+ arguments.merge!(text: @text) if @text.present?
26
+ if @reply_markup.present?
27
+ arguments.merge!(reply_markup: Telegram::Bot::Types::ReplyKeyboardMarkup.new(**@reply_markup))
28
+ elsif @inline_keyboard.present?
29
+ keyboard = @inline_keyboard.map do |button|
30
+ if button[0].is_a? Array
31
+ button.map do |b|
32
+ build_options b
33
+ end
34
+ else
35
+ build_options button
36
+ end
37
+ end
38
+ arguments.merge!(reply_markup: Telegram::Bot::Types::InlineKeyboardMarkup.new(inline_keyboard: keyboard))
39
+ end
40
+ arguments
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Bots::Telegram::Custom::Notify::File
4
+ class << self
5
+ include Tramway::Bots::Telegram::MessagesManager
6
+
7
+ def send_to_user(bot_id, username, file)
8
+ bot_record = Bot.find bot_id
9
+ bot = ::Telegram::Bot::Client.new bot_record.token
10
+ chat = ::Tramway::Bots::Telegram::Chat.where(bot_id: bot_id).find_by "options ->> 'username' = '#{username}'"
11
+ bot_message = ::Tramway::Bots::Telegram::Leopold::Message.new file
12
+ send_file bot.api, chat.telegram_chat_id, bot_message
13
+ end
14
+
15
+ def send_to_chat(bot_id, chat_id, file)
16
+ bot_record = Bot.find bot_id
17
+ bot = ::Telegram::Bot::Client.new bot_record.token
18
+ bot_message = ::Tramway::Bots::Telegram::Leopold::Message.new file
19
+ send_file bot.api, chat_id, bot_message.file
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'telegram/bot'
4
+ require 'tramway/bots/telegram/messages_manager'
5
+
6
+ module Tramway::Bots::Telegram::Custom::Notify::Text
7
+ class << self
8
+ include ::Tramway::Bots::Telegram::MessagesManager
9
+
10
+ def send_to_user(bot_id, username, message)
11
+ bot_record = Tramway::Bots::Bot.find bot_id
12
+ bot = ::Telegram::Bot::Client.new bot_record.token
13
+ chat = Tramway::Bots::Telegram::Chat.where(bot_id: bot_id).find_by "options ->> 'username' = '#{username}'"
14
+ message_to_user bot.api, message, chat.telegram_chat_id if chat.present?
15
+ end
16
+
17
+ def send_to_chat(bot_id, chat_id, message, **options)
18
+ bot_record = Tramway::Bots::Bot.find bot_id
19
+ bot = ::Telegram::Bot::Client.new bot_record.token
20
+ message_to_chat bot.api, chat_id, message, **options
21
+ end
22
+
23
+ def send_to_channel(bot_id, channel_id, message)
24
+ bot_record = Tramway::Bots::Bot.find bot_id
25
+ bot = ::Telegram::Bot::Client.new bot_record.token
26
+ message_to_user bot.api, message, channel_id
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Bots
5
+ module Telegram
6
+ module Custom
7
+ module Notify
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::Bots::Telegram::Custom::Scenario
4
+ include ::Tramway::Bots::Telegram::MessagesManager
5
+ include ::Tramway::Bots::Telegram::Info
6
+
7
+ attr_reader :bot, :bot_record, :chat, :message_from_telegram, :message, :user
8
+
9
+ def initialize(**options)
10
+ @bot = options[:bot]
11
+ @message_from_telegram = options[:message]
12
+ @bot_record = options[:bot_record]
13
+ @chat = options[:chat]
14
+ @message = options[:message_object]
15
+ @user = options[:user]
16
+ end
17
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tramway/bots/telegram'
4
+
5
+ module Tramway::Bots::Telegram::Custom
6
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Bots::Telegram::Info
4
+ def user_from(sender)
5
+ user = Tramway::Bots::Telegram::User.find_by telegram_id: sender.id
6
+ params = {
7
+ username: sender.username,
8
+ first_name: sender.first_name,
9
+ last_name: sender.last_name,
10
+ project_id: Project.find_by(title: 'PurpleMagic').id,
11
+ options: {
12
+ can_join_groups: sender.can_join_groups,
13
+ can_read_all_group_messages: sender.can_read_all_group_messages,
14
+ language_code: sender.language_code,
15
+ supports_inline_queries: sender.supports_inline_queries,
16
+ is_bot: sender.is_bot
17
+ }
18
+ }
19
+ if user.present?
20
+ user.update! params
21
+ user.reload
22
+ else
23
+ Tramway::Bots::Telegram::User.create! telegram_id: sender.id, **params
24
+ end
25
+ end
26
+
27
+ def chat_from(message_chat, bot_record)
28
+ chat = Tramway::Bots::Telegram::Chat.find_or_create_by! telegram_chat_id: message_chat.id, bot_id: bot_record.id
29
+ chat.update! title: message_chat.title,
30
+ bot_id: bot_record.id,
31
+ chat_type: message_chat.type,
32
+ project_id: Project.find_by(title: 'PurpleMagic').id,
33
+ options: (%i[
34
+ all_members_are_administrators can_set_sticker_set description first_name invite_link
35
+ last_name permissions photo pinned_message slow_mode_delay sticker_set_name
36
+ username
37
+ ].reduce({}) do |hash, attribute|
38
+ hash.merge! attribute => message_chat.send(attribute)
39
+ end)
40
+ chat.reload
41
+ end
42
+
43
+ def channel_from(channel, bot_record)
44
+ channel_record = Tramway::Bots::Telegram::Channel.find_or_create_by! telegram_channel_id: channel.id
45
+ channel_record.update! title: channel.title,
46
+ bot_id: bot_record.id,
47
+ project_id: Project.find_by(title: 'PurpleMagic').id
48
+ channel_record.reload
49
+ end
50
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'telegram/bot'
4
+
5
+ class BotTelegram::Custom::Message
6
+ attr_reader :file
7
+
8
+ def initialize(text: nil, file: nil, reply_markup: nil, inline_keyboard: nil)
9
+ raise 'You set text: argument for message' unless text.present?
10
+
11
+ @text = text
12
+ @file = file
13
+ @reply_markup = reply_markup
14
+ @inline_keyboard = inline_keyboard
15
+ end
16
+
17
+ def build_options(button)
18
+ button_options = { text: button[0] }
19
+ button_options.merge! callback_data: button[1][:data].to_json if button[1][:data].present?
20
+ Telegram::Bot::Types::InlineKeyboardButton.new(**button_options)
21
+ end
22
+
23
+ def options
24
+ arguments = {}
25
+ arguments.merge!(text: @text) if @text.present?
26
+ if @reply_markup.present?
27
+ arguments.merge!(reply_markup: Telegram::Bot::Types::ReplyKeyboardMarkup.new(**@reply_markup))
28
+ elsif @inline_keyboard.present?
29
+ keyboard = @inline_keyboard.map do |button|
30
+ if button[0].is_a? Array
31
+ button.map do |b|
32
+ build_options b
33
+ end
34
+ else
35
+ build_options button
36
+ end
37
+ end
38
+ arguments.merge!(reply_markup: Telegram::Bot::Types::InlineKeyboardMarkup.new(inline_keyboard: keyboard))
39
+ end
40
+ arguments
41
+ end
42
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Bots::Telegram::MessagesManager
4
+ def log_message(message, user, chat, bot)
5
+ file_path = "#{Rails.root}/lib/tasks/bot_telegram/bot_message_attributes.yml"
6
+ telegram_message_attributes = YAML.load_file(file_path)['telegram_message']['attributes']
7
+
8
+ message_object = Tramway::Bots::Telegram::Message.find_or_create_by(
9
+ telegram_message_id: message.message_id,
10
+ bot_id: bot.id,
11
+ user_id: user.id,
12
+ chat_id: chat.id
13
+ )
14
+
15
+ message_object.update! text: message.try(:text),
16
+ project_id: Project.find_by(title: 'PurpleMagic').id,
17
+ options: (telegram_message_attributes.reduce({}) do |hash, attribute|
18
+ hash.merge! attribute => message.send(attribute)
19
+ end)
20
+
21
+ message_object
22
+ end
23
+
24
+ # :reek:FeatureEnvy { enabled: false }
25
+ def message_to_chat(bot_api, chat_id, message_obj, **options)
26
+ case message_obj.class.to_s
27
+ when 'String'
28
+ send_string bot_api, chat_id, message_obj, **options
29
+ when 'Tramway::Bots::Telegram::Custom::Message'
30
+ bot_api.send_message chat_id: chat_id, **message_obj.options.merge(options)
31
+ send_file bot_api, chat_id, message_obj if message_obj.file.present?
32
+ else
33
+ raise message_obj.class.to_s
34
+ end
35
+ rescue StandardError => error
36
+ Airbrake.notify error
37
+ end
38
+ # :reek:FeatureEnvy { enabled: true }
39
+
40
+ def message_to_user(bot_api, message_obj, chat_id)
41
+ case message_obj.class.to_s
42
+ when 'String'
43
+ send_string bot_api, chat_id, message_obj
44
+ when 'Tramway::Bots::Telegram::Scenario::Step'
45
+ send_scenario_step bot_api, chat_id, message_obj
46
+ when 'Tramway::Bots::Telegram::Custom::Message'
47
+ bot_api.send_message chat_id: chat_id, **message_obj.options
48
+ end
49
+ rescue StandardError => error
50
+ Airbrake.notify error
51
+ end
52
+
53
+ def send_file(bot_api, chat_id, message_obj)
54
+ mime_type = case message_obj.file.file.file[-3..].downcase
55
+ when 'jpg', 'png'
56
+ [:photo, 'image/jpeg']
57
+ when 'mp3'
58
+ [:voice, 'audio/mpeg']
59
+ end
60
+ params = {
61
+ chat_id: chat_id,
62
+ mime_type[0] => Faraday::UploadIO.new(message_obj.file.file.file, mime_type[1])
63
+ }
64
+ if message_obj.reply_markup.present?
65
+ params.merge!(
66
+ reply_markup: Telegram::Bot::Types::ReplyKeyboardMarkup.new(**message_obj.reply_markup),
67
+ parse_mode: :markdown
68
+ )
69
+ end
70
+
71
+ bot_api.public_send "send_#{mime_type[0]}", **params
72
+ end
73
+
74
+ private
75
+
76
+ def send_string(bot_api, chat_id, message_obj, **options)
77
+ sleep 1
78
+ bot_api.send_message(
79
+ chat_id: chat_id,
80
+ text: message_obj,
81
+ **options
82
+ )
83
+ end
84
+
85
+ def send_scenario_step(bot_api, chat_id, message_obj)
86
+ if message_obj.try(:text).present?
87
+ if message_obj.reply_markup.present?
88
+ bot_api.send_message(
89
+ chat_id: chat_id,
90
+ text: message_obj&.text,
91
+ reply_markup: Telegram::Bot::Types::ReplyKeyboardMarkup.new(**message_obj.reply_markup),
92
+ parse_mode: :markdown
93
+ )
94
+ else
95
+ bot_api.send_message chat_id: chat_id, text: message_obj.text, parse_mode: :markdown
96
+ end
97
+ end
98
+ send_file bot_api, chat_id, message_obj if message_obj.file.path.present?
99
+ end
100
+ end
@@ -0,0 +1,6 @@
1
+ module Tramway
2
+ module Bots
3
+ module Telegram
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Tramway
2
+ module Bots
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ require "tramway/bots/version"
2
+ require "tramway/bots/engine"
3
+ require 'tramway/bots/generates/install_generator'
4
+ require 'tramway/bots/telegram/custom'
5
+ require 'tramway/bots/telegram/info'
6
+
7
+ module Tramway
8
+ module Bots
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tramway-bots
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Pavel Kalashnikov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - kalashnikovisme@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - MIT-LICENSE
21
+ - README.md
22
+ - Rakefile
23
+ - app/assets/config/tramway_bots_manifest.js
24
+ - app/assets/stylesheets/tramway/bots/application.css
25
+ - app/controllers/tramway/bots/application_controller.rb
26
+ - app/helpers/tramway/bots/application_helper.rb
27
+ - app/jobs/tramway/bots/application_job.rb
28
+ - app/mailers/tramway/bots/application_mailer.rb
29
+ - app/models/tramway/bots/application_record.rb
30
+ - app/models/tramway/bots/bot.rb
31
+ - app/models/tramway/bots/telegram/channel.rb
32
+ - app/models/tramway/bots/telegram/chat.rb
33
+ - app/models/tramway/bots/telegram/message.rb
34
+ - app/models/tramway/bots/telegram/user.rb
35
+ - app/models/tramway/bots/telegram/users.rb
36
+ - app/models/tramway/bots/telegram/users/state.rb
37
+ - app/views/layouts/tramway/bots/application.html.erb
38
+ - config/routes.rb
39
+ - lib/tramway/bots.rb
40
+ - lib/tramway/bots/engine.rb
41
+ - lib/tramway/bots/generates/install_generator.rb
42
+ - lib/tramway/bots/generates/templates/create_tramway_bots_bots.rb
43
+ - lib/tramway/bots/generates/templates/create_tramway_bots_telegram_channels.rb
44
+ - lib/tramway/bots/generates/templates/create_tramway_bots_telegram_chats.rb
45
+ - lib/tramway/bots/generates/templates/create_tramway_bots_telegram_messages.rb
46
+ - lib/tramway/bots/generates/templates/create_tramway_bots_telegram_users.rb
47
+ - lib/tramway/bots/generates/templates/create_tramway_bots_telegram_users_states.rb
48
+ - lib/tramway/bots/telegram.rb
49
+ - lib/tramway/bots/telegram/custom.rb
50
+ - lib/tramway/bots/telegram/custom/message.rb
51
+ - lib/tramway/bots/telegram/custom/notify.rb
52
+ - lib/tramway/bots/telegram/custom/notify/file.rb
53
+ - lib/tramway/bots/telegram/custom/notify/text.rb
54
+ - lib/tramway/bots/telegram/custom/scenario.rb
55
+ - lib/tramway/bots/telegram/info.rb
56
+ - lib/tramway/bots/telegram/message.rb
57
+ - lib/tramway/bots/telegram/messages_manager.rb
58
+ - lib/tramway/bots/version.rb
59
+ homepage: https://github.com/Purple-Magic/tramway-bots
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.1.6
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Rails Engine for bot management
82
+ test_files: []