tdlib-ruby 0.9.4 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.gitmodules +0 -0
- data/.travis.yml +6 -3
- data/ChangeLog.md +19 -0
- data/README.md +60 -41
- data/bin/build +12 -0
- data/lib/tdlib-ruby.rb +5 -2
- data/lib/tdlib/api.rb +20 -15
- data/lib/tdlib/client.rb +144 -141
- data/lib/tdlib/errors.rb +29 -5
- data/lib/tdlib/update_handler.rb +39 -0
- data/lib/tdlib/update_manager.rb +24 -21
- data/lib/tdlib/version.rb +1 -1
- data/spec/integration/tdlib_spec.rb +28 -22
- data/tdlib-ruby.gemspec +7 -13
- metadata +60 -16
- data/lib/tdlib/utils.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 06b622d125c84301dcd3113ab5e028fb076922307dea8362688dff32941355fd
|
4
|
+
data.tar.gz: 828a68e3d8322d8cd642e4b978069d07caa5fc82658f08752ee906468a508292
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67cbfcacfe6e972565006967a0ed354d93107ceaf0d521c4e08f919beedd7bfc797a862da9ce01d62d76302693f7220952474e99dc2edb7c5ed14e2b729c8575
|
7
|
+
data.tar.gz: 97afca505d4d80f87a43412570f3e982c65826db05d4ec0850d4a6d9300ffcf305e79468cf655082c1afadfa6c6d3f864b49c56cabc6d559b8f18d09598b38be
|
data/.gitignore
CHANGED
data/.gitmodules
ADDED
File without changes
|
data/.travis.yml
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.
|
4
|
-
- 2.
|
3
|
+
- 2.6.7
|
4
|
+
- 2.7.3
|
5
|
+
- 3.0.1
|
6
|
+
|
5
7
|
addons:
|
6
8
|
apt:
|
7
9
|
sources:
|
@@ -19,8 +21,9 @@ env:
|
|
19
21
|
global:
|
20
22
|
secure: DmAoRsr+dTPVNs486nBXzChjzCCVdoxfmSbvqMBBl0v8uuUIZD1rSfYKcEaL5pmE7vgYq3X+3Dk0gf4ef/p2xPVKqFKrkBiF/7t06WgQTH7003gHMLq3aC7R9+1xvqJDzpoc6UB59Y1fOJBe5YfqDuw1dT9a46tzY2uzoVpEpbN8M/hssaKf6Wuzvpz5yekFeXq2raPwi3aOqvkSG+ODoacVdYQgJ4Vn0//CI2HzWijkQCvdsefWQUKkbgtuLWRp3UNy8AEhVWzQnTcSM7oc+MwMsOI/90DZkTP5n2WJl/CFTM5b70VyrIciG92SvTAhhBo/p7t3QBJa6kJMPXAHh5q+3wqVQA411+CoVF48bO5rKjKY3Ply49uqAzVJRh+Tkhf5uC1pHiZ6QKGxu1Czde+mKItBpaDmJFmQi0CSdv2WYXLnJWOQIO6vc2P3liwpMDRDyaGWOQtUYS+gHAlRbD4NPycIkGjkcjmLMqSEEO1TdCpM+CYwTvNTkRS+9HrWXZNdEfWORDYHgYohoIP6kY6XWSgunUb6F6pVxLoPWJNEBEVuIMZeOa/s9oklxBzD5XXIzBx4QsPYanvfxoN1uOcXlBXbOGqwiqb+urokNDw+BzWhbA+xY03U2+yO0Ujh3HQDyMDtrXEQfaPC0SxpEvIINVYwznG4sMKvbOaCVSo=
|
21
23
|
before_install:
|
24
|
+
- gem install -v 2.1.2 bundler
|
22
25
|
- set -e
|
23
|
-
- git clone https://github.com/tdlib/td
|
26
|
+
- git clone https://github.com/tdlib/td.git
|
24
27
|
- cd td
|
25
28
|
- mkdir -p build
|
26
29
|
- cd build
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
### 2.1.0 / 2019-10-18
|
2
|
+
|
3
|
+
* Support tdlib 1.5
|
4
|
+
* Fix TD::Client#dispose race condition and client crash
|
5
|
+
|
6
|
+
### 2.0.0 / 2019-02-08
|
7
|
+
|
8
|
+
* Generated types and client functions
|
9
|
+
* Async handlers
|
10
|
+
* Use ffi instead of fiddle
|
11
|
+
* Use Concurrent::Promises
|
12
|
+
* TD errors handling in promises
|
13
|
+
* Add use_file_database setting to config
|
14
|
+
|
15
|
+
### 1.0.0 / 2018-05-27
|
16
|
+
|
17
|
+
* Return promises from TD::Client#broadcast
|
18
|
+
* Add #fetch as alias to #broadcast_and_receive
|
19
|
+
|
1
20
|
### 0.9.4 / 2018-05-16
|
2
21
|
|
3
22
|
* Fix recursive locking in nested handlers
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# tdlib-ruby
|
2
2
|
|
3
|
-
[](https://codeclimate.com/github/centosadmin/tdlib-ruby/maintainability) [](https://codeclimate.com/github/centosadmin/tdlib-ruby/maintainability) [](https://travis-ci.org/centosadmin/tdlib-ruby)
|
4
4
|
|
5
5
|
## Description
|
6
6
|
|
@@ -8,7 +8,7 @@ Ruby bindings and client for TDLib (Telegram database library).
|
|
8
8
|
|
9
9
|
## Requirements
|
10
10
|
|
11
|
-
* Ruby 2.
|
11
|
+
* Ruby 2.4+
|
12
12
|
* Compiled [tdlib](https://github.com/tdlib/td)
|
13
13
|
|
14
14
|
We have precompiled versions for CentOS 6 & 7 in our repositories:
|
@@ -23,6 +23,15 @@ http://rpms.southbridge.ru/rhel7/stable/SRPMS/
|
|
23
23
|
|
24
24
|
http://rpms.southbridge.ru/rhel6/stable/SRPMS/
|
25
25
|
|
26
|
+
## Compatibility table
|
27
|
+
|
28
|
+
| Gem Version | | tdlib version |
|
29
|
+
|:-------------:|:-:| :-----------: |
|
30
|
+
| 1.x | → | 1.0 - 1.2 |
|
31
|
+
| 2.0 | → | 1.3 |
|
32
|
+
| 2.1 | → | 1.5 |
|
33
|
+
| 2.2 | → | 1.6 |
|
34
|
+
|
26
35
|
## Install
|
27
36
|
|
28
37
|
Add to your gemfile:
|
@@ -35,7 +44,7 @@ and run *bundle install*.
|
|
35
44
|
|
36
45
|
Or just run *gem install tdlib-ruby*
|
37
46
|
|
38
|
-
## Basic example
|
47
|
+
## Basic authentication example
|
39
48
|
|
40
49
|
```ruby
|
41
50
|
require 'tdlib-ruby'
|
@@ -54,52 +63,53 @@ client = TD::Client.new
|
|
54
63
|
begin
|
55
64
|
state = nil
|
56
65
|
|
57
|
-
client.on(
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
client.on(TD::Types::Update::AuthorizationState) do |update|
|
67
|
+
state = case update.authorization_state
|
68
|
+
when TD::Types::AuthorizationState::WaitPhoneNumber
|
69
|
+
:wait_phone_number
|
70
|
+
when TD::Types::AuthorizationState::WaitCode
|
71
|
+
:wait_code
|
72
|
+
when TD::Types::AuthorizationState::WaitPassword
|
73
|
+
:wait_password
|
74
|
+
when TD::Types::AuthorizationState::Ready
|
75
|
+
:ready
|
76
|
+
else
|
77
|
+
nil
|
78
|
+
end
|
70
79
|
end
|
80
|
+
|
81
|
+
client.connect
|
71
82
|
|
72
83
|
loop do
|
73
84
|
case state
|
74
|
-
when :
|
75
|
-
|
85
|
+
when :wait_phone_number
|
86
|
+
puts 'Please, enter your phone number:'
|
76
87
|
phone = STDIN.gets.strip
|
77
|
-
|
78
|
-
'@type' => 'setAuthenticationPhoneNumber',
|
79
|
-
'phone_number' => phone
|
80
|
-
}
|
81
|
-
client.broadcast_and_receive(params)
|
88
|
+
client.set_authentication_phone_number(phone, nil).wait
|
82
89
|
when :wait_code
|
83
|
-
|
90
|
+
puts 'Please, enter code from SMS:'
|
84
91
|
code = STDIN.gets.strip
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
client.
|
92
|
+
client.check_authentication_code(code).wait
|
93
|
+
when :wait_password
|
94
|
+
puts 'Please, enter 2FA password:'
|
95
|
+
password = STDIN.gets.strip
|
96
|
+
client.check_authentication_password(password).wait
|
90
97
|
when :ready
|
91
|
-
@me =
|
98
|
+
client.get_me.then { |user| @me = user }.rescue { |err| puts "error: #{err}" }.wait
|
92
99
|
break
|
93
100
|
end
|
101
|
+
sleep 0.1
|
94
102
|
end
|
95
103
|
|
96
104
|
ensure
|
97
|
-
client.
|
105
|
+
client.dispose
|
98
106
|
end
|
99
107
|
|
100
108
|
p @me
|
101
109
|
```
|
102
110
|
|
111
|
+
Client methods are being executed asynchronously and return Concurrent::Promises::Future (see: https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs-source/promises.in.md).
|
112
|
+
|
103
113
|
## Configuration
|
104
114
|
|
105
115
|
```ruby
|
@@ -110,17 +120,18 @@ TD.configure do |config|
|
|
110
120
|
config.client.api_id = 12345
|
111
121
|
config.client.api_hash = 'your_api_hash'
|
112
122
|
config.client.use_test_dc = true # default: false
|
113
|
-
config.database_directory = 'path/to/db/dir' # default: "#{Dir.home}/.tdlib-ruby/db"
|
114
|
-
config.files_directory = 'path/to/files/dir' # default: "#{Dir.home}/.tdlib-ruby/files"
|
123
|
+
config.client.database_directory = 'path/to/db/dir' # default: "#{Dir.home}/.tdlib-ruby/db"
|
124
|
+
config.client.files_directory = 'path/to/files/dir' # default: "#{Dir.home}/.tdlib-ruby/files"
|
125
|
+
config.client.use_file_database = true # default: true
|
115
126
|
config.client.use_chat_info_database = true # default: true
|
116
|
-
config.use_secret_chats = true # default: true
|
117
|
-
config.use_message_database = true # default: true
|
118
|
-
config.system_language_code = 'ru' # default: 'en'
|
119
|
-
config.device_model = 'Some device model' # default: 'Ruby TD client'
|
120
|
-
config.system_version = '42' # default: 'Unknown'
|
121
|
-
config.application_version = '1.0' # default: '1.0'
|
122
|
-
config.enable_storage_optimizer = true # default: true
|
123
|
-
config.ignore_file_names = true # default: false
|
127
|
+
config.client.use_secret_chats = true # default: true
|
128
|
+
config.client.use_message_database = true # default: true
|
129
|
+
config.client.system_language_code = 'ru' # default: 'en'
|
130
|
+
config.client.device_model = 'Some device model' # default: 'Ruby TD client'
|
131
|
+
config.client.system_version = '42' # default: 'Unknown'
|
132
|
+
config.client.application_version = '1.0' # default: '1.0'
|
133
|
+
config.client.enable_storage_optimizer = true # default: true
|
134
|
+
config.client.ignore_file_names = true # default: false
|
124
135
|
end
|
125
136
|
```
|
126
137
|
|
@@ -145,6 +156,12 @@ TD::Client.new(database_directory: 'will override value from config',
|
|
145
156
|
files_directory: 'will override value from config')
|
146
157
|
```
|
147
158
|
|
159
|
+
If the tdlib schema changes, then `./bin/parse` can be run to
|
160
|
+
synchronize the Ruby types with the new schema. Please look through
|
161
|
+
`lib/tdlib/client_methods.rb` carefully, especially the set_password
|
162
|
+
method!
|
163
|
+
|
164
|
+
|
148
165
|
## License
|
149
166
|
|
150
167
|
[MIT](https://github.com/centosadmin/tdlib-ruby/blob/master/LICENSE.txt)
|
@@ -152,3 +169,5 @@ TD::Client.new(database_directory: 'will override value from config',
|
|
152
169
|
## Authors
|
153
170
|
|
154
171
|
The gem is designed by [Southbridge](https://southbridge.io)
|
172
|
+
|
173
|
+
Typeization made by [Yuri Mikhaylov](https://github.com/yurijmi)
|
data/bin/build
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'etc'
|
4
|
+
|
5
|
+
`
|
6
|
+
set -e
|
7
|
+
cd td
|
8
|
+
mkdir -p build
|
9
|
+
cd build
|
10
|
+
cmake -DCMAKE_BUILD_TYPE=Release #{'-DOPENSSL_ROOT_DIR=/opt/homebrew/Cellar/openssl@1.1/1.1.1k/' if RbConfig::CONFIG['host_os'] =~ /darwin|mac os/} -DCMAKE_INSTALL_PREFIX:PATH=../tdlib ..
|
11
|
+
cmake --build . --target install -j #{Etc.nprocessors}
|
12
|
+
`
|
data/lib/tdlib-ruby.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'tdlib/version'
|
2
2
|
require 'dry/configurable'
|
3
|
+
require 'concurrent-ruby'
|
3
4
|
|
4
5
|
module TD
|
5
6
|
extend Dry::Configurable
|
@@ -15,11 +16,12 @@ module TD
|
|
15
16
|
setting :encryption_key
|
16
17
|
|
17
18
|
setting :client do
|
18
|
-
setting :api_id
|
19
|
+
setting :api_id, &:to_i
|
19
20
|
setting :api_hash
|
20
21
|
setting :use_test_dc, false
|
21
22
|
setting :database_directory, "#{Dir.home}/.tdlib-ruby/db"
|
22
23
|
setting :files_directory, "#{Dir.home}/.tdlib-ruby/data"
|
24
|
+
setting :use_file_database, true
|
23
25
|
setting :use_chat_info_database, true
|
24
26
|
setting :use_secret_chats, true
|
25
27
|
setting :use_message_database, true
|
@@ -32,8 +34,9 @@ module TD
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
require 'tdlib-schema'
|
35
38
|
require 'tdlib/errors'
|
36
39
|
require 'tdlib/api'
|
37
|
-
require 'tdlib/utils'
|
38
40
|
require 'tdlib/client'
|
41
|
+
require 'tdlib/update_handler'
|
39
42
|
require 'tdlib/update_manager'
|
data/lib/tdlib/api.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'fiddle/import'
|
2
1
|
require 'json'
|
2
|
+
require 'ffi'
|
3
3
|
|
4
4
|
module TD::Api
|
5
5
|
module_function
|
@@ -18,7 +18,7 @@ module TD::Api
|
|
18
18
|
|
19
19
|
def client_receive(client, timeout)
|
20
20
|
update = Dl.td_json_client_receive(client, timeout)
|
21
|
-
|
21
|
+
JSON.parse(update) if update
|
22
22
|
end
|
23
23
|
|
24
24
|
def client_destroy(client)
|
@@ -34,7 +34,7 @@ module TD::Api
|
|
34
34
|
end
|
35
35
|
|
36
36
|
module Dl
|
37
|
-
extend
|
37
|
+
extend FFI::Library
|
38
38
|
|
39
39
|
@mutex = Mutex.new
|
40
40
|
|
@@ -42,16 +42,18 @@ module TD::Api
|
|
42
42
|
|
43
43
|
def method_missing(method_name, *args)
|
44
44
|
@mutex.synchronize do
|
45
|
-
return if respond_to?(method_name)
|
46
|
-
dlload(find_lib)
|
45
|
+
return public_send(method_name, *args) if respond_to?(method_name)
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
47
|
+
find_lib
|
48
|
+
|
49
|
+
attach_function :td_json_client_create, [], :pointer
|
50
|
+
attach_function :td_json_client_receive, [:pointer, :double], :string, blocking: true
|
51
|
+
attach_function :td_json_client_send, [:pointer, :string], :pointer, blocking: true
|
52
|
+
attach_function :td_json_client_execute, [:pointer, :string], :string, blocking: true
|
53
|
+
attach_function :td_json_client_destroy, [:pointer], :void
|
54
|
+
attach_function :td_set_log_file_path, [:string], :int
|
55
|
+
attach_function :td_set_log_max_file_size, [:long_long], :void
|
56
|
+
attach_function :td_set_log_verbosity_level, [:int], :void
|
55
57
|
|
56
58
|
undef method_missing
|
57
59
|
public_send(method_name, *args)
|
@@ -66,9 +68,12 @@ module TD::Api
|
|
66
68
|
elsif defined?(Rails) && File.exist?(Rails.root.join('vendor', file_name))
|
67
69
|
Rails.root.join('vendor')
|
68
70
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
full_path = File.join(lib_path.to_s, file_name)
|
72
|
+
ffi_lib full_path
|
73
|
+
full_path
|
74
|
+
rescue LoadError
|
75
|
+
ffi_lib 'tdjson'
|
76
|
+
ffi_libraries.first.name
|
72
77
|
end
|
73
78
|
|
74
79
|
def lib_extension
|
data/lib/tdlib/client.rb
CHANGED
@@ -1,190 +1,193 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
# Simple client for TDLib.
|
2
|
-
# @example
|
3
|
-
# TD.configure do |config|
|
4
|
-
# config.lib_path = 'path_to_tdlibjson'
|
5
|
-
# config.encryption_key = 'your_encryption_key'
|
6
|
-
#
|
7
|
-
# config.client.api_id = your_api_id
|
8
|
-
# config.client.api_hash = 'your_api_hash'
|
9
|
-
# end
|
10
|
-
#
|
11
|
-
# client = TD::Client.new
|
12
|
-
#
|
13
|
-
# begin
|
14
|
-
# state = nil
|
15
|
-
#
|
16
|
-
# client.on('updateAuthorizationState') do |update|
|
17
|
-
# next unless update.dig('authorization_state', '@type') == 'authorizationStateWaitPhoneNumber'
|
18
|
-
# state = :wait_phone
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
# client.on('updateAuthorizationState') do |update|
|
22
|
-
# next unless update.dig('authorization_state', '@type') == 'authorizationStateWaitCode'
|
23
|
-
# state = :wait_code
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# client.on('updateAuthorizationState') do |update|
|
27
|
-
# next unless update.dig('authorization_state', '@type') == 'authorizationStateReady'
|
28
|
-
# state = :ready
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# loop do
|
32
|
-
# case state
|
33
|
-
# when :wait_phone
|
34
|
-
# p 'Please, enter your phone number:'
|
35
|
-
# phone = STDIN.gets.strip
|
36
|
-
# params = {
|
37
|
-
# '@type' => 'setAuthenticationPhoneNumber',
|
38
|
-
# 'phone_number' => phone
|
39
|
-
# }
|
40
|
-
# client.broadcast_and_receive(params)
|
41
|
-
# when :wait_code
|
42
|
-
# p 'Please, enter code from SMS:'
|
43
|
-
# code = STDIN.gets.strip
|
44
|
-
# params = {
|
45
|
-
# '@type' => 'checkAuthenticationCode',
|
46
|
-
# 'code' => code
|
47
|
-
# }
|
48
|
-
# client.broadcast_and_receive(params)
|
49
|
-
# when :ready
|
50
|
-
# @me = client.broadcast_and_receive('@type' => 'getMe')
|
51
|
-
# break
|
52
|
-
# end
|
53
|
-
# end
|
54
|
-
#
|
55
|
-
# ensure
|
56
|
-
# client.close
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# p @me
|
60
4
|
class TD::Client
|
5
|
+
include Concurrent
|
6
|
+
include TD::ClientMethods
|
7
|
+
|
61
8
|
TIMEOUT = 20
|
62
9
|
|
10
|
+
def self.ready(*args)
|
11
|
+
new(*args).connect
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [FFI::Pointer] td_client
|
15
|
+
# @param [TD::UpdateManager] update_manager
|
16
|
+
# @param [Numeric] timeout
|
17
|
+
# @param [Hash] extra_config optional configuration hash that will be merged into tdlib client configuration
|
63
18
|
def initialize(td_client = TD::Api.client_create,
|
64
19
|
update_manager = TD::UpdateManager.new(td_client),
|
65
|
-
|
20
|
+
timeout: TIMEOUT,
|
66
21
|
**extra_config)
|
67
22
|
@td_client = td_client
|
23
|
+
@ready = false
|
24
|
+
@alive = true
|
68
25
|
@update_manager = update_manager
|
26
|
+
@timeout = timeout
|
69
27
|
@config = TD.config.client.to_h.merge(extra_config)
|
70
|
-
@proxy = proxy
|
71
28
|
@ready_condition_mutex = Mutex.new
|
72
29
|
@ready_condition = ConditionVariable.new
|
73
|
-
authorize
|
74
|
-
@update_manager.run
|
75
30
|
end
|
76
31
|
|
77
|
-
#
|
32
|
+
# Adds initial authorization state handler and runs update manager
|
33
|
+
# Returns future that will be fulfilled when client is ready
|
34
|
+
# @return [Concurrent::Promises::Future]
|
35
|
+
def connect
|
36
|
+
on TD::Types::Update::AuthorizationState do |update|
|
37
|
+
case update.authorization_state
|
38
|
+
when TD::Types::AuthorizationState::WaitTdlibParameters
|
39
|
+
set_tdlib_parameters(parameters: TD::Types::TdlibParameters.new(**@config))
|
40
|
+
when TD::Types::AuthorizationState::WaitEncryptionKey
|
41
|
+
check_database_encryption_key(encryption_key: TD.config.encryption_key).then do
|
42
|
+
@ready_condition_mutex.synchronize do
|
43
|
+
@ready = true
|
44
|
+
@ready_condition.broadcast
|
45
|
+
end
|
46
|
+
end
|
47
|
+
else
|
48
|
+
# do nothing
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
@update_manager.run(callback: method(:handle_update))
|
53
|
+
ready
|
54
|
+
end
|
55
|
+
|
56
|
+
# Sends asynchronous request to the TDLib client and returns Promise object
|
57
|
+
# @see TD::ClientMethods List of available queries as methods
|
58
|
+
# @see https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs-source/promises.in.md
|
59
|
+
# Concurrent::Promise documentation
|
60
|
+
# @example
|
61
|
+
# client.broadcast(some_query).then { |result| puts result }.rescue { |error| puts [error.code, error.message] }
|
78
62
|
# @param [Hash] query
|
79
|
-
# @
|
63
|
+
# @return [Concurrent::Promises::Future]
|
80
64
|
def broadcast(query)
|
81
|
-
if
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
65
|
+
return dead_client_promise if dead?
|
66
|
+
|
67
|
+
Promises.future do
|
68
|
+
condition = ConditionVariable.new
|
69
|
+
extra = SecureRandom.uuid
|
70
|
+
result = nil
|
71
|
+
mutex = Mutex.new
|
72
|
+
|
73
|
+
@update_manager << TD::UpdateHandler.new(TD::Types::Base, extra, disposable: true) do |update|
|
74
|
+
mutex.synchronize do
|
75
|
+
result = update
|
76
|
+
condition.signal
|
77
|
+
end
|
87
78
|
end
|
88
|
-
|
79
|
+
|
89
80
|
query['@extra'] = extra
|
81
|
+
|
82
|
+
mutex.synchronize do
|
83
|
+
send_to_td_client(query)
|
84
|
+
condition.wait(mutex, @timeout)
|
85
|
+
error = nil
|
86
|
+
error = result if result.is_a?(TD::Types::Error)
|
87
|
+
error = timeout_error if result.nil?
|
88
|
+
raise TD::Error.new(error) if error
|
89
|
+
result
|
90
|
+
end
|
90
91
|
end
|
91
|
-
TD::Api.client_send(@td_client, query)
|
92
92
|
end
|
93
93
|
|
94
94
|
# Sends asynchronous request to the TDLib client and returns received update synchronously
|
95
95
|
# @param [Hash] query
|
96
96
|
# @return [Hash]
|
97
|
-
def
|
98
|
-
|
99
|
-
extra = TD::Utils.generate_extra(query)
|
100
|
-
result = nil
|
101
|
-
mutex = Mutex.new
|
102
|
-
handler = ->(update) do
|
103
|
-
return unless update['@extra'] == extra
|
104
|
-
mutex.synchronize do
|
105
|
-
result = update
|
106
|
-
@update_manager.remove_handler(handler)
|
107
|
-
condition.signal
|
108
|
-
end
|
109
|
-
end
|
110
|
-
@update_manager.add_handler(handler)
|
111
|
-
query['@extra'] = extra
|
112
|
-
mutex.synchronize do
|
113
|
-
TD::Api.client_send(@td_client, query)
|
114
|
-
condition.wait(mutex, timeout)
|
115
|
-
raise TD::TimeoutError if result.nil?
|
116
|
-
result
|
117
|
-
end
|
97
|
+
def fetch(query)
|
98
|
+
broadcast(query).value!
|
118
99
|
end
|
119
100
|
|
101
|
+
alias broadcast_and_receive fetch
|
102
|
+
|
120
103
|
# Synchronously executes TDLib request
|
121
104
|
# Only a few requests can be executed synchronously
|
122
105
|
# @param [Hash] query
|
123
106
|
def execute(query)
|
107
|
+
return dead_client_error if dead?
|
124
108
|
TD::Api.client_execute(@td_client, query)
|
125
109
|
end
|
126
110
|
|
127
|
-
# Returns current authorization state (it's offline request)
|
128
|
-
# @return [Hash]
|
129
|
-
def authorization_state
|
130
|
-
broadcast_and_receive('@type' => 'getAuthorizationState')
|
131
|
-
end
|
132
|
-
|
133
111
|
# Binds passed block as a handler for updates with type of *update_type*
|
134
|
-
# @param [String] update_type
|
112
|
+
# @param [String, Class] update_type
|
135
113
|
# @yield [update] yields update to the block as soon as it's received
|
136
|
-
def on(update_type, &
|
137
|
-
|
138
|
-
|
139
|
-
|
114
|
+
def on(update_type, &action)
|
115
|
+
if update_type.is_a?(String)
|
116
|
+
if (type_const = TD::Types::LOOKUP_TABLE[update_type])
|
117
|
+
update_type = TD::Types.const_get("TD::Types::#{type_const}")
|
118
|
+
else
|
119
|
+
raise ArgumentError.new("Can't find class for #{update_type}")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
unless update_type < TD::Types::Base
|
124
|
+
raise ArgumentError.new("Wrong type specified (#{update_type}). Should be of kind TD::Types::Base")
|
140
125
|
end
|
141
|
-
|
126
|
+
|
127
|
+
@update_manager << TD::UpdateHandler.new(update_type, &action)
|
142
128
|
end
|
143
129
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
130
|
+
# returns future that will be fulfilled when client is ready
|
131
|
+
# @return [Concurrent::Promises::Future]
|
132
|
+
def ready
|
133
|
+
return dead_client_promise if dead?
|
134
|
+
return Promises.fulfilled_future(self) if ready?
|
135
|
+
|
136
|
+
Promises.future do
|
137
|
+
@ready_condition_mutex.synchronize do
|
138
|
+
next self if @ready || (@ready_condition.wait(@ready_condition_mutex, @timeout) && @ready)
|
139
|
+
raise TD::Error.new(timeout_error)
|
140
|
+
end
|
148
141
|
end
|
149
142
|
end
|
150
143
|
|
144
|
+
# @deprecated
|
145
|
+
def on_ready(&action)
|
146
|
+
ready.then(&action).value!
|
147
|
+
end
|
148
|
+
|
151
149
|
# Stops update manager and destroys TDLib client
|
152
|
-
def
|
153
|
-
|
154
|
-
|
150
|
+
def dispose
|
151
|
+
return if dead?
|
152
|
+
close.then { get_authorization_state }
|
153
|
+
end
|
154
|
+
|
155
|
+
def alive?
|
156
|
+
@alive
|
157
|
+
end
|
158
|
+
|
159
|
+
def dead?
|
160
|
+
!alive?
|
161
|
+
end
|
162
|
+
|
163
|
+
def ready?
|
164
|
+
@ready
|
155
165
|
end
|
156
166
|
|
157
167
|
private
|
158
168
|
|
159
|
-
def
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
}
|
167
|
-
|
168
|
-
if TD.config.encryption_key
|
169
|
-
encryption_key_query['encryption_key'] = TD.config.encryption_key
|
170
|
-
end
|
169
|
+
def handle_update(update)
|
170
|
+
return unless update.is_a?(TD::Types::AuthorizationState::Closed)
|
171
|
+
@alive = false
|
172
|
+
@ready = false
|
173
|
+
TD::Api.client_destroy(@td_client)
|
174
|
+
throw(:client_closed)
|
175
|
+
end
|
171
176
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end
|
188
|
-
@update_manager.add_handler(handler)
|
177
|
+
def send_to_td_client(query)
|
178
|
+
return unless alive?
|
179
|
+
TD::Api.client_send(@td_client, query)
|
180
|
+
end
|
181
|
+
|
182
|
+
def timeout_error
|
183
|
+
TD::Types::Error.new(code: 0, message: 'Timeout error')
|
184
|
+
end
|
185
|
+
|
186
|
+
def dead_client_promise
|
187
|
+
Promises.rejected_future(dead_client_error)
|
188
|
+
end
|
189
|
+
|
190
|
+
def dead_client_error
|
191
|
+
TD::Error.new(TD::Types::Error.new(code: 0, message: 'TD client is dead'))
|
189
192
|
end
|
190
193
|
end
|
data/lib/tdlib/errors.rb
CHANGED
@@ -1,8 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module TD
|
2
|
+
class MissingLibPathError < StandardError
|
3
|
+
def initialize(message = 'Please, configure the path to tdlibjson library')
|
4
|
+
super
|
5
|
+
end
|
4
6
|
end
|
5
|
-
end
|
6
7
|
|
7
|
-
class
|
8
|
+
# Proxy class that is used in failed promises to represent TDlib errors
|
9
|
+
class Error < StandardError
|
10
|
+
def initialize(td_error)
|
11
|
+
@td_error = td_error
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method, *args)
|
15
|
+
@td_error.public_send(method, *args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def respond_to_missing?(*args)
|
19
|
+
@td_error.respond_to?(*args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
@td_error.inspect
|
24
|
+
end
|
25
|
+
|
26
|
+
def message
|
27
|
+
@td_error.message
|
28
|
+
end
|
29
|
+
|
30
|
+
alias inspect to_s
|
31
|
+
end
|
8
32
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class TD::UpdateHandler
|
2
|
+
include Concurrent::Async
|
3
|
+
|
4
|
+
attr_reader :update_type, :extra
|
5
|
+
|
6
|
+
def initialize(update_type, extra = nil, disposable: false, &action)
|
7
|
+
super()
|
8
|
+
|
9
|
+
@action = action
|
10
|
+
@update_type = update_type
|
11
|
+
@extra = extra
|
12
|
+
@disposable = disposable
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(update)
|
16
|
+
action.call(update)
|
17
|
+
rescue StandardError => e
|
18
|
+
warn("Uncaught exception in handler #{self}: #{e.message}")
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
|
22
|
+
def match?(update, extra = nil)
|
23
|
+
update.is_a?(update_type) && (self.extra.nil? || self.extra == extra)
|
24
|
+
end
|
25
|
+
|
26
|
+
def disposable?
|
27
|
+
disposable
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"TD::UpdateHandler (#{update_type}#{": #{extra}" if extra})#{' disposable' if disposable?}"
|
32
|
+
end
|
33
|
+
|
34
|
+
alias inspect to_s
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :action, :disposable
|
39
|
+
end
|
data/lib/tdlib/update_manager.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
class TD::UpdateManager
|
2
2
|
TIMEOUT = 30
|
3
3
|
|
4
|
-
attr_reader :handlers
|
5
|
-
|
6
4
|
def initialize(td_client)
|
7
5
|
@td_client = td_client
|
8
|
-
@handlers =
|
6
|
+
@handlers = Concurrent::Array.new
|
9
7
|
@mutex = Mutex.new
|
10
8
|
end
|
11
9
|
|
@@ -13,31 +11,36 @@ class TD::UpdateManager
|
|
13
11
|
@mutex.synchronize { @handlers << handler }
|
14
12
|
end
|
15
13
|
|
16
|
-
|
14
|
+
alias << add_handler
|
15
|
+
|
16
|
+
def run(callback: nil)
|
17
17
|
Thread.start do
|
18
|
-
|
18
|
+
catch(:client_closed) { loop { handle_update(callback: callback) } }
|
19
|
+
@mutex.synchronize { @handlers = [] }
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
|
-
|
23
|
-
@update_loop_thread = Thread.start do
|
24
|
-
loop { stopped? ? break : handle_update }
|
25
|
-
end
|
26
|
-
end
|
23
|
+
private
|
27
24
|
|
28
|
-
|
29
|
-
@stopped = true
|
30
|
-
end
|
25
|
+
attr_reader :handlers
|
31
26
|
|
32
|
-
def
|
33
|
-
|
34
|
-
end
|
27
|
+
def handle_update(callback: nil)
|
28
|
+
update = TD::Api.client_receive(@td_client, TIMEOUT)
|
35
29
|
|
36
|
-
|
30
|
+
unless update.nil?
|
31
|
+
extra = update.delete('@extra')
|
32
|
+
update = TD::Types.wrap(update)
|
33
|
+
callback&.call(update)
|
37
34
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
match_handlers!(update, extra).each { |h| h.async.run(update) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def match_handlers!(update, extra)
|
40
|
+
@mutex.synchronize do
|
41
|
+
matched_handlers = handlers.select { |h| h.match?(update, extra) }
|
42
|
+
matched_handlers.each { |h| handlers.delete(h) if h.disposable? }
|
43
|
+
matched_handlers
|
44
|
+
end
|
42
45
|
end
|
43
46
|
end
|
data/lib/tdlib/version.rb
CHANGED
@@ -2,8 +2,10 @@ require 'spec_helper'
|
|
2
2
|
require 'tdlib-ruby'
|
3
3
|
|
4
4
|
describe TD::Client do
|
5
|
-
let(:client) { TD::Client.new }
|
6
|
-
let(:payload) { { '@type'
|
5
|
+
let(:client) { TD::Client.new(timeout: timeout).tap(&:connect) }
|
6
|
+
let!(:payload) { { '@type' => 'getTextEntities', 'text' => text } }
|
7
|
+
let!(:text) { '@telegram' }
|
8
|
+
let(:timeout) { TD::Client::TIMEOUT }
|
7
9
|
|
8
10
|
before do
|
9
11
|
TD.configure do |config|
|
@@ -17,6 +19,14 @@ describe TD::Client do
|
|
17
19
|
TD::Api.set_log_verbosity_level(1)
|
18
20
|
end
|
19
21
|
|
22
|
+
around do |example|
|
23
|
+
begin
|
24
|
+
example.run
|
25
|
+
ensure
|
26
|
+
client.dispose
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
20
30
|
describe '#on_ready' do
|
21
31
|
subject { client.on_ready { [client, 'ready'] } }
|
22
32
|
|
@@ -24,39 +34,35 @@ describe TD::Client do
|
|
24
34
|
it { is_expected.to include('ready') }
|
25
35
|
|
26
36
|
context 'when timeout reached' do
|
27
|
-
|
37
|
+
let(:timeout) { 0.0001 }
|
28
38
|
|
29
|
-
|
39
|
+
subject { client.on_ready { [client, 'ready'] } }
|
40
|
+
|
41
|
+
it { expect { subject }.to raise_error(TD::Error) }
|
30
42
|
end
|
31
43
|
end
|
32
44
|
|
33
45
|
describe '#broadcast' do
|
34
46
|
context 'when no block given' do
|
35
|
-
subject { client.
|
47
|
+
subject { client.ready.then { client.get_text_entities(text: text) }.flat.wait }
|
36
48
|
|
37
49
|
it { expect { subject }.not_to raise_error(Exception) }
|
38
|
-
|
39
|
-
|
40
|
-
context 'when block given' do
|
41
|
-
subject { client.on_ready { client.broadcast(payload) { |update| @result = update } } }
|
42
|
-
|
43
|
-
it 'runs block on update' do
|
44
|
-
subject
|
45
|
-
sleep 1
|
46
|
-
expect(@result).to include('@type', 'entities')
|
47
|
-
end
|
50
|
+
it { is_expected.to satisfy(&:fulfilled?) }
|
51
|
+
it { is_expected.to satisfy { |result| result.value.is_a?(TD::Types::TextEntities) } }
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
51
|
-
describe '#
|
52
|
-
subject { client.on_ready { client.
|
55
|
+
describe '#fetch' do
|
56
|
+
subject { client.on_ready { client.fetch(payload) } }
|
53
57
|
|
54
|
-
it { is_expected.to
|
58
|
+
it { is_expected.to respond_to(:entities) }
|
55
59
|
|
56
60
|
context 'when timeout reached' do
|
57
|
-
|
61
|
+
let(:timeout) { 0.0001 }
|
62
|
+
|
63
|
+
subject { client.on_ready { client.fetch(payload) } }
|
58
64
|
|
59
|
-
it { expect { subject }.to raise_error(TD::
|
65
|
+
it { expect { subject }.to raise_error(TD::Error) }
|
60
66
|
end
|
61
67
|
end
|
62
68
|
|
@@ -71,7 +77,7 @@ describe TD::Client do
|
|
71
77
|
it 'runs block on update' do
|
72
78
|
subject
|
73
79
|
sleep 1
|
74
|
-
expect(@result).to
|
80
|
+
expect(@result).to respond_to(:entities)
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
@@ -81,7 +87,7 @@ describe TD::Client do
|
|
81
87
|
subject do
|
82
88
|
client.on_ready do
|
83
89
|
client.broadcast(payload) do
|
84
|
-
client.
|
90
|
+
client.fetch(payload)
|
85
91
|
end
|
86
92
|
sleep 1
|
87
93
|
end
|
data/tdlib-ruby.gemspec
CHANGED
@@ -14,25 +14,19 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.email = "ask@southbridge.io"
|
15
15
|
gem.homepage = "https://github.com/centosadmin/tdlib-ruby"
|
16
16
|
|
17
|
-
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.files = `git ls-files`.split($/) - ['lib/tdlib/td_api_tl_parser.rb']
|
18
18
|
|
19
|
-
`git submodule --quiet foreach --recursive pwd`.split($/).each do |submodule|
|
20
|
-
submodule.sub!("#{Dir.pwd}/",'')
|
21
|
-
|
22
|
-
Dir.chdir(submodule) do
|
23
|
-
`git ls-files`.split($/).map do |subpath|
|
24
|
-
gem.files << File.join(submodule,subpath)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
19
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
29
20
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
30
21
|
gem.require_paths = ['lib']
|
31
22
|
|
32
|
-
gem.add_runtime_dependency 'dry-configurable', '~> 0.
|
23
|
+
gem.add_runtime_dependency 'dry-configurable', '~> 0.9'
|
24
|
+
gem.add_runtime_dependency 'concurrent-ruby', '~> 1.1'
|
25
|
+
gem.add_runtime_dependency 'ffi', '~> 1.0'
|
26
|
+
gem.add_runtime_dependency 'tdlib-schema'
|
33
27
|
|
34
|
-
gem.add_development_dependency 'bundler', '~>
|
35
|
-
gem.add_development_dependency 'rake', '
|
28
|
+
gem.add_development_dependency 'bundler', '~> 2.0'
|
29
|
+
gem.add_development_dependency 'rake', '~> 13.0'
|
36
30
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
37
31
|
gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
38
32
|
gem.add_development_dependency 'yard', '~> 0.9'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tdlib-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Southbridge
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-configurable
|
@@ -16,42 +16,84 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: concurrent-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.1'
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
40
|
+
version: '1.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ffi
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tdlib-schema
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
70
|
name: bundler
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
30
72
|
requirements:
|
31
73
|
- - "~>"
|
32
74
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
75
|
+
version: '2.0'
|
34
76
|
type: :development
|
35
77
|
prerelease: false
|
36
78
|
version_requirements: !ruby/object:Gem::Requirement
|
37
79
|
requirements:
|
38
80
|
- - "~>"
|
39
81
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
82
|
+
version: '2.0'
|
41
83
|
- !ruby/object:Gem::Dependency
|
42
84
|
name: rake
|
43
85
|
requirement: !ruby/object:Gem::Requirement
|
44
86
|
requirements:
|
45
|
-
- -
|
87
|
+
- - "~>"
|
46
88
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
89
|
+
version: '13.0'
|
48
90
|
type: :development
|
49
91
|
prerelease: false
|
50
92
|
version_requirements: !ruby/object:Gem::Requirement
|
51
93
|
requirements:
|
52
|
-
- -
|
94
|
+
- - "~>"
|
53
95
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
96
|
+
version: '13.0'
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
98
|
name: rspec
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,12 +153,14 @@ dependencies:
|
|
111
153
|
description: Ruby bindings and client for TDlib
|
112
154
|
email: ask@southbridge.io
|
113
155
|
executables:
|
156
|
+
- build
|
114
157
|
- console
|
115
158
|
extensions: []
|
116
159
|
extra_rdoc_files: []
|
117
160
|
files:
|
118
161
|
- ".document"
|
119
162
|
- ".gitignore"
|
163
|
+
- ".gitmodules"
|
120
164
|
- ".rspec"
|
121
165
|
- ".travis.yml"
|
122
166
|
- ".yardopts"
|
@@ -125,13 +169,14 @@ files:
|
|
125
169
|
- LICENSE.txt
|
126
170
|
- README.md
|
127
171
|
- Rakefile
|
172
|
+
- bin/build
|
128
173
|
- bin/console
|
129
174
|
- lib/tdlib-ruby.rb
|
130
175
|
- lib/tdlib/api.rb
|
131
176
|
- lib/tdlib/client.rb
|
132
177
|
- lib/tdlib/errors.rb
|
178
|
+
- lib/tdlib/update_handler.rb
|
133
179
|
- lib/tdlib/update_manager.rb
|
134
|
-
- lib/tdlib/utils.rb
|
135
180
|
- lib/tdlib/version.rb
|
136
181
|
- spec/integration/tdlib_spec.rb
|
137
182
|
- spec/spec_helper.rb
|
@@ -141,7 +186,7 @@ homepage: https://github.com/centosadmin/tdlib-ruby
|
|
141
186
|
licenses:
|
142
187
|
- MIT
|
143
188
|
metadata: {}
|
144
|
-
post_install_message:
|
189
|
+
post_install_message:
|
145
190
|
rdoc_options: []
|
146
191
|
require_paths:
|
147
192
|
- lib
|
@@ -156,9 +201,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
201
|
- !ruby/object:Gem::Version
|
157
202
|
version: '0'
|
158
203
|
requirements: []
|
159
|
-
|
160
|
-
|
161
|
-
signing_key:
|
204
|
+
rubygems_version: 3.1.4
|
205
|
+
signing_key:
|
162
206
|
specification_version: 4
|
163
207
|
summary: Ruby bindings and client for TDlib
|
164
208
|
test_files:
|