Apply fixes from StyleCI

This commit is contained in:
Daniil Gentili 2017-03-11 18:55:56 +00:00 committed by StyleCI Bot
parent dfd8bf93da
commit f53927d3a7
20 changed files with 396 additions and 167 deletions

View File

@ -101,7 +101,9 @@ while (true) {
} else { } else {
array_walk($rows, function (&$value, $key) { array_walk($rows, function (&$value, $key) {
$value = explode('|', $value); $value = explode('|', $value);
array_walk($value, function (&$value, $key) { $value = ['text' => trim($value)]; }); array_walk($value, function (&$value, $key) {
$value = ['text' => trim($value)];
});
}); });
$toset['results'] = [['_' => 'inputBotInlineResult', 'id' => rand(0, pow(2, 31) - 1), 'type' => 'article', 'title' => $text, 'description' => 'Your keyboard', 'send_message' => ['_' => 'inputBotInlineMessageText', 'message' => $text, 'reply_markup' => ['inline_keyboard' => $rows]]]]; $toset['results'] = [['_' => 'inputBotInlineResult', 'id' => rand(0, pow(2, 31) - 1), 'type' => 'article', 'title' => $text, 'description' => 'Your keyboard', 'send_message' => ['_' => 'inputBotInlineMessageText', 'message' => $text, 'reply_markup' => ['inline_keyboard' => $rows]]]];
$MadelineProto->messages->setInlineBotResults($toset); $MadelineProto->messages->setInlineBotResults($toset);

View File

@ -97,6 +97,7 @@ trait BotAPI
foreach ($data as $key => $element) { foreach ($data as $key => $element) {
$newd[$key] = $this->MTProto_to_botAPI($element, $sent_arguments); $newd[$key] = $this->MTProto_to_botAPI($element, $sent_arguments);
} }
return $newd; return $newd;
} }
switch ($data['_']) { switch ($data['_']) {
@ -450,5 +451,4 @@ trait BotAPI
return $arguments; return $arguments;
} }
} }

View File

@ -59,6 +59,7 @@ trait BotAPIFiles
$new .= $cur; $new .= $cur;
} }
} }
return $new; return $new;
} }
@ -146,7 +147,6 @@ trait BotAPIFiles
return $res; return $res;
case 9: case 9:
$constructor = ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false]]]; $constructor = ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false]]];
list($type, $constructor['dc_id'], $constructor['id'], $constructor['access_hash'], $verify) = \danog\PHP\Struct::unpack('<iiqqb', $file_id); list($type, $constructor['dc_id'], $constructor['id'], $constructor['access_hash'], $verify) = \danog\PHP\Struct::unpack('<iiqqb', $file_id);

View File

@ -38,7 +38,7 @@ trait TD
'via_bot_user_id' => ['via_bot_id'], 'via_bot_user_id' => ['via_bot_id'],
'views' => ['views'], 'views' => ['views'],
'content' => ['choose_message_content'], 'content' => ['choose_message_content'],
'reply_markup' => ['reply_markup'] 'reply_markup' => ['reply_markup'],
], ],
'messages.sendMessage' => [ 'messages.sendMessage' => [
@ -47,17 +47,25 @@ trait TD
'disable_notification' => ['silent'], 'disable_notification' => ['silent'],
'from_background' => ['background'], 'from_background' => ['background'],
'input_message_content' => ['choose_message_content'], 'input_message_content' => ['choose_message_content'],
'reply_markup' => ['reply_markup'] 'reply_markup' => ['reply_markup'],
] ],
]; ];
private $reverse = [ private $reverse = [
'sendMessage'=> 'messages.sendMessage', 'sendMessage'=> 'messages.sendMessage',
]; ];
private $ignore = ['updateMessageID']; private $ignore = ['updateMessageID'];
public function tdcli_to_td(&$params, $key=null) {
if (!is_array($params)) return $params; public function tdcli_to_td(&$params, $key = null)
if (!isset($params['ID'])) { array_walk($params, [$this, 'tdcli_to_td']); return $params; } {
if (!is_array($params)) {
return $params;
}
if (!isset($params['ID'])) {
array_walk($params, [$this, 'tdcli_to_td']);
return $params;
}
foreach ($params as $key => $value) { foreach ($params as $key => $value) {
$value = $this->tdcli_to_td($value); $value = $this->tdcli_to_td($value);
if (preg_match('/_$/', $key)) { if (preg_match('/_$/', $key)) {
@ -67,9 +75,12 @@ trait TD
} }
$params['_'] = lcfirst($params['ID']); $params['_'] = lcfirst($params['ID']);
unset($params['ID']); unset($params['ID']);
return $params; return $params;
} }
public function td_to_mtproto($params) {
public function td_to_mtproto($params)
{
$newparams = ['_' => $this->reverse[$params['_']]]; $newparams = ['_' => $this->reverse[$params['_']]];
foreach ($this->td_params_conversion[$newparams['_']] as $td => $mtproto) { foreach ($this->td_params_conversion[$newparams['_']] as $td => $mtproto) {
@ -79,7 +90,9 @@ trait TD
switch ($params[$td]['_']) { switch ($params[$td]['_']) {
case 'inputMessageText': case 'inputMessageText':
$params[$td]['_'] = 'messages.sendMessage'; $params[$td]['_'] = 'messages.sendMessage';
if (isset($params['disable_web_page_preview'])) $newparams['no_webpage'] = $params[$td]['disable_web_page_preview']; if (isset($params['disable_web_page_preview'])) {
$newparams['no_webpage'] = $params[$td]['disable_web_page_preview'];
}
$newparams = array_merge($params[$td], $newparams); $newparams = array_merge($params[$td], $newparams);
break; break;
default: throw new Exception("Can't convert non text messages yet!"); default: throw new Exception("Can't convert non text messages yet!");
@ -87,20 +100,35 @@ 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 (is_array($newparams[$mtproto[0]])) $newparams[$mtproto[0]] = $this->mtproto_to_td($newparams[$mtproto[0]]); if (is_array($newparams[$mtproto[0]])) {
$newparams[$mtproto[0]] = $this->mtproto_to_td($newparams[$mtproto[0]]);
} }
} }
} }
}
return $newparams; return $newparams;
} }
public function mtproto_to_tdcli($params) {
public function mtproto_to_tdcli($params)
{
return $this->td_to_tdcli($this->mtproto_to_td($params)); return $this->td_to_tdcli($this->mtproto_to_td($params));
} }
public function mtproto_to_td(&$params) {
if (!is_array($params)) return $params; public function mtproto_to_td(&$params)
if (!isset($params['_'])) { array_walk($params, [$this, 'mtproto_to_td']); return $params; } {
if (!is_array($params)) {
return $params;
}
if (!isset($params['_'])) {
array_walk($params, [$this, 'mtproto_to_td']);
return $params;
}
$newparams = ['_' => $params['_']]; $newparams = ['_' => $params['_']];
if (in_array($params['_'], $this->ignore)) return $params; if (in_array($params['_'], $this->ignore)) {
return $params;
}
foreach ($this->td_params_conversion[$params['_']] as $td => $mtproto) { foreach ($this->td_params_conversion[$params['_']] as $td => $mtproto) {
if (is_string($mtproto)) { if (is_string($mtproto)) {
$newparams[$td] = $mtproto; $newparams[$td] = $mtproto;
@ -121,11 +149,19 @@ trait TD
case 'choose_forward_info': case 'choose_forward_info':
if (isset($params['fwd_from'])) { if (isset($params['fwd_from'])) {
$newparams[$td] = ['_' => 'messageForwardedFromUser']; $newparams[$td] = ['_' => 'messageForwardedFromUser'];
if (isset($params['fwd_from']['channel_id'])) $newparams[$td] = ['_'=> 'messageForwardedPost', 'chat_id' => '-100'.$params['fwd_from']['channel_id']]; if (isset($params['fwd_from']['channel_id'])) {
$newparams[$td] = ['_'=> 'messageForwardedPost', 'chat_id' => '-100'.$params['fwd_from']['channel_id']];
}
$newparams[$td]['date'] = $params['fwd_from']['date']; $newparams[$td]['date'] = $params['fwd_from']['date'];
if (isset($params['fwd_from']['channel_post'])) $newparams[$td]['channel_post'] = $params['fwd_from']['channel_post']; if (isset($params['fwd_from']['channel_post'])) {
if (isset($params['fwd_from']['from_id'])) $newparams[$td]['sender_user_id'] = $params['fwd_from']['from_id']; $newparams[$td]['channel_post'] = $params['fwd_from']['channel_post'];
} else $newparams[$td] = null; }
if (isset($params['fwd_from']['from_id'])) {
$newparams[$td]['sender_user_id'] = $params['fwd_from']['from_id'];
}
} else {
$newparams[$td] = null;
}
break; break;
case 'choose_ttl': case 'choose_ttl':
$newparams[$td] = isset($params['ttl']) ? $params['ttl'] : 0; $newparams[$td] = isset($params['ttl']) ? $params['ttl'] : 0;
@ -136,9 +172,15 @@ trait TD
case 'choose_message_content': case 'choose_message_content':
if ($params['message'] !== '') { if ($params['message'] !== '') {
$newparams[$td] = ['_' => 'messageText', 'text' => $params['message']]; $newparams[$td] = ['_' => 'messageText', 'text' => $params['message']];
if (isset($params['media']['_']) && $params['media']['_'] === 'messageMediaWebPage') $newparams[$td]['web_page'] = $this->mtproto_to_td($params['media']['webpage']); if (isset($params['media']['_']) && $params['media']['_'] === 'messageMediaWebPage') {
if (isset($params['entities'])) $newparams[$td]['entities'] = $params['entities']; $newparams[$td]['web_page'] = $this->mtproto_to_td($params['media']['webpage']);
} else throw new Exception("Can't convert non text messages yet!"); }
if (isset($params['entities'])) {
$newparams[$td]['entities'] = $params['entities'];
}
} else {
throw new Exception("Can't convert non text messages yet!");
}
break; break;
default: default:
if (isset($mtproto[1])) { if (isset($mtproto[1])) {
@ -146,24 +188,33 @@ 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 (is_array($newparams[$td])) $newparams[$td] = $this->mtproto_to_td($newparams[$td]); if (is_array($newparams[$td])) {
$newparams[$td] = $this->mtproto_to_td($newparams[$td]);
}
} }
} }
} }
return $newparams; return $newparams;
} }
public function td_to_tdcli($params) {
if (!is_array($params)) return $params; public function td_to_tdcli($params)
{
if (!is_array($params)) {
return $params;
}
$newparams = []; $newparams = [];
foreach ($params as $key => $value) { foreach ($params as $key => $value) {
if ($key === '_') { if ($key === '_') {
$newparams['ID'] = ucfirst($value); $newparams['ID'] = ucfirst($value);
} else { } else {
if (!is_numeric($key) && !preg_match('/_^/', $key)) $key = $key.'_'; if (!is_numeric($key) && !preg_match('/_^/', $key)) {
$key = $key.'_';
}
$newparams[$key] = $this->td_to_tdcli($value); $newparams[$key] = $this->td_to_tdcli($value);
} }
} }
return $newparams; return $newparams;
} }
} }

