tdlib-ruby 0.1.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 +7 -0
- data/.document +3 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +4 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +142 -0
- data/Rakefile +25 -0
- data/lib/tdlib/api.rb +91 -0
- data/lib/tdlib/client.rb +167 -0
- data/lib/tdlib/errors.rb +5 -0
- data/lib/tdlib/update_manager.rb +44 -0
- data/lib/tdlib/utils.rb +7 -0
- data/lib/tdlib/version.rb +4 -0
- data/lib/tdlib-ruby.rb +39 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/update_manager_stub.rb +16 -0
- data/spec/tdlib_spec.rb +8 -0
- data/spec/unit/client_spec.rb +73 -0
- data/tdlib-ruby.gemspec +40 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f80634d27d92b157b5ce20130ab8a947b4bddfd348268f4126c37abd2d5f8cbe
|
4
|
+
data.tar.gz: 4b08b602b04eba761bc97349f1ea8f546158fee97a32a1242728e1c768cb5924
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9ce2500cb3d549cd7e252e0f62341709958dbbbab7f4cdd298bd48cf84c41609641c9136b220b29c1bb749d6c65397f8db4aebd31249407b5d41de36d6cce072
|
7
|
+
data.tar.gz: 395f571bdbdb46621b4a3ab78f04e83e5c9dbb173ad9cf737c2b9380608d995003ff2d86af6cc8fbdfebe1f960b6ae0a109c7394e9ad9dced47b57c13d321efc
|
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown --title "tdlib-ruby Documentation" --protected
|
data/ChangeLog.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2018 Southbridge
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
# tdlib-ruby
|
2
|
+
|
3
|
+
[](https://travis-ci.org/centosadmin/tdlib-ruby)
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
Ruby bindings and client for TDLib (Telegram database library).
|
8
|
+
|
9
|
+
## Requirements
|
10
|
+
|
11
|
+
* Ruby 2.3+
|
12
|
+
* Compiled [tdlib](https://github.com/tdlib/td)
|
13
|
+
|
14
|
+
## Install
|
15
|
+
|
16
|
+
Add to your gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'tdlib-ruby'
|
20
|
+
```
|
21
|
+
and run *bundle install*.
|
22
|
+
|
23
|
+
|
24
|
+
Or just run *gem install tdlib-ruby*
|
25
|
+
|
26
|
+
## Basic example
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require 'tdlib-ruby'
|
30
|
+
|
31
|
+
TD.configure do |config|
|
32
|
+
config.lib_path = 'path_to_dir_containing_tdlibjson'
|
33
|
+
|
34
|
+
config.client.api_id = your_api_id
|
35
|
+
config.client.api_hash = 'your_api_hash'
|
36
|
+
end
|
37
|
+
|
38
|
+
TD::Api.set_log_verbosity_level(1)
|
39
|
+
|
40
|
+
client = TD::Client.new
|
41
|
+
|
42
|
+
begin
|
43
|
+
state = nil
|
44
|
+
|
45
|
+
client.on('updateAuthorizationState') do |update|
|
46
|
+
next unless update.dig('authorization_state', '@type') == 'authorizationStateWaitPhoneNumber'
|
47
|
+
state = :wait_phone
|
48
|
+
end
|
49
|
+
|
50
|
+
client.on('updateAuthorizationState') do |update|
|
51
|
+
next unless update.dig('authorization_state', '@type') == 'authorizationStateWaitCode'
|
52
|
+
state = :wait_code
|
53
|
+
end
|
54
|
+
|
55
|
+
client.on('updateAuthorizationState') do |update|
|
56
|
+
next unless update.dig('authorization_state', '@type') == 'authorizationStateReady'
|
57
|
+
state = :ready
|
58
|
+
end
|
59
|
+
|
60
|
+
loop do
|
61
|
+
case state
|
62
|
+
when :wait_phone
|
63
|
+
p 'Please, enter your phone number:'
|
64
|
+
phone = STDIN.gets.strip
|
65
|
+
params = {
|
66
|
+
'@type' => 'setAuthenticationPhoneNumber',
|
67
|
+
'phone_number' => phone
|
68
|
+
}
|
69
|
+
client.broadcast_and_receive(params)
|
70
|
+
when :wait_code
|
71
|
+
p 'Please, enter code from SMS:'
|
72
|
+
code = STDIN.gets.strip
|
73
|
+
params = {
|
74
|
+
'@type' => 'checkAuthenticationCode',
|
75
|
+
'code' => code
|
76
|
+
}
|
77
|
+
client.broadcast_and_receive(params)
|
78
|
+
when :ready
|
79
|
+
@me = client.broadcast_and_receive('@type' => 'getMe')
|
80
|
+
break
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
ensure
|
85
|
+
client.close
|
86
|
+
end
|
87
|
+
|
88
|
+
p @me
|
89
|
+
```
|
90
|
+
|
91
|
+
## Configuration
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
TD.configure do |config|
|
95
|
+
config.lib_path = 'path/to/dir_containing_libtdjson' # libtdson will be searched in this directory (*.so, *.dylib, *.dll are valid extensions). For Rails projects, if not set, will be considered as project_root_path/vendor
|
96
|
+
config.encryption_key = 'your_encryption_key' # it's not required
|
97
|
+
|
98
|
+
config.client.api_id = 12345
|
99
|
+
config.client.api_hash = 'your_api_hash'
|
100
|
+
config.client.use_test_dc = true # default: false
|
101
|
+
config.database_directory = 'path/to/db/dir' # default: "#{Dir.home}/.tdlib-ruby/db"
|
102
|
+
config.files_directory = 'path/to/files/dir' # default: "#{Dir.home}/.tdlib-ruby/files"
|
103
|
+
config.client.use_chat_info_database = true # default: true
|
104
|
+
config.use_secret_chats = true # default: true
|
105
|
+
config.use_message_database = true # default: true
|
106
|
+
config.system_language_code = 'ru' # default: 'en'
|
107
|
+
config.device_model = 'Some device model' # default: 'Ruby TD client'
|
108
|
+
config.system_version = '42' # default: 'Unknown'
|
109
|
+
config.application_version = '1.0' # default: '1.0'
|
110
|
+
config.enable_storage_optimizer = true # default: true
|
111
|
+
config.ignore_file_names = true # default: false
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
## Advanced
|
116
|
+
|
117
|
+
You can get rid of large tdlib log with
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
TD::Api.set_log_verbosity_level(1)
|
121
|
+
```
|
122
|
+
|
123
|
+
You can also set log file path:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
TD::Api.set_log_file_path('path/to/log_file')
|
127
|
+
```
|
128
|
+
|
129
|
+
Additional options can be passed to client:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
TD::Client.new(database_directory: 'will override value from config',
|
133
|
+
files_directory: 'will override value from config')
|
134
|
+
```
|
135
|
+
|
136
|
+
## License
|
137
|
+
|
138
|
+
[MIT](https://github.com/centosadmin/tdlib-ruby/blob/master/LICENSE.txt)
|
139
|
+
|
140
|
+
## Authors
|
141
|
+
|
142
|
+
The gem is designed by [Southbridge](https://southbridge.io)
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler/setup'
|
7
|
+
rescue LoadError => e
|
8
|
+
abort e.message
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rake'
|
12
|
+
|
13
|
+
|
14
|
+
require 'rubygems/tasks'
|
15
|
+
Gem::Tasks.new
|
16
|
+
|
17
|
+
require 'rspec/core/rake_task'
|
18
|
+
RSpec::Core::RakeTask.new
|
19
|
+
|
20
|
+
task :test => :spec
|
21
|
+
task :default => :spec
|
22
|
+
|
23
|
+
require 'yard'
|
24
|
+
YARD::Rake::YardocTask.new
|
25
|
+
task :doc => :yard
|
data/lib/tdlib/api.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'fiddle/import'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module TD::Api
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def client_create
|
8
|
+
Dl.td_json_client_create
|
9
|
+
end
|
10
|
+
|
11
|
+
def client_send(client, params)
|
12
|
+
Dl.td_json_client_send(client, params.to_json)
|
13
|
+
end
|
14
|
+
|
15
|
+
def client_execute(client, params)
|
16
|
+
Dl.td_json_client_execute(client, params.to_json)
|
17
|
+
end
|
18
|
+
|
19
|
+
def client_receive(client, timeout)
|
20
|
+
update = Dl.td_json_client_receive(client, timeout)
|
21
|
+
update.null? ? nil : JSON.parse(update.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
def client_destroy(client)
|
25
|
+
Dl.td_json_client_destroy(client)
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_log_verbosity_level(level)
|
29
|
+
Dl.td_set_log_verbosity_level(level)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_log_file_path(path)
|
33
|
+
Dl.td_set_log_file_path(path)
|
34
|
+
end
|
35
|
+
|
36
|
+
module Dl
|
37
|
+
extend Fiddle::Importer
|
38
|
+
|
39
|
+
module_function
|
40
|
+
|
41
|
+
def method_missing(method_name, *args)
|
42
|
+
raise TD::MissingLibPathError unless lib_path
|
43
|
+
|
44
|
+
dlload(find_lib)
|
45
|
+
|
46
|
+
extern 'void* td_json_client_create()'
|
47
|
+
extern 'void* td_json_client_send(void*, char*)'
|
48
|
+
extern 'char* td_json_client_receive(void*, double)'
|
49
|
+
extern 'char* td_json_client_execute(void*, char*)'
|
50
|
+
extern 'void td_set_log_verbosity_level(int)'
|
51
|
+
extern 'void td_json_client_destroy(void*)'
|
52
|
+
extern 'void td_set_log_file_path(char*)'
|
53
|
+
|
54
|
+
undef method_missing
|
55
|
+
public_send(method_name, *args)
|
56
|
+
end
|
57
|
+
|
58
|
+
def lib_path
|
59
|
+
TD.config.lib_path || (defined?(Rails) ? Rails.root.join('vendor').to_s : nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
def find_lib
|
63
|
+
lib_extension =
|
64
|
+
case os
|
65
|
+
when :windows then 'dll'
|
66
|
+
when :macos then 'dylib'
|
67
|
+
when :linux then 'so'
|
68
|
+
else raise "#{os} OS is not supported"
|
69
|
+
end
|
70
|
+
File.join(lib_path, "libtdjson.#{lib_extension}")
|
71
|
+
end
|
72
|
+
|
73
|
+
def os
|
74
|
+
host_os = RbConfig::CONFIG['host_os']
|
75
|
+
case host_os
|
76
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
77
|
+
:windows
|
78
|
+
when /darwin|mac os/
|
79
|
+
:macos
|
80
|
+
when /linux/
|
81
|
+
:linux
|
82
|
+
when /solaris|bsd/
|
83
|
+
:unix
|
84
|
+
else
|
85
|
+
raise "Unknown os: #{host_os.inspect}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private_constant :Dl
|
91
|
+
end
|
data/lib/tdlib/client.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
# 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
|
+
class TD::Client
|
61
|
+
TIMEOUT = 10
|
62
|
+
|
63
|
+
def initialize(td_client = TD::Api.client_create,
|
64
|
+
update_manager = TD::UpdateManager.new(td_client),
|
65
|
+
**extra_config)
|
66
|
+
@td_client = td_client
|
67
|
+
@update_manager = update_manager
|
68
|
+
@config = TD.config.client.to_h.merge(extra_config)
|
69
|
+
authorize
|
70
|
+
end
|
71
|
+
|
72
|
+
# Sends asynchronous request to the TDLib client
|
73
|
+
# @param [Hash] query
|
74
|
+
# @yield [update] yields update to the block as soon as it's received
|
75
|
+
def broadcast(query)
|
76
|
+
if block_given?
|
77
|
+
extra = TD::Utils.generate_extra(query)
|
78
|
+
handler = ->(update) do
|
79
|
+
return unless update['@extra'] == extra
|
80
|
+
yield update
|
81
|
+
@update_manager.remove_handler(handler)
|
82
|
+
end
|
83
|
+
@update_manager.add_handler(handler)
|
84
|
+
query['@extra'] = extra
|
85
|
+
end
|
86
|
+
TD::Api.client_send(@td_client, query)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Sends asynchronous request to the TDLib client and returns received update synchronously
|
90
|
+
# @param [Hash] query
|
91
|
+
# @return [Hash]
|
92
|
+
def broadcast_and_receive(query)
|
93
|
+
result = nil
|
94
|
+
extra = TD::Utils.generate_extra(query)
|
95
|
+
handler = ->(update) { result = update if update['@extra'] == extra }
|
96
|
+
@update_manager.add_handler(handler)
|
97
|
+
query['@extra'] = extra
|
98
|
+
TD::Api.client_send(@td_client, query)
|
99
|
+
Timeout.timeout(TIMEOUT) do
|
100
|
+
loop do
|
101
|
+
if result
|
102
|
+
@update_manager.remove_handler(handler)
|
103
|
+
return result
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Synchronously executes TDLib request
|
110
|
+
# Only a few requests can be executed synchronously
|
111
|
+
# @param [Hash] query
|
112
|
+
def execute(query)
|
113
|
+
TD::Api.client_execute(@td_client, query)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns current authorization state (it's offline request)
|
117
|
+
# @return [Hash]
|
118
|
+
def authorization_state
|
119
|
+
broadcast_and_receive('@type' => 'getAuthorizationState')
|
120
|
+
end
|
121
|
+
|
122
|
+
# Binds passed block as a handler for updates with type of *update_type*
|
123
|
+
# @param [String] update_type
|
124
|
+
# @yield [update] yields update to the block as soon as it's received
|
125
|
+
def on(update_type, &_)
|
126
|
+
handler = ->(update) do
|
127
|
+
return unless update['@type'] == update_type
|
128
|
+
yield update
|
129
|
+
end
|
130
|
+
@update_manager.add_handler(handler)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Stops update manager and destroys TDLib client
|
134
|
+
def close
|
135
|
+
@update_manager.stop
|
136
|
+
TD::Api.client_destroy(@td_client)
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def authorize
|
142
|
+
tdlib_params_query = {
|
143
|
+
'@type' => 'setTdlibParameters',
|
144
|
+
parameters: { '@type' => 'tdlibParameters', **@config }
|
145
|
+
}
|
146
|
+
encryption_key_query = {
|
147
|
+
'@type' => 'checkDatabaseEncryptionKey',
|
148
|
+
}
|
149
|
+
|
150
|
+
if TD.config.encryption_key
|
151
|
+
encryption_key_query['encryption_key'] = TD.config.encryption_key
|
152
|
+
end
|
153
|
+
|
154
|
+
handler = ->(update) do
|
155
|
+
return unless update['@type'] == 'updateAuthorizationState'
|
156
|
+
case update.dig('authorization_state', '@type')
|
157
|
+
when 'authorizationStateWaitTdlibParameters'
|
158
|
+
broadcast(tdlib_params_query)
|
159
|
+
when 'authorizationStateWaitEncryptionKey'
|
160
|
+
broadcast(encryption_key_query)
|
161
|
+
else
|
162
|
+
@update_manager.remove_handler(handler)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
@update_manager.add_handler(handler)
|
166
|
+
end
|
167
|
+
end
|
data/lib/tdlib/errors.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
class TD::UpdateManager
|
2
|
+
attr_reader :handlers
|
3
|
+
|
4
|
+
def initialize(td_client)
|
5
|
+
@td_client = td_client
|
6
|
+
@handlers = []
|
7
|
+
@handlers_for_removal = []
|
8
|
+
@mutex = Mutex.new
|
9
|
+
init_update_loop
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_handler(handler)
|
13
|
+
@mutex.synchronize { @handlers << handler }
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove_handler(handler)
|
17
|
+
Thread.start do
|
18
|
+
@mutex.synchronize { @handlers.delete(handler) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop
|
23
|
+
@stopped = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def stopped?
|
27
|
+
!!@stopped
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def init_update_loop
|
33
|
+
@update_loop_thread = Thread.start do
|
34
|
+
loop { stopped? ? break : handle_update }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_update
|
39
|
+
update = TD::Api.client_receive(@td_client, 10)
|
40
|
+
@mutex.synchronize do
|
41
|
+
@handlers.each { |h| h.call(update) } unless update.nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/tdlib/utils.rb
ADDED
data/lib/tdlib-ruby.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'tdlib/version'
|
2
|
+
require 'dry/configurable'
|
3
|
+
|
4
|
+
module TD
|
5
|
+
extend Dry::Configurable
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def root_path
|
10
|
+
__dir__
|
11
|
+
end
|
12
|
+
|
13
|
+
setting :lib_path
|
14
|
+
|
15
|
+
setting :encryption_key
|
16
|
+
|
17
|
+
setting :client do
|
18
|
+
setting :api_id
|
19
|
+
setting :api_hash
|
20
|
+
setting :use_test_dc, false
|
21
|
+
setting :database_directory, "#{Dir.home}/.tdlib-ruby/db"
|
22
|
+
setting :files_directory, "#{Dir.home}/.tdlib-ruby/data"
|
23
|
+
setting :use_chat_info_database, true
|
24
|
+
setting :use_secret_chats, true
|
25
|
+
setting :use_message_database, true
|
26
|
+
setting :system_language_code, 'en'
|
27
|
+
setting :device_model, 'Ruby TD client'
|
28
|
+
setting :system_version, 'Unknown'
|
29
|
+
setting :application_version, '1.0'
|
30
|
+
setting :enable_storage_optimizer, true
|
31
|
+
setting :ignore_file_names, false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'tdlib/errors'
|
36
|
+
require 'tdlib/api'
|
37
|
+
require 'tdlib/utils'
|
38
|
+
require 'tdlib/client'
|
39
|
+
require 'tdlib/update_manager'
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class UpdateManagerStub
|
2
|
+
attr_reader :handlers
|
3
|
+
|
4
|
+
def initialize(td_client, update)
|
5
|
+
@td_client, @update, @handlers = td_client, update, []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_handler(handler)
|
9
|
+
@handlers << handler
|
10
|
+
handler.call(@update)
|
11
|
+
end
|
12
|
+
|
13
|
+
def remove_handler(handler)
|
14
|
+
@handlers.delete(handler)
|
15
|
+
end
|
16
|
+
end
|
data/spec/tdlib_spec.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tdlib-ruby'
|
3
|
+
require 'support/update_manager_stub'
|
4
|
+
|
5
|
+
Thread.abort_on_exception = true
|
6
|
+
|
7
|
+
describe TD::Client do
|
8
|
+
let(:client) { described_class.new(td_client, update_manager) }
|
9
|
+
let(:td_client) { double }
|
10
|
+
let(:update_manager) { UpdateManagerStub.new(td_client, update) }
|
11
|
+
let(:query) { { '@type' => 'type' } }
|
12
|
+
let(:send_result) { 'send_result' }
|
13
|
+
let(:update) { { '@type' => 'update' } }
|
14
|
+
let(:extra) { 'extra' }
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(TD::Api).to receive(:client_create).and_return(td_client)
|
18
|
+
allow(TD::Api).to receive(:client_send).with(td_client, query).and_return(send_result)
|
19
|
+
allow(TD::Api).to receive(:client_execute).with(td_client, query).and_return(send_result)
|
20
|
+
allow(TD::Api).to receive(:client_receive).with(td_client).and_return(update)
|
21
|
+
|
22
|
+
allow(TD::Utils).to receive(:generate_extra).with(query).and_return(extra)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#broadcast' do
|
26
|
+
context 'when no block given' do
|
27
|
+
subject { client.broadcast(query) }
|
28
|
+
|
29
|
+
it { is_expected.to eq(send_result) }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when block given' do
|
33
|
+
subject { client.broadcast(query) { |update| raise update.to_s } }
|
34
|
+
|
35
|
+
it 'adds @extra key to query' do
|
36
|
+
subject
|
37
|
+
expect(query.keys).to include('@extra')
|
38
|
+
end
|
39
|
+
|
40
|
+
it { is_expected.to eq(send_result) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#broadcast_and_receive' do
|
45
|
+
let(:update) { { '@type' => 'update', '@extra' => extra } }
|
46
|
+
|
47
|
+
subject { client.broadcast_and_receive(query) }
|
48
|
+
|
49
|
+
it { is_expected.to eq(update) }
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#execute' do
|
53
|
+
subject { client.execute(query) }
|
54
|
+
|
55
|
+
it { is_expected.to eq(send_result) }
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#on' do
|
59
|
+
subject { client.on('update') { |update| update } }
|
60
|
+
|
61
|
+
context 'when update type matches passed type' do
|
62
|
+
let(:update) { { '@type' => 'update', '@extra' => extra } }
|
63
|
+
|
64
|
+
it { is_expected.to eq(update) }
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when update type does not match passed type' do
|
68
|
+
let(:update) { { '@type' => 'not_update', '@extra' => extra } }
|
69
|
+
|
70
|
+
it { is_expected.not_to eq(update) }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/tdlib-ruby.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'tdlib/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |gem|
|
8
|
+
gem.name = "tdlib-ruby"
|
9
|
+
gem.version = TD::VERSION
|
10
|
+
gem.summary = 'Ruby bindings and client for TDlib'
|
11
|
+
gem.description = %q{Description}
|
12
|
+
gem.license = "MIT"
|
13
|
+
gem.authors = ["Southbridge"]
|
14
|
+
gem.email = "ask@southbridge.io"
|
15
|
+
gem.homepage = "https://rubygems.org/gems/tdlib-ruby"
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($/)
|
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
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
29
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
30
|
+
gem.require_paths = ['lib']
|
31
|
+
|
32
|
+
gem.add_runtime_dependency 'dry-configurable', '~> 0.7'
|
33
|
+
|
34
|
+
gem.add_development_dependency 'bundler', '~> 1.10'
|
35
|
+
gem.add_development_dependency 'rake', '~> 10.0'
|
36
|
+
gem.add_development_dependency 'rspec', '~> 3.0'
|
37
|
+
gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
38
|
+
gem.add_development_dependency 'yard', '~> 0.9'
|
39
|
+
gem.add_development_dependency 'pry', '~> 0.11'
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tdlib-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Southbridge
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-configurable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubygems-tasks
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.2'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.9'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.9'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.11'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.11'
|
111
|
+
description: Description
|
112
|
+
email: ask@southbridge.io
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- ".document"
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rspec"
|
120
|
+
- ".travis.yml"
|
121
|
+
- ".yardopts"
|
122
|
+
- ChangeLog.md
|
123
|
+
- Gemfile
|
124
|
+
- LICENSE.txt
|
125
|
+
- README.md
|
126
|
+
- Rakefile
|
127
|
+
- lib/tdlib-ruby.rb
|
128
|
+
- lib/tdlib/api.rb
|
129
|
+
- lib/tdlib/client.rb
|
130
|
+
- lib/tdlib/errors.rb
|
131
|
+
- lib/tdlib/update_manager.rb
|
132
|
+
- lib/tdlib/utils.rb
|
133
|
+
- lib/tdlib/version.rb
|
134
|
+
- spec/spec_helper.rb
|
135
|
+
- spec/support/update_manager_stub.rb
|
136
|
+
- spec/tdlib_spec.rb
|
137
|
+
- spec/unit/client_spec.rb
|
138
|
+
- tdlib-ruby.gemspec
|
139
|
+
homepage: https://rubygems.org/gems/tdlib-ruby
|
140
|
+
licenses:
|
141
|
+
- MIT
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 2.7.3
|
160
|
+
signing_key:
|
161
|
+
specification_version: 4
|
162
|
+
summary: Ruby bindings and client for TDlib
|
163
|
+
test_files:
|
164
|
+
- spec/spec_helper.rb
|
165
|
+
- spec/support/update_manager_stub.rb
|
166
|
+
- spec/tdlib_spec.rb
|
167
|
+
- spec/unit/client_spec.rb
|