Fixes to secret chats and update handling

This commit is contained in:
Daniil Gentili 2017-06-05 12:23:23 +02:00
parent 658695ad67
commit 7e729ada7b
15 changed files with 156 additions and 193 deletions

View File

@ -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;
}

View File

@ -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";

View File

@ -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()

View File

@ -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']);

View File

@ -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];

View File

@ -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;

View File

@ -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));

View File

@ -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
}
}
}
}

View File

@ -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]);
}

View File

@ -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'];

View File

@ -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) {

View File

@ -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]);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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 = [];