View File

@ -20,8 +20,12 @@ class DocsBuilder
{ {
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']); set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
$this->construct_TL($settings['tl_schema']); $this->construct_TL($settings['tl_schema']);
if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) $this->constructors = $this->td_constructors; if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) {
if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) $this->methods = $this->td_methods; $this->constructors = $this->td_constructors;
}
if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) {
$this->methods = $this->td_methods;
}
$this->settings = $settings; $this->settings = $settings;
if (!file_exists($this->settings['output_dir'])) { if (!file_exists($this->settings['output_dir'])) {
mkdir($this->settings['output_dir']); mkdir($this->settings['output_dir']);
@ -155,7 +159,7 @@ description: '.$this->settings['description'].'
$params .= "'".$param['name']."' => "; $params .= "'".$param['name']."' => ";
$params .= (isset($param['subtype']) ? '['.$ptype.']' : $ptype).', '; $params .= (isset($param['subtype']) ? '['.$ptype.']' : $ptype).', ';
$lua_params .= $param['name']."="; $lua_params .= $param['name'].'=';
$lua_params .= (isset($param['subtype']) ? '{'.$ptype.'}' : $ptype).', '; $lua_params .= (isset($param['subtype']) ? '{'.$ptype.'}' : $ptype).', ';
if ($param['name'] === 'entities') { if ($param['name'] === 'entities') {
$hasentities = true; $hasentities = true;
@ -389,7 +393,7 @@ description: List of methods
$params .= "'".$param['name']."' => "; $params .= "'".$param['name']."' => ";
$params .= (isset($param['subtype']) ? '['.$param['subtype'].']' : $param['type']).', '; $params .= (isset($param['subtype']) ? '['.$param['subtype'].']' : $param['type']).', ';
$lua_params .= $param['name']."="; $lua_params .= $param['name'].'=';
$lua_params .= (isset($param['subtype']) ? '{'.$param['subtype'].'}' : $param['type']).', '; $lua_params .= (isset($param['subtype']) ? '{'.$param['subtype'].'}' : $param['type']).', ';
} }
$params = "['_' => '".$rconstructor."', ".$params.']'; $params = "['_' => '".$rconstructor."', ".$params.']';
@ -531,11 +535,11 @@ $".$type." = 'channel#38575794'; // tg-cli style id (channels)
$header .= 'The following syntax can also be used: $header .= 'The following syntax can also be used:
``` ```
$'.$type." = -147286699; // Numeric chat id returned by request_secret_chat, can be positive or negative $'.$type.' = -147286699; // Numeric chat id returned by request_secret_chat, can be positive or negative
``` ```
"; ';
} }
$constructors = '### Possible values (constructors): $constructors = '### Possible values (constructors):

View File

