diff --git a/secret_bot.php b/secret_bot.php index d42a85f9..bfdd720d 100755 --- a/secret_bot.php +++ b/secret_bot.php @@ -82,17 +82,27 @@ while (true) { foreach ($updates as $update) { $offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id switch ($update['update']['_']) { + /*case 'updateNewChannelMessage': + if ($update['update']['message']['out'] || $update['update']['message']['message'] === '') continue; + $MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['to_id'], 'message' => $update['update']['message']['message']]); + break;*/ + case 'updateNewMessage': + if ($update['update']['message']['out'] || $update['update']['message']['message'] === '') continue; +var_dump($update); + break; case 'updateNewEncryptedMessage': if (isset($sent[$update['update']['message']['chat_id']])) continue; $i = 0; while ($i < $argv[1]) { echo "SENDING MESSAGE $i TO ".$update['update']['message']['chat_id'].PHP_EOL; $MadelineProto->messages->sendEncrypted(['peer' => $update['update']['message']['chat_id'], 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => $i++]]); + \danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto); } $sent[$update['update']['message']['chat_id']] = true; } } -// } catch (\danog\MadelineProto\SecurityException $e) { + } catch (\danog\MadelineProto\RPCErrorException $e) { + var_dump($e); } catch (\danog\MadelineProto\Exception $e) { var_dump($e->getMessage()); } - echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('bot.madeline', $MadelineProto).' bytes'.PHP_EOL; + echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL; } diff --git a/src/danog/MadelineProto/Connection.php b/src/danog/MadelineProto/Connection.php index db42bed5..d5015c61 100644 --- a/src/danog/MadelineProto/Connection.php +++ b/src/danog/MadelineProto/Connection.php @@ -40,6 +40,8 @@ class Connection extends \Volatile public $max_incoming_id; public $max_outgoing_id; + public $call_queue = []; + public $i = []; /* public function __get($name) { echo "GETTING $name\n"; diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index dacdbb0c..f8194b7a 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -163,13 +163,7 @@ class MTProto extends \Volatile public $chats = []; public $last_stored = 0; public $qres = []; - private $pending_updates = []; - private $updates_state = ['_' => 'MadelineProto.Updates_state', 'pending_seq_updates' => [], 'pending_pts_updates' => [], 'sync_loading' => true, 'seq' => 0, 'pts' => 0, 'date' => 0, 'qts' => 0]; - private $got_state = false; - private $channels_state = []; - public $updates = []; - public $updates_key = 0; - private $getting_state = false; + public $full_chats = []; private $msg_ids = []; private $v = 0; @@ -291,13 +285,17 @@ class MTProto extends \Volatile } unset($this->data); } + $this->secret_chats = []; if ($this->authorized === true) { $this->authorized = self::LOGGED_IN; } - $this->getting_state = false; + $this->updates_state["sync_loading"] = false; + foreach ($this->channels_state as &$state) { + $state['sync_loading'] = false; + } foreach (debug_backtrace(0) as $trace) { if (isset($trace['function']) && isset($trace['class']) && $trace['function'] === 'deserialize' && $trace['class'] === 'danog\MadelineProto\Serialization') { - $this->getting_state = isset($trace['args'][1]) && $trace['args'][1]; + $this->updates_state["sync_loading"] = isset($trace['args'][1]) && $trace['args'][1]; } } @@ -323,7 +321,7 @@ class MTProto extends \Volatile if ($this->authorized === self::LOGGED_IN && !$this->authorization['user']['bot']) { $this->get_dialogs(); } - if ($this->authorized === self::LOGGED_IN && $this->settings['updates']['handle_updates'] && !$this->getting_state) { + if ($this->authorized === self::LOGGED_IN && $this->settings['updates']['handle_updates'] && !$this->updates_state["sync_loading"]) { \danog\MadelineProto\Logger::log(['Getting updates after deserialization...'], Logger::NOTICE); $this->get_updates_difference(); } @@ -510,7 +508,9 @@ class MTProto extends \Volatile 'outgoing' => 200, 'call_queue' => 200 ], - 'peer' => ['full_info_cache_time' => 60], + 'peer' => [ + 'full_info_cache_time' => 60 + ], 'updates' => [ 'handle_updates' => true, // Should I handle updates? 'callback' => 'get_updates_update_handler', // A callable function that will be called every time an update is received, must accept an array (for the update) as the only parameter @@ -597,7 +597,7 @@ class MTProto extends \Volatile public function init_authorization() { $this->initing_authorization = true; - $this->getting_state = true; + $this->updates_state["sync_loading"] = true; foreach ($this->datacenter->sockets as $id => $socket) { if (strpos($id, 'media')) { continue; @@ -622,12 +622,12 @@ class MTProto extends \Volatile } } $this->initing_authorization = false; - $this->getting_state = false; + $this->updates_state["sync_loading"] = false; } public function sync_authorization($authorized_dc) { - $this->getting_state = true; + $this->updates_state["sync_loading"] = true; foreach ($this->datacenter->sockets as $new_dc => $socket) { if (($int_dc = preg_replace('|/D+|', '', $new_dc)) == $authorized_dc) { continue; @@ -644,7 +644,7 @@ class MTProto extends \Volatile $this->method_call('auth.logOut', [], ['datacenter' => $new_dc]); $this->method_call('auth.importAuthorization', $exported_authorization, ['datacenter' => $new_dc]); } - $this->getting_state = false; + $this->updates_state["sync_loading"] = false; } public function write_client_info($method, $arguments = [], $options = []) @@ -708,7 +708,7 @@ class MTProto extends \Volatile public function getV() { - return 39; + return 40; } public function get_self() diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index d5a8e314..215f0459 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -509,9 +509,9 @@ trait AuthKeyHandler public function get_dh_config() { - $this->getting_state = true; + $this->updates_state["sync_loading"] = true; $dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0], ['datacenter' => $this->datacenter->curdc]); - $this->getting_state = false; + $this->updates_state["sync_loading"] = false; if ($dh_config['_'] === 'messages.dhConfigNotModified') { \danog\MadelineProto\Logger::log(\danog\MadelineProto\Logger::VERBOSE, ['DH configuration not modified']); diff --git a/src/danog/MadelineProto/MTProtoTools/CallHandler.php b/src/danog/MadelineProto/MTProtoTools/CallHandler.php index 14ac2c07..694d2dff 100644 --- a/src/danog/MadelineProto/MTProtoTools/CallHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/CallHandler.php @@ -17,7 +17,6 @@ namespace danog\MadelineProto\MTProtoTools; */ trait CallHandler { - public $call_queue = []; public function method_call($method, $args = [], $aargs = ['message_id' => null, 'heavy' => false]) { if (!$this->is_array($args)) { @@ -51,33 +50,38 @@ trait CallHandler } $args['chat_id'] = $res['chat_id']; } - $queue = (isset($aargs['queue']) && $aargs['queue']) || in_array($method, ['messages.setEncryptedTyping', 'messages.readEncryptedHistory', 'messages.sendEncrypted', 'messages.sendEncryptedFile', 'messages.sendEncryptedService', 'messages.receivedQueue']); + if (in_array($method, ['messages.setEncryptedTyping', 'messages.readEncryptedHistory', 'messages.sendEncrypted', 'messages.sendEncryptedFile', 'messages.sendEncryptedService', 'messages.receivedQueue'])) $aargs['queue'] = 'secret'; + if (isset($aargs['queue'])) { + $queue = $aargs['queue']; + if (!isset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue])) $this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue] = []; + unset($aargs['queue']); + } $serialized = $this->serialize_method($method, $args); $content_related = $this->content_related($method); $type = $this->methods->find_by_method($method)['type']; - if ($queue) { - $serialized = $this->serialize_method('invokeAfterMsgs', ['msg_ids' => $this->call_queue, 'query' => $serialized]); + if (isset($queue)) { + $serialized = $this->serialize_method('invokeAfterMsgs', ['msg_ids' => $this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue], 'query' => $serialized]); } $last_recv = $this->last_recv; - if ($canunset = !$this->getting_state && !$this->threads && !$this->run_workers) { - $this->getting_state = true; + if ($canunset = !$this->updates_state["sync_loading"] && !$this->threads && !$this->run_workers) { + $this->updates_state["sync_loading"] = true; } for ($count = 1; $count <= $this->settings['max_tries']['query']; $count++) { try { \danog\MadelineProto\Logger::log(['Calling method (try number '.$count.' for '.$method.')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); $message_id = $this->send_message($serialized, $content_related, $aargs); - if ($queue) { - $this->call_queue[] = $message_id; - if (count($this->call_queue) > $this->settings['msg_array_limit']['call_queue']) { - reset($this->call_queue); - $key = key($this->call_queue); + if (isset($queue)) { + $this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue][] = $message_id; + if (count($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue]) > $this->settings['msg_array_limit']['call_queue']) { + reset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue]); + $key = key($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue]); if ($key[0] === "\0") { $key = 'a'.$key; } - unset($this->call_queue[$key]); + unset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue][$key]); } } if ($method === 'http_wait' || (isset($aargs['noResponse']) && $aargs['noResponse'])) { @@ -146,7 +150,7 @@ trait CallHandler } if ($canunset) { - $this->getting_state = false; + $this->updates_state["sync_loading"] = false; $this->handle_pending_updates(); } if ($server_answer === null) { @@ -216,7 +220,7 @@ trait CallHandler unset($this->datacenter->sockets[$aargs['datacenter']]->new_outgoing[$message_id]); } if ($canunset) { - $this->getting_state = false; + $this->updates_state["sync_loading"] = false; $this->handle_pending_updates(); } } @@ -259,7 +263,7 @@ trait CallHandler } for ($count = 1; $count <= $this->settings['max_tries']['query']; $count++) { try { - \danog\MadelineProto\Logger::log([$object === 'msgs_ack' ? 'ack '.$args['msg_ids'][0] : 'Sending object (try number '.$count.' for '.$object.')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); + if ($object !== 'msgs_ack') \danog\MadelineProto\Logger::log(['Sending object (try number '.$count.' for '.$object.')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); $message_id = $this->send_message($this->serialize_object(['type' => $object], $args), $this->content_related($object), $aargs); if ($object !== 'msgs_ack') { $this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['content'] = ['method' => $object, 'args' => $args]; diff --git a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php index 87fb0052..3afaa288 100644 --- a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php @@ -26,6 +26,9 @@ trait PeerHandler switch ($user['_']) { case 'user': if (!isset($this->chats[$user['id']]) || $this->chats[$user['id']] !== $user) { + foreach (str_split(pack('q', $user['access_hash'])) as $char) { + var_dump(ord($char)); + } $this->chats[$user['id']] = $user; try { $this->get_pwr_chat($user['id'], false, true); @@ -72,14 +75,14 @@ trait PeerHandler $bot_api_id = $this->to_supergroup($chat['id']); if (!isset($this->chats[$bot_api_id]) || $this->chats[$bot_api_id] !== $chat) { $this->chats[$bot_api_id] = $chat; - if (!isset($this->full_chats[$bot_api_id]) || $this->full_chats[$bot_api_id]['full']['participants_count'] !== $this->get_full_info($bot_api_id)['full']['participants_count']) { - try { + try { + if (!isset($this->full_chats[$bot_api_id]) || $this->full_chats[$bot_api_id]['full']['participants_count'] !== $this->get_full_info($bot_api_id)['full']['participants_count']) { $this->get_pwr_chat($this->to_supergroup($chat['id']), true, true); - } catch (\danog\MadelineProto\Exception $e) { - \danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::WARNING); - } catch (\danog\MadelineProto\RPCErrorException $e) { - \danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::WARNING); } + } catch (\danog\MadelineProto\Exception $e) { + \danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::WARNING); + } catch (\danog\MadelineProto\RPCErrorException $e) { + \danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::WARNING); } } break; diff --git a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php index c407721d..b20fad29 100644 --- a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php @@ -126,7 +126,7 @@ trait ResponseHandler unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]); $this->ack_incoming_message_id($current_msg_id, $datacenter); // Acknowledge that I received the server's response if ($this->authorized === self::LOGGED_IN && !$this->initing_authorization && $this->datacenter->sockets[$this->datacenter->curdc]->temp_auth_key !== null) { - $this->force_get_updates_difference(); + $this->get_updates_difference(); } $unset = true; break; @@ -351,6 +351,7 @@ trait ResponseHandler public function handle_pending_updates() { + if ($this->updates_state["sync_loading"]) return false; if (count($this->pending_updates)) { \danog\MadelineProto\Logger::log(['Parsing pending updates...'], \danog\MadelineProto\Logger::VERBOSE); foreach ($this->pending_updates as $key => $updates) { @@ -364,13 +365,14 @@ trait ResponseHandler { if (!$this->settings['updates']['handle_updates']) { return; - } - if ($this->getting_state) { + }/* + if ($this->updates_state["sync_loading"]) { \danog\MadelineProto\Logger::log(['Getting state, handle later'], \danog\MadelineProto\Logger::VERBOSE); + var_dump($updates); $this->pending_updates[] = $updates; return false; - } + }*/ \danog\MadelineProto\Logger::log(['Parsing updates received via the socket...'], \danog\MadelineProto\Logger::VERBOSE); $opts = []; foreach (['date', 'seq', 'seq_start'] as $key) { @@ -416,7 +418,7 @@ trait ResponseHandler //$this->set_update_state(['date' => $updates['date']]); break; case 'updatesTooLong': - $this->force_get_updates_difference(); + $this->get_updates_difference(); break; default: throw new \danog\MadelineProto\ResponseException('Unrecognized update received: '.var_export($updates, true)); diff --git a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php index 142b9b8e..3e53d5c0 100644 --- a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php @@ -17,8 +17,17 @@ namespace danog\MadelineProto\MTProtoTools; */ trait UpdateHandler { + private $pending_updates = []; + private $updates_state = ['_' => 'MadelineProto.Updates_state', 'seq' => 0, 'pts' => 0, 'date' => 0, 'qts' => 0]; + private $got_state = false; + private $channels_state = []; + public $updates = []; + public $updates_key = 0; + private $getting_state = false; + public function pwr_update_handler($update) { + /* if (isset($update['message']['to_id'])) { try { $full_chat = $this->get_pwr_chat($update['message']['to_id']); @@ -37,6 +46,7 @@ trait UpdateHandler \danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::WARNING); } } + */ if (isset($this->settings['pwr']['update_handler'])) { in_array($this->settings['pwr']['update_handler'], [['danog\MadelineProto\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['pwr']['update_handler']($update); } @@ -57,7 +67,7 @@ trait UpdateHandler return; } $time = microtime(true); - $this->force_get_updates_difference(); + $this->get_updates_difference(); $default_params = ['offset' => 0, 'limit' => null, 'timeout' => 0]; foreach ($default_params as $key => $default) { if (!isset($params[$key])) { @@ -89,10 +99,10 @@ trait UpdateHandler return $updates; } - public function &get_channel_state($channel, $pts = 0) + public function &load_channel_state($channel, $pts = 0) { if (!isset($this->channels_state[$channel])) { - $this->channels_state[$channel] = ['pts' => $pts, 'pending_pts_updates' => [], 'sync_loading' => false]; + $this->channels_state[$channel] = ['pts' => $pts, 'sync_loading' => false]; } return $this->channels_state[$channel]; @@ -101,10 +111,11 @@ trait UpdateHandler public function set_channel_state($channel, $data) { if (isset($data['pts']) && $data['pts'] !== 0) { - $this->get_channel_state($channel)['pts'] = $data['pts']; + $this->load_channel_state($channel)['pts'] = $data['pts']; } } - + + /* public function get_msg_id($peer) { $id = $this->get_info($peer)['bot_api_id']; @@ -117,16 +128,17 @@ trait UpdateHandler $id = $this->get_info($peer)['bot_api_id']; $this->msg_ids[$id] = $msg_id; } - + */ public function get_channel_difference($channel) { if (!$this->settings['updates']['handle_updates']) { return; } - if (!$this->get_channel_state($channel)['sync_loading']) { - $this->get_channel_state($channel)['sync_loading'] = true; - $this->get_channel_state($channel)['pending_pts_updates'] = []; + if ($this->load_channel_state($channel)['sync_loading']) { + \danog\MadelineProto\Logger::log(['Not fetching '.$channel.' difference, I am already fetching it']); + return; } + $this->load_channel_state($channel)['sync_loading'] = true; try { $input = $this->get_info('channel#'.$channel); if (!isset($input['InputChannel'])) { @@ -134,33 +146,36 @@ trait UpdateHandler } $input = $input['InputChannel']; } catch (\danog\MadelineProto\Exception $e) { + $this->load_channel_state($channel)['sync_loading'] = false; return false; } catch (\danog\MadelineProto\RPCErrorException $e) { + $this->load_channel_state($channel)['sync_loading'] = false; return false; } + \danog\MadelineProto\Logger::log(['Fetching '.$channel.' difference...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); + try { - $difference = $this->method_call('updates.getChannelDifference', ['channel' => $input, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $this->get_channel_state($channel)['pts'], 'limit' => 30], ['datacenter' => $this->datacenter->curdc]); + $difference = $this->method_call('updates.getChannelDifference', ['channel' => $input, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $this->load_channel_state($channel)['pts'], 'limit' => 30], ['datacenter' => $this->datacenter->curdc]); } catch (\danog\MadelineProto\RPCErrorException $e) { + $this->load_channel_state($channel)['sync_loading'] = false; if ($e->getMessage() === "You haven't joined this channel/supergroup") { return false; } - if ($e->rpc === 'PERSISTENT_TIMESTAMP_INVALID') { - return false; - } throw $e; } - $this->get_channel_state($channel)['sync_loading'] = false; + unset($input); switch ($difference['_']) { case 'updates.channelDifferenceEmpty': + $this->load_channel_state($channel)['sync_loading'] = false; $this->set_channel_state($channel, $difference); break; case 'updates.channelDifference': $this->set_channel_state($channel, $difference); $this->handle_update_messages($difference['new_messages'], $channel); $this->handle_multiple_update($difference['other_updates'], [], $channel); + $this->load_channel_state($channel)['sync_loading'] = false; if (!$difference['final']) { unset($difference); - unset($input); $this->get_channel_difference($channel); } break; @@ -169,7 +184,7 @@ trait UpdateHandler $this->set_channel_state($channel, $difference); $this->handle_update_messages($difference['messages'], $channel); unset($difference); - unset($input); + $this->load_channel_state($channel)['sync_loading'] = false; $this->get_channel_difference($channel); break; default: @@ -181,20 +196,20 @@ trait UpdateHandler public function set_update_state($data) { if (isset($data['pts']) && $data['pts'] !== 0) { - $this->get_update_state()['pts'] = $data['pts']; + $this->load_update_state()['pts'] = $data['pts']; } if (isset($data['qts']) && $data['qts'] !== 0) { - $this->get_update_state()['qts'] = $data['qts']; + $this->load_update_state()['qts'] = $data['qts']; } if (isset($data['seq']) && $data['seq'] !== 0) { - $this->get_update_state()['seq'] = $data['seq']; + $this->load_update_state()['seq'] = $data['seq']; } - if (isset($data['date']) && $data['date'] > $this->get_update_state()['date']) { - $this->get_update_state()['date'] = $data['date']; + if (isset($data['date']) && $data['date'] > $this->load_update_state()['date']) { + $this->load_update_state()['date'] = $data['date']; } } - public function &get_update_state() + public function &load_update_state() { if (!isset($this->updates_state['qts'])) { $this->updates_state['qts'] = 0; @@ -206,66 +221,63 @@ trait UpdateHandler return $this->updates_state; } - public function force_get_updates_difference() - { - if (!$this->get_update_state()['sync_loading']) { - $this->get_updates_difference(); - } - } - public function get_updates_difference() { if (!$this->settings['updates']['handle_updates']) { return; } - if (!$this->get_update_state()['sync_loading']) { - $this->get_update_state()['sync_loading'] = true; - $this->get_update_state()['pending_pts_updates'] = []; - $this->get_update_state()['pending_seq_updates'] = []; + if ($this->updates_state["sync_loading"]) { + \danog\MadelineProto\Logger::log(['Not fetching normal difference, I am already fetching it']); + return false; } + $this->updates_state["sync_loading"] = true; + + \danog\MadelineProto\Logger::log(['Fetching normal difference...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); + while (!isset($difference)) { try { - $difference = $this->method_call('updates.getDifference', ['pts' => $this->get_update_state()['pts'], 'date' => $this->get_update_state()['date'], 'qts' => $this->get_update_state()['qts']], ['datacenter' => $this->datacenter->curdc]); + $difference = $this->method_call('updates.getDifference', ['pts' => $this->load_update_state()['pts'], 'date' => $this->load_update_state()['date'], 'qts' => $this->load_update_state()['qts']], ['datacenter' => $this->datacenter->curdc]); } catch (\danog\MadelineProto\PTSException $e) { + $this->updates_state["sync_loading"] = false; $this->got_state = false; } } - \danog\MadelineProto\Logger::log(['Got '.$difference['_']], \danog\MadelineProto\Logger::ULTRA_VERBOSE); - $this->get_update_state()['sync_loading'] = false; + \danog\MadelineProto\Logger::log(['Got '.$difference['_']], \danog\MadelineProto\Logger::ULTRA_VERBOSE); switch ($difference['_']) { case 'updates.differenceEmpty': $this->set_update_state($difference); break; case 'updates.difference': - $this->set_update_state($difference['state']); - //var_dump($difference['new_encrypted_messages']); foreach ($difference['new_encrypted_messages'] as $encrypted) { $this->handle_encrypted_update(['_' => 'updateNewEncryptedMessage', 'message' => $encrypted], true); } $this->handle_multiple_update($difference['other_updates']); $this->handle_update_messages($difference['new_messages']); + $this->set_update_state($difference['state']); + break; case 'updates.differenceSlice': - $this->set_update_state($difference['intermediate_state']); $this->handle_multiple_update($difference['other_updates']); $this->handle_update_messages($difference['new_messages']); + $this->set_update_state($difference['intermediate_state']); unset($difference); + $this->updates_state["sync_loading"] = false; $this->get_updates_difference(); break; default: throw new \danog\MadelineProto\Exception('Unrecognized update difference received: '.var_export($difference, true)); break; } + $this->updates_state["sync_loading"] = false; } public function get_updates_state() { - $this->updates_state['sync_loading'] = false; - $this->getting_state = true; + $last = $this->updates_state['sync_loading']; + $this->updates_state['sync_loading'] = true; $this->set_update_state($this->method_call('updates.getState', [], ['datacenter' => $this->datacenter->curdc])); - $this->getting_state = false; - $this->handle_pending_updates(); + $this->updates_state['sync_loading'] = $last; } public function handle_update($update, $options = []) @@ -300,15 +312,16 @@ trait UpdateHandler break; } if ($channel_id === false) { - $cur_state = &$this->get_update_state(); + $cur_state = &$this->load_update_state(); } else { - $cur_state = &$this->get_channel_state($channel_id, (isset($update['pts']) ? $update['pts'] : 0) - (isset($update['pts_count']) ? $update['pts_count'] : 0)); + $cur_state = &$this->load_channel_state($channel_id, (isset($update['pts']) ? $update['pts'] : 0) - (isset($update['pts_count']) ? $update['pts_count'] : 0)); } + /* if ($cur_state['sync_loading'] && $this->in_array($update['_'], ['updateNewMessage', 'updateEditMessage', 'updateNewChannelMessage', 'updateEditChannelMessage'])) { \danog\MadelineProto\Logger::log(['Sync loading, not handling update'], \danog\MadelineProto\Logger::NOTICE); return false; - } + }*/ switch ($update['_']) { case 'updateChannelTooLong': @@ -330,35 +343,30 @@ trait UpdateHandler if ($channel_id !== false && $this->peer_isset($this->to_supergroup($channel_id))) { $this->get_channel_difference($channel_id); } else { - $this->force_get_updates_difference(); + $this->get_updates_difference(); } return false; } break; default: - if ($channel_id !== false && !$this->peer_isset('channel#'.$channel_id)) { + if ($channel_id !== false && !$this->peer_isset($this->to_supergroup($channel_id))) { \danog\MadelineProto\Logger::log(['Skipping update, I do not have the channel id '.$channel_id], \danog\MadelineProto\Logger::ERROR); return false; } break; } - $pop_pts = false; - $pop_seq = false; if (isset($update['pts'])) { - $new_pts = $cur_state['pts'] + (isset($update['pts_count']) ? $update['pts_count'] : 0); - if ($update['pts'] < $new_pts) { - \danog\MadelineProto\Logger::log(['Duplicate update. current pts: '.$cur_state['pts'].' + pts count: '.(isset($update['pts_count']) ? $update['pts_count'] : 0).' = new pts: '.$new_pts.'. update pts: '.$update['pts'].' < new pts '.$new_pts.', channel id: '.$channel_id], \danog\MadelineProto\Logger::ERROR); + $computed_pts = $cur_state['pts'] + (isset($update['pts_count']) ? $update['pts_count'] : 0); + if ($update['pts'] < $computed_pts) { + \danog\MadelineProto\Logger::log(['Duplicate update. current pts: '.$cur_state['pts'].' + pts count: '.(isset($update['pts_count']) ? $update['pts_count'] : 0).' = new pts: '.$computed_pts.'. update pts: '.$update['pts'].' < new pts '.$computed_pts.', channel id: '.$channel_id], \danog\MadelineProto\Logger::ERROR); return false; } - if ($update['pts'] > $new_pts) { - \danog\MadelineProto\Logger::log(['Pts hole. current pts: '.$cur_state['pts'].', pts count: '.(isset($update['pts_count']) ? $update['pts_count'] : 0).', new pts: '.$new_pts.' < update pts: '.$update['pts'].', channel id: '.$channel_id], \danog\MadelineProto\Logger::ERROR); - - $cur_state['pending_pts_updates'][] = $update; - + if ($update['pts'] > $computed_pts) { + \danog\MadelineProto\Logger::log(['Pts hole. current pts: '.$cur_state['pts'].', pts count: '.(isset($update['pts_count']) ? $update['pts_count'] : 0).', new pts: '.$computed_pts.' < update pts: '.$update['pts'].', channel id: '.$channel_id], \danog\MadelineProto\Logger::ERROR); if ($channel_id !== false && $this->peer_isset($this->to_supergroup($channel_id))) { $this->get_channel_difference($channel_id); } else { @@ -368,101 +376,33 @@ trait UpdateHandler return false; } if ($update['pts'] > $cur_state['pts']) { - \danog\MadelineProto\Logger::log(['Applying pts. current pts: '.$cur_state['pts'].' + pts count: '.(isset($update['pts_count']) ? $update['pts_count'] : 0).' = new pts: '.$new_pts.', channel id: '.$channel_id], \danog\MadelineProto\Logger::VERBOSE); + \danog\MadelineProto\Logger::log(['Applying pts. current pts: '.$cur_state['pts'].' + pts count: '.(isset($update['pts_count']) ? $update['pts_count'] : 0).' = new pts: '.$computed_pts.', channel id: '.$channel_id], \danog\MadelineProto\Logger::VERBOSE); $cur_state['pts'] = $update['pts']; - $pop_pts = true; } - if ($channel_id !== false && isset($options['date']) && $this->get_update_state()['date'] < $options['date']) { - $this->get_update_state()['date'] = $options['date']; + if ($channel_id === false && isset($options['date']) && $cur_state['date'] < $options['date']) { + $cur_state['date'] = $options['date']; } - } elseif ($channel_id === false && isset($options['seq']) && $options['seq'] > 0) { + } + if ($channel_id === false && isset($options['seq']) || isset($options['seq_start'])) { $seq = $options['seq']; $seq_start = isset($options['seq_start']) ? $options['seq_start'] : $options['seq']; if ($seq_start != $cur_state['seq'] + 1 && $seq_start > $cur_state['seq']) { \danog\MadelineProto\Logger::log(['Seq hole. seq_start: '.$seq_start.' != cur seq: '.$cur_state['seq'].' + 1'], \danog\MadelineProto\Logger::ERROR); - - if (!isset($cur_state['pending_seq_updates'][$seq_start])) { - $cur_state['pending_seq_updates'][$seq_start] = ['seq' => $seq, 'date' => $options['date'], 'updates' => []]; - } - $cur_state['pending_seq_updates'][$seq_start]['updates'][] = $update; $this->get_updates_difference(); - return false; } - if ($cur_state['seq'] != $seq) { + if ($cur_state['seq'] !== $seq) { $cur_state['seq'] = $seq; if (isset($options['date']) && $cur_state['date'] < $options['date']) { $cur_state['date'] = $options['date']; } - $pop_seq = true; } } $this->save_update($update); - if ($pop_pts) { - $this->pop_pending_pts_update($channel_id); - } elseif ($pop_seq) { - $this->pop_pending_seq_update(); - } } - public function pop_pending_seq_update() - { - if (!$this->settings['updates']['handle_updates']) { - return; - } - $next_seq = $this->get_update_state()['seq'] + 1; - if (empty($this->get_update_state()['pending_seq_updates'][$next_seq]['updates'])) { - return false; - } - foreach ($this->get_update_state()['pending_seq_updates'][$next_seq]['updates'] as $update) { - $this->save_update($update); - } - $this->get_update_state()['seq'] = $this->get_update_state()['pending_seq_updates'][$next_seq]['seq']; - if (isset($this->get_update_state()['pending_seq_updates'][$next_seq]['date']) && $this->get_update_state()['date'] < $this->get_update_state()['pending_seq_updates'][$next_seq]['date']) { - $this->get_update_state()['date'] = $this->get_update_state()['pending_seq_updates'][$next_seq]['date']; - } - unset($this->get_update_state()['pending_seq_updates'][$next_seq]); - $this->pop_pending_seq_update(); - - return true; - } - - public function pop_pending_pts_update($channel_id) - { - if (!$this->settings['updates']['handle_updates']) { - return; - } - if ($channel_id === false) { - $cur_state = &$this->get_update_state(); - } else { - $cur_state = &$this->get_channel_state($channel_id); - } - if (empty($cur_state['pending_pts_updates'])) { - return false; - } - $pending_updates = (array) $cur_state['pending_pts_updates']; - sort($pending_updates); - $cur_pts = $cur_state['pts']; - $good_pts = false; - $good_index = false; - foreach ($pending_updates as $i => $update) { - $cur_pts += $update['pts_count']; - if ($cur_pts >= $update['pts']) { - $good_pts = $update['pts']; - $good_index = $i; - } - } - if (!$good_pts) { - return false; - } - $cur_state['pts'] = $good_pts; - for ($i = 0; $i <= $good_index; $i++) { - $this->save_update($pending_updates[$i]); - } - array_splice($cur_state['pending_pts_updates'], 0, $good_index + 1); - } public function handle_multiple_update($updates, $options = [], $channel = false) { @@ -486,7 +426,7 @@ trait UpdateHandler return; } foreach ($messages as $message) { - $this->handle_update(['_' => $channel === false ? 'updateNewMessage' : 'updateNewChannelMessage', 'message' => $message, 'pts' => $channel === false ? $this->get_update_state()['pts'] : $this->get_channel_state($channel)['pts'], 'pts_count' => 0]); + $this->handle_update(['_' => $channel === false ? 'updateNewMessage' : 'updateNewChannelMessage', 'message' => $message, 'pts' => $channel === false ? $this->load_update_state()['pts'] : $this->load_channel_state($channel)['pts'], 'pts_count' => 0]); } } @@ -518,7 +458,7 @@ trait UpdateHandler } } if ($update['_'] === 'updateNewEncryptedMessage' && !isset($update['message']['decrypted_message'])) { - $cur_state = $this->get_update_state(); + $cur_state = $this->load_update_state(); if ($cur_state['qts'] === -1) { $cur_state['qts'] = $update['qts']; } @@ -528,7 +468,7 @@ trait UpdateHandler return false; } if ($update['qts'] > $cur_state['qts'] + 1) { - \danog\MadelineProto\Logger::log(['Qts hole. update qts: '.$update['qts'].' > current qts '.$cur_state['qts'].'+1, chat id: '.$update['message']['chat_id']], \danog\MadelineProto\Logger::ERROR); + \danog\MadelineProto\Logger::log(['Qts hole. Fetching updates manually: update qts: '.$update['qts'].' > current qts '.$cur_state['qts'].'+1, chat id: '.$update['message']['chat_id']], \danog\MadelineProto\Logger::ERROR); $this->get_updates_difference(); return false; @@ -554,7 +494,7 @@ trait UpdateHandler return $this->accept_secret_chat($update['chat']); case 'encryptedChatDiscarded': - \danog\MadelineProto\Logger::log(['Revoking secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE); + \danog\MadelineProto\Logger::log(['Deleting secret chat '.$update['chat']['id'].' because it was revoked by the other user'], \danog\MadelineProto\Logger::NOTICE); if (isset($this->secret_chats[$update['chat']['id']])) { unset($this->secret_chats[$update['chat']['id']]); } @@ -628,4 +568,5 @@ trait UpdateHandler } } } + } diff --git a/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php b/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php index 45c71775..b637d0ee 100644 --- a/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php +++ b/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php @@ -24,6 +24,7 @@ trait AuthKeyHandler public function accept_secret_chat($params) { + //var_dump($params['id'],$this->secret_chat_status($params['id'])); if ($this->secret_chat_status($params['id']) !== 0) { //var_dump($this->secret_chat_status($params['id'])); \danog\MadelineProto\Logger::log(["I've already accepted secret chat ".$params['id']]); @@ -233,7 +234,7 @@ trait AuthKeyHandler public function discard_secret_chat($chat) { \danog\MadelineProto\Logger::log(['Discarding secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE); - + //var_dump(debug_backtrace(0)[0]); if (isset($this->secret_chats[$chat])) { unset($this->secret_chats[$chat]); } diff --git a/src/danog/MadelineProto/SecretChats/MessageHandler.php b/src/danog/MadelineProto/SecretChats/MessageHandler.php index f3c7b708..f882dd0a 100644 --- a/src/danog/MadelineProto/SecretChats/MessageHandler.php +++ b/src/danog/MadelineProto/SecretChats/MessageHandler.php @@ -96,8 +96,8 @@ trait MessageHandler } unset($message['message']['bytes']); $message['message']['decrypted_message'] = $deserialized; - if ($test) { - var_dump($message); + if ($test = true) { + //var_dump($message); } $this->secret_chats[$message['message']['chat_id']]['incoming'][$this->secret_chats[$message['message']['chat_id']]['in_seq_no']] = $message['message']; diff --git a/src/danog/MadelineProto/SecretChats/ResponseHandler.php b/src/danog/MadelineProto/SecretChats/ResponseHandler.php index 1ec54988..8ab1faa3 100644 --- a/src/danog/MadelineProto/SecretChats/ResponseHandler.php +++ b/src/danog/MadelineProto/SecretChats/ResponseHandler.php @@ -54,7 +54,8 @@ trait ResponseHandler return; case 'decryptedMessageActionResend': - foreach ($this->secret_chats[$update['message']['chat_id']]['outgoing'] as $seq => $update['message']['decrypted_message']) { + foreach ($this->secret_chats[$update['message']['chat_id']]['outgoing'] as $seq => $message) { + $seq--; if ($seq >= $update['message']['decrypted_message']['action']['start_seq_no'] && $seq <= $update['message']['decrypted_message']['action']['end_seq_no']) { throw new \danog\MadelineProto\ResponseException('Resending of messages is not yet supported'); // $this->send_encrypted_message($update['message']['chat_id'], $update['message']['decrypted_message']); @@ -71,7 +72,6 @@ trait ResponseHandler $this->save_update($update); break; case 'decryptedMessageLayer': - var_dump($update['message']); if ($this->check_secret_out_seq_no($update['message']['chat_id'], $update['message']['decrypted_message']['out_seq_no']) && $this->check_secret_in_seq_no($update['message']['chat_id'], $update['message']['decrypted_message']['in_seq_no'])) { $this->secret_chats[$update['message']['chat_id']]['in_seq_no']++; if ($update['message']['decrypted_message']['layer'] >= 17) { diff --git a/src/danog/MadelineProto/SecretChats/SeqNoHandler.php b/src/danog/MadelineProto/SecretChats/SeqNoHandler.php index c5574d5a..23cb0d7f 100644 --- a/src/danog/MadelineProto/SecretChats/SeqNoHandler.php +++ b/src/danog/MadelineProto/SecretChats/SeqNoHandler.php @@ -52,7 +52,7 @@ trait SeqNoHandler } } } - var_dump($C, $seqno); + //var_dump($C, $seqno); if ($seqno < $C) { // <= C \danog\MadelineProto\Logger::log(['WARNING: dropping repeated message with seqno '.$seqno]); diff --git a/src/danog/MadelineProto/TL/TL.php b/src/danog/MadelineProto/TL/TL.php index fb8e0033..7f4157c6 100644 --- a/src/danog/MadelineProto/TL/TL.php +++ b/src/danog/MadelineProto/TL/TL.php @@ -593,7 +593,7 @@ trait TL } if ($constructorData['type'] === 'Vector t') { $constructorData['datacenter'] = $type['datacenter']; - $constructorData['subtype'] = $type['subtype']; + $constructorData['subtype'] = isset($type['subtype']) ? $type['subtype'] : ''; $constructorData['type'] = 'vector'; return $this->deserialize($stream, $constructorData); diff --git a/src/danog/MadelineProto/Wrappers/DialogHandler.php b/src/danog/MadelineProto/Wrappers/DialogHandler.php index fc2355cd..36230876 100644 --- a/src/danog/MadelineProto/Wrappers/DialogHandler.php +++ b/src/danog/MadelineProto/Wrappers/DialogHandler.php @@ -19,7 +19,7 @@ trait DialogHandler if (!isset($this->dialog_params['offset_date']) || $force) { $this->dialog_params = ['limit' => 0, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty']]; } - $this->getting_state = true; + $this->updates_state["sync_loading"] = true; $res = ['dialogs' => [0]]; $datacenter = $this->datacenter->curdc; $count = 0; @@ -36,6 +36,6 @@ trait DialogHandler } } - $this->getting_state = false; + $this->updates_state["sync_loading"] = false; } } diff --git a/tests/testing.php b/tests/testing.php index 90266890..cac596de 100755 --- a/tests/testing.php +++ b/tests/testing.php @@ -72,7 +72,7 @@ $message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sem echo 'Serializing MadelineProto to session.madeline...'.PHP_EOL; echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('session.madeline', $MadelineProto).' bytes'.PHP_EOL; -if (stripos(readline('Do you want to make the secret chat tests? (y/n)'), 'y') !== false) { +if (stripos(readline('Do you want to make the secret chat tests? (y/n): '), 'y') !== false) { /* $call = $MadelineProto->API->request_call(getenv('TEST_SECRET_CHAT')); @@ -104,8 +104,8 @@ var_dump($MadelineProto->get_call($call)); case 'updateNewEncryptedMessage': var_dump($update); } + echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('session.madeline', $MadelineProto).' bytes'.PHP_EOL; } - echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('bot.madeline', $MadelineProto).' bytes'.PHP_EOL; } $secret_media = [];