Apply fixes from StyleCI
This commit is contained in:
parent
dfd8bf93da
commit
f53927d3a7
@ -101,9 +101,11 @@ while (true) {
|
||||
} else {
|
||||
array_walk($rows, function (&$value, $key) {
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ $docs = [
|
||||
'readme' => false,
|
||||
],
|
||||
[
|
||||
'tl_schema' => ['telegram' => __DIR__.'/src/danog/MadelineProto/TL_telegram_v62.tl', 'secret' => __DIR__.'/src/danog/MadelineProto/TL_secret.tl','td' => __DIR__.'/src/danog/MadelineProto/TL_td.tl'],
|
||||
'tl_schema' => ['telegram' => __DIR__.'/src/danog/MadelineProto/TL_telegram_v62.tl', 'secret' => __DIR__.'/src/danog/MadelineProto/TL_secret.tl', 'td' => __DIR__.'/src/danog/MadelineProto/TL_td.tl'],
|
||||
'title' => 'MadelineProto API documentation (layer 62)',
|
||||
'description' => 'MadelineProto API documentation (layer 62)',
|
||||
'output_dir' => __DIR__.'/docs/API_docs',
|
||||
|
@ -97,6 +97,7 @@ trait BotAPI
|
||||
foreach ($data as $key => $element) {
|
||||
$newd[$key] = $this->MTProto_to_botAPI($element, $sent_arguments);
|
||||
}
|
||||
|
||||
return $newd;
|
||||
}
|
||||
switch ($data['_']) {
|
||||
@ -450,5 +451,4 @@ trait BotAPI
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ trait BotAPIFiles
|
||||
$new .= $cur;
|
||||
}
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
@ -146,7 +147,6 @@ trait BotAPIFiles
|
||||
|
||||
return $res;
|
||||
|
||||
|
||||
case 9:
|
||||
$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);
|
||||
|
@ -16,48 +16,56 @@ trait TD
|
||||
{
|
||||
private $td_params_conversion = [
|
||||
'updateNewMessage' => [
|
||||
'_' => 'updateNewMessage',
|
||||
'_' => 'updateNewMessage',
|
||||
'disable_notification' => ['message', 'silent'],
|
||||
'message' => ['message'],
|
||||
'message' => ['message'],
|
||||
],
|
||||
'message' => [
|
||||
'_' => 'message',
|
||||
'id' => ['id'],
|
||||
'sender_user_id' => ['from_id'],
|
||||
'chat_id' => ['to_id', 'choose_chat_id_from_botapi'],
|
||||
'send_state' => ['choose_incoming_or_sent'],
|
||||
'can_be_edited' => ['choose_can_edit'],
|
||||
'can_be_deleted' => ['choose_can_delete'],
|
||||
'is_post' => ['post'],
|
||||
'date' => ['date'],
|
||||
'edit_date' => ['edit_date'],
|
||||
'forward_info' => ['fwd_info', 'choose_forward_info'],
|
||||
'_' => 'message',
|
||||
'id' => ['id'],
|
||||
'sender_user_id' => ['from_id'],
|
||||
'chat_id' => ['to_id', 'choose_chat_id_from_botapi'],
|
||||
'send_state' => ['choose_incoming_or_sent'],
|
||||
'can_be_edited' => ['choose_can_edit'],
|
||||
'can_be_deleted' => ['choose_can_delete'],
|
||||
'is_post' => ['post'],
|
||||
'date' => ['date'],
|
||||
'edit_date' => ['edit_date'],
|
||||
'forward_info' => ['fwd_info', 'choose_forward_info'],
|
||||
'reply_to_message_id' => ['reply_to_msg_id'],
|
||||
'ttl' => ['choose_ttl'],
|
||||
'ttl_expires_in' => ['choose_ttl_expires_in'],
|
||||
'via_bot_user_id' => ['via_bot_id'],
|
||||
'views' => ['views'],
|
||||
'content' => ['choose_message_content'],
|
||||
'reply_markup' => ['reply_markup']
|
||||
'ttl' => ['choose_ttl'],
|
||||
'ttl_expires_in' => ['choose_ttl_expires_in'],
|
||||
'via_bot_user_id' => ['via_bot_id'],
|
||||
'views' => ['views'],
|
||||
'content' => ['choose_message_content'],
|
||||
'reply_markup' => ['reply_markup'],
|
||||
],
|
||||
|
||||
'messages.sendMessage' => [
|
||||
'chat_id' => ['peer'],
|
||||
'reply_to_message_id' => ['reply_to_msg_id'],
|
||||
'disable_notification' => ['silent'],
|
||||
'from_background' => ['background'],
|
||||
'chat_id' => ['peer'],
|
||||
'reply_to_message_id' => ['reply_to_msg_id'],
|
||||
'disable_notification' => ['silent'],
|
||||
'from_background' => ['background'],
|
||||
'input_message_content' => ['choose_message_content'],
|
||||
'reply_markup' => ['reply_markup']
|
||||
]
|
||||
'reply_markup' => ['reply_markup'],
|
||||
],
|
||||
|
||||
];
|
||||
private $reverse = [
|
||||
'sendMessage'=> 'messages.sendMessage',
|
||||
];
|
||||
private $ignore = ['updateMessageID'];
|
||||
public function tdcli_to_td(&$params, $key=null) {
|
||||
if (!is_array($params)) return $params;
|
||||
if (!isset($params['ID'])) { array_walk($params, [$this, 'tdcli_to_td']); return $params; }
|
||||
|
||||
public function tdcli_to_td(&$params, $key = null)
|
||||
{
|
||||
if (!is_array($params)) {
|
||||
return $params;
|
||||
}
|
||||
if (!isset($params['ID'])) {
|
||||
array_walk($params, [$this, 'tdcli_to_td']);
|
||||
|
||||
return $params;
|
||||
}
|
||||
foreach ($params as $key => $value) {
|
||||
$value = $this->tdcli_to_td($value);
|
||||
if (preg_match('/_$/', $key)) {
|
||||
@ -67,9 +75,12 @@ trait TD
|
||||
}
|
||||
$params['_'] = lcfirst($params['ID']);
|
||||
unset($params['ID']);
|
||||
|
||||
return $params;
|
||||
}
|
||||
public function td_to_mtproto($params) {
|
||||
|
||||
public function td_to_mtproto($params)
|
||||
{
|
||||
$newparams = ['_' => $this->reverse[$params['_']]];
|
||||
|
||||
foreach ($this->td_params_conversion[$newparams['_']] as $td => $mtproto) {
|
||||
@ -79,28 +90,45 @@ trait TD
|
||||
switch ($params[$td]['_']) {
|
||||
case 'inputMessageText':
|
||||
$params[$td]['_'] = 'messages.sendMessage';
|
||||
if (isset($params['disable_web_page_preview'])) $newparams['no_webpage'] = $params[$td]['disable_web_page_preview'];
|
||||
$newparams = array_merge($params[$td],$newparams);
|
||||
if (isset($params['disable_web_page_preview'])) {
|
||||
$newparams['no_webpage'] = $params[$td]['disable_web_page_preview'];
|
||||
}
|
||||
$newparams = array_merge($params[$td], $newparams);
|
||||
break;
|
||||
default: throw new Exception("Can't convert non text messages yet!");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$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;
|
||||
}
|
||||
public function mtproto_to_tdcli($params) {
|
||||
}
|
||||
|
||||
public function mtproto_to_tdcli($params)
|
||||
{
|
||||
return $this->td_to_tdcli($this->mtproto_to_td($params));
|
||||
}
|
||||
public function mtproto_to_td(&$params) {
|
||||
if (!is_array($params)) return $params;
|
||||
if (!isset($params['_'])) { array_walk($params, [$this, 'mtproto_to_td']); return $params; }
|
||||
|
||||
public function mtproto_to_td(&$params)
|
||||
{
|
||||
if (!is_array($params)) {
|
||||
return $params;
|
||||
}
|
||||
if (!isset($params['_'])) {
|
||||
array_walk($params, [$this, 'mtproto_to_td']);
|
||||
|
||||
return $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) {
|
||||
if (is_string($mtproto)) {
|
||||
$newparams[$td] = $mtproto;
|
||||
@ -121,11 +149,19 @@ trait TD
|
||||
case 'choose_forward_info':
|
||||
if (isset($params['fwd_from'])) {
|
||||
$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'];
|
||||
if (isset($params['fwd_from']['channel_post'])) $newparams[$td]['channel_post'] = $params['fwd_from']['channel_post'];
|
||||
if (isset($params['fwd_from']['from_id'])) $newparams[$td]['sender_user_id'] = $params['fwd_from']['from_id'];
|
||||
} else $newparams[$td] = null;
|
||||
if (isset($params['fwd_from']['channel_post'])) {
|
||||
$newparams[$td]['channel_post'] = $params['fwd_from']['channel_post'];
|
||||
}
|
||||
if (isset($params['fwd_from']['from_id'])) {
|
||||
$newparams[$td]['sender_user_id'] = $params['fwd_from']['from_id'];
|
||||
}
|
||||
} else {
|
||||
$newparams[$td] = null;
|
||||
}
|
||||
break;
|
||||
case 'choose_ttl':
|
||||
$newparams[$td] = isset($params['ttl']) ? $params['ttl'] : 0;
|
||||
@ -136,9 +172,15 @@ trait TD
|
||||
case 'choose_message_content':
|
||||
if ($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['entities'])) $newparams[$td]['entities'] = $params['entities'];
|
||||
} else throw new Exception("Can't convert non text messages yet!");
|
||||
if (isset($params['media']['_']) && $params['media']['_'] === 'messageMediaWebPage') {
|
||||
$newparams[$td]['web_page'] = $this->mtproto_to_td($params['media']['webpage']);
|
||||
}
|
||||
if (isset($params['entities'])) {
|
||||
$newparams[$td]['entities'] = $params['entities'];
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Can't convert non text messages yet!");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isset($mtproto[1])) {
|
||||
@ -146,24 +188,33 @@ trait TD
|
||||
} else {
|
||||
$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;
|
||||
}
|
||||
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 = [];
|
||||
foreach ($params as $key => $value) {
|
||||
if ($key === '_') {
|
||||
$newparams['ID'] = ucfirst($value);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
return $newparams;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,12 @@ class DocsBuilder
|
||||
{
|
||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||
$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'])) $this->methods = $this->td_methods;
|
||||
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'])) {
|
||||
$this->methods = $this->td_methods;
|
||||
}
|
||||
$this->settings = $settings;
|
||||
if (!file_exists($this->settings['output_dir'])) {
|
||||
mkdir($this->settings['output_dir']);
|
||||
@ -149,13 +153,13 @@ description: '.$this->settings['description'].'
|
||||
}
|
||||
$table .= '|'.str_replace('_', '\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\_', $ptype).'](../types/'.$ptype.'.md) | '.($param['flag'] ? 'Optional' : 'Yes').'|';
|
||||
if (isset($this->td_descriptions['methods'][$rmethod])) {
|
||||
$table .= $this->td_descriptions['methods'][$rmethod]['params'][$param['name']].'|';
|
||||
$table .= $this->td_descriptions['methods'][$rmethod]['params'][$param['name']].'|';
|
||||
}
|
||||
$table .= PHP_EOL;
|
||||
|
||||
$params .= "'".$param['name']."' => ";
|
||||
$params .= (isset($param['subtype']) ? '['.$ptype.']' : $ptype).', ';
|
||||
$lua_params .= $param['name']."=";
|
||||
$lua_params .= $param['name'].'=';
|
||||
$lua_params .= (isset($param['subtype']) ? '{'.$ptype.'}' : $ptype).', ';
|
||||
if ($param['name'] === 'entities') {
|
||||
$hasentities = true;
|
||||
@ -383,13 +387,13 @@ description: List of methods
|
||||
}
|
||||
$table .= '|'.str_replace('_', '\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\_', $ptype).'](../'.$link_type.'/'.$ptype.'.md) | '.($param['flag'] ? 'Optional' : 'Yes').'|';
|
||||
if (isset($this->td_descriptions['constructors'][$rconstructor]['params'][$param['name']])) {
|
||||
$table .= $this->td_descriptions['constructors'][$rconstructor]['params'][$param['name']].'|';
|
||||
$table .= $this->td_descriptions['constructors'][$rconstructor]['params'][$param['name']].'|';
|
||||
}
|
||||
$table .= PHP_EOL;
|
||||
|
||||
$params .= "'".$param['name']."' => ";
|
||||
$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']).', ';
|
||||
}
|
||||
$params = "['_' => '".$rconstructor."', ".$params.']';
|
||||
@ -531,11 +535,11 @@ $".$type." = 'channel#38575794'; // tg-cli style id (channels)
|
||||
$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):
|
||||
|
||||
|
@ -18,8 +18,11 @@ class Lua
|
||||
private $Lua;
|
||||
private $script;
|
||||
|
||||
public function __construct($script, $MadelineProto) {
|
||||
if (!file_exists($script)) throw new Exception('Provided script does not exist');
|
||||
public function __construct($script, $MadelineProto)
|
||||
{
|
||||
if (!file_exists($script)) {
|
||||
throw new Exception('Provided script does not exist');
|
||||
}
|
||||
$this->MadelineProto = $MadelineProto;
|
||||
$settings = $this->MadelineProto->get_settings();
|
||||
$settings['updates']['handle_updates'] = true;
|
||||
@ -27,8 +30,14 @@ class Lua
|
||||
$this->script = $script;
|
||||
$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->madelineproto_lua = 1;
|
||||
$this->Lua->registerCallback('tdcli_function', [$this, 'tdcli_function']);
|
||||
@ -45,37 +54,73 @@ class Lua
|
||||
$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));
|
||||
if ($params === 0) return 0;
|
||||
if ($params === 0) {
|
||||
return 0;
|
||||
}
|
||||
$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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (is_callable($cb)) $cb($result, $cb_extra);
|
||||
if (is_callable($cb)) {
|
||||
$cb($result, $cb_extra);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
private function convert_array($array) {
|
||||
if (!is_array($value)) return $array;
|
||||
if ($this->is_seqential($value)) return array_flip(array_map(function($el){ return $el + 1; }, array_flip($array)));
|
||||
private function convert_array($array)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
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 (array() === $arr) return false;
|
||||
private function is_sequential(array $arr)
|
||||
{
|
||||
if ([] === $arr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ class MTProto
|
||||
$this->twoe2047 = new \phpseclib\Math\BigInteger('16158503035655503650357438344334975980222051334857742016065172713762327569433945446598600705761456731844358980460949009747059779575245460547544076193224141560315438683650498045875098875194826053398028819192033784138396109321309878080919047169238085235290822926018152521443787945770532904303776199561965192760957166694834171210342487393282284747428088017663161029038902829665513096354230157075129296432088558362971801859230928678799175576150822952201848806616643615613562842355410104862578550863465661734839271290328348967522998634176499319107762583194718667771801067716614802322659239302476074096777926805529798115328');
|
||||
$this->twoe2048 = new \phpseclib\Math\BigInteger('32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656');
|
||||
|
||||
|
||||
$this->switch_dc(2, true);
|
||||
$this->get_config();
|
||||
}
|
||||
@ -200,8 +199,8 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
'src' => [
|
||||
'mtproto' => __DIR__.'/TL_mtproto_v1.json', // mtproto TL scheme
|
||||
'telegram' => __DIR__.'/TL_telegram_v62.tl', // telegram TL scheme
|
||||
'secret' => __DIR__.'/TL_secret.tl', // secret chats TL scheme
|
||||
'td' => __DIR__.'/TL_td.tl', // telegram-cli TL scheme
|
||||
'secret' => __DIR__.'/TL_secret.tl', // secret chats TL scheme
|
||||
'td' => __DIR__.'/TL_td.tl', // telegram-cli TL scheme
|
||||
],
|
||||
],
|
||||
'logger' => [ // Logger settings
|
||||
@ -387,7 +386,9 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
public function get_self() {
|
||||
|
||||
public function get_self()
|
||||
{
|
||||
return $this->datacenter->authorization['user'];
|
||||
}
|
||||
}
|
||||
|
@ -414,7 +414,9 @@ trait AuthKeyHandler
|
||||
|
||||
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;
|
||||
}
|
||||
public function check_p_g($p, $g) {
|
||||
|
||||
public function check_p_g($p, $g)
|
||||
{
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of dh_prime
|
||||
@ -468,11 +472,11 @@ trait AuthKeyHandler
|
||||
* 2^2047 < p < 2^2048
|
||||
*/
|
||||
\danog\MadelineProto\Logger::log(['Executing p/g checks (2/2)...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($p->compare($this->twoe2047) <= 0 // 2^2047 < p or p > 2^2047 or ! p <= 2^2047
|
||||
if ($p->compare($this->twoe2047) <= 0 // 2^2047 < p or p > 2^2047 or ! p <= 2^2047
|
||||
|| $p->compare($this->twoe2048) >= 0 // p < 2^2048 or ! p >= 2^2048
|
||||
) {
|
||||
throw new \danog\MadelineProto\SecurityException("g isn't a safe 2048-bit prime (2^2047 < p < 2^2048 is false).");
|
||||
}
|
||||
throw new \danog\MadelineProto\SecurityException("g isn't a safe 2048-bit prime (2^2047 < p < 2^2048 is false).");
|
||||
}
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
@ -481,29 +485,37 @@ trait AuthKeyHandler
|
||||
*/
|
||||
\danog\MadelineProto\Logger::log(['Executing g check...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
|
||||
if ($g->compare($this->one) <= 0 // 1 < g or g > 1 or ! g <= 1
|
||||
if ($g->compare($this->one) <= 0 // 1 < g or g > 1 or ! g <= 1
|
||||
|| $g->compare($p->subtract($this->one)) >= 0 // g < p - 1 or ! g >= p - 1
|
||||
) {
|
||||
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;
|
||||
}
|
||||
public function get_dh_config() {
|
||||
|
||||
public function get_dh_config()
|
||||
{
|
||||
$this->getting_state = true;
|
||||
$dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0]);
|
||||
$this->getting_state = false;
|
||||
if ($dh_config['_'] === 'messages.dhConfigNotModified') {
|
||||
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Logger::VERBOSE, ['DH configuration not modified']);
|
||||
|
||||
return $this->dh_config;
|
||||
}
|
||||
$dh_config['p'] = new \phpseclib\Math\BigInteger($dh_config['p'], 256);
|
||||
$dh_config['g'] = new \phpseclib\Math\BigInteger($dh_config['g']);
|
||||
$this->check_p_g($dh_config['p'], $dh_config['g']);
|
||||
|
||||
return $this->dh_config = $dh_config;
|
||||
}
|
||||
|
||||
private $temp_requested_secret_chats = [];
|
||||
private $secret_chats = [];
|
||||
public function accept_secret_chat($params) {
|
||||
|
||||
public function accept_secret_chat($params)
|
||||
{
|
||||
$dh_config = $this->get_dh_config();
|
||||
\danog\MadelineProto\Logger::log(['Generating b...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = new \phpseclib\Math\BigInteger($this->random(256), 256);
|
||||
@ -518,9 +530,10 @@ trait AuthKeyHandler
|
||||
$this->check_G($g_b, $dh_config['p']);
|
||||
$this->notify_layer($params['id']);
|
||||
$this->handle_pending_updates();
|
||||
|
||||
}
|
||||
public function request_secret_chat($user) {
|
||||
|
||||
public function request_secret_chat($user)
|
||||
{
|
||||
$user = $this->get_info($user)['InputUser'];
|
||||
\danog\MadelineProto\Logger::log(['Creating secret chat with '.$user['user_id'].'...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
$dh_config = $this->get_dh_config();
|
||||
@ -533,11 +546,15 @@ trait AuthKeyHandler
|
||||
$this->temp_requested_secret_chats[$res['id']] = $a;
|
||||
$this->handle_pending_updates();
|
||||
$this->get_updates_difference();
|
||||
|
||||
return $res['id'];
|
||||
}
|
||||
public function complete_secret_chat($params) {
|
||||
|
||||
public function complete_secret_chat($params)
|
||||
{
|
||||
if ($this->secret_chat_status($params['id']) !== 1) {
|
||||
\danog\MadelineProto\Logger::log(['Could not find and complete secret chat '.$params['id']]);
|
||||
|
||||
return false;
|
||||
}
|
||||
$dh_config = $this->get_dh_config();
|
||||
@ -556,12 +573,19 @@ trait AuthKeyHandler
|
||||
$this->notify_layer($params['id']);
|
||||
$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]]]);
|
||||
}
|
||||
|
||||
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);
|
||||
$dh_config = $this->get_dh_config();
|
||||
\danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
@ -575,9 +599,12 @@ trait AuthKeyHandler
|
||||
$this->secret_chats[$chat]['rekeying'] = [1, $e];
|
||||
$this->handle_pending_updates();
|
||||
$this->get_updates_difference();
|
||||
|
||||
return $e;
|
||||
}
|
||||
public function accept_rekey($chat, $params) {
|
||||
|
||||
public function accept_rekey($chat, $params)
|
||||
{
|
||||
if ($this->secret_chats[$chat]['rekeying'][0] !== 0) {
|
||||
$my = $this->temp_rekeyed_secret_chats[$this->secret_chats[$chat]['rekeying'][1]];
|
||||
if ($my['exchange_id'] > $params['exchange_id']) {
|
||||
@ -586,6 +613,7 @@ trait AuthKeyHandler
|
||||
if ($my['exchange_id'] === $params['exchange_id']) {
|
||||
$this->secret_chats[$chat]['rekeying'] = [0];
|
||||
$this->rekey($chat);
|
||||
|
||||
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->handle_pending_updates();
|
||||
$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);
|
||||
$dh_config = $this->get_dh_config();
|
||||
$params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256);
|
||||
@ -631,10 +662,13 @@ trait AuthKeyHandler
|
||||
|
||||
$this->handle_pending_updates();
|
||||
$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']) {
|
||||
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]]);
|
||||
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
||||
@ -647,14 +681,24 @@ trait AuthKeyHandler
|
||||
unset($this->temp_rekeyed_secret_chats[$params['exchange_id']]);
|
||||
$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;
|
||||
if (isset($this->temp_requested_secret_chats[$chat])) return 1;
|
||||
|
||||
public function secret_chat_status($chat)
|
||||
{
|
||||
if (isset($this->secret_chats[$chat])) {
|
||||
return 2;
|
||||
}
|
||||
if (isset($this->temp_requested_secret_chats[$chat])) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
public function get_secret_chat($chat) {
|
||||
|
||||
public function get_secret_chat($chat)
|
||||
{
|
||||
return $this->secret_chats[$chat];
|
||||
}
|
||||
|
||||
public function bind_temp_auth_key($expires_in)
|
||||
{
|
||||
for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) {
|
||||
|
@ -158,7 +158,9 @@ trait CallHandler
|
||||
|
||||
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)) {
|
||||
throw new \danog\MadelineProto\Exception("Arguments aren't an array.");
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ If not, see <http://www.gnu.org/licenses/>.
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
/**
|
||||
* Manages upload and download of files
|
||||
* Manages upload and download of files.
|
||||
*/
|
||||
trait Files
|
||||
{
|
||||
@ -46,7 +46,7 @@ trait Files
|
||||
$key = $this->random(32);
|
||||
$iv = $this->random(32);
|
||||
$digest = hash('md5', $key.$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];
|
||||
$ige = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_IGE);
|
||||
$ige->setIV($iv);
|
||||
$ige->setKey($key);
|
||||
@ -70,12 +70,15 @@ trait Files
|
||||
$constructor['key'] = $key;
|
||||
$constructor['key'] = $iv;
|
||||
}
|
||||
|
||||
return $constructor;
|
||||
}
|
||||
|
||||
public function upload_encrypted($file, $file_name = '', $cb = null)
|
||||
{
|
||||
return $this->upload($file, $file_name, $cb, true);
|
||||
}
|
||||
|
||||
public function get_download_info($message_media)
|
||||
{
|
||||
if (is_string($message_media)) {
|
||||
@ -93,16 +96,18 @@ trait Files
|
||||
$res['key'] = $message_media['decrypted_message']['media']['key'];
|
||||
$res['iv'] = $message_media['decrypted_message']['media']['iv'];
|
||||
if (isset($message_media['decrypted_message']['media']['file_name'])) {
|
||||
$pathinfo = pathinfo($message_media['decrypted_message']['media']['file_name']);
|
||||
if (isset($pathinfo['extension'])) {
|
||||
$res['ext'] = '.'.$pathinfo['extension'];
|
||||
}
|
||||
$res['name'] = $pathinfo['filename'];
|
||||
$pathinfo = pathinfo($message_media['decrypted_message']['media']['file_name']);
|
||||
if (isset($pathinfo['extension'])) {
|
||||
$res['ext'] = '.'.$pathinfo['extension'];
|
||||
}
|
||||
$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'])) {
|
||||
foreach ($message_media['decrypted_message']['media']['attributes'] as $attribute) {
|
||||
switch ($attribute['_']) {
|
||||
foreach ($message_media['decrypted_message']['media']['attributes'] as $attribute) {
|
||||
switch ($attribute['_']) {
|
||||
case 'documentAttributeFilename':
|
||||
$pathinfo = pathinfo($attribute['file_name']);
|
||||
if (isset($pathinfo['extension'])) {
|
||||
@ -114,7 +119,7 @@ trait Files
|
||||
$audio = $attribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
|
||||
$res['name'] = $audio['title'];
|
||||
@ -128,6 +133,7 @@ trait Files
|
||||
if (!isset($res['name'])) {
|
||||
$res['name'] = $message_media['file']['access_hash'];
|
||||
}
|
||||
|
||||
return $res;
|
||||
case 'messageMediaPhoto':
|
||||
$photo = end($message_media['photo']['sizes']);
|
||||
@ -245,8 +251,10 @@ trait Files
|
||||
}
|
||||
if (isset($info['key'])) {
|
||||
$digest = hash('md5', $info['key'].$info['iv'], true);
|
||||
$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!');
|
||||
$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!');
|
||||
}
|
||||
$ige = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_IGE);
|
||||
$ige->setIV($info['iv']);
|
||||
$ige->setKey($info['key']);
|
||||
|
@ -129,15 +129,18 @@ trait MessageHandler
|
||||
$this->datacenter->new_incoming[$message_id] = $message_id;
|
||||
$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])) {
|
||||
\danog\MadelineProto\Logger::log('I do not have the secret chat '.$chat_id.' in the database, skipping message...');
|
||||
|
||||
return false;
|
||||
}
|
||||
$message = $this->serialize_object(['type' => $message['_']], $message, $this->secret_chats[$chat_id]['layer']);
|
||||
$this->secret_chats[$chat_id]['outgoing'][] = $message;
|
||||
$this->secret_chats[$chat_id]['ttr']--;
|
||||
if (($this->secret_chats[$chat_id]['ttr'] <= 0 || time() - $this->secret_chats[$chat_id]['updated'] > 7*24*60*60) && $this->secret_chats[$chat_id]['rekeying'] === 0) {
|
||||
if (($this->secret_chats[$chat_id]['ttr'] <= 0 || time() - $this->secret_chats[$chat_id]['updated'] > 7 * 24 * 60 * 60) && $this->secret_chats[$chat_id]['rekeying'] === 0) {
|
||||
$this->rekey($chat_id);
|
||||
}
|
||||
|
||||
@ -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');
|
||||
$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);
|
||||
|
||||
return $message;
|
||||
}
|
||||
public function handle_encrypted_update($message) {
|
||||
|
||||
public function handle_encrypted_update($message)
|
||||
{
|
||||
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...');
|
||||
|
||||
return false;
|
||||
}
|
||||
$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);
|
||||
$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');
|
||||
@ -180,7 +189,7 @@ trait MessageHandler
|
||||
throw new \danog\MadelineProto\SecurityException('random_bytes is too short');
|
||||
}
|
||||
$this->secret_chats[$message['message']['chat_id']]['ttr']--;
|
||||
if (($this->secret_chats[$message['message']['chat_id']]['ttr'] <= 0 || time() - $this->secret_chats[$message['message']['chat_id']]['updated'] > 7*24*60*60) && $this->secret_chats[$message['message']['chat_id']]['rekeying'] === 0) {
|
||||
if (($this->secret_chats[$message['message']['chat_id']]['ttr'] <= 0 || time() - $this->secret_chats[$message['message']['chat_id']]['updated'] > 7 * 24 * 60 * 60) && $this->secret_chats[$message['message']['chat_id']]['rekeying'] === 0) {
|
||||
$this->rekey($message['message']['chat_id']);
|
||||
}
|
||||
unset($message['message']['bytes']);
|
||||
|
@ -332,31 +332,42 @@ trait ResponseHandler
|
||||
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'];
|
||||
switch ($update['message']['decrypted_message']['_']) {
|
||||
case 'decryptedMessageService':
|
||||
switch ($update['message']['decrypted_message']['action']) {
|
||||
case 'decryptedMessageActionRequestKey':
|
||||
$this->accept_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']);
|
||||
|
||||
return;
|
||||
|
||||
case 'decryptedMessageActionAcceptKey':
|
||||
$this->commit_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']);
|
||||
|
||||
return;
|
||||
|
||||
case 'decryptedMessageActionCommitKey':
|
||||
$this->complete_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']);
|
||||
|
||||
return;
|
||||
|
||||
case 'decryptedMessageActionNotifyLayer':
|
||||
$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;
|
||||
|
||||
case 'decryptedMessageActionSetMessageTTL':
|
||||
$this->secret_chats[$update['message']['chat_id']]['ttl'] = $update['message']['decrypted_message']['action']['ttl_seconds'];
|
||||
|
||||
return;
|
||||
|
||||
case 'decryptedMessageActionResend':
|
||||
@ -366,6 +377,7 @@ trait ResponseHandler
|
||||
// $this->send_encrypted_message($update['message']['chat_id'], $update['message']['decrypted_message']);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
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']]);
|
||||
|
@ -25,10 +25,14 @@ trait SeqNoHandler
|
||||
|
||||
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']);
|
||||
}
|
||||
public function get_out_seq_no($chat) {
|
||||
|
||||
public function get_out_seq_no($chat)
|
||||
{
|
||||
return count($this->secret_chats[$chat]['outgoing']);
|
||||
}
|
||||
}
|
||||
|
@ -198,6 +198,7 @@ trait UpdateHandler
|
||||
$this->should_serialize = true;
|
||||
$this->updates_state['qts'] = 0;
|
||||
}
|
||||
|
||||
return $this->updates_state;
|
||||
}
|
||||
|
||||
@ -500,7 +501,7 @@ trait UpdateHandler
|
||||
|
||||
return false;
|
||||
}
|
||||
if ($update['qts'] > $cur_state['qts']+1) {
|
||||
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);
|
||||
|
||||
$this->get_updates_difference();
|
||||
@ -511,6 +512,7 @@ trait UpdateHandler
|
||||
$cur_state['qts'] = $update['qts'];
|
||||
$this->should_serialize = true;
|
||||
$this->handle_encrypted_update($update);
|
||||
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@ -521,16 +523,25 @@ trait UpdateHandler
|
||||
if ($update['_'] === 'updateEncryption') {
|
||||
switch ($update['chat']['_']) {
|
||||
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);
|
||||
|
||||
return $this->accept_secret_chat($update['chat']);
|
||||
case 'encryptedChatDiscarded':
|
||||
\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->temp_requested_secret_chats[$update['chat']['id']])) unset($this->temp_requested_secret_chats[$update['chat']['id']]);
|
||||
if (isset($this->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;
|
||||
case 'encryptedChat':
|
||||
\danog\MadelineProto\Logger::log(['Completing creation of secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE);
|
||||
|
||||
return $this->complete_secret_chat($update['chat']);
|
||||
}
|
||||
\danog\MadelineProto\Logger::log([$update], \danog\MadelineProto\Logger::NOTICE);
|
||||
|
@ -63,6 +63,7 @@ class Serialization
|
||||
if ($unserialized === false) {
|
||||
throw new Exception('An error occurred on deserialization');
|
||||
}
|
||||
|
||||
return $unserialized;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ namespace danog\MadelineProto\TL;
|
||||
trait TL
|
||||
{
|
||||
public $encrypted_layer = -1;
|
||||
|
||||
public function construct_tl($files)
|
||||
{
|
||||
\danog\MadelineProto\Logger::log(['Loading TL schemes...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
@ -40,7 +41,9 @@ trait TL
|
||||
if (preg_match('|^//@|', $line)) {
|
||||
$list = explode(' @', str_replace('//', ' ', $line));
|
||||
foreach ($list as $elem) {
|
||||
if ($elem === '') continue;
|
||||
if ($elem === '') {
|
||||
continue;
|
||||
}
|
||||
$elem = explode(' ', $elem, 2);
|
||||
if ($elem[0] === 'class') {
|
||||
$elem = explode(' ', $elem[1], 2);
|
||||
@ -51,11 +54,15 @@ trait TL
|
||||
if (!is_null($class)) {
|
||||
$this->td_descriptions['types'][$class] = $elem[1];
|
||||
$class = null;
|
||||
} else $e = $elem[1];
|
||||
} else {
|
||||
$e = $elem[1];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($elem[0] === 'param_description') $elem[0] = 'description';
|
||||
$dparams[$elem[0]]= $elem[1];
|
||||
if ($elem[0] === 'param_description') {
|
||||
$elem[0] = 'description';
|
||||
}
|
||||
$dparams[$elem[0]] = $elem[1];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -78,9 +85,13 @@ trait TL
|
||||
if (preg_match('/^vector#/', $line)) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/ \?= /', $line)) continue;
|
||||
if (preg_match('/ \?= /', $line)) {
|
||||
continue;
|
||||
}
|
||||
$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([
|
||||
'/:bytes /',
|
||||
'/;/',
|
||||
@ -93,7 +104,7 @@ trait TL
|
||||
'/ $/',
|
||||
'/\?bytes /',
|
||||
'/{/',
|
||||
'/}/'
|
||||
'/}/',
|
||||
], [
|
||||
':string ',
|
||||
'',
|
||||
@ -106,10 +117,10 @@ trait TL
|
||||
'',
|
||||
'?string ',
|
||||
'',
|
||||
''], $line);
|
||||
'', ], $line);
|
||||
$id = hash('crc32b', $clean);
|
||||
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) {
|
||||
\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]['params'] = [];
|
||||
$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) {
|
||||
if ($param === '') {
|
||||
continue;
|
||||
@ -143,17 +156,23 @@ trait TL
|
||||
$orig = $this->encrypted_layer;
|
||||
\danog\MadelineProto\Logger::log(['Translating objects...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
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);
|
||||
}
|
||||
|
||||
\danog\MadelineProto\Logger::log(['Translating methods...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
foreach ($TL_dict['methods'] as $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)) {
|
||||
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'])) {
|
||||
@ -185,7 +204,6 @@ trait TL
|
||||
return array_unique(array_values($this->methods->method_namespace));
|
||||
}
|
||||
|
||||
|
||||
public function serialize_bool($bool)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
case 'double':
|
||||
return \danog\PHP\Struct::pack('<d', $object);
|
||||
@ -297,10 +321,13 @@ trait TL
|
||||
}
|
||||
|
||||
$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) {
|
||||
$concat .= \danog\PHP\Struct::pack('<i', $constructorData['id']);
|
||||
}
|
||||
|
||||
return $concat.$this->serialize_params($constructorData, $object);
|
||||
}
|
||||
|
||||
@ -310,10 +337,10 @@ trait TL
|
||||
if ($tl === false) {
|
||||
throw new Exception('Could not find method: '.$method);
|
||||
}
|
||||
|
||||
return \danog\PHP\Struct::pack('<i', $tl['id']).$this->serialize_params($tl, $arguments);
|
||||
}
|
||||
|
||||
|
||||
public function serialize_params($tl, $arguments)
|
||||
{
|
||||
$serialized = '';
|
||||
@ -348,7 +375,7 @@ trait TL
|
||||
continue;
|
||||
}
|
||||
if ($current_argument['name'] === 'random_bytes') {
|
||||
$serialized .= $this->random(15+random_int(0, 10));
|
||||
$serialized .= $this->random(15 + random_int(0, 10));
|
||||
continue;
|
||||
}
|
||||
if ($current_argument['name'] === 'data' && isset($arguments['message'])) {
|
||||
|
@ -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->type[$this->key] = (($scheme_type === 'mtproto' && $json_dict['type'] === 'Message') ? 'MT' : '').$json_dict['type'];
|
||||
$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->key++;
|
||||
}
|
||||
@ -50,10 +52,16 @@ class TLConstructor extends TLParams
|
||||
$key = 0;
|
||||
$keys = array_keys($this->predicate, $predicate);
|
||||
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 : [
|
||||
'id' => $this->id[$key],
|
||||
|
@ -47,9 +47,11 @@ class TLMethod extends TLParams
|
||||
'params' => $this->params[$key],
|
||||
];
|
||||
}
|
||||
|
||||
public function find_by_id($id)
|
||||
{
|
||||
$key = array_search($id, $this->id);
|
||||
|
||||
return ($key === false) ? false : [
|
||||
'id' => $this->id[$key],
|
||||
'method' => $this->method[$key],
|
||||
|
@ -32,7 +32,6 @@ echo 'Loading settings...'.PHP_EOL;
|
||||
$settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: [];
|
||||
|
||||
if ($MadelineProto === false) {
|
||||
|
||||
echo 'Loading MadelineProto...'.PHP_EOL;
|
||||
$MadelineProto = new \danog\MadelineProto\API($settings);
|
||||
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
|
||||
//$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
|
||||
$media['photo'] = ['_' => 'inputMediaUploadedPhoto', 'file' => $inputFile, 'mime_type' => mime_content_type('tests/faust.jpg'), 'caption' => 'This photo was uploaded using MadelineProto'];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user