@ -18,8 +18,11 @@ class Lua
private $Lua; private $Lua;
private $script; private $script;
public function __construct($script, $MadelineProto) { public function __construct($script, $MadelineProto)
if (!file_exists($script)) throw new Exception('Provided script does not exist'); {
if (!file_exists($script)) {
throw new Exception('Provided script does not exist');
}
$this->MadelineProto = $MadelineProto; $this->MadelineProto = $MadelineProto;
$settings = $this->MadelineProto->get_settings(); $settings = $this->MadelineProto->get_settings();
$settings['updates']['handle_updates'] = true; $settings['updates']['handle_updates'] = true;
@ -27,8 +30,14 @@ class Lua
$this->script = $script; $this->script = $script;
$this->__wakeup(); $this->__wakeup();
} }
public function __sleep() { return ['MadelineProto', 'script']; }
public function __wakeup() { public function __sleep()
{
return ['MadelineProto', 'script'];
}
public function __wakeup()
{
$this->Lua = new \Lua($this->script); $this->Lua = new \Lua($this->script);
$this->madelineproto_lua = 1; $this->madelineproto_lua = 1;
$this->Lua->registerCallback('tdcli_function', [$this, 'tdcli_function']); $this->Lua->registerCallback('tdcli_function', [$this, 'tdcli_function']);
@ -45,37 +54,73 @@ class Lua
$this->{$namespace} = $methods[$namespace]; $this->{$namespace} = $methods[$namespace];
} }
} }
public function tdcli_function ($params, $cb = null, $cb_extra = null) {
public function tdcli_function($params, $cb = null, $cb_extra = null)
{
$params = $this->MadelineProto->td_to_mtproto($this->MadelineProto->tdcli_to_td($params)); $params = $this->MadelineProto->td_to_mtproto($this->MadelineProto->tdcli_to_td($params));
if ($params === 0) return 0; if ($params === 0) {
return 0;
}
$result = $this->MadelineProto->API->method_call($params['_'], $params); $result = $this->MadelineProto->API->method_call($params['_'], $params);
if (is_callable($cb)) $cb($this->MadelineProto->mtproto_to_td($result), $cb_extra); if (is_callable($cb)) {
$cb($this->MadelineProto->mtproto_to_td($result), $cb_extra);
}
return $result; return $result;
} }
public function madeline_function ($params, $cb = null, $cb_extra = null) { public function madeline_function($params, $cb = null, $cb_extra = null)
{
$result = $this->MadelineProto->API->method_call($params['_'], $params); $result = $this->MadelineProto->API->method_call($params['_'], $params);
if (is_callable($cb)) $cb($result, $cb_extra); if (is_callable($cb)) {
$cb($result, $cb_extra);
}
return $result; return $result;
} }
public function tdcli_update_callback($update) {
public function tdcli_update_callback($update)
{
$this->Lua->tdcli_update_callback($this->MadelineProto->mtproto_to_tdcli($update)); $this->Lua->tdcli_update_callback($this->MadelineProto->mtproto_to_tdcli($update));
} }
private function convert_array($array)
private function convert_array($array) { {
if (!is_array($value)) return $array; if (!is_array($value)) {
if ($this->is_seqential($value)) return array_flip(array_map(function($el){ return $el + 1; }, array_flip($array))); return $array;
}
if ($this->is_seqential($value)) {
return array_flip(array_map(function ($el) {
return $el + 1;
}, array_flip($array)));
}
}
private function is_sequential(array $arr)
{
if ([] === $arr) {
return false;
} }
private function is_sequential(array $arr) {
if (array() === $arr) return false;
return isset($arr[0]) && array_keys($arr) === range(0, count($arr) - 1); return isset($arr[0]) && array_keys($arr) === range(0, count($arr) - 1);
} }
public function __get($name) {
if ($name === 'API') return $this->MadelineProto->API; public function __get($name)
{
if ($name === 'API') {
return $this->MadelineProto->API;
}
return $this->Lua->{$name}; return $this->Lua->{$name};
} }
public function __call($name, $params) { return $this->Lua->{$name}(...$params); }
public function __set($name, $value) { return $this->Lua->{$name} = $value; } public function __call($name, $params)
{
return $this->Lua->{$name}(...$params);
}
public function __set($name, $value)
{
return $this->Lua->{$name} = $value;
}
} }

View File

@ -71,7 +71,6 @@ class MTProto
$this->twoe2047 = new \phpseclib\Math\BigInteger('16158503035655503650357438344334975980222051334857742016065172713762327569433945446598600705761456731844358980460949009747059779575245460547544076193224141560315438683650498045875098875194826053398028819192033784138396109321309878080919047169238085235290822926018152521443787945770532904303776199561965192760957166694834171210342487393282284747428088017663161029038902829665513096354230157075129296432088558362971801859230928678799175576150822952201848806616643615613562842355410104862578550863465661734839271290328348967522998634176499319107762583194718667771801067716614802322659239302476074096777926805529798115328'); $this->twoe2047 = new \phpseclib\Math\BigInteger('16158503035655503650357438344334975980222051334857742016065172713762327569433945446598600705761456731844358980460949009747059779575245460547544076193224141560315438683650498045875098875194826053398028819192033784138396109321309878080919047169238085235290822926018152521443787945770532904303776199561965192760957166694834171210342487393282284747428088017663161029038902829665513096354230157075129296432088558362971801859230928678799175576150822952201848806616643615613562842355410104862578550863465661734839271290328348967522998634176499319107762583194718667771801067716614802322659239302476074096777926805529798115328');
$this->twoe2048 = new \phpseclib\Math\BigInteger('32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656'); $this->twoe2048 = new \phpseclib\Math\BigInteger('32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656');
$this->switch_dc(2, true); $this->switch_dc(2, true);
$this->get_config(); $this->get_config();
} }
@ -387,7 +386,9 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
{ {
return 2; return 2;
} }
public function get_self() {
public function get_self()
{
return $this->datacenter->authorization['user']; return $this->datacenter->authorization['user'];
} }
} }

View File

