kanal-interfaces-telegram 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 214fdfb6f4940364c3169b9db39c19276bb9c435ac0204f81b7a2943fb90b1ed
4
- data.tar.gz: 97f7f66f82039c0722ba552a8929739a04fa2b8f6e78a8142a6ec44bdbd4babe
3
+ metadata.gz: e2099dcf092fbe8f08c3d7238fce49192a5b473ee0cf9d3768fddc2831cfc444
4
+ data.tar.gz: 01f5d546c65176738d3e4b06ea526e906a63bfd78db53f774eb24a0e085a9afd
5
5
  SHA512:
6
- metadata.gz: 8257d35fc51f48850dcf32707c92b25449470c121c28096178a19433cb62f33f2c89fd6f3dbea9934542de2d23d033ef12c6a4a8e44d9573cf68da3264bd8e34
7
- data.tar.gz: 134c37797653dec0f74baa42e7e6db3a2ffbc238451bd55d607e74f9cc992f9a8ed0e5b71711bbaa1725980ea2ea55c38a8698ee59dd08b44b839e9eeea5a1e8
6
+ metadata.gz: 27db3b2693ac6ce49f93c85d82cf0c52f2dc8943c4b366952fb7c53a70c7d6643aca915120b1168fce7edee95b6418ad07d08461e340c59a8a1878a92250b152
7
+ data.tar.gz: 4b9691fa2117d2fc0b68ab2e45517ece35d9db66662270a843c0c9d6765d8b916beaad0408260ebf817048b9cb796d35dff3e6e527971f375126b82149b24d49
data/CHANGELOG.md CHANGED
@@ -1,10 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.2.0] - 2023-01-30
3
+ ## [0.3.1] - 2023-03-31
4
+ - Fixed parsing link for file attachments. Now file attachments parsing works
4
5
 
5
- - Library now can send images via .tg_image_path
6
- - Populating separate field in input
7
- - Using output.tg_chat_id and not the one inside interface, this is preparations for future sending outputs in separate methods... Probably
6
+ ## [0.3.0] - 2023-03-10
7
+ - Reworked interface with the new Kanal release, now it uses Interface base class properly
8
8
 
9
9
  ## [0.1.0] - 2022-11-21
10
10
 
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ gem "rake", "~> 13.0"
9
9
 
10
10
  gem "rspec", "~> 3.0"
11
11
 
12
- gem "kanal"
12
+ gem "kanal", "0.4.3"
13
13
 
14
14
  group :development do
15
15
  gem "rubocop", "~> 1.21"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kanal-interfaces-telegram (0.2.1)
4
+ kanal-interfaces-telegram (0.3.1)
5
5
  telegram-bot-ruby
6
6
 
7
7
  GEM
@@ -31,7 +31,7 @@ GEM
31
31
  ice_nine (0.11.2)
32
32
  jaro_winkler (1.5.4)
33
33
  json (2.6.3)
34
- kanal (0.3.0)
34
+ kanal (0.4.3)
35
35
  kramdown (2.4.0)
36
36
  rexml
37
37
  kramdown-parser-gfm (1.1.0)
@@ -39,6 +39,8 @@ GEM
39
39
  multipart-post (2.3.0)
40
40
  nokogiri (1.14.0-x86_64-darwin)
41
41
  racc (~> 1.4)
42
+ nokogiri (1.14.0-x86_64-linux)
43
+ racc (~> 1.4)
42
44
  parallel (1.22.1)
43
45
  parser (3.2.0.0)
44
46
  ast (~> 2.4.1)
@@ -118,9 +120,10 @@ GEM
118
120
 
119
121
  PLATFORMS
120
122
  x86_64-darwin-21
123
+ x86_64-linux
121
124
 
122
125
  DEPENDENCIES
123
- kanal
126
+ kanal (= 0.4.3)
124
127
  kanal-interfaces-telegram!
125
128
  rake (~> 13.0)
126
129
  rspec (~> 3.0)
@@ -131,4 +134,4 @@ DEPENDENCIES
131
134
  yard
132
135
 
