mtproto 0.0.8 → 0.0.9
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/ext/aes_ige/extconf.rb +3 -9
- data/ext/factorization/extconf.rb +2 -0
- data/lib/mtproto/auth_key_generator.rb +68 -105
- data/lib/mtproto/binary.rb +21 -0
- data/lib/mtproto/client/api/check_password.rb +41 -0
- data/lib/mtproto/client/api/export_login_token.rb +27 -0
- data/lib/mtproto/client/api/get_updates_difference.rb +21 -0
- data/lib/mtproto/client/api/get_updates_state.rb +14 -0
- data/lib/mtproto/client/api/get_users.rb +14 -0
- data/lib/mtproto/client/api/import_login_token.rb +23 -0
- data/lib/mtproto/client/api/send_code.rb +21 -0
- data/lib/mtproto/client/api/sign_in.rb +27 -0
- data/lib/mtproto/client/api.rb +28 -0
- data/lib/mtproto/client/rpc/response.rb +63 -0
- data/lib/mtproto/client/rpc.rb +61 -125
- data/lib/mtproto/client.rb +142 -31
- data/lib/mtproto/crypto/dh_key_exchange.rb +1 -2
- data/lib/mtproto/crypto/dh_validator.rb +17 -19
- data/lib/mtproto/crypto/factorization.rb +1 -1
- data/lib/mtproto/crypto/rsa_key.rb +2 -2
- data/lib/mtproto/crypto/srp.rb +117 -0
- data/lib/mtproto/delegate_methods.rb +11 -0
- data/lib/mtproto/message/message.rb +85 -0
- data/lib/mtproto/session.rb +1 -1
- data/lib/mtproto/tl/constructors.rb +2269 -0
- data/lib/mtproto/tl/object.rb +25 -0
- data/lib/mtproto/tl/objects/account_password.rb +72 -0
- data/lib/mtproto/tl/objects/authorization.rb +73 -0
- data/lib/mtproto/tl/objects/check_password.rb +46 -0
- data/lib/mtproto/tl/objects/client_dh_inner_data.rb +47 -0
- data/lib/mtproto/tl/objects/dh_gen_response.rb +50 -0
- data/lib/mtproto/tl/objects/export_login_token.rb +51 -0
- data/lib/mtproto/tl/objects/get_config.rb +15 -0
- data/lib/mtproto/tl/objects/get_difference.rb +36 -0
- data/lib/mtproto/tl/objects/get_password.rb +15 -0
- data/lib/mtproto/tl/objects/get_state.rb +15 -0
- data/lib/mtproto/tl/objects/get_users.rb +20 -0
- data/lib/mtproto/tl/objects/help_config.rb +77 -0
- data/lib/mtproto/tl/objects/import_login_token.rb +39 -0
- data/lib/mtproto/tl/objects/init_connection.rb +59 -0
- data/lib/mtproto/tl/objects/invoke_with_layer.rb +22 -0
- data/lib/mtproto/tl/objects/login_token.rb +82 -0
- data/lib/mtproto/tl/objects/pq_inner_data.rb +69 -0
- data/lib/mtproto/tl/objects/req_dh_params.rb +65 -0
- data/lib/mtproto/tl/objects/req_pq_multi.rb +23 -0
- data/lib/mtproto/tl/objects/res_pq.rb +75 -0
- data/lib/mtproto/tl/objects/send_code.rb +50 -0
- data/lib/mtproto/tl/objects/sent_code.rb +79 -0
- data/lib/mtproto/tl/objects/server_dh_inner_data.rb +74 -0
- data/lib/mtproto/tl/objects/server_dh_params.rb +53 -0
- data/lib/mtproto/tl/objects/set_client_dh_params.rb +48 -0
- data/lib/mtproto/tl/objects/sign_in.rb +47 -0
- data/lib/mtproto/tl/objects/update.rb +80 -0
- data/lib/mtproto/tl/objects/update_short.rb +22 -0
- data/lib/mtproto/tl/objects/update_short_message.rb +67 -0
- data/lib/mtproto/tl/objects/updates_difference.rb +157 -0
- data/lib/mtproto/tl/objects/updates_state.rb +37 -0
- data/lib/mtproto/tl/objects/users.rb +86 -0
- data/lib/mtproto/transport/abridged_packet_codec.rb +35 -12
- data/lib/mtproto/transport/connection.rb +23 -0
- data/lib/mtproto/transport/errors.rb +11 -0
- data/lib/mtproto/transport/packet.rb +19 -0
- data/lib/mtproto/transport/tcp_connection.rb +57 -46
- data/lib/mtproto/type/bad_msg_notification.rb +10 -10
- data/lib/mtproto/type/gzip_packed.rb +5 -3
- data/lib/mtproto/type/message.rb +2 -2
- data/lib/mtproto/type/rpc_error.rb +0 -1
- data/lib/mtproto/updates_poller.rb +37 -33
- data/lib/mtproto/version.rb +1 -1
- data/lib/mtproto.rb +11 -17
- data/scripts/generate_constructors.rb +65 -0
- metadata +62 -51
- data/lib/mtproto/async/middleware/base.rb +0 -17
- data/lib/mtproto/async/middleware/flood_wait.rb +0 -42
- data/lib/mtproto/async/request.rb +0 -18
- data/lib/mtproto/async/request_queue.rb +0 -63
- data/lib/mtproto/async_client.rb +0 -201
- data/lib/mtproto/rpc/get_config.rb +0 -34
- data/lib/mtproto/rpc/get_contacts.rb +0 -29
- data/lib/mtproto/rpc/get_updates_difference.rb +0 -51
- data/lib/mtproto/rpc/get_updates_state.rb +0 -29
- data/lib/mtproto/rpc/get_users.rb +0 -29
- data/lib/mtproto/rpc/ping.rb +0 -33
- data/lib/mtproto/rpc/send_code.rb +0 -41
- data/lib/mtproto/rpc/send_message.rb +0 -47
- data/lib/mtproto/rpc/sign_in.rb +0 -48
- data/lib/mtproto/type/auth_key/dh_gen_response.rb +0 -37
- data/lib/mtproto/type/auth_key/req_dh_params.rb +0 -31
- data/lib/mtproto/type/auth_key/req_pq_multi.rb +0 -18
- data/lib/mtproto/type/auth_key/res_pq.rb +0 -62
- data/lib/mtproto/type/auth_key/server_dh_params.rb +0 -43
- data/lib/mtproto/type/auth_key/set_client_dh_params.rb +0 -25
- data/lib/mtproto/type/code_settings.rb +0 -25
- data/lib/mtproto/type/config.rb +0 -124
- data/lib/mtproto/type/rpc/auth/authorization.rb +0 -107
- data/lib/mtproto/type/rpc/auth/send_code.rb +0 -28
- data/lib/mtproto/type/rpc/auth/sent_code.rb +0 -36
- data/lib/mtproto/type/rpc/auth/sign_in.rb +0 -32
- data/lib/mtproto/type/rpc/contacts/contacts.rb +0 -155
- data/lib/mtproto/type/rpc/contacts/get_contacts.rb +0 -18
- data/lib/mtproto/type/rpc/help/config.rb +0 -35
- data/lib/mtproto/type/rpc/help/get_config.rb +0 -17
- data/lib/mtproto/type/rpc/init_connection.rb +0 -28
- data/lib/mtproto/type/rpc/invoke_with_layer.rb +0 -19
- data/lib/mtproto/type/rpc/messages/send_message.rb +0 -43
- data/lib/mtproto/type/rpc/messages/updates.rb +0 -87
- data/lib/mtproto/type/rpc/ping.rb +0 -18
- data/lib/mtproto/type/rpc/pong.rb +0 -46
- data/lib/mtproto/type/rpc/updates/difference.rb +0 -332
- data/lib/mtproto/type/rpc/updates/get_difference.rb +0 -42
- data/lib/mtproto/type/rpc/updates/get_state.rb +0 -17
- data/lib/mtproto/type/rpc/updates/state.rb +0 -59
- data/lib/mtproto/type/rpc/users/get_users.rb +0 -25
- data/lib/mtproto/type/rpc/users/users.rb +0 -99
- data/lib/mtproto/type/sent_code.rb +0 -128
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Async
|
|
5
|
-
module Middleware
|
|
6
|
-
class Base
|
|
7
|
-
def initialize(app)
|
|
8
|
-
@app = app
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def call(request, future, retry_fn, retries)
|
|
12
|
-
@app.call(request, future, retry_fn, retries)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'base'
|
|
4
|
-
|
|
5
|
-
module MTProto
|
|
6
|
-
module Async
|
|
7
|
-
module Middleware
|
|
8
|
-
class FloodWait < Base
|
|
9
|
-
def initialize(app, max_retries: 5)
|
|
10
|
-
super(app)
|
|
11
|
-
@max_retries = max_retries
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def call(request, future, retry_fn, retries)
|
|
15
|
-
wrapped = @app.call(request, future, retry_fn, retries)
|
|
16
|
-
|
|
17
|
-
wrapped.rescue do |error|
|
|
18
|
-
if flood_wait_error?(error) && retries < @max_retries
|
|
19
|
-
delay = extract_delay(error.error_message)
|
|
20
|
-
sleep(delay)
|
|
21
|
-
retry_fn.call.value!
|
|
22
|
-
else
|
|
23
|
-
raise error
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def flood_wait_error?(error)
|
|
31
|
-
error.is_a?(MTProto::RpcError) &&
|
|
32
|
-
error.error_code == 420 &&
|
|
33
|
-
error.error_message.start_with?('FLOOD_WAIT_')
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def extract_delay(error_message)
|
|
37
|
-
error_message[11..-1].to_i
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module MTProto
|
|
4
|
-
module Async
|
|
5
|
-
class Request
|
|
6
|
-
attr_reader :body, :metadata
|
|
7
|
-
|
|
8
|
-
def initialize(body:, metadata: {})
|
|
9
|
-
@body = body
|
|
10
|
-
@metadata = metadata
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def key
|
|
14
|
-
metadata[:key] || :default
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'concurrent-ruby'
|
|
4
|
-
|
|
5
|
-
module MTProto
|
|
6
|
-
module Async
|
|
7
|
-
class RequestQueue
|
|
8
|
-
def initialize
|
|
9
|
-
@queues = Concurrent::Hash.new
|
|
10
|
-
@threads = Concurrent::Hash.new
|
|
11
|
-
@running = Concurrent::AtomicBoolean.new(true)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def call(key:, &blk)
|
|
15
|
-
ensure_worker_running!(key)
|
|
16
|
-
|
|
17
|
-
future = Concurrent::Promises.resolvable_future
|
|
18
|
-
@queues[key] << [blk, future]
|
|
19
|
-
future
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def shutdown
|
|
23
|
-
@running.make_false
|
|
24
|
-
@threads.each_value do |thread|
|
|
25
|
-
thread.join(2)
|
|
26
|
-
thread.kill if thread.alive?
|
|
27
|
-
end
|
|
28
|
-
@threads.clear
|
|
29
|
-
@queues.clear
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
private
|
|
33
|
-
|
|
34
|
-
def ensure_worker_running!(key)
|
|
35
|
-
return if @threads.key?(key) && @threads[key].alive?
|
|
36
|
-
|
|
37
|
-
@queues[key] ||= Queue.new
|
|
38
|
-
@threads[key] = Thread.new { worker_loop(key) }
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def worker_loop(key)
|
|
42
|
-
queue = @queues[key]
|
|
43
|
-
loop do
|
|
44
|
-
break unless @running.true?
|
|
45
|
-
|
|
46
|
-
begin
|
|
47
|
-
blk, future = queue.pop(true)
|
|
48
|
-
result = blk.call
|
|
49
|
-
if result.is_a?(Concurrent::Promises::Future)
|
|
50
|
-
result.then { |v| future.fulfill(v) }.rescue { |e| future.reject(e) }
|
|
51
|
-
else
|
|
52
|
-
future.fulfill(result)
|
|
53
|
-
end
|
|
54
|
-
rescue ThreadError
|
|
55
|
-
sleep 0.01
|
|
56
|
-
rescue => e
|
|
57
|
-
future&.reject(e) if future
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
data/lib/mtproto/async_client.rb
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'concurrent'
|
|
4
|
-
require_relative 'async/request'
|
|
5
|
-
require_relative 'async/request_queue'
|
|
6
|
-
require_relative 'async/middleware/base'
|
|
7
|
-
require_relative 'async/middleware/flood_wait'
|
|
8
|
-
|
|
9
|
-
module MTProto
|
|
10
|
-
class AsyncClient
|
|
11
|
-
attr_reader :client
|
|
12
|
-
|
|
13
|
-
def initialize(client)
|
|
14
|
-
@client = client
|
|
15
|
-
@queue = Async::RequestQueue.new
|
|
16
|
-
@middleware_classes = []
|
|
17
|
-
@pending_requests = Concurrent::Hash.new
|
|
18
|
-
@timeout_threads = Concurrent::Hash.new
|
|
19
|
-
@receiver_thread = nil
|
|
20
|
-
@running = Concurrent::AtomicBoolean.new(false)
|
|
21
|
-
|
|
22
|
-
use(Async::Middleware::FloodWait)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def use(middleware_class, **options)
|
|
26
|
-
@middleware_classes << [middleware_class, options]
|
|
27
|
-
self
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def call(body, metadata: {})
|
|
31
|
-
ensure_receiver_running!
|
|
32
|
-
|
|
33
|
-
request = Async::Request.new(body: body, metadata: metadata)
|
|
34
|
-
|
|
35
|
-
@queue.call(key: request.key) do
|
|
36
|
-
send_and_wrap = lambda do |retries = 0|
|
|
37
|
-
base_future = send_request(request.body)
|
|
38
|
-
|
|
39
|
-
retry_fn = lambda do
|
|
40
|
-
send_and_wrap.call(retries + 1)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
build_middleware_stack.call(request, base_future, retry_fn, retries)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
send_and_wrap.call(0)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def shutdown
|
|
51
|
-
@running.make_false
|
|
52
|
-
|
|
53
|
-
@client.disconnect! if @client.connected?
|
|
54
|
-
|
|
55
|
-
if @receiver_thread
|
|
56
|
-
@receiver_thread.join(2)
|
|
57
|
-
@receiver_thread.kill if @receiver_thread.alive?
|
|
58
|
-
@receiver_thread = nil
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
@timeout_threads.each_value(&:kill)
|
|
62
|
-
@timeout_threads.clear
|
|
63
|
-
|
|
64
|
-
@pending_requests.each_value do |future|
|
|
65
|
-
future.reject(MTProto::Transport::ConnectionError.new('Client shutting down')) unless future.resolved?
|
|
66
|
-
end
|
|
67
|
-
@pending_requests.clear
|
|
68
|
-
|
|
69
|
-
@queue.shutdown
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
private
|
|
73
|
-
|
|
74
|
-
def send_request(body)
|
|
75
|
-
msg_id = @client.rpc.call(body)
|
|
76
|
-
future = Concurrent::Promises.resolvable_future
|
|
77
|
-
@pending_requests[msg_id] = future
|
|
78
|
-
|
|
79
|
-
timeout_thread = Thread.new do
|
|
80
|
-
sleep @client.timeout
|
|
81
|
-
if @pending_requests.delete(msg_id)
|
|
82
|
-
future.reject(MTProto::Transport::ConnectionError.new('RPC timeout'))
|
|
83
|
-
end
|
|
84
|
-
@timeout_threads.delete(msg_id)
|
|
85
|
-
end
|
|
86
|
-
@timeout_threads[msg_id] = timeout_thread
|
|
87
|
-
|
|
88
|
-
future.on_fulfillment! do
|
|
89
|
-
timeout_thread.kill
|
|
90
|
-
@timeout_threads.delete(msg_id)
|
|
91
|
-
end
|
|
92
|
-
future.on_rejection! do
|
|
93
|
-
timeout_thread.kill
|
|
94
|
-
@timeout_threads.delete(msg_id)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
future
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def ensure_receiver_running!
|
|
101
|
-
return if @running.true?
|
|
102
|
-
|
|
103
|
-
@running.make_true
|
|
104
|
-
@receiver_thread = Thread.new { receiver_loop }
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def receiver_loop
|
|
108
|
-
loop do
|
|
109
|
-
break unless @running.true?
|
|
110
|
-
|
|
111
|
-
begin
|
|
112
|
-
response_data = @client.connection.recv(timeout: 1)
|
|
113
|
-
|
|
114
|
-
decrypted = EncryptedMessage.decrypt(
|
|
115
|
-
auth_key: @client.auth_key,
|
|
116
|
-
encrypted_message_data: response_data,
|
|
117
|
-
sender: :server
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
process_message(decrypted[:body])
|
|
121
|
-
rescue MTProto::Transport::ConnectionError => e
|
|
122
|
-
next if e.message == 'Receive timeout' && @running.true?
|
|
123
|
-
break
|
|
124
|
-
rescue IOError => e
|
|
125
|
-
break
|
|
126
|
-
rescue => e
|
|
127
|
-
warn "AsyncClient receiver error: #{e.class}: #{e.message}"
|
|
128
|
-
warn e.backtrace.join("\n")
|
|
129
|
-
break
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def process_message(response_body)
|
|
135
|
-
constructor = response_body[0, 4].unpack1('L<')
|
|
136
|
-
|
|
137
|
-
case constructor
|
|
138
|
-
when Client::RPC::CONSTRUCTOR_BAD_SERVER_SALT
|
|
139
|
-
handle_bad_server_salt(response_body)
|
|
140
|
-
when Type::NewSessionCreated::CONSTRUCTOR
|
|
141
|
-
handle_new_session(response_body)
|
|
142
|
-
when Type::MsgContainer::CONSTRUCTOR
|
|
143
|
-
handle_container(response_body)
|
|
144
|
-
when Client::RPC::CONSTRUCTOR_RPC_RESULT
|
|
145
|
-
handle_rpc_result(response_body)
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def handle_bad_server_salt(response_body)
|
|
150
|
-
offset = 4
|
|
151
|
-
offset += 8
|
|
152
|
-
offset += 4
|
|
153
|
-
offset += 4
|
|
154
|
-
new_server_salt = response_body[offset, 8].unpack1('Q<')
|
|
155
|
-
|
|
156
|
-
@client.instance_variable_set(:@server_salt, new_server_salt)
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def handle_new_session(response_body)
|
|
160
|
-
session_info = Type::NewSessionCreated.deserialize(response_body)
|
|
161
|
-
@client.instance_variable_set(:@server_salt, session_info.server_salt)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def handle_container(response_body)
|
|
165
|
-
container = Type::MsgContainer.deserialize(response_body)
|
|
166
|
-
|
|
167
|
-
container.messages.each do |msg|
|
|
168
|
-
process_message(msg[:body])
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def handle_rpc_result(response_body)
|
|
173
|
-
offset = 4
|
|
174
|
-
req_msg_id = response_body[offset, 8].unpack1('Q<')
|
|
175
|
-
offset += 8
|
|
176
|
-
result = response_body[offset..]
|
|
177
|
-
|
|
178
|
-
future = @pending_requests.delete(req_msg_id)
|
|
179
|
-
return unless future # No pending request for this msg_id
|
|
180
|
-
|
|
181
|
-
# Check if result is an RPC error
|
|
182
|
-
result_constructor = result[0, 4].unpack1('L<')
|
|
183
|
-
if result_constructor == Type::RpcError::CONSTRUCTOR
|
|
184
|
-
error = Type::RpcError.deserialize(result)
|
|
185
|
-
future.reject(MTProto::RpcError.new(error.error_code, error.error_message))
|
|
186
|
-
else
|
|
187
|
-
future.fulfill(result)
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
def build_middleware_stack
|
|
192
|
-
# Middleware now wraps Futures and can trigger retries
|
|
193
|
-
# The base "app" just returns the Future as-is
|
|
194
|
-
app = ->(request, future, retry_fn, retries) { future }
|
|
195
|
-
|
|
196
|
-
@middleware_classes.reverse.reduce(app) do |stack, (middleware_class, options)|
|
|
197
|
-
middleware_class.new(stack, **options)
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
end
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/help/get_config'
|
|
4
|
-
require_relative '../type/rpc/help/config'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class GetConfig
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call
|
|
14
|
-
query = build_query
|
|
15
|
-
|
|
16
|
-
@client.rpc.call(query)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def call_sync
|
|
20
|
-
query = build_query
|
|
21
|
-
|
|
22
|
-
response = @client.rpc.call_sync(query)
|
|
23
|
-
|
|
24
|
-
Type::RPC::Help::Config.parse(response)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
def build_query
|
|
30
|
-
Type::RPC::Help::GetConfig.build
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/contacts/get_contacts'
|
|
4
|
-
require_relative '../type/rpc/contacts/contacts'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class GetContacts
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(hash: 0)
|
|
14
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
15
|
-
|
|
16
|
-
query = Type::RPC::Contacts::GetContacts.build(hash: hash)
|
|
17
|
-
@client.rpc.call(query)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def call_sync(hash: 0)
|
|
21
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
22
|
-
|
|
23
|
-
query = Type::RPC::Contacts::GetContacts.build(hash: hash)
|
|
24
|
-
response = @client.rpc.call_sync(query)
|
|
25
|
-
Type::RPC::Contacts::Contacts.parse(response)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/updates/get_difference'
|
|
4
|
-
require_relative '../type/rpc/updates/difference'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class GetUpdatesDifference
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(pts:, date:, qts:, pts_limit: 100, qts_limit: 100, pts_total_limit: nil)
|
|
14
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
15
|
-
raise ArgumentError, 'pts is required' if pts.nil?
|
|
16
|
-
raise ArgumentError, 'date is required' if date.nil?
|
|
17
|
-
raise ArgumentError, 'qts is required' if qts.nil?
|
|
18
|
-
|
|
19
|
-
query = Type::RPC::Updates::GetDifference.build(
|
|
20
|
-
pts: pts,
|
|
21
|
-
pts_limit: pts_limit,
|
|
22
|
-
pts_total_limit: pts_total_limit,
|
|
23
|
-
date: date,
|
|
24
|
-
qts: qts,
|
|
25
|
-
qts_limit: qts_limit
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
@client.rpc.call(query)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def call_sync(pts:, date:, qts:, pts_limit: 100, qts_limit: 100, pts_total_limit: nil)
|
|
32
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
33
|
-
raise ArgumentError, 'pts is required' if pts.nil?
|
|
34
|
-
raise ArgumentError, 'date is required' if date.nil?
|
|
35
|
-
raise ArgumentError, 'qts is required' if qts.nil?
|
|
36
|
-
|
|
37
|
-
query = Type::RPC::Updates::GetDifference.build(
|
|
38
|
-
pts: pts,
|
|
39
|
-
pts_limit: pts_limit,
|
|
40
|
-
pts_total_limit: pts_total_limit,
|
|
41
|
-
date: date,
|
|
42
|
-
qts: qts,
|
|
43
|
-
qts_limit: qts_limit
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
response = @client.rpc.call_sync(query)
|
|
47
|
-
Type::RPC::Updates::Difference.parse(response)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/updates/get_state'
|
|
4
|
-
require_relative '../type/rpc/updates/state'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class GetUpdatesState
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call
|
|
14
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
15
|
-
|
|
16
|
-
query = Type::RPC::Updates::GetState.build
|
|
17
|
-
@client.rpc.call(query)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def call_sync
|
|
21
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
22
|
-
|
|
23
|
-
query = Type::RPC::Updates::GetState.build
|
|
24
|
-
response = @client.rpc.call_sync(query)
|
|
25
|
-
Type::RPC::Updates::State.parse(response)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/users/get_users'
|
|
4
|
-
require_relative '../type/rpc/users/users'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class GetUsers
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call
|
|
14
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
15
|
-
|
|
16
|
-
query = Type::RPC::Users::GetUsers.build
|
|
17
|
-
@client.rpc.call(query)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def call_sync
|
|
21
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
22
|
-
|
|
23
|
-
query = Type::RPC::Users::GetUsers.build
|
|
24
|
-
response = @client.rpc.call_sync(query)
|
|
25
|
-
Type::RPC::Users::Users.parse(response)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
data/lib/mtproto/rpc/ping.rb
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/ping'
|
|
4
|
-
require_relative '../type/rpc/pong'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class Ping
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(ping_id = nil)
|
|
14
|
-
ping_id ||= rand(2**63)
|
|
15
|
-
body = Type::RPC::Ping.build(ping_id)
|
|
16
|
-
|
|
17
|
-
@client.rpc.call(body)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def call_sync(ping_id = nil)
|
|
21
|
-
ping_id ||= rand(2**63)
|
|
22
|
-
body = Type::RPC::Ping.build(ping_id)
|
|
23
|
-
|
|
24
|
-
response_body = @client.rpc.call_sync(body)
|
|
25
|
-
pong = Type::RPC::Pong.parse(response_body)
|
|
26
|
-
|
|
27
|
-
raise PingMismatchError unless pong[:ping_id] == ping_id
|
|
28
|
-
|
|
29
|
-
true
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/auth/send_code'
|
|
4
|
-
require_relative '../type/rpc/auth/sent_code'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class SendCode
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(phone_number, code_settings: {})
|
|
14
|
-
query = build_query(phone_number, code_settings)
|
|
15
|
-
|
|
16
|
-
@client.rpc.call(query)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def call_sync(phone_number, code_settings: {})
|
|
20
|
-
query = build_query(phone_number, code_settings)
|
|
21
|
-
|
|
22
|
-
response = @client.rpc.call_sync(query)
|
|
23
|
-
|
|
24
|
-
Type::RPC::Auth::SentCode.parse(response)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
def build_query(phone_number, code_settings)
|
|
30
|
-
raise ArgumentError, 'phone_number is required' if phone_number.nil? || phone_number.empty?
|
|
31
|
-
|
|
32
|
-
Type::RPC::Auth::SendCode.build(
|
|
33
|
-
phone_number: phone_number,
|
|
34
|
-
api_id: @client.api_id,
|
|
35
|
-
api_hash: @client.api_hash,
|
|
36
|
-
code_settings: code_settings
|
|
37
|
-
)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/messages/send_message'
|
|
4
|
-
require_relative '../type/rpc/messages/updates'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class SendMessage
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(user_id:, access_hash:, message:, random_id: nil)
|
|
14
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
15
|
-
raise ArgumentError, 'user_id is required' if user_id.nil?
|
|
16
|
-
raise ArgumentError, 'access_hash is required' if access_hash.nil?
|
|
17
|
-
raise ArgumentError, 'message is required and cannot be empty' if message.nil? || message.empty?
|
|
18
|
-
|
|
19
|
-
query = Type::RPC::Messages::SendMessage.build(
|
|
20
|
-
user_id: user_id,
|
|
21
|
-
access_hash: access_hash,
|
|
22
|
-
message: message,
|
|
23
|
-
random_id: random_id
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
@client.rpc.call(query)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def call_sync(user_id:, access_hash:, message:, random_id: nil)
|
|
30
|
-
raise 'Auth key not generated' unless @client.auth_key
|
|
31
|
-
raise ArgumentError, 'user_id is required' if user_id.nil?
|
|
32
|
-
raise ArgumentError, 'access_hash is required' if access_hash.nil?
|
|
33
|
-
raise ArgumentError, 'message is required and cannot be empty' if message.nil? || message.empty?
|
|
34
|
-
|
|
35
|
-
query = Type::RPC::Messages::SendMessage.build(
|
|
36
|
-
user_id: user_id,
|
|
37
|
-
access_hash: access_hash,
|
|
38
|
-
message: message,
|
|
39
|
-
random_id: random_id
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
response = @client.rpc.call_sync(query)
|
|
43
|
-
Type::RPC::Messages::Updates.parse(response)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
data/lib/mtproto/rpc/sign_in.rb
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../type/rpc/auth/sign_in'
|
|
4
|
-
require_relative '../type/rpc/auth/authorization'
|
|
5
|
-
|
|
6
|
-
module MTProto
|
|
7
|
-
module RPC
|
|
8
|
-
class SignIn
|
|
9
|
-
def initialize(client)
|
|
10
|
-
@client = client
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(phone_number:, phone_code_hash:, phone_code:)
|
|
14
|
-
query = build_query(phone_number, phone_code_hash, phone_code)
|
|
15
|
-
|
|
16
|
-
@client.rpc.call(query)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def call_sync(phone_number:, phone_code_hash:, phone_code:)
|
|
20
|
-
query = build_query(phone_number, phone_code_hash, phone_code)
|
|
21
|
-
|
|
22
|
-
response = @client.rpc.call_sync(query)
|
|
23
|
-
|
|
24
|
-
result = Type::RPC::Auth::Authorization.parse(response)
|
|
25
|
-
|
|
26
|
-
if result[:authorization] && result[:user_id]
|
|
27
|
-
@client.update_user(user_id: result[:user_id], access_hash: result[:access_hash])
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
result
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def build_query(phone_number, phone_code_hash, phone_code)
|
|
36
|
-
raise ArgumentError, 'phone_number is required' if phone_number.nil? || phone_number.empty?
|
|
37
|
-
raise ArgumentError, 'phone_code_hash is required' if phone_code_hash.nil? || phone_code_hash.empty?
|
|
38
|
-
raise ArgumentError, 'phone_code is required' if phone_code.nil? || phone_code.empty?
|
|
39
|
-
|
|
40
|
-
Type::RPC::Auth::SignIn.build(
|
|
41
|
-
phone_number: phone_number,
|
|
42
|
-
phone_code_hash: phone_code_hash,
|
|
43
|
-
phone_code: phone_code
|
|
44
|
-
)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|