@ -414,7 +414,9 @@ trait AuthKeyHandler
throw new \danog\MadelineProto\SecurityException('Auth Failed'); throw new \danog\MadelineProto\SecurityException('Auth Failed');
} }
public function check_G($g_a, $p) {
public function check_G($g_a, $p)
{
/* /*
* *********************************************************************** * ***********************************************************************
@ -437,7 +439,9 @@ trait AuthKeyHandler
return true; return true;
} }
public function check_p_g($p, $g) {
public function check_p_g($p, $g)
{
/* /*
* *********************************************************************** * ***********************************************************************
* Check validity of dh_prime * Check validity of dh_prime
@ -486,24 +490,32 @@ trait AuthKeyHandler
) { ) {
throw new \danog\MadelineProto\SecurityException('g is invalid (1 < g < p - 1 is false).'); throw new \danog\MadelineProto\SecurityException('g is invalid (1 < g < p - 1 is false).');
} }
return true; return true;
} }
public function get_dh_config() {
public function get_dh_config()
{
$this->getting_state = true; $this->getting_state = true;
$dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0]); $dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0]);
$this->getting_state = false; $this->getting_state = false;
if ($dh_config['_'] === 'messages.dhConfigNotModified') { if ($dh_config['_'] === 'messages.dhConfigNotModified') {
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Logger::VERBOSE, ['DH configuration not modified']); \danog\MadelineProto\Logger::log(\danog\MadelineProto\Logger::VERBOSE, ['DH configuration not modified']);
return $this->dh_config; return $this->dh_config;
} }
$dh_config['p'] = new \phpseclib\Math\BigInteger($dh_config['p'], 256); $dh_config['p'] = new \phpseclib\Math\BigInteger($dh_config['p'], 256);
$dh_config['g'] = new \phpseclib\Math\BigInteger($dh_config['g']); $dh_config['g'] = new \phpseclib\Math\BigInteger($dh_config['g']);
$this->check_p_g($dh_config['p'], $dh_config['g']); $this->check_p_g($dh_config['p'], $dh_config['g']);
return $this->dh_config = $dh_config; return $this->dh_config = $dh_config;
} }
private $temp_requested_secret_chats = []; private $temp_requested_secret_chats = [];
private $secret_chats = []; private $secret_chats = [];
public function accept_secret_chat($params) {
public function accept_secret_chat($params)
{
$dh_config = $this->get_dh_config(); $dh_config = $this->get_dh_config();
\danog\MadelineProto\Logger::log(['Generating b...'], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log(['Generating b...'], \danog\MadelineProto\Logger::VERBOSE);
$b = new \phpseclib\Math\BigInteger($this->random(256), 256); $b = new \phpseclib\Math\BigInteger($this->random(256), 256);
@ -518,9 +530,10 @@ trait AuthKeyHandler
$this->check_G($g_b, $dh_config['p']); $this->check_G($g_b, $dh_config['p']);
$this->notify_layer($params['id']); $this->notify_layer($params['id']);
$this->handle_pending_updates(); $this->handle_pending_updates();
} }
public function request_secret_chat($user) {
public function request_secret_chat($user)
{
$user = $this->get_info($user)['InputUser']; $user = $this->get_info($user)['InputUser'];
\danog\MadelineProto\Logger::log(['Creating secret chat with '.$user['user_id'].'...'], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log(['Creating secret chat with '.$user['user_id'].'...'], \danog\MadelineProto\Logger::VERBOSE);
$dh_config = $this->get_dh_config(); $dh_config = $this->get_dh_config();
@ -533,11 +546,15 @@ trait AuthKeyHandler
$this->temp_requested_secret_chats[$res['id']] = $a; $this->temp_requested_secret_chats[$res['id']] = $a;
$this->handle_pending_updates(); $this->handle_pending_updates();
$this->get_updates_difference(); $this->get_updates_difference();
return $res['id']; return $res['id'];
} }
public function complete_secret_chat($params) {
public function complete_secret_chat($params)
{
if ($this->secret_chat_status($params['id']) !== 1) { if ($this->secret_chat_status($params['id']) !== 1) {
\danog\MadelineProto\Logger::log(['Could not find and complete secret chat '.$params['id']]); \danog\MadelineProto\Logger::log(['Could not find and complete secret chat '.$params['id']]);
return false; return false;
} }
$dh_config = $this->get_dh_config(); $dh_config = $this->get_dh_config();
@ -556,12 +573,19 @@ trait AuthKeyHandler
$this->notify_layer($params['id']); $this->notify_layer($params['id']);
$this->handle_pending_updates(); $this->handle_pending_updates();
} }
public function notify_layer($chat) {
public function notify_layer($chat)
{
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNotifyLayer', 'layer' => $this->encrypted_layer]]]); $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNotifyLayer', 'layer' => $this->encrypted_layer]]]);
} }
private $temp_rekeyed_secret_chats = []; private $temp_rekeyed_secret_chats = [];
public function rekey($chat) {
if ($this->secret_chats[$chat]['rekeying'][0] !== 0) return; public function rekey($chat)
{
if ($this->secret_chats[$chat]['rekeying'][0] !== 0) {
return;
}
\danog\MadelineProto\Logger::log(['Rekeying secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log(['Rekeying secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE);
$dh_config = $this->get_dh_config(); $dh_config = $this->get_dh_config();
\danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE);
@ -575,9 +599,12 @@ trait AuthKeyHandler
$this->secret_chats[$chat]['rekeying'] = [1, $e]; $this->secret_chats[$chat]['rekeying'] = [1, $e];
$this->handle_pending_updates(); $this->handle_pending_updates();
$this->get_updates_difference(); $this->get_updates_difference();
return $e; return $e;
} }
public function accept_rekey($chat, $params) {
public function accept_rekey($chat, $params)
{
if ($this->secret_chats[$chat]['rekeying'][0] !== 0) { if ($this->secret_chats[$chat]['rekeying'][0] !== 0) {
$my = $this->temp_rekeyed_secret_chats[$this->secret_chats[$chat]['rekeying'][1]]; $my = $this->temp_rekeyed_secret_chats[$this->secret_chats[$chat]['rekeying'][1]];
if ($my['exchange_id'] > $params['exchange_id']) { if ($my['exchange_id'] > $params['exchange_id']) {
@ -586,6 +613,7 @@ trait AuthKeyHandler
if ($my['exchange_id'] === $params['exchange_id']) { if ($my['exchange_id'] === $params['exchange_id']) {
$this->secret_chats[$chat]['rekeying'] = [0]; $this->secret_chats[$chat]['rekeying'] = [0];
$this->rekey($chat); $this->rekey($chat);
return; return;
} }
} }
@ -606,10 +634,13 @@ trait AuthKeyHandler
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAcceptKey', 'g_b' => $g_b->toBytes(), 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]]); $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAcceptKey', 'g_b' => $g_b->toBytes(), 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]]);
$this->handle_pending_updates(); $this->handle_pending_updates();
$this->get_updates_difference(); $this->get_updates_difference();
} }
public function commit_rekey($chat, $params) {
if ($this->secret_chats[$chat]['rekeying'][0] !== 1) return; public function commit_rekey($chat, $params)
{
if ($this->secret_chats[$chat]['rekeying'][0] !== 1) {
return;
}
\danog\MadelineProto\Logger::log(['Committing rekeying of secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log(['Committing rekeying of secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE);
$dh_config = $this->get_dh_config(); $dh_config = $this->get_dh_config();
$params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256); $params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256);
@ -631,10 +662,13 @@ trait AuthKeyHandler
$this->handle_pending_updates(); $this->handle_pending_updates();
$this->get_updates_difference(); $this->get_updates_difference();
} }
public function complete_rekey($chat, $params) {
if ($this->secret_chats[$chat]['rekeying'][0] !== 2) return; public function complete_rekey($chat, $params)
{
if ($this->secret_chats[$chat]['rekeying'][0] !== 2) {
return;
}
if ($this->temp_rekeyed_secret_chats['fingerprint'] !== $params['key_fingerprint']) { if ($this->temp_rekeyed_secret_chats['fingerprint'] !== $params['key_fingerprint']) {
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]]); $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]]);
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!'); throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
@ -647,14 +681,24 @@ trait AuthKeyHandler
unset($this->temp_rekeyed_secret_chats[$params['exchange_id']]); unset($this->temp_rekeyed_secret_chats[$params['exchange_id']]);
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNoop']]]); $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNoop']]]);
} }
public function secret_chat_status($chat) {
if (isset($this->secret_chats[$chat])) return 2; public function secret_chat_status($chat)
if (isset($this->temp_requested_secret_chats[$chat])) return 1; {
if (isset($this->secret_chats[$chat])) {
return 2;
}
if (isset($this->temp_requested_secret_chats[$chat])) {
return 1;
}
return 0; return 0;
} }
public function get_secret_chat($chat) {
public function get_secret_chat($chat)
{
return $this->secret_chats[$chat]; return $this->secret_chats[$chat];
} }
public function bind_temp_auth_key($expires_in) public function bind_temp_auth_key($expires_in)
{ {
for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) { for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) {

View File

@ -158,7 +158,9 @@ trait CallHandler
throw new \danog\MadelineProto\Exception('An error occurred while calling method '.$method.' ('.$last_error.').'); throw new \danog\MadelineProto\Exception('An error occurred while calling method '.$method.' ('.$last_error.').');
} }
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 (!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.");
} }

View File

@ -13,7 +13,7 @@ If not, see <http://www.gnu.org/licenses/>.
namespace danog\MadelineProto\MTProtoTools; namespace danog\MadelineProto\MTProtoTools;
/** /**
* Manages upload and download of files * Manages upload and download of files.
*/ */
trait Files trait Files
{ {
@ -70,12 +70,15 @@ trait Files
$constructor['key'] = $key; $constructor['key'] = $key;
$constructor['key'] = $iv; $constructor['key'] = $iv;
} }
return $constructor; return $constructor;
} }
public function upload_encrypted($file, $file_name = '', $cb = null) public function upload_encrypted($file, $file_name = '', $cb = null)
{ {
return $this->upload($file, $file_name, $cb, true); return $this->upload($file, $file_name, $cb, true);
} }
public function get_download_info($message_media) public function get_download_info($message_media)
{ {
if (is_string($message_media)) { if (is_string($message_media)) {
@ -99,7 +102,9 @@ trait Files
} }
$res['name'] = $pathinfo['filename']; $res['name'] = $pathinfo['filename'];
} }
if (isset($message_media['decrypted_message']['media']['mime_type'])) $res['mime'] = $message_media['decrypted_message']['media']['mime_type']; if (isset($message_media['decrypted_message']['media']['mime_type'])) {
$res['mime'] = $message_media['decrypted_message']['media']['mime_type'];
}
if (isset($message_media['decrypted_message']['media']['attributes'])) { if (isset($message_media['decrypted_message']['media']['attributes'])) {
foreach ($message_media['decrypted_message']['media']['attributes'] as $attribute) { foreach ($message_media['decrypted_message']['media']['attributes'] as $attribute) {
switch ($attribute['_']) { switch ($attribute['_']) {
@ -128,6 +133,7 @@ trait Files
if (!isset($res['name'])) { if (!isset($res['name'])) {
$res['name'] = $message_media['file']['access_hash']; $res['name'] = $message_media['file']['access_hash'];
} }
return $res; return $res;
case 'messageMediaPhoto': case 'messageMediaPhoto':
$photo = end($message_media['photo']['sizes']); $photo = end($message_media['photo']['sizes']);
@ -246,7 +252,9 @@ trait Files
if (isset($info['key'])) { if (isset($info['key'])) {
$digest = hash('md5', $info['key'].$info['iv'], true); $digest = hash('md5', $info['key'].$info['iv'], true);
$fingerprint = \danog\PHP\Struct::unpack('<i', substr($digest, 0, 4) ^ substr($digest, 4, 4))[0]; $fingerprint = \danog\PHP\Struct::unpack('<i', substr($digest, 0, 4) ^ substr($digest, 4, 4))[0];
if ($fingerprint !== $info['key_fingerprint']) throw new \danog\MadelineProto\Exception('Fingerprint mismatch!'); if ($fingerprint !== $info['key_fingerprint']) {
throw new \danog\MadelineProto\Exception('Fingerprint mismatch!');
}
$ige = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_IGE); $ige = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_IGE);
$ige->setIV($info['iv']); $ige->setIV($info['iv']);
$ige->setKey($info['key']); $ige->setKey($info['key']);

View File

@ -129,9 +129,12 @@ trait MessageHandler
$this->datacenter->new_incoming[$message_id] = $message_id; $this->datacenter->new_incoming[$message_id] = $message_id;
$this->handle_messages(); $this->handle_messages();
} }
public function encrypt_secret_message($chat_id, $message) {
public function encrypt_secret_message($chat_id, $message)
{
if (!isset($this->secret_chats[$chat_id])) { if (!isset($this->secret_chats[$chat_id])) {
\danog\MadelineProto\Logger::log('I do not have the secret chat '.$chat_id.' in the database, skipping message...'); \danog\MadelineProto\Logger::log('I do not have the secret chat '.$chat_id.' in the database, skipping message...');
return false; return false;
} }
$message = $this->serialize_object(['type' => $message['_']], $message, $this->secret_chats[$chat_id]['layer']); $message = $this->serialize_object(['type' => $message['_']], $message, $this->secret_chats[$chat_id]['layer']);
@ -146,15 +149,21 @@ trait MessageHandler
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], 'to server'); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], 'to server');
$padding = $this->random($this->posmod(-strlen($message), 16)); $padding = $this->random($this->posmod(-strlen($message), 16));
$message = $this->secret_chats[$chat_id]['key']['fingerprint'].$message_key.$this->ige_encrypt($message.$padding, $aes_key, $aes_iv); $message = $this->secret_chats[$chat_id]['key']['fingerprint'].$message_key.$this->ige_encrypt($message.$padding, $aes_key, $aes_iv);
return $message; return $message;
} }
public function handle_encrypted_update($message) {
public function handle_encrypted_update($message)
{
if (!isset($this->secret_chats[$message['message']['chat_id']])) { if (!isset($this->secret_chats[$message['message']['chat_id']])) {
\danog\MadelineProto\Logger::log('I do not have the secret chat '.$message['message']['chat_id'].' in the database, skipping message...'); \danog\MadelineProto\Logger::log('I do not have the secret chat '.$message['message']['chat_id'].' in the database, skipping message...');
return false; return false;
} }
$auth_key_id = \danog\PHP\Struct::unpack('<q', substr($message['message']['bytes'], 0, 8))[0]; $auth_key_id = \danog\PHP\Struct::unpack('<q', substr($message['message']['bytes'], 0, 8))[0];
if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['key']['fingerprint']) throw new \danog\MadelineProto\SecurityException('Key fingerprint mismatch'); if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['key']['fingerprint']) {
throw new \danog\MadelineProto\SecurityException('Key fingerprint mismatch');
}
$message_key = substr($message['message']['bytes'], 8, 16); $message_key = substr($message['message']['bytes'], 8, 16);
$encrypted_data = substr($message['message']['bytes'], 24); $encrypted_data = substr($message['message']['bytes'], 24);
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$message['message']['chat_id']]['key']['auth_key'], 'to server'); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$message['message']['chat_id']]['key']['auth_key'], 'to server');

