Huge performance improvements

This commit is contained in:
Daniil Gentili 2017-08-27 20:20:55 +02:00
parent 37ab960266
commit 90fc78014e
21 changed files with 71 additions and 95 deletions

View File

@ -29,7 +29,6 @@ class API extends APIFactory
\danog\MadelineProto\Logger::log(['Pong: '.$pong['ping_id']], Logger::ULTRA_VERBOSE); \danog\MadelineProto\Logger::log(['Pong: '.$pong['ping_id']], Logger::ULTRA_VERBOSE);
//\danog\MadelineProto\Logger::log(['Getting future salts...'], Logger::ULTRA_VERBOSE); //\danog\MadelineProto\Logger::log(['Getting future salts...'], Logger::ULTRA_VERBOSE);
//$this->future_salts = $this->get_future_salts(['num' => 3]); //$this->future_salts = $this->get_future_salts(['num' => 3]);
$this->API->v = \danog\MadelineProto\MTProto::V;
\danog\MadelineProto\Logger::log(['MadelineProto is ready!'], Logger::NOTICE); \danog\MadelineProto\Logger::log(['MadelineProto is ready!'], Logger::NOTICE);
} }

View File

@ -129,14 +129,14 @@ class APIFactory
$this->API->__construct($this->API->settings); $this->API->__construct($this->API->settings);
} }
$this->API->get_config([], ['datacenter' => $this->API->datacenter->curdc]); $this->API->get_config([], ['datacenter' => $this->API->datacenter->curdc]);
$aargs = isset($arguments[1]) && $this->is_array($arguments[1]) ? $arguments[1] : []; $aargs = isset($arguments[1]) && is_array($arguments[1]) ? $arguments[1] : [];
$aargs['datacenter'] = $this->API->datacenter->curdc; $aargs['datacenter'] = $this->API->datacenter->curdc;
if ($this->lua === false) { if ($this->lua === false) {
return method_exists($this->API, $this->namespace.$name) ? $this->API->{$this->namespace.$name}(...$arguments) : $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && $this->is_array($arguments[0])) ? $arguments[0] : [], $aargs); return method_exists($this->API, $this->namespace.$name) ? $this->API->{$this->namespace.$name}(...$arguments) : $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && is_array($arguments[0])) ? $arguments[0] : [], $aargs);
} }
try { try {
$deserialized = method_exists($this->API, $this->namespace.$name) ? $this->API->{$this->namespace.$name}(...$arguments) : $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && $this->is_array($arguments[0])) ? $arguments[0] : [], $aargs); $deserialized = method_exists($this->API, $this->namespace.$name) ? $this->API->{$this->namespace.$name}(...$arguments) : $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && is_array($arguments[0])) ? $arguments[0] : [], $aargs);
Lua::convert_objects($deserialized); Lua::convert_objects($deserialized);
return $deserialized; return $deserialized;

View File