133
136
  BUNDLED WITH
134
- 2.3.19
137
+ 2.4.5
data/README.md CHANGED
@@ -1,8 +1,14 @@
1
1
  # Kanal::Interfaces::Telegram
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/kanal/interfaces/telegram`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Welcome to Telegram interface!
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Integrate this interface into your Kanal app workflow and it will handle the incoming messages containing plain text or media (images, audio, videos, documents). You can attach media to your responses as well.
6
+
7
+ This interface relies on telegram-bot-ruby wrapper (https://github.com/atipugin/telegram-bot-ruby) to handle the actual communication with Telegram API.
8
+
9
+ Upon receiving a message or callback from end-user through telegram-bot-ruby, Telegram interface will transform incoming data into Kanal input with specific Telegram properties and feed it to router. Router will form an output (or outputs), which will be sent to Telegram interface. Telegram interface will send a message (or messages) through telegram-bot-ruby wrapper to end-user.
10
+
11
+ It is advised to use Telegram interface with Telegram bridge which converts specific input/output properties to standard Kanal properties.
6
12
 
7
13
  ## Installation
8
14
 
@@ -16,7 +22,48 @@ If bundler is not being used to manage dependencies, install the gem by executin
16
22
 
17
23
  ## Usage
18
24
 
19
- TODO: Write usage instructions here
25
+ 1. Create instance of Core:
26
+
27
+ ```core = Kanal::Core::Core.new```
28
+
29
+ 2. Create instance of Telegram interface
30
+
31
+ ```interface = Kanal::Interfaces::Telegram::TelegramInterface.new core, "YOUR_TOKEN"```
32
+
33
+ 3. You can use https://github.com/idchlife/kanal-plugins-batteries_bridge to convert Telegram interface specific properties to Kanal Batteries plugin properties. Batteries plugin properties are using generally known keywords such as :body, :image, :audio etc. More info you can get inside batteries bridge plugin repository
34
+
35
+ ```core.register_plugin Kanal::Plugins::Batteries::BatteriesPlugin.new```
36
+
37
+ 4. Add your condition packs (or use conditions provided by Batteries plugin)
38
+
39
+ ```
40
+ # Conditions need to be coded for usage in routing
41
+ core.add_condition_pack :tg_text do
42
+ add_condition :is do
43
+ with_argument
44
+ met? do |input, _core, argument| # 3 arguments provided to the block
45
+ input.tg_text == argument
46
+ end
47
+ end
48
+ end
49
+
50
+ core.router.configure do
51
+ # Response for condition created above
52
+ on :tg_text, is: "foo" do
53
+ respond do
54
+ tg_text "bar"
55
+ end
56
+ end
57
+ end
58
+
59
+ core.router.default_response do
60
+ tg_text "Default response"
61
+ end
62
+ ```
63
+
64
+ 5. Start your bot
65
+
66
+ ```interface.start```
20
67
 
21
68
  ## Development
22
69
 
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "kanal/core/core"
4
+ require "kanal/interfaces/telegram/telegram_interface"
5
+
6
+ core = Kanal::Core::Core.new
7
+
8
+ interface = Kanal::Interfaces::Telegram::TelegramInterface.new core, "replace-me-with-your-token"
9
+
10
+ core.add_condition_pack :tg_text do
11
+ add_condition :is do
12
+ with_argument
13
+ met? do |input, _core, argument|
14
+ input.tg_text == argument
15
+ end
16
+ end
17
+ end
18
+
19
+ core.router.configure do
20
+ on :tg_text, is: "foo" do
21
+ respond do
22
+ tg_text "bar"
23
+ end
24
+ end
25
+ end
26
+
27
+ core.router.default_response do
28
+ tg_text "Default response"
29
+ end
30
+
31
+ interface.start
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanal
4
+ module Interfaces
5
+ module Telegram
6
+ module Helpers
7
+ class TelegramLinkParser
8
+ def get_file_link(file_id, bot, bot_token)
9
+ file = bot.api.get_file(file_id: file_id)
10
+ file_path = file.dig('result', 'file_path')
11
+ "https://api.telegram.org/file/bot#{bot_token}/#{file_path}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -16,17 +16,22 @@ module Kanal
16
16
  end
17
17
 
18
18
  def register_parameters(core)
19
- core.register_input_parameter :tg_message, readonly: true
20
- core.register_input_parameter :tg_text, readonly: true
21
19
  core.register_input_parameter :tg_chat_id, readonly: true
22
20
  core.register_input_parameter :tg_username, readonly: true
21
+ core.register_input_parameter :tg_text, readonly: true
22
+ core.register_input_parameter :tg_button_pressed, readonly: true
23
+ core.register_input_parameter :tg_image_link, readonly: true
24
+ core.register_input_parameter :tg_audio_link, readonly: true
25
+ core.register_input_parameter :tg_video_link, readonly: true
26
+ core.register_input_parameter :tg_document_link, readonly: true
23
27
 
24
28
  core.register_output_parameter :tg_chat_id
25
29
  core.register_output_parameter :tg_text
26
- core.register_output_parameter :tg_reply_markup
27
30
  core.register_output_parameter :tg_image_path
28
31
  core.register_output_parameter :tg_audio_path
32
+ core.register_output_parameter :tg_video_path
29
33
  core.register_output_parameter :tg_document_path
34
+ core.register_output_parameter :tg_reply_markup
30
35
  end
31
36
 
32
37
  def register_hooks(core)
@@ -34,12 +39,7 @@ module Kanal
34
39
  input.source = :telegram
35
40
  end
36
41
 
37
- core.hooks.attach :input_before_router do |input|
38
- input.body = input.tg_text
39
- end
40
-
41
42
  core.hooks.attach :output_before_returned do |input, output|
42
- output.tg_text = output.body
43
43
  output.tg_chat_id = input.tg_chat_id
44
44
  end
45
45
  end
@@ -3,6 +3,7 @@
3
3
  require "kanal/core/interfaces/interface"
4
4
  require "kanal/plugins/batteries/batteries_plugin"
5
5
  require_relative "./plugins/telegram_integration_plugin"
6
+ require_relative "./helpers/telegram_link_parser"
6
7
 
7
8
  require "telegram/bot"
8
9
 
@@ -16,60 +17,138 @@ module Kanal
16
17
 
17
18
  @bot_token = bot_token
18
19
 
20
+ @bot = ::Telegram::Bot::Client.new(bot_token)
21
+
19
22
  @core.register_plugin Kanal::Plugins::Batteries::BatteriesPlugin.new
20
23
  @core.register_plugin Kanal::Interfaces::Telegram::Plugins::TelegramIntegrationPlugin.new
24
+
25
+ @link_parser = Kanal::Interfaces::Telegram::Helpers::TelegramLinkParser.new
21
26
  end
22
27
 
23
28
  def start
24
29
  ::Telegram::Bot::Client.run(@bot_token) do |bot|
25
30
  bot.listen do |message|
26
- input = @core.create_input
31
+ router.consume_input create_input message
32
+ end
33
+ end
34
+ end
27
35
 
28
- input.tg_message = message
29
- input.tg_text = message.text
30
- input.tg_chat_id = message.chat.id
31
- input.tg_username = message.try(:chat).try(:username) || input.tg_message.try(:from).try(:username)
36
+ def consume_output(output)
37
+ send_output @bot, output
38
+ end
32
39
 
33
- output = router.create_output_for_input input
40
+ def create_input(message)
41
+ input = @core.create_input
34
42
 
35
- bot.api.send_message(
36
- chat_id: output.tg_chat_id,
37
- text: output.tg_text,
38
- reply_markup: output.tg_reply_markup
39
- )
43
+ if !message.instance_variable_defined?(:@data)
44
+ # Regular message received
45
+ input.tg_text = message.text
46
+ input.tg_chat_id = message.chat.id
47
+ input.tg_username = message.chat.username || message.from.username
40
48
 
41
- image_path = output.tg_image_path
49
+ if message.photo.count > 0
50
+ # Array of images contains thumbnails, we take 3rd element to get the high-res image
51
+ input.tg_image_link = @link_parser.get_file_link message.photo[2].file_id, @bot, @bot_token
52
+ end
42
53
 
43
- if image_path && File.exist?(image_path)
44
- bot.api.send_photo(
45
- chat_id: message.chat.id,
46
- photo: Faraday::UploadIO.new(image_path, guess_mimetype(image_path))
47
- )
48
- end
54
+ if !message.audio.nil?
55
+ input.tg_audio_link = @link_parser.get_file_link message.audio.file_id, @bot, @bot_token
49
56
  end
57
+
58
+ if !message.video.nil?
59
+ input.tg_video_link = @link_parser.get_file_link message.video.file_id, @bot, @bot_token
60
+ end
61
+
62
+ if !message.document.nil?
63
+ input.tg_document_link = @link_parser.get_file_link message.document.file_id, @bot, @bot_token
64
+ end
65
+ else
66
+ # Inline button pressed
67
+ input.tg_button_pressed = message.data
68
+ input.tg_chat_id = message.from.id
69
+ input.tg_username = message.from.username
50
70
  end
71
+
72
+ input
51
73
  end
52
74
 
53
75
  private
54
76
 
77
+ def send_output(bot, output)
78
+ bot.api.send_message(
79
+ chat_id: output.tg_chat_id,
80
+ text: output.tg_text,
81
+ reply_markup: output.tg_reply_markup
82
+ )
83
+
84
+ image_path = output.tg_image_path
85
+
86
+ if !image_path.nil? && File.exist?(image_path)
87
+ bot.api.send_photo(
88
+ chat_id: output.tg_chat_id,
89
+ photo: Faraday::UploadIO.new(output.tg_image_path, guess_mimetype(output.tg_image_path))
90
+ )
91
+ end
92
+
93
+ audio_path = output.tg_audio_path
94
+
95
+ if !output.tg_audio_path.nil? && File.exist?(audio_path)
96
+ bot.api.send_audio(
97
+ chat_id: output.tg_chat_id,
98
+ audio: Faraday::UploadIO.new(output.tg_audio_path, guess_mimetype(output.tg_audio_path))
99
+ )
100
+ end
101
+
102
+ video_path = output.tg_video_path
103
+
104
+ if !output.tg_video_path.nil? && File.exist?(video_path)
105
+ bot.api.send_video(
106
+ chat_id: output.tg_chat_id,
107
+ video: Faraday::UploadIO.new(output.tg_video_path, guess_mimetype(output.tg_video_path))
108
+ )
109
+ end
110
+
111
+ document_path = output.tg_document_path
112
+
113
+ if !output.tg_document_path.nil? && File.exist?(document_path)
114
+ bot.api.send_document(
115
+ chat_id: output.tg_chat_id,
116
+ document: Faraday::UploadIO.new(output.tg_document_path, guess_mimetype(output.tg_document_path))
117
+ )
118
+ end
119
+ end
120
+
55
121
  def guess_mimetype(filename)
56
- images = {
57
- "image/jpeg" => %w[jpg jpeg],
58
- "image/png" => ["png"],
59
- "image/bmp" => ["bmp"]
60
- }
61
-
62
- # TODO: rewrite with .find or .each
63
- for pack in [images] do
64
- for mime, types in pack do
65
- for type in types do
66
- return mime if filename.include? type
122
+ media_types = [
123
+ images: {
124
+ "image/jpeg" => %w[jpg jpeg],
125
+ "image/png" => ["png"],
126
+ "image/bmp" => ["bmp"]
127
+ },
128
+ audios: {
129
+ "audio/mp3" => ["mp3"],
130
+ "audio/ogg" => ["ogg"],
131
+ "audio/vnd.wave" => ["wav"]
132
+ },
133
+ videos: {
134
+ "video/mp4" => ["mp4"],
135
+ "video/webm" => ["webm"]
136
+ },
137
+ documents: {
138
+ "application/msword" => %w[doc docx],
139
+ "application/pdf" => ["pdf"]
140
+ }
141
+ ]
142
+
143
+ media_types.each do |media_type|
144
+ media_type.each do |media_name, variant|
145
+ variant.each do |mime, extensions|
146
+ extensions.each do |extension|
147
+ return mime if filename.include? extension
148
+ end
67
149
  end
68
150
  end
69
151
  end
70
-
71
-
72
- "application/octet-stream"
73
152
  end
74
153
  end
75
154
  end
@@ -3,7 +3,7 @@
3
3
  module Kanal
4
4
  module Interfaces
5
5
  module Telegram
6
- VERSION = "0.2.1"
6
+ VERSION = "0.3.1"
7
7
  end
8
8
  end
9
9
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  require_relative "telegram/version"
4
4
 
5
+ require "kanal/core/core"
6
+ require "kanal/interfaces/telegram/telegram_interface"
7
+
5
8
  module Kanal
6
9
  module Interfaces
7
10
  module Telegram
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kanal-interfaces-telegram
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - idchlife
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-29 00:00:00.000000000 Z
11
+ date: 2023-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: telegram-bot-ruby
@@ -42,8 +42,9 @@ files:
42
42
  - LICENSE.txt
43
43
  - README.md
44
44
  - Rakefile
45
- - kanal-interfaces-telegram.gemspec
45
+ - examples/telegram_bot.rb
46
46
  - lib/kanal/interfaces/telegram.rb
47
+ - lib/kanal/interfaces/telegram/helpers/telegram_link_parser.rb
47
48
  - lib/kanal/interfaces/telegram/plugins/telegram_integration_plugin.rb
48
49
  - lib/kanal/interfaces/telegram/telegram_interface.rb
49
50
  - lib/kanal/interfaces/telegram/version.rb
@@ -56,7 +57,7 @@ metadata:
56
57
  homepage_uri: https://github.com/idchlife/kanal-interfaces-telegram
57
58
  source_code_uri: https://github.com/idchlife/kanal-interfaces-telegram
58
59
  changelog_uri: https://github.com/idchlife/kanal-interfaces-telegram
59
- post_install_message:
60
+ post_install_message:
60
61
  rdoc_options: []
61
62
  require_paths:
62
63
  - lib
@@ -72,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
73
  version: '0'
73
74
  requirements: []
74
75
  rubygems_version: 3.1.6
75
- signing_key:
76
+ signing_key:
76
77
  specification_version: 4
77
78
  summary: This library provides a Telegram interface for Kanal
78
79
  test_files: []
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/kanal/interfaces/telegram/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "kanal-interfaces-telegram"
7
- spec.version = Kanal::Interfaces::Telegram::VERSION
8
- spec.authors = ["idchlife"]
9
- spec.email = ["idchlife@gmail.com"]
10
-
11
- spec.summary = "This library provides a Telegram interface for Kanal"
12
- spec.description = "Library provides Telegram interface for Kanal. With this you can connect to telegram bot and control it"
13
- spec.homepage = "https://github.com/idchlife/kanal-interfaces-telegram"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.7.6"
16
-
17
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
-
19
- spec.metadata["homepage_uri"] = spec.homepage
20
- spec.metadata["source_code_uri"] = "https://github.com/idchlife/kanal-interfaces-telegram"
21
- spec.metadata["changelog_uri"] = "https://github.com/idchlife/kanal-interfaces-telegram"
22
-
23
- # spec.add_dependency "kanal", git: "git@github.com:idchlife/kanal.git"
24
- spec.add_dependency "telegram-bot-ruby"
25
-
26
- # Specify which files should be added to the gem when it is released.
27
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
28
- spec.files = Dir.chdir(__dir__) do
29
- `git ls-files -z`.split("\x0").reject do |f|
30
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
31
- end
32
- end
33
- spec.bindir = "exe"
34
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
35
- spec.require_paths = ["lib"]
36
-
37
- # Uncomment to register a new dependency of your gem
38
- # spec.add_dependency "example-gem", "~> 1.0"
39
-
40
- # For more information and examples about making a new gem, check out our
41
- # guide at: https://bundler.io/guides/creating_gem.html
42
- end