View File

@ -332,31 +332,42 @@ trait ResponseHandler
break; break;
} }
} }
public function handle_decrypted_update($update) {
if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) throw new \danog\MadelineProto\ResponseException('random_bytes is too short!'); public function handle_decrypted_update($update)
{
if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) {
throw new \danog\MadelineProto\ResponseException('random_bytes is too short!');
}
$this->secret_chats[$update['message']['chat_id']]['incoming'][] = $update['message']; $this->secret_chats[$update['message']['chat_id']]['incoming'][] = $update['message'];
switch ($update['message']['decrypted_message']['_']) { switch ($update['message']['decrypted_message']['_']) {
case 'decryptedMessageService': case 'decryptedMessageService':
switch ($update['message']['decrypted_message']['action']) { switch ($update['message']['decrypted_message']['action']) {
case 'decryptedMessageActionRequestKey': case 'decryptedMessageActionRequestKey':
$this->accept_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']); $this->accept_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']);
return; return;
case 'decryptedMessageActionAcceptKey': case 'decryptedMessageActionAcceptKey':
$this->commit_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']); $this->commit_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']);
return; return;
case 'decryptedMessageActionCommitKey': case 'decryptedMessageActionCommitKey':
$this->complete_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']); $this->complete_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']);
return; return;
case 'decryptedMessageActionNotifyLayer': case 'decryptedMessageActionNotifyLayer':
$this->secret_chats[$update['message']['chat_id']]['layer'] = $update['message']['decrypted_message']['action']['layer']; $this->secret_chats[$update['message']['chat_id']]['layer'] = $update['message']['decrypted_message']['action']['layer'];
if ($update['message']['decrypted_message']['action']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) $this->notify_layer($update['message']['chat_id']); if ($update['message']['decrypted_message']['action']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) {
$this->notify_layer($update['message']['chat_id']);
}
return; return;
case 'decryptedMessageActionSetMessageTTL': case 'decryptedMessageActionSetMessageTTL':
$this->secret_chats[$update['message']['chat_id']]['ttl'] = $update['message']['decrypted_message']['action']['ttl_seconds']; $this->secret_chats[$update['message']['chat_id']]['ttl'] = $update['message']['decrypted_message']['action']['ttl_seconds'];
return; return;
case 'decryptedMessageActionResend': case 'decryptedMessageActionResend':
@ -366,6 +377,7 @@ trait ResponseHandler
// $this->send_encrypted_message($update['message']['chat_id'], $update['message']['decrypted_message']); // $this->send_encrypted_message($update['message']['chat_id'], $update['message']['decrypted_message']);
} }
} }
return; return;
default: default:
// $this->save_update(['_' => 'updateNewDecryptedMessage', 'peer' => $this->secret_chats[$update['message']['chat_id']]['InputEncryptedChat'], 'in_seq_no' => $this->get_in_seq_no($update['message']['chat_id']), 'out_seq_no' => $this->get_out_seq_no($update['message']['chat_id']), 'message' => $update['message']['decrypted_message']]); // $this->save_update(['_' => 'updateNewDecryptedMessage', 'peer' => $this->secret_chats[$update['message']['chat_id']]['InputEncryptedChat'], 'in_seq_no' => $this->get_in_seq_no($update['message']['chat_id']), 'out_seq_no' => $this->get_out_seq_no($update['message']['chat_id']), 'message' => $update['message']['decrypted_message']]);

