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 +4 -4
- data/CHANGELOG.md +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +7 -4
- data/README.md +50 -3
- data/examples/telegram_bot.rb +31 -0
- data/lib/kanal/interfaces/telegram/helpers/telegram_link_parser.rb +17 -0
- data/lib/kanal/interfaces/telegram/plugins/telegram_integration_plugin.rb +8 -8
- data/lib/kanal/interfaces/telegram/telegram_interface.rb +111 -32
- data/lib/kanal/interfaces/telegram/version.rb +1 -1
- data/lib/kanal/interfaces/telegram.rb +3 -0
- metadata +7 -6
- data/kanal-interfaces-telegram.gemspec +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2099dcf092fbe8f08c3d7238fce49192a5b473ee0cf9d3768fddc2831cfc444
|
4
|
+
data.tar.gz: 01f5d546c65176738d3e4b06ea526e906a63bfd78db53f774eb24a0e085a9afd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27db3b2693ac6ce49f93c85d82cf0c52f2dc8943c4b366952fb7c53a70c7d6643aca915120b1168fce7edee95b6418ad07d08461e340c59a8a1878a92250b152
|
7
|
+
data.tar.gz: 4b9691fa2117d2fc0b68ab2e45517ece35d9db66662270a843c0c9d6765d8b916beaad0408260ebf817048b9cb796d35dff3e6e527971f375126b82149b24d49
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
## [0.
|
3
|
+
## [0.3.1] - 2023-03-31
|
4
|
+
- Fixed parsing link for file attachments. Now file attachments parsing works
|
4
5
|
|
5
|
-
|
6
|
-
-
|
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
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kanal-interfaces-telegram (0.
|
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
|
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.
|
137
|
+
2.4.5
|
data/README.md
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
# Kanal::Interfaces::Telegram
|
2
2
|
|
3
|
-
Welcome to
|
3
|
+
Welcome to Telegram interface!
|
4
4
|
|
5
|
-
|
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
|
-
|
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
|
-
|
31
|
+
router.consume_input create_input message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
27
35
|
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
40
|
+
def create_input(message)
|
41
|
+
input = @core.create_input
|
34
42
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
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
|
-
|
44
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
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.
|
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-
|
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
|
-
-
|
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
|