tdlib-ruby 1.0.0 → 3.0.1
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 +4 -4
- data/.gitignore +2 -0
- data/.gitmodules +0 -0
- data/.travis.yml +6 -3
- data/ChangeLog.md +22 -0
- data/README.md +59 -48
- data/bin/build +12 -0
- data/lib/tdlib-ruby.rb +5 -2
- data/lib/tdlib/api.rb +20 -15
- data/lib/tdlib/client.rb +130 -126
- 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 -15
- data/tdlib-ruby.gemspec +7 -14
- metadata +46 -16
- data/lib/tdlib/utils.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 851d0531bf3de68a43c0f72acf22aa549142fd1b866f915df4af2bf919408211
|
|
4
|
+
data.tar.gz: '0320249654babf8f873936c5e74e09a03b24d1689a6019f9d7edccfc72c5d96c'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3a8ba653e0261bde8fd13e237846f052520d7d9cca6fd808cbbf31937a706978b7b04273931192b5494e6e004c1f06c823ed65615f3a52d5cbbd8da7c5c5bbe2
|
|
7
|
+
data.tar.gz: 93c09fc96b0881d372b46f4f2970b803f99f2bc569657946a431687b46ae6d8b0f47aa6e7437c580ede440248b3cc3802986dc9676084439616348107a57cdcc
|
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,25 @@
|
|
|
1
|
+
### 3.0.1 / 2020-06-29
|
|
2
|
+
|
|
3
|
+
* Fix client dispose
|
|
4
|
+
|
|
5
|
+
### 3.0.0 / 2020-06-28
|
|
6
|
+
|
|
7
|
+
* Extract schema to separate gem
|
|
8
|
+
|
|
9
|
+
### 2.1.0 / 2019-10-18
|
|
10
|
+
|
|
11
|
+
* Support tdlib 1.5
|
|
12
|
+
* Fix TD::Client#dispose race condition and client crash
|
|
13
|
+
|
|
14
|
+
### 2.0.0 / 2019-02-08
|
|
15
|
+
|
|
16
|
+
* Generated types and client functions
|
|
17
|
+
* Async handlers
|
|
18
|
+
* Use ffi instead of fiddle
|
|
19
|
+
* Use Concurrent::Promises
|
|
20
|
+
* TD errors handling in promises
|
|
21
|
+
* Add use_file_database setting to config
|
|
22
|
+
|
|
1
23
|
### 1.0.0 / 2018-05-27
|
|
2
24
|
|
|
3
25
|
* Return promises from TD::Client#broadcast
|
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,59 +63,52 @@ 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
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
From version 1.0 TD::Client##broadcast returns [Concurrent::Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html) object.
|
|
106
|
-
|
|
107
|
-
```ruby
|
|
108
|
-
me = client.broadcast('@type' => 'getMe').then { |result| puts result }.rescue { |error| puts error }.value
|
|
109
|
-
```
|
|
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).
|
|
110
112
|
|
|
111
113
|
## Configuration
|
|
112
114
|
|
|
@@ -118,17 +120,18 @@ TD.configure do |config|
|
|
|
118
120
|
config.client.api_id = 12345
|
|
119
121
|
config.client.api_hash = 'your_api_hash'
|
|
120
122
|
config.client.use_test_dc = true # default: false
|
|
121
|
-
config.database_directory = 'path/to/db/dir' # default: "#{Dir.home}/.tdlib-ruby/db"
|
|
122
|
-
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
|
|
123
126
|
config.client.use_chat_info_database = true # default: true
|
|
124
|
-
config.use_secret_chats = true # default: true
|
|
125
|
-
config.use_message_database = true # default: true
|
|
126
|
-
config.system_language_code = 'ru' # default: 'en'
|
|
127
|
-
config.device_model = 'Some device model' # default: 'Ruby TD client'
|
|
128
|
-
config.system_version = '42' # default: 'Unknown'
|
|
129
|
-
config.application_version = '1.0' # default: '1.0'
|
|
130
|
-
config.enable_storage_optimizer = true # default: true
|
|
131
|
-
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
|
|
132
135
|
end
|
|
133
136
|
```
|
|
134
137
|
|
|
@@ -153,6 +156,12 @@ TD::Client.new(database_directory: 'will override value from config',
|
|
|
153
156
|
files_directory: 'will override value from config')
|
|
154
157
|
```
|
|
155
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
|
+
|
|
156
165
|
## License
|
|
157
166
|
|
|
158
167
|
[MIT](https://github.com/centosadmin/tdlib-ruby/blob/master/LICENSE.txt)
|
|
@@ -160,3 +169,5 @@ TD::Client.new(database_directory: 'will override value from config',
|
|
|
160
169
|
## Authors
|
|
161
170
|
|
|
162
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,108 +1,91 @@
|
|
|
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
|
|
61
5
|
include Concurrent
|
|
6
|
+
include TD::ClientMethods
|
|
62
7
|
|
|
63
8
|
TIMEOUT = 20
|
|
64
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
|
|
65
18
|
def initialize(td_client = TD::Api.client_create,
|
|
66
19
|
update_manager = TD::UpdateManager.new(td_client),
|
|
67
|
-
|
|
20
|
+
timeout: TIMEOUT,
|
|
68
21
|
**extra_config)
|
|
69
22
|
@td_client = td_client
|
|
23
|
+
@ready = false
|
|
24
|
+
@alive = true
|
|
70
25
|
@update_manager = update_manager
|
|
26
|
+
@timeout = timeout
|
|
71
27
|
@config = TD.config.client.to_h.merge(extra_config)
|
|
72
|
-
@proxy = proxy
|
|
73
28
|
@ready_condition_mutex = Mutex.new
|
|
74
29
|
@ready_condition = ConditionVariable.new
|
|
75
|
-
|
|
76
|
-
|
|
30
|
+
end
|
|
31
|
+
|
|
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
|
|
77
54
|
end
|
|
78
55
|
|
|
79
56
|
# Sends asynchronous request to the TDLib client and returns Promise object
|
|
80
|
-
# @see
|
|
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
|
|
81
60
|
# @example
|
|
82
|
-
# client.broadcast(some_query).then { |result| puts result }.rescue
|
|
61
|
+
# client.broadcast(some_query).then { |result| puts result }.rescue { |error| puts [error.code, error.message] }
|
|
83
62
|
# @param [Hash] query
|
|
84
|
-
# @
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
63
|
+
# @return [Concurrent::Promises::Future]
|
|
64
|
+
def broadcast(query)
|
|
65
|
+
return dead_client_promise if dead?
|
|
66
|
+
|
|
67
|
+
Promises.future do
|
|
88
68
|
condition = ConditionVariable.new
|
|
89
|
-
extra =
|
|
69
|
+
extra = SecureRandom.uuid
|
|
90
70
|
result = nil
|
|
91
71
|
mutex = Mutex.new
|
|
92
|
-
|
|
93
|
-
|
|
72
|
+
|
|
73
|
+
@update_manager << TD::UpdateHandler.new(TD::Types::Base, extra, disposable: true) do |update|
|
|
94
74
|
mutex.synchronize do
|
|
95
75
|
result = update
|
|
96
|
-
@update_manager.remove_handler(handler)
|
|
97
76
|
condition.signal
|
|
98
77
|
end
|
|
99
78
|
end
|
|
100
|
-
|
|
79
|
+
|
|
101
80
|
query['@extra'] = extra
|
|
81
|
+
|
|
102
82
|
mutex.synchronize do
|
|
103
|
-
|
|
104
|
-
condition.wait(mutex, timeout)
|
|
105
|
-
|
|
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
|
|
106
89
|
result
|
|
107
90
|
end
|
|
108
91
|
end
|
|
@@ -111,8 +94,8 @@ class TD::Client
|
|
|
111
94
|
# Sends asynchronous request to the TDLib client and returns received update synchronously
|
|
112
95
|
# @param [Hash] query
|
|
113
96
|
# @return [Hash]
|
|
114
|
-
def fetch(query
|
|
115
|
-
broadcast(query
|
|
97
|
+
def fetch(query)
|
|
98
|
+
broadcast(query).value!
|
|
116
99
|
end
|
|
117
100
|
|
|
118
101
|
alias broadcast_and_receive fetch
|
|
@@ -121,70 +104,91 @@ class TD::Client
|
|
|
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
|
|
140
121
|
end
|
|
141
|
-
|
|
122
|
+
|
|
123
|
+
unless update_type < TD::Types::Base
|
|
124
|
+
raise ArgumentError.new("Wrong type specified (#{update_type}). Should be of kind TD::Types::Base")
|
|
125
|
+
end
|
|
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::Update::AuthorizationState) && update.authorization_state.is_a?(TD::Types::AuthorizationState::Closed)
|
|
171
|
+
@alive = false
|
|
172
|
+
@ready = false
|
|
173
|
+
sleep 0.001
|
|
174
|
+
TD::Api.client_destroy(@td_client)
|
|
175
|
+
throw(:client_closed)
|
|
176
|
+
end
|
|
171
177
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
end
|
|
188
|
-
@update_manager.add_handler(handler)
|
|
178
|
+
def send_to_td_client(query)
|
|
179
|
+
return unless alive?
|
|
180
|
+
TD::Api.client_send(@td_client, query)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def timeout_error
|
|
184
|
+
TD::Types::Error.new(code: 0, message: 'Timeout error')
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def dead_client_promise
|
|
188
|
+
Promises.rejected_future(dead_client_error)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def dead_client_error
|
|
192
|
+
TD::Error.new(TD::Types::Error.new(code: 0, message: 'TD client is dead'))
|
|
189
193
|
end
|
|
190
194
|
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,32 +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
|
-
it { is_expected.to satisfy
|
|
39
|
-
it { is_expected.to satisfy { |result|
|
|
40
|
-
it { is_expected.to satisfy { |result| sleep 1; result.value['@type'] == 'textEntities' } }
|
|
50
|
+
it { is_expected.to satisfy(&:fulfilled?) }
|
|
51
|
+
it { is_expected.to satisfy { |result| result.value.is_a?(TD::Types::TextEntities) } }
|
|
41
52
|
end
|
|
42
53
|
end
|
|
43
54
|
|
|
44
|
-
describe '#
|
|
45
|
-
subject { client.on_ready { client.
|
|
55
|
+
describe '#fetch' do
|
|
56
|
+
subject { client.on_ready { client.fetch(payload) } }
|
|
46
57
|
|
|
47
|
-
it { is_expected.to
|
|
58
|
+
it { is_expected.to respond_to(:entities) }
|
|
48
59
|
|
|
49
60
|
context 'when timeout reached' do
|
|
50
|
-
|
|
61
|
+
let(:timeout) { 0.0001 }
|
|
62
|
+
|
|
63
|
+
subject { client.on_ready { client.fetch(payload) } }
|
|
51
64
|
|
|
52
|
-
it { expect { subject }.to raise_error(TD::
|
|
65
|
+
it { expect { subject }.to raise_error(TD::Error) }
|
|
53
66
|
end
|
|
54
67
|
end
|
|
55
68
|
|
|
@@ -64,7 +77,7 @@ describe TD::Client do
|
|
|
64
77
|
it 'runs block on update' do
|
|
65
78
|
subject
|
|
66
79
|
sleep 1
|
|
67
|
-
expect(@result).to
|
|
80
|
+
expect(@result).to respond_to(:entities)
|
|
68
81
|
end
|
|
69
82
|
end
|
|
70
83
|
|
|
@@ -74,7 +87,7 @@ describe TD::Client do
|
|
|
74
87
|
subject do
|
|
75
88
|
client.on_ready do
|
|
76
89
|
client.broadcast(payload) do
|
|
77
|
-
client.
|
|
90
|
+
client.fetch(payload)
|
|
78
91
|
end
|
|
79
92
|
sleep 1
|
|
80
93
|
end
|
data/tdlib-ruby.gemspec
CHANGED
|
@@ -14,26 +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.
|
|
33
|
-
gem.add_runtime_dependency 'concurrent-ruby',
|
|
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'
|
|
34
27
|
|
|
35
|
-
gem.add_development_dependency 'bundler', '~>
|
|
36
|
-
gem.add_development_dependency 'rake', '
|
|
28
|
+
gem.add_development_dependency 'bundler', '~> 2.0'
|
|
29
|
+
gem.add_development_dependency 'rake', '~> 13.0'
|
|
37
30
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
|
38
31
|
gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
|
39
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:
|
|
4
|
+
version: 3.0.1
|
|
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-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dry-configurable
|
|
@@ -16,16 +16,30 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.9'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0.
|
|
26
|
+
version: '0.9'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: concurrent-ruby
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: ffi
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
|
30
44
|
requirements:
|
|
31
45
|
- - "~>"
|
|
@@ -38,34 +52,48 @@ dependencies:
|
|
|
38
52
|
- - "~>"
|
|
39
53
|
- !ruby/object:Gem::Version
|
|
40
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'
|
|
41
69
|
- !ruby/object:Gem::Dependency
|
|
42
70
|
name: bundler
|
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
|
44
72
|
requirements:
|
|
45
73
|
- - "~>"
|
|
46
74
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
75
|
+
version: '2.0'
|
|
48
76
|
type: :development
|
|
49
77
|
prerelease: false
|
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
79
|
requirements:
|
|
52
80
|
- - "~>"
|
|
53
81
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
82
|
+
version: '2.0'
|
|
55
83
|
- !ruby/object:Gem::Dependency
|
|
56
84
|
name: rake
|
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
|
58
86
|
requirements:
|
|
59
|
-
- -
|
|
87
|
+
- - "~>"
|
|
60
88
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
89
|
+
version: '13.0'
|
|
62
90
|
type: :development
|
|
63
91
|
prerelease: false
|
|
64
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
93
|
requirements:
|
|
66
|
-
- -
|
|
94
|
+
- - "~>"
|
|
67
95
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
96
|
+
version: '13.0'
|
|
69
97
|
- !ruby/object:Gem::Dependency
|
|
70
98
|
name: rspec
|
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -125,12 +153,14 @@ dependencies:
|
|
|
125
153
|
description: Ruby bindings and client for TDlib
|
|
126
154
|
email: ask@southbridge.io
|
|
127
155
|
executables:
|
|
156
|
+
- build
|
|
128
157
|
- console
|
|
129
158
|
extensions: []
|
|
130
159
|
extra_rdoc_files: []
|
|
131
160
|
files:
|
|
132
161
|
- ".document"
|
|
133
162
|
- ".gitignore"
|
|
163
|
+
- ".gitmodules"
|
|
134
164
|
- ".rspec"
|
|
135
165
|
- ".travis.yml"
|
|
136
166
|
- ".yardopts"
|
|
@@ -139,13 +169,14 @@ files:
|
|
|
139
169
|
- LICENSE.txt
|
|
140
170
|
- README.md
|
|
141
171
|
- Rakefile
|
|
172
|
+
- bin/build
|
|
142
173
|
- bin/console
|
|
143
174
|
- lib/tdlib-ruby.rb
|
|
144
175
|
- lib/tdlib/api.rb
|
|
145
176
|
- lib/tdlib/client.rb
|
|
146
177
|
- lib/tdlib/errors.rb
|
|
178
|
+
- lib/tdlib/update_handler.rb
|
|
147
179
|
- lib/tdlib/update_manager.rb
|
|
148
|
-
- lib/tdlib/utils.rb
|
|
149
180
|
- lib/tdlib/version.rb
|
|
150
181
|
- spec/integration/tdlib_spec.rb
|
|
151
182
|
- spec/spec_helper.rb
|
|
@@ -155,7 +186,7 @@ homepage: https://github.com/centosadmin/tdlib-ruby
|
|
|
155
186
|
licenses:
|
|
156
187
|
- MIT
|
|
157
188
|
metadata: {}
|
|
158
|
-
post_install_message:
|
|
189
|
+
post_install_message:
|
|
159
190
|
rdoc_options: []
|
|
160
191
|
require_paths:
|
|
161
192
|
- lib
|
|
@@ -170,9 +201,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
170
201
|
- !ruby/object:Gem::Version
|
|
171
202
|
version: '0'
|
|
172
203
|
requirements: []
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
signing_key:
|
|
204
|
+
rubygems_version: 3.1.4
|
|
205
|
+
signing_key:
|
|
176
206
|
specification_version: 4
|
|
177
207
|
summary: Ruby bindings and client for TDlib
|
|
178
208
|
test_files:
|