View File

@ -25,10 +25,14 @@ trait SeqNoHandler
return ($value * 2) + $in; return ($value * 2) + $in;
} }
public function get_in_seq_no($chat) {
public function get_in_seq_no($chat)
{
return count($this->secret_chats[$chat]['incoming']); return count($this->secret_chats[$chat]['incoming']);
} }
public function get_out_seq_no($chat) {
public function get_out_seq_no($chat)
{
return count($this->secret_chats[$chat]['outgoing']); return count($this->secret_chats[$chat]['outgoing']);
} }
} }

View File

@ -198,6 +198,7 @@ trait UpdateHandler
$this->should_serialize = true; $this->should_serialize = true;
$this->updates_state['qts'] = 0; $this->updates_state['qts'] = 0;
} }
return $this->updates_state; return $this->updates_state;
} }
@ -511,6 +512,7 @@ trait UpdateHandler
$cur_state['qts'] = $update['qts']; $cur_state['qts'] = $update['qts'];
$this->should_serialize = true; $this->should_serialize = true;
$this->handle_encrypted_update($update); $this->handle_encrypted_update($update);
return; return;
} }
/* /*
@ -521,16 +523,25 @@ 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 || (is_array($this->settings['secret_chats']['accept_chats']) && !in_array($update['chat']['admin_id'], $this->settings['secret_chats']['accept_chats']))) return; 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;
}
\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);
return $this->accept_secret_chat($update['chat']); return $this->accept_secret_chat($update['chat']);
case 'encryptedChatDiscarded': case 'encryptedChatDiscarded':
\danog\MadelineProto\Logger::log(['Revoking secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log(['Revoking secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE);
if (isset($this->secret_chats[$update['chat']['id']])) unset($this->secret_chats[$update['chat']['id']]); if (isset($this->secret_chats[$update['chat']['id']])) {
if (isset($this->temp_requested_secret_chats[$update['chat']['id']])) unset($this->temp_requested_secret_chats[$update['chat']['id']]); unset($this->secret_chats[$update['chat']['id']]);
}
if (isset($this->temp_requested_secret_chats[$update['chat']['id']])) {
unset($this->temp_requested_secret_chats[$update['chat']['id']]);
}
return; return;
case 'encryptedChat': case 'encryptedChat':
\danog\MadelineProto\Logger::log(['Completing creation of secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log(['Completing creation of secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE);
return $this->complete_secret_chat($update['chat']); return $this->complete_secret_chat($update['chat']);
} }
\danog\MadelineProto\Logger::log([$update], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log([$update], \danog\MadelineProto\Logger::NOTICE);

View File

@ -63,6 +63,7 @@ class Serialization
if ($unserialized === false) { if ($unserialized === false) {
throw new Exception('An error occurred on deserialization'); throw new Exception('An error occurred on deserialization');
} }
return $unserialized; return $unserialized;
} }
} }

View File

@ -15,6 +15,7 @@ namespace danog\MadelineProto\TL;
trait TL trait TL
{ {
public $encrypted_layer = -1; public $encrypted_layer = -1;
public function construct_tl($files) public function construct_tl($files)
{ {
\danog\MadelineProto\Logger::log(['Loading TL schemes...'], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log(['Loading TL schemes...'], \danog\MadelineProto\Logger::VERBOSE);
@ -40,7 +41,9 @@ trait TL
if (preg_match('|^//@|', $line)) { if (preg_match('|^//@|', $line)) {
$list = explode(' @', str_replace('//', ' ', $line)); $list = explode(' @', str_replace('//', ' ', $line));
foreach ($list as $elem) { foreach ($list as $elem) {
if ($elem === '') continue; if ($elem === '') {
continue;
}
$elem = explode(' ', $elem, 2); $elem = explode(' ', $elem, 2);
if ($elem[0] === 'class') { if ($elem[0] === 'class') {
$elem = explode(' ', $elem[1], 2); $elem = explode(' ', $elem[1], 2);
@ -51,10 +54,14 @@ trait TL
if (!is_null($class)) { if (!is_null($class)) {
$this->td_descriptions['types'][$class] = $elem[1]; $this->td_descriptions['types'][$class] = $elem[1];
$class = null; $class = null;
} else $e = $elem[1]; } else {
$e = $elem[1];
}
continue; continue;
} }
if ($elem[0] === 'param_description') $elem[0] = 'description'; if ($elem[0] === 'param_description') {
$elem[0] = 'description';
}
$dparams[$elem[0]] = $elem[1]; $dparams[$elem[0]] = $elem[1];
} }
continue; continue;
@ -78,9 +85,13 @@ trait TL
if (preg_match('/^vector#/', $line)) { if (preg_match('/^vector#/', $line)) {
continue; continue;
} }
if (preg_match('/ \?= /', $line)) continue; if (preg_match('/ \?= /', $line)) {
continue;
}
$name = preg_replace(['/#.*/', '/\s.*/'], '', $line); $name = preg_replace(['/#.*/', '/\s.*/'], '', $line);
if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) continue; if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
continue;
}
$clean = preg_replace([ $clean = preg_replace([
'/:bytes /', '/:bytes /',
'/;/', '/;/',
@ -93,7 +104,7 @@ trait TL
'/ $/', '/ $/',
'/\?bytes /', '/\?bytes /',
'/{/', '/{/',
'/}/' '/}/',
], [ ], [
':string ', ':string ',
'', '',
@ -106,10 +117,10 @@ trait TL
'', '',
'?string ', '?string ',
'', '',
''], $line); '', ], $line);
$id = hash('crc32b', $clean); $id = hash('crc32b', $clean);
if (preg_match('/^[^\s]+#/', $line)) { if (preg_match('/^[^\s]+#/', $line)) {
$nid = str_pad(preg_replace(['/^[^#]+#/', '/\s.+/'], '', $line), 8, "0", \STR_PAD_LEFT); $nid = str_pad(preg_replace(['/^[^#]+#/', '/\s.+/'], '', $line), 8, '0', \STR_PAD_LEFT);
if ($id !== $nid) { if ($id !== $nid) {
\danog\MadelineProto\Logger::log(['CRC32 mismatch ('.$id.', '.$nid.') for '.$line], \danog\MadelineProto\Logger::ERROR); \danog\MadelineProto\Logger::log(['CRC32 mismatch ('.$id.', '.$nid.') for '.$line], \danog\MadelineProto\Logger::ERROR);
} }
@ -123,7 +134,9 @@ trait TL
$TL_dict[$type][$key]['id'] = \danog\PHP\Struct::unpack('<i', \danog\PHP\Struct::pack('<I', hexdec($id)))[0]; $TL_dict[$type][$key]['id'] = \danog\PHP\Struct::unpack('<i', \danog\PHP\Struct::pack('<I', hexdec($id)))[0];
$TL_dict[$type][$key]['params'] = []; $TL_dict[$type][$key]['params'] = [];
$TL_dict[$type][$key]['type'] = preg_replace(['/.+\s/', '/;/'], '', $line); $TL_dict[$type][$key]['type'] = preg_replace(['/.+\s/', '/;/'], '', $line);
if ($layer !== null) $TL_dict[$type][$key]['layer'] = $layer; if ($layer !== null) {
$TL_dict[$type][$key]['layer'] = $layer;
}
foreach (explode(' ', preg_replace(['/^[^\s]+\s/', '/=\s[^\s]+/', '/\s$/'], '', $line)) as $param) { foreach (explode(' ', preg_replace(['/^[^\s]+\s/', '/=\s[^\s]+/', '/\s$/'], '', $line)) as $param) {
if ($param === '') { if ($param === '') {
continue; continue;
@ -143,17 +156,23 @@ trait TL
$orig = $this->encrypted_layer; $orig = $this->encrypted_layer;
\danog\MadelineProto\Logger::log(['Translating objects...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); \danog\MadelineProto\Logger::log(['Translating objects...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
foreach ($TL_dict['constructors'] as $elem) { foreach ($TL_dict['constructors'] as $elem) {
if ($scheme_type === 'secret') $this->encrypted_layer = max($this->encrypted_layer, $elem['layer']); if ($scheme_type === 'secret') {
$this->encrypted_layer = max($this->encrypted_layer, $elem['layer']);
}
$this->{($scheme_type === 'td' ? 'td_' : '').'constructors'}->add($elem, $scheme_type); $this->{($scheme_type === 'td' ? 'td_' : '').'constructors'}->add($elem, $scheme_type);
} }
\danog\MadelineProto\Logger::log(['Translating methods...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); \danog\MadelineProto\Logger::log(['Translating methods...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
foreach ($TL_dict['methods'] as $elem) { foreach ($TL_dict['methods'] as $elem) {
$this->{($scheme_type === 'td' ? 'td_' : '').'methods'}->add($elem); $this->{($scheme_type === 'td' ? 'td_' : '').'methods'}->add($elem);
if ($scheme_type === 'secret') $this->encrypted_layer = max($this->encrypted_layer, $elem['layer']); if ($scheme_type === 'secret') {
$this->encrypted_layer = max($this->encrypted_layer, $elem['layer']);
}
} }
if ($this->encrypted_layer != $orig && isset($this->secret_chats)) { if ($this->encrypted_layer != $orig && isset($this->secret_chats)) {
foreach ($this->secret_chats as $chat => $data) { $this->notify_layer($chat); } foreach ($this->secret_chats as $chat => $data) {
$this->notify_layer($chat);
}
} }
} }
if (isset($files['td']) && isset($files['telegram'])) { if (isset($files['td']) && isset($files['telegram'])) {
@ -185,7 +204,6 @@ trait TL
return array_unique(array_values($this->methods->method_namespace)); return array_unique(array_values($this->methods->method_namespace));
} }
public function serialize_bool($bool) public function serialize_bool($bool)
{ {
return \danog\PHP\Struct::pack('<i', $this->constructors->find_by_predicate('bool'.($bool ? 'True' : 'False'))['id']); return \danog\PHP\Struct::pack('<i', $this->constructors->find_by_predicate('bool'.($bool ? 'True' : 'False'))['id']);
@ -224,13 +242,19 @@ trait TL
return \danog\PHP\Struct::pack('<q', $object); return \danog\PHP\Struct::pack('<q', $object);
case 'int128': case 'int128':
if (strlen($object) !== 16) throw new Exception('Given value is not 16 bytes long'); if (strlen($object) !== 16) {
throw new Exception('Given value is not 16 bytes long');
}
return (string) $object; return (string) $object;
case 'int256': case 'int256':
if (strlen($object) !== 32) throw new Exception('Given value is not 32 bytes long'); if (strlen($object) !== 32) {
throw new Exception('Given value is not 32 bytes long');
}
return (string) $object; return (string) $object;
case 'int512': case 'int512':
if (strlen($object) !== 64) throw new Exception('Given value is not 64 bytes long'); if (strlen($object) !== 64) {
throw new Exception('Given value is not 64 bytes long');
}
return (string) $object; return (string) $object;
case 'double': case 'double':
return \danog\PHP\Struct::pack('<d', $object); return \danog\PHP\Struct::pack('<d', $object);
@ -297,10 +321,13 @@ trait TL
} }
$concat = ''; $concat = '';
if ($constructorData['predicate'] === 'messageEntityMentionName') $constructorData = $this->constructors->find_by_predicate('inputMessageEntityMentionName'); if ($constructorData['predicate'] === 'messageEntityMentionName') {
$constructorData = $this->constructors->find_by_predicate('inputMessageEntityMentionName');
}
if (!$bare) { if (!$bare) {
$concat .= \danog\PHP\Struct::pack('<i', $constructorData['id']); $concat .= \danog\PHP\Struct::pack('<i', $constructorData['id']);
} }
return $concat.$this->serialize_params($constructorData, $object); return $concat.$this->serialize_params($constructorData, $object);
} }
@ -310,10 +337,10 @@ trait TL
if ($tl === false) { if ($tl === false) {
throw new Exception('Could not find method: '.$method); throw new Exception('Could not find method: '.$method);
} }
return \danog\PHP\Struct::pack('<i', $tl['id']).$this->serialize_params($tl, $arguments); return \danog\PHP\Struct::pack('<i', $tl['id']).$this->serialize_params($tl, $arguments);
} }
public function serialize_params($tl, $arguments) public function serialize_params($tl, $arguments)
{ {
$serialized = ''; $serialized = '';

View File

@ -27,7 +27,9 @@ class TLConstructor extends TLParams
$this->predicate[$this->key] = (string) ((($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message') ? 'MT' : '').$json_dict['predicate']); $this->predicate[$this->key] = (string) ((($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message') ? 'MT' : '').$json_dict['predicate']);
$this->type[$this->key] = (($scheme_type === 'mtproto' && $json_dict['type'] === 'Message') ? 'MT' : '').$json_dict['type']; $this->type[$this->key] = (($scheme_type === 'mtproto' && $json_dict['type'] === 'Message') ? 'MT' : '').$json_dict['type'];
$this->params[$this->key] = $json_dict['params']; $this->params[$this->key] = $json_dict['params'];
if ($scheme_type === 'secret') $this->layer[$this->key] = $json_dict['layer']; if ($scheme_type === 'secret') {
$this->layer[$this->key] = $json_dict['layer'];
}
$this->parse_params($this->key, $scheme_type === 'mtproto'); $this->parse_params($this->key, $scheme_type === 'mtproto');
$this->key++; $this->key++;
} }
@ -50,10 +52,16 @@ class TLConstructor extends TLParams
$key = 0; $key = 0;
$keys = array_keys($this->predicate, $predicate); $keys = array_keys($this->predicate, $predicate);
foreach ($keys as $k) { foreach ($keys as $k) {
if ($this->layer[$k] === $layer) $key = $k; if ($this->layer[$k] === $layer) {
$key = $k;
}
}
if ($key === 0) {
$key = array_search($predicate, $this->predicate);
}
} else {
$key = array_search($predicate, $this->predicate);
} }
if ($key === 0) $key = array_search($predicate, $this->predicate);
} else $key = array_search($predicate, $this->predicate);
return ($key === false) ? false : [ return ($key === false) ? false : [
'id' => $this->id[$key], 'id' => $this->id[$key],

View File

@ -47,9 +47,11 @@ class TLMethod extends TLParams
'params' => $this->params[$key], 'params' => $this->params[$key],
]; ];
} }
public function find_by_id($id) public function find_by_id($id)
{ {
$key = array_search($id, $this->id); $key = array_search($id, $this->id);
return ($key === false) ? false : [ return ($key === false) ? false : [
'id' => $this->id[$key], 'id' => $this->id[$key],
'method' => $this->method[$key], 'method' => $this->method[$key],

View File

@ -32,7 +32,6 @@ echo 'Loading settings...'.PHP_EOL;
$settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: []; $settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: [];
if ($MadelineProto === false) { if ($MadelineProto === false) {
echo 'Loading MadelineProto...'.PHP_EOL; echo 'Loading MadelineProto...'.PHP_EOL;
$MadelineProto = new \danog\MadelineProto\API($settings); $MadelineProto = new \danog\MadelineProto\API($settings);
if (getenv('TRAVIS_COMMIT') == '') { if (getenv('TRAVIS_COMMIT') == '') {
@ -88,7 +87,6 @@ $media['document_photo'] = ['_' => 'inputMediaUploadedDocument', 'file' => $inpu
//$inputFile = $MadelineProto->upload_encrypted('tests/faust.jpg', 'fausticorn.jpg'); // This gets an inputFile object with file name magic //$inputFile = $MadelineProto->upload_encrypted('tests/faust.jpg', 'fausticorn.jpg'); // This gets an inputFile object with file name magic
//$secret_media['document_photo'] = ['peer' => $secret, 'file' => $inputFile, 'message' => ['ttl' => PHP_INT_MAX, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'mime_type' => mime_content_type('tests/faust.jpg'), 'caption' => 'This file was uploaded using MadelineProto', 'attributes' => [['_' => 'documentAttributeImageSize', 'w' => 1280, 'h' => 914]]]]]; //$secret_media['document_photo'] = ['peer' => $secret, 'file' => $inputFile, 'message' => ['ttl' => PHP_INT_MAX, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'mime_type' => mime_content_type('tests/faust.jpg'), 'caption' => 'This file was uploaded using MadelineProto', 'attributes' => [['_' => 'documentAttributeImageSize', 'w' => 1280, 'h' => 914]]]]];
// Photo // Photo
$media['photo'] = ['_' => 'inputMediaUploadedPhoto', 'file' => $inputFile, 'mime_type' => mime_content_type('tests/faust.jpg'), 'caption' => 'This photo was uploaded using MadelineProto']; $media['photo'] = ['_' => 'inputMediaUploadedPhoto', 'file' => $inputFile, 'mime_type' => mime_content_type('tests/faust.jpg'), 'caption' => 'This photo was uploaded using MadelineProto'];