Class: MTProto::Client
- Inherits:
-
Object
- Object
- MTProto::Client
- Extended by:
- DelegateMethods
- Defined in:
- lib/mtproto/client.rb,
lib/mtproto/client/api.rb,
lib/mtproto/client/rpc.rb,
lib/mtproto/client/api/sign_in.rb,
lib/mtproto/client/rpc/response.rb,
lib/mtproto/client/api/get_users.rb,
lib/mtproto/client/api/send_code.rb,
lib/mtproto/client/api/get_dialogs.rb,
lib/mtproto/client/api/get_history.rb,
lib/mtproto/client/api/get_contacts.rb,
lib/mtproto/client/api/send_message.rb,
lib/mtproto/client/api/check_password.rb,
lib/mtproto/client/api/get_updates_state.rb,
lib/mtproto/client/api/export_login_token.rb,
lib/mtproto/client/api/import_login_token.rb,
lib/mtproto/client/api/export_authorization.rb,
lib/mtproto/client/api/import_authorization.rb,
lib/mtproto/client/api/get_channel_difference.rb,
lib/mtproto/client/api/get_updates_difference.rb,
lib/mtproto/client/api/get_bot_callback_answer.rb,
lib/mtproto/client/api/import_bot_authorization.rb
Defined Under Namespace
Constant Summary collapse
- API_LAYER =
227- ACK_INTERVAL =
Keepalive cadence: flush pending acks every ACK_INTERVAL seconds, send a ping every PING_INTERVAL seconds.
5- PING_INTERVAL =
30- RECONNECT_BACKOFF_BASE =
Reconnect backoff: wait RECONNECT_BACKOFF_BASE seconds after the first failed attempt, doubling each retry, capped at RECONNECT_BACKOFF_MAX.
1- RECONNECT_BACKOFF_MAX =
30
Instance Attribute Summary collapse
-
#access_hash ⇒ Object
readonly
Returns the value of attribute access_hash.
-
#api_hash ⇒ Object
Returns the value of attribute api_hash.
-
#api_id ⇒ Object
Returns the value of attribute api_id.
-
#app_version ⇒ Object
Returns the value of attribute app_version.
-
#auth_key ⇒ Object
readonly
Returns the value of attribute auth_key.
-
#connection ⇒ Object
readonly
Returns the value of attribute connection.
-
#dc_number ⇒ Object
readonly
Returns the value of attribute dc_number.
-
#device_model ⇒ Object
Returns the value of attribute device_model.
-
#lang_code ⇒ Object
Returns the value of attribute lang_code.
-
#lang_pack ⇒ Object
Returns the value of attribute lang_pack.
-
#server_key ⇒ Object
readonly
Returns the value of attribute server_key.
-
#server_salt ⇒ Object
readonly
Returns the value of attribute server_salt.
-
#session ⇒ Object
readonly
Returns the value of attribute session.
-
#system_lang_code ⇒ Object
Returns the value of attribute system_lang_code.
-
#system_version ⇒ Object
Returns the value of attribute system_version.
-
#time_offset ⇒ Object
readonly
Returns the value of attribute time_offset.
-
#timeout ⇒ Object
readonly
Returns the value of attribute timeout.
-
#user_id ⇒ Object
readonly
Returns the value of attribute user_id.
Instance Method Summary collapse
- #api ⇒ Object
- #auth_key? ⇒ Boolean
- #disconnect! ⇒ Object
- #exchange_keys! ⇒ Object
- #init_connection! ⇒ Object
-
#initialize(host:, api_id:, api_hash:, port: 443, public_key: nil, dc_number: nil, test_mode: false, timeout: 10) ⇒ Client
constructor
A new instance of Client.
- #load_auth_data(auth_data) ⇒ Object
- #mainloop_running? ⇒ Boolean
- #on_update(&block) ⇒ Object
-
#reinit_connection! ⇒ Object
Force a fresh initConnection on the current connection.
- #rpc ⇒ Object
- #run_mainloop ⇒ Object
- #save_auth_data ⇒ Object
-
#start_receiving! ⇒ Object
Start the receiver task without taking over the current Async reactor.
- #update_server_salt(new_salt) ⇒ Object
- #update_user(user_id:, access_hash: nil) ⇒ Object
Methods included from DelegateMethods
Constructor Details
#initialize(host:, api_id:, api_hash:, port: 443, public_key: nil, dc_number: nil, test_mode: false, timeout: 10) ⇒ Client
Returns a new instance of Client.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/mtproto/client.rb', line 41 def initialize( host:, api_id:, api_hash:, port: 443, public_key: nil, dc_number: nil, test_mode: false, timeout: 10 ) raise ArgumentError, 'host is required' if host.nil? || host.empty? raise ArgumentError, 'dc_number must be positive. Use test_mode: true for test DCs' if dc_number && dc_number < 0 @api_id = api_id @api_hash = api_hash transport = Transport::TCPConnection.new(host, port) @connection = Transport::Connection.new(transport) @public_key = public_key @dc_number = dc_number @test_mode = test_mode @timeout = timeout @server_key = nil @auth_key = nil @server_salt = nil @time_offset = 0 @session = nil @connection_initialized = false @user_id = nil @access_hash = nil @device_model = 'Ruby MTProto' @system_version = RUBY_DESCRIPTION @app_version = '0.1.0' @system_lang_code = 'en' @lang_pack = '' @lang_code = 'en' @receiver_task = nil @keepalive_task = nil @ack_ids = [] @running = false @on_update_callbacks = [] end |
Instance Attribute Details
#access_hash ⇒ Object (readonly)
Returns the value of attribute access_hash.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def access_hash @access_hash end |
#api_hash ⇒ Object
Returns the value of attribute api_hash.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def api_hash @api_hash end |
#api_id ⇒ Object
Returns the value of attribute api_id.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def api_id @api_id end |
#app_version ⇒ Object
Returns the value of attribute app_version.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def app_version @app_version end |
#auth_key ⇒ Object (readonly)
Returns the value of attribute auth_key.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def auth_key @auth_key end |
#connection ⇒ Object (readonly)
Returns the value of attribute connection.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def connection @connection end |
#dc_number ⇒ Object (readonly)
Returns the value of attribute dc_number.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def dc_number @dc_number end |
#device_model ⇒ Object
Returns the value of attribute device_model.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def device_model @device_model end |
#lang_code ⇒ Object
Returns the value of attribute lang_code.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def lang_code @lang_code end |
#lang_pack ⇒ Object
Returns the value of attribute lang_pack.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def lang_pack @lang_pack end |
#server_key ⇒ Object (readonly)
Returns the value of attribute server_key.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def server_key @server_key end |
#server_salt ⇒ Object (readonly)
Returns the value of attribute server_salt.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def server_salt @server_salt end |
#session ⇒ Object (readonly)
Returns the value of attribute session.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def session @session end |
#system_lang_code ⇒ Object
Returns the value of attribute system_lang_code.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def system_lang_code @system_lang_code end |
#system_version ⇒ Object
Returns the value of attribute system_version.
28 29 30 |
# File 'lib/mtproto/client.rb', line 28 def system_version @system_version end |
#time_offset ⇒ Object (readonly)
Returns the value of attribute time_offset.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def time_offset @time_offset end |
#timeout ⇒ Object (readonly)
Returns the value of attribute timeout.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def timeout @timeout end |
#user_id ⇒ Object (readonly)
Returns the value of attribute user_id.
26 27 28 |
# File 'lib/mtproto/client.rb', line 26 def user_id @user_id end |
Instance Method Details
#api ⇒ Object
169 170 171 |
# File 'lib/mtproto/client.rb', line 169 def api @api ||= API.new(self) end |
#auth_key? ⇒ Boolean
33 34 35 |
# File 'lib/mtproto/client.rb', line 33 def auth_key? !@auth_key.nil? end |
#disconnect! ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/mtproto/client.rb', line 132 def disconnect! @running = false @keepalive_task&.stop @keepalive_task = nil @receiver_task&.stop @receiver_task = nil @ack_ids = [] rpc.signal_all_error(Transport::ConnectionError.new('Client shutting down')) @connection.disconnect! if @connection&.connected? end |
#exchange_keys! ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/mtproto/client.rb', line 145 def exchange_keys! raise ArgumentError, 'public_key is required for auth key generation' if @public_key.nil? || @public_key.empty? generator = AuthKeyGenerator.new( @connection, @public_key, @dc_number, test_mode: @test_mode, timeout: @timeout ) result = generator.generate @auth_key = generator.auth_key @server_salt = generator.server_salt @time_offset = generator.time_offset @session = Session.new result end |
#init_connection! ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/mtproto/client.rb', line 173 def init_connection! return if @connection_initialized query = TL::InvokeWithLayer.new( layer: API_LAYER, query: TL::InitConnection.new( api_id: api_id, device_model: device_model, system_version: system_version, app_version: app_version, system_lang_code: system_lang_code, lang_pack: lang_pack, lang_code: lang_code, query: TL::GetConfig.new ) ) response = rpc.call(query, TL::HelpConfig) response.wait!(timeout) @connection_initialized = true response.body end |
#load_auth_data(auth_data) ⇒ Object
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/mtproto/client.rb', line 219 def load_auth_data(auth_data) raise ArgumentError, 'auth_data must be a Hash' unless auth_data.is_a?(Hash) raise ArgumentError, 'auth_key is required' unless auth_data[:auth_key] raise ArgumentError, 'server_salt is required' unless auth_data[:server_salt] @auth_key = Base64.strict_decode64(auth_data[:auth_key]) @server_salt = auth_data[:server_salt] @time_offset = auth_data[:time_offset] || 0 @user_id = auth_data[:user_id] @access_hash = auth_data[:access_hash] @session = Session.new true end |
#mainloop_running? ⇒ Boolean
37 38 39 |
# File 'lib/mtproto/client.rb', line 37 def mainloop_running? @running end |
#on_update(&block) ⇒ Object
97 98 99 |
# File 'lib/mtproto/client.rb', line 97 def on_update(&block) @on_update_callbacks << block end |
#reinit_connection! ⇒ Object
Force a fresh initConnection on the current connection. Used to recover when the server reports CONNECTION_NOT_INITED (it lost our connection state): reset the guard and run init again.
201 202 203 204 |
# File 'lib/mtproto/client.rb', line 201 def reinit_connection! @connection_initialized = false init_connection! end |
#rpc ⇒ Object
165 166 167 |
# File 'lib/mtproto/client.rb', line 165 def rpc @rpc ||= RPC.new(self) end |
#run_mainloop ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/mtproto/client.rb', line 101 def run_mainloop raise 'Auth key not set' unless auth_key? raise 'Mainloop already running' if @running raise ArgumentError, 'Block is required' unless block_given? begin Async do start_receiving! yield self ensure disconnect! end rescue Interrupt # Ctrl+C end end |
#save_auth_data ⇒ Object
206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/mtproto/client.rb', line 206 def save_auth_data raise 'Cannot save auth_data: auth_key not set' unless @auth_key { auth_key: Base64.strict_encode64(@auth_key), server_salt: @server_salt, user_id: @user_id, access_hash: @access_hash, dc_number: @dc_number, time_offset: @time_offset } end |
#start_receiving! ⇒ Object
Start the receiver task without taking over the current Async reactor. Use when orchestrating multiple clients in a shared Async block — call from inside an Async do ... end. The caller is responsible for disconnect! at the end.
122 123 124 125 126 127 128 129 130 |
# File 'lib/mtproto/client.rb', line 122 def start_receiving! raise 'Auth key not set' unless auth_key? raise 'Mainloop already running' if @running @running = true @ack_ids = [] @receiver_task = Async { receiver_loop } @keepalive_task = Async { keepalive_loop } end |
#update_server_salt(new_salt) ⇒ Object
240 241 242 |
# File 'lib/mtproto/client.rb', line 240 def update_server_salt(new_salt) @server_salt = new_salt end |
#update_user(user_id:, access_hash: nil) ⇒ Object
235 236 237 238 |
# File 'lib/mtproto/client.rb', line 235 def update_user(user_id:, access_hash: nil) @user_id = user_id @access_hash = access_hash end |