@ -15,7 +15,7 @@ namespace danog\MadelineProto;
/** /**
* Manages connection to telegram servers. * Manages connection to telegram servers.
*/ */
class Connection extends \Volatile class Connection
{ {
use \danog\Serializable; use \danog\Serializable;
use \danog\MadelineProto\Tools; use \danog\MadelineProto\Tools;

View File

@ -15,7 +15,7 @@ namespace danog\MadelineProto;
/** /**
* Manages datacenters. * Manages datacenters.
*/ */
class DataCenter extends \Volatile class DataCenter
{ {
use \danog\MadelineProto\Tools; use \danog\MadelineProto\Tools;
use \danog\Serializable; use \danog\Serializable;

View File

@ -100,7 +100,7 @@ class Lua
private function convert_array($array) private function convert_array($array)
{ {
if (!$this->is_array($value)) { if (!is_array($value)) {
return $array; return $array;
} }
if ($this->is_seqential($value)) { if ($this->is_seqential($value)) {

View File

@ -15,7 +15,7 @@ namespace danog\MadelineProto;
/** /**
* Manages all of the mtproto stuff. * Manages all of the mtproto stuff.
*/ */
class MTProto extends \Volatile class MTProto
{ {
use \danog\Serializable; use \danog\Serializable;
use \danog\MadelineProto\MTProtoTools\AckHandler; use \danog\MadelineProto\MTProtoTools\AckHandler;
@ -43,8 +43,10 @@ class MTProto extends \Volatile
use \danog\MadelineProto\VoIP\AuthKeyHandler; use \danog\MadelineProto\VoIP\AuthKeyHandler;
use \danog\MadelineProto\Wrappers\DialogHandler; use \danog\MadelineProto\Wrappers\DialogHandler;
use \danog\MadelineProto\Wrappers\Login; use \danog\MadelineProto\Wrappers\Login;
/*
const V = 71; const V = 71;
*/
const V = 72;
const NOT_LOGGED_IN = 0; const NOT_LOGGED_IN = 0;
const WAITING_CODE = 1; const WAITING_CODE = 1;
@ -615,6 +617,8 @@ class MTProto extends \Volatile
$socket->session_id = $this->random(8); $socket->session_id = $this->random(8);
$socket->session_in_seq_no = 0; $socket->session_in_seq_no = 0;
$socket->session_out_seq_no = 0; $socket->session_out_seq_no = 0;
$socket->max_incoming_id = null;
$socket->max_outgoing_id = null;
} }
if ($auth_key) { if ($auth_key) {
$socket->temp_auth_key = null; $socket->temp_auth_key = null;

View File

@ -65,7 +65,7 @@ trait AuthKeyHandler
*/ */
foreach ($this->rsa_keys as $curkey) { foreach ($this->rsa_keys as $curkey) {
if ($this->in_array($curkey->fp, $ResPQ['server_public_key_fingerprints'])) { if (in_array($curkey->fp, $ResPQ['server_public_key_fingerprints'])) {
$key = $curkey; $key = $curkey;
} }
} }

View File

@ -19,10 +19,10 @@ trait CallHandler
{ {
public function method_call($method, $args = [], $aargs = ['message_id' => null, 'heavy' => false]) public function method_call($method, $args = [], $aargs = ['message_id' => null, 'heavy' => false])
{ {
if (!$this->is_array($args)) { if (!is_array($args)) {
throw new \danog\MadelineProto\Exception("Arguments aren't an array."); throw new \danog\MadelineProto\Exception("Arguments aren't an array.");
} }
if (!$this->is_array($aargs)) { if (!is_array($aargs)) {
throw new \danog\MadelineProto\Exception("Additonal arguments aren't an array."); throw new \danog\MadelineProto\Exception("Additonal arguments aren't an array.");
} }
if (!isset($aargs['datacenter'])) { if (!isset($aargs['datacenter'])) {
@ -90,7 +90,7 @@ trait CallHandler
reset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue]); reset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue]);
$key = key($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue]); $key = key($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue]);
if ($key[0] === "\0") { if ($key[0] === "\0") {
$key = 'a'.$key; $key = $key;
} }
unset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue][$key]); unset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue][$key]);
} }
@ -206,7 +206,7 @@ trait CallHandler
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
$last_error = $e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine(); $last_error = $e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine();
\danog\MadelineProto\Logger::log(['An error occurred while calling method '.$method.': '.$last_error.'. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING); \danog\MadelineProto\Logger::log(['An error occurred while calling method '.$method.': '.$last_error.'. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING);
if ($this->in_array($this->datacenter->sockets[$aargs['datacenter']]->protocol, ['http', 'https']) && $method !== 'http_wait') { if (in_array($this->datacenter->sockets[$aargs['datacenter']]->protocol, ['http', 'https']) && $method !== 'http_wait') {
//$this->method_call('http_wait', ['max_wait' => $this->datacenter->sockets[$aargs['datacenter']]->timeout, 'wait_after' => 0, 'max_delay' => 0], ['datacenter' => $aargs['datacenter']]); //$this->method_call('http_wait', ['max_wait' => $this->datacenter->sockets[$aargs['datacenter']]->timeout, 'wait_after' => 0, 'max_delay' => 0], ['datacenter' => $aargs['datacenter']]);
} else { } else {
$this->datacenter->sockets[$aargs['datacenter']]->close_and_reopen(); $this->datacenter->sockets[$aargs['datacenter']]->close_and_reopen();
@ -216,7 +216,7 @@ trait CallHandler
} catch (\RuntimeException $e) { } catch (\RuntimeException $e) {
$last_error = $e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine(); $last_error = $e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine();
\danog\MadelineProto\Logger::log(['An error occurred while calling method '.$method.': '.$last_error.'. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING); \danog\MadelineProto\Logger::log(['An error occurred while calling method '.$method.': '.$last_error.'. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING);
if ($this->in_array($this->datacenter->sockets[$aargs['datacenter']]->protocol, ['http', 'https']) && $method !== 'http_wait') { if (in_array($this->datacenter->sockets[$aargs['datacenter']]->protocol, ['http', 'https']) && $method !== 'http_wait') {
//$this->method_call('http_wait', ['max_wait' => $this->datacenter->sockets[$aargs['datacenter']]->timeout, 'wait_after' => 0, 'max_delay' => 0], ['datacenter' => $aargs['datacenter']]); //$this->method_call('http_wait', ['max_wait' => $this->datacenter->sockets[$aargs['datacenter']]->timeout, 'wait_after' => 0, 'max_delay' => 0], ['datacenter' => $aargs['datacenter']]);
} else { } else {
$this->datacenter->sockets[$aargs['datacenter']]->close_and_reopen(); $this->datacenter->sockets[$aargs['datacenter']]->close_and_reopen();
@ -271,7 +271,7 @@ trait CallHandler
public function object_call($object, $args = [], $aargs = ['message_id' => null, 'heavy' => false]) public function object_call($object, $args = [], $aargs = ['message_id' => null, 'heavy' => false])
{ {
if (!$this->is_array($args)) { if (!is_array($args)) {
throw new \danog\MadelineProto\Exception("Arguments aren't an array."); throw new \danog\MadelineProto\Exception("Arguments aren't an array.");
} }
if (!isset($aargs['datacenter'])) { if (!isset($aargs['datacenter'])) {

View File

@ -31,7 +31,7 @@ trait MessageHandler
if (!is_string($message_id)) { if (!is_string($message_id)) {
throw new \danog\MadelineProto\Exception("Specified message id isn't a string"); throw new \danog\MadelineProto\Exception("Specified message id isn't a string");
} }
$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages['a'.$message_id] = []; $this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id] = [];
if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['auth_key'] === null || $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['server_salt'] === null) { if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['auth_key'] === null || $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['server_salt'] === null) {
$message = "\0\0\0\0\0\0\0\0".$message_id.$this->pack_unsigned_int(strlen($message_data)).$message_data; $message = "\0\0\0\0\0\0\0\0".$message_id.$this->pack_unsigned_int(strlen($message_data)).$message_data;
@ -42,12 +42,12 @@ trait MessageHandler
$message_key = substr(sha1($data2enc, true), -16); $message_key = substr(sha1($data2enc, true), -16);
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['auth_key']); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['auth_key']);
$message = $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['id'].$message_key.$this->ige_encrypt($data2enc.$padding, $aes_key, $aes_iv); $message = $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['id'].$message_key.$this->ige_encrypt($data2enc.$padding, $aes_key, $aes_iv);
$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages['a'.$message_id]['seq_no'] = $seq_no; $this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['seq_no'] = $seq_no;
} }
$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages['a'.$message_id]['response'] = -1; $this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['response'] = -1;
$this->datacenter->sockets[$aargs['datacenter']]->send_message($message); $this->datacenter->sockets[$aargs['datacenter']]->send_message($message);
return 'a'.$message_id; return $message_id;
} }
/** /**
@ -61,7 +61,7 @@ trait MessageHandler
} }
$auth_key_id = substr($payload, 0, 8); $auth_key_id = substr($payload, 0, 8);
if ($auth_key_id === "\0\0\0\0\0\0\0\0") { if ($auth_key_id === "\0\0\0\0\0\0\0\0") {
$message_id = 'a'.substr($payload, 8, 8); $message_id = substr($payload, 8, 8);
$this->check_message_id($message_id, ['outgoing' => false, 'datacenter' => $datacenter, 'container' => false]); $this->check_message_id($message_id, ['outgoing' => false, 'datacenter' => $datacenter, 'container' => false]);
$message_length = unpack('V', substr($payload, 16, 4))[1]; $message_length = unpack('V', substr($payload, 16, 4))[1];
$message_data = substr($payload, 20, $message_length); $message_data = substr($payload, 20, $message_length);
@ -82,7 +82,7 @@ trait MessageHandler
throw new \danog\MadelineProto\Exception('Session id mismatch.'); throw new \danog\MadelineProto\Exception('Session id mismatch.');
} }
$message_id = 'a'.substr($decrypted_data, 16, 8); $message_id = substr($decrypted_data, 16, 8);
$this->check_message_id($message_id, ['outgoing' => false, 'datacenter' => $datacenter, 'container' => false]); $this->check_message_id($message_id, ['outgoing' => false, 'datacenter' => $datacenter, 'container' => false]);
$seq_no = unpack('V', substr($decrypted_data, 24, 4))[1]; $seq_no = unpack('V', substr($decrypted_data, 24, 4))[1];

View File

@ -20,7 +20,7 @@ trait MsgIdHandler
public function check_message_id($new_message_id, $aargs) public function check_message_id($new_message_id, $aargs)
{ {
if (!is_object($new_message_id)) { if (!is_object($new_message_id)) {
$new_message_id = new \phpseclib\Math\BigInteger(strrev(substr($new_message_id, 1)), 256); $new_message_id = new \phpseclib\Math\BigInteger(strrev($new_message_id), 256);
} }
$min_message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$aargs['datacenter']]->time_delta - 300))->bitwise_leftShift(32); $min_message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$aargs['datacenter']]->time_delta - 300))->bitwise_leftShift(32);
if ($min_message_id->compare($new_message_id) > 0) { if ($min_message_id->compare($new_message_id) > 0) {
@ -40,13 +40,10 @@ trait MsgIdHandler
if (count($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages) > $this->settings['msg_array_limit']['outgoing']) { if (count($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages) > $this->settings['msg_array_limit']['outgoing']) {
reset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages); reset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages);
$key = key($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages); $key = key($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages);
if ($key[0] === "\0") {
$key = 'a'.$key;
}
unset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$key]); unset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$key]);
} }
$this->datacenter->sockets[$aargs['datacenter']]->max_outgoing_id = $new_message_id; $this->datacenter->sockets[$aargs['datacenter']]->max_outgoing_id = $new_message_id;
$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages['a'.strrev($new_message_id->toBytes())] = []; $this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[strrev($new_message_id->toBytes())] = [];
} else { } else {
if (!$new_message_id->divide($this->four)[1]->equals($this->one) && !$new_message_id->divide($this->four)[1]->equals($this->three)) { if (!$new_message_id->divide($this->four)[1]->equals($this->one) && !$new_message_id->divide($this->four)[1]->equals($this->three)) {
throw new \danog\MadelineProto\Exception('message id mod 4 != 1 or 3'); throw new \danog\MadelineProto\Exception('message id mod 4 != 1 or 3');
@ -66,12 +63,12 @@ trait MsgIdHandler
reset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages); reset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages);
$key = key($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages); $key = key($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages);
if ($key[0] === "\0") { if ($key[0] === "\0") {
$key = 'a'.$key; $key = $key;
} }
unset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[$key]); unset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[$key]);
} }
$this->datacenter->sockets[$aargs['datacenter']]->max_incoming_id = $new_message_id; $this->datacenter->sockets[$aargs['datacenter']]->max_incoming_id = $new_message_id;
$this->datacenter->sockets[$aargs['datacenter']]->incoming_messages['a'.strrev($new_message_id->toBytes())] = []; $this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[strrev($new_message_id->toBytes())] = [];
} }
} }
@ -94,16 +91,5 @@ trait MsgIdHandler
} }
return $this->zero; return $this->zero;
/*
$keys = array_keys((array) $this->datacenter->sockets[$datacenter]->{$incoming.'_messages'});
if (empty($keys)) {
return $this->zero;
}
array_walk($keys, function (&$value, $key) {
$value = new \phpseclib\Math\BigInteger(strrev(substr($value, 1)), 256);
});
return \phpseclib\Math\BigInteger::max(...$keys);
*/
} }
} }

View File

@ -142,7 +142,7 @@ trait PeerHandler
public function get_info($id, $recursive = true) public function get_info($id, $recursive = true)
{ {
if ($this->is_array($id)) { if (is_array($id)) {
switch ($id['_']) { switch ($id['_']) {
case 'inputUserSelf': case 'inputUserSelf':
case 'inputPeerSelf': case 'inputPeerSelf':

View File

@ -23,7 +23,7 @@ trait ResponseHandler
foreach ($msg_ids as $msg_id) { foreach ($msg_ids as $msg_id) {
$cur_info = 0; $cur_info = 0;
if (!isset($this->datacenter->sockets[$datacenter]->incoming_messages[$msg_id])) { if (!isset($this->datacenter->sockets[$datacenter]->incoming_messages[$msg_id])) {
$msg_id = new \phpseclib\Math\BigInteger(strrev(substr($msg_id, 1)), 256); $msg_id = new \phpseclib\Math\BigInteger(strrev($msg_id), 256);
if ((new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$datacenter]->time_delta + 30))->bitwise_leftShift(32)->compare($msg_id) < 0) { if ((new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$datacenter]->time_delta + 30))->bitwise_leftShift(32)->compare($msg_id) < 0) {
$cur_info |= 3; $cur_info |= 3;
} elseif ((new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$datacenter]->time_delta - 300))->bitwise_leftShift(32)->compare($msg_id) > 0) { } elseif ((new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$datacenter]->time_delta - 300))->bitwise_leftShift(32)->compare($msg_id) > 0) {
@ -187,7 +187,7 @@ trait ResponseHandler
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]); unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
foreach ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_ids'] as $key => $msg_id) { foreach ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_ids'] as $key => $msg_id) {
$msg_id = new \phpseclib\Math\BigInteger(strrev(substr($msg_id, 1)), 256); $msg_id = new \phpseclib\Math\BigInteger(strrev($msg_id), 256);
$status = 'Status for message id '.$msg_id.': '; $status = 'Status for message id '.$msg_id.': ';
if (($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['info'][$key] & 4) !== 0) { if (($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['info'][$key] & 4) !== 0) {
$this->ack_outgoing_message_id($msg_id, $datacenter); $this->ack_outgoing_message_id($msg_id, $datacenter);

View File

@ -44,7 +44,7 @@ trait SeqNoHandler
public function content_related($method) public function content_related($method)
{ {
return isset($method['_']) ? !$this->in_array( return isset($method['_']) ? !in_array(
$method['_'], $method['_'],
[ [
'rpc_result', 'rpc_result',

View File

@ -339,7 +339,7 @@ trait UpdateHandler
$cur_state = &$this->load_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'])) { if ($cur_state['sync_loading'] && in_array($update['_'], ['updateNewMessage', 'updateEditMessage', 'updateNewChannelMessage', 'updateEditChannelMessage'])) {
\danog\MadelineProto\Logger::log(['Sync loading, not handling update'], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log(['Sync loading, not handling update'], \danog\MadelineProto\Logger::NOTICE);
return false; return false;
@ -539,7 +539,7 @@ trait UpdateHandler
if ($update['_'] === 'updateEncryption') { if ($update['_'] === 'updateEncryption') {
switch ($update['chat']['_']) { switch ($update['chat']['_']) {
case 'encryptedChatRequested': case 'encryptedChatRequested':
if ($this->settings['secret_chats']['accept_chats'] === false || ($this->is_array($this->settings['secret_chats']['accept_chats']) && !$this->in_array($update['chat']['admin_id'], $this->settings['secret_chats']['accept_chats']))) { if ($this->settings['secret_chats']['accept_chats'] === false || (is_array($this->settings['secret_chats']['accept_chats']) && !in_array($update['chat']['admin_id'], $this->settings['secret_chats']['accept_chats']))) {
return; return;
} }
\danog\MadelineProto\Logger::log(['Accepting secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log(['Accepting secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE);
@ -611,7 +611,7 @@ trait UpdateHandler
curl_close($ch); curl_close($ch);
\danog\MadelineProto\Logger::log(['Result of webhook query is '.$result], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log(['Result of webhook query is '.$result], \danog\MadelineProto\Logger::NOTICE);
$result = json_decode($result, true); $result = json_decode($result, true);
if ($this->is_array($result) && isset($result['method']) && $result['method'] != '' && is_string($result['method'])) { if (is_array($result) && isset($result['method']) && $result['method'] != '' && is_string($result['method'])) {
try { try {
\danog\MadelineProto\Logger::log(['Reverse webhook command returned', $this->method_call($result['method'], $result, ['datacenter' => $this->datacenter->curdc])]); \danog\MadelineProto\Logger::log(['Reverse webhook command returned', $this->method_call($result['method'], $result, ['datacenter' => $this->datacenter->curdc])]);
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {

View File

@ -12,7 +12,7 @@ If not, see <http://www.gnu.org/licenses/>.
namespace danog\MadelineProto; namespace danog\MadelineProto;
class RSA extends \Volatile class RSA
{ {
use \danog\MadelineProto\TL\TL; use \danog\MadelineProto\TL\TL;
use \danog\MadelineProto\Tools; use \danog\MadelineProto\Tools;

View File

@ -32,9 +32,9 @@ class Serialization
touch($lock); touch($lock);
clearstatcache(); clearstatcache();
} }
$lock = fopen($lock, 'r'); $lock = fopen($lock, 'w');
flock($lock, LOCK_EX); flock($lock, LOCK_EX);
$wrote = file_put_contents($filename.'.temp.session', \danog\Serialization::serialize($instance, true)); $wrote = file_put_contents($filename.'.temp.session', serialize($instance));
rename($filename.'.temp.session', $filename); rename($filename.'.temp.session', $filename);
flock($lock, LOCK_UN); flock($lock, LOCK_UN);
fclose($lock); fclose($lock);
@ -64,22 +64,19 @@ class Serialization
$unserialized = file_get_contents($filename); $unserialized = file_get_contents($filename);
flock($lock, LOCK_UN); flock($lock, LOCK_UN);
fclose($lock); fclose($lock);
$unserialized = str_replace('O:26:"danog\MadelineProto\Button":', 'O:35:"danog\MadelineProto\TL\Types\Button":', $unserialized); $tounserialize = str_replace('O:26:"danog\MadelineProto\Button":', 'O:35:"danog\MadelineProto\TL\Types\Button":', $unserialized);
foreach (['RSA', 'TL\TLMethod', 'TL\TLConstructor', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\Types\Button', 'TL\Types\Bytes', 'APIFactory'] as $class) { foreach (['RSA', 'TL\TLMethod', 'TL\TLConstructor', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\Types\Button', 'TL\Types\Bytes', 'APIFactory'] as $class) {
class_exists('\danog\MadelineProto\\'.$class); class_exists('\danog\MadelineProto\\'.$class);
} }
class_exists('\Volatile'); class_exists('\Volatile');
\danog\MadelineProto\Logger::class_exists(); \danog\MadelineProto\Logger::class_exists();
try { try {
$unserialized = \danog\Serialization::unserialize($unserialized); $unserialized = unserialize($tounserialize);
} catch (Bug74586Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
$unserialized = \danog\Serialization::unserialize($unserialized); $unserialized = \danog\Serialization::unserialize($tounserialize);
/*} catch (Exception $e) { }
$unserialized = \danog\Serialization::unserialize($unserialized); if ($unserialized instanceof \danog\PlaceHolder) {
*/ $unserialized = \danog\Serialization::unserialize($tounserialize);
} catch (\Error $e) {
$unserialized = \danog\Serialization::unserialize($unserialized);
} }
} else { } else {
throw new Exception('File does not exist'); throw new Exception('File does not exist');

View File

@ -16,7 +16,7 @@ trait TD
{ {
public function tdcli_to_td(&$params, $key = null) public function tdcli_to_td(&$params, $key = null)
{ {
if (!$this->is_array($params)) { if (!is_array($params)) {
return $params; return $params;
} }
if (!isset($params['ID'])) { if (!isset($params['ID'])) {
@ -42,7 +42,7 @@ trait TD
$newparams = ['_' => self::REVERSE[$params['_']]]; $newparams = ['_' => self::REVERSE[$params['_']]];
foreach (self::TD_PARAMS_CONVERSION[$newparams['_']] as $td => $mtproto) { foreach (self::TD_PARAMS_CONVERSION[$newparams['_']] as $td => $mtproto) {
if ($this->is_array($mtproto)) { if (is_array($mtproto)) {
switch (end($mtproto)) { switch (end($mtproto)) {
case 'choose_message_content': case 'choose_message_content':
switch ($params[$td]['_']) { switch ($params[$td]['_']) {
@ -58,7 +58,7 @@ trait TD
break; break;
default: default:
$newparams[$mtproto[0]] = isset($params[$td]) ? $params[$td] : null; $newparams[$mtproto[0]] = isset($params[$td]) ? $params[$td] : null;
if ($this->is_array($newparams[$mtproto[0]])) { if (is_array($newparams[$mtproto[0]])) {
$newparams[$mtproto[0]] = $this->mtproto_to_td($newparams[$mtproto[0]]); $newparams[$mtproto[0]] = $this->mtproto_to_td($newparams[$mtproto[0]]);
} }
} }
@ -75,7 +75,7 @@ trait TD
public function mtproto_to_td(&$params) public function mtproto_to_td(&$params)
{ {
if (!$this->is_array($params)) { if (!is_array($params)) {
return $params; return $params;
} }
if (!isset($params['_'])) { if (!isset($params['_'])) {
@ -84,7 +84,7 @@ trait TD
return $params; return $params;
} }
$newparams = ['_' => $params['_']]; $newparams = ['_' => $params['_']];
if ($this->in_array($params['_'], self::TD_IGNORE)) { if (in_array($params['_'], self::TD_IGNORE)) {
return $params; return $params;
} }
foreach (self::TD_PARAMS_CONVERSION[$params['_']] as $td => $mtproto) { foreach (self::TD_PARAMS_CONVERSION[$params['_']] as $td => $mtproto) {
@ -146,7 +146,7 @@ trait TD
} else { } else {
$newparams[$td] = isset($params[$mtproto[0]]) ? $params[$mtproto[0]] : null; $newparams[$td] = isset($params[$mtproto[0]]) ? $params[$mtproto[0]] : null;
} }
if ($this->is_array($newparams[$td])) { if (is_array($newparams[$td])) {
$newparams[$td] = $this->mtproto_to_td($newparams[$td]); $newparams[$td] = $this->mtproto_to_td($newparams[$td]);
} }
} }
@ -158,7 +158,7 @@ trait TD
public function td_to_tdcli($params) public function td_to_tdcli($params)
{ {
if (!$this->is_array($params)) { if (!is_array($params)) {
return $params; return $params;
} }
$newparams = []; $newparams = [];

View File

@ -95,7 +95,7 @@ trait TL
continue; continue;
} }
$name = preg_replace(['/#.*/', '/\s.*/'], '', $line); $name = preg_replace(['/#.*/', '/\s.*/'], '', $line);
if ($this->in_array($name, ['bytes', 'int128', 'int256', 'int512'])) { if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
continue; continue;
} }
$clean = preg_replace([ $clean = preg_replace([
@ -331,7 +331,7 @@ trait TL
case '!X': case '!X':
return $object; return $object;
case 'Vector t': case 'Vector t':
if (!$this->is_array($object)) { if (!is_array($object)) {
throw new Exception("You didn't provide a valid array"); throw new Exception("You didn't provide a valid array");
} }
$concat = $this->constructors->find_by_predicate('vector')['id']; $concat = $this->constructors->find_by_predicate('vector')['id'];
@ -344,7 +344,7 @@ trait TL
} }
$auto = false; $auto = false;
if ((!$this->is_array($object) || (isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type'])) && $this->in_array($type['type'], ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) { if ((!is_array($object) || (isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type'])) && in_array($type['type'], ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) {
$object = $this->get_info($object); $object = $this->get_info($object);
if (!isset($object[$type['type']])) { if (!isset($object[$type['type']])) {
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database'); throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
@ -427,7 +427,7 @@ trait TL
$arguments['flags'] = $flags; $arguments['flags'] = $flags;
foreach ($tl['params'] as $current_argument) { foreach ($tl['params'] as $current_argument) {
if (!isset($arguments[$current_argument['name']])) { if (!isset($arguments[$current_argument['name']])) {
if (isset($current_argument['pow']) && ($this->in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) { if (isset($current_argument['pow']) && (in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) {
//\danog\MadelineProto\Logger::log(['Skipping '.$current_argument['name'].' of type '.$current_argument['type']); //\danog\MadelineProto\Logger::log(['Skipping '.$current_argument['name'].' of type '.$current_argument['type']);
continue; continue;
} }
@ -459,7 +459,7 @@ trait TL
throw new Exception('Missing required parameter', $current_argument['name']); throw new Exception('Missing required parameter', $current_argument['name']);
} }
if (!$this->is_array($arguments[$current_argument['name']]) && $current_argument['type'] === 'InputEncryptedChat') { if (!is_array($arguments[$current_argument['name']]) && $current_argument['type'] === 'InputEncryptedChat') {
if (!isset($this->secret_chats[$arguments[$current_argument['name']]])) { if (!isset($this->secret_chats[$arguments[$current_argument['name']]])) {
throw new \danog\MadelineProto\Exception('This secret peer is not present in the internal peer database'); throw new \danog\MadelineProto\Exception('This secret peer is not present in the internal peer database');
} }
@ -514,7 +514,7 @@ trait TL
return unpack('V', stream_get_contents($stream, 4))[1]; return unpack('V', stream_get_contents($stream, 4))[1];
case 'long': case 'long':
if (isset($type['idstrlong'])) { if (isset($type['idstrlong'])) {
return 'a'.stream_get_contents($stream, 8); return stream_get_contents($stream, 8);
} }
return \danog\MadelineProto\Logger::$bigint || isset($type['strlong']) ? stream_get_contents($stream, 8) : $this->unpack_signed_long(stream_get_contents($stream, 8)); return \danog\MadelineProto\Logger::$bigint || isset($type['strlong']) ? stream_get_contents($stream, 8) : $this->unpack_signed_long(stream_get_contents($stream, 8));
@ -628,13 +628,13 @@ trait TL
} }
} }
} }
if ($this->in_array($arg['name'], ['msg_ids', 'msg_id', 'bad_msg_id', 'req_msg_id', 'answer_msg_id', 'first_msg_id'])) { if (in_array($arg['name'], ['msg_ids', 'msg_id', 'bad_msg_id', 'req_msg_id', 'answer_msg_id', 'first_msg_id'])) {
$arg['idstrlong'] = true; $arg['idstrlong'] = true;
} }
if ($this->in_array($arg['name'], ['key_fingerprint', 'server_salt', 'new_server_salt', 'server_public_key_fingerprints', 'ping_id', 'exchange_id'])) { if (in_array($arg['name'], ['key_fingerprint', 'server_salt', 'new_server_salt', 'server_public_key_fingerprints', 'ping_id', 'exchange_id'])) {
$arg['strlong'] = true; $arg['strlong'] = true;
} }
if ($this->in_array($arg['name'], ['peer_tag', 'file_token', 'cdn_key', 'cdn_iv'])) { if (in_array($arg['name'], ['peer_tag', 'file_token', 'cdn_key', 'cdn_iv'])) {
$arg['type'] = 'string'; $arg['type'] = 'string';
} }

View File

@ -12,7 +12,7 @@ If not, see <http://www.gnu.org/licenses/>.
namespace danog\MadelineProto\TL; namespace danog\MadelineProto\TL;
class TLConstructor extends \Volatile class TLConstructor
{ {
use \danog\Serializable; use \danog\Serializable;
use \danog\MadelineProto\Tools; use \danog\MadelineProto\Tools;
@ -51,7 +51,7 @@ class TLConstructor extends \Volatile
foreach ($this->by_id as $id => $constructor) { foreach ($this->by_id as $id => $constructor) {
if ($constructor['type'] === $type) { if ($constructor['type'] === $type) {
$constructor['id'] = $id; $constructor['id'] = $id;
$constructor['params'] = $this->array_cast_recursive($constructor['params']); $constructor['params'] = $constructor['params'];
return $constructor; return $constructor;
} }
@ -77,14 +77,14 @@ class TLConstructor extends \Volatile
} }
$constructor = $this->by_id[$chosenid]; $constructor = $this->by_id[$chosenid];
$constructor['id'] = $chosenid; $constructor['id'] = $chosenid;
$constructor['params'] = $this->array_cast_recursive($constructor['params']); $constructor['params'] = $constructor['params'];
return $constructor; return $constructor;
} }
if (isset($this->by_predicate_and_layer[$predicate])) { if (isset($this->by_predicate_and_layer[$predicate])) {
$constructor = $this->by_id[$this->by_predicate_and_layer[$predicate]]; $constructor = $this->by_id[$this->by_predicate_and_layer[$predicate]];
$constructor['id'] = $this->by_predicate_and_layer[$predicate]; $constructor['id'] = $this->by_predicate_and_layer[$predicate];
$constructor['params'] = $this->array_cast_recursive($constructor['params']); $constructor['params'] = $constructor['params'];
return $constructor; return $constructor;
} }
@ -97,7 +97,7 @@ class TLConstructor extends \Volatile
if (isset($this->by_id[$id])) { if (isset($this->by_id[$id])) {
$constructor = $this->by_id[$id]; $constructor = $this->by_id[$id];
$constructor['id'] = $id; $constructor['id'] = $id;
$constructor['params'] = $this->array_cast_recursive($constructor['params']); $constructor['params'] = $constructor['params'];
return $constructor; return $constructor;
} }

View File

@ -12,7 +12,7 @@ If not, see <http://www.gnu.org/licenses/>.
namespace danog\MadelineProto\TL; namespace danog\MadelineProto\TL;
class TLMethod extends \Volatile class TLMethod
{ {
use \danog\Serializable; use \danog\Serializable;
use \danog\MadelineProto\Tools; use \danog\MadelineProto\Tools;
@ -44,7 +44,7 @@ class TLMethod extends \Volatile
if (isset($this->by_id[$id])) { if (isset($this->by_id[$id])) {
$method = $this->by_id[$id]; $method = $this->by_id[$id];
$method['id'] = $id; $method['id'] = $id;
$method['params'] = $this->array_cast_recursive($method['params']); $method['params'] = $method['params'];
return $method; return $method;
} }
@ -57,7 +57,7 @@ class TLMethod extends \Volatile
if (isset($this->by_method[$method_name])) { if (isset($this->by_method[$method_name])) {
$method = $this->by_id[$this->by_method[$method_name]]; $method = $this->by_id[$this->by_method[$method_name]];
$method['id'] = $this->by_method[$method_name]; $method['id'] = $this->by_method[$method_name];
$method['params'] = $this->array_cast_recursive($method['params']); $method['params'] = $method['params'];
return $method; return $method;
} }

View File

@ -33,22 +33,12 @@ trait Tools
return $resto < 0 ? ($resto + abs($b)) : $resto; return $resto < 0 ? ($resto + abs($b)) : $resto;
} }
public function is_array($elem)
{
return is_array($elem) || ($elem instanceof \Volatile);
}
public function __call($method, $params)
{
return (is_object($params[0]) || \danog\MadelineProto\Logger::$has_thread) ? $method(...$this->array_cast_recursive($params, true)) : $method(...$params);
}
public function array_cast_recursive($array, $force = false) public function array_cast_recursive($array, $force = false)
{ {
if (!\danog\MadelineProto\Logger::$has_thread && !$force) { if (!\danog\MadelineProto\Logger::$has_thread && !$force) {
return $array; return $array;
} }
if ($this->is_array($array)) { if (is_array($array)) {
if (!is_array($array)) { if (!is_array($array)) {
$array = (array) $array; $array = (array) $array;
} }