Repeat RPC query on internal server errors, improve retry management, improve http client
This commit is contained in:
parent
4d7eab05c4
commit
5519782618
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,20 +10,17 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class API extends APIFactory
|
class API extends APIFactory
|
||||||
{
|
{
|
||||||
use \danog\Serializable;
|
use \danog\Serializable;
|
||||||
|
|
||||||
public $session;
|
public $session;
|
||||||
public $serialized = 0;
|
public $serialized = 0;
|
||||||
|
|
||||||
public function __magic_construct($params = [])
|
public function __magic_construct($params = [])
|
||||||
{
|
{
|
||||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
|
||||||
set_exception_handler(['\danog\MadelineProto\Serialization', 'serialize_all']);
|
set_exception_handler(['\\danog\\MadelineProto\\Serialization', 'serialize_all']);
|
||||||
if (is_string($params)) {
|
if (is_string($params)) {
|
||||||
if (file_exists($params)) {
|
if (file_exists($params)) {
|
||||||
$this->session = $params;
|
$this->session = $params;
|
||||||
@ -34,29 +32,26 @@ class API extends APIFactory
|
|||||||
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'r');
|
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'r');
|
||||||
\danog\MadelineProto\Logger::log(['Waiting for shared lock of serialization lockfile...']);
|
\danog\MadelineProto\Logger::log(['Waiting for shared lock of serialization lockfile...']);
|
||||||
flock($realpaths['lockfile'], LOCK_SH);
|
flock($realpaths['lockfile'], LOCK_SH);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$unserialized = file_get_contents($realpaths['file']);
|
$unserialized = file_get_contents($realpaths['file']);
|
||||||
} finally {
|
} finally {
|
||||||
flock($realpaths['lockfile'], LOCK_UN);
|
flock($realpaths['lockfile'], LOCK_UN);
|
||||||
fclose($realpaths['lockfile']);
|
fclose($realpaths['lockfile']);
|
||||||
}
|
}
|
||||||
|
$tounserialize = str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $unserialized);
|
||||||
$tounserialize = str_replace('O:26:"danog\MadelineProto\Button":', 'O:35:"danog\MadelineProto\TL\Types\Button":', $unserialized);
|
foreach (['RSA', 'TL\\TLMethod', 'TL\\TLConstructor', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\\Types\\Button', 'TL\\Types\\Bytes', 'APIFactory'] as $class) {
|
||||||
foreach (['RSA', 'TL\TLMethod', 'TL\TLConstructor', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\Types\Button', 'TL\Types\Bytes', 'APIFactory'] as $class) {
|
class_exists('\\danog\\MadelineProto\\' . $class);
|
||||||
class_exists('\danog\MadelineProto\\'.$class);
|
|
||||||
}
|
}
|
||||||
class_exists('\Volatile');
|
class_exists('\\Volatile');
|
||||||
\danog\MadelineProto\Logger::class_exists();
|
\danog\MadelineProto\Logger::class_exists();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$unserialized = unserialize($tounserialize);
|
$unserialized = unserialize($tounserialize);
|
||||||
} catch (\danog\MadelineProto\Bug74586Exception $e) {
|
} catch (\danog\MadelineProto\Bug74586Exception $e) {
|
||||||
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
Logger::log([(string) $e], Logger::ERROR);
|
Logger::log([(string) $e], Logger::ERROR);
|
||||||
if (strpos($e->getMessage(), "Erroneous data format for unserializing 'phpseclib\Math\BigInteger'") === 0) {
|
if (strpos($e->getMessage(), "Erroneous data format for unserializing 'phpseclib\\Math\\BigInteger'") === 0) {
|
||||||
$tounserialize = str_replace('phpseclib\Math\BigInteger', 'phpseclib\Math\BigIntegor', $unserialized);
|
$tounserialize = str_replace('phpseclib\\Math\\BigInteger', 'phpseclib\\Math\\BigIntegor', $unserialized);
|
||||||
}
|
}
|
||||||
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
||||||
}
|
}
|
||||||
@ -74,31 +69,25 @@ class API extends APIFactory
|
|||||||
$this->APIFactory();
|
$this->APIFactory();
|
||||||
}
|
}
|
||||||
Serialization::$instances[spl_object_hash($unserialized)] = $unserialized;
|
Serialization::$instances[spl_object_hash($unserialized)] = $unserialized;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->API = new MTProto($params);
|
$this->API = new MTProto($params);
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['apifactory_start']], Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['apifactory_start']], Logger::VERBOSE);
|
||||||
$this->APIFactory();
|
$this->APIFactory();
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Ping...'], Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Ping...'], Logger::ULTRA_VERBOSE);
|
||||||
$pong = $this->ping(['ping_id' => 3]);
|
$pong = $this->ping(['ping_id' => 3]);
|
||||||
\danog\MadelineProto\Logger::log(['Pong: '.$pong['ping_id']], Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Pong: ' . $pong['ping_id']], Logger::ULTRA_VERBOSE);
|
||||||
//\danog\MadelineProto\Logger::log(['Getting future salts...'], Logger::ULTRA_VERBOSE);
|
//\danog\MadelineProto\Logger::log(['Getting future salts...'], Logger::ULTRA_VERBOSE);
|
||||||
//$this->future_salts = $this->get_future_salts(['num' => 3]);
|
//$this->future_salts = $this->get_future_salts(['num' => 3]);
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['madelineproto_ready']], Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['madelineproto_ready']], Logger::NOTICE);
|
||||||
|
|
||||||
Serialization::$instances[spl_object_hash($this)] = $this;
|
Serialization::$instances[spl_object_hash($this)] = $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __wakeup()
|
public function __wakeup()
|
||||||
{
|
{
|
||||||
//if (method_exists($this->API, 'wakeup')) $this->API = $this->API->wakeup();
|
//if (method_exists($this->API, 'wakeup')) $this->API = $this->API->wakeup();
|
||||||
Serialization::$instances[spl_object_hash($this)] = $this;
|
Serialization::$instances[spl_object_hash($this)] = $this;
|
||||||
$this->APIFactory();
|
$this->APIFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
||||||
@ -109,56 +98,45 @@ class API extends APIFactory
|
|||||||
}
|
}
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['API'];
|
return ['API'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &__get($name)
|
public function &__get($name)
|
||||||
{
|
{
|
||||||
if ($name === 'settings') {
|
if ($name === 'settings') {
|
||||||
$this->API->setdem = true;
|
$this->API->setdem = true;
|
||||||
|
|
||||||
return $this->API->settings;
|
return $this->API->settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->API->storage[$name];
|
return $this->API->storage[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __set($name, $value)
|
public function __set($name, $value)
|
||||||
{
|
{
|
||||||
if ($name === 'settings') {
|
if ($name === 'settings') {
|
||||||
return $this->API->__construct($value);
|
return $this->API->__construct($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->API->storage[$name] = $value;
|
return $this->API->storage[$name] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __isset($name)
|
public function __isset($name)
|
||||||
{
|
{
|
||||||
return isset($this->API->storage[$name]);
|
return isset($this->API->storage[$name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __unset($name)
|
public function __unset($name)
|
||||||
{
|
{
|
||||||
unset($this->API->storage[$name]);
|
unset($this->API->storage[$name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function APIFactory()
|
public function APIFactory()
|
||||||
{
|
{
|
||||||
foreach ($this->API->get_method_namespaces() as $namespace) {
|
foreach ($this->API->get_method_namespaces() as $namespace) {
|
||||||
$this->{$namespace} = new APIFactory($namespace, $this->API);
|
$this->{$namespace} = new APIFactory($namespace, $this->API);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serialize($params = '')
|
public function serialize($params = '')
|
||||||
{
|
{
|
||||||
if ($params === '') {
|
if ($params === '') {
|
||||||
$params = $this->session;
|
$params = $this->session;
|
||||||
}
|
}
|
||||||
Logger::log([\danog\MadelineProto\Lang::$current_lang['serializing_madelineproto']]);
|
Logger::log([\danog\MadelineProto\Lang::$current_lang['serializing_madelineproto']]);
|
||||||
|
|
||||||
return Serialization::serialize($params, $this);
|
return Serialization::serialize($params, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class APIFactory
|
class APIFactory
|
||||||
@ -105,17 +105,14 @@ class APIFactory
|
|||||||
*/
|
*/
|
||||||
public $auth;
|
public $auth;
|
||||||
use Tools;
|
use Tools;
|
||||||
|
|
||||||
public $namespace = '';
|
public $namespace = '';
|
||||||
public $API;
|
public $API;
|
||||||
public $lua = false;
|
public $lua = false;
|
||||||
|
|
||||||
public function __construct($namespace, $API)
|
public function __construct($namespace, $API)
|
||||||
{
|
{
|
||||||
$this->namespace = $namespace.'.';
|
$this->namespace = $namespace . '.';
|
||||||
$this->API = $API;
|
$this->API = $API;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __call($name, $arguments)
|
public function __call($name, $arguments)
|
||||||
{
|
{
|
||||||
if ($this->API->setdem) {
|
if ($this->API->setdem) {
|
||||||
@ -130,13 +127,11 @@ class APIFactory
|
|||||||
$this->serialize($this->session);
|
$this->serialize($this->session);
|
||||||
}
|
}
|
||||||
if ($this->lua === false) {
|
if ($this->lua === false) {
|
||||||
return method_exists($this->API, $this->namespace.$name) ? $this->API->{$this->namespace.$name}(...$arguments) : $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && is_array($arguments[0])) ? $arguments[0] : [], $aargs);
|
return method_exists($this->API, $this->namespace . $name) ? $this->API->{$this->namespace . $name}(...$arguments) : $this->API->method_call($this->namespace . $name, isset($arguments[0]) && is_array($arguments[0]) ? $arguments[0] : [], $aargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$deserialized = method_exists($this->API, $this->namespace.$name) ? $this->API->{$this->namespace.$name}(...$arguments) : $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && is_array($arguments[0])) ? $arguments[0] : [], $aargs);
|
$deserialized = method_exists($this->API, $this->namespace . $name) ? $this->API->{$this->namespace . $name}(...$arguments) : $this->API->method_call($this->namespace . $name, isset($arguments[0]) && is_array($arguments[0]) ? $arguments[0] : [], $aargs);
|
||||||
Lua::convert_objects($deserialized);
|
Lua::convert_objects($deserialized);
|
||||||
|
|
||||||
return $deserialized;
|
return $deserialized;
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
|
return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,29 +10,24 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
use phpDocumentor\Reflection\DocBlockFactory;
|
use phpDocumentor\Reflection\DocBlockFactory;
|
||||||
|
|
||||||
class AnnotationsBuilder
|
class AnnotationsBuilder
|
||||||
{
|
{
|
||||||
use \danog\MadelineProto\TL\TL;
|
use \danog\MadelineProto\TL\TL;
|
||||||
use Tools;
|
use Tools;
|
||||||
|
|
||||||
public function __construct($settings)
|
public function __construct($settings)
|
||||||
{
|
{
|
||||||
$this->construct_TL($settings['tl_schema']);
|
$this->construct_TL($settings['tl_schema']);
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function mk_annotations()
|
public function mk_annotations()
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log(['Generating annotations...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating annotations...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->setProperties();
|
$this->setProperties();
|
||||||
$this->createInternalClasses();
|
$this->createInternalClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open file of class APIFactory
|
* Open file of class APIFactory
|
||||||
* Insert properties
|
* Insert properties
|
||||||
@ -47,33 +43,22 @@ class AnnotationsBuilder
|
|||||||
if ($raw_docblock = $property->getDocComment()) {
|
if ($raw_docblock = $property->getDocComment()) {
|
||||||
$docblock = $fixture->create($raw_docblock);
|
$docblock = $fixture->create($raw_docblock);
|
||||||
if ($docblock->hasTag('internal')) {
|
if ($docblock->hasTag('internal')) {
|
||||||
$content = str_replace("\n ".$raw_docblock."\n public $".$property->getName().';', '', $content);
|
$content = str_replace("\n " . $raw_docblock . "\n public \$" . $property->getName() . ';', '', $content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($this->get_method_namespaces() as $namespace) {
|
foreach ($this->get_method_namespaces() as $namespace) {
|
||||||
$content = preg_replace(
|
$content = preg_replace('/(class( \\w+[,]?){0,}\\n{\\n)/', '${1}' . " /**\n" . " * @internal this is a internal property generated by build_docs.php, don't change manually\n" . " *\n" . " * @var {$namespace}\n" . " */\n" . " public \${$namespace};\n", $content);
|
||||||
'/(class( \w+[,]?){0,}\n{\n)/',
|
|
||||||
'${1}'.
|
|
||||||
" /**\n".
|
|
||||||
" * @internal this is a internal property generated by build_docs.php, don't change manually\n".
|
|
||||||
" *\n".
|
|
||||||
" * @var $namespace\n".
|
|
||||||
" */\n".
|
|
||||||
" public \$$namespace;\n",
|
|
||||||
$content
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
file_put_contents($filename, $content);
|
file_put_contents($filename, $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create file InternalDoc with all interfaces.
|
* Create file InternalDoc with all interfaces.
|
||||||
*/
|
*/
|
||||||
private function createInternalClasses()
|
private function createInternalClasses()
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log(['Creating internal classes...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Creating internal classes...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$handle = fopen(dirname(__FILE__).'/InternalDoc.php', 'w');
|
$handle = fopen(dirname(__FILE__) . '/InternalDoc.php', 'w');
|
||||||
foreach ($this->methods->by_id as $id => $data) {
|
foreach ($this->methods->by_id as $id => $data) {
|
||||||
if (!strpos($data['method'], '.')) {
|
if (!strpos($data['method'], '.')) {
|
||||||
continue;
|
continue;
|
||||||
@ -110,22 +95,22 @@ class AnnotationsBuilder
|
|||||||
fwrite($handle, " * and is used only for autocomplete in multiple IDE\n");
|
fwrite($handle, " * and is used only for autocomplete in multiple IDE\n");
|
||||||
fwrite($handle, " * don't modify manually.\n");
|
fwrite($handle, " * don't modify manually.\n");
|
||||||
fwrite($handle, " */\n\n");
|
fwrite($handle, " */\n\n");
|
||||||
fwrite($handle, "namespace danog\MadelineProto;\n");
|
fwrite($handle, "namespace danog\\MadelineProto;\n");
|
||||||
foreach ($internalDoc as $namespace => $methods) {
|
foreach ($internalDoc as $namespace => $methods) {
|
||||||
fwrite($handle, "\ninterface $namespace\n{");
|
fwrite($handle, "\ninterface {$namespace}\n{");
|
||||||
foreach ($methods as $method => $properties) {
|
foreach ($methods as $method => $properties) {
|
||||||
fwrite($handle, "\n /**\n");
|
fwrite($handle, "\n /**\n");
|
||||||
if (isset($properties['attr'])) {
|
if (isset($properties['attr'])) {
|
||||||
fwrite($handle, " * @param array params [\n");
|
fwrite($handle, " * @param array params [\n");
|
||||||
foreach ($properties['attr'] as $name => $type) {
|
foreach ($properties['attr'] as $name => $type) {
|
||||||
fwrite($handle, " * $type $name,\n");
|
fwrite($handle, " * {$type} {$name},\n");
|
||||||
}
|
}
|
||||||
fwrite($handle, " * ]\n");
|
fwrite($handle, " * ]\n");
|
||||||
fwrite($handle, " *\n");
|
fwrite($handle, " *\n");
|
||||||
}
|
}
|
||||||
fwrite($handle, " * @return {$properties['return']}\n");
|
fwrite($handle, " * @return {$properties['return']}\n");
|
||||||
fwrite($handle, " */\n");
|
fwrite($handle, " */\n");
|
||||||
fwrite($handle, " public function $method(");
|
fwrite($handle, " public function {$method}(");
|
||||||
if (isset($properties['attr'])) {
|
if (isset($properties['attr'])) {
|
||||||
fwrite($handle, 'array $params');
|
fwrite($handle, 'array $params');
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class Bug74586Exception extends \Exception
|
class Bug74586Exception extends \Exception
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,7 +20,6 @@ class Connection
|
|||||||
use \danog\Serializable;
|
use \danog\Serializable;
|
||||||
use \danog\MadelineProto\Tools;
|
use \danog\MadelineProto\Tools;
|
||||||
public $sock = null;
|
public $sock = null;
|
||||||
|
|
||||||
public $protocol = null;
|
public $protocol = null;
|
||||||
public $ip = null;
|
public $ip = null;
|
||||||
public $port = null;
|
public $port = null;
|
||||||
@ -39,15 +38,15 @@ class Connection
|
|||||||
public $new_outgoing = [];
|
public $new_outgoing = [];
|
||||||
public $max_incoming_id;
|
public $max_incoming_id;
|
||||||
public $max_outgoing_id;
|
public $max_outgoing_id;
|
||||||
public $proxy = '\Socket';
|
public $proxy = '\\Socket';
|
||||||
public $extra = [];
|
public $extra = [];
|
||||||
public $obfuscated = [];
|
public $obfuscated = [];
|
||||||
public $authorized = false;
|
public $authorized = false;
|
||||||
public $call_queue = [];
|
public $call_queue = [];
|
||||||
public $object_queue = [];
|
public $object_queue = [];
|
||||||
public $ack_queue = [];
|
public $ack_queue = [];
|
||||||
|
|
||||||
public $i = [];
|
public $i = [];
|
||||||
|
private $must_open = false;
|
||||||
|
|
||||||
public function __magic_construct($proxy, $extra, $ip, $port, $protocol, $timeout, $ipv6)
|
public function __magic_construct($proxy, $extra, $ip, $port, $protocol, $timeout, $ipv6)
|
||||||
{
|
{
|
||||||
@ -67,7 +66,7 @@ class Connection
|
|||||||
$this->port = $port;
|
$this->port = $port;
|
||||||
$this->proxy = $proxy;
|
$this->proxy = $proxy;
|
||||||
$this->extra = $extra;
|
$this->extra = $extra;
|
||||||
if (($has_proxy = $proxy !== '\Socket') && !isset(class_implements($proxy)['danog\MadelineProto\Proxy'])) {
|
if (($has_proxy = $proxy !== '\\Socket') && !isset(class_implements($proxy)['danog\\MadelineProto\\Proxy'])) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['proxy_class_invalid']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['proxy_class_invalid']);
|
||||||
}
|
}
|
||||||
switch ($this->protocol) {
|
switch ($this->protocol) {
|
||||||
@ -97,7 +96,6 @@ class Connection
|
|||||||
$this->sock->setBlocking(true);
|
$this->sock->setBlocking(true);
|
||||||
$this->write(str_repeat(chr(238), 4));
|
$this->write(str_repeat(chr(238), 4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tcp_full':
|
case 'tcp_full':
|
||||||
$this->sock = new $proxy($ipv6 ? \AF_INET6 : \AF_INET, \SOCK_STREAM, getprotobyname('tcp'));
|
$this->sock = new $proxy($ipv6 ? \AF_INET6 : \AF_INET, \SOCK_STREAM, getprotobyname('tcp'));
|
||||||
if ($has_proxy && $this->extra !== []) {
|
if ($has_proxy && $this->extra !== []) {
|
||||||
@ -109,7 +107,6 @@ class Connection
|
|||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
|
||||||
}
|
}
|
||||||
$this->sock->setBlocking(true);
|
$this->sock->setBlocking(true);
|
||||||
|
|
||||||
$this->out_seq_no = -1;
|
$this->out_seq_no = -1;
|
||||||
$this->in_seq_no = -1;
|
$this->in_seq_no = -1;
|
||||||
break;
|
break;
|
||||||
@ -129,42 +126,31 @@ class Connection
|
|||||||
} while (in_array(substr($random, 0, 4), ['PVrG', 'GET ', 'POST', 'HEAD', str_repeat(chr(238), 4)]) || $random[0] === chr(0xef) || substr($random, 4, 4) === "\0\0\0\0");
|
} while (in_array(substr($random, 0, 4), ['PVrG', 'GET ', 'POST', 'HEAD', str_repeat(chr(238), 4)]) || $random[0] === chr(0xef) || substr($random, 4, 4) === "\0\0\0\0");
|
||||||
$random[56] = $random[57] = $random[58] = $random[59] = chr(0xef);
|
$random[56] = $random[57] = $random[58] = $random[59] = chr(0xef);
|
||||||
$reversed = strrev(substr($random, 8, 48));
|
$reversed = strrev(substr($random, 8, 48));
|
||||||
|
|
||||||
$this->obfuscated = ['encryption' => new \phpseclib\Crypt\AES('ctr'), 'decryption' => new \phpseclib\Crypt\AES('ctr')];
|
$this->obfuscated = ['encryption' => new \phpseclib\Crypt\AES('ctr'), 'decryption' => new \phpseclib\Crypt\AES('ctr')];
|
||||||
$this->obfuscated['encryption']->enableContinuousBuffer();
|
$this->obfuscated['encryption']->enableContinuousBuffer();
|
||||||
$this->obfuscated['decryption']->enableContinuousBuffer();
|
$this->obfuscated['decryption']->enableContinuousBuffer();
|
||||||
|
|
||||||
$this->obfuscated['encryption']->setKey(substr($random, 8, 32));
|
$this->obfuscated['encryption']->setKey(substr($random, 8, 32));
|
||||||
$this->obfuscated['encryption']->setIV(substr($random, 40, 16));
|
$this->obfuscated['encryption']->setIV(substr($random, 40, 16));
|
||||||
|
|
||||||
$this->obfuscated['decryption']->setKey(substr($reversed, 0, 32));
|
$this->obfuscated['decryption']->setKey(substr($reversed, 0, 32));
|
||||||
$this->obfuscated['decryption']->setIV(substr($reversed, 32, 16));
|
$this->obfuscated['decryption']->setIV(substr($reversed, 32, 16));
|
||||||
$random = substr_replace(
|
$random = substr_replace($random, substr(@$this->obfuscated['encryption']->encrypt($random), 56, 8), 56, 8);
|
||||||
$random,
|
|
||||||
substr(
|
|
||||||
@$this->obfuscated['encryption']->encrypt($random),
|
|
||||||
56,
|
|
||||||
8
|
|
||||||
),
|
|
||||||
56,
|
|
||||||
8
|
|
||||||
);
|
|
||||||
$wrote = 0;
|
$wrote = 0;
|
||||||
if (($wrote += $this->sock->write($random)) !== 64) {
|
if (($wrote += $this->sock->write($random)) !== 64) {
|
||||||
while (($wrote += $this->sock->write(substr($what, $wrote))) !== 64);
|
while (($wrote += $this->sock->write(substr($what, $wrote))) !== 64) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'http':
|
case 'http':
|
||||||
case 'https':
|
case 'https':
|
||||||
|
case 'https_proxied':
|
||||||
$this->parsed = parse_url($ip);
|
$this->parsed = parse_url($ip);
|
||||||
if ($this->parsed['host'][0] === '[') {
|
if ($this->parsed['host'][0] === '[') {
|
||||||
$this->parsed['host'] = substr($this->parsed['host'], 1, -1);
|
$this->parsed['host'] = substr($this->parsed['host'], 1, -1);
|
||||||
}
|
}
|
||||||
if ($this->protocol === 'https' && $proxy === '\Socket') {
|
if (strpos($this->protocol, 'https') === 0 && $proxy === '\\Socket') {
|
||||||
$proxy = '\FSocket';
|
$proxy = '\\FSocket';
|
||||||
}
|
}
|
||||||
$this->sock = new $proxy($ipv6 ? \AF_INET6 : \AF_INET, \SOCK_STREAM, $this->protocol === 'https' ? PHP_INT_MAX : getprotobyname('tcp'));
|
$this->sock = new $proxy($ipv6 ? \AF_INET6 : \AF_INET, \SOCK_STREAM, strpos($this->protocol, 'https') === 0 ? PHP_INT_MAX : getprotobyname('tcp'));
|
||||||
if ($has_proxy && $this->extra !== []) {
|
if ($has_proxy && $this->extra !== []) {
|
||||||
$this->sock->setExtra($this->extra);
|
$this->sock->setExtra($this->extra);
|
||||||
}
|
}
|
||||||
@ -174,6 +160,10 @@ class Connection
|
|||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
|
||||||
}
|
}
|
||||||
$this->sock->setBlocking(true);
|
$this->sock->setBlocking(true);
|
||||||
|
if ($this->protocol === 'https_proxied') {
|
||||||
|
$this->write("CONNECT {$this->parsed['host']}:$port HTTP/1.1\r\nHost: {$this->parsed['host']}:$port\r\n\r\n");
|
||||||
|
$this->read_message();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'udp':
|
case 'udp':
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
||||||
@ -182,18 +172,15 @@ class Connection
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch ($this->protocol) {
|
switch ($this->protocol) {
|
||||||
case 'tcp_abridged':
|
case 'tcp_abridged':
|
||||||
case 'tcp_intermediate':
|
case 'tcp_intermediate':
|
||||||
case 'tcp_full':
|
case 'tcp_full':
|
||||||
case 'http':
|
case 'http':
|
||||||
case 'https':
|
case 'https':
|
||||||
|
case 'https_proxied':
|
||||||
case 'obfuscated2':
|
case 'obfuscated2':
|
||||||
try {
|
try {
|
||||||
unset($this->sock);
|
unset($this->sock);
|
||||||
@ -207,23 +194,17 @@ class Connection
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close_and_reopen()
|
public function close_and_reopen()
|
||||||
{
|
{
|
||||||
$this->__destruct();
|
$this->__destruct();
|
||||||
$this->__construct($this->proxy, $this->extra, $this->ip, $this->port, $this->protocol, $this->timeout, $this->ipv6);
|
$this->must_open = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['proxy', 'extra', 'protocol', 'ip', 'port', 'timeout', 'parsed', 'time_delta', 'temp_auth_key', 'auth_key', 'session_id', 'session_out_seq_no', 'session_in_seq_no', 'ipv6', 'incoming_messages', 'outgoing_messages', 'new_incoming', 'new_outgoing', 'max_incoming_id', 'max_outgoing_id', 'obfuscated', 'authorized', 'object_queue', 'ack_queue'];
|
return ['proxy', 'extra', 'protocol', 'ip', 'port', 'timeout', 'parsed', 'time_delta', 'temp_auth_key', 'auth_key', 'session_id', 'session_out_seq_no', 'session_in_seq_no', 'ipv6', 'incoming_messages', 'outgoing_messages', 'new_incoming', 'new_outgoing', 'max_incoming_id', 'max_outgoing_id', 'obfuscated', 'authorized', 'object_queue', 'ack_queue'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __wakeup()
|
public function __wakeup()
|
||||||
{
|
{
|
||||||
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$keys = array_keys((array) get_object_vars($this));
|
$keys = array_keys((array) get_object_vars($this));
|
||||||
if (count($keys) !== count(array_unique($keys))) {
|
if (count($keys) !== count(array_unique($keys))) {
|
||||||
throw new Bug74586Exception();
|
throw new Bug74586Exception();
|
||||||
@ -231,15 +212,17 @@ class Connection
|
|||||||
$this->time_delta = 0;
|
$this->time_delta = 0;
|
||||||
//$this->__construct($this->proxy, $this->extra, $this->ip, $this->port, $this->protocol, $this->timeout, $this->ipv6);
|
//$this->__construct($this->proxy, $this->extra, $this->ip, $this->port, $this->protocol, $this->timeout, $this->ipv6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function write($what, $length = null)
|
public function write($what, $length = null)
|
||||||
{
|
{
|
||||||
|
if ($this->must_open) {
|
||||||
|
$this->__construct($this->proxy, $this->extra, $this->ip, $this->port, $this->protocol, $this->timeout, $this->ipv6);
|
||||||
|
$this->must_open = false;
|
||||||
|
}
|
||||||
if ($length !== null) {
|
if ($length !== null) {
|
||||||
$what = substr($what, 0, $length);
|
$what = substr($what, 0, $length);
|
||||||
} else {
|
} else {
|
||||||
$length = strlen($what);
|
$length = strlen($what);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->protocol) {
|
switch ($this->protocol) {
|
||||||
case 'obfuscated2':
|
case 'obfuscated2':
|
||||||
$what = @$this->obfuscated['encryption']->encrypt($what);
|
$what = @$this->obfuscated['encryption']->encrypt($what);
|
||||||
@ -248,11 +231,12 @@ class Connection
|
|||||||
case 'tcp_full':
|
case 'tcp_full':
|
||||||
case 'http':
|
case 'http':
|
||||||
case 'https':
|
case 'https':
|
||||||
|
case 'https_proxied':
|
||||||
$wrote = 0;
|
$wrote = 0;
|
||||||
if (($wrote += $this->sock->write($what)) !== $length) {
|
if (($wrote += $this->sock->write($what)) !== $length) {
|
||||||
while (($wrote += $this->sock->write(substr($what, $wrote))) !== $length);
|
while (($wrote += $this->sock->write(substr($what, $wrote))) !== $length) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $wrote;
|
return $wrote;
|
||||||
break;
|
break;
|
||||||
case 'udp':
|
case 'udp':
|
||||||
@ -263,9 +247,12 @@ class Connection
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function read($length)
|
public function read($length)
|
||||||
{
|
{
|
||||||
|
if ($this->must_open) {
|
||||||
|
$this->__construct($this->proxy, $this->extra, $this->ip, $this->port, $this->protocol, $this->timeout, $this->ipv6);
|
||||||
|
$this->must_open = false;
|
||||||
|
}
|
||||||
switch ($this->protocol) {
|
switch ($this->protocol) {
|
||||||
case 'obfuscated2':
|
case 'obfuscated2':
|
||||||
$packet = '';
|
$packet = '';
|
||||||
@ -277,17 +264,15 @@ class Connection
|
|||||||
}
|
}
|
||||||
if (strlen($packet) !== $length) {
|
if (strlen($packet) !== $length) {
|
||||||
$this->close_and_reopen();
|
$this->close_and_reopen();
|
||||||
|
|
||||||
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['wrong_length_read'], $length, strlen($packet)));
|
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['wrong_length_read'], $length, strlen($packet)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return @$this->obfuscated['decryption']->encrypt($packet);
|
return @$this->obfuscated['decryption']->encrypt($packet);
|
||||||
|
|
||||||
case 'tcp_abridged':
|
case 'tcp_abridged':
|
||||||
case 'tcp_intermediate':
|
case 'tcp_intermediate':
|
||||||
case 'tcp_full':
|
case 'tcp_full':
|
||||||
case 'http':
|
case 'http':
|
||||||
case 'https':
|
case 'https':
|
||||||
|
case 'https_proxied':
|
||||||
$packet = '';
|
$packet = '';
|
||||||
while (strlen($packet) < $length) {
|
while (strlen($packet) < $length) {
|
||||||
$packet .= $this->sock->read($length - strlen($packet));
|
$packet .= $this->sock->read($length - strlen($packet));
|
||||||
@ -297,10 +282,8 @@ class Connection
|
|||||||
}
|
}
|
||||||
if (strlen($packet) !== $length) {
|
if (strlen($packet) !== $length) {
|
||||||
$this->close_and_reopen();
|
$this->close_and_reopen();
|
||||||
|
|
||||||
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['wrong_length_read'], $length, strlen($packet)));
|
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['wrong_length_read'], $length, strlen($packet)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $packet;
|
return $packet;
|
||||||
case 'udp':
|
case 'udp':
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
||||||
@ -309,7 +292,6 @@ class Connection
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function read_message()
|
public function read_message()
|
||||||
{
|
{
|
||||||
switch ($this->protocol) {
|
switch ($this->protocol) {
|
||||||
@ -317,8 +299,7 @@ class Connection
|
|||||||
$packet_length_data = $this->read(4);
|
$packet_length_data = $this->read(4);
|
||||||
$packet_length = unpack('V', $packet_length_data)[1];
|
$packet_length = unpack('V', $packet_length_data)[1];
|
||||||
$packet = $this->read($packet_length - 4);
|
$packet = $this->read($packet_length - 4);
|
||||||
|
if (strrev(hash('crc32b', $packet_length_data . substr($packet, 0, -4), true)) !== substr($packet, -4)) {
|
||||||
if (strrev(hash('crc32b', $packet_length_data.substr($packet, 0, -4), true)) !== substr($packet, -4)) {
|
|
||||||
throw new Exception('CRC32 was not correct!');
|
throw new Exception('CRC32 was not correct!');
|
||||||
}
|
}
|
||||||
$this->in_seq_no++;
|
$this->in_seq_no++;
|
||||||
@ -326,88 +307,102 @@ class Connection
|
|||||||
if ($in_seq_no != $this->in_seq_no) {
|
if ($in_seq_no != $this->in_seq_no) {
|
||||||
throw new Exception('Incoming seq_no mismatch');
|
throw new Exception('Incoming seq_no mismatch');
|
||||||
}
|
}
|
||||||
|
|
||||||
return substr($packet, 4, $packet_length - 12);
|
return substr($packet, 4, $packet_length - 12);
|
||||||
case 'tcp_intermediate':
|
case 'tcp_intermediate':
|
||||||
return $this->read(unpack('V', $this->read(4))[1]);
|
return $this->read(unpack('V', $this->read(4))[1]);
|
||||||
|
|
||||||
case 'obfuscated2':
|
case 'obfuscated2':
|
||||||
case 'tcp_abridged':
|
case 'tcp_abridged':
|
||||||
$packet_length = ord($this->read(1));
|
$packet_length = ord($this->read(1));
|
||||||
|
return $this->read($packet_length < 127 ? $packet_length << 2 : unpack('V', $this->read(3) . "\0")[1] << 2);
|
||||||
return $this->read($packet_length < 127 ? $packet_length << 2 : unpack('V', $this->read(3)."\0")[1] << 2);
|
|
||||||
|
|
||||||
case 'http':
|
case 'http':
|
||||||
case 'https':
|
case 'https':
|
||||||
$headers = [];
|
case 'https_proxied':
|
||||||
$close = false;
|
$response = $this->read_http_payload();
|
||||||
$length = 0;
|
if ($response['code'] !== 200) {
|
||||||
while (true) {
|
throw new Exception($response['description'], $response['code']);
|
||||||
$current_header = '';
|
|
||||||
while (($curchar = $this->read(1)) !== "\n") {
|
|
||||||
$current_header .= $curchar;
|
|
||||||
}
|
}
|
||||||
$current_header = rtrim($current_header);
|
$close = $response['protocol'] === 'HTTP/1.0';
|
||||||
if ($current_header === '') {
|
if (isset($headers['connection'])) {
|
||||||
break;
|
$close = $headers['connection'] === 'close';
|
||||||
}
|
|
||||||
if ($current_header === false) {
|
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['no_data_in_socket']);
|
|
||||||
}
|
|
||||||
if (preg_match('|^Content-Length: |i', $current_header)) {
|
|
||||||
$length = (int) preg_replace('|Content-Length: |i', '', $current_header);
|
|
||||||
}
|
|
||||||
if (preg_match('|^Connection: close|i', $current_header)) {
|
|
||||||
$close = true;
|
|
||||||
}
|
|
||||||
$headers[] = $current_header;
|
|
||||||
}
|
|
||||||
$read = $this->read($length);
|
|
||||||
$headers[0] = explode(' ', $headers[0], 3);
|
|
||||||
if ($headers[0][1] !== '200') {
|
|
||||||
throw new Exception($headers[0][2]);
|
|
||||||
}
|
}
|
||||||
if ($close) {
|
if ($close) {
|
||||||
$this->close_and_reopen();
|
$this->close_and_reopen();
|
||||||
}
|
}
|
||||||
|
return $response['body'];
|
||||||
return $read;
|
|
||||||
case 'udp':
|
case 'udp':
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function send_message($message)
|
public function send_message($message)
|
||||||
{
|
{
|
||||||
switch ($this->protocol) {
|
switch ($this->protocol) {
|
||||||
case 'tcp_full':
|
case 'tcp_full':
|
||||||
$this->out_seq_no++;
|
$this->out_seq_no++;
|
||||||
$step1 = pack('VV', (strlen($message) + 12), $this->out_seq_no).$message;
|
$step1 = pack('VV', strlen($message) + 12, $this->out_seq_no) . $message;
|
||||||
$step2 = $step1.strrev(hash('crc32b', $step1, true));
|
$step2 = $step1 . strrev(hash('crc32b', $step1, true));
|
||||||
$this->write($step2);
|
$this->write($step2);
|
||||||
break;
|
break;
|
||||||
case 'tcp_intermediate':
|
case 'tcp_intermediate':
|
||||||
$this->write(pack('V', strlen($message)).$message);
|
$this->write(pack('V', strlen($message)) . $message);
|
||||||
break;
|
break;
|
||||||
case 'obfuscated2':
|
case 'obfuscated2':
|
||||||
case 'tcp_abridged':
|
case 'tcp_abridged':
|
||||||
$len = strlen($message) / 4;
|
$len = strlen($message) / 4;
|
||||||
if ($len < 127) {
|
if ($len < 127) {
|
||||||
$message = chr($len).$message;
|
$message = chr($len) . $message;
|
||||||
} else {
|
} else {
|
||||||
$message = chr(127).substr(pack('V', $len), 0, 3).$message;
|
$message = chr(127) . substr(pack('V', $len), 0, 3) . $message;
|
||||||
}
|
}
|
||||||
$this->write($message);
|
$this->write($message);
|
||||||
break;
|
break;
|
||||||
case 'http':
|
case 'http':
|
||||||
case 'https':
|
case 'https':
|
||||||
$this->write('POST '.$this->parsed['path']." HTTP/1.1\r\nHost: ".$this->parsed['host']."\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: keep-alive\r\nContent-Length: ".strlen($message)."\r\n\r\n".$message);
|
case 'https_proxied':
|
||||||
|
$this->write('POST ' . $this->parsed['path'] . " HTTP/1.1\r\nHost: " . $this->parsed['host'] . "\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: keep-alive\r\nKeep-Alive: timeout=100000, max=10000000\r\nContent-Length: " . strlen($message) . "\r\n\r\n" . $message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'udp':
|
case 'udp':
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['protocol_not_implemented']);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function read_http_line()
|
||||||
|
{
|
||||||
|
$line = '';
|
||||||
|
while (($curchar = $this->read(1)) !== "\n")
|
||||||
|
{
|
||||||
|
$line.= $curchar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtrim($line);
|
||||||
|
}
|
||||||
|
|
||||||
|
function read_http_payload()
|
||||||
|
{
|
||||||
|
$header = explode(' ', $this->read_http_line() , 3);
|
||||||
|
$protocol = $header[0];
|
||||||
|
$code = (int)$header[1];
|
||||||
|
$description = $header[2];
|
||||||
|
$headers = [];
|
||||||
|
while (strlen($current_header = $this->read_http_line())) {
|
||||||
|
$current_header = explode(':', $current_header, 2);
|
||||||
|
$headers[strtolower($current_header[0]) ] = trim($current_header[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$read = '';
|
||||||
|
if (isset($headers['content-length']))
|
||||||
|
{
|
||||||
|
$read = $this->read((int)$headers['content-length']);
|
||||||
|
} elseif (isset($headers['transfer-encoding']) && $headers['transfer-encoding'] === 'chunked') {
|
||||||
|
do
|
||||||
|
{
|
||||||
|
$length = hexdec($this->read_http_line($res));
|
||||||
|
$read.= $this->read($length);
|
||||||
|
$this->read_http_line($res);
|
||||||
|
} while ($length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['protocol' => $protocol, 'code' => $code, 'description' => $description, 'body' => $read, 'headers' => $headers];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,17 +19,14 @@ class DataCenter
|
|||||||
{
|
{
|
||||||
use \danog\MadelineProto\Tools;
|
use \danog\MadelineProto\Tools;
|
||||||
use \danog\Serializable;
|
use \danog\Serializable;
|
||||||
|
|
||||||
public $sockets = [];
|
public $sockets = [];
|
||||||
public $curdc = 0;
|
public $curdc = 0;
|
||||||
private $dclist = [];
|
private $dclist = [];
|
||||||
private $settings = [];
|
private $settings = [];
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['sockets', 'curdc', 'dclist', 'settings'];
|
return ['sockets', 'curdc', 'dclist', 'settings'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __magic_construct($dclist, $settings)
|
public function __magic_construct($dclist, $settings)
|
||||||
{
|
{
|
||||||
$this->dclist = $dclist;
|
$this->dclist = $dclist;
|
||||||
@ -44,7 +41,6 @@ class DataCenter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dc_disconnect($dc_number)
|
public function dc_disconnect($dc_number)
|
||||||
{
|
{
|
||||||
if ($this->curdc === $dc_number) {
|
if ($this->curdc === $dc_number) {
|
||||||
@ -55,7 +51,6 @@ class DataCenter
|
|||||||
unset($this->sockets[$dc_number]);
|
unset($this->sockets[$dc_number]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dc_connect($dc_number)
|
public function dc_connect($dc_number)
|
||||||
{
|
{
|
||||||
if (isset($this->sockets[$dc_number]) && !isset($this->sockets[$dc_number]->old)) {
|
if (isset($this->sockets[$dc_number]) && !isset($this->sockets[$dc_number]->old)) {
|
||||||
@ -64,18 +59,14 @@ class DataCenter
|
|||||||
$dc_config_number = isset($this->settings[$dc_number]) ? $dc_number : 'all';
|
$dc_config_number = isset($this->settings[$dc_number]) ? $dc_number : 'all';
|
||||||
$test = $this->settings[$dc_config_number]['test_mode'] ? 'test' : 'main';
|
$test = $this->settings[$dc_config_number]['test_mode'] ? 'test' : 'main';
|
||||||
$x = 0;
|
$x = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$ipv6 = $this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4';
|
$ipv6 = $this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4';
|
||||||
|
|
||||||
if (!isset($this->dclist[$test][$ipv6][$dc_number]['ip_address'])) {
|
if (!isset($this->dclist[$test][$ipv6][$dc_number]['ip_address'])) {
|
||||||
unset($this->sockets[$dc_number]);
|
unset($this->sockets[$dc_number]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$address = $this->dclist[$test][$ipv6][$dc_number]['ip_address'];
|
$address = $this->dclist[$test][$ipv6][$dc_number]['ip_address'];
|
||||||
$port = $this->dclist[$test][$ipv6][$dc_number]['port'];
|
$port = $this->dclist[$test][$ipv6][$dc_number]['port'];
|
||||||
|
|
||||||
if (isset($this->dclist[$test][$ipv6][$dc_number]['tcpo_only']) && $this->dclist[$test][$ipv6][$dc_number]['tcpo_only']) {
|
if (isset($this->dclist[$test][$ipv6][$dc_number]['tcpo_only']) && $this->dclist[$test][$ipv6][$dc_number]['tcpo_only']) {
|
||||||
if ($dc_config_number === 'all') {
|
if ($dc_config_number === 'all') {
|
||||||
$dc_config_number = $dc_number;
|
$dc_config_number = $dc_number;
|
||||||
@ -85,23 +76,21 @@ class DataCenter
|
|||||||
}
|
}
|
||||||
$this->settings[$dc_config_number]['protocol'] = 'obfuscated2';
|
$this->settings[$dc_config_number]['protocol'] = 'obfuscated2';
|
||||||
}
|
}
|
||||||
|
if (strpos($this->settings[$dc_config_number]['protocol'], 'https') === 0) {
|
||||||
if ($this->settings[$dc_config_number]['protocol'] === 'https') {
|
|
||||||
$subdomain = $this->dclist['ssl_subdomains'][$dc_number];
|
$subdomain = $this->dclist['ssl_subdomains'][$dc_number];
|
||||||
$path = $this->settings[$dc_config_number]['test_mode'] ? 'apiw_test1' : 'apiw1';
|
$path = $this->settings[$dc_config_number]['test_mode'] ? 'apiw_test1' : 'apiw1';
|
||||||
$address = $this->settings[$dc_config_number]['protocol'].'://'.$subdomain.'.web.telegram.org/'.$path;
|
$address = 'https://' . $subdomain . '.web.telegram.org/' . $path;
|
||||||
|
$port = 443;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->settings[$dc_config_number]['protocol'] === 'http') {
|
if ($this->settings[$dc_config_number]['protocol'] === 'http') {
|
||||||
if ($ipv6) {
|
if ($ipv6) {
|
||||||
$address = '['.$address.']';
|
$address = '[' . $address . ']';
|
||||||
}
|
}
|
||||||
$address = $this->settings[$dc_config_number]['protocol'].'://'.$address.'/api';
|
$address = $this->settings[$dc_config_number]['protocol'] . '://' . $address . '/api';
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['dc_con_test_start'], $dc_number, $test, $ipv6, $this->settings[$dc_config_number]['protocol'])], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['dc_con_test_start'], $dc_number, $test, $ipv6, $this->settings[$dc_config_number]['protocol'])], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
foreach (array_unique([$port, 443, 80, 88]) as $port) {
|
foreach (array_unique([$port, 443, 80, 88]) as $port) {
|
||||||
\danog\MadelineProto\Logger::log(['Trying connection on port '.$port.'...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Trying connection on port ' . $port . '...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isset($this->sockets[$dc_number]->old)) {
|
if (isset($this->sockets[$dc_number]->old)) {
|
||||||
$this->sockets[$dc_number]->__construct($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']);
|
$this->sockets[$dc_number]->__construct($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']);
|
||||||
@ -110,7 +99,6 @@ class DataCenter
|
|||||||
$this->sockets[$dc_number] = new Connection($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']);
|
$this->sockets[$dc_number] = new Connection($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']);
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['OK!'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['OK!'], \danog\MadelineProto\Logger::WARNING);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
} catch (\danog\MadelineProto\NothingInTheSocketException $e) {
|
} catch (\danog\MadelineProto\NothingInTheSocketException $e) {
|
||||||
@ -119,50 +107,26 @@ class DataCenter
|
|||||||
switch ($x) {
|
switch ($x) {
|
||||||
case 0:
|
case 0:
|
||||||
$this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6'];
|
$this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6'];
|
||||||
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection with ' . ($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4') . '...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
continue;
|
continue;
|
||||||
case 1:
|
case 1:
|
||||||
$this->settings[$dc_config_number]['proxy'] = '\Socket';
|
$this->settings[$dc_config_number]['proxy'] = '\\Socket';
|
||||||
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with ' . ($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4') . '...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
continue;
|
continue;
|
||||||
case 2:
|
case 2:
|
||||||
$this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6'];
|
$this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6'];
|
||||||
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with ' . ($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4') . '...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while (++$x);
|
} while (++$x);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_dcs($all = true)
|
public function get_dcs($all = true)
|
||||||
{
|
{
|
||||||
$test = $this->settings['all']['test_mode'] ? 'test' : 'main';
|
$test = $this->settings['all']['test_mode'] ? 'test' : 'main';
|
||||||
$ipv6 = $this->settings['all']['ipv6'] ? 'ipv6' : 'ipv4';
|
$ipv6 = $this->settings['all']['ipv6'] ? 'ipv6' : 'ipv4';
|
||||||
|
|
||||||
return $all ? array_keys((array) $this->dclist[$test][$ipv6]) : array_keys((array) $this->sockets);
|
return $all ? array_keys((array) $this->dclist[$test][$ipv6]) : array_keys((array) $this->sockets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public function &__get($name)
|
|
||||||
{
|
|
||||||
return $this->sockets[$this->curdc]->{$name};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __set($name, $value)
|
|
||||||
{
|
|
||||||
$this->sockets[$this->curdc]->{$name} = &$value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __isset($name)
|
|
||||||
{
|
|
||||||
return isset($this->sockets[$this->curdc]->{$name});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __call($name, $arguments)
|
|
||||||
{
|
|
||||||
return call_user_func_array([$this->sockets[$this->curdc], $name], $arguments);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class DocsBuilder
|
class DocsBuilder
|
||||||
@ -18,12 +18,10 @@ class DocsBuilder
|
|||||||
use \danog\MadelineProto\DocsBuilder\Methods;
|
use \danog\MadelineProto\DocsBuilder\Methods;
|
||||||
use \danog\MadelineProto\DocsBuilder\Constructors;
|
use \danog\MadelineProto\DocsBuilder\Constructors;
|
||||||
use Tools;
|
use Tools;
|
||||||
|
|
||||||
public $td = false;
|
public $td = false;
|
||||||
|
|
||||||
public function __construct($settings)
|
public function __construct($settings)
|
||||||
{
|
{
|
||||||
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'])) {
|
if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) {
|
||||||
$this->constructors = $this->td_constructors;
|
$this->constructors = $this->td_constructors;
|
||||||
@ -37,29 +35,24 @@ class DocsBuilder
|
|||||||
chdir($this->settings['output_dir']);
|
chdir($this->settings['output_dir']);
|
||||||
$this->index = $settings['readme'] ? 'README.md' : 'index.md';
|
$this->index = $settings['readme'] ? 'README.md' : 'index.md';
|
||||||
}
|
}
|
||||||
|
|
||||||
public $types = [];
|
public $types = [];
|
||||||
public $any = '*';
|
public $any = '*';
|
||||||
|
|
||||||
public function end($what)
|
public function end($what)
|
||||||
{
|
{
|
||||||
return end($what);
|
return end($what);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function escape($hwat)
|
public function escape($hwat)
|
||||||
{
|
{
|
||||||
return str_replace('_', '\_', $hwat);
|
return str_replace('_', '\\_', $hwat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function mk_docs()
|
public function mk_docs()
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log(['Generating documentation index...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating documentation index...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
file_put_contents($this->index, '---
|
file_put_contents($this->index, '---
|
||||||
title: '.$this->settings['title'].'
|
title: ' . $this->settings['title'] . '
|
||||||
description: '.$this->settings['description'].'
|
description: ' . $this->settings['description'] . '
|
||||||
---
|
---
|
||||||
# '.$this->settings['description'].'
|
# ' . $this->settings['description'] . '
|
||||||
|
|
||||||
[Methods](methods/)
|
[Methods](methods/)
|
||||||
|
|
||||||
@ -72,19 +65,15 @@ description: '.$this->settings['description'].'
|
|||||||
');
|
');
|
||||||
$this->mk_methodS();
|
$this->mk_methodS();
|
||||||
$this->mk_constructors();
|
$this->mk_constructors();
|
||||||
|
|
||||||
foreach (glob('types/*') as $unlink) {
|
foreach (glob('types/*') as $unlink) {
|
||||||
unlink($unlink);
|
unlink($unlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_exists('types')) {
|
if (file_exists('types')) {
|
||||||
rmdir('types');
|
rmdir('types');
|
||||||
}
|
}
|
||||||
mkdir('types');
|
mkdir('types');
|
||||||
|
|
||||||
ksort($this->types);
|
ksort($this->types);
|
||||||
$index = '';
|
$index = '';
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Generating types documentation...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating types documentation...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$last_namespace = '';
|
$last_namespace = '';
|
||||||
foreach ($this->types as $otype => $keys) {
|
foreach ($this->types as $otype => $keys) {
|
||||||
@ -92,14 +81,14 @@ description: '.$this->settings['description'].'
|
|||||||
//$br = $new_namespace != $last_namespace ? '***<br><br>' : '';
|
//$br = $new_namespace != $last_namespace ? '***<br><br>' : '';
|
||||||
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $otype);
|
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $otype);
|
||||||
$type = preg_replace('/.*_of_/', '', $type);
|
$type = preg_replace('/.*_of_/', '', $type);
|
||||||
$index .= '['.str_replace('_', '\_', $type).']('.$type.'.md)<a name="'.$type.'"></a>
|
$index .= '[' . str_replace('_', '\\_', $type) . '](' . $type . '.md)<a name="' . $type . '"></a>
|
||||||
|
|
||||||
';
|
';
|
||||||
$constructors = '';
|
$constructors = '';
|
||||||
foreach ($keys['constructors'] as $data) {
|
foreach ($keys['constructors'] as $data) {
|
||||||
$predicate = str_replace('.', '_', $data['predicate']).(isset($data['layer']) && $data['layer'] !== '' ? '_'.$data['layer'] : '');
|
$predicate = str_replace('.', '_', $data['predicate']) . (isset($data['layer']) && $data['layer'] !== '' ? '_' . $data['layer'] : '');
|
||||||
$md_predicate = str_replace('_', '\_', $predicate);
|
$md_predicate = str_replace('_', '\\_', $predicate);
|
||||||
$constructors .= '['.$md_predicate.'](../constructors/'.$predicate.'.md)
|
$constructors .= '[' . $md_predicate . '](../constructors/' . $predicate . '.md)
|
||||||
|
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
@ -107,50 +96,38 @@ description: '.$this->settings['description'].'
|
|||||||
foreach ($keys['methods'] as $data) {
|
foreach ($keys['methods'] as $data) {
|
||||||
$name = str_replace('.', '_', $data['method']);
|
$name = str_replace('.', '_', $data['method']);
|
||||||
$md_name = str_replace('_', '->', $name);
|
$md_name = str_replace('_', '->', $name);
|
||||||
$methods .= '[$MadelineProto->'.$md_name.'](../methods/'.$name.'.md)
|
$methods .= '[$MadelineProto->' . $md_name . '](../methods/' . $name . '.md)
|
||||||
|
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
$description = isset($this->td_descriptions['types'][$otype]) ? $this->td_descriptions['types'][$otype] : ('constructors and methods of typr '.$type);
|
$description = isset($this->td_descriptions['types'][$otype]) ? $this->td_descriptions['types'][$otype] : 'constructors and methods of typr ' . $type;
|
||||||
|
|
||||||
$header = '---
|
$header = '---
|
||||||
title: '.$type.'
|
title: ' . $type . '
|
||||||
description: constructors and methods of type '.$type.'
|
description: constructors and methods of type ' . $type . '
|
||||||
---
|
---
|
||||||
## Type: '.str_replace('_', '\_', $type).'
|
## Type: ' . str_replace('_', '\\_', $type) . '
|
||||||
[Back to types index](index.md)
|
[Back to types index](index.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
';
|
';
|
||||||
$header .= isset($this->td_descriptions['types'][$otype]) ? $this->td_descriptions['types'][$otype].PHP_EOL.PHP_EOL : '';
|
$header .= isset($this->td_descriptions['types'][$otype]) ? $this->td_descriptions['types'][$otype] . PHP_EOL . PHP_EOL : '';
|
||||||
|
|
||||||
if (!isset($this->settings['td'])) {
|
if (!isset($this->settings['td'])) {
|
||||||
if (in_array($type, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) {
|
if (in_array($type, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) {
|
||||||
$header .= 'The following syntaxes can also be used:
|
$header .= 'The following syntaxes can also be used:
|
||||||
|
|
||||||
```
|
```
|
||||||
$'.$type." = '@username'; // Username
|
$' . $type . " = '@username'; // Username\n\n\$" . $type . ' = 44700; // bot API id (users)
|
||||||
|
$' . $type . ' = -492772765; // bot API id (chats)
|
||||||
|
$' . $type . ' = -10038575794; // bot API id (channels)
|
||||||
|
|
||||||
$".$type.' = 44700; // bot API id (users)
|
$' . $type . " = 'user#44700'; // tg-cli style id (users)\n\$" . $type . " = 'chat#492772765'; // tg-cli style id (chats)\n\$" . $type . " = 'channel#38575794'; // tg-cli style id (channels)\n```\n\nA [Chat](Chat.md), a [User](User.md), an [InputPeer](InputPeer.md), an [InputUser](InputUser.md), an [InputChannel](InputChannel.md), a [Peer](Peer.md), or a [Chat](Chat.md) object can also be used.\n\n\n";
|
||||||
$'.$type.' = -492772765; // bot API id (chats)
|
|
||||||
$'.$type.' = -10038575794; // bot API id (channels)
|
|
||||||
|
|
||||||
$'.$type." = 'user#44700'; // tg-cli style id (users)
|
|
||||||
$".$type." = 'chat#492772765'; // tg-cli style id (chats)
|
|
||||||
$".$type." = 'channel#38575794'; // tg-cli style id (channels)
|
|
||||||
```
|
|
||||||
|
|
||||||
A [Chat](Chat.md), a [User](User.md), an [InputPeer](InputPeer.md), an [InputUser](InputUser.md), an [InputChannel](InputChannel.md), a [Peer](Peer.md), or a [Chat](Chat.md) object can also be used.
|
|
||||||
|
|
||||||
|
|
||||||
";
|
|
||||||
}
|
}
|
||||||
if (in_array($type, ['InputEncryptedChat'])) {
|
if (in_array($type, ['InputEncryptedChat'])) {
|
||||||
$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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -162,7 +139,7 @@ $'.$type.' = -147286699; // Numeric chat id returned by request_secret_chat, can
|
|||||||
To click these buttons simply run the `click` method:
|
To click these buttons simply run the `click` method:
|
||||||
|
|
||||||
```
|
```
|
||||||
$result = $'.$type.'->click();
|
$result = $' . $type . '->click();
|
||||||
```
|
```
|
||||||
|
|
||||||
`$result` can be one of the following:
|
`$result` can be one of the following:
|
||||||
@ -182,19 +159,19 @@ $result = $'.$type.'->click();
|
|||||||
}
|
}
|
||||||
$constructors = '### Possible values (constructors):
|
$constructors = '### Possible values (constructors):
|
||||||
|
|
||||||
'.$constructors.'
|
' . $constructors . '
|
||||||
|
|
||||||
';
|
';
|
||||||
$methods = '### Methods that return an object of this type (methods):
|
$methods = '### Methods that return an object of this type (methods):
|
||||||
|
|
||||||
'.$methods.'
|
' . $methods . '
|
||||||
|
|
||||||
';
|
';
|
||||||
if (!isset($this->settings['td'])) {
|
if (!isset($this->settings['td'])) {
|
||||||
if (in_array($type, ['PhoneCall'])) {
|
if (in_array($type, ['PhoneCall'])) {
|
||||||
$methods = '';
|
$methods = '';
|
||||||
$constructors = '';
|
$constructors = '';
|
||||||
$header .= 'This is an object of type `\danog\MadelineProto\VoIP`.
|
$header .= 'This is an object of type `\\danog\\MadelineProto\\VoIP`.
|
||||||
|
|
||||||
It will only be available if the [php-libtgvoip](https://github.com/danog/php-libtgvoip) extension is installed, see [the main docs](https://daniil.it/MadelineProto#calls) for an easy installation script.
|
It will only be available if the [php-libtgvoip](https://github.com/danog/php-libtgvoip) extension is installed, see [the main docs](https://daniil.it/MadelineProto#calls) for an easy installation script.
|
||||||
|
|
||||||
@ -362,8 +339,8 @@ Example:
|
|||||||
```
|
```
|
||||||
$call->configuration["log_file_path"] = "logs".$call->getOtherID().".log"; // Default is /dev/null
|
$call->configuration["log_file_path"] = "logs".$call->getOtherID().".log"; // Default is /dev/null
|
||||||
$call->configuration["stats_dump_file_path"] = "stats".$call->getOtherID().".log"; // Default is /dev/null
|
$call->configuration["stats_dump_file_path"] = "stats".$call->getOtherID().".log"; // Default is /dev/null
|
||||||
$call->configuration["network_type"] = \danog\MadelineProto\VoIP::NET_TYPE_WIFI; // Default is NET_TYPE_ETHERNET
|
$call->configuration["network_type"] = \\danog\\MadelineProto\\VoIP::NET_TYPE_WIFI; // Default is NET_TYPE_ETHERNET
|
||||||
$call->configuration["data_saving"] = \danog\MadelineProto\VoIP::DATA_SAVING_MOBILE; // Default is DATA_SAVING_NEVER
|
$call->configuration["data_saving"] = \\danog\\MadelineProto\\VoIP::DATA_SAVING_MOBILE; // Default is DATA_SAVING_NEVER
|
||||||
$call->parseConfig(); // Always call this after changing settings
|
$call->parseConfig(); // Always call this after changing settings
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -374,16 +351,14 @@ After modifying it, you must always parse the new configuration with a call to `
|
|||||||
';
|
';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (file_exists('types/'.$type.'.md')) {
|
if (file_exists('types/' . $type . '.md')) {
|
||||||
\danog\MadelineProto\Logger::log([$type]);
|
\danog\MadelineProto\Logger::log([$type]);
|
||||||
}
|
}
|
||||||
file_put_contents('types/'.$type.'.md', $header.$constructors.$methods);
|
file_put_contents('types/' . $type . '.md', $header . $constructors . $methods);
|
||||||
$last_namespace = $new_namespace;
|
$last_namespace = $new_namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Generating types index...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating types index...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
file_put_contents('types/' . $this->index, '---
|
||||||
file_put_contents('types/'.$this->index, '---
|
|
||||||
title: Types
|
title: Types
|
||||||
description: List of types
|
description: List of types
|
||||||
---
|
---
|
||||||
@ -391,10 +366,8 @@ description: List of types
|
|||||||
[Back to API documentation index](..)
|
[Back to API documentation index](..)
|
||||||
|
|
||||||
|
|
||||||
'.$index);
|
' . $index);
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Generating additional types...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating additional types...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
file_put_contents('types/string.md', '---
|
file_put_contents('types/string.md', '---
|
||||||
title: string
|
title: string
|
||||||
description: A UTF8 string of variable length
|
description: A UTF8 string of variable length
|
||||||
@ -413,7 +386,6 @@ description: A string of variable length
|
|||||||
|
|
||||||
A string of bytes of variable length, with length smaller than or equal to 16777215.
|
A string of bytes of variable length, with length smaller than or equal to 16777215.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/int.md', '---
|
file_put_contents('types/int.md', '---
|
||||||
title: integer
|
title: integer
|
||||||
description: A 32 bit signed integer ranging from -2147483648 to 2147483647
|
description: A 32 bit signed integer ranging from -2147483648 to 2147483647
|
||||||
@ -423,7 +395,6 @@ description: A 32 bit signed integer ranging from -2147483648 to 2147483647
|
|||||||
|
|
||||||
A 32 bit signed integer ranging from `-2147483648` to `2147483647`.
|
A 32 bit signed integer ranging from `-2147483648` to `2147483647`.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/int53.md', '---
|
file_put_contents('types/int53.md', '---
|
||||||
title: integer
|
title: integer
|
||||||
description: A 53 bit signed integer
|
description: A 53 bit signed integer
|
||||||
@ -433,7 +404,6 @@ description: A 53 bit signed integer
|
|||||||
|
|
||||||
A 53 bit signed integer.
|
A 53 bit signed integer.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/long.md', '---
|
file_put_contents('types/long.md', '---
|
||||||
title: long
|
title: long
|
||||||
description: A 32 bit signed integer ranging from -9223372036854775808 to 9223372036854775807
|
description: A 32 bit signed integer ranging from -9223372036854775808 to 9223372036854775807
|
||||||
@ -443,7 +413,6 @@ description: A 32 bit signed integer ranging from -9223372036854775808 to 922337
|
|||||||
|
|
||||||
A 64 bit signed integer ranging from `-9223372036854775808` to `9223372036854775807`.
|
A 64 bit signed integer ranging from `-9223372036854775808` to `9223372036854775807`.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/int128.md', '---
|
file_put_contents('types/int128.md', '---
|
||||||
title: int128
|
title: int128
|
||||||
description: A 128 bit signed integer
|
description: A 128 bit signed integer
|
||||||
@ -453,7 +422,6 @@ description: A 128 bit signed integer
|
|||||||
|
|
||||||
A 128 bit signed integer represented in little-endian base256 (`string`) format.
|
A 128 bit signed integer represented in little-endian base256 (`string`) format.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/int256.md', '---
|
file_put_contents('types/int256.md', '---
|
||||||
title: int256
|
title: int256
|
||||||
description: A 256 bit signed integer
|
description: A 256 bit signed integer
|
||||||
@ -463,7 +431,6 @@ description: A 256 bit signed integer
|
|||||||
|
|
||||||
A 256 bit signed integer represented in little-endian base256 (`string`) format.
|
A 256 bit signed integer represented in little-endian base256 (`string`) format.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/int512.md', '---
|
file_put_contents('types/int512.md', '---
|
||||||
title: int512
|
title: int512
|
||||||
description: A 512 bit signed integer
|
description: A 512 bit signed integer
|
||||||
@ -473,7 +440,6 @@ description: A 512 bit signed integer
|
|||||||
|
|
||||||
A 512 bit signed integer represented in little-endian base256 (`string`) format.
|
A 512 bit signed integer represented in little-endian base256 (`string`) format.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/double.md', '---
|
file_put_contents('types/double.md', '---
|
||||||
title: double
|
title: double
|
||||||
description: A double precision floating point number
|
description: A double precision floating point number
|
||||||
@ -483,7 +449,6 @@ description: A double precision floating point number
|
|||||||
|
|
||||||
A double precision floating point number, single precision can also be used (float).
|
A double precision floating point number, single precision can also be used (float).
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/!X.md', '---
|
file_put_contents('types/!X.md', '---
|
||||||
title: !X
|
title: !X
|
||||||
description: Represents a TL serialized payload
|
description: Represents a TL serialized payload
|
||||||
@ -493,7 +458,6 @@ description: Represents a TL serialized payload
|
|||||||
|
|
||||||
Represents a TL serialized payload.
|
Represents a TL serialized payload.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/X.md', '---
|
file_put_contents('types/X.md', '---
|
||||||
title: X
|
title: X
|
||||||
description: Represents a TL serialized payload
|
description: Represents a TL serialized payload
|
||||||
@ -503,7 +467,6 @@ description: Represents a TL serialized payload
|
|||||||
|
|
||||||
Represents a TL serialized payload.
|
Represents a TL serialized payload.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('constructors/boolFalse.md', '---
|
file_put_contents('constructors/boolFalse.md', '---
|
||||||
title: boolFalse
|
title: boolFalse
|
||||||
description: Represents a boolean with value equal to false
|
description: Represents a boolean with value equal to false
|
||||||
@ -513,7 +476,6 @@ description: Represents a boolean with value equal to false
|
|||||||
|
|
||||||
Represents a boolean with value equal to `false`.
|
Represents a boolean with value equal to `false`.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('constructors/boolTrue.md', '---
|
file_put_contents('constructors/boolTrue.md', '---
|
||||||
title: boolTrue
|
title: boolTrue
|
||||||
description: Represents a boolean with value equal to true
|
description: Represents a boolean with value equal to true
|
||||||
@ -523,7 +485,6 @@ description: Represents a boolean with value equal to true
|
|||||||
|
|
||||||
Represents a boolean with value equal to `true`.
|
Represents a boolean with value equal to `true`.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('constructors/null.md', '---
|
file_put_contents('constructors/null.md', '---
|
||||||
title: null
|
title: null
|
||||||
description: Represents a null value
|
description: Represents a null value
|
||||||
@ -533,7 +494,6 @@ description: Represents a null value
|
|||||||
|
|
||||||
Represents a `null` value.
|
Represents a `null` value.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/Bool.md', '---
|
file_put_contents('types/Bool.md', '---
|
||||||
title: Bool
|
title: Bool
|
||||||
description: Represents a boolean.
|
description: Represents a boolean.
|
||||||
@ -543,7 +503,6 @@ description: Represents a boolean.
|
|||||||
|
|
||||||
Represents a boolean.
|
Represents a boolean.
|
||||||
');
|
');
|
||||||
|
|
||||||
file_put_contents('types/DataJSON.md', '---
|
file_put_contents('types/DataJSON.md', '---
|
||||||
title: DataJSON
|
title: DataJSON
|
||||||
description: Any json-encodable data
|
description: Any json-encodable data
|
||||||
@ -553,7 +512,6 @@ description: Any json-encodable data
|
|||||||
|
|
||||||
Any json-encodable data.
|
Any json-encodable data.
|
||||||
');
|
');
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Done!'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Done!'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,14 +10,13 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\DocsBuilder;
|
namespace danog\MadelineProto\DocsBuilder;
|
||||||
|
|
||||||
trait Constructors
|
trait Constructors
|
||||||
{
|
{
|
||||||
public function mk_constructors()
|
public function mk_constructors()
|
||||||
{
|
{
|
||||||
foreach (glob('constructors/'.$this->any) as $unlink) {
|
foreach (glob('constructors/' . $this->any) as $unlink) {
|
||||||
unlink($unlink);
|
unlink($unlink);
|
||||||
}
|
}
|
||||||
if (file_exists('constructors')) {
|
if (file_exists('constructors')) {
|
||||||
@ -32,12 +32,11 @@ trait Constructors
|
|||||||
$data['layer'] = '';
|
$data['layer'] = '';
|
||||||
}
|
}
|
||||||
$got[$id] = '';
|
$got[$id] = '';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (preg_match('/%/', $type)) {
|
if (preg_match('/%/', $type)) {
|
||||||
$type = $this->constructors->find_by_type(str_replace('%', '', $type))['predicate'];
|
$type = $this->constructors->find_by_type(str_replace('%', '', $type))['predicate'];
|
||||||
}*/
|
}*/
|
||||||
$layer = isset($data['layer']) && $data['layer'] !== '' ? '_'.$data['layer'] : '';
|
$layer = isset($data['layer']) && $data['layer'] !== '' ? '_' . $data['layer'] : '';
|
||||||
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
|
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
|
||||||
$php_type = preg_replace('/.*_of_/', '', $type);
|
$php_type = preg_replace('/.*_of_/', '', $type);
|
||||||
$constructor = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['predicate']);
|
$constructor = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['predicate']);
|
||||||
@ -58,22 +57,20 @@ trait Constructors
|
|||||||
$param['type'] = 'DecryptedMessage';
|
$param['type'] = 'DecryptedMessage';
|
||||||
}
|
}
|
||||||
$type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type';
|
$type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type';
|
||||||
$type_or_bare_type = (ctype_upper($this->end(explode('.', $param[$type_or_subtype]))[0]) || in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512'])) ? 'types' : 'constructors';
|
$type_or_bare_type = ctype_upper($this->end(explode('.', $param[$type_or_subtype]))[0]) || in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512']) ? 'types' : 'constructors';
|
||||||
|
|
||||||
$param[$type_or_subtype] = str_replace(['.', 'true', 'false'], ['_', 'Bool', 'Bool'], $param[$type_or_subtype]);
|
$param[$type_or_subtype] = str_replace(['.', 'true', 'false'], ['_', 'Bool', 'Bool'], $param[$type_or_subtype]);
|
||||||
|
|
||||||
if (preg_match('/%/', $param[$type_or_subtype])) {
|
if (preg_match('/%/', $param[$type_or_subtype])) {
|
||||||
$param[$type_or_subtype] = $this->constructors->find_by_type(str_replace('%', '', $param[$type_or_subtype]))['predicate'];
|
$param[$type_or_subtype] = $this->constructors->find_by_type(str_replace('%', '', $param[$type_or_subtype]))['predicate'];
|
||||||
}
|
}
|
||||||
if (substr($param[$type_or_subtype], -1) === '>') {
|
if (substr($param[$type_or_subtype], -1) === '>') {
|
||||||
$param[$type_or_subtype] = substr($param[$type_or_subtype], 0, -1);
|
$param[$type_or_subtype] = substr($param[$type_or_subtype], 0, -1);
|
||||||
}
|
}
|
||||||
$params .= "'".$param['name']."' => ";
|
$params .= "'" . $param['name'] . "' => ";
|
||||||
$param[$type_or_subtype] = '['.$this->escape($param[$type_or_subtype]).'](../'.$type_or_bare_type.'/'.$param[$type_or_subtype].'.md)';
|
$param[$type_or_subtype] = '[' . $this->escape($param[$type_or_subtype]) . '](../' . $type_or_bare_type . '/' . $param[$type_or_subtype] . '.md)';
|
||||||
$params .= (isset($param['subtype']) ? '\['.$param[$type_or_subtype].'\]' : $param[$type_or_subtype]).', ';
|
$params .= (isset($param['subtype']) ? '\\[' . $param[$type_or_subtype] . '\\]' : $param[$type_or_subtype]) . ', ';
|
||||||
}
|
}
|
||||||
$md_constructor = str_replace('_', '\_', $constructor.$layer);
|
$md_constructor = str_replace('_', '\\_', $constructor . $layer);
|
||||||
$this->docs_constructors[$constructor] = '[$'.$md_constructor.'](../constructors/'.$php_constructor.$layer.'.md) = \['.$params.'\];<a name="'.$constructor.$layer.'"></a>
|
$this->docs_constructors[$constructor] = '[$' . $md_constructor . '](../constructors/' . $php_constructor . $layer . '.md) = \\[' . $params . '\\];<a name="' . $constructor . $layer . '"></a>
|
||||||
|
|
||||||
';
|
';
|
||||||
$table = empty($data['params']) ? '' : '### Attributes:
|
$table = empty($data['params']) ? '' : '### Attributes:
|
||||||
@ -111,42 +108,40 @@ trait Constructors
|
|||||||
if (preg_match('/%/', $ptype)) {
|
if (preg_match('/%/', $ptype)) {
|
||||||
$ptype = $this->constructors->find_by_type(str_replace('%', '', $ptype))['predicate'];
|
$ptype = $this->constructors->find_by_type(str_replace('%', '', $ptype))['predicate'];
|
||||||
}
|
}
|
||||||
$type_or_bare_type = ((ctype_upper($this->end(explode('_', $ptype))[0]) || in_array($ptype, ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512'])) && $ptype !== 'MTmessage') ? 'types' : 'constructors';
|
$type_or_bare_type = (ctype_upper($this->end(explode('_', $ptype))[0]) || in_array($ptype, ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512'])) && $ptype !== 'MTmessage' ? 'types' : 'constructors';
|
||||||
|
|
||||||
if (substr($ptype, -1) === '>') {
|
if (substr($ptype, -1) === '>') {
|
||||||
$ptype = substr($ptype, 0, -1);
|
$ptype = substr($ptype, 0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($ptype) {
|
switch ($ptype) {
|
||||||
case 'true':
|
case 'true':
|
||||||
case 'false':
|
case 'false':
|
||||||
$ptype = 'Bool';
|
$ptype = 'Bool';
|
||||||
}
|
}
|
||||||
$table .= '|'.str_replace('_', '\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\_', $ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || $this->constructors->find_by_predicate(lcfirst($param['type']).'Empty') ? 'Optional' : 'Yes').'|';
|
$table .= '|' . str_replace('_', '\\_', $param['name']) . '|' . (isset($param['subtype']) ? 'Array of ' : '') . '[' . str_replace('_', '\\_', $ptype) . '](../' . $type_or_bare_type . '/' . $ptype . '.md) | ' . (isset($param['pow']) || $this->constructors->find_by_predicate(lcfirst($param['type']) . 'Empty') ? 'Optional' : 'Yes') . '|';
|
||||||
if (isset($this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']])) {
|
if (isset($this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']])) {
|
||||||
$table .= $this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']].'|';
|
$table .= $this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']] . '|';
|
||||||
}
|
}
|
||||||
$table .= PHP_EOL;
|
$table .= PHP_EOL;
|
||||||
$pptype = in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype;
|
$pptype = in_array($ptype, ['string', 'bytes']) ? "'" . $ptype . "'" : $ptype;
|
||||||
$ppptype = in_array($ptype, ['string', 'bytes']) ? '"'.$ptype.'"' : $ptype;
|
$ppptype = in_array($ptype, ['string', 'bytes']) ? '"' . $ptype . '"' : $ptype;
|
||||||
$params .= ", '".$param['name']."' => ";
|
$params .= ", '" . $param['name'] . "' => ";
|
||||||
$params .= (isset($param['subtype']) ? '['.$pptype.']' : $pptype);
|
$params .= isset($param['subtype']) ? '[' . $pptype . ']' : $pptype;
|
||||||
$lua_params .= ', '.$param['name'].'=';
|
$lua_params .= ', ' . $param['name'] . '=';
|
||||||
$lua_params .= (isset($param['subtype']) ? '{'.$pptype.'}' : $pptype);
|
$lua_params .= isset($param['subtype']) ? '{' . $pptype . '}' : $pptype;
|
||||||
$pwr_params .= ', "'.$param['name'].'": '.(isset($param['subtype']) ? '['.$ppptype.']' : $ppptype);
|
$pwr_params .= ', "' . $param['name'] . '": ' . (isset($param['subtype']) ? '[' . $ppptype . ']' : $ppptype);
|
||||||
if ($param['name'] === 'reply_markup') {
|
if ($param['name'] === 'reply_markup') {
|
||||||
$hasreplymarkup = true;
|
$hasreplymarkup = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$params = "['_' => '".$data['predicate']."'".$params.']';
|
$params = "['_' => '" . $data['predicate'] . "'" . $params . ']';
|
||||||
$lua_params = "{_='".$data['predicate']."'".$lua_params.'}';
|
$lua_params = "{_='" . $data['predicate'] . "'" . $lua_params . '}';
|
||||||
$pwr_params = '{"_": "'.$data['predicate'].'"'.$pwr_params.'}';
|
$pwr_params = '{"_": "' . $data['predicate'] . '"' . $pwr_params . '}';
|
||||||
$description = isset($this->td_descriptions['constructors'][$data['predicate']]) ? $this->td_descriptions['constructors'][$data['predicate']]['description'] : ($constructor.' attributes, type and example');
|
$description = isset($this->td_descriptions['constructors'][$data['predicate']]) ? $this->td_descriptions['constructors'][$data['predicate']]['description'] : $constructor . ' attributes, type and example';
|
||||||
$header = '---
|
$header = '---
|
||||||
title: '.$data['predicate'].'
|
title: ' . $data['predicate'] . '
|
||||||
description: '.$description.'
|
description: ' . $description . '
|
||||||
---
|
---
|
||||||
## Constructor: '.str_replace('_', '\_', $data['predicate'].$layer).'
|
## Constructor: ' . str_replace('_', '\\_', $data['predicate'] . $layer) . '
|
||||||
[Back to constructors index](index.md)
|
[Back to constructors index](index.md)
|
||||||
|
|
||||||
|
|
||||||
@ -157,9 +152,9 @@ description: '.$description.'
|
|||||||
|
|
||||||
';
|
';
|
||||||
if (isset($this->td_descriptions['constructors'][$data['predicate']])) {
|
if (isset($this->td_descriptions['constructors'][$data['predicate']])) {
|
||||||
$header .= $this->td_descriptions['constructors'][$data['predicate']]['description'].PHP_EOL.PHP_EOL;
|
$header .= $this->td_descriptions['constructors'][$data['predicate']]['description'] . PHP_EOL . PHP_EOL;
|
||||||
}
|
}
|
||||||
$type = '### Type: ['.str_replace('_', '\_', $php_type).'](../types/'.$php_type.'.md)
|
$type = '### Type: [' . str_replace('_', '\\_', $php_type) . '](../types/' . $php_type . '.md)
|
||||||
|
|
||||||
|
|
||||||
';
|
';
|
||||||
@ -168,13 +163,13 @@ description: '.$description.'
|
|||||||
$example = '### Example:
|
$example = '### Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
$'.$constructor.$layer.' = '.$params.';
|
$' . $constructor . $layer . ' = ' . $params . ';
|
||||||
```
|
```
|
||||||
|
|
||||||
[PWRTelegram](https://pwrtelegram.xyz) json-encoded version:
|
[PWRTelegram](https://pwrtelegram.xyz) json-encoded version:
|
||||||
|
|
||||||
```
|
```
|
||||||
'.$pwr_params.'
|
' . $pwr_params . '
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -182,13 +177,12 @@ Or, if you\'re into Lua:
|
|||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
'.$constructor.$layer.'='.$lua_params.'
|
' . $constructor . $layer . '=' . $lua_params . '
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
';
|
';
|
||||||
|
|
||||||
if ($hasreplymarkup) {
|
if ($hasreplymarkup) {
|
||||||
$example .= '
|
$example .= '
|
||||||
## Usage of reply_markup
|
## Usage of reply_markup
|
||||||
@ -233,7 +227,7 @@ MadelineProto supports all html entities supported by [html_entity_decode](http:
|
|||||||
';
|
';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_put_contents('constructors/'.$constructor.$layer.'.md', $header.$table.$type.$example);
|
file_put_contents('constructors/' . $constructor . $layer . '.md', $header . $table . $type . $example);
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Generating constructors index...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating constructors index...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
ksort($this->docs_constructors);
|
ksort($this->docs_constructors);
|
||||||
@ -242,16 +236,16 @@ MadelineProto supports all html entities supported by [html_entity_decode](http:
|
|||||||
$new_namespace = preg_replace('/_.*/', '', $constructor);
|
$new_namespace = preg_replace('/_.*/', '', $constructor);
|
||||||
$br = $new_namespace != $last_namespace ? '***
|
$br = $new_namespace != $last_namespace ? '***
|
||||||
<br><br>' : '';
|
<br><br>' : '';
|
||||||
$value = $br.$value;
|
$value = $br . $value;
|
||||||
$last_namespace = $new_namespace;
|
$last_namespace = $new_namespace;
|
||||||
}
|
}
|
||||||
file_put_contents('constructors/'.$this->index, '---
|
file_put_contents('constructors/' . $this->index, '---
|
||||||
title: Constructors
|
title: Constructors
|
||||||
description: List of constructors
|
description: List of constructors
|
||||||
---
|
---
|
||||||
# Constructors
|
# Constructors
|
||||||
[Back to API documentation index](..)
|
[Back to API documentation index](..)
|
||||||
|
|
||||||
'.implode('', $this->docs_constructors));
|
' . implode('', $this->docs_constructors));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\DocsBuilder;
|
namespace danog\MadelineProto\DocsBuilder;
|
||||||
|
|
||||||
trait Methods
|
trait Methods
|
||||||
@ -19,18 +19,14 @@ trait Methods
|
|||||||
$bots = json_decode(file_get_contents('https://rpc.pwrtelegram.xyz/?bot'), true)['result'];
|
$bots = json_decode(file_get_contents('https://rpc.pwrtelegram.xyz/?bot'), true)['result'];
|
||||||
$errors = json_decode(file_get_contents('https://rpc.pwrtelegram.xyz/?all'), true);
|
$errors = json_decode(file_get_contents('https://rpc.pwrtelegram.xyz/?all'), true);
|
||||||
$errors['result'] = array_merge_recursive(...$errors['result']);
|
$errors['result'] = array_merge_recursive(...$errors['result']);
|
||||||
foreach (glob('methods/'.$this->any) as $unlink) {
|
foreach (glob('methods/' . $this->any) as $unlink) {
|
||||||
unlink($unlink);
|
unlink($unlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_exists('methods')) {
|
if (file_exists('methods')) {
|
||||||
rmdir('methods');
|
rmdir('methods');
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdir('methods');
|
mkdir('methods');
|
||||||
|
|
||||||
$this->docs_methods = [];
|
$this->docs_methods = [];
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Generating methods documentation...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating methods documentation...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
foreach ($this->methods->by_id as $id => $data) {
|
foreach ($this->methods->by_id as $id => $data) {
|
||||||
$method = str_replace('.', '_', $data['method']);
|
$method = str_replace('.', '_', $data['method']);
|
||||||
@ -43,7 +39,6 @@ trait Methods
|
|||||||
if (!in_array($data, $this->types[$php_type]['methods'])) {
|
if (!in_array($data, $this->types[$php_type]['methods'])) {
|
||||||
$this->types[$php_type]['methods'][] = $data;
|
$this->types[$php_type]['methods'][] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = '';
|
$params = '';
|
||||||
foreach ($data['params'] as $param) {
|
foreach ($data['params'] as $param) {
|
||||||
if (in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
|
if (in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
|
||||||
@ -57,19 +52,15 @@ trait Methods
|
|||||||
$param['type'] = 'InputPeer';
|
$param['type'] = 'InputPeer';
|
||||||
}
|
}
|
||||||
$type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type';
|
$type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type';
|
||||||
$type_or_bare_type = (ctype_upper($this->end(explode('.', $param[$type_or_subtype]))[0]) || in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int', 'long', 'int128', 'int256', 'int512', 'int53'])) ? 'types' : 'constructors';
|
$type_or_bare_type = ctype_upper($this->end(explode('.', $param[$type_or_subtype]))[0]) || in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int', 'long', 'int128', 'int256', 'int512', 'int53']) ? 'types' : 'constructors';
|
||||||
$param[$type_or_subtype] = str_replace(['.', 'true', 'false'], ['_', 'Bool', 'Bool'], $param[$type_or_subtype]);
|
$param[$type_or_subtype] = str_replace(['.', 'true', 'false'], ['_', 'Bool', 'Bool'], $param[$type_or_subtype]);
|
||||||
|
$param[$type_or_subtype] = '[' . $this->escape($param[$type_or_subtype]) . '](../' . $type_or_bare_type . '/' . $param[$type_or_subtype] . '.md)';
|
||||||
$param[$type_or_subtype] = '['.$this->escape($param[$type_or_subtype]).'](../'.$type_or_bare_type.'/'.$param[$type_or_subtype].'.md)';
|
$params .= "'" . $param['name'] . "' => " . (isset($param['subtype']) ? '\\[' . $param[$type_or_subtype] . '\\]' : $param[$type_or_subtype]) . ', ';
|
||||||
|
|
||||||
$params .= "'".$param['name']."' => ".(isset($param['subtype']) ? '\['.$param[$type_or_subtype].'\]' : $param[$type_or_subtype]).', ';
|
|
||||||
}
|
}
|
||||||
$md_method = '['.$php_method.']('.$method.'.md)';
|
$md_method = '[' . $php_method . '](' . $method . '.md)';
|
||||||
|
$this->docs_methods[$method] = '$MadelineProto->' . $md_method . '(\\[' . $params . '\\]) === [$' . str_replace('_', '\\_', $type) . '](../types/' . $php_type . '.md)<a name="' . $method . '"></a>
|
||||||
$this->docs_methods[$method] = '$MadelineProto->'.$md_method.'(\['.$params.'\]) === [$'.str_replace('_', '\_', $type).'](../types/'.$php_type.'.md)<a name="'.$method.'"></a>
|
|
||||||
|
|
||||||
';
|
';
|
||||||
|
|
||||||
$params = '';
|
$params = '';
|
||||||
$lua_params = '';
|
$lua_params = '';
|
||||||
$pwr_params = '';
|
$pwr_params = '';
|
||||||
@ -86,7 +77,6 @@ trait Methods
|
|||||||
|----------|---------------|----------|-------------|
|
|----------|---------------|----------|-------------|
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
|
|
||||||
$hasentities = false;
|
$hasentities = false;
|
||||||
$hasreplymarkup = false;
|
$hasreplymarkup = false;
|
||||||
$hasmessage = false;
|
$hasmessage = false;
|
||||||
@ -101,30 +91,26 @@ trait Methods
|
|||||||
if ($param['name'] === 'chat_id' && $data['method'] !== 'messages.discardEncryption' && !isset($this->settings['td'])) {
|
if ($param['name'] === 'chat_id' && $data['method'] !== 'messages.discardEncryption' && !isset($this->settings['td'])) {
|
||||||
$param['type'] = 'InputPeer';
|
$param['type'] = 'InputPeer';
|
||||||
}
|
}
|
||||||
|
|
||||||
$ptype = str_replace('.', '_', $param[$type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type']);
|
$ptype = str_replace('.', '_', $param[$type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type']);
|
||||||
switch ($ptype) {
|
switch ($ptype) {
|
||||||
case 'true':
|
case 'true':
|
||||||
case 'false':
|
case 'false':
|
||||||
$ptype = 'Bool';
|
$ptype = 'Bool';
|
||||||
}
|
}
|
||||||
$type_or_bare_type = (ctype_upper($this->end(explode('.', $param[$type_or_subtype]))[0]) || in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int', 'long', 'int128', 'int256', 'int512', 'int53'])) ? 'types' : 'constructors';
|
$type_or_bare_type = ctype_upper($this->end(explode('.', $param[$type_or_subtype]))[0]) || in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int', 'long', 'int128', 'int256', 'int512', 'int53']) ? 'types' : 'constructors';
|
||||||
|
$table .= '|' . str_replace('_', '\\_', $param['name']) . '|' . (isset($param['subtype']) ? 'Array of ' : '') . '[' . str_replace('_', '\\_', $ptype) . '](../' . $type_or_bare_type . '/' . $ptype . '.md) | ' . (isset($param['pow']) || $this->constructors->find_by_predicate(lcfirst($param['type']) . 'Empty') ? 'Optional' : 'Yes') . '|';
|
||||||
$table .= '|'.str_replace('_', '\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\_', $ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || $this->constructors->find_by_predicate(lcfirst($param['type']).'Empty') ? 'Optional' : 'Yes').'|';
|
|
||||||
if (isset($this->td_descriptions['methods'][$data['method']])) {
|
if (isset($this->td_descriptions['methods'][$data['method']])) {
|
||||||
$table .= $this->td_descriptions['methods'][$data['method']]['params'][$param['name']].'|';
|
$table .= $this->td_descriptions['methods'][$data['method']]['params'][$param['name']] . '|';
|
||||||
}
|
}
|
||||||
$table .= PHP_EOL;
|
$table .= PHP_EOL;
|
||||||
|
$pptype = in_array($ptype, ['string', 'bytes']) ? "'" . $ptype . "'" : $ptype;
|
||||||
$pptype = in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype;
|
$ppptype = in_array($ptype, ['string', 'bytes']) ? '"' . $ptype . '"' : $ptype;
|
||||||
$ppptype = in_array($ptype, ['string', 'bytes']) ? '"'.$ptype.'"' : $ptype;
|
$params .= "'" . $param['name'] . "' => ";
|
||||||
|
$params .= (isset($param['subtype']) ? '[' . $pptype . ']' : $pptype) . ', ';
|
||||||
$params .= "'".$param['name']."' => ";
|
$json_params .= '"' . $param['name'] . '": ' . (isset($param['subtype']) ? '[' . $ppptype . ']' : $ppptype) . ', ';
|
||||||
$params .= (isset($param['subtype']) ? '['.$pptype.']' : $pptype).', ';
|
$pwr_params .= $param['name'] . ' - Json encoded ' . (isset($param['subtype']) ? ' array of ' . $ptype : $ptype) . "\n\n";
|
||||||
$json_params .= '"'.$param['name'].'": '.(isset($param['subtype']) ? '['.$ppptype.']' : $ppptype).', ';
|
$lua_params .= $param['name'] . '=';
|
||||||
$pwr_params .= $param['name'].' - Json encoded '.(isset($param['subtype']) ? ' array of '.$ptype : $ptype)."\n\n";
|
$lua_params .= (isset($param['subtype']) ? '{' . $pptype . '}' : $pptype) . ', ';
|
||||||
$lua_params .= $param['name'].'=';
|
|
||||||
$lua_params .= (isset($param['subtype']) ? '{'.$pptype.'}' : $pptype).', ';
|
|
||||||
if ($param['name'] === 'reply_markup') {
|
if ($param['name'] === 'reply_markup') {
|
||||||
$hasreplymarkup = true;
|
$hasreplymarkup = true;
|
||||||
}
|
}
|
||||||
@ -133,7 +119,7 @@ trait Methods
|
|||||||
}
|
}
|
||||||
if ($param['name'] === 'entities') {
|
if ($param['name'] === 'entities') {
|
||||||
$hasentities = true;
|
$hasentities = true;
|
||||||
$table .= '|parse\_mode| [string](../types/string.md) | Optional |
|
$table .= '|parse\\_mode| [string](../types/string.md) | Optional |
|
||||||
';
|
';
|
||||||
$params .= "'parse_mode' => 'string', ";
|
$params .= "'parse_mode' => 'string', ";
|
||||||
$lua_params .= "parse_mode='string', ";
|
$lua_params .= "parse_mode='string', ";
|
||||||
@ -141,19 +127,19 @@ trait Methods
|
|||||||
$pwr_params = "parse_mode - string\n";
|
$pwr_params = "parse_mode - string\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$description = isset($this->td_descriptions['methods'][$data['method']]) ? $this->td_descriptions['methods'][$data['method']]['description'] : ($data['method'].' parameters, return type and example');
|
$description = isset($this->td_descriptions['methods'][$data['method']]) ? $this->td_descriptions['methods'][$data['method']]['description'] : $data['method'] . ' parameters, return type and example';
|
||||||
$header = '---
|
$header = '---
|
||||||
title: '.$data['method'].'
|
title: ' . $data['method'] . '
|
||||||
description: '.$description.'
|
description: ' . $description . '
|
||||||
---
|
---
|
||||||
## Method: '.str_replace('_', '\_', $data['method']).'
|
## Method: ' . str_replace('_', '\\_', $data['method']) . '
|
||||||
[Back to methods index](index.md)
|
[Back to methods index](index.md)
|
||||||
|
|
||||||
|
|
||||||
';
|
';
|
||||||
if (isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']])) {
|
if (isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']])) {
|
||||||
$header .= '**'.\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']]."**\n\n\n\n\n";
|
$header .= '**' . \danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']] . "**\n\n\n\n\n";
|
||||||
file_put_contents('methods/'.$method.'.md', $header);
|
file_put_contents('methods/' . $method . '.md', $header);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($this->td) {
|
if ($this->td) {
|
||||||
@ -162,17 +148,17 @@ description: '.$description.'
|
|||||||
|
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
$header .= isset($this->td_descriptions['methods'][$data['method']]) ? $this->td_descriptions['methods'][$data['method']]['description'].PHP_EOL.PHP_EOL : '';
|
$header .= isset($this->td_descriptions['methods'][$data['method']]) ? $this->td_descriptions['methods'][$data['method']]['description'] . PHP_EOL . PHP_EOL : '';
|
||||||
$table .= '
|
$table .= '
|
||||||
|
|
||||||
';
|
';
|
||||||
$return = '### Return type: ['.str_replace('_', '\_', $type).'](../types/'.$php_type.'.md)
|
$return = '### Return type: [' . str_replace('_', '\\_', $type) . '](../types/' . $php_type . '.md)
|
||||||
|
|
||||||
';
|
';
|
||||||
$bot = !in_array($data['method'], $bots);
|
$bot = !in_array($data['method'], $bots);
|
||||||
$example = '';
|
$example = '';
|
||||||
if (!isset($this->settings['td'])) {
|
if (!isset($this->settings['td'])) {
|
||||||
$example .= '### Can bots use this method: **'.($bot ? 'YES' : 'NO')."**\n\n\n";
|
$example .= '### Can bots use this method: **' . ($bot ? 'YES' : 'NO') . "**\n\n\n";
|
||||||
if (isset($errors['result'][$data['method']])) {
|
if (isset($errors['result'][$data['method']])) {
|
||||||
$example .= '### Errors this method can return:
|
$example .= '### Errors this method can return:
|
||||||
|
|
||||||
@ -180,7 +166,7 @@ description: '.$description.'
|
|||||||
|----------|---------------|
|
|----------|---------------|
|
||||||
';
|
';
|
||||||
foreach ($errors['result'][$data['method']] as $error) {
|
foreach ($errors['result'][$data['method']] as $error) {
|
||||||
$example .= '|'.$error.'|'.$errors['human_result'][$error][0].'|'."\n";
|
$example .= '|' . $error . '|' . $errors['human_result'][$error][0] . '|' . "\n";
|
||||||
}
|
}
|
||||||
$example .= "\n\n";
|
$example .= "\n\n";
|
||||||
}
|
}
|
||||||
@ -188,46 +174,46 @@ description: '.$description.'
|
|||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$MadelineProto = new \danog\MadelineProto\API();
|
$MadelineProto = new \\danog\\MadelineProto\\API();
|
||||||
$MadelineProto->session = \'mySession.madeline\';
|
$MadelineProto->session = \'mySession.madeline\';
|
||||||
'.($bot ? 'if (isset($token)) { // Login as a bot
|
' . ($bot ? 'if (isset($token)) { // Login as a bot
|
||||||
$MadelineProto->bot_login($token);
|
$MadelineProto->bot_login($token);
|
||||||
}
|
}
|
||||||
' : '').'if (isset($number)) { // Login as a user
|
' : '') . 'if (isset($number)) { // Login as a user
|
||||||
$MadelineProto->phone_login($number);
|
$MadelineProto->phone_login($number);
|
||||||
$code = readline(\'Enter the code you received: \'); // Or do this in two separate steps in an HTTP API
|
$code = readline(\'Enter the code you received: \'); // Or do this in two separate steps in an HTTP API
|
||||||
$MadelineProto->complete_phone_login($code);
|
$MadelineProto->complete_phone_login($code);
|
||||||
}
|
}
|
||||||
|
|
||||||
$'.$type.' = $MadelineProto->'.$php_method.'(['.$params.']);
|
$' . $type . ' = $MadelineProto->' . $php_method . '([' . $params . ']);
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, if you\'re using the [PWRTelegram HTTP API](https://pwrtelegram.xyz):
|
Or, if you\'re using the [PWRTelegram HTTP API](https://pwrtelegram.xyz):
|
||||||
|
|
||||||
'.($bot ? '### As a bot:
|
' . ($bot ? '### As a bot:
|
||||||
|
|
||||||
POST/GET to `https://api.pwrtelegram.xyz/botTOKEN/madeline`
|
POST/GET to `https://api.pwrtelegram.xyz/botTOKEN/madeline`
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
* method - '.$data['method'].'
|
* method - ' . $data['method'] . '
|
||||||
* params - `{'.$json_params.'}`
|
* params - `{' . $json_params . '}`
|
||||||
|
|
||||||
' : '').'
|
' : '') . '
|
||||||
|
|
||||||
### As a user:
|
### As a user:
|
||||||
|
|
||||||
POST/GET to `https://api.pwrtelegram.xyz/userTOKEN/'.$data['method'].'`
|
POST/GET to `https://api.pwrtelegram.xyz/userTOKEN/' . $data['method'] . '`
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
'.$pwr_params.'
|
' . $pwr_params . '
|
||||||
|
|
||||||
|
|
||||||
Or, if you\'re into Lua:
|
Or, if you\'re into Lua:
|
||||||
|
|
||||||
```
|
```
|
||||||
'.$type.' = '.$data['method'].'({'.$lua_params.'})
|
' . $type . ' = ' . $data['method'] . '({' . $lua_params . '})
|
||||||
```
|
```
|
||||||
|
|
||||||
');
|
');
|
||||||
@ -244,7 +230,7 @@ You can provide bot API reply_markup objects here.
|
|||||||
$example .= '
|
$example .= '
|
||||||
## Return value
|
## Return value
|
||||||
|
|
||||||
If the length of the provided message is bigger than 4096, the message will be split in chunks and the method will be called multiple times, with the same parameters (except for the message), and an array of ['.str_replace('_', '\_', $type).'](../types/'.$php_type.'.md) will be returned instead.
|
If the length of the provided message is bigger than 4096, the message will be split in chunks and the method will be called multiple times, with the same parameters (except for the message), and an array of [' . str_replace('_', '\\_', $type) . '](../types/' . $php_type . '.md) will be returned instead.
|
||||||
|
|
||||||
|
|
||||||
';
|
';
|
||||||
@ -284,22 +270,19 @@ MadelineProto supports all html entities supported by [html_entity_decode](http:
|
|||||||
';
|
';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_put_contents('methods/'.$method.'.md', $header.$table.$return.$example);
|
file_put_contents('methods/' . $method . '.md', $header . $table . $return . $example);
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Generating methods index...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Generating methods index...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
ksort($this->docs_methods);
|
ksort($this->docs_methods);
|
||||||
$last_namespace = '';
|
$last_namespace = '';
|
||||||
foreach ($this->docs_methods as $method => &$value) {
|
foreach ($this->docs_methods as $method => &$value) {
|
||||||
$new_namespace = preg_replace('/_.*/', '', $method);
|
$new_namespace = preg_replace('/_.*/', '', $method);
|
||||||
$br = $new_namespace != $last_namespace ? '***
|
$br = $new_namespace != $last_namespace ? '***
|
||||||
<br><br>' : '';
|
<br><br>' : '';
|
||||||
$value = $br.$value;
|
$value = $br . $value;
|
||||||
$last_namespace = $new_namespace;
|
$last_namespace = $new_namespace;
|
||||||
}
|
}
|
||||||
|
file_put_contents('methods/' . $this->index, '---
|
||||||
file_put_contents('methods/'.$this->index, '---
|
|
||||||
title: Methods
|
title: Methods
|
||||||
description: List of methods
|
description: List of methods
|
||||||
---
|
---
|
||||||
@ -329,6 +312,6 @@ $MadelineProto->[get_full_info](https://docs.madelineproto.xyz/get_full_info.htm
|
|||||||
$MadelineProto->[get_self](https://docs.madelineproto.xyz/get_self.html)();
|
$MadelineProto->[get_self](https://docs.madelineproto.xyz/get_self.html)();
|
||||||
|
|
||||||
|
|
||||||
'.implode('', $this->docs_methods));
|
' . implode('', $this->docs_methods));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,19 +10,16 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class Exception extends \Exception
|
class Exception extends \Exception
|
||||||
{
|
{
|
||||||
use TL\PrettyException;
|
use TL\PrettyException;
|
||||||
public static $rollbar = true;
|
public static $rollbar = true;
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return $this->file === 'MadelineProto' ? $this->message : '\danog\MadelineProto\Exception'.($this->message !== '' ? ': ' : '').$this->message.' in '.$this->file.':'.$this->line.PHP_EOL.'Revision: '.@file_get_contents(__DIR__.'/../../../.git/refs/heads/master').PHP_EOL.'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):'.PHP_EOL.$this->getTLTrace();
|
return $this->file === 'MadelineProto' ? $this->message : '\\danog\\MadelineProto\\Exception' . ($this->message !== '' ? ': ' : '') . $this->message . ' in ' . $this->file . ':' . $this->line . PHP_EOL . 'Revision: ' . @file_get_contents(__DIR__ . '/../../../.git/refs/heads/master') . PHP_EOL . 'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):' . PHP_EOL . $this->getTLTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct($message = null, $code = 0, self $previous = null, $file = null, $line = null)
|
public function __construct($message = null, $code = 0, self $previous = null, $file = null, $line = null)
|
||||||
{
|
{
|
||||||
$this->prettify_tl();
|
$this->prettify_tl();
|
||||||
@ -36,8 +34,7 @@ class Exception extends \Exception
|
|||||||
$this->line = $line;
|
$this->line = $line;
|
||||||
}
|
}
|
||||||
parent::__construct($message, $code, $previous);
|
parent::__construct($message, $code, $previous);
|
||||||
|
\danog\MadelineProto\Logger::log([$message . ' in ' . basename($this->file) . ':' . $this->line], \danog\MadelineProto\Logger::FATAL_ERROR);
|
||||||
\danog\MadelineProto\Logger::log([$message.' in '.basename($this->file).':'.$this->line], \danog\MadelineProto\Logger::FATAL_ERROR);
|
|
||||||
if (in_array($message, ['The session is corrupted!', 'Re-executing query...', 'I had to recreate the temporary authorization key', 'This peer is not present in the internal peer database', "Couldn't get response", 'Chat forbidden', 'The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.', 'File does not exist', 'Please install this fork of phpseclib: https://github.com/danog/phpseclib'])) {
|
if (in_array($message, ['The session is corrupted!', 'Re-executing query...', 'I had to recreate the temporary authorization key', 'This peer is not present in the internal peer database', "Couldn't get response", 'Chat forbidden', 'The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.', 'File does not exist', 'Please install this fork of phpseclib: https://github.com/danog/phpseclib'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -48,7 +45,6 @@ class Exception extends \Exception
|
|||||||
\Rollbar\Rollbar::log(\Rollbar\Payload\Level::error(), $this, debug_backtrace(0));
|
\Rollbar\Rollbar::log(\Rollbar\Payload\Level::error(), $this, debug_backtrace(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ExceptionErrorHandler.
|
* ExceptionErrorHandler.
|
||||||
*
|
*
|
||||||
@ -58,9 +54,9 @@ class Exception extends \Exception
|
|||||||
{
|
{
|
||||||
// If error is suppressed with @, don't throw an exception
|
// If error is suppressed with @, don't throw an exception
|
||||||
if (error_reporting() === 0) {
|
if (error_reporting() === 0) {
|
||||||
return true; // return true to continue through the others error handlers
|
return true;
|
||||||
|
// return true to continue through the others error handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new self($errstr, $errno, null, $errfile, $errline);
|
throw new self($errstr, $errno, null, $errfile, $errline);
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -12,74 +13,14 @@ If not, see <http://www.gnu.org/licenses/>.
|
|||||||
/*
|
/*
|
||||||
* Logger class
|
* Logger class
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class Logger
|
class Logger
|
||||||
{
|
{
|
||||||
const foreground = [
|
const foreground = ['default' => 39, 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'light_gray' => 37, 'dark_gray' => 90, 'light_red' => 91, 'light_green' => 92, 'light_yellow' => 93, 'light_blue' => 94, 'light_magenta' => 95, 'light_cyan' => 96, 'white' => 97];
|
||||||
'default' => 39,
|
const background = ['default' => 49, 'black' => 40, 'red' => 41, 'magenta' => 45, 'yellow' => 43, 'green' => 42, 'blue' => 44, 'cyan' => 46, 'light_gray' => 47, 'dark_gray' => 100, 'light_red' => 101, 'light_green' => 102, 'light_yellow' => 103, 'light_blue' => 104, 'light_magenta' => 105, 'light_cyan' => 106, 'white' => 107];
|
||||||
|
const set = ['bold' => 1, 'dim' => 2, 'underlined' => 3, 'blink' => 4, 'reverse' => 5, 'hidden' => 6];
|
||||||
'black' => 30,
|
const reset = ['all' => 0, 'bold' => 21, 'dim' => 22, 'underlined' => 24, 'blink' => 25, 'reverse' => 26, 'hidden' => 28];
|
||||||
'red' => 31,
|
|
||||||
'green' => 32,
|
|
||||||
'yellow' => 33,
|
|
||||||
'blue' => 34,
|
|
||||||
'magenta' => 35,
|
|
||||||
'cyan' => 36,
|
|
||||||
'light_gray' => 37,
|
|
||||||
|
|
||||||
'dark_gray' => 90,
|
|
||||||
'light_red' => 91,
|
|
||||||
'light_green' => 92,
|
|
||||||
'light_yellow' => 93,
|
|
||||||
'light_blue' => 94,
|
|
||||||
'light_magenta' => 95,
|
|
||||||
'light_cyan' => 96,
|
|
||||||
'white' => 97,
|
|
||||||
];
|
|
||||||
|
|
||||||
const background = [
|
|
||||||
'default' => 49,
|
|
||||||
|
|
||||||
'black' => 40,
|
|
||||||
'red' => 41,
|
|
||||||
'magenta' => 45,
|
|
||||||
'yellow' => 43,
|
|
||||||
'green' => 42,
|
|
||||||
'blue' => 44,
|
|
||||||
'cyan' => 46,
|
|
||||||
'light_gray' => 47,
|
|
||||||
|
|
||||||
'dark_gray' => 100,
|
|
||||||
'light_red' => 101,
|
|
||||||
'light_green' => 102,
|
|
||||||
'light_yellow' => 103,
|
|
||||||
'light_blue' => 104,
|
|
||||||
'light_magenta' => 105,
|
|
||||||
'light_cyan' => 106,
|
|
||||||
'white' => 107,
|
|
||||||
];
|
|
||||||
|
|
||||||
const set = [
|
|
||||||
'bold' => 1,
|
|
||||||
'dim' => 2,
|
|
||||||
'underlined' => 3,
|
|
||||||
'blink' => 4,
|
|
||||||
'reverse' => 5,
|
|
||||||
'hidden' => 6,
|
|
||||||
];
|
|
||||||
|
|
||||||
const reset = [
|
|
||||||
'all' => 0,
|
|
||||||
'bold' => 21,
|
|
||||||
'dim' => 22,
|
|
||||||
'underlined' => 24,
|
|
||||||
'blink' => 25,
|
|
||||||
'reverse' => 26,
|
|
||||||
'hidden' => 28,
|
|
||||||
];
|
|
||||||
|
|
||||||
public static $storage = [];
|
public static $storage = [];
|
||||||
public static $mode = 1;
|
public static $mode = 1;
|
||||||
public static $optional = null;
|
public static $optional = null;
|
||||||
@ -90,32 +31,27 @@ class Logger
|
|||||||
public static $bigint = true;
|
public static $bigint = true;
|
||||||
public static $colors = [];
|
public static $colors = [];
|
||||||
public static $isatty = false;
|
public static $isatty = false;
|
||||||
|
|
||||||
const ULTRA_VERBOSE = 5;
|
const ULTRA_VERBOSE = 5;
|
||||||
const VERBOSE = 4;
|
const VERBOSE = 4;
|
||||||
const NOTICE = 3;
|
const NOTICE = 3;
|
||||||
const WARNING = 2;
|
const WARNING = 2;
|
||||||
const ERROR = 1;
|
const ERROR = 1;
|
||||||
const FATAL_ERROR = 0;
|
const FATAL_ERROR = 0;
|
||||||
|
|
||||||
public static function class_exists()
|
public static function class_exists()
|
||||||
{
|
{
|
||||||
self::$has_thread = class_exists('\Thread') && method_exists('\Thread', 'getCurrentThread');
|
self::$has_thread = class_exists('\\Thread') && method_exists('\\Thread', 'getCurrentThread');
|
||||||
self::$BIG_ENDIAN = (pack('L', 1) === pack('N', 1));
|
self::$BIG_ENDIAN = pack('L', 1) === pack('N', 1);
|
||||||
self::$bigint = PHP_INT_SIZE < 8;
|
self::$bigint = PHP_INT_SIZE < 8;
|
||||||
|
preg_match('/const V = (\\d+);/', @file_get_contents('https://raw.githubusercontent.com/danog/MadelineProto/master/src/danog/MadelineProto/MTProto.php'), $matches);
|
||||||
preg_match('/const V = (\d+);/', @file_get_contents('https://raw.githubusercontent.com/danog/MadelineProto/master/src/danog/MadelineProto/MTProto.php'), $matches);
|
|
||||||
|
|
||||||
if (isset($matches[1]) && \danog\MadelineProto\MTProto::V < (int) $matches[1]) {
|
if (isset($matches[1]) && \danog\MadelineProto\MTProto::V < (int) $matches[1]) {
|
||||||
throw new \danog\MadelineProto\Exception(hex2bin(\danog\MadelineProto\Lang::$current_lang['v_error']), 0, null, 'MadelineProto', 1);
|
throw new \danog\MadelineProto\Exception(hex2bin(\danog\MadelineProto\Lang::$current_lang['v_error']), 0, null, 'MadelineProto', 1);
|
||||||
}
|
}
|
||||||
if (class_exists('\danog\MadelineProto\VoIP')) {
|
if (class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
if (!defined('\danog\MadelineProto\VoIP::PHP_LIBTGVOIP_VERSION') || \danog\MadelineProto\VoIP::PHP_LIBTGVOIP_VERSION !== '1.1.2') {
|
if (!defined('\\danog\\MadelineProto\\VoIP::PHP_LIBTGVOIP_VERSION') || \danog\MadelineProto\VoIP::PHP_LIBTGVOIP_VERSION !== '1.1.2') {
|
||||||
throw new \danog\MadelineProto\Exception(hex2bin(\danog\MadelineProto\Lang::$current_lang['v_tgerror']), 0, null, 'MadelineProto', 1);
|
throw new \danog\MadelineProto\Exception(hex2bin(\danog\MadelineProto\Lang::$current_lang['v_tgerror']), 0, null, 'MadelineProto', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
\Threaded::extend('\danog\MadelineProto\VoIP');
|
\Threaded::extend('\\danog\\MadelineProto\\VoIP');
|
||||||
} catch (\RuntimeException $e) {
|
} catch (\RuntimeException $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,13 +61,11 @@ class Logger
|
|||||||
self::$colors[self::WARNING] = implode(';', [self::foreground['white'], self::set['dim'], self::background['red']]);
|
self::$colors[self::WARNING] = implode(';', [self::foreground['white'], self::set['dim'], self::background['red']]);
|
||||||
self::$colors[self::ERROR] = implode(';', [self::foreground['white'], self::set['bold'], self::background['red']]);
|
self::$colors[self::ERROR] = implode(';', [self::foreground['white'], self::set['bold'], self::background['red']]);
|
||||||
self::$colors[self::FATAL_ERROR] = implode(';', [self::foreground['red'], self::set['bold'], self::background['light_gray']]);
|
self::$colors[self::FATAL_ERROR] = implode(';', [self::foreground['red'], self::set['bold'], self::background['light_gray']]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self::$isatty = defined('STDOUT') && function_exists('posix_isatty') && posix_isatty(STDOUT);
|
self::$isatty = defined('STDOUT') && function_exists('posix_isatty') && posix_isatty(STDOUT);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor function
|
* Constructor function
|
||||||
* Accepts various logger modes:
|
* Accepts various logger modes:
|
||||||
@ -149,11 +83,10 @@ class Logger
|
|||||||
}
|
}
|
||||||
self::$mode = $mode;
|
self::$mode = $mode;
|
||||||
self::$optional = $optional;
|
self::$optional = $optional;
|
||||||
self::$prefix = $prefix === '' ? '' : ', '.$prefix;
|
self::$prefix = $prefix === '' ? '' : ', ' . $prefix;
|
||||||
self::$level = $level;
|
self::$level = $level;
|
||||||
self::class_exists();
|
self::class_exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function log($params, $level = self::NOTICE)
|
public static function log($params, $level = self::NOTICE)
|
||||||
{
|
{
|
||||||
if (self::$mode === 4) {
|
if (self::$mode === 4) {
|
||||||
@ -162,7 +95,6 @@ class Logger
|
|||||||
if ($level > self::$level) {
|
if ($level > self::$level) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$prefix = self::$prefix;
|
$prefix = self::$prefix;
|
||||||
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
||||||
$prefix .= ' (t)';
|
$prefix .= ' (t)';
|
||||||
@ -171,16 +103,16 @@ class Logger
|
|||||||
if (!is_string($param)) {
|
if (!is_string($param)) {
|
||||||
$param = json_encode($param, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
$param = json_encode($param, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
}
|
}
|
||||||
$param = str_pad(basename(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)[0]['file'], '.php').$prefix.': ', 16 + strlen($prefix))."\t".$param;
|
$param = str_pad(basename(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)[0]['file'], '.php') . $prefix . ': ', 16 + strlen($prefix)) . "\t" . $param;
|
||||||
switch (self::$mode) {
|
switch (self::$mode) {
|
||||||
case 1:
|
case 1:
|
||||||
error_log($param);
|
error_log($param);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
error_log($param.PHP_EOL, 3, self::$optional);
|
error_log($param . PHP_EOL, 3, self::$optional);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
echo self::$isatty ? "\033[".self::$colors[$level].'m'.$param."\033[0m".PHP_EOL : $param.PHP_EOL;
|
echo self::$isatty ? "\33[" . self::$colors[$level] . 'm' . $param . "\33[0m" . PHP_EOL : $param . PHP_EOL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class Lua
|
class Lua
|
||||||
@ -18,7 +18,6 @@ class Lua
|
|||||||
public $MadelineProto;
|
public $MadelineProto;
|
||||||
protected $Lua;
|
protected $Lua;
|
||||||
protected $script;
|
protected $script;
|
||||||
|
|
||||||
public function __magic_construct($script, $MadelineProto)
|
public function __magic_construct($script, $MadelineProto)
|
||||||
{
|
{
|
||||||
if (!file_exists($script)) {
|
if (!file_exists($script)) {
|
||||||
@ -29,12 +28,10 @@ class Lua
|
|||||||
$this->script = $script;
|
$this->script = $script;
|
||||||
$this->__wakeup();
|
$this->__wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['MadelineProto', 'script'];
|
return ['MadelineProto', 'script'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __wakeup()
|
public function __wakeup()
|
||||||
{
|
{
|
||||||
$this->Lua = new \Lua($this->script);
|
$this->Lua = new \Lua($this->script);
|
||||||
@ -68,7 +65,6 @@ class Lua
|
|||||||
$this->MadelineProto->{$namespace}->lua = true;
|
$this->MadelineProto->{$namespace}->lua = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
@ -79,10 +75,8 @@ class Lua
|
|||||||
if (is_callable($cb)) {
|
if (is_callable($cb)) {
|
||||||
$cb($this->MadelineProto->mtproto_to_td($result), $cb_extra);
|
$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, ['datacenter' => $this->MadelineProto->API->datacenter->curdc]);
|
$result = $this->MadelineProto->API->method_call($params['_'], $params, ['datacenter' => $this->MadelineProto->API->datacenter->curdc]);
|
||||||
@ -90,15 +84,12 @@ class Lua
|
|||||||
$cb($result, $cb_extra);
|
$cb($result, $cb_extra);
|
||||||
}
|
}
|
||||||
self::convert_objects($result);
|
self::convert_objects($result);
|
||||||
|
|
||||||
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)) {
|
if (!is_array($value)) {
|
||||||
@ -110,29 +101,23 @@ class Lua
|
|||||||
}, array_flip($array)));
|
}, array_flip($array)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function is_sequential(array $arr)
|
private function is_sequential(array $arr)
|
||||||
{
|
{
|
||||||
if ([] === $arr) {
|
if ([] === $arr) {
|
||||||
return false;
|
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)
|
public function __get($name)
|
||||||
{
|
{
|
||||||
if ($name === 'API') {
|
if ($name === 'API') {
|
||||||
return $this->MadelineProto->API;
|
return $this->MadelineProto->API;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->Lua->{$name};
|
return $this->Lua->{$name};
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __call($name, $params)
|
public function __call($name, $params)
|
||||||
{
|
{
|
||||||
self::convert_objects($params);
|
self::convert_objects($params);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return $this->Lua->{$name}(...$params);
|
return $this->Lua->{$name}(...$params);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
@ -151,16 +136,14 @@ class Lua
|
|||||||
return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
|
return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __set($name, $value)
|
public function __set($name, $value)
|
||||||
{
|
{
|
||||||
return $this->Lua->{$name} = $value;
|
return $this->Lua->{$name} = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function convert_objects(&$data)
|
public static function convert_objects(&$data)
|
||||||
{
|
{
|
||||||
array_walk_recursive($data, function (&$value, $key) {
|
array_walk_recursive($data, function (&$value, $key) {
|
||||||
if (is_object($value) && !($value instanceof \phpseclib\Math\BigInteger)) {
|
if (is_object($value) && !$value instanceof \phpseclib\Math\BigInteger) {
|
||||||
$newval = [];
|
$newval = [];
|
||||||
foreach (get_class_methods($value) as $name) {
|
foreach (get_class_methods($value) as $name) {
|
||||||
$newval[$name] = [$value, $name];
|
$newval[$name] = [$value, $name];
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,28 +21,25 @@ trait AckHandler
|
|||||||
{
|
{
|
||||||
// The server acknowledges that it received my message
|
// The server acknowledges that it received my message
|
||||||
if (!isset($this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id])) {
|
if (!isset($this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id])) {
|
||||||
\danog\MadelineProto\Logger::log(["WARNING: Couldn't find message id ".$message_id.' in the array of outgoing messages. Maybe try to increase its size?'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(["WARNING: Couldn't find message id " . $message_id . ' in the array of outgoing messages. Maybe try to increase its size?'], \danog\MadelineProto\Logger::WARNING);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id]['ack'] = true;
|
return $this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id]['ack'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ack_incoming_message_id($message_id, $datacenter)
|
public function ack_incoming_message_id($message_id, $datacenter)
|
||||||
{
|
{
|
||||||
// I let the server know that I received its message
|
// I let the server know that I received its message
|
||||||
if (!isset($this->datacenter->sockets[$datacenter]->incoming_messages[$message_id])) {
|
if (!isset($this->datacenter->sockets[$datacenter]->incoming_messages[$message_id])) {
|
||||||
\danog\MadelineProto\Logger::log(["WARNING: Couldn't find message id ".$message_id.' in the array of incomgoing messages. Maybe try to increase its size?'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(["WARNING: Couldn't find message id " . $message_id . ' in the array of incomgoing messages. Maybe try to increase its size?'], \danog\MadelineProto\Logger::WARNING);
|
||||||
//throw new \danog\MadelineProto\Exception("Couldn't find message id ".$message_id.' in the array of incoming message ids. Maybe try to increase its size?');
|
//throw new \danog\MadelineProto\Exception("Couldn't find message id ".$message_id.' in the array of incoming message ids. Maybe try to increase its size?');
|
||||||
}
|
}
|
||||||
if ($this->datacenter->sockets[$datacenter]->temp_auth_key['id'] === null || $this->datacenter->sockets[$datacenter]->temp_auth_key['id'] === "\0\0\0\0\0\0\0\0") { // || (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['ack']) && $this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['ack'])) {
|
if ($this->datacenter->sockets[$datacenter]->temp_auth_key['id'] === null || $this->datacenter->sockets[$datacenter]->temp_auth_key['id'] === "\0\0\0\0\0\0\0\0") {
|
||||||
|
// || (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['ack']) && $this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['ack'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->datacenter->sockets[$datacenter]->ack_queue[] = $message_id;
|
$this->datacenter->sockets[$datacenter]->ack_queue[] = $message_id;
|
||||||
//$this->object_call('msgs_ack', ['msg_ids' => [$message_id]], ['datacenter' => $datacenter]);
|
//$this->object_call('msgs_ack', ['msg_ids' => [$message_id]], ['datacenter' => $datacenter]);
|
||||||
|
return true;
|
||||||
return true; //$this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['ack'] = true;
|
//$this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['ack'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,7 +26,6 @@ trait AuthKeyHandler
|
|||||||
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++) {
|
||||||
try {
|
try {
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['req_pq']], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['req_pq']], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Make pq request, DH exchange initiation.
|
* Make pq request, DH exchange initiation.
|
||||||
@ -45,13 +44,7 @@ trait AuthKeyHandler
|
|||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
$nonce = $this->random(16);
|
$nonce = $this->random(16);
|
||||||
$ResPQ = $this->method_call($req_pq,
|
$ResPQ = $this->method_call($req_pq, ['nonce' => $nonce], ['datacenter' => $datacenter]);
|
||||||
[
|
|
||||||
'nonce' => $nonce,
|
|
||||||
],
|
|
||||||
['datacenter' => $datacenter]
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check if the client's nonce and the server's nonce are the same
|
* Check if the client's nonce and the server's nonce are the same
|
||||||
@ -59,24 +52,20 @@ trait AuthKeyHandler
|
|||||||
if ($ResPQ['nonce'] !== $nonce) {
|
if ($ResPQ['nonce'] !== $nonce) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong nonce');
|
throw new \danog\MadelineProto\SecurityException('wrong nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Find our key in the server_public_key_fingerprints vector
|
* Find our key in the server_public_key_fingerprints vector
|
||||||
*/
|
*/
|
||||||
|
|
||||||
foreach ($this->rsa_keys as $curkey) {
|
foreach ($this->rsa_keys as $curkey) {
|
||||||
if (in_array($curkey->fp, $ResPQ['server_public_key_fingerprints'])) {
|
if (in_array($curkey->fp, $ResPQ['server_public_key_fingerprints'])) {
|
||||||
$key = $curkey;
|
$key = $curkey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($key)) {
|
if (!isset($key)) {
|
||||||
throw new \danog\MadelineProto\SecurityException("Couldn't find any of our keys in the server_public_key_fingerprints vector.");
|
throw new \danog\MadelineProto\SecurityException("Couldn't find any of our keys in the server_public_key_fingerprints vector.");
|
||||||
}
|
}
|
||||||
$pq_bytes = $ResPQ['pq'];
|
$pq_bytes = $ResPQ['pq'];
|
||||||
$server_nonce = $ResPQ['server_nonce'];
|
$server_nonce = $ResPQ['server_nonce'];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Compute p and q
|
* Compute p and q
|
||||||
@ -87,42 +76,27 @@ trait AuthKeyHandler
|
|||||||
if ($p->compare($q) > 0) {
|
if ($p->compare($q) > 0) {
|
||||||
list($p, $q) = [$q, $p];
|
list($p, $q) = [$q, $p];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$pq->equals($p->multiply($q))) {
|
if (!$pq->equals($p->multiply($q))) {
|
||||||
throw new \danog\MadelineProto\SecurityException("couldn't compute p and q. Original pq: $pq, computed p: $p, computed q: $q, computed pq: ".$p->multiply($q));
|
throw new \danog\MadelineProto\SecurityException("couldn't compute p and q. Original pq: {$pq}, computed p: {$p}, computed q: {$q}, computed pq: " . $p->multiply($q));
|
||||||
}
|
}
|
||||||
|
\danog\MadelineProto\Logger::log(['Factorization ' . $pq . ' = ' . $p . ' * ' . $q], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
\danog\MadelineProto\Logger::log(['Factorization '.$pq.' = '.$p.' * '.$q], \danog\MadelineProto\Logger::VERBOSE);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Serialize object for req_DH_params
|
* Serialize object for req_DH_params
|
||||||
*/
|
*/
|
||||||
$p_bytes = $p->toBytes();
|
$p_bytes = $p->toBytes();
|
||||||
$q_bytes = $q->toBytes();
|
$q_bytes = $q->toBytes();
|
||||||
|
|
||||||
$new_nonce = $this->random(32);
|
$new_nonce = $this->random(32);
|
||||||
|
$data_unserialized = ['pq' => $pq_bytes, 'p' => $p_bytes, 'q' => $q_bytes, 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'new_nonce' => $new_nonce, 'expires_in' => $expires_in];
|
||||||
$data_unserialized = [
|
$p_q_inner_data = $this->serialize_object(['type' => 'p_q_inner_data' . ($expires_in < 0 ? '' : '_temp')], $data_unserialized, 'p_q_inner_data');
|
||||||
'pq' => $pq_bytes,
|
|
||||||
'p' => $p_bytes,
|
|
||||||
'q' => $q_bytes,
|
|
||||||
'nonce' => $nonce,
|
|
||||||
'server_nonce' => $server_nonce,
|
|
||||||
'new_nonce' => $new_nonce,
|
|
||||||
'expires_in' => $expires_in,
|
|
||||||
];
|
|
||||||
$p_q_inner_data = $this->serialize_object(['type' => 'p_q_inner_data'.($expires_in < 0 ? '' : '_temp')], $data_unserialized, 'p_q_inner_data');
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Encrypt serialized object
|
* Encrypt serialized object
|
||||||
*/
|
*/
|
||||||
$sha_digest = sha1($p_q_inner_data, true);
|
$sha_digest = sha1($p_q_inner_data, true);
|
||||||
$random_bytes = $this->random(255 - strlen($p_q_inner_data) - strlen($sha_digest));
|
$random_bytes = $this->random(255 - strlen($p_q_inner_data) - strlen($sha_digest));
|
||||||
$to_encrypt = $sha_digest.$p_q_inner_data.$random_bytes;
|
$to_encrypt = $sha_digest . $p_q_inner_data . $random_bytes;
|
||||||
$encrypted_data = $key->encrypt($to_encrypt);
|
$encrypted_data = $key->encrypt($to_encrypt);
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Starting Diffie Hellman key exchange'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Starting Diffie Hellman key exchange'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
@ -144,19 +118,7 @@ trait AuthKeyHandler
|
|||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
//
|
//
|
||||||
$server_dh_params = $this->method_call('req_DH_params',
|
$server_dh_params = $this->method_call('req_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'p' => $p_bytes, 'q' => $q_bytes, 'public_key_fingerprint' => $key->fp, 'encrypted_data' => $encrypted_data], ['datacenter' => $datacenter]);
|
||||||
[
|
|
||||||
'nonce' => $nonce,
|
|
||||||
'server_nonce' => $server_nonce,
|
|
||||||
'p' => $p_bytes,
|
|
||||||
'q' => $q_bytes,
|
|
||||||
'public_key_fingerprint' => $key->fp,
|
|
||||||
'encrypted_data' => $encrypted_data,
|
|
||||||
],
|
|
||||||
['datacenter' => $datacenter]
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check if the client's nonce and the server's nonce are the same
|
* Check if the client's nonce and the server's nonce are the same
|
||||||
@ -164,7 +126,6 @@ trait AuthKeyHandler
|
|||||||
if ($nonce != $server_dh_params['nonce']) {
|
if ($nonce != $server_dh_params['nonce']) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong nonce.');
|
throw new \danog\MadelineProto\SecurityException('wrong nonce.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check if server_nonce and new server_nonce are the same
|
* Check if server_nonce and new server_nonce are the same
|
||||||
@ -172,7 +133,6 @@ trait AuthKeyHandler
|
|||||||
if ($server_nonce != $server_dh_params['server_nonce']) {
|
if ($server_nonce != $server_dh_params['server_nonce']) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong server nonce.');
|
throw new \danog\MadelineProto\SecurityException('wrong server nonce.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check valid new nonce hash if return from server
|
* Check valid new nonce hash if return from server
|
||||||
@ -181,24 +141,20 @@ trait AuthKeyHandler
|
|||||||
if (isset($server_dh_params['new_nonce_hash']) && substr(sha1($new_nonce), -32) != $server_dh_params['new_nonce_hash']) {
|
if (isset($server_dh_params['new_nonce_hash']) && substr(sha1($new_nonce), -32) != $server_dh_params['new_nonce_hash']) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong new nonce hash.');
|
throw new \danog\MadelineProto\SecurityException('wrong new nonce hash.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Get key, iv and decrypt answer
|
* Get key, iv and decrypt answer
|
||||||
*/
|
*/
|
||||||
$encrypted_answer = $server_dh_params['encrypted_answer'];
|
$encrypted_answer = $server_dh_params['encrypted_answer'];
|
||||||
|
$tmp_aes_key = sha1($new_nonce . $server_nonce, true) . substr(sha1($server_nonce . $new_nonce, true), 0, 12);
|
||||||
$tmp_aes_key = sha1($new_nonce.$server_nonce, true).substr(sha1($server_nonce.$new_nonce, true), 0, 12);
|
$tmp_aes_iv = substr(sha1($server_nonce . $new_nonce, true), 12, 8) . sha1($new_nonce . $new_nonce, true) . substr($new_nonce, 0, 4);
|
||||||
$tmp_aes_iv = substr(sha1($server_nonce.$new_nonce, true), 12, 8).sha1($new_nonce.$new_nonce, true).substr($new_nonce, 0, 4);
|
|
||||||
$answer_with_hash = $this->ige_decrypt($encrypted_answer, $tmp_aes_key, $tmp_aes_iv);
|
$answer_with_hash = $this->ige_decrypt($encrypted_answer, $tmp_aes_key, $tmp_aes_iv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Separate answer and hash
|
* Separate answer and hash
|
||||||
*/
|
*/
|
||||||
$answer_hash = substr($answer_with_hash, 0, 20);
|
$answer_hash = substr($answer_with_hash, 0, 20);
|
||||||
$answer = substr($answer_with_hash, 20);
|
$answer = substr($answer_with_hash, 20);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Deserialize answer
|
* Deserialize answer
|
||||||
@ -212,7 +168,6 @@ trait AuthKeyHandler
|
|||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
$server_DH_inner_data = $this->deserialize($answer, ['type' => '']);
|
$server_DH_inner_data = $this->deserialize($answer, ['type' => '']);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Do some checks
|
* Do some checks
|
||||||
@ -221,54 +176,41 @@ trait AuthKeyHandler
|
|||||||
if (sha1(substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
|
if (sha1(substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
|
||||||
throw new \danog\MadelineProto\SecurityException('answer_hash mismatch.');
|
throw new \danog\MadelineProto\SecurityException('answer_hash mismatch.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($nonce != $server_DH_inner_data['nonce']) {
|
if ($nonce != $server_DH_inner_data['nonce']) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong nonce');
|
throw new \danog\MadelineProto\SecurityException('wrong nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($server_nonce != $server_DH_inner_data['server_nonce']) {
|
if ($server_nonce != $server_DH_inner_data['server_nonce']) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong server nonce');
|
throw new \danog\MadelineProto\SecurityException('wrong server nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
$g = new \phpseclib\Math\BigInteger($server_DH_inner_data['g']);
|
$g = new \phpseclib\Math\BigInteger($server_DH_inner_data['g']);
|
||||||
$g_a = new \phpseclib\Math\BigInteger($server_DH_inner_data['g_a'], 256);
|
$g_a = new \phpseclib\Math\BigInteger($server_DH_inner_data['g_a'], 256);
|
||||||
$dh_prime = new \phpseclib\Math\BigInteger($server_DH_inner_data['dh_prime'], 256);
|
$dh_prime = new \phpseclib\Math\BigInteger($server_DH_inner_data['dh_prime'], 256);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Time delta
|
* Time delta
|
||||||
*/
|
*/
|
||||||
$server_time = $server_DH_inner_data['server_time'];
|
$server_time = $server_DH_inner_data['server_time'];
|
||||||
$this->datacenter->sockets[$datacenter]->time_delta = $server_time - time();
|
$this->datacenter->sockets[$datacenter]->time_delta = $server_time - time();
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([sprintf('Server-client time delta = %.1f s', $this->datacenter->sockets[$datacenter]->time_delta)], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf('Server-client time delta = %.1f s', $this->datacenter->sockets[$datacenter]->time_delta)], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
$this->check_p_g($dh_prime, $g);
|
$this->check_p_g($dh_prime, $g);
|
||||||
$this->check_G($g_a, $dh_prime);
|
$this->check_G($g_a, $dh_prime);
|
||||||
|
|
||||||
for ($retry_id = 0; $retry_id <= $this->settings['max_tries']['authorization']; $retry_id++) {
|
for ($retry_id = 0; $retry_id <= $this->settings['max_tries']['authorization']; $retry_id++) {
|
||||||
\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);
|
||||||
\danog\MadelineProto\Logger::log(['Generating g_b...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Generating g_b...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$g_b = $g->powMod($b, $dh_prime);
|
$g_b = $g->powMod($b, $dh_prime);
|
||||||
$this->check_G($g_b, $dh_prime);
|
$this->check_G($g_b, $dh_prime);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check validity of g_b
|
* Check validity of g_b
|
||||||
* 1 < g_b < dh_prime - 1
|
* 1 < g_b < dh_prime - 1
|
||||||
*/
|
*/
|
||||||
\danog\MadelineProto\Logger::log(['Executing g_b check...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Executing g_b check...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
if ($g_b->compare($this->one) <= 0 // 1 < g_b or g_b > 1 or ! g_b <= 1
|
if ($g_b->compare($this->one) <= 0 || $g_b->compare($dh_prime->subtract($this->one)) >= 0) {
|
||||||
|| $g_b->compare($dh_prime->subtract($this->one)) >= 0 // g_b < dh_prime - 1 or ! g_b >= dh_prime - 1
|
|
||||||
) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException('g_b is invalid (1 < g_b < dh_prime - 1 is false).');
|
throw new \danog\MadelineProto\SecurityException('g_b is invalid (1 < g_b < dh_prime - 1 is false).');
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Preparing client_DH_inner_data...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Preparing client_DH_inner_data...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
$g_b_str = $g_b->toBytes();
|
$g_b_str = $g_b->toBytes();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* serialize client_DH_inner_data
|
* serialize client_DH_inner_data
|
||||||
@ -280,24 +222,14 @@ trait AuthKeyHandler
|
|||||||
* string $g_b : g^b mod dh_prime
|
* string $g_b : g^b mod dh_prime
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
$data = $this->serialize_object(
|
$data = $this->serialize_object(['type' => 'client_DH_inner_data'], ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str], 'client_DH_inner_data');
|
||||||
['type' => 'client_DH_inner_data'],
|
|
||||||
[
|
|
||||||
'nonce' => $nonce,
|
|
||||||
'server_nonce' => $server_nonce,
|
|
||||||
'retry_id' => $retry_id,
|
|
||||||
'g_b' => $g_b_str,
|
|
||||||
], 'client_DH_inner_data'
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* encrypt client_DH_inner_data
|
* encrypt client_DH_inner_data
|
||||||
*/
|
*/
|
||||||
$data_with_sha = sha1($data, true).$data;
|
$data_with_sha = sha1($data, true) . $data;
|
||||||
$data_with_sha_padded = $data_with_sha.$this->random($this->posmod(-strlen($data_with_sha), 16));
|
$data_with_sha_padded = $data_with_sha . $this->random($this->posmod(-strlen($data_with_sha), 16));
|
||||||
$encrypted_data = $this->ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
|
$encrypted_data = $this->ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Executing set_client_DH_params...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Executing set_client_DH_params...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
@ -316,17 +248,7 @@ trait AuthKeyHandler
|
|||||||
* int128 $new_nonce_hash2 : Return this value if server responds with dh_gen_fail
|
* int128 $new_nonce_hash2 : Return this value if server responds with dh_gen_fail
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
$Set_client_DH_params_answer = $this->method_call(
|
$Set_client_DH_params_answer = $this->method_call('set_client_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'encrypted_data' => $encrypted_data], ['datacenter' => $datacenter]);
|
||||||
'set_client_DH_params',
|
|
||||||
[
|
|
||||||
'nonce' => $nonce,
|
|
||||||
'server_nonce' => $server_nonce,
|
|
||||||
'encrypted_data' => $encrypted_data,
|
|
||||||
],
|
|
||||||
['datacenter' => $datacenter]
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Generate auth_key
|
* Generate auth_key
|
||||||
@ -336,10 +258,9 @@ trait AuthKeyHandler
|
|||||||
$auth_key_str = $auth_key->toBytes();
|
$auth_key_str = $auth_key->toBytes();
|
||||||
$auth_key_sha = sha1($auth_key_str, true);
|
$auth_key_sha = sha1($auth_key_str, true);
|
||||||
$auth_key_aux_hash = substr($auth_key_sha, 0, 8);
|
$auth_key_aux_hash = substr($auth_key_sha, 0, 8);
|
||||||
$new_nonce_hash1 = substr(sha1($new_nonce.chr(1).$auth_key_aux_hash, true), -16);
|
$new_nonce_hash1 = substr(sha1($new_nonce . chr(1) . $auth_key_aux_hash, true), -16);
|
||||||
$new_nonce_hash2 = substr(sha1($new_nonce.chr(2).$auth_key_aux_hash, true), -16);
|
$new_nonce_hash2 = substr(sha1($new_nonce . chr(2) . $auth_key_aux_hash, true), -16);
|
||||||
$new_nonce_hash3 = substr(sha1($new_nonce.chr(3).$auth_key_aux_hash, true), -16);
|
$new_nonce_hash3 = substr(sha1($new_nonce . chr(3) . $auth_key_aux_hash, true), -16);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check if the client's nonce and the server's nonce are the same
|
* Check if the client's nonce and the server's nonce are the same
|
||||||
@ -347,7 +268,6 @@ trait AuthKeyHandler
|
|||||||
if ($Set_client_DH_params_answer['nonce'] != $nonce) {
|
if ($Set_client_DH_params_answer['nonce'] != $nonce) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong nonce.');
|
throw new \danog\MadelineProto\SecurityException('wrong nonce.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check if server_nonce and new server_nonce are the same
|
* Check if server_nonce and new server_nonce are the same
|
||||||
@ -355,7 +275,6 @@ trait AuthKeyHandler
|
|||||||
if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
|
if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong server nonce');
|
throw new \danog\MadelineProto\SecurityException('wrong server nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check Set_client_DH_params_answer type
|
* Check Set_client_DH_params_answer type
|
||||||
@ -365,22 +284,17 @@ trait AuthKeyHandler
|
|||||||
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash1');
|
throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash1');
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Diffie Hellman key exchange processed successfully!'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Diffie Hellman key exchange processed successfully!'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
$res_authorization['server_salt'] = substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0);
|
$res_authorization['server_salt'] = substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0);
|
||||||
$res_authorization['auth_key'] = $auth_key_str;
|
$res_authorization['auth_key'] = $auth_key_str;
|
||||||
$res_authorization['id'] = substr($auth_key_sha, -8);
|
$res_authorization['id'] = substr($auth_key_sha, -8);
|
||||||
$res_authorization['connection_inited'] = false;
|
$res_authorization['connection_inited'] = false;
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Auth key generated'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Auth key generated'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return $res_authorization;
|
return $res_authorization;
|
||||||
case 'dh_gen_retry':
|
case 'dh_gen_retry':
|
||||||
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash_2');
|
throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash_2');
|
||||||
}
|
}
|
||||||
|
|
||||||
//repeat foreach
|
//repeat foreach
|
||||||
\danog\MadelineProto\Logger::log(['Retrying Auth'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Retrying Auth'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
break;
|
break;
|
||||||
@ -388,7 +302,6 @@ trait AuthKeyHandler
|
|||||||
if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
|
if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
|
||||||
throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash_3');
|
throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash_3');
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Auth Failed'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Auth Failed'], \danog\MadelineProto\Logger::WARNING);
|
||||||
break 2;
|
break 2;
|
||||||
default:
|
default:
|
||||||
@ -397,51 +310,41 @@ trait AuthKeyHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (\danog\MadelineProto\SecurityException $e) {
|
} catch (\danog\MadelineProto\SecurityException $e) {
|
||||||
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: ' . $e->getMessage() . ' in ' . basename($e->getFile(), '.php') . ' on line ' . $e->getLine() . '. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: ' . $e->getMessage() . ' in ' . basename($e->getFile(), '.php') . ' on line ' . $e->getLine() . '. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
$req_pq = $req_pq === 'req_pq_multi' ? 'req_pq' : 'req_pq_multi';
|
$req_pq = $req_pq === 'req_pq_multi' ? 'req_pq' : 'req_pq_multi';
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
if ($e->rpc === 'RPC_CALL_FAIL') {
|
if ($e->rpc === 'RPC_CALL_FAIL') {
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['An RPCErrorException occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An RPCErrorException occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
} finally {
|
} finally {
|
||||||
$this->datacenter->sockets[$datacenter]->new_outgoing = [];
|
$this->datacenter->sockets[$datacenter]->new_outgoing = [];
|
||||||
$this->datacenter->sockets[$datacenter]->new_incoming = [];
|
$this->datacenter->sockets[$datacenter]->new_incoming = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($datacenter, 'cdn') === false) {
|
if (strpos($datacenter, 'cdn') === false) {
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check validity of g_a
|
* Check validity of g_a
|
||||||
* 1 < g_a < p - 1
|
* 1 < g_a < p - 1
|
||||||
*/
|
*/
|
||||||
\danog\MadelineProto\Logger::log(['Executing g_a check (1/2)...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Executing g_a check (1/2)...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
if ($g_a->compare($this->one) <= 0 // 1 < g_a or g_a > 1 or ! g_a <= 1
|
if ($g_a->compare($this->one) <= 0 || $g_a->compare($p->subtract($this->one)) >= 0) {
|
||||||
|| $g_a->compare($p->subtract($this->one)) >= 0 // g_a < dh_prime - 1 or ! g_a >= dh_prime - 1
|
|
||||||
) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException('g_a is invalid (1 < g_a < dh_prime - 1 is false).');
|
throw new \danog\MadelineProto\SecurityException('g_a is invalid (1 < g_a < dh_prime - 1 is false).');
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Executing g_a check (2/2)...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Executing g_a check (2/2)...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
if ($g_a->compare($this->twoe1984) < 0 // gA < 2^{2048-64}
|
if ($g_a->compare($this->twoe1984) < 0 || $g_a->compare($p->subtract($this->twoe1984)) >= 0) {
|
||||||
|| $g_a->compare($p->subtract($this->twoe1984)) >= 0 // gA > dhPrime - 2^{2048-64}
|
|
||||||
) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException('g_a is invalid (2^1984 < gA < dh_prime - 2^1984 is false).');
|
throw new \danog\MadelineProto\SecurityException('g_a is invalid (2^1984 < gA < dh_prime - 2^1984 is false).');
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function check_p_g($p, $g)
|
public function check_p_g($p, $g)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -453,7 +356,6 @@ trait AuthKeyHandler
|
|||||||
if (!$p->isPrime()) {
|
if (!$p->isPrime()) {
|
||||||
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime (p isn't a prime).");
|
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime (p isn't a prime).");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check validity of p
|
* Check validity of p
|
||||||
@ -467,39 +369,29 @@ trait AuthKeyHandler
|
|||||||
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime ((p - 1) / 2 isn't a prime).");
|
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime ((p - 1) / 2 isn't a prime).");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check validity of p
|
* Check validity of p
|
||||||
* 2^2047 < p < 2^2048
|
* 2^2047 < p < 2^2048
|
||||||
*/
|
*/
|
||||||
\danog\MadelineProto\Logger::log(['Executing p/g checks (2/2)...'], \danog\MadelineProto\Logger::VERBOSE);
|
\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 || $p->compare($this->twoe2048) >= 0) {
|
||||||
|| $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).");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check validity of g
|
* Check validity of g
|
||||||
* 1 < g < p - 1
|
* 1 < g < p - 1
|
||||||
*/
|
*/
|
||||||
\danog\MadelineProto\Logger::log(['Executing g check...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Executing g check...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
if ($g->compare($this->one) <= 0 || $g->compare($p->subtract($this->one)) >= 0) {
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_dh_config()
|
public function get_dh_config()
|
||||||
{
|
{
|
||||||
$this->updates_state['sync_loading'] = true;
|
$this->updates_state['sync_loading'] = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0], ['datacenter' => $this->datacenter->curdc]);
|
$dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0], ['datacenter' => $this->datacenter->curdc]);
|
||||||
} finally {
|
} finally {
|
||||||
@ -507,16 +399,13 @@ trait AuthKeyHandler
|
|||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bind_temp_auth_key($expires_in, $datacenter)
|
public function bind_temp_auth_key($expires_in, $datacenter)
|
||||||
{
|
{
|
||||||
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++) {
|
||||||
@ -527,54 +416,39 @@ trait AuthKeyHandler
|
|||||||
$temp_auth_key_id = $this->datacenter->sockets[$datacenter]->temp_auth_key['id'];
|
$temp_auth_key_id = $this->datacenter->sockets[$datacenter]->temp_auth_key['id'];
|
||||||
$perm_auth_key_id = $this->datacenter->sockets[$datacenter]->auth_key['id'];
|
$perm_auth_key_id = $this->datacenter->sockets[$datacenter]->auth_key['id'];
|
||||||
$temp_session_id = $this->datacenter->sockets[$datacenter]->session_id;
|
$temp_session_id = $this->datacenter->sockets[$datacenter]->session_id;
|
||||||
$message_data = $this->serialize_object(['type' => 'bind_auth_key_inner'],
|
$message_data = $this->serialize_object(['type' => 'bind_auth_key_inner'], ['nonce' => $nonce, 'temp_auth_key_id' => $temp_auth_key_id, 'perm_auth_key_id' => $perm_auth_key_id, 'temp_session_id' => $temp_session_id, 'expires_at' => $expires_at], 'bind_temp_auth_key_inner');
|
||||||
[
|
|
||||||
'nonce' => $nonce,
|
|
||||||
'temp_auth_key_id' => $temp_auth_key_id,
|
|
||||||
'perm_auth_key_id' => $perm_auth_key_id,
|
|
||||||
'temp_session_id' => $temp_session_id,
|
|
||||||
'expires_at' => $expires_at,
|
|
||||||
], 'bind_temp_auth_key_inner'
|
|
||||||
);
|
|
||||||
$message_id = $this->generate_message_id($datacenter);
|
$message_id = $this->generate_message_id($datacenter);
|
||||||
|
|
||||||
$seq_no = 0;
|
$seq_no = 0;
|
||||||
$encrypted_data = $this->random(16).$message_id.pack('VV', $seq_no, strlen($message_data)).$message_data;
|
$encrypted_data = $this->random(16) . $message_id . pack('VV', $seq_no, strlen($message_data)) . $message_data;
|
||||||
$message_key = substr(sha1($encrypted_data, true), -16);
|
$message_key = substr(sha1($encrypted_data, true), -16);
|
||||||
$padding = $this->random($this->posmod(-strlen($encrypted_data), 16));
|
$padding = $this->random($this->posmod(-strlen($encrypted_data), 16));
|
||||||
|
|
||||||
//$message_key = substr(hash('sha256', substr($this->datacenter->sockets[$datacenter]->auth_key['auth_key'], 88, 32).$encrypted_data.$padding, true), 8, 16);
|
//$message_key = substr(hash('sha256', substr($this->datacenter->sockets[$datacenter]->auth_key['auth_key'], 88, 32).$encrypted_data.$padding, true), 8, 16);
|
||||||
|
|
||||||
list($aes_key, $aes_iv) = $this->old_aes_calculate($message_key, $this->datacenter->sockets[$datacenter]->auth_key['auth_key']);
|
list($aes_key, $aes_iv) = $this->old_aes_calculate($message_key, $this->datacenter->sockets[$datacenter]->auth_key['auth_key']);
|
||||||
$encrypted_message = $this->datacenter->sockets[$datacenter]->auth_key['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
$encrypted_message = $this->datacenter->sockets[$datacenter]->auth_key['id'] . $message_key . $this->ige_encrypt($encrypted_data . $padding, $aes_key, $aes_iv);
|
||||||
$res = $this->method_call('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], ['message_id' => $message_id, 'datacenter' => $datacenter]);
|
$res = $this->method_call('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], ['message_id' => $message_id, 'datacenter' => $datacenter]);
|
||||||
if ($res === true) {
|
if ($res === true) {
|
||||||
\danog\MadelineProto\Logger::log(['Successfully binded temporary and permanent authorization keys, DC '.$datacenter], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Successfully binded temporary and permanent authorization keys, DC ' . $datacenter], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (\danog\MadelineProto\SecurityException $e) {
|
} catch (\danog\MadelineProto\SecurityException $e) {
|
||||||
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
\danog\MadelineProto\Logger::log(['An RPCErrorException occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An RPCErrorException occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
} finally {
|
} finally {
|
||||||
$this->datacenter->sockets[$datacenter]->new_outgoing = [];
|
$this->datacenter->sockets[$datacenter]->new_outgoing = [];
|
||||||
$this->datacenter->sockets[$datacenter]->new_incoming = [];
|
$this->datacenter->sockets[$datacenter]->new_incoming = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException('An error occurred while binding temporary and permanent authorization keys.');
|
throw new \danog\MadelineProto\SecurityException('An error occurred while binding temporary and permanent authorization keys.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates authorization keys
|
// Creates authorization keys
|
||||||
public function init_authorization()
|
public function init_authorization()
|
||||||
{
|
{
|
||||||
$this->initing_authorization = true;
|
$this->initing_authorization = true;
|
||||||
$this->updates_state['sync_loading'] = true;
|
$this->updates_state['sync_loading'] = true;
|
||||||
$this->postpone_updates = true;
|
$this->postpone_updates = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
foreach ($this->datacenter->sockets as $id => $socket) {
|
foreach ($this->datacenter->sockets as $id => $socket) {
|
||||||
$cdn = strpos($id, 'cdn');
|
$cdn = strpos($id, 'cdn');
|
||||||
@ -626,7 +500,6 @@ trait AuthKeyHandler
|
|||||||
$this->updates_state['sync_loading'] = false;
|
$this->updates_state['sync_loading'] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sync_authorization($id)
|
public function sync_authorization($id)
|
||||||
{
|
{
|
||||||
if (!isset($this->datacenter->sockets[$id])) {
|
if (!isset($this->datacenter->sockets[$id])) {
|
||||||
@ -640,19 +513,20 @@ trait AuthKeyHandler
|
|||||||
}
|
}
|
||||||
if ($authorized_socket->temp_auth_key !== null && $authorized_socket->auth_key !== null && $authorized_socket->authorized === true && $this->authorized === self::LOGGED_IN && $socket->authorized === false && strpos($authorized_dc_id, 'cdn') === false) {
|
if ($authorized_socket->temp_auth_key !== null && $authorized_socket->auth_key !== null && $authorized_socket->authorized === true && $this->authorized === self::LOGGED_IN && $socket->authorized === false && strpos($authorized_dc_id, 'cdn') === false) {
|
||||||
try {
|
try {
|
||||||
\danog\MadelineProto\Logger::log(['Trying to copy authorization from dc '.$authorized_dc_id.' to dc '.$id]);
|
\danog\MadelineProto\Logger::log(['Trying to copy authorization from dc ' . $authorized_dc_id . ' to dc ' . $id]);
|
||||||
$exported_authorization = $this->method_call('auth.exportAuthorization', ['dc_id' => preg_replace('|_.*|', '', $id)], ['datacenter' => $authorized_dc_id]);
|
$exported_authorization = $this->method_call('auth.exportAuthorization', ['dc_id' => preg_replace('|_.*|', '', $id)], ['datacenter' => $authorized_dc_id]);
|
||||||
$authorization = $this->method_call('auth.importAuthorization', $exported_authorization, ['datacenter' => $id]);
|
$authorization = $this->method_call('auth.importAuthorization', $exported_authorization, ['datacenter' => $id]);
|
||||||
$socket->authorized = true;
|
$socket->authorized = true;
|
||||||
break;
|
break;
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
\danog\MadelineProto\Logger::log(['Failure while syncing authorization from DC '.$authorized_dc_id.' to DC '.$id.': '.$e->getMessage()], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Failure while syncing authorization from DC ' . $authorized_dc_id . ' to DC ' . $id . ': ' . $e->getMessage()], \danog\MadelineProto\Logger::ERROR);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
\danog\MadelineProto\Logger::log(['Failure while syncing authorization from DC '.$authorized_dc_id.' to DC '.$id.': '.$e->getMessage()], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Failure while syncing authorization from DC ' . $authorized_dc_id . ' to DC ' . $id . ': ' . $e->getMessage()], \danog\MadelineProto\Logger::ERROR);
|
||||||
if ($e->rpc === 'DC_ID_INVALID') {
|
if ($e->rpc === 'DC_ID_INVALID') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // Turns out this DC isn't authorized after all
|
}
|
||||||
|
// Turns out this DC isn't authorized after all
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,45 +73,24 @@ trait CallHandler
|
|||||||
}
|
}
|
||||||
if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null && (!isset($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited']) || $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited'] === false)) {
|
if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null && (!isset($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited']) || $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited'] === false)) {
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['write_client_info'], $method)], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['write_client_info'], $method)], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$serialized = $this->serialize_method(
|
$serialized = $this->serialize_method('invokeWithLayer', ['layer' => $this->settings['tl_schema']['layer'], 'query' => $this->serialize_method('initConnection', ['api_id' => $this->settings['app_info']['api_id'], 'api_hash' => $this->settings['app_info']['api_hash'], 'device_model' => strpos($aargs['datacenter'], 'cdn') === false ? $this->settings['app_info']['device_model'] : 'n/a', 'system_version' => strpos($aargs['datacenter'], 'cdn') === false ? $this->settings['app_info']['system_version'] : 'n/a', 'app_version' => $this->settings['app_info']['app_version'], 'system_lang_code' => $this->settings['app_info']['lang_code'], 'lang_code' => $this->settings['app_info']['lang_code'], 'lang_pack' => '', 'query' => $serialized])]);
|
||||||
'invokeWithLayer',
|
|
||||||
[
|
|
||||||
'layer' => $this->settings['tl_schema']['layer'],
|
|
||||||
'query' => $this->serialize_method('initConnection',
|
|
||||||
[
|
|
||||||
'api_id' => $this->settings['app_info']['api_id'],
|
|
||||||
'api_hash' => $this->settings['app_info']['api_hash'],
|
|
||||||
'device_model' => strpos($aargs['datacenter'], 'cdn') === false ? $this->settings['app_info']['device_model'] : 'n/a',
|
|
||||||
'system_version' => strpos($aargs['datacenter'], 'cdn') === false ? $this->settings['app_info']['system_version'] : 'n/a',
|
|
||||||
'app_version' => $this->settings['app_info']['app_version'],
|
|
||||||
'system_lang_code' => $this->settings['app_info']['lang_code'],
|
|
||||||
'lang_code' => $this->settings['app_info']['lang_code'],
|
|
||||||
'lang_pack' => '',
|
|
||||||
'query' => $serialized,
|
|
||||||
]
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$content_related = $this->content_related($method);
|
$content_related = $this->content_related($method);
|
||||||
|
|
||||||
$type = $this->methods->find_by_method($method)['type'];
|
$type = $this->methods->find_by_method($method)['type'];
|
||||||
|
|
||||||
if (isset($queue)) {
|
if (isset($queue)) {
|
||||||
$serialized = $this->serialize_method('invokeAfterMsgs', ['msg_ids' => $this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue], 'query' => $serialized]);
|
$serialized = $this->serialize_method('invokeAfterMsgs', ['msg_ids' => $this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue], 'query' => $serialized]);
|
||||||
}
|
}
|
||||||
if ($this->settings['requests']['gzip_encode_if_gt'] !== -1 && ($l = strlen($serialized)) > $this->settings['requests']['gzip_encode_if_gt'] && ($g = strlen($gzipped = gzencode($serialized))) < $l) {
|
if ($this->settings['requests']['gzip_encode_if_gt'] !== -1 && ($l = strlen($serialized)) > $this->settings['requests']['gzip_encode_if_gt'] && ($g = strlen($gzipped = gzencode($serialized))) < $l) {
|
||||||
$serialized = $this->serialize_object(['type' => 'gzip_packed'], ['packed_data' => $gzipped], 'gzipped data');
|
$serialized = $this->serialize_object(['type' => 'gzip_packed'], ['packed_data' => $gzipped], 'gzipped data');
|
||||||
\danog\MadelineProto\Logger::log(['Using GZIP compression for '.$method.', saved '.($l - $g).' bytes of data, reduced call size by '.($g * 100 / $l).'%'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Using GZIP compression for ' . $method . ', saved ' . ($l - $g) . ' bytes of data, reduced call size by ' . $g * 100 / $l . '%'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
}
|
}
|
||||||
$last_recv = $this->last_recv;
|
$last_recv = $this->last_recv;
|
||||||
for ($count = 1; $count <= $this->settings['max_tries']['query']; $count++) {
|
for ($count = 1; $count <= $this->settings['max_tries']['query']; $count++) {
|
||||||
if ($canunset = !$this->updates_state['sync_loading']) {
|
if ($canunset = !$this->updates_state['sync_loading']) {
|
||||||
$this->updates_state['sync_loading'] = true;
|
$this->updates_state['sync_loading'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
\danog\MadelineProto\Logger::log(['Calling method (try number '.$count.' for '.$method.')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Calling method (try number ' . $count . ' for ' . $method . ')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null) {
|
if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null) {
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->object_queue[] = ['body' => $serialized, 'content_related' => $content_related, 'msg_id' => $message_id = isset($aargs['message_id']) ? $aargs['message_id'] : $this->generate_message_id($aargs['datacenter'])];
|
$this->datacenter->sockets[$aargs['datacenter']]->object_queue[] = ['body' => $serialized, 'content_related' => $content_related, 'msg_id' => $message_id = isset($aargs['message_id']) ? $aargs['message_id'] : $this->generate_message_id($aargs['datacenter'])];
|
||||||
if (count($this->datacenter->sockets[$aargs['datacenter']]->ack_queue)) {
|
if (count($this->datacenter->sockets[$aargs['datacenter']]->ack_queue)) {
|
||||||
@ -123,8 +102,8 @@ trait CallHandler
|
|||||||
$this->send_messages($aargs['datacenter']);
|
$this->send_messages($aargs['datacenter']);
|
||||||
} else {
|
} else {
|
||||||
$this->send_unencrypted_message($serialized, $message_id = isset($aargs['message_id']) ? $aargs['message_id'] : $this->generate_message_id($aargs['datacenter']), $aargs['datacenter']);
|
$this->send_unencrypted_message($serialized, $message_id = isset($aargs['message_id']) ? $aargs['message_id'] : $this->generate_message_id($aargs['datacenter']), $aargs['datacenter']);
|
||||||
|
$aargs['message_id'] = $message_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->is_http($aargs['datacenter']) && isset($aargs['reopen'])) {
|
if ($this->is_http($aargs['datacenter']) && isset($aargs['reopen'])) {
|
||||||
\danog\MadelineProto\Logger::log(['Closing and reopening connection...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Closing and reopening connection...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->close_and_reopen($aargs['datacenter']);
|
$this->close_and_reopen($aargs['datacenter']);
|
||||||
@ -140,7 +119,7 @@ trait CallHandler
|
|||||||
unset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue][$key]);
|
unset($this->datacenter->sockets[$aargs['datacenter']]->call_queue[$queue][$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($method === 'http_wait' || (isset($aargs['noResponse']) && $aargs['noResponse'])) {
|
if ($method === 'http_wait' || isset($aargs['noResponse']) && $aargs['noResponse']) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['content'] = ['method' => $method, 'args' => $args];
|
//$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['content'] = ['method' => $method, 'args' => $args];
|
||||||
@ -149,10 +128,12 @@ trait CallHandler
|
|||||||
$server_answer = null;
|
$server_answer = null;
|
||||||
$update_count = 0;
|
$update_count = 0;
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
while ($server_answer === null && $res_count++ < $this->settings['max_tries']['response'] + 1) { // Loop until we get a response, loop for a max of $this->settings['max_tries']['response'] times
|
while ($server_answer === null && $res_count++ < $this->settings['max_tries']['response'] + 1) {
|
||||||
|
// Loop until we get a response, loop for a max of $this->settings['max_tries']['response'] times
|
||||||
try {
|
try {
|
||||||
\danog\MadelineProto\Logger::log(['Getting response (try number '.$res_count.' for '.$method.')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Getting response (try number ' . $res_count . ' for ' . $method . ')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
if (!isset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['response']) || !isset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['response']]['content'])) { // Checks if I have received the response to the called method, if not continue looping
|
if (!isset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['response']) || !isset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['response']]['content'])) {
|
||||||
|
// Checks if I have received the response to the called method, if not continue looping
|
||||||
if ($only_updates) {
|
if ($only_updates) {
|
||||||
if ($update_count > 50) {
|
if ($update_count > 50) {
|
||||||
$update_count = 0;
|
$update_count = 0;
|
||||||
@ -172,26 +153,24 @@ trait CallHandler
|
|||||||
\danog\MadelineProto\Logger::log(['WARNING: Resetting auth key...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['WARNING: Resetting auth key...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
|
|
||||||
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \danog\MadelineProto\RPCErrorException($error, $error);
|
throw new \danog\MadelineProto\RPCErrorException($error, $error);
|
||||||
}
|
}
|
||||||
$only_updates = $this->handle_messages($aargs['datacenter']); // This method receives data from the socket, and parses stuff
|
$only_updates = $this->handle_messages($aargs['datacenter']);
|
||||||
|
// This method receives data from the socket, and parses stuff
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
if ($e->getMessage() === 'I had to recreate the temporary authorization key') {
|
if ($e->getMessage() === 'I had to recreate the temporary authorization key') {
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['An error getting response of method '.$method.': '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An error getting response of method ' . $method . ': ' . $e->getMessage() . ' in ' . basename($e->getFile(), '.php') . ' on line ' . $e->getLine() . '. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
continue;
|
continue;
|
||||||
} catch (\danog\MadelineProto\NothingInTheSocketException $e) {
|
} catch (\danog\MadelineProto\NothingInTheSocketException $e) {
|
||||||
\danog\MadelineProto\Logger::log(['An error getting response of method '.$method.': '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An error getting response of method ' . $method . ': ' . $e->getMessage() . ' in ' . basename($e->getFile(), '.php') . ' on line ' . $e->getLine() . '. Retrying...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($canunset) {
|
if ($canunset) {
|
||||||
$this->updates_state['sync_loading'] = false;
|
$this->updates_state['sync_loading'] = false;
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
@ -214,16 +193,15 @@ trait CallHandler
|
|||||||
continue 3;
|
continue 3;
|
||||||
case 16:
|
case 16:
|
||||||
case 17:
|
case 17:
|
||||||
\danog\MadelineProto\Logger::log(['Received bad_msg_notification: '.self::BAD_MSG_ERROR_CODES[$server_answer['error_code']]], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Received bad_msg_notification: ' . self::BAD_MSG_ERROR_CODES[$server_answer['error_code']]], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->time_delta = (int) ((new \phpseclib\Math\BigInteger(strrev($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['response']), 256))->bitwise_rightShift(32)->subtract(new \phpseclib\Math\BigInteger(time()))->toString());
|
$this->datacenter->sockets[$aargs['datacenter']]->time_delta = (int) (new \phpseclib\Math\BigInteger(strrev($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id]['response']), 256))->bitwise_rightShift(32)->subtract(new \phpseclib\Math\BigInteger(time()))->toString();
|
||||||
\danog\MadelineProto\Logger::log(['Set time delta to '.$this->datacenter->sockets[$aargs['datacenter']]->time_delta], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Set time delta to ' . $this->datacenter->sockets[$aargs['datacenter']]->time_delta], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->reset_session();
|
$this->reset_session();
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
continue 3;
|
continue 3;
|
||||||
}
|
}
|
||||||
|
throw new \danog\MadelineProto\RPCErrorException('Received bad_msg_notification: ' . self::BAD_MSG_ERROR_CODES[$server_answer['error_code']], $server_answer['error_code']);
|
||||||
throw new \danog\MadelineProto\RPCErrorException('Received bad_msg_notification: '.self::BAD_MSG_ERROR_CODES[$server_answer['error_code']], $server_answer['error_code']);
|
|
||||||
break;
|
break;
|
||||||
case 'boolTrue':
|
case 'boolTrue':
|
||||||
case 'boolFalse':
|
case 'boolFalse':
|
||||||
@ -234,13 +212,16 @@ trait CallHandler
|
|||||||
$server_answer = $this->MTProto_to_botAPI($server_answer, $args);
|
$server_answer = $this->MTProto_to_botAPI($server_answer, $args);
|
||||||
}
|
}
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
$last_error = $e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine();
|
$last_error = $e->getMessage() . ' in ' . basename($e->getFile(), '.php') . ' on line ' . $e->getLine();
|
||||||
\danog\MadelineProto\Logger::log(['An error occurred while calling method '.$method.': '.$last_error.'. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An error occurred while calling method ' . $method . ': ' . $last_error . '. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->close_and_reopen($aargs['datacenter']);
|
$this->close_and_reopen($aargs['datacenter']);
|
||||||
|
if ($e->getMessage() === 'Re-executing query after server error...') {
|
||||||
|
return $this->method_call($method, $args, $aargs);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
} catch (\RuntimeException $e) {
|
} catch (\RuntimeException $e) {
|
||||||
$last_error = $e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine();
|
$last_error = $e->getMessage() . ' in ' . basename($e->getFile(), '.php') . ' on line ' . $e->getLine();
|
||||||
\danog\MadelineProto\Logger::log(['An error occurred while calling method '.$method.': '.$last_error.'. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['An error occurred while calling method ' . $method . ': ' . $last_error . '. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->close_and_reopen($aargs['datacenter']);
|
$this->close_and_reopen($aargs['datacenter']);
|
||||||
continue;
|
continue;
|
||||||
} finally {
|
} finally {
|
||||||
@ -258,23 +239,19 @@ trait CallHandler
|
|||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($server_answer === null) {
|
if ($server_answer === null) {
|
||||||
if ($last_recv === $this->last_recv && $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null) {
|
if ($last_recv === $this->last_recv && $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null) {
|
||||||
\danog\MadelineProto\Logger::log(['WARNING: Resetting auth key...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['WARNING: Resetting auth key...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
|
|
||||||
return $this->method_call($method, $args, $aargs);
|
return $this->method_call($method, $args, $aargs);
|
||||||
}
|
}
|
||||||
|
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.').');
|
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Got response for method '.$method.' @ try '.$count.' (response try '.$res_count.')'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Got response for method ' . $method . ' @ try ' . $count . ' (response try ' . $res_count . ')'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null && (!isset($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited']) || $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited'] === false)) {
|
if ($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key !== null && (!isset($this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited']) || $this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited'] === false)) {
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited'] = true;
|
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key['connection_inited'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id] = [];
|
$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$message_id] = [];
|
||||||
if (isset($message_chunks) && count($message_chunks)) {
|
if (isset($message_chunks) && count($message_chunks)) {
|
||||||
$server_answer = [$server_answer];
|
$server_answer = [$server_answer];
|
||||||
@ -283,16 +260,13 @@ trait CallHandler
|
|||||||
$server_answer[] = $this->method_call($method, $args, $aargs);
|
$server_answer[] = $this->method_call($method, $args, $aargs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $server_answer;
|
return $server_answer;
|
||||||
}
|
}
|
||||||
if ($method === 'req_pq') {
|
if ($method === 'req_pq') {
|
||||||
throw new \danog\MadelineProto\RPCErrorException('RPC_CALL_FAIL');
|
throw new \danog\MadelineProto\RPCErrorException('RPC_CALL_FAIL');
|
||||||
}
|
}
|
||||||
|
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)) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
trait Crypt
|
trait Crypt
|
||||||
@ -17,51 +17,42 @@ trait Crypt
|
|||||||
public function aes_calculate($msg_key, $auth_key, $to_server = true)
|
public function aes_calculate($msg_key, $auth_key, $to_server = true)
|
||||||
{
|
{
|
||||||
$x = $to_server ? 0 : 8;
|
$x = $to_server ? 0 : 8;
|
||||||
$sha256_a = hash('sha256', $msg_key.substr($auth_key, $x, 36), true);
|
$sha256_a = hash('sha256', $msg_key . substr($auth_key, $x, 36), true);
|
||||||
$sha256_b = hash('sha256', substr($auth_key, 40 + $x, 36).$msg_key, true);
|
$sha256_b = hash('sha256', substr($auth_key, 40 + $x, 36) . $msg_key, true);
|
||||||
$aes_key = substr($sha256_a, 0, 8).substr($sha256_b, 8, 16).substr($sha256_a, 24, 8);
|
$aes_key = substr($sha256_a, 0, 8) . substr($sha256_b, 8, 16) . substr($sha256_a, 24, 8);
|
||||||
$aes_iv = substr($sha256_b, 0, 8).substr($sha256_a, 8, 16).substr($sha256_b, 24, 8);
|
$aes_iv = substr($sha256_b, 0, 8) . substr($sha256_a, 8, 16) . substr($sha256_b, 24, 8);
|
||||||
|
|
||||||
return [$aes_key, $aes_iv];
|
return [$aes_key, $aes_iv];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function old_aes_calculate($msg_key, $auth_key, $to_server = true)
|
public function old_aes_calculate($msg_key, $auth_key, $to_server = true)
|
||||||
{
|
{
|
||||||
$x = $to_server ? 0 : 8;
|
$x = $to_server ? 0 : 8;
|
||||||
$sha1_a = sha1($msg_key.substr($auth_key, $x, 32), true);
|
$sha1_a = sha1($msg_key . substr($auth_key, $x, 32), true);
|
||||||
$sha1_b = sha1(substr($auth_key, 32 + $x, 16).$msg_key.substr($auth_key, 48 + $x, 16), true);
|
$sha1_b = sha1(substr($auth_key, 32 + $x, 16) . $msg_key . substr($auth_key, 48 + $x, 16), true);
|
||||||
$sha1_c = sha1(substr($auth_key, 64 + $x, 32).$msg_key, true);
|
$sha1_c = sha1(substr($auth_key, 64 + $x, 32) . $msg_key, true);
|
||||||
$sha1_d = sha1($msg_key.substr($auth_key, 96 + $x, 32), true);
|
$sha1_d = sha1($msg_key . substr($auth_key, 96 + $x, 32), true);
|
||||||
$aes_key = substr($sha1_a, 0, 8).substr($sha1_b, 8, 12).substr($sha1_c, 4, 12);
|
$aes_key = substr($sha1_a, 0, 8) . substr($sha1_b, 8, 12) . substr($sha1_c, 4, 12);
|
||||||
$aes_iv = substr($sha1_a, 8, 12).substr($sha1_b, 0, 8).substr($sha1_c, 16, 4).substr($sha1_d, 0, 8);
|
$aes_iv = substr($sha1_a, 8, 12) . substr($sha1_b, 0, 8) . substr($sha1_c, 16, 4) . substr($sha1_d, 0, 8);
|
||||||
|
|
||||||
return [$aes_key, $aes_iv];
|
return [$aes_key, $aes_iv];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ige_encrypt($message, $key, $iv)
|
public function ige_encrypt($message, $key, $iv)
|
||||||
{
|
{
|
||||||
$cipher = new \phpseclib\Crypt\AES('ige');
|
$cipher = new \phpseclib\Crypt\AES('ige');
|
||||||
$cipher->setKey($key);
|
$cipher->setKey($key);
|
||||||
$cipher->setIV($iv);
|
$cipher->setIV($iv);
|
||||||
|
|
||||||
return @$cipher->encrypt($message);
|
return @$cipher->encrypt($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ctr_encrypt($message, $key, $iv)
|
public function ctr_encrypt($message, $key, $iv)
|
||||||
{
|
{
|
||||||
$cipher = new \phpseclib\Crypt\AES('ctr');
|
$cipher = new \phpseclib\Crypt\AES('ctr');
|
||||||
$cipher->setKey($key);
|
$cipher->setKey($key);
|
||||||
$cipher->setIV($iv);
|
$cipher->setIV($iv);
|
||||||
|
|
||||||
return @$cipher->encrypt($message);
|
return @$cipher->encrypt($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ige_decrypt($message, $key, $iv)
|
public function ige_decrypt($message, $key, $iv)
|
||||||
{
|
{
|
||||||
$cipher = new \phpseclib\Crypt\AES('ige');
|
$cipher = new \phpseclib\Crypt\AES('ige');
|
||||||
$cipher->setKey($key);
|
$cipher->setKey($key);
|
||||||
$cipher->setIV($iv);
|
$cipher->setIV($iv);
|
||||||
|
|
||||||
return @$cipher->decrypt($message);
|
return @$cipher->decrypt($message);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,21 +32,21 @@ trait Files
|
|||||||
}
|
}
|
||||||
if ($cb === null) {
|
if ($cb === null) {
|
||||||
$cb = function ($percent) {
|
$cb = function ($percent) {
|
||||||
\danog\MadelineProto\Logger::log(['Upload status: '.$percent.'%'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Upload status: ' . $percent . '%'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
$part_size = 512 * 1024;
|
$part_size = 512 * 1024;
|
||||||
$part_total_num = (int) ceil($file_size / $part_size);
|
$part_total_num = (int) ceil($file_size / $part_size);
|
||||||
$part_num = 0;
|
$part_num = 0;
|
||||||
$method = $file_size > 10 * 1024 * 1024 ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
$method = $file_size > 10 * 1024 * 1024 ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
||||||
$constructor = 'input'.($encrypted === true ? 'Encrypted' : '').($file_size > 10 * 1024 * 1024 ? 'FileBig' : 'File').($encrypted === true ? 'Uploaded' : '');
|
$constructor = 'input' . ($encrypted === true ? 'Encrypted' : '') . ($file_size > 10 * 1024 * 1024 ? 'FileBig' : 'File') . ($encrypted === true ? 'Uploaded' : '');
|
||||||
$file_id = $this->random(8);
|
$file_id = $this->random(8);
|
||||||
$f = fopen($file, 'r');
|
$f = fopen($file, 'r');
|
||||||
fseek($f, 0);
|
fseek($f, 0);
|
||||||
if ($encrypted === true) {
|
if ($encrypted === true) {
|
||||||
$key = $this->random(32);
|
$key = $this->random(32);
|
||||||
$iv = $this->random(32);
|
$iv = $this->random(32);
|
||||||
$digest = hash('md5', $key.$iv, true);
|
$digest = hash('md5', $key . $iv, true);
|
||||||
$fingerprint = $this->unpack_signed_int(substr($digest, 0, 4) ^ substr($digest, 4, 4));
|
$fingerprint = $this->unpack_signed_int(substr($digest, 0, 4) ^ substr($digest, 4, 4));
|
||||||
$ige = new \phpseclib\Crypt\AES('ige');
|
$ige = new \phpseclib\Crypt\AES('ige');
|
||||||
$ige->setIV($iv);
|
$ige->setIV($iv);
|
||||||
@ -54,7 +54,6 @@ trait Files
|
|||||||
$ige->enableContinuousBuffer();
|
$ige->enableContinuousBuffer();
|
||||||
}
|
}
|
||||||
$ctx = hash_init('md5');
|
$ctx = hash_init('md5');
|
||||||
|
|
||||||
while (ftell($f) !== $file_size) {
|
while (ftell($f) !== $file_size) {
|
||||||
$bytes = stream_get_contents($f, $part_size);
|
$bytes = stream_get_contents($f, $part_size);
|
||||||
if ($encrypted === true) {
|
if ($encrypted === true) {
|
||||||
@ -62,12 +61,11 @@ trait Files
|
|||||||
}
|
}
|
||||||
hash_update($ctx, $bytes);
|
hash_update($ctx, $bytes);
|
||||||
if (!$this->method_call($method, ['file_id' => $file_id, 'file_part' => $part_num++, 'file_total_parts' => $part_total_num, 'bytes' => $bytes], ['heavy' => true, 'datacenter' => &$datacenter])) {
|
if (!$this->method_call($method, ['file_id' => $file_id, 'file_part' => $part_num++, 'file_total_parts' => $part_total_num, 'bytes' => $bytes], ['heavy' => true, 'datacenter' => &$datacenter])) {
|
||||||
throw new \danog\MadelineProto\Exception('An error occurred while uploading file part '.$part_num);
|
throw new \danog\MadelineProto\Exception('An error occurred while uploading file part ' . $part_num);
|
||||||
}
|
}
|
||||||
$cb(ftell($f) * 100 / $file_size);
|
$cb(ftell($f) * 100 / $file_size);
|
||||||
}
|
}
|
||||||
fclose($f);
|
fclose($f);
|
||||||
|
|
||||||
$constructor = ['_' => $constructor, 'id' => $file_id, 'parts' => $part_total_num, 'name' => $file_name, 'md5_checksum' => hash_final($ctx)];
|
$constructor = ['_' => $constructor, 'id' => $file_id, 'parts' => $part_total_num, 'name' => $file_name, 'md5_checksum' => hash_final($ctx)];
|
||||||
if ($encrypted === true) {
|
if ($encrypted === true) {
|
||||||
$constructor['key_fingerprint'] = $fingerprint;
|
$constructor['key_fingerprint'] = $fingerprint;
|
||||||
@ -75,15 +73,12 @@ trait Files
|
|||||||
$constructor['iv'] = $iv;
|
$constructor['iv'] = $iv;
|
||||||
$constructor['md5_checksum'] = '';
|
$constructor['md5_checksum'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
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)) {
|
||||||
@ -106,7 +101,7 @@ trait Files
|
|||||||
if (isset($message_media['decrypted_message']['media']['file_name'])) {
|
if (isset($message_media['decrypted_message']['media']['file_name'])) {
|
||||||
$pathinfo = pathinfo($message_media['decrypted_message']['media']['file_name']);
|
$pathinfo = pathinfo($message_media['decrypted_message']['media']['file_name']);
|
||||||
if (isset($pathinfo['extension'])) {
|
if (isset($pathinfo['extension'])) {
|
||||||
$res['ext'] = '.'.$pathinfo['extension'];
|
$res['ext'] = '.' . $pathinfo['extension'];
|
||||||
}
|
}
|
||||||
$res['name'] = $pathinfo['filename'];
|
$res['name'] = $pathinfo['filename'];
|
||||||
}
|
}
|
||||||
@ -115,14 +110,13 @@ trait Files
|
|||||||
} elseif ($message_media['decrypted_message']['media']['_'] === 'decryptedMessageMediaPhoto') {
|
} elseif ($message_media['decrypted_message']['media']['_'] === 'decryptedMessageMediaPhoto') {
|
||||||
$res['mime'] = 'image/jpeg';
|
$res['mime'] = 'image/jpeg';
|
||||||
}
|
}
|
||||||
|
|
||||||
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['_']) {
|
||||||
case 'documentAttributeFilename':
|
case 'documentAttributeFilename':
|
||||||
$pathinfo = pathinfo($attribute['file_name']);
|
$pathinfo = pathinfo($attribute['file_name']);
|
||||||
if (isset($pathinfo['extension'])) {
|
if (isset($pathinfo['extension'])) {
|
||||||
$res['ext'] = '.'.$pathinfo['extension'];
|
$res['ext'] = '.' . $pathinfo['extension'];
|
||||||
}
|
}
|
||||||
$res['name'] = $pathinfo['filename'];
|
$res['name'] = $pathinfo['filename'];
|
||||||
break;
|
break;
|
||||||
@ -135,7 +129,7 @@ trait Files
|
|||||||
if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
|
if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
|
||||||
$res['name'] = $audio['title'];
|
$res['name'] = $audio['title'];
|
||||||
if (isset($audio['performer'])) {
|
if (isset($audio['performer'])) {
|
||||||
$res['name'] .= ' - '.$audio['performer'];
|
$res['name'] .= ' - ' . $audio['performer'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isset($res['ext'])) {
|
if (!isset($res['ext'])) {
|
||||||
@ -144,7 +138,6 @@ 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 'photo':
|
case 'photo':
|
||||||
case 'messageMediaPhoto':
|
case 'messageMediaPhoto':
|
||||||
@ -153,9 +146,8 @@ trait Files
|
|||||||
} else {
|
} else {
|
||||||
$photo = end($message_media['photo']['sizes']);
|
$photo = end($message_media['photo']['sizes']);
|
||||||
}
|
}
|
||||||
$res['name'] = $photo['location']['volume_id'].'_'.$photo['location']['local_id'];
|
$res['name'] = $photo['location']['volume_id'] . '_' . $photo['location']['local_id'];
|
||||||
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret'], 'dc_id' => $photo['location']['dc_id']];
|
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret'], 'dc_id' => $photo['location']['dc_id']];
|
||||||
|
|
||||||
$res['ext'] = $this->get_extension_from_location($res['InputFileLocation'], '.jpg');
|
$res['ext'] = $this->get_extension_from_location($res['InputFileLocation'], '.jpg');
|
||||||
$res['mime'] = 'image/jpeg';
|
$res['mime'] = 'image/jpeg';
|
||||||
if (isset($photo['location']['size'])) {
|
if (isset($photo['location']['size'])) {
|
||||||
@ -164,11 +156,10 @@ trait Files
|
|||||||
if (isset($photo['location']['bytes'])) {
|
if (isset($photo['location']['bytes'])) {
|
||||||
$res['size'] = strlen($photo['location']['bytes']);
|
$res['size'] = strlen($photo['location']['bytes']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
case 'photoSize':
|
case 'photoSize':
|
||||||
case 'photoCachedSize':
|
case 'photoCachedSize':
|
||||||
$res['name'] = $message_media['location']['volume_id'].'_'.$message_media['location']['local_id'];
|
$res['name'] = $message_media['location']['volume_id'] . '_' . $message_media['location']['local_id'];
|
||||||
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $message_media['location']['volume_id'], 'local_id' => $message_media['location']['local_id'], 'secret' => $message_media['location']['secret'], 'dc_id' => $message_media['location']['dc_id']];
|
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $message_media['location']['volume_id'], 'local_id' => $message_media['location']['local_id'], 'secret' => $message_media['location']['secret'], 'dc_id' => $message_media['location']['dc_id']];
|
||||||
$res['ext'] = $this->get_extension_from_location($res['InputFileLocation'], '.jpg');
|
$res['ext'] = $this->get_extension_from_location($res['InputFileLocation'], '.jpg');
|
||||||
$res['mime'] = 'image/jpeg';
|
$res['mime'] = 'image/jpeg';
|
||||||
@ -178,7 +169,6 @@ trait Files
|
|||||||
if (isset($photo['location']['bytes'])) {
|
if (isset($photo['location']['bytes'])) {
|
||||||
$res['size'] = strlen($photo['location']['bytes']);
|
$res['size'] = strlen($photo['location']['bytes']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
case 'decryptedMessageMediaExternalDocument':
|
case 'decryptedMessageMediaExternalDocument':
|
||||||
case 'document':
|
case 'document':
|
||||||
@ -189,7 +179,7 @@ trait Files
|
|||||||
case 'documentAttributeFilename':
|
case 'documentAttributeFilename':
|
||||||
$pathinfo = pathinfo($attribute['file_name']);
|
$pathinfo = pathinfo($attribute['file_name']);
|
||||||
if (isset($pathinfo['extension'])) {
|
if (isset($pathinfo['extension'])) {
|
||||||
$res['ext'] = '.'.$pathinfo['extension'];
|
$res['ext'] = '.' . $pathinfo['extension'];
|
||||||
}
|
}
|
||||||
$res['name'] = $pathinfo['filename'];
|
$res['name'] = $pathinfo['filename'];
|
||||||
break;
|
break;
|
||||||
@ -201,7 +191,7 @@ trait Files
|
|||||||
if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
|
if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
|
||||||
$res['name'] = $audio['title'];
|
$res['name'] = $audio['title'];
|
||||||
if (isset($audio['performer'])) {
|
if (isset($audio['performer'])) {
|
||||||
$res['name'] .= ' - '.$audio['performer'];
|
$res['name'] .= ' - ' . $audio['performer'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$res['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $message_media['document']['id'], 'access_hash' => $message_media['document']['access_hash'], 'version' => isset($message_media['document']['version']) ? $message_media['document']['version'] : 0, 'dc_id' => $message_media['document']['dc_id']];
|
$res['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $message_media['document']['id'], 'access_hash' => $message_media['document']['access_hash'], 'version' => isset($message_media['document']['version']) ? $message_media['document']['version'] : 0, 'dc_id' => $message_media['document']['dc_id']];
|
||||||
@ -211,26 +201,21 @@ trait Files
|
|||||||
if (!isset($res['name'])) {
|
if (!isset($res['name'])) {
|
||||||
$res['name'] = $message_media['document']['access_hash'];
|
$res['name'] = $message_media['document']['access_hash'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($message_media['document']['size'])) {
|
if (isset($message_media['document']['size'])) {
|
||||||
$res['size'] = $message_media['document']['size'];
|
$res['size'] = $message_media['document']['size'];
|
||||||
}
|
}
|
||||||
$res['name'] .= '_'.$message_media['document']['id'];
|
$res['name'] .= '_' . $message_media['document']['id'];
|
||||||
$res['mime'] = $message_media['document']['mime_type'];
|
$res['mime'] = $message_media['document']['mime_type'];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\Exception('Invalid constructor provided: '.$message_media['_']);
|
throw new \danog\MadelineProto\Exception('Invalid constructor provided: ' . $message_media['_']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function download_to_dir($message_media, $dir, $cb = null)
|
public function download_to_dir($message_media, $dir, $cb = null)
|
||||||
{
|
{
|
||||||
$message_media = $this->get_download_info($message_media);
|
$message_media = $this->get_download_info($message_media);
|
||||||
|
return $this->download_to_file($message_media, $dir . '/' . $message_media['name'] . $message_media['ext'], $cb);
|
||||||
return $this->download_to_file($message_media, $dir.'/'.$message_media['name'].$message_media['ext'], $cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function download_to_file($message_media, $file, $cb = null)
|
public function download_to_file($message_media, $file, $cb = null)
|
||||||
{
|
{
|
||||||
$file = preg_replace('|/+|', '/', $file);
|
$file = preg_replace('|/+|', '/', $file);
|
||||||
@ -242,7 +227,6 @@ trait Files
|
|||||||
$stream = fopen($file, 'r+b');
|
$stream = fopen($file, 'r+b');
|
||||||
\danog\MadelineProto\Logger::log(['Waiting for lock of file to download...']);
|
\danog\MadelineProto\Logger::log(['Waiting for lock of file to download...']);
|
||||||
flock($stream, LOCK_EX);
|
flock($stream, LOCK_EX);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->download_to_stream($message_media, $stream, $cb, filesize($file), -1);
|
$this->download_to_stream($message_media, $stream, $cb, filesize($file), -1);
|
||||||
} finally {
|
} finally {
|
||||||
@ -250,15 +234,13 @@ trait Files
|
|||||||
fclose($stream);
|
fclose($stream);
|
||||||
clearstatcache();
|
clearstatcache();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $file;
|
return $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function download_to_stream($message_media, $stream, $cb = null, $offset = 0, $end = -1)
|
public function download_to_stream($message_media, $stream, $cb = null, $offset = 0, $end = -1)
|
||||||
{
|
{
|
||||||
if ($cb === null) {
|
if ($cb === null) {
|
||||||
$cb = function ($percent) {
|
$cb = function ($percent) {
|
||||||
\danog\MadelineProto\Logger::log(['Download status: '.$percent.'%'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Download status: ' . $percent . '%'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
$message_media = $this->get_download_info($message_media);
|
$message_media = $this->get_download_info($message_media);
|
||||||
@ -274,7 +256,7 @@ trait Files
|
|||||||
$percent = 0;
|
$percent = 0;
|
||||||
$datacenter = isset($message_media['InputFileLocation']['dc_id']) ? $message_media['InputFileLocation']['dc_id'] : $this->datacenter->curdc;
|
$datacenter = isset($message_media['InputFileLocation']['dc_id']) ? $message_media['InputFileLocation']['dc_id'] : $this->datacenter->curdc;
|
||||||
if (isset($message_media['key'])) {
|
if (isset($message_media['key'])) {
|
||||||
$digest = hash('md5', $message_media['key'].$message_media['iv'], true);
|
$digest = hash('md5', $message_media['key'] . $message_media['iv'], true);
|
||||||
$fingerprint = $this->unpack_signed_int(substr($digest, 0, 4) ^ substr($digest, 4, 4));
|
$fingerprint = $this->unpack_signed_int(substr($digest, 0, 4) ^ substr($digest, 4, 4));
|
||||||
if ($fingerprint !== $message_media['key_fingerprint']) {
|
if ($fingerprint !== $message_media['key_fingerprint']) {
|
||||||
throw new \danog\MadelineProto\Exception('Fingerprint mismatch!');
|
throw new \danog\MadelineProto\Exception('Fingerprint mismatch!');
|
||||||
@ -290,7 +272,6 @@ trait Files
|
|||||||
if ($start_at = $offset % $part_size) {
|
if ($start_at = $offset % $part_size) {
|
||||||
$offset -= $start_at;
|
$offset -= $start_at;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$res = $cdn ? $this->method_call('upload.getCdnFile', ['file_token' => $message_media['file_token'], 'offset' => $offset, 'limit' => $part_size], ['heavy' => true, 'datacenter' => $datacenter]) : $this->method_call('upload.getFile', ['location' => $message_media['InputFileLocation'], 'offset' => $offset, 'limit' => $part_size], ['heavy' => true, 'datacenter' => &$datacenter]);
|
$res = $cdn ? $this->method_call('upload.getCdnFile', ['file_token' => $message_media['file_token'], 'offset' => $offset, 'limit' => $part_size], ['heavy' => true, 'datacenter' => $datacenter]) : $this->method_call('upload.getFile', ['location' => $message_media['InputFileLocation'], 'offset' => $offset, 'limit' => $part_size], ['heavy' => true, 'datacenter' => &$datacenter]);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
@ -298,7 +279,6 @@ trait Files
|
|||||||
case 'FILE_TOKEN_INVALID':
|
case 'FILE_TOKEN_INVALID':
|
||||||
$cdn = false;
|
$cdn = false;
|
||||||
continue 2;
|
continue 2;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
@ -309,7 +289,7 @@ trait Files
|
|||||||
$message_media['cdn_key'] = $res['encryption_key'];
|
$message_media['cdn_key'] = $res['encryption_key'];
|
||||||
$message_media['cdn_iv'] = $res['encryption_iv'];
|
$message_media['cdn_iv'] = $res['encryption_iv'];
|
||||||
$old_dc = $datacenter;
|
$old_dc = $datacenter;
|
||||||
$datacenter = $res['dc_id'].'_cdn';
|
$datacenter = $res['dc_id'] . '_cdn';
|
||||||
if (!isset($this->datacenter->sockets[$datacenter])) {
|
if (!isset($this->datacenter->sockets[$datacenter])) {
|
||||||
$this->config['expires'] = -1;
|
$this->config['expires'] = -1;
|
||||||
$this->get_config([], ['datacenter' => $this->datacenter->curdc]);
|
$this->get_config([], ['datacenter' => $this->datacenter->curdc]);
|
||||||
@ -320,7 +300,6 @@ trait Files
|
|||||||
if ($res['_'] === 'upload.cdnFileReuploadNeeded') {
|
if ($res['_'] === 'upload.cdnFileReuploadNeeded') {
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['cdn_reupload']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['cdn_reupload']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->get_config([], ['datacenter' => $this->datacenter->curdc]);
|
$this->get_config([], ['datacenter' => $this->datacenter->curdc]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->add_cdn_hashes($message_media['file_token'], $this->method_call('upload.reuploadCdnFile', ['file_token' => $message_media['file_token'], 'request_token' => $res['request_token']], ['heavy' => true, 'datacenter' => $old_dc]));
|
$this->add_cdn_hashes($message_media['file_token'], $this->method_call('upload.reuploadCdnFile', ['file_token' => $message_media['file_token'], 'request_token' => $res['request_token']], ['heavy' => true, 'datacenter' => $old_dc]));
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
@ -329,7 +308,6 @@ trait Files
|
|||||||
case 'REQUEST_TOKEN_INVALID':
|
case 'REQUEST_TOKEN_INVALID':
|
||||||
$cdn = false;
|
$cdn = false;
|
||||||
continue 2;
|
continue 2;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
@ -347,7 +325,7 @@ trait Files
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($message_media['cdn_key'])) {
|
if (isset($message_media['cdn_key'])) {
|
||||||
$ivec = substr($message_media['cdn_iv'], 0, 12).pack('N', $offset >> 4);
|
$ivec = substr($message_media['cdn_iv'], 0, 12) . pack('N', $offset >> 4);
|
||||||
$res['bytes'] = $this->ctr_encrypt($res['bytes'], $message_media['cdn_key'], $ivec);
|
$res['bytes'] = $this->ctr_encrypt($res['bytes'], $message_media['cdn_key'], $ivec);
|
||||||
$this->check_cdn_hash($message_media['file_token'], $offset, $res['bytes'], $old_dc);
|
$this->check_cdn_hash($message_media['file_token'], $offset, $res['bytes'], $old_dc);
|
||||||
}
|
}
|
||||||
@ -367,7 +345,6 @@ trait Files
|
|||||||
$offset += strlen($res['bytes']);
|
$offset += strlen($res['bytes']);
|
||||||
$downloaded_size += strlen($res['bytes']);
|
$downloaded_size += strlen($res['bytes']);
|
||||||
\danog\MadelineProto\Logger::log([fwrite($stream, $res['bytes'])], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log([fwrite($stream, $res['bytes'])], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
|
|
||||||
if ($theend) {
|
if ($theend) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -381,12 +358,9 @@ trait Files
|
|||||||
if ($cdn) {
|
if ($cdn) {
|
||||||
$this->clear_cdn_hashes($message_media['file_token']);
|
$this->clear_cdn_hashes($message_media['file_token']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private $cdn_hashes = [];
|
private $cdn_hashes = [];
|
||||||
|
|
||||||
private function add_cdn_hashes($file, $hashes)
|
private function add_cdn_hashes($file, $hashes)
|
||||||
{
|
{
|
||||||
if (!isset($this->cdn_hashes[$file])) {
|
if (!isset($this->cdn_hashes[$file])) {
|
||||||
@ -396,7 +370,6 @@ trait Files
|
|||||||
$this->cdn_hashes[$file][$hash['offset']] = ['limit' => $hash['limit'], 'hash' => (string) $hash['hash']];
|
$this->cdn_hashes[$file][$hash['offset']] = ['limit' => $hash['limit'], 'hash' => (string) $hash['hash']];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function check_cdn_hash($file, $offset, $data, &$datacenter)
|
private function check_cdn_hash($file, $offset, $data, &$datacenter)
|
||||||
{
|
{
|
||||||
while (strlen($data)) {
|
while (strlen($data)) {
|
||||||
@ -404,23 +377,19 @@ trait Files
|
|||||||
$this->add_cdn_hashes($file, $this->method_call('upload.getCdnFileHashes', ['file_token' => $file, 'offset' => $offset], ['datacenter' => $datacenter]));
|
$this->add_cdn_hashes($file, $this->method_call('upload.getCdnFileHashes', ['file_token' => $file, 'offset' => $offset], ['datacenter' => $datacenter]));
|
||||||
}
|
}
|
||||||
if (!isset($this->cdn_hashes[$file][$offset])) {
|
if (!isset($this->cdn_hashes[$file][$offset])) {
|
||||||
throw new \danog\MadelineProto\Exception('Could not fetch CDN hashes for offset '.$offset);
|
throw new \danog\MadelineProto\Exception('Could not fetch CDN hashes for offset ' . $offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hash('sha256', substr($data, 0, $this->cdn_hashes[$file][$offset]['limit']), true) !== $this->cdn_hashes[$file][$offset]['hash']) {
|
if (hash('sha256', substr($data, 0, $this->cdn_hashes[$file][$offset]['limit']), true) !== $this->cdn_hashes[$file][$offset]['hash']) {
|
||||||
throw new \danog\MadelineProto\SecurityException('CDN hash mismatch for offset '.$offset);
|
throw new \danog\MadelineProto\SecurityException('CDN hash mismatch for offset ' . $offset);
|
||||||
}
|
}
|
||||||
$data = substr($data, $this->cdn_hashes[$file][$offset]['limit']);
|
$data = substr($data, $this->cdn_hashes[$file][$offset]['limit']);
|
||||||
$offset += $this->cdn_hashes[$file][$offset]['limit'];
|
$offset += $this->cdn_hashes[$file][$offset]['limit'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function clear_cdn_hashes($file)
|
private function clear_cdn_hashes($file)
|
||||||
{
|
{
|
||||||
unset($this->cdn_hashes[$file]);
|
unset($this->cdn_hashes[$file]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,11 +19,10 @@ trait MessageHandler
|
|||||||
{
|
{
|
||||||
public function send_unencrypted_message($message_data, $message_id, $datacenter)
|
public function send_unencrypted_message($message_data, $message_id, $datacenter)
|
||||||
{
|
{
|
||||||
$message_data = "\0\0\0\0\0\0\0\0".$message_id.$this->pack_unsigned_int(strlen($message_data)).$message_data;
|
$message_data = "\0\0\0\0\0\0\0\0" . $message_id . $this->pack_unsigned_int(strlen($message_data)) . $message_data;
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id] = ['response' => -1];
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id] = ['response' => -1];
|
||||||
$this->datacenter->sockets[$datacenter]->send_message($message_data);
|
$this->datacenter->sockets[$datacenter]->send_message($message_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function send_messages($datacenter)
|
public function send_messages($datacenter)
|
||||||
{
|
{
|
||||||
if (count($this->datacenter->sockets[$datacenter]->object_queue) > 1) {
|
if (count($this->datacenter->sockets[$datacenter]->object_queue) > 1) {
|
||||||
@ -46,27 +45,23 @@ trait MessageHandler
|
|||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$plaintext = $this->datacenter->sockets[$datacenter]->temp_auth_key['server_salt'] . $this->datacenter->sockets[$datacenter]->session_id . $message_id . pack('VV', $seq_no, strlen($message_data)) . $message_data;
|
||||||
$plaintext = $this->datacenter->sockets[$datacenter]->temp_auth_key['server_salt'].$this->datacenter->sockets[$datacenter]->session_id.$message_id.pack('VV', $seq_no, strlen($message_data)).$message_data;
|
|
||||||
$padding = $this->posmod(-strlen($plaintext), 16);
|
$padding = $this->posmod(-strlen($plaintext), 16);
|
||||||
if ($padding < 12) {
|
if ($padding < 12) {
|
||||||
$padding += 16;
|
$padding += 16;
|
||||||
}
|
}
|
||||||
$padding = $this->random($padding);
|
$padding = $this->random($padding);
|
||||||
|
$message_key = substr(hash('sha256', substr($this->datacenter->sockets[$datacenter]->temp_auth_key['auth_key'], 88, 32) . $plaintext . $padding, true), 8, 16);
|
||||||
$message_key = substr(hash('sha256', substr($this->datacenter->sockets[$datacenter]->temp_auth_key['auth_key'], 88, 32).$plaintext.$padding, true), 8, 16);
|
|
||||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->sockets[$datacenter]->temp_auth_key['auth_key']);
|
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->sockets[$datacenter]->temp_auth_key['auth_key']);
|
||||||
$message = $this->datacenter->sockets[$datacenter]->temp_auth_key['id'].$message_key.$this->ige_encrypt($plaintext.$padding, $aes_key, $aes_iv);
|
$message = $this->datacenter->sockets[$datacenter]->temp_auth_key['id'] . $message_key . $this->ige_encrypt($plaintext . $padding, $aes_key, $aes_iv);
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id] = ['seq_no' => $seq_no, 'response' => -1];
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$message_id] = ['seq_no' => $seq_no, 'response' => -1];
|
||||||
$this->datacenter->sockets[$datacenter]->send_message($message);
|
$this->datacenter->sockets[$datacenter]->send_message($message);
|
||||||
|
|
||||||
$this->datacenter->sockets[$datacenter]->object_queue = [];
|
$this->datacenter->sockets[$datacenter]->object_queue = [];
|
||||||
foreach ($this->datacenter->sockets[$datacenter]->ack_queue as $msg_id) {
|
foreach ($this->datacenter->sockets[$datacenter]->ack_queue as $msg_id) {
|
||||||
$this->datacenter->sockets[$datacenter]->incoming_messages[$msg_id]['ack'] = true;
|
$this->datacenter->sockets[$datacenter]->incoming_messages[$msg_id]['ack'] = true;
|
||||||
}
|
}
|
||||||
$this->datacenter->sockets[$datacenter]->ack_queue = [];
|
$this->datacenter->sockets[$datacenter]->ack_queue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reading connection and receiving message from server.
|
* Reading connection and receiving message from server.
|
||||||
*/
|
*/
|
||||||
@ -98,37 +93,28 @@ trait MessageHandler
|
|||||||
if ($session_id != $this->datacenter->sockets[$datacenter]->session_id) {
|
if ($session_id != $this->datacenter->sockets[$datacenter]->session_id) {
|
||||||
throw new \danog\MadelineProto\Exception('Session id mismatch.');
|
throw new \danog\MadelineProto\Exception('Session id mismatch.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$message_id = substr($decrypted_data, 16, 8);
|
$message_id = substr($decrypted_data, 16, 8);
|
||||||
$this->check_message_id($message_id, ['outgoing' => false, 'datacenter' => $datacenter, 'container' => false]);
|
$this->check_message_id($message_id, ['outgoing' => false, 'datacenter' => $datacenter, 'container' => false]);
|
||||||
|
|
||||||
$seq_no = unpack('V', substr($decrypted_data, 24, 4))[1];
|
$seq_no = unpack('V', substr($decrypted_data, 24, 4))[1];
|
||||||
// Dunno how to handle any incorrect sequence numbers
|
// Dunno how to handle any incorrect sequence numbers
|
||||||
|
|
||||||
$message_data_length = unpack('V', substr($decrypted_data, 28, 4))[1];
|
$message_data_length = unpack('V', substr($decrypted_data, 28, 4))[1];
|
||||||
|
|
||||||
if ($message_data_length > strlen($decrypted_data)) {
|
if ($message_data_length > strlen($decrypted_data)) {
|
||||||
throw new \danog\MadelineProto\SecurityException('message_data_length is too big');
|
throw new \danog\MadelineProto\SecurityException('message_data_length is too big');
|
||||||
}
|
}
|
||||||
|
if (strlen($decrypted_data) - 32 - $message_data_length < 12) {
|
||||||
if ((strlen($decrypted_data) - 32) - $message_data_length < 12) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException('padding is too small');
|
throw new \danog\MadelineProto\SecurityException('padding is too small');
|
||||||
}
|
}
|
||||||
|
if (strlen($decrypted_data) - 32 - $message_data_length > 1024) {
|
||||||
if ((strlen($decrypted_data) - 32) - $message_data_length > 1024) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException('padding is too big');
|
throw new \danog\MadelineProto\SecurityException('padding is too big');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message_data_length < 0) {
|
if ($message_data_length < 0) {
|
||||||
throw new \danog\MadelineProto\SecurityException('message_data_length not positive');
|
throw new \danog\MadelineProto\SecurityException('message_data_length not positive');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message_data_length % 4 != 0) {
|
if ($message_data_length % 4 != 0) {
|
||||||
throw new \danog\MadelineProto\SecurityException('message_data_length not divisible by 4');
|
throw new \danog\MadelineProto\SecurityException('message_data_length not divisible by 4');
|
||||||
}
|
}
|
||||||
|
|
||||||
$message_data = substr($decrypted_data, 32, $message_data_length);
|
$message_data = substr($decrypted_data, 32, $message_data_length);
|
||||||
if ($message_key != substr(hash('sha256', substr($this->datacenter->sockets[$datacenter]->temp_auth_key['auth_key'], 96, 32).$decrypted_data, true), 8, 16)) {
|
if ($message_key != substr(hash('sha256', substr($this->datacenter->sockets[$datacenter]->temp_auth_key['auth_key'], 96, 32) . $decrypted_data, true), 8, 16)) {
|
||||||
throw new \danog\MadelineProto\SecurityException('msg_key mismatch');
|
throw new \danog\MadelineProto\SecurityException('msg_key mismatch');
|
||||||
}
|
}
|
||||||
$this->datacenter->sockets[$datacenter]->incoming_messages[$message_id] = ['seq_no' => $seq_no];
|
$this->datacenter->sockets[$datacenter]->incoming_messages[$message_id] = ['seq_no' => $seq_no];
|
||||||
@ -141,7 +127,6 @@ trait MessageHandler
|
|||||||
$this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['response'] = -1;
|
$this->datacenter->sockets[$datacenter]->incoming_messages[$message_id]['response'] = -1;
|
||||||
$this->datacenter->sockets[$datacenter]->new_incoming[$message_id] = $message_id;
|
$this->datacenter->sockets[$datacenter]->new_incoming[$message_id] = $message_id;
|
||||||
$this->last_recv = time();
|
$this->last_recv = time();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,18 +24,18 @@ trait MsgIdHandler
|
|||||||
}
|
}
|
||||||
$min_message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$aargs['datacenter']]->time_delta - 300))->bitwise_leftShift(32);
|
$min_message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$aargs['datacenter']]->time_delta - 300))->bitwise_leftShift(32);
|
||||||
if ($min_message_id->compare($new_message_id) > 0) {
|
if ($min_message_id->compare($new_message_id) > 0) {
|
||||||
\danog\MadelineProto\Logger::log(['Given message id ('.$new_message_id.') is too old compared to the min value ('.$min_message_id.').'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Given message id (' . $new_message_id . ') is too old compared to the min value (' . $min_message_id . ').'], \danog\MadelineProto\Logger::WARNING);
|
||||||
}
|
}
|
||||||
$max_message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$aargs['datacenter']]->time_delta + 30))->bitwise_leftShift(32);
|
$max_message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$aargs['datacenter']]->time_delta + 30))->bitwise_leftShift(32);
|
||||||
if ($max_message_id->compare($new_message_id) < 0) {
|
if ($max_message_id->compare($new_message_id) < 0) {
|
||||||
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is too new compared to the max value ('.$max_message_id.'). Consider syncing your date.');
|
throw new \danog\MadelineProto\Exception('Given message id (' . $new_message_id . ') is too new compared to the max value (' . $max_message_id . '). Consider syncing your date.');
|
||||||
}
|
}
|
||||||
if ($aargs['outgoing']) {
|
if ($aargs['outgoing']) {
|
||||||
if (!$new_message_id->divide($this->four)[1]->equals($this->zero)) {
|
if (!$new_message_id->divide($this->four)[1]->equals($this->zero)) {
|
||||||
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is not divisible by 4. Consider syncing your date.');
|
throw new \danog\MadelineProto\Exception('Given message id (' . $new_message_id . ') is not divisible by 4. Consider syncing your date.');
|
||||||
}
|
}
|
||||||
if (!\danog\MadelineProto\Logger::$has_thread && $new_message_id->compare($key = $this->get_max_id($aargs['datacenter'], false)) <= 0) {
|
if (!\danog\MadelineProto\Logger::$has_thread && $new_message_id->compare($key = $this->get_max_id($aargs['datacenter'], false)) <= 0) {
|
||||||
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is lower than or equal to the current limit ('.$key.'). Consider syncing your date.', 1);
|
throw new \danog\MadelineProto\Exception('Given message id (' . $new_message_id . ') is lower than or equal to the current limit (' . $key . '). Consider syncing your date.', 1);
|
||||||
}
|
}
|
||||||
if (count($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages) > $this->settings['msg_array_limit']['outgoing']) {
|
if (count($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages) > $this->settings['msg_array_limit']['outgoing']) {
|
||||||
reset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages);
|
reset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages);
|
||||||
@ -51,14 +51,13 @@ trait MsgIdHandler
|
|||||||
$key = $this->get_max_id($aargs['datacenter'], true);
|
$key = $this->get_max_id($aargs['datacenter'], true);
|
||||||
if ($aargs['container']) {
|
if ($aargs['container']) {
|
||||||
if ($new_message_id->compare($key = $this->get_max_id($aargs['datacenter'], true)) >= 0) {
|
if ($new_message_id->compare($key = $this->get_max_id($aargs['datacenter'], true)) >= 0) {
|
||||||
\danog\MadelineProto\Logger::log(['WARNING: Given message id ('.$new_message_id.') is bigger than or equal to the current limit ('.$key.'). Consider syncing your date.'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['WARNING: Given message id (' . $new_message_id . ') is bigger than or equal to the current limit (' . $key . '). Consider syncing your date.'], \danog\MadelineProto\Logger::WARNING);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ($new_message_id->compare($key = $this->get_max_id($aargs['datacenter'], true)) <= 0) {
|
if ($new_message_id->compare($key = $this->get_max_id($aargs['datacenter'], true)) <= 0) {
|
||||||
\danog\MadelineProto\Logger::log(['WARNING: Given message id ('.$new_message_id.') is lower than or equal to the current limit ('.$key.'). Consider syncing your date.'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['WARNING: Given message id (' . $new_message_id . ') is lower than or equal to the current limit (' . $key . '). Consider syncing your date.'], \danog\MadelineProto\Logger::WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages) > $this->settings['msg_array_limit']['incoming']) {
|
if (count($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages) > $this->settings['msg_array_limit']['incoming']) {
|
||||||
reset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages);
|
reset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages);
|
||||||
$key = key($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages);
|
$key = key($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages);
|
||||||
@ -71,7 +70,6 @@ trait MsgIdHandler
|
|||||||
$this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[strrev($new_message_id->toBytes())] = [];
|
$this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[strrev($new_message_id->toBytes())] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate_message_id($datacenter)
|
public function generate_message_id($datacenter)
|
||||||
{
|
{
|
||||||
$message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$datacenter]->time_delta))->bitwise_leftShift(32);
|
$message_id = (new \phpseclib\Math\BigInteger(time() + $this->datacenter->sockets[$datacenter]->time_delta))->bitwise_leftShift(32);
|
||||||
@ -79,17 +77,14 @@ trait MsgIdHandler
|
|||||||
$message_id = $key->add($this->four);
|
$message_id = $key->add($this->four);
|
||||||
}
|
}
|
||||||
$this->check_message_id($message_id, ['outgoing' => true, 'datacenter' => $datacenter, 'container' => false]);
|
$this->check_message_id($message_id, ['outgoing' => true, 'datacenter' => $datacenter, 'container' => false]);
|
||||||
|
|
||||||
return strrev($message_id->toBytes());
|
return strrev($message_id->toBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_max_id($datacenter, $incoming)
|
public function get_max_id($datacenter, $incoming)
|
||||||
{
|
{
|
||||||
$incoming = $incoming ? 'incoming' : 'outgoing';
|
$incoming = $incoming ? 'incoming' : 'outgoing';
|
||||||
if (isset($this->datacenter->sockets[$datacenter]->{'max_'.$incoming.'_id'}) && is_object($this->datacenter->sockets[$datacenter]->{'max_'.$incoming.'_id'})) {
|
if (isset($this->datacenter->sockets[$datacenter]->{'max_' . $incoming . '_id'}) && is_object($this->datacenter->sockets[$datacenter]->{'max_' . $incoming . '_id'})) {
|
||||||
return $this->datacenter->sockets[$datacenter]->{'max_'.$incoming.'_id'};
|
return $this->datacenter->sockets[$datacenter]->{'max_' . $incoming . '_id'};
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->zero;
|
return $this->zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,7 +30,6 @@ trait PeerHandler
|
|||||||
case 'user':
|
case 'user':
|
||||||
if (!isset($this->chats[$user['id']]) || $this->chats[$user['id']] !== $user) {
|
if (!isset($this->chats[$user['id']]) || $this->chats[$user['id']] !== $user) {
|
||||||
$this->chats[$user['id']] = $user;
|
$this->chats[$user['id']] = $user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->get_pwr_chat($user['id'], false, true);
|
$this->get_pwr_chat($user['id'], false, true);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
@ -42,12 +41,11 @@ trait PeerHandler
|
|||||||
case 'userEmpty':
|
case 'userEmpty':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\Exception('Invalid user provided at key '.$key.': '.var_export($user, true));
|
throw new \danog\MadelineProto\Exception('Invalid user provided at key ' . $key . ': ' . var_export($user, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add_chats($chats)
|
public function add_chats($chats)
|
||||||
{
|
{
|
||||||
foreach ($chats as $key => $chat) {
|
foreach ($chats as $key => $chat) {
|
||||||
@ -57,7 +55,6 @@ trait PeerHandler
|
|||||||
case 'chatForbidden':
|
case 'chatForbidden':
|
||||||
if (!isset($this->chats[-$chat['id']]) || $this->chats[-$chat['id']] !== $chat) {
|
if (!isset($this->chats[-$chat['id']]) || $this->chats[-$chat['id']] !== $chat) {
|
||||||
$this->chats[-$chat['id']] = $chat;
|
$this->chats[-$chat['id']] = $chat;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->get_pwr_chat(-$chat['id'], $this->settings['peer']['full_fetch'], true);
|
$this->get_pwr_chat(-$chat['id'], $this->settings['peer']['full_fetch'], true);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
@ -66,7 +63,6 @@ trait PeerHandler
|
|||||||
\danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'channelEmpty':
|
case 'channelEmpty':
|
||||||
break;
|
break;
|
||||||
case 'channel':
|
case 'channel':
|
||||||
@ -80,7 +76,6 @@ trait PeerHandler
|
|||||||
}
|
}
|
||||||
if (!isset($this->chats[$bot_api_id]) || $this->chats[$bot_api_id] !== $chat) {
|
if (!isset($this->chats[$bot_api_id]) || $this->chats[$bot_api_id] !== $chat) {
|
||||||
$this->chats[$bot_api_id] = $chat;
|
$this->chats[$bot_api_id] = $chat;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!isset($this->full_chats[$bot_api_id]) || $this->full_chats[$bot_api_id]['full']['participants_count'] !== $this->get_full_info($bot_api_id)['full']['participants_count']) {
|
if (!isset($this->full_chats[$bot_api_id]) || $this->full_chats[$bot_api_id]['full']['participants_count'] !== $this->get_full_info($bot_api_id)['full']['participants_count']) {
|
||||||
$this->get_pwr_chat($this->to_supergroup($chat['id']), $this->settings['peer']['full_fetch'], true);
|
$this->get_pwr_chat($this->to_supergroup($chat['id']), $this->settings['peer']['full_fetch'], true);
|
||||||
@ -93,12 +88,11 @@ trait PeerHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\Exception('Invalid chat provided at key '.$key.': '.var_export($chat, true));
|
throw new \danog\MadelineProto\Exception('Invalid chat provided at key ' . $key . ': ' . var_export($chat, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function peer_isset($id)
|
public function peer_isset($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -109,7 +103,6 @@ trait PeerHandler
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entities_peer_isset($entities)
|
public function entities_peer_isset($entities)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -123,10 +116,8 @@ trait PeerHandler
|
|||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fwd_peer_isset($fwd)
|
public function fwd_peer_isset($fwd)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -139,10 +130,8 @@ trait PeerHandler
|
|||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_info($id, $recursive = true)
|
public function get_info($id, $recursive = true)
|
||||||
{
|
{
|
||||||
if (is_array($id)) {
|
if (is_array($id)) {
|
||||||
@ -162,47 +151,42 @@ trait PeerHandler
|
|||||||
case 'peerUser':
|
case 'peerUser':
|
||||||
$id = $id['user_id'];
|
$id = $id['user_id'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'chat':
|
case 'chat':
|
||||||
case 'chatFull':
|
case 'chatFull':
|
||||||
$id = -$id['id'];
|
$id = -$id['id'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'inputPeerChat':
|
case 'inputPeerChat':
|
||||||
case 'peerChat':
|
case 'peerChat':
|
||||||
$id = -$id['chat_id'];
|
$id = -$id['chat_id'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'channel':
|
case 'channel':
|
||||||
case 'channelFull':
|
case 'channelFull':
|
||||||
$id = $this->to_supergroup($id['id']);
|
$id = $this->to_supergroup($id['id']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'inputPeerChannel':
|
case 'inputPeerChannel':
|
||||||
case 'inputChannel':
|
case 'inputChannel':
|
||||||
case 'peerChannel':
|
case 'peerChannel':
|
||||||
$id = $this->to_supergroup($id['channel_id']);
|
$id = $this->to_supergroup($id['channel_id']);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\Exception('Invalid constructor given '.var_export($id, true));
|
throw new \danog\MadelineProto\Exception('Invalid constructor given ' . var_export($id, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_string($id) && strpos($id, '#') !== false) {
|
if (is_string($id) && strpos($id, '#') !== false) {
|
||||||
if (preg_match('/^channel#/', $id)) {
|
if (preg_match('/^channel#/', $id)) {
|
||||||
$id = $this->to_supergroup(preg_replace('|\D+|', '', $id));
|
$id = $this->to_supergroup(preg_replace('|\\D+|', '', $id));
|
||||||
}
|
}
|
||||||
if (preg_match('/^chat#/', $id)) {
|
if (preg_match('/^chat#/', $id)) {
|
||||||
$id = preg_replace('|\D+|', '-', $id);
|
$id = preg_replace('|\\D+|', '-', $id);
|
||||||
}
|
}
|
||||||
if (preg_match('/^user#/', $id)) {
|
if (preg_match('/^user#/', $id)) {
|
||||||
$id = preg_replace('|\D+|', '', $id);
|
$id = preg_replace('|\\D+|', '', $id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_numeric($id)) {
|
if (is_numeric($id)) {
|
||||||
if (is_string($id)) {
|
if (is_string($id)) {
|
||||||
$id = \danog\MadelineProto\Logger::$bigint ? ((float) $id) : ((int) $id);
|
$id = \danog\MadelineProto\Logger::$bigint ? (double) $id : (int) $id;
|
||||||
}
|
}
|
||||||
if (!isset($this->chats[$id]) && $id < 0 && !preg_match('/^-100/', $id)) {
|
if (!isset($this->chats[$id]) && $id < 0 && !preg_match('/^-100/', $id)) {
|
||||||
$this->method_call('messages.getFullChat', ['chat_id' => -$id], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.getFullChat', ['chat_id' => -$id], ['datacenter' => $this->datacenter->curdc]);
|
||||||
@ -211,15 +195,11 @@ trait PeerHandler
|
|||||||
return $this->gen_all($this->chats[$id]);
|
return $this->gen_all($this->chats[$id]);
|
||||||
}
|
}
|
||||||
if (!isset($this->settings['pwr']['requests']) || $this->settings['pwr']['requests'] === true) {
|
if (!isset($this->settings['pwr']['requests']) || $this->settings['pwr']['requests'] === true) {
|
||||||
$dbres = json_decode(@file_get_contents('https://id.pwrtelegram.xyz/db/getusername?id='.$id, false, stream_context_create(['http' => [
|
$dbres = json_decode(@file_get_contents('https://id.pwrtelegram.xyz/db/getusername?id=' . $id, false, stream_context_create(['http' => ['timeout' => 2]])), true);
|
||||||
'timeout' => 2,
|
|
||||||
],
|
|
||||||
])), true);
|
|
||||||
if (isset($dbres['ok']) && $dbres['ok']) {
|
if (isset($dbres['ok']) && $dbres['ok']) {
|
||||||
return $this->get_info('@'.$dbres['result']);
|
return $this->get_info('@' . $dbres['result']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
||||||
}
|
}
|
||||||
$id = strtolower(str_replace('@', '', $id));
|
$id = strtolower(str_replace('@', '', $id));
|
||||||
@ -230,13 +210,10 @@ trait PeerHandler
|
|||||||
}
|
}
|
||||||
if ($recursive) {
|
if ($recursive) {
|
||||||
$this->resolve_username($id);
|
$this->resolve_username($id);
|
||||||
|
|
||||||
return $this->get_info($id, false);
|
return $this->get_info($id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function gen_all($constructor)
|
public function gen_all($constructor)
|
||||||
{
|
{
|
||||||
$res = [$this->constructors->find_by_predicate($constructor['_'])['type'] => $constructor];
|
$res = [$this->constructors->find_by_predicate($constructor['_'])['type'] => $constructor];
|
||||||
@ -278,20 +255,16 @@ trait PeerHandler
|
|||||||
case 'channelForbidden':
|
case 'channelForbidden':
|
||||||
throw new \danog\MadelineProto\Exception('Chat forbidden');
|
throw new \danog\MadelineProto\Exception('Chat forbidden');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\Exception('Invalid constructor given '.var_export($constructor, true));
|
throw new \danog\MadelineProto\Exception('Invalid constructor given ' . var_export($constructor, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function full_chat_last_updated($id)
|
public function full_chat_last_updated($id)
|
||||||
{
|
{
|
||||||
return isset($this->full_chats[$id]['last_update']) ? $this->full_chats[$id]['last_update'] : 0;
|
return isset($this->full_chats[$id]['last_update']) ? $this->full_chats[$id]['last_update'] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_full_info($id)
|
public function get_full_info($id)
|
||||||
{
|
{
|
||||||
$partial = $this->get_info($id);
|
$partial = $this->get_info($id);
|
||||||
@ -303,11 +276,9 @@ trait PeerHandler
|
|||||||
case 'bot':
|
case 'bot':
|
||||||
$full = $this->method_call('users.getFullUser', ['id' => $partial['InputUser']], ['datacenter' => $this->datacenter->curdc]);
|
$full = $this->method_call('users.getFullUser', ['id' => $partial['InputUser']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'chat':
|
case 'chat':
|
||||||
$full = $this->method_call('messages.getFullChat', $partial, ['datacenter' => $this->datacenter->curdc])['full_chat'];
|
$full = $this->method_call('messages.getFullChat', $partial, ['datacenter' => $this->datacenter->curdc])['full_chat'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'channel':
|
case 'channel':
|
||||||
case 'supergroup':
|
case 'supergroup':
|
||||||
$full = $this->method_call('channels.getFullChannel', ['channel' => $partial['InputChannel']], ['datacenter' => $this->datacenter->curdc])['full_chat'];
|
$full = $this->method_call('channels.getFullChannel', ['channel' => $partial['InputChannel']], ['datacenter' => $this->datacenter->curdc])['full_chat'];
|
||||||
@ -317,10 +288,8 @@ trait PeerHandler
|
|||||||
$res['full'] = $full;
|
$res['full'] = $full;
|
||||||
$res['last_update'] = time();
|
$res['last_update'] = time();
|
||||||
$this->full_chats[$partial['bot_api_id']] = $res;
|
$this->full_chats[$partial['bot_api_id']] = $res;
|
||||||
|
|
||||||
return array_merge($partial, $res);
|
return array_merge($partial, $res);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_pwr_chat($id, $fullfetch = true, $send = true)
|
public function get_pwr_chat($id, $fullfetch = true, $send = true)
|
||||||
{
|
{
|
||||||
$full = $fullfetch ? $this->get_full_info($id) : $this->get_info($id);
|
$full = $fullfetch ? $this->get_full_info($id) : $this->get_info($id);
|
||||||
@ -372,7 +341,6 @@ trait PeerHandler
|
|||||||
if (isset($res['admins_enabled'])) {
|
if (isset($res['admins_enabled'])) {
|
||||||
$res['all_members_are_administrators'] = $res['admins_enabled'];
|
$res['all_members_are_administrators'] = $res['admins_enabled'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($full['full']['chat_photo']['sizes'])) {
|
if (isset($full['full']['chat_photo']['sizes'])) {
|
||||||
$res['photo'] = $this->photosize_to_botapi(end($full['full']['chat_photo']['sizes']), []);
|
$res['photo'] = $this->photosize_to_botapi(end($full['full']['chat_photo']['sizes']), []);
|
||||||
}
|
}
|
||||||
@ -395,7 +363,6 @@ trait PeerHandler
|
|||||||
$res[$key] = $full['full'][$key];
|
$res[$key] = $full['full'][$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($full['full']['chat_photo']['sizes'])) {
|
if (isset($full['full']['chat_photo']['sizes'])) {
|
||||||
$res['photo'] = $this->photosize_to_botapi(end($full['full']['chat_photo']['sizes']), []);
|
$res['photo'] = $this->photosize_to_botapi(end($full['full']['chat_photo']['sizes']), []);
|
||||||
}
|
}
|
||||||
@ -439,11 +406,9 @@ trait PeerHandler
|
|||||||
case 'chatParticipant':
|
case 'chatParticipant':
|
||||||
$newres['role'] = 'user';
|
$newres['role'] = 'user';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'chatParticipantAdmin':
|
case 'chatParticipantAdmin':
|
||||||
$newres['role'] = 'admin';
|
$newres['role'] = 'admin';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'chatParticipantCreator':
|
case 'chatParticipantCreator':
|
||||||
$newres['role'] = 'creator';
|
$newres['role'] = 'creator';
|
||||||
break;
|
break;
|
||||||
@ -457,7 +422,6 @@ trait PeerHandler
|
|||||||
$filters = ['channelParticipantsRecent', 'channelParticipantsAdmins', 'channelParticipantsKicked', 'channelParticipantsBots', 'channelParticipantsBanned'];
|
$filters = ['channelParticipantsRecent', 'channelParticipantsAdmins', 'channelParticipantsKicked', 'channelParticipantsBots', 'channelParticipantsBanned'];
|
||||||
foreach ($filters as $filter) {
|
foreach ($filters as $filter) {
|
||||||
$offset = -$limit;
|
$offset = -$limit;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$gres = $this->method_call('channels.getParticipants', ['channel' => $full['InputChannel'], 'filter' => ['_' => $filter, 'q' => ''], 'offset' => $offset += $limit, 'limit' => $limit, 'hash' => 0], ['datacenter' => $this->datacenter->curdc]);
|
$gres = $this->method_call('channels.getParticipants', ['channel' => $full['InputChannel'], 'filter' => ['_' => $filter, 'q' => ''], 'offset' => $offset += $limit, 'limit' => $limit, 'hash' => 0], ['datacenter' => $this->datacenter->curdc]);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
@ -494,28 +458,22 @@ trait PeerHandler
|
|||||||
$newres['banned_rights'] = $full['Chat']['banned_rights'];
|
$newres['banned_rights'] = $full['Chat']['banned_rights'];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'channelParticipant':
|
case 'channelParticipant':
|
||||||
$newres['role'] = 'user';
|
$newres['role'] = 'user';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'channelParticipantCreator':
|
case 'channelParticipantCreator':
|
||||||
$newres['role'] = 'creator';
|
$newres['role'] = 'creator';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'channelParticipantAdmin':
|
case 'channelParticipantAdmin':
|
||||||
$newres['role'] = 'admin';
|
$newres['role'] = 'admin';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'channelParticipantBanned':
|
case 'channelParticipantBanned':
|
||||||
$newres['role'] = 'banned';
|
$newres['role'] = 'banned';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
$res['participants'][$participant['user_id']] = $newres;
|
$res['participants'][$participant['user_id']] = $newres;
|
||||||
}
|
}
|
||||||
$gres = $this->method_call('channels.getParticipants', ['channel' => $full['InputChannel'], 'filter' => ['_' => $filter, 'q' => ''], 'offset' => $offset += $limit, 'limit' => $limit, 'hash' => 0], ['datacenter' => $this->datacenter->curdc]);
|
$gres = $this->method_call('channels.getParticipants', ['channel' => $full['InputChannel'], 'filter' => ['_' => $filter, 'q' => ''], 'offset' => $offset += $limit, 'limit' => $limit, 'hash' => 0], ['datacenter' => $this->datacenter->curdc]);
|
||||||
|
|
||||||
if (empty($gres['participants'])) {
|
if (empty($gres['participants'])) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -529,10 +487,8 @@ trait PeerHandler
|
|||||||
if ($fullfetch || $send) {
|
if ($fullfetch || $send) {
|
||||||
$this->store_db($res);
|
$this->store_db($res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store_db($res, $force = false)
|
public function store_db($res, $force = false)
|
||||||
{
|
{
|
||||||
$settings = isset($this->settings['connection_settings'][$this->datacenter->curdc]) ? $this->settings['connection_settings'][$this->datacenter->curdc] : $this->settings['connection_settings']['all'];
|
$settings = isset($this->settings['connection_settings'][$this->datacenter->curdc]) ? $this->settings['connection_settings'][$this->datacenter->curdc] : $this->settings['connection_settings']['all'];
|
||||||
@ -560,13 +516,12 @@ trait PeerHandler
|
|||||||
if (empty($this->qres)) {
|
if (empty($this->qres)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$payload = json_encode($this->qres);
|
$payload = json_encode($this->qres);
|
||||||
$path = '/tmp/ids'.hash('sha256', $payload);
|
$path = '/tmp/ids' . hash('sha256', $payload);
|
||||||
file_put_contents($path, $payload);
|
file_put_contents($path, $payload);
|
||||||
$id = isset($this->authorization['user']['username']) ? $this->authorization['user']['username'] : $this->authorization['user']['id'];
|
$id = isset($this->authorization['user']['username']) ? $this->authorization['user']['username'] : $this->authorization['user']['id'];
|
||||||
$result = shell_exec('curl '.escapeshellarg('https://id.pwrtelegram.xyz/db'.$this->settings['pwr']['db_token'].'/addnewmadeline?d=pls&from='.$id).' -d '.escapeshellarg('@'.$path).' -s -o '.escapeshellarg($path.'.log').' >/dev/null 2>/dev/null & ');
|
$result = shell_exec('curl ' . escapeshellarg('https://id.pwrtelegram.xyz/db' . $this->settings['pwr']['db_token'] . '/addnewmadeline?d=pls&from=' . $id) . ' -d ' . escapeshellarg('@' . $path) . ' -s -o ' . escapeshellarg($path . '.log') . ' >/dev/null 2>/dev/null & ');
|
||||||
\danog\MadelineProto\Logger::log([$result], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([$result], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
\danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([$e->getMessage()], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
@ -574,7 +529,6 @@ trait PeerHandler
|
|||||||
$this->qres = [];
|
$this->qres = [];
|
||||||
$this->last_stored = time() + 10;
|
$this->last_stored = time() + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resolve_username($username)
|
public function resolve_username($username)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -585,10 +539,8 @@ trait PeerHandler
|
|||||||
if ($res['_'] === 'contacts.resolvedPeer') {
|
if ($res['_'] === 'contacts.resolvedPeer') {
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function to_supergroup($id)
|
public function to_supergroup($id)
|
||||||
{
|
{
|
||||||
return -($id + pow(10, (int) floor(log($id, 10) + 3)));
|
return -($id + pow(10, (int) floor(log($id, 10) + 3)));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,13 +41,12 @@ trait ResponseHandler
|
|||||||
}
|
}
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->object_call('msgs_state_info', ['req_msg_id' => $req_msg_id, 'info' => $info], ['datacenter' => $datacenter])]['response'] = $req_msg_id;
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->object_call('msgs_state_info', ['req_msg_id' => $req_msg_id, 'info' => $info], ['datacenter' => $datacenter])]['response'] = $req_msg_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_messages($datacenter)
|
public function handle_messages($datacenter)
|
||||||
{
|
{
|
||||||
$only_updates = true;
|
$only_updates = true;
|
||||||
foreach ($this->datacenter->sockets[$datacenter]->new_incoming as $current_msg_id) {
|
foreach ($this->datacenter->sockets[$datacenter]->new_incoming as $current_msg_id) {
|
||||||
$unset = false;
|
$unset = false;
|
||||||
\danog\MadelineProto\Logger::log(['Received '.$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'].'.'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Received ' . $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'] . '.'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
//\danog\MadelineProto\Logger::log([$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
//\danog\MadelineProto\Logger::log([$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
if (\danog\MadelineProto\Logger::$has_thread && is_object(\Thread::getCurrentThread())) {
|
||||||
if (!$this->synchronized(function ($zis, $datacenter, $current_msg_id) {
|
if (!$this->synchronized(function ($zis, $datacenter, $current_msg_id) {
|
||||||
@ -55,13 +54,12 @@ trait ResponseHandler
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['handling'] = true;
|
$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['handling'] = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, $this, $datacenter, $current_msg_id)) {
|
}, $this, $datacenter, $current_msg_id)) {
|
||||||
\danog\MadelineProto\Logger::log([base64_encode($current_msg_id).$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'].' is already being handled'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([base64_encode($current_msg_id) . $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'] . ' is already being handled'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Handling '.base64_encode($current_msg_id).$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'].'.'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Handling ' . base64_encode($current_msg_id) . $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'] . '.'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
}
|
}
|
||||||
switch ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_']) {
|
switch ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_']) {
|
||||||
case 'msgs_ack':
|
case 'msgs_ack':
|
||||||
@ -69,15 +67,17 @@ trait ResponseHandler
|
|||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
foreach ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_ids'] as $msg_id) {
|
foreach ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_ids'] as $msg_id) {
|
||||||
$this->ack_outgoing_message_id($msg_id, $datacenter); // Acknowledge that the server received my message
|
$this->ack_outgoing_message_id($msg_id, $datacenter);
|
||||||
|
// Acknowledge that the server received my message
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'rpc_result':
|
case 'rpc_result':
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]);
|
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]);
|
||||||
$this->ack_incoming_message_id($current_msg_id, $datacenter); // Acknowledge that I received the server's response
|
$this->ack_incoming_message_id($current_msg_id, $datacenter);
|
||||||
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id'], $datacenter); // Acknowledge that the server received my request
|
// Acknowledge that I received the server's response
|
||||||
|
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id'], $datacenter);
|
||||||
|
// Acknowledge that the server received my request
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]['response'] = $current_msg_id;
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]['response'] = $current_msg_id;
|
||||||
$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content'] = $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['result'];
|
$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content'] = $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['result'];
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
@ -88,35 +88,36 @@ trait ResponseHandler
|
|||||||
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]);
|
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]);
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id'], $datacenter); // Acknowledge that the server received my request
|
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id'], $datacenter);
|
||||||
|
// Acknowledge that the server received my request
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]['response'] = $current_msg_id;
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['req_msg_id']]['response'] = $current_msg_id;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bad_server_salt':
|
case 'bad_server_salt':
|
||||||
case 'bad_msg_notification':
|
case 'bad_msg_notification':
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['bad_msg_id'], $datacenter); // Acknowledge that the server received my request
|
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['bad_msg_id'], $datacenter);
|
||||||
|
// Acknowledge that the server received my request
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['bad_msg_id']]['response'] = $current_msg_id;
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['bad_msg_id']]['response'] = $current_msg_id;
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['bad_msg_id']]);
|
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['bad_msg_id']]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'pong':
|
case 'pong':
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_id']]);
|
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_id']]);
|
||||||
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_id'], $datacenter); // Acknowledge that the server received my request
|
$this->ack_outgoing_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_id'], $datacenter);
|
||||||
|
// Acknowledge that the server received my request
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_id']]['response'] = $current_msg_id;
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_id']]['response'] = $current_msg_id;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'new_session_created':
|
case 'new_session_created':
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
$this->datacenter->sockets[$datacenter]->temp_auth_key['server_salt'] = $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['server_salt'];
|
$this->datacenter->sockets[$datacenter]->temp_auth_key['server_salt'] = $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['server_salt'];
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
$this->ack_incoming_message_id($current_msg_id, $datacenter); // Acknowledge that I received the server's response
|
$this->ack_incoming_message_id($current_msg_id, $datacenter);
|
||||||
|
// Acknowledge that I received the server's response
|
||||||
if ($this->authorized === self::LOGGED_IN && !$this->initing_authorization && $this->datacenter->sockets[$this->datacenter->curdc]->temp_auth_key !== null) {
|
if ($this->authorized === self::LOGGED_IN && !$this->initing_authorization && $this->datacenter->sockets[$this->datacenter->curdc]->temp_auth_key !== null) {
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
}
|
}
|
||||||
@ -128,7 +129,6 @@ trait ResponseHandler
|
|||||||
$this->check_message_id($message['msg_id'], ['outgoing' => false, 'datacenter' => $datacenter, 'container' => true]);
|
$this->check_message_id($message['msg_id'], ['outgoing' => false, 'datacenter' => $datacenter, 'container' => true]);
|
||||||
$this->datacenter->sockets[$datacenter]->incoming_messages[$message['msg_id']] = ['seq_no' => $message['seqno'], 'content' => $message['body']];
|
$this->datacenter->sockets[$datacenter]->incoming_messages[$message['msg_id']] = ['seq_no' => $message['seqno'], 'content' => $message['body']];
|
||||||
$this->datacenter->sockets[$datacenter]->new_incoming[$message['msg_id']] = $message['msg_id'];
|
$this->datacenter->sockets[$datacenter]->new_incoming[$message['msg_id']] = $message['msg_id'];
|
||||||
|
|
||||||
$this->handle_messages($datacenter);
|
$this->handle_messages($datacenter);
|
||||||
}
|
}
|
||||||
$unset = true;
|
$unset = true;
|
||||||
@ -138,14 +138,15 @@ trait ResponseHandler
|
|||||||
case 'msg_copy':
|
case 'msg_copy':
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
$this->ack_incoming_message_id($current_msg_id, $datacenter); // Acknowledge that I received the server's response
|
$this->ack_incoming_message_id($current_msg_id, $datacenter);
|
||||||
|
// Acknowledge that I received the server's response
|
||||||
if (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']['msg_id']])) {
|
if (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']['msg_id']])) {
|
||||||
$this->ack_incoming_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']['msg_id'], $datacenter); // Acknowledge that I received the server's response
|
$this->ack_incoming_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']['msg_id'], $datacenter);
|
||||||
|
// Acknowledge that I received the server's response
|
||||||
} else {
|
} else {
|
||||||
$this->check_message_id($message['orig_message']['msg_id'], ['outgoing' => false, 'datacenter' => $datacenter, 'container' => true]);
|
$this->check_message_id($message['orig_message']['msg_id'], ['outgoing' => false, 'datacenter' => $datacenter, 'container' => true]);
|
||||||
$this->datacenter->sockets[$datacenter]->incoming_messages[$message['orig_message']['msg_id']] = ['content' => $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']];
|
$this->datacenter->sockets[$datacenter]->incoming_messages[$message['orig_message']['msg_id']] = ['content' => $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']];
|
||||||
$this->datacenter->sockets[$datacenter]->new_incoming[$message['orig_message']['msg_id']] = $message['orig_message']['msg_id'];
|
$this->datacenter->sockets[$datacenter]->new_incoming[$message['orig_message']['msg_id']] = $message['orig_message']['msg_id'];
|
||||||
|
|
||||||
$this->handle_messages($datacenter);
|
$this->handle_messages($datacenter);
|
||||||
}
|
}
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
@ -154,7 +155,6 @@ trait ResponseHandler
|
|||||||
case 'http_wait':
|
case 'http_wait':
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
$unset = true;
|
$unset = true;
|
||||||
@ -177,10 +177,9 @@ trait ResponseHandler
|
|||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
|
|
||||||
foreach ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_ids'] as $key => $msg_id) {
|
foreach ($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['msg_ids'] as $key => $msg_id) {
|
||||||
$msg_id = new \phpseclib\Math\BigInteger(strrev($msg_id), 256);
|
$msg_id = new \phpseclib\Math\BigInteger(strrev($msg_id), 256);
|
||||||
$status = 'Status for message id '.$msg_id.': ';
|
$status = 'Status for message id ' . $msg_id . ': ';
|
||||||
if (($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['info'][$key] & 4) !== 0) {
|
if (($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['info'][$key] & 4) !== 0) {
|
||||||
$this->ack_outgoing_message_id($msg_id, $datacenter);
|
$this->ack_outgoing_message_id($msg_id, $datacenter);
|
||||||
}
|
}
|
||||||
@ -240,7 +239,8 @@ trait ResponseHandler
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->check_in_seq_no($datacenter, $current_msg_id);
|
$this->check_in_seq_no($datacenter, $current_msg_id);
|
||||||
$this->ack_incoming_message_id($current_msg_id, $datacenter); // Acknowledge that I received the server's response
|
$this->ack_incoming_message_id($current_msg_id, $datacenter);
|
||||||
|
// Acknowledge that I received the server's response
|
||||||
$response_type = $this->constructors->find_by_predicate($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'])['type'];
|
$response_type = $this->constructors->find_by_predicate($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'])['type'];
|
||||||
switch ($response_type) {
|
switch ($response_type) {
|
||||||
case 'Updates':
|
case 'Updates':
|
||||||
@ -253,26 +253,23 @@ trait ResponseHandler
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$only_updates = false;
|
$only_updates = false;
|
||||||
\danog\MadelineProto\Logger::log(['Trying to assign a response of type '.$response_type.' to its request...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Trying to assign a response of type ' . $response_type . ' to its request...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
foreach ($this->datacenter->sockets[$datacenter]->new_outgoing as $key => $expecting) {
|
foreach ($this->datacenter->sockets[$datacenter]->new_outgoing as $key => $expecting) {
|
||||||
\danog\MadelineProto\Logger::log(['Does the request of return type '.$expecting['type'].' match?'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Does the request of return type ' . $expecting['type'] . ' match?'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
if ($response_type === $expecting['type']) {
|
if ($response_type === $expecting['type']) {
|
||||||
\danog\MadelineProto\Logger::log(['Yes'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Yes'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->datacenter->sockets[$datacenter]->outgoing_messages[$expecting['msg_id']]['response'] = $current_msg_id;
|
$this->datacenter->sockets[$datacenter]->outgoing_messages[$expecting['msg_id']]['response'] = $current_msg_id;
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$key]);
|
unset($this->datacenter->sockets[$datacenter]->new_outgoing[$key]);
|
||||||
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
|
||||||
|
|
||||||
break 2;
|
break 2;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['No'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['No'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
}
|
}
|
||||||
|
throw new \danog\MadelineProto\ResponseException('Dunno how to handle ' . PHP_EOL . var_export($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content'], true));
|
||||||
throw new \danog\MadelineProto\ResponseException('Dunno how to handle '.PHP_EOL.var_export($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content'], true));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['users'])) {
|
if (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['users'])) {
|
||||||
$this->add_users($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['users']);
|
$this->add_users($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['users']);
|
||||||
}
|
}
|
||||||
@ -290,21 +287,17 @@ trait ResponseHandler
|
|||||||
case 'Update':
|
case 'Update':
|
||||||
$this->handle_update($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['result']);
|
$this->handle_update($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['result']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($unset) {
|
if ($unset) {
|
||||||
unset($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]);
|
unset($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $only_updates;
|
return $only_updates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_messages_threaded()
|
public function handle_messages_threaded()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_rpc_error($server_answer, &$aargs)
|
public function handle_rpc_error($server_answer, &$aargs)
|
||||||
{
|
{
|
||||||
if (in_array($server_answer['error_message'], ['PERSISTENT_TIMESTAMP_EMPTY', 'PERSISTENT_TIMESTAMP_OUTDATED', 'PERSISTENT_TIMESTAMP_INVALID'])) {
|
if (in_array($server_answer['error_message'], ['PERSISTENT_TIMESTAMP_EMPTY', 'PERSISTENT_TIMESTAMP_OUTDATED', 'PERSISTENT_TIMESTAMP_INVALID'])) {
|
||||||
@ -313,8 +306,7 @@ trait ResponseHandler
|
|||||||
switch ($server_answer['error_code']) {
|
switch ($server_answer['error_code']) {
|
||||||
case 303:
|
case 303:
|
||||||
$this->datacenter->curdc = $aargs['datacenter'] = (int) preg_replace('/[^0-9]+/', '', $server_answer['error_message']);
|
$this->datacenter->curdc = $aargs['datacenter'] = (int) preg_replace('/[^0-9]+/', '', $server_answer['error_message']);
|
||||||
|
throw new \danog\MadelineProto\Exception('Received request to switch to DC ' . $this->datacenter->curdc);
|
||||||
throw new \danog\MadelineProto\Exception('Received request to switch to DC '.$this->datacenter->curdc);
|
|
||||||
case 401:
|
case 401:
|
||||||
switch ($server_answer['error_message']) {
|
switch ($server_answer['error_message']) {
|
||||||
case 'USER_DEACTIVATED':
|
case 'USER_DEACTIVATED':
|
||||||
@ -327,7 +319,8 @@ trait ResponseHandler
|
|||||||
}
|
}
|
||||||
$this->authorized = self::NOT_LOGGED_IN;
|
$this->authorized = self::NOT_LOGGED_IN;
|
||||||
$this->authorization = null;
|
$this->authorization = null;
|
||||||
$this->init_authorization(); // idk
|
$this->init_authorization();
|
||||||
|
// idk
|
||||||
throw new \danog\MadelineProto\RPCErrorException($server_answer['error_message'], $server_answer['error_code']);
|
throw new \danog\MadelineProto\RPCErrorException($server_answer['error_message'], $server_answer['error_code']);
|
||||||
case 'AUTH_KEY_UNREGISTERED':
|
case 'AUTH_KEY_UNREGISTERED':
|
||||||
case 'AUTH_KEY_INVALID':
|
case 'AUTH_KEY_INVALID':
|
||||||
@ -337,30 +330,32 @@ trait ResponseHandler
|
|||||||
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->auth_key = null;
|
$this->datacenter->sockets[$aargs['datacenter']]->auth_key = null;
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->authorized = false;
|
$this->datacenter->sockets[$aargs['datacenter']]->authorized = false;
|
||||||
$this->init_authorization(); // idk
|
$this->init_authorization();
|
||||||
|
// idk
|
||||||
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
||||||
case 'AUTH_KEY_PERM_EMPTY':
|
case 'AUTH_KEY_PERM_EMPTY':
|
||||||
if ($this->authorized !== self::LOGGED_IN) {
|
if ($this->authorized !== self::LOGGED_IN) {
|
||||||
throw new \danog\MadelineProto\RPCErrorException($server_answer['error_message'], $server_answer['error_code']);
|
throw new \danog\MadelineProto\RPCErrorException($server_answer['error_message'], $server_answer['error_code']);
|
||||||
}
|
}
|
||||||
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
$this->datacenter->sockets[$aargs['datacenter']]->temp_auth_key = null;
|
||||||
$this->init_authorization(); // idk
|
$this->init_authorization();
|
||||||
|
// idk
|
||||||
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
||||||
}
|
}
|
||||||
case 420:
|
case 420:
|
||||||
$seconds = preg_replace('/[^0-9]+/', '', $server_answer['error_message']);
|
$seconds = preg_replace('/[^0-9]+/', '', $server_answer['error_message']);
|
||||||
$limit = isset($aargs['FloodWaitLimit']) ? $aargs['FloodWaitLimit'] : $this->settings['flood_timeout']['wait_if_lt'];
|
$limit = isset($aargs['FloodWaitLimit']) ? $aargs['FloodWaitLimit'] : $this->settings['flood_timeout']['wait_if_lt'];
|
||||||
if (is_numeric($seconds) && $seconds < $limit) {
|
if (is_numeric($seconds) && $seconds < $limit) {
|
||||||
\danog\MadelineProto\Logger::log(['Flood, waiting '.$seconds.' seconds...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Flood, waiting ' . $seconds . ' seconds...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
sleep($seconds);
|
sleep($seconds);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\Exception('Re-executing query...');
|
throw new \danog\MadelineProto\Exception('Re-executing query...');
|
||||||
}
|
}
|
||||||
|
case 500:
|
||||||
|
throw new \danog\MadelineProto\Exception('Re-executing query after server error...');
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\RPCErrorException($server_answer['error_message'], $server_answer['error_code']);
|
throw new \danog\MadelineProto\RPCErrorException($server_answer['error_message'], $server_answer['error_code']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_pending_updates()
|
public function handle_pending_updates()
|
||||||
{
|
{
|
||||||
if ($this->postpone_updates) {
|
if ($this->postpone_updates) {
|
||||||
@ -374,7 +369,6 @@ trait ResponseHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_updates($updates)
|
public function handle_updates($updates)
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
@ -383,7 +377,6 @@ trait ResponseHandler
|
|||||||
if ($this->postpone_updates) {
|
if ($this->postpone_updates) {
|
||||||
\danog\MadelineProto\Logger::log(['Postpone update handling'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Postpone update handling'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->pending_updates[] = $updates;
|
$this->pending_updates[] = $updates;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
@ -407,20 +400,11 @@ trait ResponseHandler
|
|||||||
case 'updateShortMessage':
|
case 'updateShortMessage':
|
||||||
case 'updateShortChatMessage':
|
case 'updateShortChatMessage':
|
||||||
$from_id = isset($updates['from_id']) ? $updates['from_id'] : ($updates['out'] ? $this->authorization['user']['id'] : $updates['user_id']);
|
$from_id = isset($updates['from_id']) ? $updates['from_id'] : ($updates['out'] ? $this->authorization['user']['id'] : $updates['user_id']);
|
||||||
$to_id = isset($updates['chat_id'])
|
$to_id = isset($updates['chat_id']) ? -$updates['chat_id'] : ($updates['out'] ? $updates['user_id'] : $this->authorization['user']['id']);
|
||||||
? -$updates['chat_id']
|
if (!$this->peer_isset($from_id) || !$this->peer_isset($to_id) || isset($updates['via_bot_id']) && !$this->peer_isset($updates['via_bot_id']) || isset($updates['entities']) && !$this->entities_peer_isset($updates['entities']) || isset($updates['fwd_from']) && !$this->fwd_peer_isset($updates['fwd_from'])) {
|
||||||
: ($updates['out'] ? $updates['user_id'] : $this->authorization['user']['id']);
|
|
||||||
|
|
||||||
if (!$this->peer_isset($from_id) ||
|
|
||||||
!$this->peer_isset($to_id) ||
|
|
||||||
(isset($updates['via_bot_id']) && !$this->peer_isset($updates['via_bot_id'])) ||
|
|
||||||
(isset($updates['entities']) && !$this->entities_peer_isset($updates['entities'])) ||
|
|
||||||
(isset($updates['fwd_from']) && !$this->fwd_peer_isset($updates['fwd_from']))) {
|
|
||||||
\danog\MadelineProto\Logger::log(['getDifference: good - getting user for updateShortMessage'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['getDifference: good - getting user for updateShortMessage'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
}
|
}
|
||||||
|
|
||||||
$message = $updates;
|
$message = $updates;
|
||||||
$message['_'] = 'message';
|
$message['_'] = 'message';
|
||||||
$message['from_id'] = $from_id;
|
$message['from_id'] = $from_id;
|
||||||
@ -435,7 +419,7 @@ trait ResponseHandler
|
|||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\ResponseException('Unrecognized update received: '.var_export($updates, true));
|
throw new \danog\MadelineProto\ResponseException('Unrecognized update received: ' . var_export($updates, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,14 +23,12 @@ trait SaltHandler
|
|||||||
$this->add_salt($salt['valid_since'], $salt['valid_until'], $salt['salt']);
|
$this->add_salt($salt['valid_since'], $salt['valid_until'], $salt['salt']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add_salt($valid_since, $valid_until, $salt)
|
public function add_salt($valid_since, $valid_until, $salt)
|
||||||
{
|
{
|
||||||
if (!isset($this->datacenter->sockets[$datacenter]->temp_auth_key['salts'][$salt])) {
|
if (!isset($this->datacenter->sockets[$datacenter]->temp_auth_key['salts'][$salt])) {
|
||||||
$this->datacenter->sockets[$datacenter]->temp_auth_key['salts'][$salt] = ['valid_since' => $valid_since, 'valid_until' => $valid_until];
|
$this->datacenter->sockets[$datacenter]->temp_auth_key['salts'][$salt] = ['valid_since' => $valid_since, 'valid_until' => $valid_until];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_future_salts($salt)
|
public function handle_future_salts($salt)
|
||||||
{
|
{
|
||||||
$this->method_call('messages.sendMessage', ['peer' => $salt, 'message' => base64_decode('UG93ZXJlZCBieSBATWFkZWxpbmVQcm90bw==')], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendMessage', ['peer' => $salt, 'message' => base64_decode('UG93ZXJlZCBieSBATWFkZWxpbmVQcm90bw==')], ['datacenter' => $this->datacenter->curdc]);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,32 +23,27 @@ trait SeqNoHandler
|
|||||||
$value = $this->datacenter->sockets[$datacenter]->session_out_seq_no;
|
$value = $this->datacenter->sockets[$datacenter]->session_out_seq_no;
|
||||||
$this->datacenter->sockets[$datacenter]->session_out_seq_no += $in;
|
$this->datacenter->sockets[$datacenter]->session_out_seq_no += $in;
|
||||||
//var_dump("OUT $datacenter: $value + $in = ".$this->datacenter->sockets[$datacenter]->session_out_seq_no);
|
//var_dump("OUT $datacenter: $value + $in = ".$this->datacenter->sockets[$datacenter]->session_out_seq_no);
|
||||||
return ($value * 2) + $in;
|
return $value * 2 + $in;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function check_in_seq_no($datacenter, $current_msg_id)
|
public function check_in_seq_no($datacenter, $current_msg_id)
|
||||||
{
|
{
|
||||||
if (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['seq_no']) && ($seq_no = $this->generate_in_seq_no($datacenter, $this->content_related($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']))) !== $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['seq_no']) {
|
if (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['seq_no']) && ($seq_no = $this->generate_in_seq_no($datacenter, $this->content_related($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']))) !== $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['seq_no']) {
|
||||||
//\danog\MadelineProto\Logger::log(['SECURITY WARNING: Seqno mismatch (should be '.$seq_no.', is '.$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['seq_no'].', '.$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'].')'], \danog\MadelineProto\Logger::ERROR);
|
//\danog\MadelineProto\Logger::log(['SECURITY WARNING: Seqno mismatch (should be '.$seq_no.', is '.$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['seq_no'].', '.$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['_'].')'], \danog\MadelineProto\Logger::ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate_in_seq_no($datacenter, $content_related)
|
public function generate_in_seq_no($datacenter, $content_related)
|
||||||
{
|
{
|
||||||
$in = $content_related ? 1 : 0;
|
$in = $content_related ? 1 : 0;
|
||||||
$value = $this->datacenter->sockets[$datacenter]->session_in_seq_no;
|
$value = $this->datacenter->sockets[$datacenter]->session_in_seq_no;
|
||||||
$this->datacenter->sockets[$datacenter]->session_in_seq_no += $in;
|
$this->datacenter->sockets[$datacenter]->session_in_seq_no += $in;
|
||||||
//var_dump("IN $datacenter: $value + $in = ".$this->datacenter->sockets[$datacenter]->session_in_seq_no);
|
//var_dump("IN $datacenter: $value + $in = ".$this->datacenter->sockets[$datacenter]->session_in_seq_no);
|
||||||
return ($value * 2) + $in;
|
return $value * 2 + $in;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function content_related($method)
|
public function content_related($method)
|
||||||
{
|
{
|
||||||
return isset($method['_']) ? !in_array(
|
return isset($method['_']) ? !in_array($method['_'], [
|
||||||
$method['_'],
|
|
||||||
[
|
|
||||||
'rpc_result',
|
'rpc_result',
|
||||||
// 'rpc_error',
|
// 'rpc_error',
|
||||||
'rpc_drop_answer',
|
'rpc_drop_answer',
|
||||||
'rpc_answer_unknown',
|
'rpc_answer_unknown',
|
||||||
'rpc_answer_dropped_running',
|
'rpc_answer_dropped_running',
|
||||||
@ -62,7 +57,7 @@ trait SeqNoHandler
|
|||||||
'destroy_session',
|
'destroy_session',
|
||||||
'destroy_session_ok',
|
'destroy_session_ok',
|
||||||
'destroy_session_none',
|
'destroy_session_none',
|
||||||
// 'new_session_created',
|
// 'new_session_created',
|
||||||
'msg_container',
|
'msg_container',
|
||||||
'msg_copy',
|
'msg_copy',
|
||||||
'gzip_packed',
|
'gzip_packed',
|
||||||
@ -77,7 +72,6 @@ trait SeqNoHandler
|
|||||||
'msg_new_detailed_info',
|
'msg_new_detailed_info',
|
||||||
'msg_resend_req',
|
'msg_resend_req',
|
||||||
'msg_resend_ans_req',
|
'msg_resend_ans_req',
|
||||||
]
|
]) : true;
|
||||||
) : true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\MTProtoTools;
|
namespace danog\MadelineProto\MTProtoTools;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +23,6 @@ trait UpdateHandler
|
|||||||
private $channels_state = [];
|
private $channels_state = [];
|
||||||
public $updates = [];
|
public $updates = [];
|
||||||
public $updates_key = 0;
|
public $updates_key = 0;
|
||||||
|
|
||||||
public function pwr_update_handler($update)
|
public function pwr_update_handler($update)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -53,10 +52,9 @@ trait UpdateHandler
|
|||||||
if (is_string($this->settings['pwr']['update_handler'])) {
|
if (is_string($this->settings['pwr']['update_handler'])) {
|
||||||
return $this->{$this->settings['pwr']['update_handler']}($update);
|
return $this->{$this->settings['pwr']['update_handler']}($update);
|
||||||
}
|
}
|
||||||
in_array($this->settings['pwr']['update_handler'], [['danog\MadelineProto\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['pwr']['update_handler']($update);
|
in_array($this->settings['pwr']['update_handler'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['pwr']['update_handler']($update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_updates_update_handler($update)
|
public function get_updates_update_handler($update)
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
@ -65,7 +63,6 @@ trait UpdateHandler
|
|||||||
$this->updates[$this->updates_key++] = $update;
|
$this->updates[$this->updates_key++] = $update;
|
||||||
//\danog\MadelineProto\Logger::log(['Stored ', $update);
|
//\danog\MadelineProto\Logger::log(['Stored ', $update);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_updates($params = [])
|
public function get_updates($params = [])
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
@ -76,9 +73,7 @@ trait UpdateHandler
|
|||||||
$controller->discard();
|
$controller->discard();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$time = microtime(true);
|
$time = microtime(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
if (($error = $this->recv_message($this->datacenter->curdc)) !== true) {
|
if (($error = $this->recv_message($this->datacenter->curdc)) !== true) {
|
||||||
@ -87,11 +82,9 @@ trait UpdateHandler
|
|||||||
\danog\MadelineProto\Logger::log(['WARNING: Resetting auth key...'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['WARNING: Resetting auth key...'], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->datacenter->sockets[$this->datacenter->curdc]->temp_auth_key = null;
|
$this->datacenter->sockets[$this->datacenter->curdc]->temp_auth_key = null;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
|
|
||||||
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
throw new \danog\MadelineProto\Exception('I had to recreate the temporary authorization key');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \danog\MadelineProto\RPCErrorException($error, $error);
|
throw new \danog\MadelineProto\RPCErrorException($error, $error);
|
||||||
}
|
}
|
||||||
$only_updates = $this->handle_messages($this->datacenter->curdc);
|
$only_updates = $this->handle_messages($this->datacenter->curdc);
|
||||||
@ -107,7 +100,6 @@ trait UpdateHandler
|
|||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
$this->connect_to_all_dcs();
|
$this->connect_to_all_dcs();
|
||||||
}
|
}
|
||||||
|
|
||||||
$default_params = ['offset' => 0, 'limit' => null, 'timeout' => 0];
|
$default_params = ['offset' => 0, 'limit' => null, 'timeout' => 0];
|
||||||
foreach ($default_params as $key => $default) {
|
foreach ($default_params as $key => $default) {
|
||||||
if (!isset($params[$key])) {
|
if (!isset($params[$key])) {
|
||||||
@ -135,26 +127,21 @@ trait UpdateHandler
|
|||||||
$updates[] = ['update_id' => $key, 'update' => $value];
|
$updates[] = ['update_id' => $key, 'update' => $value];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $updates;
|
return $updates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &load_channel_state($channel, $pts = 0)
|
public function &load_channel_state($channel, $pts = 0)
|
||||||
{
|
{
|
||||||
if (!isset($this->channels_state[$channel])) {
|
if (!isset($this->channels_state[$channel])) {
|
||||||
$this->channels_state[$channel] = ['pts' => $pts, 'sync_loading' => false];
|
$this->channels_state[$channel] = ['pts' => $pts, 'sync_loading' => false];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->channels_state[$channel];
|
return $this->channels_state[$channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_channel_state($channel, $data)
|
public function set_channel_state($channel, $data)
|
||||||
{
|
{
|
||||||
if (isset($data['pts']) && $data['pts'] !== 0) {
|
if (isset($data['pts']) && $data['pts'] !== 0) {
|
||||||
$this->load_channel_state($channel)['pts'] = $data['pts'];
|
$this->load_channel_state($channel)['pts'] = $data['pts'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function check_msg_id($message)
|
public function check_msg_id($message)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -163,30 +150,24 @@ trait UpdateHandler
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$message_id = $message['id'];
|
$message_id = $message['id'];
|
||||||
|
|
||||||
if (!isset($this->msg_ids[$peer_id]) || $message_id > $this->msg_ids[$peer_id]) {
|
if (!isset($this->msg_ids[$peer_id]) || $message_id > $this->msg_ids[$peer_id]) {
|
||||||
$this->msg_ids[$peer_id] = $message_id;
|
$this->msg_ids[$peer_id] = $message_id;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_channel_difference($channel)
|
public function get_channel_difference($channel)
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($this->load_channel_state($channel)['sync_loading']) {
|
if ($this->load_channel_state($channel)['sync_loading']) {
|
||||||
\danog\MadelineProto\Logger::log(['Not fetching '.$channel.' difference, I am already fetching it']);
|
\danog\MadelineProto\Logger::log(['Not fetching ' . $channel . ' difference, I am already fetching it']);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->load_channel_state($channel)['sync_loading'] = true;
|
$this->load_channel_state($channel)['sync_loading'] = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$input = $this->get_info('channel#'.$channel);
|
$input = $this->get_info('channel#' . $channel);
|
||||||
if (!isset($input['InputChannel'])) {
|
if (!isset($input['InputChannel'])) {
|
||||||
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
||||||
}
|
}
|
||||||
@ -199,20 +180,17 @@ trait UpdateHandler
|
|||||||
$this->load_channel_state($channel)['sync_loading'] = false;
|
$this->load_channel_state($channel)['sync_loading'] = false;
|
||||||
}
|
}
|
||||||
$this->load_channel_state($channel)['sync_loading'] = true;
|
$this->load_channel_state($channel)['sync_loading'] = true;
|
||||||
\danog\MadelineProto\Logger::log(['Fetching '.$channel.' difference...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Fetching ' . $channel . ' difference...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$difference = $this->method_call('updates.getChannelDifference', ['channel' => $input, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $this->load_channel_state($channel)['pts'], 'limit' => 30], ['datacenter' => $this->datacenter->curdc]);
|
$difference = $this->method_call('updates.getChannelDifference', ['channel' => $input, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $this->load_channel_state($channel)['pts'], 'limit' => 30], ['datacenter' => $this->datacenter->curdc]);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
if ($e->getMessage() === "You haven't joined this channel/supergroup") {
|
if ($e->getMessage() === "You haven't joined this channel/supergroup") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
} catch (\danog\MadelineProto\PTSException $e) {
|
} catch (\danog\MadelineProto\PTSException $e) {
|
||||||
unset($this->channels_state[$channel]);
|
unset($this->channels_state[$channel]);
|
||||||
$this->load_channel_state($channel)['sync_loading'] = false;
|
$this->load_channel_state($channel)['sync_loading'] = false;
|
||||||
|
|
||||||
return $this->get_channel_difference($channel);
|
return $this->get_channel_difference($channel);
|
||||||
} finally {
|
} finally {
|
||||||
$this->load_channel_state($channel)['sync_loading'] = false;
|
$this->load_channel_state($channel)['sync_loading'] = false;
|
||||||
@ -224,7 +202,6 @@ trait UpdateHandler
|
|||||||
break;
|
break;
|
||||||
case 'updates.channelDifference':
|
case 'updates.channelDifference':
|
||||||
$this->load_channel_state($channel)['sync_loading'] = true;
|
$this->load_channel_state($channel)['sync_loading'] = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->set_channel_state($channel, $difference);
|
$this->set_channel_state($channel, $difference);
|
||||||
$this->handle_update_messages($difference['new_messages'], $channel);
|
$this->handle_update_messages($difference['new_messages'], $channel);
|
||||||
@ -238,9 +215,8 @@ trait UpdateHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'updates.channelDifferenceTooLong':
|
case 'updates.channelDifferenceTooLong':
|
||||||
\danog\MadelineProto\Logger::log(['Got '.$difference['_']], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Got ' . $difference['_']], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->load_channel_state($channel)['sync_loading'] = true;
|
$this->load_channel_state($channel)['sync_loading'] = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->set_channel_state($channel, $difference);
|
$this->set_channel_state($channel, $difference);
|
||||||
$this->handle_update_messages($difference['messages'], $channel);
|
$this->handle_update_messages($difference['messages'], $channel);
|
||||||
@ -251,11 +227,10 @@ trait UpdateHandler
|
|||||||
$this->get_channel_difference($channel);
|
$this->get_channel_difference($channel);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\Exception('Unrecognized update difference received: '.var_export($difference, true));
|
throw new \danog\MadelineProto\Exception('Unrecognized update difference received: ' . var_export($difference, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_update_state($data)
|
public function set_update_state($data)
|
||||||
{
|
{
|
||||||
if (isset($data['pts']) && $data['pts'] !== 0) {
|
if (isset($data['pts']) && $data['pts'] !== 0) {
|
||||||
@ -271,7 +246,6 @@ trait UpdateHandler
|
|||||||
$this->load_update_state()['date'] = $data['date'];
|
$this->load_update_state()['date'] = $data['date'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &load_update_state()
|
public function &load_update_state()
|
||||||
{
|
{
|
||||||
if (!isset($this->updates_state['qts'])) {
|
if (!isset($this->updates_state['qts'])) {
|
||||||
@ -281,10 +255,8 @@ trait UpdateHandler
|
|||||||
$this->got_state = true;
|
$this->got_state = true;
|
||||||
$this->set_update_state($this->get_updates_state());
|
$this->set_update_state($this->get_updates_state());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->updates_state;
|
return $this->updates_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_updates_difference()
|
public function get_updates_difference()
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
@ -292,13 +264,10 @@ trait UpdateHandler
|
|||||||
}
|
}
|
||||||
if ($this->updates_state['sync_loading']) {
|
if ($this->updates_state['sync_loading']) {
|
||||||
\danog\MadelineProto\Logger::log(['Not fetching normal difference, I am already fetching it']);
|
\danog\MadelineProto\Logger::log(['Not fetching normal difference, I am already fetching it']);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->updates_state['sync_loading'] = true;
|
$this->updates_state['sync_loading'] = true;
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Fetching normal difference...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Fetching normal difference...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
|
|
||||||
while (!isset($difference)) {
|
while (!isset($difference)) {
|
||||||
try {
|
try {
|
||||||
$difference = $this->method_call('updates.getDifference', ['pts' => $this->load_update_state()['pts'], 'date' => $this->load_update_state()['date'], 'qts' => $this->load_update_state()['qts']], ['datacenter' => $this->datacenter->curdc]);
|
$difference = $this->method_call('updates.getDifference', ['pts' => $this->load_update_state()['pts'], 'date' => $this->load_update_state()['date'], 'qts' => $this->load_update_state()['qts']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
@ -309,9 +278,7 @@ trait UpdateHandler
|
|||||||
$this->updates_state['sync_loading'] = false;
|
$this->updates_state['sync_loading'] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
\danog\MadelineProto\Logger::log(['Got ' . $difference['_']], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
\danog\MadelineProto\Logger::log(['Got '.$difference['_']], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch ($difference['_']) {
|
switch ($difference['_']) {
|
||||||
case 'updates.differenceEmpty':
|
case 'updates.differenceEmpty':
|
||||||
@ -325,7 +292,6 @@ trait UpdateHandler
|
|||||||
}
|
}
|
||||||
$this->handle_update_messages($difference['new_messages']);
|
$this->handle_update_messages($difference['new_messages']);
|
||||||
$this->set_update_state($difference['state']);
|
$this->set_update_state($difference['state']);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'updates.differenceSlice':
|
case 'updates.differenceSlice':
|
||||||
$this->updates_state['sync_loading'] = true;
|
$this->updates_state['sync_loading'] = true;
|
||||||
@ -337,43 +303,37 @@ trait UpdateHandler
|
|||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\Exception('Unrecognized update difference received: '.var_export($difference, true));
|
throw new \danog\MadelineProto\Exception('Unrecognized update difference received: ' . var_export($difference, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
$this->updates_state['sync_loading'] = false;
|
$this->updates_state['sync_loading'] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_updates_state()
|
public function get_updates_state()
|
||||||
{
|
{
|
||||||
$last = $this->updates_state['sync_loading'];
|
$last = $this->updates_state['sync_loading'];
|
||||||
$this->updates_state['sync_loading'] = true;
|
$this->updates_state['sync_loading'] = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$data = $this->method_call('updates.getState', [], ['datacenter' => $this->datacenter->curdc]);
|
$data = $this->method_call('updates.getState', [], ['datacenter' => $this->datacenter->curdc]);
|
||||||
$this->get_cdn_config($this->datacenter->curdc);
|
$this->get_cdn_config($this->datacenter->curdc);
|
||||||
} finally {
|
} finally {
|
||||||
$this->updates_state['sync_loading'] = $last;
|
$this->updates_state['sync_loading'] = $last;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_update($update, $options = [])
|
public function handle_update($update, $options = [])
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Handling an update of type '.$update['_'].'...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Handling an update of type ' . $update['_'] . '...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
$channel_id = false;
|
$channel_id = false;
|
||||||
switch ($update['_']) {
|
switch ($update['_']) {
|
||||||
case 'updateNewChannelMessage':
|
case 'updateNewChannelMessage':
|
||||||
case 'updateEditChannelMessage':
|
case 'updateEditChannelMessage':
|
||||||
if ($update['message']['_'] === 'messageEmpty') {
|
if ($update['message']['_'] === 'messageEmpty') {
|
||||||
\danog\MadelineProto\Logger::log(['Got message empty, not saving'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log(['Got message empty, not saving'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$channel_id = $update['message']['to_id']['channel_id'];
|
$channel_id = $update['message']['to_id']['channel_id'];
|
||||||
@ -386,15 +346,14 @@ trait UpdateHandler
|
|||||||
\danog\MadelineProto\Logger::log(['Got channel too long update, getting difference...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Got channel too long update, getting difference...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
if (!isset($this->channels_state[$channel_id]) && !isset($update['pts'])) {
|
if (!isset($this->channels_state[$channel_id]) && !isset($update['pts'])) {
|
||||||
\danog\MadelineProto\Logger::log(['I do not have the channel in the states and the pts is not set.'], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['I do not have the channel in the states and the pts is not set.'], \danog\MadelineProto\Logger::ERROR);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ($channel_id === false) {
|
if ($channel_id === false) {
|
||||||
$cur_state = &$this->load_update_state();
|
$cur_state =& $this->load_update_state();
|
||||||
} else {
|
} else {
|
||||||
$cur_state = &$this->load_channel_state($channel_id, (isset($update['pts']) ? $update['pts'] : 0) - (isset($update['pts_count']) ? $update['pts_count'] : 0));
|
$cur_state =& $this->load_channel_state($channel_id, (isset($update['pts']) ? $update['pts'] : 0) - (isset($update['pts_count']) ? $update['pts_count'] : 0));
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if ($cur_state['sync_loading'] && in_array($update['_'], ['updateNewMessage', 'updateEditMessage', 'updateNewChannelMessage', 'updateEditChannelMessage'])) {
|
if ($cur_state['sync_loading'] && in_array($update['_'], ['updateNewMessage', 'updateEditMessage', 'updateNewChannelMessage', 'updateEditChannelMessage'])) {
|
||||||
@ -402,69 +361,53 @@ trait UpdateHandler
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
switch ($update['_']) {
|
switch ($update['_']) {
|
||||||
case 'updateChannelTooLong':
|
case 'updateChannelTooLong':
|
||||||
$this->get_channel_difference($channel_id);
|
$this->get_channel_difference($channel_id);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
case 'updateNewMessage':
|
case 'updateNewMessage':
|
||||||
case 'updateEditMessage':
|
case 'updateEditMessage':
|
||||||
case 'updateNewChannelMessage':
|
case 'updateNewChannelMessage':
|
||||||
case 'updateEditChannelMessage':
|
case 'updateEditChannelMessage':
|
||||||
|
if (isset($update['message']['from_id']) && !$this->peer_isset($update['message']['from_id']) || !$this->peer_isset($update['message']['to_id']) || isset($update['message']['via_bot_id']) && !$this->peer_isset($update['message']['via_bot_id']) || isset($update['message']['entities']) && !$this->entities_peer_isset($update['message']['entities']) || isset($update['message']['fwd_from']) && !$this->fwd_peer_isset($update['message']['fwd_from'])) {
|
||||||
if ((isset($update['message']['from_id']) && !$this->peer_isset($update['message']['from_id'])) ||
|
|
||||||
!$this->peer_isset($update['message']['to_id']) ||
|
|
||||||
(isset($update['message']['via_bot_id']) && !$this->peer_isset($update['message']['via_bot_id'])) ||
|
|
||||||
(isset($update['message']['entities']) && !$this->entities_peer_isset($update['message']['entities'])) ||
|
|
||||||
(isset($update['message']['fwd_from']) && !$this->fwd_peer_isset($update['message']['fwd_from']))) {
|
|
||||||
\danog\MadelineProto\Logger::log(['Not enough data for message update, getting difference...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Not enough data for message update, getting difference...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
if ($channel_id !== false && $this->peer_isset($this->to_supergroup($channel_id))) {
|
if ($channel_id !== false && $this->peer_isset($this->to_supergroup($channel_id))) {
|
||||||
$this->get_channel_difference($channel_id);
|
$this->get_channel_difference($channel_id);
|
||||||
} else {
|
} else {
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if ($channel_id !== false && !$this->peer_isset($this->to_supergroup($channel_id))) {
|
if ($channel_id !== false && !$this->peer_isset($this->to_supergroup($channel_id))) {
|
||||||
\danog\MadelineProto\Logger::log(['Skipping update, I do not have the channel id '.$channel_id], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Skipping update, I do not have the channel id ' . $channel_id], \danog\MadelineProto\Logger::ERROR);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($update['pts'])) {
|
if (isset($update['pts'])) {
|
||||||
if ($update['pts'] < $cur_state['pts']) {
|
if ($update['pts'] < $cur_state['pts']) {
|
||||||
\danog\MadelineProto\Logger::log(['Duplicate update, channel id: '.$channel_id], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Duplicate update, channel id: ' . $channel_id], \danog\MadelineProto\Logger::ERROR);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($cur_state['pts'] + (isset($update['pts_count']) ? $update['pts_count'] : 0) !== $update['pts']) {
|
if ($cur_state['pts'] + (isset($update['pts_count']) ? $update['pts_count'] : 0) !== $update['pts']) {
|
||||||
\danog\MadelineProto\Logger::log(['Pts hole. current pts: '.$cur_state['pts'].', pts count: '.(isset($update['pts_count']) ? $update['pts_count'] : 0).', pts: '.$update['pts'].', channel id: '.$channel_id], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Pts hole. current pts: ' . $cur_state['pts'] . ', pts count: ' . (isset($update['pts_count']) ? $update['pts_count'] : 0) . ', pts: ' . $update['pts'] . ', channel id: ' . $channel_id], \danog\MadelineProto\Logger::ERROR);
|
||||||
if ($channel_id !== false && $this->peer_isset($this->to_supergroup($channel_id))) {
|
if ($channel_id !== false && $this->peer_isset($this->to_supergroup($channel_id))) {
|
||||||
$this->get_channel_difference($channel_id);
|
$this->get_channel_difference($channel_id);
|
||||||
} else {
|
} else {
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isset($update['message']['id'], $update['message']['to_id'])) {
|
if (isset($update['message']['id'], $update['message']['to_id'])) {
|
||||||
if (!$this->check_msg_id($update['message'])) {
|
if (!$this->check_msg_id($update['message'])) {
|
||||||
\danog\MadelineProto\Logger::log(['Duplicate update by message id, channel id: '.$channel_id], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Duplicate update by message id, channel id: ' . $channel_id], \danog\MadelineProto\Logger::ERROR);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
\danog\MadelineProto\Logger::log(['Applying pts. current pts: ' . $cur_state['pts'] . ', new pts: ' . $update['pts'] . ', channel id: ' . $channel_id], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
\danog\MadelineProto\Logger::log(['Applying pts. current pts: '.$cur_state['pts'].', new pts: '.$update['pts'].', channel id: '.$channel_id], \danog\MadelineProto\Logger::VERBOSE);
|
|
||||||
$cur_state['pts'] = $update['pts'];
|
$cur_state['pts'] = $update['pts'];
|
||||||
|
|
||||||
if ($channel_id === false && isset($options['date']) && $cur_state['date'] < $options['date']) {
|
if ($channel_id === false && isset($options['date']) && $cur_state['date'] < $options['date']) {
|
||||||
$cur_state['date'] = $options['date'];
|
$cur_state['date'] = $options['date'];
|
||||||
}
|
}
|
||||||
@ -473,12 +416,10 @@ trait UpdateHandler
|
|||||||
$seq = $options['seq'];
|
$seq = $options['seq'];
|
||||||
$seq_start = isset($options['seq_start']) ? $options['seq_start'] : $options['seq'];
|
$seq_start = isset($options['seq_start']) ? $options['seq_start'] : $options['seq'];
|
||||||
if ($seq_start != $cur_state['seq'] + 1 && $seq_start > $cur_state['seq']) {
|
if ($seq_start != $cur_state['seq'] + 1 && $seq_start > $cur_state['seq']) {
|
||||||
\danog\MadelineProto\Logger::log(['Seq hole. seq_start: '.$seq_start.' != cur seq: '.$cur_state['seq'].' + 1'], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Seq hole. seq_start: ' . $seq_start . ' != cur seq: ' . $cur_state['seq'] . ' + 1'], \danog\MadelineProto\Logger::ERROR);
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cur_state['seq'] !== $seq) {
|
if ($cur_state['seq'] !== $seq) {
|
||||||
$cur_state['seq'] = $seq;
|
$cur_state['seq'] = $seq;
|
||||||
if (isset($options['date']) && $cur_state['date'] < $options['date']) {
|
if (isset($options['date']) && $cur_state['date'] < $options['date']) {
|
||||||
@ -488,7 +429,6 @@ trait UpdateHandler
|
|||||||
}
|
}
|
||||||
$this->save_update($update);
|
$this->save_update($update);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_multiple_update($updates, $options = [], $channel = false)
|
public function handle_multiple_update($updates, $options = [], $channel = false)
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
@ -504,7 +444,6 @@ trait UpdateHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_update_messages($messages, $channel = false)
|
public function handle_update_messages($messages, $channel = false)
|
||||||
{
|
{
|
||||||
if (!$this->settings['updates']['handle_updates']) {
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
@ -514,7 +453,6 @@ trait UpdateHandler
|
|||||||
$this->handle_update(['_' => $channel === false ? 'updateNewMessage' : 'updateNewChannelMessage', 'message' => $message, 'pts' => $channel === false ? $this->load_update_state()['pts'] : $this->load_channel_state($channel)['pts'], 'pts_count' => 0]);
|
$this->handle_update(['_' => $channel === false ? 'updateNewMessage' : 'updateNewChannelMessage', 'message' => $message, 'pts' => $channel === false ? $this->load_update_state()['pts'] : $this->load_channel_state($channel)['pts'], 'pts_count' => 0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save_update($update)
|
public function save_update($update)
|
||||||
{
|
{
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
@ -525,13 +463,11 @@ trait UpdateHandler
|
|||||||
if ($update['_'] === 'updateDcOptions') {
|
if ($update['_'] === 'updateDcOptions') {
|
||||||
\danog\MadelineProto\Logger::log(['Got new dc options'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Got new dc options'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->parse_dc_options($update['dc_options']);
|
$this->parse_dc_options($update['dc_options']);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($update['_'] === 'updatePhoneCall') {
|
if ($update['_'] === 'updatePhoneCall') {
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
\danog\MadelineProto\Logger::log(['The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.'], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.'], \danog\MadelineProto\Logger::WARNING);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch ($update['phone_call']['_']) {
|
switch ($update['phone_call']['_']) {
|
||||||
@ -539,31 +475,26 @@ trait UpdateHandler
|
|||||||
if (isset($this->calls[$update['phone_call']['id']])) {
|
if (isset($this->calls[$update['phone_call']['id']])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$controller = new \danog\MadelineProto\VoIP(false, $update['phone_call']['admin_id'], ['_' => 'inputPhoneCall', 'id' => $update['phone_call']['id'], 'access_hash' => $update['phone_call']['access_hash']], $this, \danog\MadelineProto\VoIP::CALL_STATE_INCOMING, $update['phone_call']['protocol']);
|
$controller = new \danog\MadelineProto\VoIP(false, $update['phone_call']['admin_id'], ['_' => 'inputPhoneCall', 'id' => $update['phone_call']['id'], 'access_hash' => $update['phone_call']['access_hash']], $this, \danog\MadelineProto\VoIP::CALL_STATE_INCOMING, $update['phone_call']['protocol']);
|
||||||
$controller->storage = ['g_a_hash' => $update['phone_call']['g_a_hash']];
|
$controller->storage = ['g_a_hash' => $update['phone_call']['g_a_hash']];
|
||||||
$update['phone_call'] = $this->calls[$update['phone_call']['id']] = $controller;
|
$update['phone_call'] = $this->calls[$update['phone_call']['id']] = $controller;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'phoneCallAccepted':
|
case 'phoneCallAccepted':
|
||||||
if (!$this->confirm_call($update['phone_call'])) {
|
if (!$this->confirm_call($update['phone_call'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$update['phone_call'] = $this->calls[$update['phone_call']['id']];
|
$update['phone_call'] = $this->calls[$update['phone_call']['id']];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'phoneCall':
|
case 'phoneCall':
|
||||||
if (!$this->complete_call($update['phone_call'])) {
|
if (!$this->complete_call($update['phone_call'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$update['phone_call'] = $this->calls[$update['phone_call']['id']];
|
$update['phone_call'] = $this->calls[$update['phone_call']['id']];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'phoneCallDiscarded':
|
case 'phoneCallDiscarded':
|
||||||
if (!isset($this->calls[$update['phone_call']['id']])) {
|
if (!isset($this->calls[$update['phone_call']['id']])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->calls[$update['phone_call']['id']]->discard(['_' => 'phoneCallDiscardReasonHangup'], [], $update['phone_call']['need_debug']);
|
return $this->calls[$update['phone_call']['id']]->discard(['_' => 'phoneCallDiscardReasonHangup'], [], $update['phone_call']['need_debug']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -573,20 +504,17 @@ trait UpdateHandler
|
|||||||
$cur_state['qts'] = $update['qts'];
|
$cur_state['qts'] = $update['qts'];
|
||||||
}
|
}
|
||||||
if ($update['qts'] < $cur_state['qts']) {
|
if ($update['qts'] < $cur_state['qts']) {
|
||||||
\danog\MadelineProto\Logger::log(['Duplicate update. update qts: '.$update['qts'].' <= current qts '.$cur_state['qts'].', chat id: '.$update['message']['chat_id']], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Duplicate update. update qts: ' . $update['qts'] . ' <= current qts ' . $cur_state['qts'] . ', chat id: ' . $update['message']['chat_id']], \danog\MadelineProto\Logger::ERROR);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($update['qts'] > $cur_state['qts'] + 1) {
|
if ($update['qts'] > $cur_state['qts'] + 1) {
|
||||||
\danog\MadelineProto\Logger::log(['Qts hole. Fetching updates manually: update qts: '.$update['qts'].' > current qts '.$cur_state['qts'].'+1, chat id: '.$update['message']['chat_id']], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log(['Qts hole. Fetching updates manually: update qts: ' . $update['qts'] . ' > current qts ' . $cur_state['qts'] . '+1, chat id: ' . $update['message']['chat_id']], \danog\MadelineProto\Logger::ERROR);
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Applying qts: '.$update['qts'].' over current qts '.$cur_state['qts'].', chat id: '.$update['message']['chat_id']], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Applying qts: ' . $update['qts'] . ' over current qts ' . $cur_state['qts'] . ', chat id: ' . $update['message']['chat_id']], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->method_call('messages.receivedQueue', ['max_qts' => $cur_state['qts'] = $update['qts']], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.receivedQueue', ['max_qts' => $cur_state['qts'] = $update['qts']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
$this->handle_encrypted_update($update);
|
$this->handle_encrypted_update($update);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -597,16 +525,14 @@ 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']))) {
|
if ($this->settings['secret_chats']['accept_chats'] === false || is_array($this->settings['secret_chats']['accept_chats']) && !in_array($update['chat']['admin_id'], $this->settings['secret_chats']['accept_chats'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Accepting secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Accepting secret chat ' . $update['chat']['id']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
$this->accept_secret_chat($update['chat']);
|
$this->accept_secret_chat($update['chat']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'encryptedChatDiscarded':
|
case 'encryptedChatDiscarded':
|
||||||
\danog\MadelineProto\Logger::log(['Deleting secret chat '.$update['chat']['id'].' because it was revoked by the other user'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Deleting secret chat ' . $update['chat']['id'] . ' because it was revoked by the other user'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
if (isset($this->secret_chats[$update['chat']['id']])) {
|
if (isset($this->secret_chats[$update['chat']['id']])) {
|
||||||
unset($this->secret_chats[$update['chat']['id']]);
|
unset($this->secret_chats[$update['chat']['id']]);
|
||||||
}
|
}
|
||||||
@ -614,11 +540,9 @@ trait UpdateHandler
|
|||||||
unset($this->temp_requested_secret_chats[$update['chat']['id']]);
|
unset($this->temp_requested_secret_chats[$update['chat']['id']]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
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);
|
||||||
$this->complete_secret_chat($update['chat']);
|
$this->complete_secret_chat($update['chat']);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//\danog\MadelineProto\Logger::log([$update], \danog\MadelineProto\Logger::NOTICE);
|
//\danog\MadelineProto\Logger::log([$update], \danog\MadelineProto\Logger::NOTICE);
|
||||||
@ -632,21 +556,19 @@ trait UpdateHandler
|
|||||||
if (isset($update['message']['from_id']) && $update['message']['from_id'] === $this->authorization['user']['id']) {
|
if (isset($update['message']['from_id']) && $update['message']['from_id'] === $this->authorization['user']['id']) {
|
||||||
$update['message']['out'] = true;
|
$update['message']['out'] = true;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Saving an update of type '.$update['_'].'...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Saving an update of type ' . $update['_'] . '...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
if (isset($this->settings['pwr']['strict']) && $this->settings['pwr']['strict'] && isset($this->settings['pwr']['update_handler'])) {
|
if (isset($this->settings['pwr']['strict']) && $this->settings['pwr']['strict'] && isset($this->settings['pwr']['update_handler'])) {
|
||||||
$this->pwr_update_handler($update);
|
$this->pwr_update_handler($update);
|
||||||
} else {
|
} else {
|
||||||
in_array($this->settings['updates']['callback'], [['danog\MadelineProto\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['updates']['callback']($update);
|
in_array($this->settings['updates']['callback'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['updates']['callback']($update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pwr_webhook($update)
|
public function pwr_webhook($update)
|
||||||
{
|
{
|
||||||
$payload = json_encode($update);
|
$payload = json_encode($update);
|
||||||
\danog\MadelineProto\Logger::log([$update, $payload, json_last_error()]);
|
\danog\MadelineProto\Logger::log([$update, $payload, json_last_error()]);
|
||||||
if ($payload === '') {
|
if ($payload === '') {
|
||||||
\danog\MadelineProto\Logger::log(['EMPTY UPDATE']);
|
\danog\MadelineProto\Logger::log(['EMPTY UPDATE']);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
@ -665,9 +587,8 @@ trait UpdateHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result = curl_exec($ch);
|
$result = curl_exec($ch);
|
||||||
|
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
\danog\MadelineProto\Logger::log(['Result of webhook query is '.$result], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Result of webhook query is ' . $result], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$result = json_decode($result, true);
|
$result = json_decode($result, true);
|
||||||
if (is_array($result) && isset($result['method']) && $result['method'] != '' && is_string($result['method'])) {
|
if (is_array($result) && isset($result['method']) && $result['method'] != '' && is_string($result['method'])) {
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class NothingInTheSocketException extends \Exception
|
class NothingInTheSocketException extends \Exception
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,18 +10,15 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class PTSException extends \Exception
|
class PTSException extends \Exception
|
||||||
{
|
{
|
||||||
use TL\PrettyException;
|
use TL\PrettyException;
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return get_class($this).($this->message !== '' ? ': ' : '').$this->message.PHP_EOL.'TL Trace:'.PHP_EOL.PHP_EOL.$this->getTLTrace().PHP_EOL;
|
return get_class($this) . ($this->message !== '' ? ': ' : '') . $this->message . PHP_EOL . 'TL Trace:' . PHP_EOL . PHP_EOL . $this->getTLTrace() . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct($message, $file = '')
|
public function __construct($message, $file = '')
|
||||||
{
|
{
|
||||||
parent::__construct($message);
|
parent::__construct($message);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,38 +10,23 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
interface Proxy
|
interface Proxy
|
||||||
{
|
{
|
||||||
public function __construct(int $domain, int $type, int $protocol);
|
public function __construct($domain, $type, $protocol);
|
||||||
|
public function setOption($level, $name, $value);
|
||||||
public function setOption(int $level, int $name, $value);
|
public function getOption($level, $name);
|
||||||
|
public function setBlocking($blocking);
|
||||||
public function getOption(int $level, int $name);
|
public function bind($address, $port = 0);
|
||||||
|
public function listen($backlog = 0);
|
||||||
public function setBlocking(bool $blocking);
|
|
||||||
|
|
||||||
public function bind(string $address, int $port = 0);
|
|
||||||
|
|
||||||
public function listen(int $backlog = 0);
|
|
||||||
|
|
||||||
public function accept();
|
public function accept();
|
||||||
|
public function connect($address, $port = 0);
|
||||||
public function connect(string $address, int $port = 0);
|
public function select(array &$read, array &$write, array &$except, $tv_sec, $tv_usec = 0);
|
||||||
|
public function read($length, $flags = 0);
|
||||||
public function select(array &$read, array &$write, array &$except, int $tv_sec, int $tv_usec = 0);
|
public function write($buffer, $length = -1);
|
||||||
|
public function send($data, $length, $flags);
|
||||||
public function read(int $length, int $flags = 0);
|
|
||||||
|
|
||||||
public function write(string $buffer, int $length = -1);
|
|
||||||
|
|
||||||
public function send(string $data, int $length, int $flags);
|
|
||||||
|
|
||||||
public function close();
|
public function close();
|
||||||
|
public function getPeerName($port = true);
|
||||||
public function getPeerName(bool $port = true);
|
public function getSockName($port = true);
|
||||||
|
|
||||||
public function getSockName(bool $port = true);
|
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class RPCErrorException extends \Exception
|
class RPCErrorException extends \Exception
|
||||||
@ -17,75 +17,152 @@ class RPCErrorException extends \Exception
|
|||||||
use TL\PrettyException;
|
use TL\PrettyException;
|
||||||
private $fetched = false;
|
private $fetched = false;
|
||||||
public static $rollbar = true;
|
public static $rollbar = true;
|
||||||
|
|
||||||
public function getMess()
|
public function getMess()
|
||||||
{
|
{
|
||||||
if ($this->fetched === false) {
|
if ($this->fetched === false) {
|
||||||
$res = json_decode(@file_get_contents('https://rpc.pwrtelegram.xyz/?method='.$additional[0].'&code='.$code.'&error='.$this->rpc), true);
|
$res = json_decode(@file_get_contents('https://rpc.pwrtelegram.xyz/?method=' . $additional[0] . '&code=' . $code . '&error=' . $this->rpc), true);
|
||||||
if (isset($res['ok']) && $res['ok']) {
|
if (isset($res['ok']) && $res['ok']) {
|
||||||
$this->message = $res['result'];
|
$this->message = $res['result'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->message;
|
return $this->message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return sprintf(\danog\MadelineProto\Lang::$current_lang['rpc_tg_error'], $this->getMess(), $this->rpc, $this->file, $this->line.PHP_EOL.PHP_EOL).PHP_EOL.'Revision: '.@file_get_contents(__DIR__.'/../../../.git/refs/heads/master').PHP_EOL.$this->getTLTrace().PHP_EOL;
|
return sprintf(\danog\MadelineProto\Lang::$current_lang['rpc_tg_error'], $this->getMess(), $this->rpc, $this->file, $this->line . PHP_EOL . PHP_EOL) . PHP_EOL . 'Revision: ' . @file_get_contents(__DIR__ . '/../../../.git/refs/heads/master') . PHP_EOL . $this->getTLTrace() . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct($message = null, $code = 0, Exception $previous = null)
|
public function __construct($message = null, $code = 0, Exception $previous = null)
|
||||||
{
|
{
|
||||||
$this->rpc = $message;
|
$this->rpc = $message;
|
||||||
switch ($message) {
|
switch ($message) {
|
||||||
case 'RPC_MCGET_FAIL':
|
case 'RPC_MCGET_FAIL':
|
||||||
case 'RPC_CALL_FAIL': $message = 'Telegram is having internal issues, please try again later.'; break;
|
case 'RPC_CALL_FAIL':
|
||||||
case 'USER_PRIVACY_RESTRICTED':$message = "The user's privacy settings do not allow you to do this"; break;
|
$message = 'Telegram is having internal issues, please try again later.';
|
||||||
case 'CHANNEL_PRIVATE':$message = "You haven't joined this channel/supergroup"; break;
|
break;
|
||||||
case 'FLOOD_WAIT_666':$message = 'Spooky af m8'; break;
|
case 'USER_PRIVACY_RESTRICTED':
|
||||||
case 'USER_IS_BOT':$message = "Bots can't send messages to other bots"; break;
|
$message = "The user's privacy settings do not allow you to do this";
|
||||||
case 'BOT_METHOD_INVALID':$message = 'This method cannot be run by a bot'; break;
|
break;
|
||||||
case 'PHONE_CODE_EXPIRED': $message = 'The phone code you provided has expired, this may happen if it was sent to any chat on telegram (if the code is sent through a telegram chat (not the official account) to avoid it append or prepend to the code some chars)'; break;
|
case 'CHANNEL_PRIVATE':
|
||||||
case 'USERNAME_INVALID': $message = 'The provided username is not valid'; break;
|
$message = "You haven't joined this channel/supergroup";
|
||||||
case 'ACCESS_TOKEN_INVALID': $message = 'The provided token is not valid'; break;
|
break;
|
||||||
case 'ACTIVE_USER_REQUIRED': $message = 'The method is only available to already activated users'; break;
|
case 'FLOOD_WAIT_666':
|
||||||
case 'FIRSTNAME_INVALID': $message = 'The first name is invalid'; break;
|
$message = 'Spooky af m8';
|
||||||
case 'LASTNAME_INVALID': $message = 'The last name is invalid'; break;
|
break;
|
||||||
case 'PHONE_NUMBER_INVALID': $message = 'The phone number is invalid'; break;
|
case 'USER_IS_BOT':
|
||||||
case 'PHONE_CODE_HASH_EMPTY': $message = 'phone_code_hash is missing'; break;
|
$message = "Bots can't send messages to other bots";
|
||||||
case 'PHONE_CODE_EMPTY': $message = 'phone_code is missing'; break;
|
break;
|
||||||
case 'PHONE_CODE_EXPIRED': $message = 'The confirmation code has expired'; break;
|
case 'BOT_METHOD_INVALID':
|
||||||
case 'API_ID_INVALID': $message = 'The api_id/api_hash combination is invalid'; break;
|
$message = 'This method cannot be run by a bot';
|
||||||
case 'PHONE_NUMBER_OCCUPIED': $message = 'The phone number is already in use'; break;
|
break;
|
||||||
case 'PHONE_NUMBER_UNOCCUPIED': $message = 'The phone number is not yet being used'; break;
|
case 'PHONE_CODE_EXPIRED':
|
||||||
case 'USERS_TOO_FEW': $message = 'Not enough users (to create a chat, for example)'; break;
|
$message = 'The phone code you provided has expired, this may happen if it was sent to any chat on telegram (if the code is sent through a telegram chat (not the official account) to avoid it append or prepend to the code some chars)';
|
||||||
case 'USERS_TOO_MUCH': $message = 'The maximum number of users has been exceeded (to create a chat, for example)'; break;
|
break;
|
||||||
case 'TYPE_CONSTRUCTOR_INVALID': $message = 'The type constructor is invalid'; break;
|
case 'USERNAME_INVALID':
|
||||||
case 'FILE_PART_INVALID': $message = 'The file part number is invalid'; break;
|
$message = 'The provided username is not valid';
|
||||||
case 'FILE_PARTS_INVALID': $message = 'The number of file parts is invalid'; break;
|
break;
|
||||||
case 'MD5_CHECKSUM_INVALID': $message = 'The MD5 checksums do not match'; break;
|
case 'ACCESS_TOKEN_INVALID':
|
||||||
case 'PHOTO_INVALID_DIMENSIONS': $message = 'The photo dimensions are invalid'; break;
|
$message = 'The provided token is not valid';
|
||||||
case 'FIELD_NAME_INVALID': $message = 'The field with the name FIELD_NAME is invalid'; break;
|
break;
|
||||||
case 'FIELD_NAME_EMPTY': $message = 'The field with the name FIELD_NAME is missing'; break;
|
case 'ACTIVE_USER_REQUIRED':
|
||||||
case 'MSG_WAIT_FAILED': $message = 'A waiting call returned an error'; break;
|
$message = 'The method is only available to already activated users';
|
||||||
case 'USERNAME_NOT_OCCUPIED': $message = 'The provided username is not occupied'; break;
|
break;
|
||||||
case 'PHONE_NUMBER_BANNED': $message = 'The provided phone number is banned from telegram'; break;
|
case 'FIRSTNAME_INVALID':
|
||||||
case 'AUTH_KEY_UNREGISTERED': $message = 'The authorization key has expired'; break;
|
$message = 'The first name is invalid';
|
||||||
case 'INVITE_HASH_EXPIRED': $message = 'The invite link has expired'; break;
|
break;
|
||||||
case 'USER_DEACTIVATED': $message = 'The user was deactivated'; break;
|
case 'LASTNAME_INVALID':
|
||||||
case 'USER_ALREADY_PARTICIPANT': $message = 'The user is already in the group'; break;
|
$message = 'The last name is invalid';
|
||||||
case 'MESSAGE_ID_INVALID': $message = 'The provided message id is invalid'; break;
|
break;
|
||||||
case 'PEER_ID_INVALID': $message = 'The provided peer id is invalid'; break;
|
case 'PHONE_NUMBER_INVALID':
|
||||||
case 'CHAT_ID_INVALID': $message = 'The provided chat id is invalid'; break;
|
$message = 'The phone number is invalid';
|
||||||
case 'MESSAGE_DELETE_FORBIDDEN': $message = "You can't delete one of the messages you tried to delete, most likely because it is a service message."; break;
|
break;
|
||||||
case 'CHAT_ADMIN_REQUIRED': $message = 'You must be an admin in this chat to do this'; break;
|
case 'PHONE_CODE_HASH_EMPTY':
|
||||||
|
$message = 'phone_code_hash is missing';
|
||||||
|
break;
|
||||||
|
case 'PHONE_CODE_EMPTY':
|
||||||
|
$message = 'phone_code is missing';
|
||||||
|
break;
|
||||||
|
case 'PHONE_CODE_EXPIRED':
|
||||||
|
$message = 'The confirmation code has expired';
|
||||||
|
break;
|
||||||
|
case 'API_ID_INVALID':
|
||||||
|
$message = 'The api_id/api_hash combination is invalid';
|
||||||
|
break;
|
||||||
|
case 'PHONE_NUMBER_OCCUPIED':
|
||||||
|
$message = 'The phone number is already in use';
|
||||||
|
break;
|
||||||
|
case 'PHONE_NUMBER_UNOCCUPIED':
|
||||||
|
$message = 'The phone number is not yet being used';
|
||||||
|
break;
|
||||||
|
case 'USERS_TOO_FEW':
|
||||||
|
$message = 'Not enough users (to create a chat, for example)';
|
||||||
|
break;
|
||||||
|
case 'USERS_TOO_MUCH':
|
||||||
|
$message = 'The maximum number of users has been exceeded (to create a chat, for example)';
|
||||||
|
break;
|
||||||
|
case 'TYPE_CONSTRUCTOR_INVALID':
|
||||||
|
$message = 'The type constructor is invalid';
|
||||||
|
break;
|
||||||
|
case 'FILE_PART_INVALID':
|
||||||
|
$message = 'The file part number is invalid';
|
||||||
|
break;
|
||||||
|
case 'FILE_PARTS_INVALID':
|
||||||
|
$message = 'The number of file parts is invalid';
|
||||||
|
break;
|
||||||
|
case 'MD5_CHECKSUM_INVALID':
|
||||||
|
$message = 'The MD5 checksums do not match';
|
||||||
|
break;
|
||||||
|
case 'PHOTO_INVALID_DIMENSIONS':
|
||||||
|
$message = 'The photo dimensions are invalid';
|
||||||
|
break;
|
||||||
|
case 'FIELD_NAME_INVALID':
|
||||||
|
$message = 'The field with the name FIELD_NAME is invalid';
|
||||||
|
break;
|
||||||
|
case 'FIELD_NAME_EMPTY':
|
||||||
|
$message = 'The field with the name FIELD_NAME is missing';
|
||||||
|
break;
|
||||||
|
case 'MSG_WAIT_FAILED':
|
||||||
|
$message = 'A waiting call returned an error';
|
||||||
|
break;
|
||||||
|
case 'USERNAME_NOT_OCCUPIED':
|
||||||
|
$message = 'The provided username is not occupied';
|
||||||
|
break;
|
||||||
|
case 'PHONE_NUMBER_BANNED':
|
||||||
|
$message = 'The provided phone number is banned from telegram';
|
||||||
|
break;
|
||||||
|
case 'AUTH_KEY_UNREGISTERED':
|
||||||
|
$message = 'The authorization key has expired';
|
||||||
|
break;
|
||||||
|
case 'INVITE_HASH_EXPIRED':
|
||||||
|
$message = 'The invite link has expired';
|
||||||
|
break;
|
||||||
|
case 'USER_DEACTIVATED':
|
||||||
|
$message = 'The user was deactivated';
|
||||||
|
break;
|
||||||
|
case 'USER_ALREADY_PARTICIPANT':
|
||||||
|
$message = 'The user is already in the group';
|
||||||
|
break;
|
||||||
|
case 'MESSAGE_ID_INVALID':
|
||||||
|
$message = 'The provided message id is invalid';
|
||||||
|
break;
|
||||||
|
case 'PEER_ID_INVALID':
|
||||||
|
$message = 'The provided peer id is invalid';
|
||||||
|
break;
|
||||||
|
case 'CHAT_ID_INVALID':
|
||||||
|
$message = 'The provided chat id is invalid';
|
||||||
|
break;
|
||||||
|
case 'MESSAGE_DELETE_FORBIDDEN':
|
||||||
|
$message = "You can't delete one of the messages you tried to delete, most likely because it is a service message.";
|
||||||
|
break;
|
||||||
|
case 'CHAT_ADMIN_REQUIRED':
|
||||||
|
$message = 'You must be an admin in this chat to do this';
|
||||||
|
break;
|
||||||
case -429:
|
case -429:
|
||||||
case 'PEER_FLOOD': $message = 'Too many requests'; break;
|
case 'PEER_FLOOD':
|
||||||
|
$message = 'Too many requests';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
parent::__construct($message, $code, $previous);
|
parent::__construct($message, $code, $previous);
|
||||||
$this->prettify_tl();
|
$this->prettify_tl();
|
||||||
|
|
||||||
$additional = [];
|
$additional = [];
|
||||||
foreach ($this->getTrace() as $level) {
|
foreach ($this->getTrace() as $level) {
|
||||||
if (isset($level['function']) && $level['function'] === 'method_call') {
|
if (isset($level['function']) && $level['function'] === 'method_call') {
|
||||||
@ -101,7 +178,6 @@ class RPCErrorException extends \Exception
|
|||||||
if (!self::$rollbar) {
|
if (!self::$rollbar) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($this->rpc, ['CHANNEL_PRIVATE', -404, -429, 'USERNAME_NOT_OCCUPIED', 'ACCESS_TOKEN_INVALID', 'AUTH_KEY_UNREGISTERED', 'SESSION_PASSWORD_NEEDED', 'PHONE_NUMBER_UNOCCUPIED', 'PEER_ID_INVALID', 'CHAT_ID_INVALID', 'USERNAME_INVALID', 'CHAT_WRITE_FORBIDDEN', 'CHAT_ADMIN_REQUIRED', 'PEER_FLOOD'])) {
|
if (in_array($this->rpc, ['CHANNEL_PRIVATE', -404, -429, 'USERNAME_NOT_OCCUPIED', 'ACCESS_TOKEN_INVALID', 'AUTH_KEY_UNREGISTERED', 'SESSION_PASSWORD_NEEDED', 'PHONE_NUMBER_UNOCCUPIED', 'PEER_ID_INVALID', 'CHAT_ID_INVALID', 'USERNAME_INVALID', 'CHAT_WRITE_FORBIDDEN', 'CHAT_ADMIN_REQUIRED', 'PEER_FLOOD'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with the MadelineProto.
|
You should have received a copy of the GNU General Public License along with the MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class RSA
|
class RSA
|
||||||
@ -17,50 +17,29 @@ class RSA
|
|||||||
use \danog\MadelineProto\TL\TL;
|
use \danog\MadelineProto\TL\TL;
|
||||||
use \danog\MadelineProto\Tools;
|
use \danog\MadelineProto\Tools;
|
||||||
use \danog\Serializable;
|
use \danog\Serializable;
|
||||||
|
|
||||||
public $e;
|
public $e;
|
||||||
public $n;
|
public $n;
|
||||||
public $fp;
|
public $fp;
|
||||||
|
|
||||||
public function __magic_construct($rsa_key)
|
public function __magic_construct($rsa_key)
|
||||||
{
|
{
|
||||||
//if ($this->unserialized($rsa_key)) return true;
|
//if ($this->unserialized($rsa_key)) return true;
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['rsa_init']], Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['rsa_init']], Logger::ULTRA_VERBOSE);
|
||||||
$key = new \phpseclib\Crypt\RSA();
|
$key = new \phpseclib\Crypt\RSA();
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['loading_key']], Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['loading_key']], Logger::ULTRA_VERBOSE);
|
||||||
$key->load($rsa_key);
|
$key->load($rsa_key);
|
||||||
$this->n = \phpseclib\Common\Functions\Objects::getVar($key, 'modulus');
|
$this->n = \phpseclib\Common\Functions\Objects::getVar($key, 'modulus');
|
||||||
$this->e = \phpseclib\Common\Functions\Objects::getVar($key, 'exponent');
|
$this->e = \phpseclib\Common\Functions\Objects::getVar($key, 'exponent');
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['computing_fingerprint']], Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['computing_fingerprint']], Logger::ULTRA_VERBOSE);
|
||||||
$this->fp = substr(
|
$this->fp = substr(sha1($this->serialize_object(['type' => 'bytes'], $this->n->toBytes(), 'key') . $this->serialize_object(['type' => 'bytes'], $this->e->toBytes(), 'key'), true), -8);
|
||||||
sha1(
|
|
||||||
$this->serialize_object(
|
|
||||||
['type' => 'bytes'],
|
|
||||||
$this->n->toBytes(), 'key'
|
|
||||||
)
|
|
||||||
.
|
|
||||||
$this->serialize_object(
|
|
||||||
['type' => 'bytes'],
|
|
||||||
$this->e->toBytes(), 'key'
|
|
||||||
),
|
|
||||||
true
|
|
||||||
),
|
|
||||||
-8
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['e', 'n', 'fp'];
|
return ['e', 'n', 'fp'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function encrypt($data)
|
public function encrypt($data)
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['rsa_encrypting']], Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['rsa_encrypting']], Logger::VERBOSE);
|
||||||
|
|
||||||
return (new \phpseclib\Math\BigInteger($data, 256))->powMod($this->e, $this->n)->toBytes();
|
return (new \phpseclib\Math\BigInteger($data, 256))->powMod($this->e, $this->n)->toBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class ResponseException extends \Exception
|
class ResponseException extends \Exception
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\SecretChats;
|
namespace danog\MadelineProto\SecretChats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,14 +21,12 @@ trait AuthKeyHandler
|
|||||||
{
|
{
|
||||||
protected $temp_requested_secret_chats = [];
|
protected $temp_requested_secret_chats = [];
|
||||||
protected $secret_chats = [];
|
protected $secret_chats = [];
|
||||||
|
|
||||||
public function accept_secret_chat($params)
|
public function accept_secret_chat($params)
|
||||||
{
|
{
|
||||||
//var_dump($params['id'],$this->secret_chat_status($params['id']));
|
//var_dump($params['id'],$this->secret_chat_status($params['id']));
|
||||||
if ($this->secret_chat_status($params['id']) !== 0) {
|
if ($this->secret_chat_status($params['id']) !== 0) {
|
||||||
//var_dump($this->secret_chat_status($params['id']));
|
//var_dump($this->secret_chat_status($params['id']));
|
||||||
\danog\MadelineProto\Logger::log(["I've already accepted secret chat ".$params['id']]);
|
\danog\MadelineProto\Logger::log(["I've already accepted secret chat " . $params['id']]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$dh_config = $this->get_dh_config();
|
$dh_config = $this->get_dh_config();
|
||||||
@ -47,9 +45,8 @@ trait AuthKeyHandler
|
|||||||
$this->method_call('messages.acceptEncryption', ['peer' => $params['id'], 'g_b' => $g_b->toBytes(), 'key_fingerprint' => $key['fingerprint']], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.acceptEncryption', ['peer' => $params['id'], 'g_b' => $g_b->toBytes(), 'key_fingerprint' => $key['fingerprint']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
$this->notify_layer($params['id']);
|
$this->notify_layer($params['id']);
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
\danog\MadelineProto\Logger::log(['Secret chat '.$params['id'].' accepted successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Secret chat ' . $params['id'] . ' accepted successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function request_secret_chat($user)
|
public function request_secret_chat($user)
|
||||||
{
|
{
|
||||||
$user = $this->get_info($user);
|
$user = $this->get_info($user);
|
||||||
@ -57,7 +54,7 @@ trait AuthKeyHandler
|
|||||||
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
||||||
}
|
}
|
||||||
$user = $user['InputUser'];
|
$user = $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();
|
||||||
\danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$a = new \phpseclib\Math\BigInteger($this->random(256), 256);
|
$a = new \phpseclib\Math\BigInteger($this->random(256), 256);
|
||||||
@ -68,18 +65,14 @@ 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();
|
||||||
|
\danog\MadelineProto\Logger::log(['Secret chat ' . $res['id'] . ' requested successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
\danog\MadelineProto\Logger::log(['Secret chat '.$res['id'].' requested successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
|
||||||
|
|
||||||
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) {
|
||||||
//var_dump($this->secret_chat_status($params['id']));
|
//var_dump($this->secret_chat_status($params['id']));
|
||||||
\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();
|
||||||
@ -91,7 +84,6 @@ trait AuthKeyHandler
|
|||||||
//var_dump($key);
|
//var_dump($key);
|
||||||
if ($key['fingerprint'] !== $params['key_fingerprint']) {
|
if ($key['fingerprint'] !== $params['key_fingerprint']) {
|
||||||
$this->discard_secret_chat($params['id']);
|
$this->discard_secret_chat($params['id']);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
||||||
}
|
}
|
||||||
$key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16);
|
$key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16);
|
||||||
@ -99,22 +91,19 @@ trait AuthKeyHandler
|
|||||||
$this->secret_chats[$params['id']] = ['key' => $key, 'admin' => true, 'user_id' => $params['participant_id'], 'InputEncryptedChat' => ['chat_id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputEncryptedChat'], 'in_seq_no_x' => 0, 'out_seq_no_x' => 1, 'in_seq_no' => 0, 'out_seq_no' => 0, 'layer' => 8, 'ttl' => 0, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0], 'key_x' => 'to server', 'mtproto' => 1];
|
$this->secret_chats[$params['id']] = ['key' => $key, 'admin' => true, 'user_id' => $params['participant_id'], 'InputEncryptedChat' => ['chat_id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputEncryptedChat'], 'in_seq_no_x' => 0, 'out_seq_no_x' => 1, 'in_seq_no' => 0, 'out_seq_no' => 0, 'layer' => 8, 'ttl' => 0, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0], 'key_x' => 'to server', 'mtproto' => 1];
|
||||||
$this->notify_layer($params['id']);
|
$this->notify_layer($params['id']);
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
\danog\MadelineProto\Logger::log(['Secret chat '.$params['id'].' completed successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Secret chat ' . $params['id'] . ' completed successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
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]]], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNotifyLayer', 'layer' => $this->encrypted_layer]]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $temp_rekeyed_secret_chats = [];
|
protected $temp_rekeyed_secret_chats = [];
|
||||||
|
|
||||||
public function rekey($chat)
|
public function rekey($chat)
|
||||||
{
|
{
|
||||||
if ($this->secret_chats[$chat]['rekeying'][0] !== 0) {
|
if ($this->secret_chats[$chat]['rekeying'][0] !== 0) {
|
||||||
return;
|
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);
|
||||||
$a = new \phpseclib\Math\BigInteger($this->random(256), 256);
|
$a = new \phpseclib\Math\BigInteger($this->random(256), 256);
|
||||||
@ -127,10 +116,8 @@ trait AuthKeyHandler
|
|||||||
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionRequestKey', 'g_a' => $g_a->toBytes(), 'exchange_id' => $e]]], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionRequestKey', 'g_a' => $g_a->toBytes(), 'exchange_id' => $e]]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
$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) {
|
||||||
@ -142,11 +129,10 @@ trait AuthKeyHandler
|
|||||||
}
|
}
|
||||||
if ($my_exchange_id === $other_exchange_id) {
|
if ($my_exchange_id === $other_exchange_id) {
|
||||||
$this->secret_chats[$chat]['rekeying'] = [0];
|
$this->secret_chats[$chat]['rekeying'] = [0];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Accepting rekeying of secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Accepting rekeying of secret chat ' . $chat . '...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$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);
|
||||||
@ -154,7 +140,6 @@ trait AuthKeyHandler
|
|||||||
$this->check_G($params['g_a'], $dh_config['p']);
|
$this->check_G($params['g_a'], $dh_config['p']);
|
||||||
$key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
$key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
||||||
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
|
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
|
||||||
|
|
||||||
$key['visualization_orig'] = $this->secret_chats[$chat]['key']['visualization_orig'];
|
$key['visualization_orig'] = $this->secret_chats[$chat]['key']['visualization_orig'];
|
||||||
$key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20);
|
$key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20);
|
||||||
$this->temp_rekeyed_secret_chats[$params['exchange_id']] = $key;
|
$this->temp_rekeyed_secret_chats[$params['exchange_id']] = $key;
|
||||||
@ -165,15 +150,13 @@ trait AuthKeyHandler
|
|||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function commit_rekey($chat, $params)
|
public function commit_rekey($chat, $params)
|
||||||
{
|
{
|
||||||
if ($this->secret_chats[$chat]['rekeying'][0] !== 1 || !isset($this->temp_rekeyed_secret_chats[$params['exchange_id']])) {
|
if ($this->secret_chats[$chat]['rekeying'][0] !== 1 || !isset($this->temp_rekeyed_secret_chats[$params['exchange_id']])) {
|
||||||
$this->secret_chats[$chat]['rekeying'] = [0];
|
$this->secret_chats[$chat]['rekeying'] = [0];
|
||||||
|
|
||||||
return;
|
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);
|
||||||
$this->check_G($params['g_b'], $dh_config['p']);
|
$this->check_G($params['g_b'], $dh_config['p']);
|
||||||
@ -183,7 +166,6 @@ trait AuthKeyHandler
|
|||||||
$key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20);
|
$key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20);
|
||||||
if ($key['fingerprint'] !== $params['key_fingerprint']) {
|
if ($key['fingerprint'] !== $params['key_fingerprint']) {
|
||||||
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
||||||
}
|
}
|
||||||
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionCommitKey', 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionCommitKey', 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
@ -193,11 +175,9 @@ trait AuthKeyHandler
|
|||||||
$this->secret_chats[$chat]['key'] = $key;
|
$this->secret_chats[$chat]['key'] = $key;
|
||||||
$this->secret_chats[$chat]['ttr'] = 100;
|
$this->secret_chats[$chat]['ttr'] = 100;
|
||||||
$this->secret_chats[$chat]['updated'] = time();
|
$this->secret_chats[$chat]['updated'] = time();
|
||||||
|
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function complete_rekey($chat, $params)
|
public function complete_rekey($chat, $params)
|
||||||
{
|
{
|
||||||
if ($this->secret_chats[$chat]['rekeying'][0] !== 2 || !isset($this->temp_rekeyed_secret_chats['fingerprint'])) {
|
if ($this->secret_chats[$chat]['rekeying'][0] !== 2 || !isset($this->temp_rekeyed_secret_chats['fingerprint'])) {
|
||||||
@ -205,10 +185,9 @@ trait AuthKeyHandler
|
|||||||
}
|
}
|
||||||
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']]]], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log(['Completing rekeying of secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Completing rekeying of secret chat ' . $chat . '...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->secret_chats[$chat]['rekeying'] = [0];
|
$this->secret_chats[$chat]['rekeying'] = [0];
|
||||||
$this->secret_chats[$chat]['old_key'] = $this->secret_chats[$chat]['key'];
|
$this->secret_chats[$chat]['old_key'] = $this->secret_chats[$chat]['key'];
|
||||||
$this->secret_chats[$chat]['key'] = $this->temp_rekeyed_secret_chats[$chat];
|
$this->secret_chats[$chat]['key'] = $this->temp_rekeyed_secret_chats[$chat];
|
||||||
@ -216,11 +195,9 @@ trait AuthKeyHandler
|
|||||||
$this->secret_chats[$chat]['updated'] = time();
|
$this->secret_chats[$chat]['updated'] = time();
|
||||||
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']]], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNoop']]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
\danog\MadelineProto\Logger::log(['Secret chat '.$chat.' rekeyed successfully!'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Secret chat ' . $chat . ' rekeyed successfully!'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function secret_chat_status($chat)
|
public function secret_chat_status($chat)
|
||||||
{
|
{
|
||||||
if (isset($this->secret_chats[$chat])) {
|
if (isset($this->secret_chats[$chat])) {
|
||||||
@ -229,18 +206,15 @@ trait AuthKeyHandler
|
|||||||
if (isset($this->temp_requested_secret_chats[$chat])) {
|
if (isset($this->temp_requested_secret_chats[$chat])) {
|
||||||
return 1;
|
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 discard_secret_chat($chat)
|
public function discard_secret_chat($chat)
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log(['Discarding secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log(['Discarding secret chat ' . $chat . '...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
//var_dump(debug_backtrace(0)[0]);
|
//var_dump(debug_backtrace(0)[0]);
|
||||||
if (isset($this->secret_chats[$chat])) {
|
if (isset($this->secret_chats[$chat])) {
|
||||||
unset($this->secret_chats[$chat]);
|
unset($this->secret_chats[$chat]);
|
||||||
@ -251,7 +225,6 @@ trait AuthKeyHandler
|
|||||||
if (isset($this->temp_rekeyed_secret_chats[$chat])) {
|
if (isset($this->temp_rekeyed_secret_chats[$chat])) {
|
||||||
unset($this->temp_rekeyed_secret_chats[$chat]);
|
unset($this->temp_rekeyed_secret_chats[$chat]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->method_call('messages.discardEncryption', ['chat_id' => $chat], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.discardEncryption', ['chat_id' => $chat], ['datacenter' => $this->datacenter->curdc]);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\SecretChats;
|
namespace danog\MadelineProto\SecretChats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,10 +21,8 @@ trait MessageHandler
|
|||||||
{
|
{
|
||||||
if (!isset($this->secret_chats[$chat_id])) {
|
if (!isset($this->secret_chats[$chat_id])) {
|
||||||
\danog\MadelineProto\Logger::log(sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $chat_id));
|
\danog\MadelineProto\Logger::log(sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $chat_id));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->secret_chats[$chat_id]['ttr']--;
|
$this->secret_chats[$chat_id]['ttr']--;
|
||||||
if ($this->secret_chats[$chat_id]['layer'] > 8) {
|
if ($this->secret_chats[$chat_id]['layer'] > 8) {
|
||||||
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] === 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] === 0) {
|
||||||
@ -35,34 +33,27 @@ trait MessageHandler
|
|||||||
}
|
}
|
||||||
$this->secret_chats[$chat_id]['outgoing'][$this->secret_chats[$chat_id]['out_seq_no']] = $message;
|
$this->secret_chats[$chat_id]['outgoing'][$this->secret_chats[$chat_id]['out_seq_no']] = $message;
|
||||||
$message = $this->serialize_object(['type' => $constructor = $this->secret_chats[$chat_id]['layer'] === 8 ? 'DecryptedMessage' : 'DecryptedMessageLayer'], $message, $constructor, $this->secret_chats[$chat_id]['layer']);
|
$message = $this->serialize_object(['type' => $constructor = $this->secret_chats[$chat_id]['layer'] === 8 ? 'DecryptedMessage' : 'DecryptedMessageLayer'], $message, $constructor, $this->secret_chats[$chat_id]['layer']);
|
||||||
$message = $this->pack_unsigned_int(strlen($message)).$message;
|
$message = $this->pack_unsigned_int(strlen($message)) . $message;
|
||||||
|
|
||||||
if ($this->secret_chats[$chat_id]['mtproto'] === 2) {
|
if ($this->secret_chats[$chat_id]['mtproto'] === 2) {
|
||||||
$padding = $this->posmod(-strlen($message), 16);
|
$padding = $this->posmod(-strlen($message), 16);
|
||||||
if ($padding < 12) {
|
if ($padding < 12) {
|
||||||
$padding += 16;
|
$padding += 16;
|
||||||
}
|
}
|
||||||
$message .= $this->random($padding);
|
$message .= $this->random($padding);
|
||||||
|
$message_key = substr(hash('sha256', substr($this->secret_chats[$chat_id]['key']['auth_key'], 88 + ($this->secret_chats[$chat_id]['admin'] ? 0 : 8), 32) . $message, true), 8, 16);
|
||||||
$message_key = substr(hash('sha256', substr($this->secret_chats[$chat_id]['key']['auth_key'], 88 + ($this->secret_chats[$chat_id]['admin'] ? 0 : 8), 32).$message, true), 8, 16);
|
|
||||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], $this->secret_chats[$chat_id]['admin']);
|
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], $this->secret_chats[$chat_id]['admin']);
|
||||||
} else {
|
} else {
|
||||||
$message_key = substr(sha1($message, true), -16);
|
$message_key = substr(sha1($message, true), -16);
|
||||||
list($aes_key, $aes_iv) = $this->old_aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], true);
|
list($aes_key, $aes_iv) = $this->old_aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], true);
|
||||||
|
|
||||||
$message .= $this->random($this->posmod(-strlen($message), 16));
|
$message .= $this->random($this->posmod(-strlen($message), 16));
|
||||||
}
|
}
|
||||||
|
$message = $this->secret_chats[$chat_id]['key']['fingerprint'] . $message_key . $this->ige_encrypt($message, $aes_key, $aes_iv);
|
||||||
$message = $this->secret_chats[$chat_id]['key']['fingerprint'].$message_key.$this->ige_encrypt($message, $aes_key, $aes_iv);
|
|
||||||
|
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_encrypted_update($message, $test = false)
|
public function handle_encrypted_update($message, $test = false)
|
||||||
{
|
{
|
||||||
if (!isset($this->secret_chats[$message['message']['chat_id']])) {
|
if (!isset($this->secret_chats[$message['message']['chat_id']])) {
|
||||||
\danog\MadelineProto\Logger::log(sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $message['message']['chat_id']));
|
\danog\MadelineProto\Logger::log(sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $message['message']['chat_id']));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$auth_key_id = substr($message['message']['bytes'], 0, 8);
|
$auth_key_id = substr($message['message']['bytes'], 0, 8);
|
||||||
@ -71,47 +62,39 @@ trait MessageHandler
|
|||||||
if (isset($this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint'])) {
|
if (isset($this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint'])) {
|
||||||
if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint']) {
|
if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint']) {
|
||||||
$this->discard_secret_chat($message['message']['chat_id']);
|
$this->discard_secret_chat($message['message']['chat_id']);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_mismatch']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_mismatch']);
|
||||||
}
|
}
|
||||||
$old = true;
|
$old = true;
|
||||||
} else {
|
} else {
|
||||||
$this->discard_secret_chat($message['message']['chat_id']);
|
$this->discard_secret_chat($message['message']['chat_id']);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_mismatch']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['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);
|
||||||
|
|
||||||
if ($this->secret_chats[$message['message']['chat_id']]['mtproto'] === 2) {
|
if ($this->secret_chats[$message['message']['chat_id']]['mtproto'] === 2) {
|
||||||
\danog\MadelineProto\Logger::log(['Trying MTProto v2 decryption for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Trying MTProto v2 decryption for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$message_data = $this->try_mtproto_v2_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
$message_data = $this->try_mtproto_v2_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
||||||
\danog\MadelineProto\Logger::log(['MTProto v2 decryption OK for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['MTProto v2 decryption OK for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
} catch (\danog\MadelineProto\SecurityException $e) {
|
} catch (\danog\MadelineProto\SecurityException $e) {
|
||||||
\danog\MadelineProto\Logger::log(['MTProto v2 decryption failed with message '.$e->getMessage().', trying MTProto v1 decryption for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['MTProto v2 decryption failed with message ' . $e->getMessage() . ', trying MTProto v1 decryption for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$message_data = $this->try_mtproto_v1_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
$message_data = $this->try_mtproto_v1_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
||||||
\danog\MadelineProto\Logger::log(['MTProto v1 decryption OK for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['MTProto v1 decryption OK for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->secret_chats[$message['message']['chat_id']]['mtproto'] = 1;
|
$this->secret_chats[$message['message']['chat_id']]['mtproto'] = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
\danog\MadelineProto\Logger::log(['Trying MTProto v1 decryption for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['Trying MTProto v1 decryption for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$message_data = $this->try_mtproto_v1_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
$message_data = $this->try_mtproto_v1_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
||||||
\danog\MadelineProto\Logger::log(['MTProto v1 decryption OK for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['MTProto v1 decryption OK for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
} catch (\danog\MadelineProto\SecurityException $e) {
|
} catch (\danog\MadelineProto\SecurityException $e) {
|
||||||
\danog\MadelineProto\Logger::log(['MTProto v1 decryption failed with message '.$e->getMessage().', trying MTProto v2 decryption for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['MTProto v1 decryption failed with message ' . $e->getMessage() . ', trying MTProto v2 decryption for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$message_data = $this->try_mtproto_v2_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
$message_data = $this->try_mtproto_v2_decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
|
||||||
\danog\MadelineProto\Logger::log(['MTProto v2 decryption OK for chat '.$message['message']['chat_id'].'...'], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log(['MTProto v2 decryption OK for chat ' . $message['message']['chat_id'] . '...'], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
$this->secret_chats[$message['message']['chat_id']]['mtproto'] = 2;
|
$this->secret_chats[$message['message']['chat_id']]['mtproto'] = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$deserialized = $this->deserialize($message_data, ['type' => '']);
|
$deserialized = $this->deserialize($message_data, ['type' => '']);
|
||||||
$this->secret_chats[$message['message']['chat_id']]['ttr']--;
|
$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] === 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] === 0) {
|
||||||
@ -120,60 +103,49 @@ trait MessageHandler
|
|||||||
unset($message['message']['bytes']);
|
unset($message['message']['bytes']);
|
||||||
$message['message']['decrypted_message'] = $deserialized;
|
$message['message']['decrypted_message'] = $deserialized;
|
||||||
$this->secret_chats[$message['message']['chat_id']]['incoming'][$this->secret_chats[$message['message']['chat_id']]['in_seq_no']] = $message['message'];
|
$this->secret_chats[$message['message']['chat_id']]['incoming'][$this->secret_chats[$message['message']['chat_id']]['in_seq_no']] = $message['message'];
|
||||||
|
|
||||||
$this->handle_decrypted_update($message);
|
$this->handle_decrypted_update($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function try_mtproto_v1_decrypt($message_key, $chat_id, $old, $encrypted_data)
|
public function try_mtproto_v1_decrypt($message_key, $chat_id, $old, $encrypted_data)
|
||||||
{
|
{
|
||||||
list($aes_key, $aes_iv) = $this->old_aes_calculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], true);
|
list($aes_key, $aes_iv) = $this->old_aes_calculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], true);
|
||||||
$decrypted_data = $this->ige_decrypt($encrypted_data, $aes_key, $aes_iv);
|
$decrypted_data = $this->ige_decrypt($encrypted_data, $aes_key, $aes_iv);
|
||||||
|
|
||||||
$message_data_length = unpack('V', substr($decrypted_data, 0, 4))[1];
|
$message_data_length = unpack('V', substr($decrypted_data, 0, 4))[1];
|
||||||
$message_data = substr($decrypted_data, 4, $message_data_length);
|
$message_data = substr($decrypted_data, 4, $message_data_length);
|
||||||
if ($message_data_length > strlen($decrypted_data)) {
|
if ($message_data_length > strlen($decrypted_data)) {
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message_key != substr(sha1(substr($decrypted_data, 0, 4 + $message_data_length), true), -16)) {
|
if ($message_key != substr(sha1(substr($decrypted_data, 0, 4 + $message_data_length), true), -16)) {
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_key_mismatch']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_key_mismatch']);
|
||||||
}
|
}
|
||||||
if ((strlen($decrypted_data) - 4) - $message_data_length > 15) {
|
if (strlen($decrypted_data) - 4 - $message_data_length > 15) {
|
||||||
throw new \danog\MadelineProto\SecurityException('difference between message_data_length and the length of the remaining decrypted buffer is too big');
|
throw new \danog\MadelineProto\SecurityException('difference between message_data_length and the length of the remaining decrypted buffer is too big');
|
||||||
}
|
}
|
||||||
if (strlen($decrypted_data) % 16 != 0) {
|
if (strlen($decrypted_data) % 16 != 0) {
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $message_data;
|
return $message_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function try_mtproto_v2_decrypt($message_key, $chat_id, $old, $encrypted_data)
|
public function try_mtproto_v2_decrypt($message_key, $chat_id, $old, $encrypted_data)
|
||||||
{
|
{
|
||||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], !$this->secret_chats[$chat_id]['admin']);
|
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], !$this->secret_chats[$chat_id]['admin']);
|
||||||
$decrypted_data = $this->ige_decrypt($encrypted_data, $aes_key, $aes_iv);
|
$decrypted_data = $this->ige_decrypt($encrypted_data, $aes_key, $aes_iv);
|
||||||
|
|
||||||
$message_data_length = unpack('V', substr($decrypted_data, 0, 4))[1];
|
$message_data_length = unpack('V', substr($decrypted_data, 0, 4))[1];
|
||||||
$message_data = substr($decrypted_data, 4, $message_data_length);
|
$message_data = substr($decrypted_data, 4, $message_data_length);
|
||||||
if ($message_data_length > strlen($decrypted_data)) {
|
if ($message_data_length > strlen($decrypted_data)) {
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
|
||||||
}
|
}
|
||||||
|
if ($message_key != substr(hash('sha256', substr($this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], 88 + ($this->secret_chats[$chat_id]['admin'] ? 8 : 0), 32) . $decrypted_data, true), 8, 16)) {
|
||||||
if ($message_key != substr(hash('sha256', substr($this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], 88 + ($this->secret_chats[$chat_id]['admin'] ? 8 : 0), 32).$decrypted_data, true), 8, 16)) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_key_mismatch']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_key_mismatch']);
|
||||||
}
|
}
|
||||||
|
if (strlen($decrypted_data) - 4 - $message_data_length < 12) {
|
||||||
if ((strlen($decrypted_data) - 4) - $message_data_length < 12) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException('padding is too small');
|
throw new \danog\MadelineProto\SecurityException('padding is too small');
|
||||||
}
|
}
|
||||||
|
if (strlen($decrypted_data) - 4 - $message_data_length > 1024) {
|
||||||
if ((strlen($decrypted_data) - 4) - $message_data_length > 1024) {
|
|
||||||
throw new \danog\MadelineProto\SecurityException('padding is too big');
|
throw new \danog\MadelineProto\SecurityException('padding is too big');
|
||||||
}
|
}
|
||||||
if (strlen($decrypted_data) % 16 != 0) {
|
if (strlen($decrypted_data) % 16 != 0) {
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $message_data;
|
return $message_data;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\SecretChats;
|
namespace danog\MadelineProto\SecretChats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,25 +21,20 @@ trait ResponseHandler
|
|||||||
{
|
{
|
||||||
/*if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) {
|
/*if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) {
|
||||||
throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['rand_bytes_too_short']);
|
throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['rand_bytes_too_short']);
|
||||||
}*/ // already checked in TL.php
|
}*/
|
||||||
|
// already checked in TL.php
|
||||||
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) {
|
if ($update['message']['decrypted_message']['action']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) {
|
||||||
@ -48,34 +43,27 @@ trait ResponseHandler
|
|||||||
if ($update['message']['decrypted_message']['action']['layer'] >= 73) {
|
if ($update['message']['decrypted_message']['action']['layer'] >= 73) {
|
||||||
$this->secret_chats[$update['message']['chat_id']]['mtproto'] = 2;
|
$this->secret_chats[$update['message']['chat_id']]['mtproto'] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 'decryptedMessageActionNoop':
|
case 'decryptedMessageActionNoop':
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'decryptedMessageActionResend':
|
case 'decryptedMessageActionResend':
|
||||||
$update['message']['decrypted_message']['action']['start_seq_no'] -= $this->secret_chats[$update['message']['chat_id']]['out_seq_no_x'];
|
$update['message']['decrypted_message']['action']['start_seq_no'] -= $this->secret_chats[$update['message']['chat_id']]['out_seq_no_x'];
|
||||||
$update['message']['decrypted_message']['action']['end_seq_no'] -= $this->secret_chats[$update['message']['chat_id']]['out_seq_no_x'];
|
$update['message']['decrypted_message']['action']['end_seq_no'] -= $this->secret_chats[$update['message']['chat_id']]['out_seq_no_x'];
|
||||||
$update['message']['decrypted_message']['action']['start_seq_no'] /= 2;
|
$update['message']['decrypted_message']['action']['start_seq_no'] /= 2;
|
||||||
$update['message']['decrypted_message']['action']['end_seq_no'] /= 2;
|
$update['message']['decrypted_message']['action']['end_seq_no'] /= 2;
|
||||||
\danog\MadelineProto\Logger::log(['Resending messages for secret chat '.$update['message']['chat_id']], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log(['Resending messages for secret chat ' . $update['message']['chat_id']], \danog\MadelineProto\Logger::WARNING);
|
||||||
foreach ($this->secret_chats[$update['message']['chat_id']]['outgoing'] as $seq => $message) {
|
foreach ($this->secret_chats[$update['message']['chat_id']]['outgoing'] as $seq => $message) {
|
||||||
if ($seq >= $update['message']['decrypted_message']['action']['start_seq_no'] && $seq <= $update['message']['decrypted_message']['action']['end_seq_no']) {
|
if ($seq >= $update['message']['decrypted_message']['action']['start_seq_no'] && $seq <= $update['message']['decrypted_message']['action']['end_seq_no']) {
|
||||||
//throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['resending_unsupported']);
|
//throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['resending_unsupported']);
|
||||||
$this->method_call('messages.sendEncrypted', ['peer' => $update['message']['chat_id'], 'message' => $update['message']['decrypted_message']], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('messages.sendEncrypted', ['peer' => $update['message']['chat_id'], 'message' => $update['message']['decrypted_message']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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']]);
|
||||||
$this->save_update($update);
|
$this->save_update($update);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -96,7 +84,7 @@ trait ResponseHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['unrecognized_dec_msg'].var_export($update, true));
|
throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['unrecognized_dec_msg'] . var_export($update, true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\SecretChats;
|
namespace danog\MadelineProto\SecretChats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +25,6 @@ trait SeqNoHandler
|
|||||||
if (isset($message['decrypted_message']['in_seq_no'])) {
|
if (isset($message['decrypted_message']['in_seq_no'])) {
|
||||||
if (($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2 < $last) {
|
if (($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2 < $last) {
|
||||||
$this->discard_secret_chat($chat_id);
|
$this->discard_secret_chat($chat_id);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException('in_seq_no is not increasing');
|
throw new \danog\MadelineProto\SecurityException('in_seq_no is not increasing');
|
||||||
}
|
}
|
||||||
$last = ($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2;
|
$last = ($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2;
|
||||||
@ -33,13 +32,10 @@ trait SeqNoHandler
|
|||||||
}
|
}
|
||||||
if ($seqno > $this->secret_chats[$chat_id]['out_seq_no'] + 1) {
|
if ($seqno > $this->secret_chats[$chat_id]['out_seq_no'] + 1) {
|
||||||
$this->discard_secret_chat($chat_id);
|
$this->discard_secret_chat($chat_id);
|
||||||
|
|
||||||
throw new \danog\MadelineProto\SecurityException('in_seq_no is too big');
|
throw new \danog\MadelineProto\SecurityException('in_seq_no is too big');
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function check_secret_out_seq_no($chat_id, $seqno)
|
public function check_secret_out_seq_no($chat_id, $seqno)
|
||||||
{
|
{
|
||||||
$seqno = ($seqno - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2;
|
$seqno = ($seqno - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2;
|
||||||
@ -48,35 +44,31 @@ trait SeqNoHandler
|
|||||||
if (isset($message['decrypted_message']['out_seq_no']) && $C < $this->secret_chats[$chat_id]['in_seq_no']) {
|
if (isset($message['decrypted_message']['out_seq_no']) && $C < $this->secret_chats[$chat_id]['in_seq_no']) {
|
||||||
if (($message['decrypted_message']['out_seq_no'] - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2 !== $C) {
|
if (($message['decrypted_message']['out_seq_no'] - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2 !== $C) {
|
||||||
$this->discard_secret_chat($chat_id);
|
$this->discard_secret_chat($chat_id);
|
||||||
|
throw new \danog\MadelineProto\SecurityException('out_seq_no hole: should be ' . $C . ', is ' . ($message['decrypted_message']['out_seq_no'] - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2);
|
||||||
throw new \danog\MadelineProto\SecurityException('out_seq_no hole: should be '.$C.', is '.(($message['decrypted_message']['out_seq_no'] - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2));
|
|
||||||
} else {
|
} else {
|
||||||
$C++;
|
$C++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//var_dump($C, $seqno);
|
//var_dump($C, $seqno);
|
||||||
if ($seqno < $C) { // <= C
|
if ($seqno < $C) {
|
||||||
\danog\MadelineProto\Logger::log(['WARNING: dropping repeated message with seqno '.$seqno]);
|
// <= C
|
||||||
|
\danog\MadelineProto\Logger::log(['WARNING: dropping repeated message with seqno ' . $seqno]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($seqno > $C) { // > C+1
|
if ($seqno > $C) {
|
||||||
|
// > C+1
|
||||||
$this->discard_secret_chat($chat_id);
|
$this->discard_secret_chat($chat_id);
|
||||||
|
throw new \danog\MadelineProto\SecurityException('WARNING: out_seq_no gap detected (' . $seqno . ' > ' . $C . ')!');
|
||||||
throw new \danog\MadelineProto\SecurityException('WARNING: out_seq_no gap detected ('.$seqno.' > '.$C.')!');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate_secret_in_seq_no($chat)
|
public function generate_secret_in_seq_no($chat)
|
||||||
{
|
{
|
||||||
return $this->secret_chats[$chat]['layer'] > 8 ? ($this->secret_chats[$chat]['in_seq_no'] * 2) + $this->secret_chats[$chat]['in_seq_no_x'] : -1;
|
return $this->secret_chats[$chat]['layer'] > 8 ? $this->secret_chats[$chat]['in_seq_no'] * 2 + $this->secret_chats[$chat]['in_seq_no_x'] : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate_secret_out_seq_no($chat)
|
public function generate_secret_out_seq_no($chat)
|
||||||
{
|
{
|
||||||
return $this->secret_chats[$chat]['layer'] > 8 ? ($this->secret_chats[$chat]['out_seq_no'] * 2) + $this->secret_chats[$chat]['out_seq_no_x'] : -1;
|
return $this->secret_chats[$chat]['layer'] > 8 ? $this->secret_chats[$chat]['out_seq_no'] * 2 + $this->secret_chats[$chat]['out_seq_no_x'] : -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class SecurityException extends \Exception
|
class SecurityException extends \Exception
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,11 +18,9 @@ namespace danog\MadelineProto;
|
|||||||
class Serialization
|
class Serialization
|
||||||
{
|
{
|
||||||
public static $instances = [];
|
public static $instances = [];
|
||||||
|
|
||||||
public static function serialize_all($exception)
|
public static function serialize_all($exception)
|
||||||
{
|
{
|
||||||
echo $exception.PHP_EOL;
|
echo $exception . PHP_EOL;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
foreach (self::$instances as $instance) {
|
foreach (self::$instances as $instance) {
|
||||||
if (isset($instance->session)) {
|
if (isset($instance->session)) {
|
||||||
@ -30,16 +28,13 @@ class Serialization
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function realpaths($file)
|
public static function realpaths($file)
|
||||||
{
|
{
|
||||||
if ($file[0] !== '/') {
|
if ($file[0] !== '/') {
|
||||||
$file = getcwd().'/'.$file;
|
$file = getcwd() . '/' . $file;
|
||||||
}
|
}
|
||||||
|
return ['file' => $file, 'lockfile' => $file . '.lock', 'tempfile' => $file . '.temp.session'];
|
||||||
return ['file' => $file, 'lockfile' => $file.'.lock', 'tempfile' => $file.'.temp.session'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize API class.
|
* Serialize API class.
|
||||||
*
|
*
|
||||||
@ -64,7 +59,6 @@ class Serialization
|
|||||||
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'w');
|
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'w');
|
||||||
\danog\MadelineProto\Logger::log(['Waiting for exclusive lock of serialization lockfile...']);
|
\danog\MadelineProto\Logger::log(['Waiting for exclusive lock of serialization lockfile...']);
|
||||||
flock($realpaths['lockfile'], LOCK_EX);
|
flock($realpaths['lockfile'], LOCK_EX);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$wrote = file_put_contents($realpaths['tempfile'], serialize($instance));
|
$wrote = file_put_contents($realpaths['tempfile'], serialize($instance));
|
||||||
rename($realpaths['tempfile'], $realpaths['file']);
|
rename($realpaths['tempfile'], $realpaths['file']);
|
||||||
@ -72,10 +66,8 @@ class Serialization
|
|||||||
flock($realpaths['lockfile'], LOCK_UN);
|
flock($realpaths['lockfile'], LOCK_UN);
|
||||||
fclose($realpaths['lockfile']);
|
fclose($realpaths['lockfile']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $wrote;
|
return $wrote;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize API class.
|
* Deserialize API class.
|
||||||
*
|
*
|
||||||
@ -94,32 +86,28 @@ class Serialization
|
|||||||
clearstatcache();
|
clearstatcache();
|
||||||
}
|
}
|
||||||
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'r');
|
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'r');
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log(['Waiting for shared lock of serialization lockfile...']);
|
\danog\MadelineProto\Logger::log(['Waiting for shared lock of serialization lockfile...']);
|
||||||
flock($realpaths['lockfile'], LOCK_SH);
|
flock($realpaths['lockfile'], LOCK_SH);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$unserialized = file_get_contents($realpaths['file']);
|
$unserialized = file_get_contents($realpaths['file']);
|
||||||
} finally {
|
} finally {
|
||||||
flock($realpaths['lockfile'], LOCK_UN);
|
flock($realpaths['lockfile'], LOCK_UN);
|
||||||
fclose($realpaths['lockfile']);
|
fclose($realpaths['lockfile']);
|
||||||
}
|
}
|
||||||
|
$tounserialize = str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $unserialized);
|
||||||
$tounserialize = str_replace('O:26:"danog\MadelineProto\Button":', 'O:35:"danog\MadelineProto\TL\Types\Button":', $unserialized);
|
foreach (['RSA', 'TL\\TLMethod', 'TL\\TLConstructor', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\\Types\\Button', 'TL\\Types\\Bytes', 'APIFactory'] as $class) {
|
||||||
foreach (['RSA', 'TL\TLMethod', 'TL\TLConstructor', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\Types\Button', 'TL\Types\Bytes', 'APIFactory'] as $class) {
|
class_exists('\\danog\\MadelineProto\\' . $class);
|
||||||
class_exists('\danog\MadelineProto\\'.$class);
|
|
||||||
}
|
}
|
||||||
class_exists('\Volatile');
|
class_exists('\\Volatile');
|
||||||
\danog\MadelineProto\Logger::class_exists();
|
\danog\MadelineProto\Logger::class_exists();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$unserialized = unserialize($tounserialize);
|
$unserialized = unserialize($tounserialize);
|
||||||
} catch (\danog\MadelineProto\Bug74586Exception $e) {
|
} catch (\danog\MadelineProto\Bug74586Exception $e) {
|
||||||
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
||||||
} catch (\danog\MadelineProto\Exception $e) {
|
} catch (\danog\MadelineProto\Exception $e) {
|
||||||
Logger::log([(string) $e], Logger::ERROR);
|
Logger::log([(string) $e], Logger::ERROR);
|
||||||
if (strpos($e->getMessage(), "Erroneous data format for unserializing 'phpseclib\Math\BigInteger'") === 0) {
|
if (strpos($e->getMessage(), "Erroneous data format for unserializing 'phpseclib\\Math\\BigInteger'") === 0) {
|
||||||
$tounserialize = str_replace('phpseclib\Math\BigInteger', 'phpseclib\Math\BigIntegor', $unserialized);
|
$tounserialize = str_replace('phpseclib\\Math\\BigInteger', 'phpseclib\\Math\\BigIntegor', $unserialized);
|
||||||
}
|
}
|
||||||
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
$unserialized = \danog\Serialization::unserialize($tounserialize);
|
||||||
}
|
}
|
||||||
@ -136,7 +124,6 @@ class Serialization
|
|||||||
$unserialized->session = $filename;
|
$unserialized->session = $filename;
|
||||||
}
|
}
|
||||||
self::$instances[spl_object_hash($unserialized)] = $unserialized;
|
self::$instances[spl_object_hash($unserialized)] = $unserialized;
|
||||||
|
|
||||||
return $unserialized;
|
return $unserialized;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL\Conversion;
|
namespace danog\MadelineProto\TL\Conversion;
|
||||||
|
|
||||||
trait BotAPI
|
trait BotAPI
|
||||||
@ -18,7 +18,6 @@ trait BotAPI
|
|||||||
{
|
{
|
||||||
return html_entity_decode(preg_replace('#< *br */? *>#', "\n", $stuff));
|
return html_entity_decode(preg_replace('#< *br */? *>#', "\n", $stuff));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parse_buttons($rows)
|
public function parse_buttons($rows)
|
||||||
{
|
{
|
||||||
$newrows = [];
|
$newrows = [];
|
||||||
@ -54,10 +53,8 @@ trait BotAPI
|
|||||||
}
|
}
|
||||||
$key++;
|
$key++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $newrows;
|
return $newrows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parse_reply_markup($markup)
|
public function parse_reply_markup($markup)
|
||||||
{
|
{
|
||||||
if (isset($markup['force_reply']) && $markup['force_reply']) {
|
if (isset($markup['force_reply']) && $markup['force_reply']) {
|
||||||
@ -86,10 +83,8 @@ trait BotAPI
|
|||||||
$markup['rows'] = $this->parse_buttons($markup['inline_keyboard']);
|
$markup['rows'] = $this->parse_buttons($markup['inline_keyboard']);
|
||||||
unset($markup['inline_keyboard']);
|
unset($markup['inline_keyboard']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $markup;
|
return $markup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function MTProto_to_botAPI($data, $sent_arguments = [])
|
public function MTProto_to_botAPI($data, $sent_arguments = [])
|
||||||
{
|
{
|
||||||
$newd = [];
|
$newd = [];
|
||||||
@ -97,7 +92,6 @@ 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['_']) {
|
||||||
@ -115,13 +109,10 @@ trait BotAPI
|
|||||||
if (isset($data['media'])) {
|
if (isset($data['media'])) {
|
||||||
$newd = array_merge($newd, $this->MTProto_to_botAPI($data['media'], $sent_arguments));
|
$newd = array_merge($newd, $this->MTProto_to_botAPI($data['media'], $sent_arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $newd;
|
return $newd;
|
||||||
|
|
||||||
case 'updateNewChannelMessage':
|
case 'updateNewChannelMessage':
|
||||||
case 'updateNewMessage':
|
case 'updateNewMessage':
|
||||||
return $this->MTProto_to_botAPI($data['message']);
|
return $this->MTProto_to_botAPI($data['message']);
|
||||||
|
|
||||||
case 'message':
|
case 'message':
|
||||||
$newd['message_id'] = $data['id'];
|
$newd['message_id'] = $data['id'];
|
||||||
$newd['date'] = $data['date'];
|
$newd['date'] = $data['date'];
|
||||||
@ -156,81 +147,56 @@ trait BotAPI
|
|||||||
if (isset($data['fwd_from']['channel_post'])) {
|
if (isset($data['fwd_from']['channel_post'])) {
|
||||||
$newd['forward_from_message_id'] = $data['fwd_from']['channel_post'];
|
$newd['forward_from_message_id'] = $data['fwd_from']['channel_post'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['media'])) {
|
if (isset($data['media'])) {
|
||||||
$newd = array_merge($newd, $this->MTProto_to_botAPI($data['media'], $sent_arguments));
|
$newd = array_merge($newd, $this->MTProto_to_botAPI($data['media'], $sent_arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $newd;
|
return $newd;
|
||||||
|
|
||||||
case 'messageEntityMention':
|
case 'messageEntityMention':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'mention';
|
$data['type'] = 'mention';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityHashtag':
|
case 'messageEntityHashtag':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'hashtag';
|
$data['type'] = 'hashtag';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityBotCommand':
|
case 'messageEntityBotCommand':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'bot_command';
|
$data['type'] = 'bot_command';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityUrl':
|
case 'messageEntityUrl':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'url';
|
$data['type'] = 'url';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityEmail':
|
case 'messageEntityEmail':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'email';
|
$data['type'] = 'email';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityBold':
|
case 'messageEntityBold':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'bold';
|
$data['type'] = 'bold';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityItalic':
|
case 'messageEntityItalic':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'italic';
|
$data['type'] = 'italic';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityCode':
|
case 'messageEntityCode':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'code';
|
$data['type'] = 'code';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityPre':
|
case 'messageEntityPre':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'pre';
|
$data['type'] = 'pre';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityTextUrl':
|
case 'messageEntityTextUrl':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'text_url';
|
$data['type'] = 'text_url';
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageEntityMentionName':
|
case 'messageEntityMentionName':
|
||||||
unset($data['_']);
|
unset($data['_']);
|
||||||
$data['type'] = 'text_mention';
|
$data['type'] = 'text_mention';
|
||||||
$data['user'] = $this->get_pwr_chat($data['user_id']);
|
$data['user'] = $this->get_pwr_chat($data['user_id']);
|
||||||
unset($data['user_id']);
|
unset($data['user_id']);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
||||||
case 'messageMediaPhoto':
|
case 'messageMediaPhoto':
|
||||||
if (isset($data['caption'])) {
|
if (isset($data['caption'])) {
|
||||||
$res['caption'] = $data['caption'];
|
$res['caption'] = $data['caption'];
|
||||||
@ -239,11 +205,9 @@ trait BotAPI
|
|||||||
foreach ($data['photo']['sizes'] as $key => $photo) {
|
foreach ($data['photo']['sizes'] as $key => $photo) {
|
||||||
$res['photo'][$key] = $this->photosize_to_botapi($photo, $data['photo']);
|
$res['photo'][$key] = $this->photosize_to_botapi($photo, $data['photo']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
case 'messageMediaEmpty':
|
case 'messageMediaEmpty':
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
case 'messageMediaDocument':
|
case 'messageMediaDocument':
|
||||||
$type_name = 'document';
|
$type_name = 'document';
|
||||||
$res = [];
|
$res = [];
|
||||||
@ -254,10 +218,9 @@ trait BotAPI
|
|||||||
switch ($attribute['_']) {
|
switch ($attribute['_']) {
|
||||||
case 'documentAttributeFilename':
|
case 'documentAttributeFilename':
|
||||||
$pathinfo = pathinfo($attribute['file_name']);
|
$pathinfo = pathinfo($attribute['file_name']);
|
||||||
$res['ext'] = isset($pathinfo['extension']) ? '.'.$pathinfo['extension'] : '';
|
$res['ext'] = isset($pathinfo['extension']) ? '.' . $pathinfo['extension'] : '';
|
||||||
$res['file_name'] = $pathinfo['filename'];
|
$res['file_name'] = $pathinfo['filename'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'documentAttributeAudio':
|
case 'documentAttributeAudio':
|
||||||
$audio = $attribute;
|
$audio = $attribute;
|
||||||
$type_name = 'audio';
|
$type_name = 'audio';
|
||||||
@ -275,28 +238,23 @@ trait BotAPI
|
|||||||
$res['title'] = $attribute['waveform'];
|
$res['title'] = $attribute['waveform'];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'documentAttributeVideo':
|
case 'documentAttributeVideo':
|
||||||
$type_name = $attribute['round_message'] ? 'video_note' : 'video';
|
$type_name = $attribute['round_message'] ? 'video_note' : 'video';
|
||||||
$res['width'] = $attribute['w'];
|
$res['width'] = $attribute['w'];
|
||||||
$res['height'] = $attribute['h'];
|
$res['height'] = $attribute['h'];
|
||||||
$res['duration'] = $attribute['duration'];
|
$res['duration'] = $attribute['duration'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'documentAttributeImageSize':
|
case 'documentAttributeImageSize':
|
||||||
$res['width'] = $attribute['w'];
|
$res['width'] = $attribute['w'];
|
||||||
$res['height'] = $attribute['h'];
|
$res['height'] = $attribute['h'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'documentAttributeAnimated':
|
case 'documentAttributeAnimated':
|
||||||
$type_name = 'gif';
|
$type_name = 'gif';
|
||||||
$res['animated'] = true;
|
$res['animated'] = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'documentAttributeHasStickers':
|
case 'documentAttributeHasStickers':
|
||||||
$res['has_stickers'] = true;
|
$res['has_stickers'] = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'documentAttributeSticker':
|
case 'documentAttributeSticker':
|
||||||
$type_name = 'sticker';
|
$type_name = 'sticker';
|
||||||
$res['mask'] = $attribute['mask'];
|
$res['mask'] = $attribute['mask'];
|
||||||
@ -306,44 +264,34 @@ trait BotAPI
|
|||||||
$res['mask_coords'] = $attribute['mask_coords'];
|
$res['mask_coords'] = $attribute['mask_coords'];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($audio) && isset($audio['title']) && !isset($res['file_name'])) {
|
if (isset($audio) && isset($audio['title']) && !isset($res['file_name'])) {
|
||||||
$res['file_name'] = $audio['title'];
|
$res['file_name'] = $audio['title'];
|
||||||
if (isset($audio['performer'])) {
|
if (isset($audio['performer'])) {
|
||||||
$res['file_name'] .= ' - '.$audio['performer'];
|
$res['file_name'] .= ' - ' . $audio['performer'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isset($res['file_name'])) {
|
if (!isset($res['file_name'])) {
|
||||||
$res['file_name'] = $data['document']['access_hash'];
|
$res['file_name'] = $data['document']['access_hash'];
|
||||||
}
|
}
|
||||||
$res['file_name'] .= '_'.$data['document']['id'];
|
$res['file_name'] .= '_' . $data['document']['id'];
|
||||||
if (isset($res['ext'])) {
|
if (isset($res['ext'])) {
|
||||||
$res['file_name'] .= $res['ext'];
|
$res['file_name'] .= $res['ext'];
|
||||||
unset($res['ext']);
|
unset($res['ext']);
|
||||||
} else {
|
} else {
|
||||||
$res['file_name'] .= $this->get_extension_from_mime($data['document']['mime_type']);
|
$res['file_name'] .= $this->get_extension_from_mime($data['document']['mime_type']);
|
||||||
}
|
}
|
||||||
$data['document']['_'] = 'bot_'.$type_name;
|
$data['document']['_'] = 'bot_' . $type_name;
|
||||||
$res['file_size'] = $data['document']['size'];
|
$res['file_size'] = $data['document']['size'];
|
||||||
$res['mime_type'] = $data['document']['mime_type'];
|
$res['mime_type'] = $data['document']['mime_type'];
|
||||||
$res['file_id'] = $this->base64url_encode($this->rle_encode($this->serialize_object(['type' => 'File'], $data['document'], 'File').chr(2)));
|
$res['file_id'] = $this->base64url_encode($this->rle_encode($this->serialize_object(['type' => 'File'], $data['document'], 'File') . chr(2)));
|
||||||
|
|
||||||
return [$type_name => $res, 'caption' => isset($data['caption']) ? $data['caption'] : ''];
|
return [$type_name => $res, 'caption' => isset($data['caption']) ? $data['caption'] : ''];
|
||||||
default:
|
default:
|
||||||
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['botapi_conversion_error'], $data['_']));
|
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['botapi_conversion_error'], $data['_']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public $botapi_params = ['disable_web_page_preview' => 'no_webpage', 'disable_notification' => 'silent', 'reply_to_message_id' => 'reply_to_msg_id', 'chat_id' => 'peer', 'text' => 'message'];
|
||||||
public $botapi_params = [
|
|
||||||
'disable_web_page_preview' => 'no_webpage',
|
|
||||||
'disable_notification' => 'silent',
|
|
||||||
'reply_to_message_id' => 'reply_to_msg_id',
|
|
||||||
'chat_id' => 'peer',
|
|
||||||
'text' => 'message',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function botAPI_to_MTProto($arguments)
|
public function botAPI_to_MTProto($arguments)
|
||||||
{
|
{
|
||||||
foreach ($this->botapi_params as $bot => $mtproto) {
|
foreach ($this->botapi_params as $bot => $mtproto) {
|
||||||
@ -358,10 +306,8 @@ trait BotAPI
|
|||||||
if (isset($arguments['parse_mode'])) {
|
if (isset($arguments['parse_mode'])) {
|
||||||
$arguments = $this->parse_mode($arguments);
|
$arguments = $this->parse_mode($arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $arguments;
|
return $arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parse_node($node, &$entities, &$nmessage, $recursive = true)
|
public function parse_node($node, &$entities, &$nmessage, $recursive = true)
|
||||||
{
|
{
|
||||||
switch ($node->nodeName) {
|
switch ($node->nodeName) {
|
||||||
@ -374,20 +320,17 @@ trait BotAPI
|
|||||||
$entities[] = ['_' => 'messageEntityBold', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text)];
|
$entities[] = ['_' => 'messageEntityBold', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text)];
|
||||||
$nmessage .= $text;
|
$nmessage .= $text;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'em':
|
case 'em':
|
||||||
$text = $this->html_entity_decode($node->textContent);
|
$text = $this->html_entity_decode($node->textContent);
|
||||||
$entities[] = ['_' => 'messageEntityItalic', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text)];
|
$entities[] = ['_' => 'messageEntityItalic', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text)];
|
||||||
$nmessage .= $text;
|
$nmessage .= $text;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'code':
|
case 'code':
|
||||||
$text = $this->html_entity_decode($node->textContent);
|
$text = $this->html_entity_decode($node->textContent);
|
||||||
$entities[] = ['_' => 'messageEntityCode', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text)];
|
$entities[] = ['_' => 'messageEntityCode', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text)];
|
||||||
$nmessage .= $text;
|
$nmessage .= $text;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'pre':
|
case 'pre':
|
||||||
$text = $this->html_entity_decode($node->textContent);
|
$text = $this->html_entity_decode($node->textContent);
|
||||||
$language = $node->getAttribute('language');
|
$language = $node->getAttribute('language');
|
||||||
@ -397,13 +340,11 @@ trait BotAPI
|
|||||||
$entities[] = ['_' => 'messageEntityPre', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text), 'language' => $language];
|
$entities[] = ['_' => 'messageEntityPre', 'offset' => mb_strlen($nmessage), 'length' => mb_strlen($text), 'language' => $language];
|
||||||
$nmessage .= $text;
|
$nmessage .= $text;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
foreach ($node->childNodes as $node) {
|
foreach ($node->childNodes as $node) {
|
||||||
$this->parse_node($node, $entities, $nmessage);
|
$this->parse_node($node, $entities, $nmessage);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
$text = $this->html_entity_decode($node->textContent);
|
$text = $this->html_entity_decode($node->textContent);
|
||||||
$href = $node->getAttribute('href');
|
$href = $node->getAttribute('href');
|
||||||
@ -428,13 +369,11 @@ trait BotAPI
|
|||||||
}
|
}
|
||||||
$nmessage .= $text;
|
$nmessage .= $text;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$nmessage .= $this->html_entity_decode($node->nodeValue);
|
$nmessage .= $this->html_entity_decode($node->nodeValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parse_mode($arguments)
|
public function parse_mode($arguments)
|
||||||
{
|
{
|
||||||
if (isset($arguments['parse_mode']['_'])) {
|
if (isset($arguments['parse_mode']['_'])) {
|
||||||
@ -446,7 +385,6 @@ trait BotAPI
|
|||||||
}
|
}
|
||||||
if (preg_match('/html/i', $arguments['parse_mode'])) {
|
if (preg_match('/html/i', $arguments['parse_mode'])) {
|
||||||
$nmessage = '';
|
$nmessage = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$arguments['message'] = $this->html_fixtags($arguments['message']);
|
$arguments['message'] = $this->html_fixtags($arguments['message']);
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@ -467,10 +405,8 @@ trait BotAPI
|
|||||||
}
|
}
|
||||||
$arguments['message'] = $nmessage;
|
$arguments['message'] = $nmessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $arguments;
|
return $arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function split_to_chunks($text)
|
public function split_to_chunks($text)
|
||||||
{
|
{
|
||||||
$max_length = 4096;
|
$max_length = 4096;
|
||||||
@ -487,17 +423,15 @@ trait BotAPI
|
|||||||
$i = 0;
|
$i = 0;
|
||||||
$message = [''];
|
$message = [''];
|
||||||
foreach ($text_arr as $word) {
|
foreach ($text_arr as $word) {
|
||||||
if (strlen($message[$i].$word) <= $max_length) {
|
if (strlen($message[$i] . $word) <= $max_length) {
|
||||||
$message[$i] .= $word;
|
$message[$i] .= $word;
|
||||||
} else {
|
} else {
|
||||||
$i++;
|
$i++;
|
||||||
$message[$i] = $word;
|
$message[$i] = $word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function multipleExplodeKeepDelimiters($delimiters, $string)
|
public function multipleExplodeKeepDelimiters($delimiters, $string)
|
||||||
{
|
{
|
||||||
$initialArray = explode(chr(1), str_replace($delimiters, chr(1), $string));
|
$initialArray = explode(chr(1), str_replace($delimiters, chr(1), $string));
|
||||||
@ -506,17 +440,15 @@ trait BotAPI
|
|||||||
foreach ($initialArray as $item) {
|
foreach ($initialArray as $item) {
|
||||||
$delimOffset += strlen($item);
|
$delimOffset += strlen($item);
|
||||||
if (strlen($item) > 0) {
|
if (strlen($item) > 0) {
|
||||||
$finalArray[] = $item.($delimOffset < strlen($string) ? $string[$delimOffset] : '');
|
$finalArray[] = $item . ($delimOffset < strlen($string) ? $string[$delimOffset] : '');
|
||||||
}
|
}
|
||||||
$delimOffset++;
|
$delimOffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $finalArray;
|
return $finalArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function html_fixtags($text)
|
public function html_fixtags($text)
|
||||||
{
|
{
|
||||||
preg_match_all("#(.*?)(<(a|b|strong|em|i|code|pre)[^>]*>)([^<]*?)(<\/\\3>)(.*)?#is", $text, $matches, PREG_SET_ORDER);
|
preg_match_all("#(.*?)(<(a|b|strong|em|i|code|pre)[^>]*>)([^<]*?)(<\\/\\3>)(.*)?#is", $text, $matches, PREG_SET_ORDER);
|
||||||
if ($matches) {
|
if ($matches) {
|
||||||
$last = count($matches) - 1;
|
$last = count($matches) - 1;
|
||||||
foreach ($matches as $val) {
|
foreach ($matches as $val) {
|
||||||
@ -528,17 +460,15 @@ trait BotAPI
|
|||||||
$text = str_replace($val[6], $this->html_fixtags($val[6]), $text);
|
$text = str_replace($val[6], $this->html_fixtags($val[6]), $text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
preg_match_all("#<a href=\x22(.+?)\x22>#is", $text, $matches);
|
preg_match_all("#<a href=\"(.+?)\">#is", $text, $matches);
|
||||||
foreach ($matches[1] as $match) {
|
foreach ($matches[1] as $match) {
|
||||||
$text = str_replace($match, htmlentities($match), $text);
|
$text = str_replace($match, htmlentities($match), $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $text;
|
return $text;
|
||||||
} else {
|
} else {
|
||||||
return htmlentities($text);
|
return htmlentities($text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function build_rows($button_list)
|
public function build_rows($button_list)
|
||||||
{
|
{
|
||||||
$end = false;
|
$end = false;
|
||||||
@ -559,12 +489,10 @@ trait BotAPI
|
|||||||
$end = true;
|
$end = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($end) {
|
if ($end) {
|
||||||
$row = ['_' => 'keyboardButtonRow', 'buttons' => $buttons];
|
$row = ['_' => 'keyboardButtonRow', 'buttons' => $buttons];
|
||||||
$rows[] = $row;
|
$rows[] = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['_' => 'replyInlineMarkup', 'rows' => $rows];
|
return ['_' => 'replyInlineMarkup', 'rows' => $rows];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL\Conversion;
|
namespace danog\MadelineProto\TL\Conversion;
|
||||||
|
|
||||||
trait BotAPIFiles
|
trait BotAPIFiles
|
||||||
@ -18,12 +18,10 @@ trait BotAPIFiles
|
|||||||
{
|
{
|
||||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function base64url_encode($data)
|
public function base64url_encode($data)
|
||||||
{
|
{
|
||||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rle_decode($string)
|
public function rle_decode($string)
|
||||||
{
|
{
|
||||||
$new = '';
|
$new = '';
|
||||||
@ -38,11 +36,9 @@ trait BotAPIFiles
|
|||||||
$last = $cur;
|
$last = $cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$string = $new.$last;
|
$string = $new . $last;
|
||||||
|
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rle_encode($string)
|
public function rle_encode($string)
|
||||||
{
|
{
|
||||||
$new = '';
|
$new = '';
|
||||||
@ -53,34 +49,23 @@ trait BotAPIFiles
|
|||||||
$count++;
|
$count++;
|
||||||
} else {
|
} else {
|
||||||
if ($count > 0) {
|
if ($count > 0) {
|
||||||
$new .= $null.chr($count);
|
$new .= $null . chr($count);
|
||||||
$count = 0;
|
$count = 0;
|
||||||
}
|
}
|
||||||
$new .= $cur;
|
$new .= $cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $new;
|
return $new;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function photosize_to_botapi($photo, $message_media, $thumbnail = false)
|
public function photosize_to_botapi($photo, $message_media, $thumbnail = false)
|
||||||
{
|
{
|
||||||
$ext = $this->get_extension_from_location(['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret'], 'dc_id' => $photo['location']['dc_id']], '.jpg');
|
$ext = $this->get_extension_from_location(['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret'], 'dc_id' => $photo['location']['dc_id']], '.jpg');
|
||||||
$photo['location']['access_hash'] = isset($message_media['access_hash']) ? $message_media['access_hash'] : 0;
|
$photo['location']['access_hash'] = isset($message_media['access_hash']) ? $message_media['access_hash'] : 0;
|
||||||
$photo['location']['id'] = isset($message_media['id']) ? $message_media['id'] : 0;
|
$photo['location']['id'] = isset($message_media['id']) ? $message_media['id'] : 0;
|
||||||
$photo['location']['_'] = $thumbnail ? 'bot_thumbnail' : 'bot_photo';
|
$photo['location']['_'] = $thumbnail ? 'bot_thumbnail' : 'bot_photo';
|
||||||
$data = $this->serialize_object(['type' => 'File'], $photo['location'], 'File').chr(2);
|
$data = $this->serialize_object(['type' => 'File'], $photo['location'], 'File') . chr(2);
|
||||||
|
return ['file_id' => $this->base64url_encode($this->rle_encode($data)), 'width' => $photo['w'], 'height' => $photo['h'], 'file_size' => isset($photo['size']) ? $photo['size'] : strlen($photo['bytes']), 'mime_type' => 'image/jpeg', 'file_name' => $photo['location']['volume_id'] . '_' . $photo['location']['local_id'] . $ext];
|
||||||
return [
|
|
||||||
'file_id' => $this->base64url_encode($this->rle_encode($data)),
|
|
||||||
'width' => $photo['w'],
|
|
||||||
'height' => $photo['h'],
|
|
||||||
'file_size' => isset($photo['size']) ? $photo['size'] : strlen($photo['bytes']),
|
|
||||||
'mime_type' => 'image/jpeg',
|
|
||||||
'file_name' => $photo['location']['volume_id'].'_'.$photo['location']['local_id'].$ext,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unpack_file_id($file_id)
|
public function unpack_file_id($file_id)
|
||||||
{
|
{
|
||||||
$file_id = $this->rle_decode($this->base64url_decode($file_id));
|
$file_id = $this->rle_decode($this->base64url_decode($file_id));
|
||||||
@ -93,69 +78,49 @@ trait BotAPIFiles
|
|||||||
case 'bot_thumbnail':
|
case 'bot_thumbnail':
|
||||||
case 'bot_photo':
|
case 'bot_photo':
|
||||||
$constructor = ['_' => 'photo', 'sizes' => []];
|
$constructor = ['_' => 'photo', 'sizes' => []];
|
||||||
|
|
||||||
$constructor['id'] = $deserialized['id'];
|
$constructor['id'] = $deserialized['id'];
|
||||||
$constructor['access_hash'] = $deserialized['access_hash'];
|
$constructor['access_hash'] = $deserialized['access_hash'];
|
||||||
unset($deserialized['id']);
|
unset($deserialized['id']);
|
||||||
unset($deserialized['access_hash']);
|
unset($deserialized['access_hash']);
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
|
|
||||||
$constructor['sizes'][0]['location'] = $deserialized;
|
$constructor['sizes'][0]['location'] = $deserialized;
|
||||||
|
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaPhoto', 'photo' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaPhoto', 'photo' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
||||||
case 'bot_voice':
|
case 'bot_voice':
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true]]]);
|
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true]]]);
|
||||||
|
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
||||||
case 'bot_video':
|
case 'bot_video':
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeVideo', 'round_message' => false]]]);
|
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeVideo', 'round_message' => false]]]);
|
||||||
|
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
||||||
case 'bot_video_note':
|
case 'bot_video_note':
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeVideo', 'round_message' => true]]]);
|
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeVideo', 'round_message' => true]]]);
|
||||||
|
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
case 'bot_document':
|
case 'bot_document':
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => []]);
|
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => []]);
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
case 'bot_sticker':
|
case 'bot_sticker':
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeSticker']]]);
|
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeSticker']]]);
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
||||||
case 'bot_gif':
|
case 'bot_gif':
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAnimated']]]);
|
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAnimated']]]);
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
||||||
case 'bot_audio':
|
case 'bot_audio':
|
||||||
unset($deserialized['_']);
|
unset($deserialized['_']);
|
||||||
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false]]]);
|
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false]]]);
|
||||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['file_type_invalid'], $type));
|
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['file_type_invalid'], $type));
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL\Conversion;
|
namespace danog\MadelineProto\TL\Conversion;
|
||||||
|
|
||||||
class Exception extends \Exception
|
class Exception extends \Exception
|
||||||
|
@ -11,7 +11,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL\Conversion;
|
namespace danog\MadelineProto\TL\Conversion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,13 +22,11 @@ trait Extension
|
|||||||
{
|
{
|
||||||
foreach (self::ALL_MIMES as $key => $value) {
|
foreach (self::ALL_MIMES as $key => $value) {
|
||||||
if (array_search($mime, (array) $value) !== false) {
|
if (array_search($mime, (array) $value) !== false) {
|
||||||
return '.'.$key;
|
return '.' . $key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_extension_from_location($location, $default)
|
public function get_extension_from_location($location, $default)
|
||||||
{
|
{
|
||||||
return $default;
|
return $default;
|
||||||
@ -38,15 +35,24 @@ trait Extension
|
|||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
switch ($res['type']['_']) {
|
switch ($res['type']['_']) {
|
||||||
case 'storage.fileJpeg': return '.jpg';
|
case 'storage.fileJpeg':
|
||||||
case 'storage.fileGif': return '.gif';
|
return '.jpg';
|
||||||
case 'storage.filePng': return '.png';
|
case 'storage.fileGif':
|
||||||
case 'storage.filePdf': return '.pdf';
|
return '.gif';
|
||||||
case 'storage.fileMp3': return '.mp3';
|
case 'storage.filePng':
|
||||||
case 'storage.fileMov': return '.mov';
|
return '.png';
|
||||||
case 'storage.fileMp4': return '.mp4';
|
case 'storage.filePdf':
|
||||||
case 'storage.fileWebp': return '.webp';
|
return '.pdf';
|
||||||
default: return $default;
|
case 'storage.fileMp3':
|
||||||
|
return '.mp3';
|
||||||
|
case 'storage.fileMov':
|
||||||
|
return '.mov';
|
||||||
|
case 'storage.fileMp4':
|
||||||
|
return '.mp4';
|
||||||
|
case 'storage.fileWebp':
|
||||||
|
return '.webp';
|
||||||
|
default:
|
||||||
|
return $default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL\Conversion;
|
namespace danog\MadelineProto\TL\Conversion;
|
||||||
|
|
||||||
trait TD
|
trait TD
|
||||||
@ -21,7 +21,6 @@ trait TD
|
|||||||
}
|
}
|
||||||
if (!isset($params['ID'])) {
|
if (!isset($params['ID'])) {
|
||||||
array_walk($params, [$this, 'tdcli_to_td']);
|
array_walk($params, [$this, 'tdcli_to_td']);
|
||||||
|
|
||||||
return $params;
|
return $params;
|
||||||
}
|
}
|
||||||
foreach ($params as $key => $value) {
|
foreach ($params as $key => $value) {
|
||||||
@ -33,14 +32,11 @@ 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 = ['_' => self::REVERSE[$params['_']]];
|
$newparams = ['_' => self::REVERSE[$params['_']]];
|
||||||
|
|
||||||
foreach (self::TD_PARAMS_CONVERSION[$newparams['_']] as $td => $mtproto) {
|
foreach (self::TD_PARAMS_CONVERSION[$newparams['_']] as $td => $mtproto) {
|
||||||
if (is_array($mtproto)) {
|
if (is_array($mtproto)) {
|
||||||
switch (end($mtproto)) {
|
switch (end($mtproto)) {
|
||||||
@ -53,7 +49,8 @@ trait TD
|
|||||||
}
|
}
|
||||||
$newparams = array_merge($params[$td], $newparams);
|
$newparams = array_merge($params[$td], $newparams);
|
||||||
break;
|
break;
|
||||||
default: throw new Exception(\danog\MadelineProto\Lang::$current_lang['non_text_conversion']);
|
default:
|
||||||
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['non_text_conversion']);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -64,15 +61,12 @@ trait TD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
public function mtproto_to_td(&$params)
|
||||||
{
|
{
|
||||||
if (!is_array($params)) {
|
if (!is_array($params)) {
|
||||||
@ -80,7 +74,6 @@ trait TD
|
|||||||
}
|
}
|
||||||
if (!isset($params['_'])) {
|
if (!isset($params['_'])) {
|
||||||
array_walk($params, [$this, 'mtproto_to_td']);
|
array_walk($params, [$this, 'mtproto_to_td']);
|
||||||
|
|
||||||
return $params;
|
return $params;
|
||||||
}
|
}
|
||||||
$newparams = ['_' => $params['_']];
|
$newparams = ['_' => $params['_']];
|
||||||
@ -93,7 +86,7 @@ trait TD
|
|||||||
} else {
|
} else {
|
||||||
switch (end($mtproto)) {
|
switch (end($mtproto)) {
|
||||||
case 'choose_chat_id_from_botapi':
|
case 'choose_chat_id_from_botapi':
|
||||||
$newparams[$td] = ($this->get_info($params[$mtproto[0]])['bot_api_id'] == $this->authorization['user']['id']) ? $params['from_id'] : $this->get_info($params[$mtproto[0]])['bot_api_id'];
|
$newparams[$td] = $this->get_info($params[$mtproto[0]])['bot_api_id'] == $this->authorization['user']['id'] ? $params['from_id'] : $this->get_info($params[$mtproto[0]])['bot_api_id'];
|
||||||
break;
|
break;
|
||||||
case 'choose_incoming_or_sent':
|
case 'choose_incoming_or_sent':
|
||||||
$newparams[$td] = ['_' => $params['out'] ? 'messageIsSuccessfullySent' : 'messageIsIncoming'];
|
$newparams[$td] = ['_' => $params['out'] ? 'messageIsSuccessfullySent' : 'messageIsIncoming'];
|
||||||
@ -108,7 +101,7 @@ trait TD
|
|||||||
if (isset($params['fwd_from'])) {
|
if (isset($params['fwd_from'])) {
|
||||||
$newparams[$td] = ['_' => 'messageForwardedFromUser'];
|
$newparams[$td] = ['_' => 'messageForwardedFromUser'];
|
||||||
if (isset($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] = ['_' => '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'])) {
|
if (isset($params['fwd_from']['channel_post'])) {
|
||||||
@ -152,10 +145,8 @@ trait TD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $newparams;
|
return $newparams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function td_to_tdcli($params)
|
public function td_to_tdcli($params)
|
||||||
{
|
{
|
||||||
if (!is_array($params)) {
|
if (!is_array($params)) {
|
||||||
@ -167,12 +158,11 @@ trait TD
|
|||||||
$newparams['ID'] = ucfirst($value);
|
$newparams['ID'] = ucfirst($value);
|
||||||
} else {
|
} else {
|
||||||
if (!is_numeric($key) && !preg_match('/_^/', $key)) {
|
if (!is_numeric($key) && !preg_match('/_^/', $key)) {
|
||||||
$key = $key.'_';
|
$key = $key . '_';
|
||||||
}
|
}
|
||||||
$newparams[$key] = $this->td_to_tdcli($value);
|
$newparams[$key] = $this->td_to_tdcli($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $newparams;
|
return $newparams;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,18 +10,15 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL;
|
namespace danog\MadelineProto\TL;
|
||||||
|
|
||||||
class Exception extends \Exception
|
class Exception extends \Exception
|
||||||
{
|
{
|
||||||
use PrettyException;
|
use PrettyException;
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return get_class($this).($this->message !== '' ? ': ' : '').$this->message.PHP_EOL.@file_get_contents(__DIR__.'/../../../.git/refs/heads/master').PHP_EOL.'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):'.PHP_EOL.PHP_EOL.$this->getTLTrace().PHP_EOL;
|
return get_class($this) . ($this->message !== '' ? ': ' : '') . $this->message . PHP_EOL . @file_get_contents(__DIR__ . '/../../../.git/refs/heads/master') . PHP_EOL . 'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):' . PHP_EOL . PHP_EOL . $this->getTLTrace() . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct($message, $file = '')
|
public function __construct($message, $file = '')
|
||||||
{
|
{
|
||||||
parent::__construct($message);
|
parent::__construct($message);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,25 +10,22 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL;
|
namespace danog\MadelineProto\TL;
|
||||||
|
|
||||||
trait PrettyException
|
trait PrettyException
|
||||||
{
|
{
|
||||||
public $tl_trace;
|
public $tl_trace;
|
||||||
|
|
||||||
public function getTLTrace()
|
public function getTLTrace()
|
||||||
{
|
{
|
||||||
return $this->tl_trace;
|
return $this->tl_trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function prettify_tl($init = '')
|
public function prettify_tl($init = '')
|
||||||
{
|
{
|
||||||
$tl = false;
|
$tl = false;
|
||||||
foreach (array_reverse($this->getTrace()) as $k => $frame) {
|
foreach (array_reverse($this->getTrace()) as $k => $frame) {
|
||||||
if (isset($frame['function']) && in_array($frame['function'], ['serialize_params', 'serialize_object'])) {
|
if (isset($frame['function']) && in_array($frame['function'], ['serialize_params', 'serialize_object'])) {
|
||||||
if ($frame['args'][2] !== '') {
|
if ($frame['args'][2] !== '') {
|
||||||
$this->tl_trace .= $tl ? "['".$frame['args'][2]."']" : "While serializing: \t".$frame['args'][2].PHP_EOL;
|
$this->tl_trace .= $tl ? "['" . $frame['args'][2] . "']" : "While serializing: \t" . $frame['args'][2] . PHP_EOL;
|
||||||
$tl = true;
|
$tl = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -37,15 +35,15 @@ trait PrettyException
|
|||||||
if (isset($frame['function']) && ($frame['function'] === 'handle_rpc_error' && $k === count($this->getTrace()) - 1) || $frame['function'] === 'unserialize') {
|
if (isset($frame['function']) && ($frame['function'] === 'handle_rpc_error' && $k === count($this->getTrace()) - 1) || $frame['function'] === 'unserialize') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$this->tl_trace .= isset($frame['file']) ? str_pad(basename($frame['file']).'('.$frame['line'].'):', 20)."\t" : '';
|
$this->tl_trace .= isset($frame['file']) ? str_pad(basename($frame['file']) . '(' . $frame['line'] . '):', 20) . "\t" : '';
|
||||||
$this->tl_trace .= isset($frame['function']) ? $frame['function'].'(' : '';
|
$this->tl_trace .= isset($frame['function']) ? $frame['function'] . '(' : '';
|
||||||
$this->tl_trace .= isset($frame['args']) ? substr(json_encode($frame['args']), 1, -1) : '';
|
$this->tl_trace .= isset($frame['args']) ? substr(json_encode($frame['args']), 1, -1) : '';
|
||||||
$this->tl_trace .= ')';
|
$this->tl_trace .= ')';
|
||||||
$this->tl_trace .= PHP_EOL;
|
$this->tl_trace .= PHP_EOL;
|
||||||
$tl = false;
|
$tl = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->tl_trace .= $init !== '' ? "['".$init."']" : '';
|
$this->tl_trace .= $init !== '' ? "['" . $init . "']" : '';
|
||||||
$this->tl_trace = implode(PHP_EOL, array_reverse(explode(PHP_EOL, $this->tl_trace)));
|
$this->tl_trace = implode(PHP_EOL, array_reverse(explode(PHP_EOL, $this->tl_trace)));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL;
|
namespace danog\MadelineProto\TL;
|
||||||
|
|
||||||
trait TL
|
trait TL
|
||||||
@ -20,7 +20,6 @@ trait TL
|
|||||||
public $td_constructors;
|
public $td_constructors;
|
||||||
public $td_methods;
|
public $td_methods;
|
||||||
public $td_descriptions;
|
public $td_descriptions;
|
||||||
|
|
||||||
public function construct_tl($files)
|
public function construct_tl($files)
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['TL_loading']], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['TL_loading']], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
@ -72,7 +71,7 @@ trait TL
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$line = preg_replace(['|//.*|', '|^\s+$|'], '', $line);
|
$line = preg_replace(['|//.*|', '|^\\s+$|'], '', $line);
|
||||||
if ($line === '') {
|
if ($line === '') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -84,49 +83,24 @@ trait TL
|
|||||||
$type = 'constructors';
|
$type = 'constructors';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (preg_match('|^===\d*===|', $line)) {
|
if (preg_match('|^===\\d*===|', $line)) {
|
||||||
$layer = (int) preg_replace('|\D*|', '', $line);
|
$layer = (int) preg_replace('|\\D*|', '', $line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (preg_match('/^vector#/', $line)) {
|
if (preg_match('/^vector#/', $line)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (preg_match('/ \?= /', $line)) {
|
if (preg_match('/ \\?= /', $line)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$name = preg_replace(['/#.*/', '/\s.*/'], '', $line);
|
$name = preg_replace(['/#.*/', '/\\s.*/'], '', $line);
|
||||||
if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
|
if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$clean = preg_replace([
|
$clean = preg_replace(['/:bytes /', '/;/', '/#[a-f0-9]+ /', '/ [a-zA-Z0-9_]+\\:flags\\.[0-9]+\\?true/', '/[<]/', '/[>]/', '/ /', '/^ /', '/ $/', '/\\?bytes /', '/{/', '/}/'], [':string ', '', ' ', '', ' ', ' ', ' ', '', '', '?string ', '', ''], $line);
|
||||||
'/:bytes /',
|
|
||||||
'/;/',
|
|
||||||
'/#[a-f0-9]+ /',
|
|
||||||
'/ [a-zA-Z0-9_]+\:flags\.[0-9]+\?true/',
|
|
||||||
'/[<]/',
|
|
||||||
'/[>]/',
|
|
||||||
'/ /',
|
|
||||||
'/^ /',
|
|
||||||
'/ $/',
|
|
||||||
'/\?bytes /',
|
|
||||||
'/{/',
|
|
||||||
'/}/',
|
|
||||||
], [
|
|
||||||
':string ',
|
|
||||||
'',
|
|
||||||
' ',
|
|
||||||
'',
|
|
||||||
' ',
|
|
||||||
' ',
|
|
||||||
' ',
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
'?string ',
|
|
||||||
'',
|
|
||||||
'', ], $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 && $scheme_type !== 'botAPI') {
|
if ($id !== $nid && $scheme_type !== 'botAPI') {
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['crc32_mismatch'], $id, $nid, $line)], \danog\MadelineProto\Logger::ERROR);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['crc32_mismatch'], $id, $nid, $line)], \danog\MadelineProto\Logger::ERROR);
|
||||||
}
|
}
|
||||||
@ -140,11 +114,11 @@ trait TL
|
|||||||
$TL_dict[$type][$key][$type === 'constructors' ? 'predicate' : 'method'] = $name;
|
$TL_dict[$type][$key][$type === 'constructors' ? 'predicate' : 'method'] = $name;
|
||||||
$TL_dict[$type][$key]['id'] = strrev(hex2bin($id));
|
$TL_dict[$type][$key]['id'] = strrev(hex2bin($id));
|
||||||
$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) {
|
if ($layer !== null) {
|
||||||
$TL_dict[$type][$key]['layer'] = $layer;
|
$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;
|
||||||
}
|
}
|
||||||
@ -165,7 +139,7 @@ trait TL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (empty($TL_dict) || empty($TL_dict['constructors']) || !isset($TL_dict['methods'])) {
|
if (empty($TL_dict) || empty($TL_dict['constructors']) || !isset($TL_dict['methods'])) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['src_file_invalid'].$file);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['src_file_invalid'] . $file);
|
||||||
}
|
}
|
||||||
$orig = $this->encrypted_layer;
|
$orig = $this->encrypted_layer;
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['translating_obj']], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['translating_obj']], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||||
@ -173,12 +147,11 @@ trait TL
|
|||||||
if ($scheme_type === 'secret') {
|
if ($scheme_type === 'secret') {
|
||||||
$this->encrypted_layer = max($this->encrypted_layer, $elem['layer']);
|
$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([\danog\MadelineProto\Lang::$current_lang['translating_methods']], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['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') {
|
if ($scheme_type === 'secret') {
|
||||||
$this->encrypted_layer = max($this->encrypted_layer, $elem['layer']);
|
$this->encrypted_layer = max($this->encrypted_layer, $elem['layer']);
|
||||||
}
|
}
|
||||||
@ -210,7 +183,6 @@ trait TL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_method_namespaces()
|
public function get_method_namespaces()
|
||||||
{
|
{
|
||||||
$res = [];
|
$res = [];
|
||||||
@ -218,25 +190,20 @@ trait TL
|
|||||||
$a = key($pair);
|
$a = key($pair);
|
||||||
$res[$a] = $a;
|
$res[$a] = $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_methods_namespaced()
|
public function get_methods_namespaced()
|
||||||
{
|
{
|
||||||
return $this->methods->method_namespace;
|
return $this->methods->method_namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deserialize_bool($id)
|
public function deserialize_bool($id)
|
||||||
{
|
{
|
||||||
$tl_elem = $this->constructors->find_by_id($id);
|
$tl_elem = $this->constructors->find_by_id($id);
|
||||||
if ($tl_elem === false) {
|
if ($tl_elem === false) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['bool_error']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['bool_error']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tl_elem['predicate'] === 'boolTrue';
|
return $tl_elem['predicate'] === 'boolTrue';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serialize_object($type, $object, $ctx, $layer = -1)
|
public function serialize_object($type, $object, $ctx, $layer = -1)
|
||||||
{
|
{
|
||||||
switch ($type['type']) {
|
switch ($type['type']) {
|
||||||
@ -244,19 +211,16 @@ trait TL
|
|||||||
if (!is_numeric($object)) {
|
if (!is_numeric($object)) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->pack_signed_int($object);
|
return $this->pack_signed_int($object);
|
||||||
case '#':
|
case '#':
|
||||||
if (!is_numeric($object)) {
|
if (!is_numeric($object)) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->pack_unsigned_int($object);
|
return $this->pack_unsigned_int($object);
|
||||||
case 'long':
|
case 'long':
|
||||||
if (is_object($object)) {
|
if (is_object($object)) {
|
||||||
return str_pad(strrev($object->toBytes()), 8, chr(0));
|
return str_pad(strrev($object->toBytes()), 8, chr(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($object) && strlen($object) === 8) {
|
if (is_string($object) && strlen($object) === 8) {
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
@ -266,25 +230,21 @@ trait TL
|
|||||||
if (!is_numeric($object)) {
|
if (!is_numeric($object)) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->pack_signed_long($object);
|
return $this->pack_signed_long($object);
|
||||||
case 'int128':
|
case 'int128':
|
||||||
if (strlen($object) !== 16) {
|
if (strlen($object) !== 16) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_16']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_16']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (string) $object;
|
return (string) $object;
|
||||||
case 'int256':
|
case 'int256':
|
||||||
if (strlen($object) !== 32) {
|
if (strlen($object) !== 32) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_32']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_32']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (string) $object;
|
return (string) $object;
|
||||||
case 'int512':
|
case 'int512':
|
||||||
if (strlen($object) !== 64) {
|
if (strlen($object) !== 64) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_64']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_64']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (string) $object;
|
return (string) $object;
|
||||||
case 'double':
|
case 'double':
|
||||||
return $this->pack_double($object);
|
return $this->pack_double($object);
|
||||||
@ -292,24 +252,22 @@ trait TL
|
|||||||
if (!is_string($object)) {
|
if (!is_string($object)) {
|
||||||
throw new Exception("You didn't provide a valid string");
|
throw new Exception("You didn't provide a valid string");
|
||||||
}
|
}
|
||||||
|
|
||||||
$object = pack('C*', ...unpack('C*', $object));
|
$object = pack('C*', ...unpack('C*', $object));
|
||||||
$l = strlen($object);
|
$l = strlen($object);
|
||||||
$concat = '';
|
$concat = '';
|
||||||
if ($l <= 253) {
|
if ($l <= 253) {
|
||||||
$concat .= chr($l);
|
$concat .= chr($l);
|
||||||
$concat .= $object;
|
$concat .= $object;
|
||||||
$concat .= pack('@'.$this->posmod((-$l - 1), 4));
|
$concat .= pack('@' . $this->posmod(-$l - 1, 4));
|
||||||
} else {
|
} else {
|
||||||
$concat .= chr(254);
|
$concat .= chr(254);
|
||||||
$concat .= substr($this->pack_signed_int($l), 0, 3);
|
$concat .= substr($this->pack_signed_int($l), 0, 3);
|
||||||
$concat .= $object;
|
$concat .= $object;
|
||||||
$concat .= pack('@'.$this->posmod(-$l, 4));
|
$concat .= pack('@' . $this->posmod(-$l, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $concat;
|
return $concat;
|
||||||
case 'bytes':
|
case 'bytes':
|
||||||
if (!is_string($object) && !($object instanceof \danog\MadelineProto\TL\Types\Bytes)) {
|
if (!is_string($object) && !$object instanceof \danog\MadelineProto\TL\Types\Bytes) {
|
||||||
throw new Exception("You didn't provide a valid string");
|
throw new Exception("You didn't provide a valid string");
|
||||||
}
|
}
|
||||||
$l = strlen($object);
|
$l = strlen($object);
|
||||||
@ -317,17 +275,16 @@ trait TL
|
|||||||
if ($l <= 253) {
|
if ($l <= 253) {
|
||||||
$concat .= chr($l);
|
$concat .= chr($l);
|
||||||
$concat .= $object;
|
$concat .= $object;
|
||||||
$concat .= pack('@'.$this->posmod((-$l - 1), 4));
|
$concat .= pack('@' . $this->posmod(-$l - 1, 4));
|
||||||
} else {
|
} else {
|
||||||
$concat .= chr(254);
|
$concat .= chr(254);
|
||||||
$concat .= substr($this->pack_signed_int($l), 0, 3);
|
$concat .= substr($this->pack_signed_int($l), 0, 3);
|
||||||
$concat .= $object;
|
$concat .= $object;
|
||||||
$concat .= pack('@'.$this->posmod(-$l, 4));
|
$concat .= pack('@' . $this->posmod(-$l, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $concat;
|
return $concat;
|
||||||
case 'Bool':
|
case 'Bool':
|
||||||
return $this->constructors->find_by_predicate(((bool) $object) ? 'boolTrue' : 'boolFalse')['id'];
|
return $this->constructors->find_by_predicate((bool) $object ? 'boolTrue' : 'boolFalse')['id'];
|
||||||
case 'true':
|
case 'true':
|
||||||
return;
|
return;
|
||||||
case '!X':
|
case '!X':
|
||||||
@ -341,7 +298,6 @@ trait TL
|
|||||||
foreach ($object as $k => $current_object) {
|
foreach ($object as $k => $current_object) {
|
||||||
$concat .= $this->serialize_object(['type' => $type['subtype']], $current_object, $k);
|
$concat .= $this->serialize_object(['type' => $type['subtype']], $current_object, $k);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $concat;
|
return $concat;
|
||||||
case 'vector':
|
case 'vector':
|
||||||
if (!is_array($object)) {
|
if (!is_array($object)) {
|
||||||
@ -351,16 +307,14 @@ trait TL
|
|||||||
foreach ($object as $k => $current_object) {
|
foreach ($object as $k => $current_object) {
|
||||||
$concat .= $this->serialize_object(['type' => $type['subtype']], $current_object, $k);
|
$concat .= $this->serialize_object(['type' => $type['subtype']], $current_object, $k);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $concat;
|
return $concat;
|
||||||
|
|
||||||
case 'Object':
|
case 'Object':
|
||||||
if (is_string($object)) {
|
if (is_string($object)) {
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$auto = false;
|
$auto = false;
|
||||||
if ((!is_array($object) || (isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type'])) && in_array($type['type'], ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) {
|
if ((!is_array($object) || isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type']) && in_array($type['type'], ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) {
|
||||||
$object = $this->get_info($object);
|
$object = $this->get_info($object);
|
||||||
if (!isset($object[$type['type']])) {
|
if (!isset($object[$type['type']])) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
|
||||||
@ -369,7 +323,6 @@ trait TL
|
|||||||
}
|
}
|
||||||
if (!isset($object['_'])) {
|
if (!isset($object['_'])) {
|
||||||
$constructorData = $this->constructors->find_by_predicate($type['type'], $layer);
|
$constructorData = $this->constructors->find_by_predicate($type['type'], $layer);
|
||||||
|
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['predicate_not_set']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['predicate_not_set']);
|
||||||
}
|
}
|
||||||
@ -377,22 +330,17 @@ trait TL
|
|||||||
$object['_'] = $constructorData['predicate'];
|
$object['_'] = $constructorData['predicate'];
|
||||||
}
|
}
|
||||||
$predicate = $object['_'];
|
$predicate = $object['_'];
|
||||||
|
|
||||||
$constructorData = $this->constructors->find_by_predicate($predicate, $layer);
|
$constructorData = $this->constructors->find_by_predicate($predicate, $layer);
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
\danog\MadelineProto\Logger::log([$object], \danog\MadelineProto\Logger::FATAL_ERROR);
|
\danog\MadelineProto\Logger::log([$object], \danog\MadelineProto\Logger::FATAL_ERROR);
|
||||||
|
|
||||||
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error'], $predicate));
|
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error'], $predicate));
|
||||||
}
|
}
|
||||||
|
if ($bare = $type['type'] != '' && $type['type'][0] === '%') {
|
||||||
if ($bare = ($type['type'] != '' && $type['type'][0] === '%')) {
|
|
||||||
$type['type'] = substr($type['type'], 1);
|
$type['type'] = substr($type['type'], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($predicate === $type['type'] && !$auto) {
|
if ($predicate === $type['type'] && !$auto) {
|
||||||
$bare = true;
|
$bare = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($predicate === 'messageEntityMentionName') {
|
if ($predicate === 'messageEntityMentionName') {
|
||||||
$constructorData = $this->constructors->find_by_predicate('inputMessageEntityMentionName');
|
$constructorData = $this->constructors->find_by_predicate('inputMessageEntityMentionName');
|
||||||
}
|
}
|
||||||
@ -400,24 +348,19 @@ trait TL
|
|||||||
if (!$bare) {
|
if (!$bare) {
|
||||||
$concat = $constructorData['id'];
|
$concat = $constructorData['id'];
|
||||||
}
|
}
|
||||||
|
return $concat . $this->serialize_params($constructorData, $object, '', $layer);
|
||||||
return $concat.$this->serialize_params($constructorData, $object, '', $layer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serialize_method($method, $arguments)
|
public function serialize_method($method, $arguments)
|
||||||
{
|
{
|
||||||
$tl = $this->methods->find_by_method($method);
|
$tl = $this->methods->find_by_method($method);
|
||||||
if ($tl === false) {
|
if ($tl === false) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['method_not_found'].$method);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['method_not_found'] . $method);
|
||||||
}
|
}
|
||||||
|
return $tl['id'] . $this->serialize_params($tl, $arguments, $method);
|
||||||
return $tl['id'].$this->serialize_params($tl, $arguments, $method);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serialize_params($tl, $arguments, $ctx, $layer = -1)
|
public function serialize_params($tl, $arguments, $ctx, $layer = -1)
|
||||||
{
|
{
|
||||||
$serialized = '';
|
$serialized = '';
|
||||||
|
|
||||||
$arguments = $this->botAPI_to_MTProto($arguments);
|
$arguments = $this->botAPI_to_MTProto($arguments);
|
||||||
$flags = 0;
|
$flags = 0;
|
||||||
foreach ($tl['params'] as $cur_flag) {
|
foreach ($tl['params'] as $cur_flag) {
|
||||||
@ -425,17 +368,17 @@ trait TL
|
|||||||
switch ($cur_flag['type']) {
|
switch ($cur_flag['type']) {
|
||||||
case 'true':
|
case 'true':
|
||||||
case 'false':
|
case 'false':
|
||||||
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) ? ($flags | $cur_flag['pow']) : ($flags & ~$cur_flag['pow']);
|
$flags = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] ? $flags | $cur_flag['pow'] : $flags & ~$cur_flag['pow'];
|
||||||
unset($arguments[$cur_flag['name']]);
|
unset($arguments[$cur_flag['name']]);
|
||||||
break;
|
break;
|
||||||
case 'Bool':
|
case 'Bool':
|
||||||
$arguments[$cur_flag['name']] = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) && (($flags & $cur_flag['pow']) != 0);
|
$arguments[$cur_flag['name']] = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] && ($flags & $cur_flag['pow']) != 0;
|
||||||
if (($flags & $cur_flag['pow']) === 0) {
|
if (($flags & $cur_flag['pow']) === 0) {
|
||||||
unset($arguments[$cur_flag['name']]);
|
unset($arguments[$cur_flag['name']]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null) ? ($flags | $cur_flag['pow']) : ($flags & ~$cur_flag['pow']);
|
$flags = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null ? $flags | $cur_flag['pow'] : $flags & ~$cur_flag['pow'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,7 +391,7 @@ trait TL
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($current_argument['name'] === 'random_bytes') {
|
if ($current_argument['name'] === 'random_bytes') {
|
||||||
$serialized .= $this->serialize_object(['type' => 'bytes'], $this->random(15 + (4 * (random_int(0, PHP_INT_MAX) % 3))), 'random_bytes');
|
$serialized .= $this->serialize_object(['type' => 'bytes'], $this->random(15 + 4 * (random_int(0, PHP_INT_MAX) % 3)), 'random_bytes');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($current_argument['name'] === 'data' && isset($arguments['message'])) {
|
if ($current_argument['name'] === 'data' && isset($arguments['message'])) {
|
||||||
@ -472,11 +415,10 @@ trait TL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($id = $this->constructors->find_by_predicate(lcfirst($current_argument['type']).'Empty')) {
|
if ($id = $this->constructors->find_by_predicate(lcfirst($current_argument['type']) . 'Empty')) {
|
||||||
$serialized .= $id['id'];
|
$serialized .= $id['id'];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['params_missing'], $current_argument['name']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['params_missing'], $current_argument['name']);
|
||||||
}
|
}
|
||||||
if (!is_array($arguments[$current_argument['name']]) && $current_argument['type'] === 'InputEncryptedChat') {
|
if (!is_array($arguments[$current_argument['name']]) && $current_argument['type'] === 'InputEncryptedChat') {
|
||||||
@ -488,14 +430,11 @@ trait TL
|
|||||||
if ($current_argument['type'] === 'DataJSON') {
|
if ($current_argument['type'] === 'DataJSON') {
|
||||||
$arguments[$current_argument['name']] = ['_' => 'dataJSON', 'data' => json_encode($arguments[$current_argument['name']])];
|
$arguments[$current_argument['name']] = ['_' => 'dataJSON', 'data' => json_encode($arguments[$current_argument['name']])];
|
||||||
}
|
}
|
||||||
|
|
||||||
//\danog\MadelineProto\Logger::log(['Serializing '.$current_argument['name'].' of type '.$current_argument['type']);
|
//\danog\MadelineProto\Logger::log(['Serializing '.$current_argument['name'].' of type '.$current_argument['type']);
|
||||||
$serialized .= $this->serialize_object($current_argument, $arguments[$current_argument['name']], $current_argument['name'], $layer);
|
$serialized .= $this->serialize_object($current_argument, $arguments[$current_argument['name']], $current_argument['name'], $layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $serialized;
|
return $serialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_length($stream, $type = ['type' => ''])
|
public function get_length($stream, $type = ['type' => ''])
|
||||||
{
|
{
|
||||||
if (is_string($stream)) {
|
if (is_string($stream)) {
|
||||||
@ -507,10 +446,8 @@ trait TL
|
|||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
|
||||||
}
|
}
|
||||||
$this->deserialize($stream, $type);
|
$this->deserialize($stream, $type);
|
||||||
|
|
||||||
return ftell($stream);
|
return ftell($stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* :type stream: io.BytesIO object.
|
* :type stream: io.BytesIO object.
|
||||||
*/
|
*/
|
||||||
@ -524,7 +461,6 @@ trait TL
|
|||||||
} elseif (!is_resource($stream)) {
|
} elseif (!is_resource($stream)) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($type['type']) {
|
switch ($type['type']) {
|
||||||
case 'Bool':
|
case 'Bool':
|
||||||
return $this->deserialize_bool(stream_get_contents($stream, 4));
|
return $this->deserialize_bool(stream_get_contents($stream, 4));
|
||||||
@ -536,7 +472,6 @@ trait TL
|
|||||||
if (isset($type['idstrlong'])) {
|
if (isset($type['idstrlong'])) {
|
||||||
return stream_get_contents($stream, 8);
|
return stream_get_contents($stream, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
return \danog\MadelineProto\Logger::$bigint || isset($type['strlong']) ? stream_get_contents($stream, 8) : $this->unpack_signed_long(stream_get_contents($stream, 8));
|
return \danog\MadelineProto\Logger::$bigint || isset($type['strlong']) ? stream_get_contents($stream, 8) : $this->unpack_signed_long(stream_get_contents($stream, 8));
|
||||||
case 'double':
|
case 'double':
|
||||||
return $this->unpack_double(stream_get_contents($stream, 8));
|
return $this->unpack_double(stream_get_contents($stream, 8));
|
||||||
@ -553,7 +488,7 @@ trait TL
|
|||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['length_too_big']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['length_too_big']);
|
||||||
}
|
}
|
||||||
if ($l === 254) {
|
if ($l === 254) {
|
||||||
$long_len = unpack('V', stream_get_contents($stream, 3).chr(0))[1];
|
$long_len = unpack('V', stream_get_contents($stream, 3) . chr(0))[1];
|
||||||
$x = stream_get_contents($stream, $long_len);
|
$x = stream_get_contents($stream, $long_len);
|
||||||
$resto = $this->posmod(-$long_len, 4);
|
$resto = $this->posmod(-$long_len, 4);
|
||||||
if ($resto > 0) {
|
if ($resto > 0) {
|
||||||
@ -569,17 +504,14 @@ trait TL
|
|||||||
if (!is_string($x)) {
|
if (!is_string($x)) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['deserialize_not_str']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['deserialize_not_str']);
|
||||||
}
|
}
|
||||||
|
return $type['type'] === 'bytes' ? new Types\Bytes($x) : $x;
|
||||||
return $type['type'] === 'bytes' ? (new Types\Bytes($x)) : $x;
|
|
||||||
case 'Vector t':
|
case 'Vector t':
|
||||||
$id = stream_get_contents($stream, 4);
|
$id = stream_get_contents($stream, 4);
|
||||||
$constructorData = $this->constructors->find_by_id($id);
|
$constructorData = $this->constructors->find_by_id($id);
|
||||||
|
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
$constructorData = $this->methods->find_by_id($id);
|
$constructorData = $this->methods->find_by_id($id);
|
||||||
$constructorData['predicate'] = 'method_'.$constructorData['method'];
|
$constructorData['predicate'] = 'method_' . $constructorData['method'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error_id'], $type['type'], bin2hex(strrev($id))));
|
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error_id'], $type['type'], bin2hex(strrev($id))));
|
||||||
}
|
}
|
||||||
@ -590,7 +522,7 @@ trait TL
|
|||||||
case 'vector':
|
case 'vector':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['vector_invalid'].$constructorData['predicate']);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['vector_invalid'] . $constructorData['predicate']);
|
||||||
}
|
}
|
||||||
case 'vector':
|
case 'vector':
|
||||||
$count = unpack('V', stream_get_contents($stream, 4))[1];
|
$count = unpack('V', stream_get_contents($stream, 4))[1];
|
||||||
@ -599,14 +531,13 @@ trait TL
|
|||||||
for ($i = 0; $i < $count; $i++) {
|
for ($i = 0; $i < $count; $i++) {
|
||||||
$result[] = $this->deserialize($stream, $type);
|
$result[] = $this->deserialize($stream, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
if ($type['type'] != '' && $type['type'][0] === '%') {
|
if ($type['type'] != '' && $type['type'][0] === '%') {
|
||||||
$checkType = substr($type['type'], 1);
|
$checkType = substr($type['type'], 1);
|
||||||
$constructorData = $this->constructors->find_by_type($checkType);
|
$constructorData = $this->constructors->find_by_type($checkType);
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['constructor_not_found'].$checkType);
|
throw new Exception(\danog\MadelineProto\Lang::$current_lang['constructor_not_found'] . $checkType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$constructorData = $this->constructors->find_by_predicate($type['type']);
|
$constructorData = $this->constructors->find_by_predicate($type['type']);
|
||||||
@ -618,7 +549,7 @@ trait TL
|
|||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error_id'], $type['type'], bin2hex(strrev($id))));
|
throw new Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error_id'], $type['type'], bin2hex(strrev($id))));
|
||||||
}
|
}
|
||||||
$constructorData['predicate'] = 'method_'.$constructorData['method'];
|
$constructorData['predicate'] = 'method_' . $constructorData['method'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -626,14 +557,12 @@ trait TL
|
|||||||
if (!isset($type['subtype'])) {
|
if (!isset($type['subtype'])) {
|
||||||
$type['subtype'] = '';
|
$type['subtype'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->deserialize(gzdecode($this->deserialize($stream, ['type' => 'bytes'])), ['type' => '', 'datacenter' => $type['datacenter'], 'subtype' => $type['subtype']]);
|
return $this->deserialize(gzdecode($this->deserialize($stream, ['type' => 'bytes'])), ['type' => '', 'datacenter' => $type['datacenter'], 'subtype' => $type['subtype']]);
|
||||||
}
|
}
|
||||||
if ($constructorData['type'] === 'Vector t') {
|
if ($constructorData['type'] === 'Vector t') {
|
||||||
$constructorData['datacenter'] = $type['datacenter'];
|
$constructorData['datacenter'] = $type['datacenter'];
|
||||||
$constructorData['subtype'] = isset($type['subtype']) ? $type['subtype'] : '';
|
$constructorData['subtype'] = isset($type['subtype']) ? $type['subtype'] : '';
|
||||||
$constructorData['type'] = 'vector';
|
$constructorData['type'] = 'vector';
|
||||||
|
|
||||||
return $this->deserialize($stream, $constructorData);
|
return $this->deserialize($stream, $constructorData);
|
||||||
}
|
}
|
||||||
if ($constructorData['predicate'] === 'boolTrue') {
|
if ($constructorData['predicate'] === 'boolTrue') {
|
||||||
@ -670,7 +599,6 @@ trait TL
|
|||||||
if (in_array($arg['name'], ['peer_tag', 'file_token', 'cdn_key', 'cdn_iv'])) {
|
if (in_array($arg['name'], ['peer_tag', 'file_token', 'cdn_key', 'cdn_iv'])) {
|
||||||
$arg['type'] = 'string';
|
$arg['type'] = 'string';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($x['_'] === 'rpc_result' && $arg['name'] === 'result' && isset($this->datacenter->sockets[$type['datacenter']]->new_outgoing[$x['req_msg_id']]['type']) && stripos($this->datacenter->sockets[$type['datacenter']]->new_outgoing[$x['req_msg_id']]['type'], '<') !== false) {
|
if ($x['_'] === 'rpc_result' && $arg['name'] === 'result' && isset($this->datacenter->sockets[$type['datacenter']]->new_outgoing[$x['req_msg_id']]['type']) && stripos($this->datacenter->sockets[$type['datacenter']]->new_outgoing[$x['req_msg_id']]['type'], '<') !== false) {
|
||||||
$arg['subtype'] = preg_replace(['|Vector[<]|', '|[>]|'], '', $this->datacenter->sockets[$type['datacenter']]->new_outgoing[$x['req_msg_id']]['type']);
|
$arg['subtype'] = preg_replace(['|Vector[<]|', '|[>]|'], '', $this->datacenter->sockets[$type['datacenter']]->new_outgoing[$x['req_msg_id']]['type']);
|
||||||
}
|
}
|
||||||
@ -686,13 +614,13 @@ trait TL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($x['flags'])) { // I don't think we need this anymore
|
if (isset($x['flags'])) {
|
||||||
|
// I don't think we need this anymore
|
||||||
unset($x['flags']);
|
unset($x['flags']);
|
||||||
}
|
}
|
||||||
if ($x['_'] === 'dataJSON') {
|
if ($x['_'] === 'dataJSON') {
|
||||||
return json_decode($x['data'], true);
|
return json_decode($x['data'], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($x['_'] === 'message' && isset($x['reply_markup']['rows'])) {
|
if ($x['_'] === 'message' && isset($x['reply_markup']['rows'])) {
|
||||||
foreach ($x['reply_markup']['rows'] as $key => $row) {
|
foreach ($x['reply_markup']['rows'] as $key => $row) {
|
||||||
foreach ($row['buttons'] as $bkey => $button) {
|
foreach ($row['buttons'] as $bkey => $button) {
|
||||||
@ -700,7 +628,6 @@ trait TL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $x;
|
return $x;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL;
|
namespace danog\MadelineProto\TL;
|
||||||
|
|
||||||
class TLConstructor
|
class TLConstructor
|
||||||
@ -17,7 +17,6 @@ class TLConstructor
|
|||||||
use \danog\Serializable;
|
use \danog\Serializable;
|
||||||
use \danog\MadelineProto\Tools;
|
use \danog\MadelineProto\Tools;
|
||||||
use TLParams;
|
use TLParams;
|
||||||
|
|
||||||
public $by_id = [];
|
public $by_id = [];
|
||||||
public $by_predicate_and_layer = [];
|
public $by_predicate_and_layer = [];
|
||||||
public $layers = [];
|
public $layers = [];
|
||||||
@ -25,16 +24,14 @@ class TLConstructor
|
|||||||
//public $params = [];
|
//public $params = [];
|
||||||
//public $layer = [];
|
//public $layer = [];
|
||||||
//public $key = 0;
|
//public $key = 0;
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['by_predicate_and_layer', 'by_id', 'layers'];
|
return ['by_predicate_and_layer', 'by_id', 'layers'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add($json_dict, $scheme_type)
|
public function add($json_dict, $scheme_type)
|
||||||
{
|
{
|
||||||
$predicate = (string) ((($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message') ? 'MT' : '').$json_dict['predicate']);
|
$predicate = (string) (($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message' ? 'MT' : '') . $json_dict['predicate']);
|
||||||
$this->by_id[$json_dict['id']] = ['predicate' => $predicate, 'params' => $json_dict['params'], 'type' => (($scheme_type === 'mtproto' && $json_dict['type'] === 'Message') ? 'MT' : '').$json_dict['type']];
|
$this->by_id[$json_dict['id']] = ['predicate' => $predicate, 'params' => $json_dict['params'], 'type' => ($scheme_type === 'mtproto' && $json_dict['type'] === 'Message' ? 'MT' : '') . $json_dict['type']];
|
||||||
if ($scheme_type === 'secret') {
|
if ($scheme_type === 'secret') {
|
||||||
$this->by_id[$json_dict['id']]['layer'] = $json_dict['layer'];
|
$this->by_id[$json_dict['id']]['layer'] = $json_dict['layer'];
|
||||||
$this->layers[$json_dict['layer']] = $json_dict['layer'];
|
$this->layers[$json_dict['layer']] = $json_dict['layer'];
|
||||||
@ -42,34 +39,30 @@ class TLConstructor
|
|||||||
} else {
|
} else {
|
||||||
$json_dict['layer'] = '';
|
$json_dict['layer'] = '';
|
||||||
}
|
}
|
||||||
$this->by_predicate_and_layer[$predicate.$json_dict['layer']] = $json_dict['id'];
|
$this->by_predicate_and_layer[$predicate . $json_dict['layer']] = $json_dict['id'];
|
||||||
$this->parse_params($json_dict['id'], $scheme_type === 'mtproto');
|
$this->parse_params($json_dict['id'], $scheme_type === 'mtproto');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find_by_type($type)
|
public function find_by_type($type)
|
||||||
{
|
{
|
||||||
foreach ($this->by_id as $id => $constructor) {
|
foreach ($this->by_id as $id => $constructor) {
|
||||||
if ($constructor['type'] === $type) {
|
if ($constructor['type'] === $type) {
|
||||||
$constructor['id'] = $id;
|
$constructor['id'] = $id;
|
||||||
$constructor['params'] = $constructor['params'];
|
$constructor['params'] = $constructor['params'];
|
||||||
|
|
||||||
return $constructor;
|
return $constructor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find_by_predicate($predicate, $layer = -1)
|
public function find_by_predicate($predicate, $layer = -1)
|
||||||
{
|
{
|
||||||
if ($layer !== -1) {
|
if ($layer !== -1) {
|
||||||
foreach ($this->layers as $alayer) {
|
foreach ($this->layers as $alayer) {
|
||||||
if ($alayer <= $layer) {
|
if ($alayer <= $layer) {
|
||||||
if (isset($this->by_predicate_and_layer[$predicate.$alayer])) {
|
if (isset($this->by_predicate_and_layer[$predicate . $alayer])) {
|
||||||
$chosenid = $this->by_predicate_and_layer[$predicate.$alayer];
|
$chosenid = $this->by_predicate_and_layer[$predicate . $alayer];
|
||||||
}
|
}
|
||||||
} elseif (!isset($chosenid)) {
|
} elseif (!isset($chosenid)) {
|
||||||
$chosenid = $this->by_predicate_and_layer[$predicate.$alayer];
|
$chosenid = $this->by_predicate_and_layer[$predicate . $alayer];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isset($chosenid)) {
|
if (!isset($chosenid)) {
|
||||||
@ -78,30 +71,24 @@ class TLConstructor
|
|||||||
$constructor = $this->by_id[$chosenid];
|
$constructor = $this->by_id[$chosenid];
|
||||||
$constructor['id'] = $chosenid;
|
$constructor['id'] = $chosenid;
|
||||||
$constructor['params'] = $constructor['params'];
|
$constructor['params'] = $constructor['params'];
|
||||||
|
|
||||||
return $constructor;
|
return $constructor;
|
||||||
}
|
}
|
||||||
if (isset($this->by_predicate_and_layer[$predicate])) {
|
if (isset($this->by_predicate_and_layer[$predicate])) {
|
||||||
$constructor = $this->by_id[$this->by_predicate_and_layer[$predicate]];
|
$constructor = $this->by_id[$this->by_predicate_and_layer[$predicate]];
|
||||||
$constructor['id'] = $this->by_predicate_and_layer[$predicate];
|
$constructor['id'] = $this->by_predicate_and_layer[$predicate];
|
||||||
$constructor['params'] = $constructor['params'];
|
$constructor['params'] = $constructor['params'];
|
||||||
|
|
||||||
return $constructor;
|
return $constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find_by_id($id)
|
public function find_by_id($id)
|
||||||
{
|
{
|
||||||
if (isset($this->by_id[$id])) {
|
if (isset($this->by_id[$id])) {
|
||||||
$constructor = $this->by_id[$id];
|
$constructor = $this->by_id[$id];
|
||||||
$constructor['id'] = $id;
|
$constructor['id'] = $id;
|
||||||
$constructor['params'] = $constructor['params'];
|
$constructor['params'] = $constructor['params'];
|
||||||
|
|
||||||
return $constructor;
|
return $constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL;
|
namespace danog\MadelineProto\TL;
|
||||||
|
|
||||||
class TLMethod
|
class TLMethod
|
||||||
@ -20,48 +20,38 @@ class TLMethod
|
|||||||
public $by_id = [];
|
public $by_id = [];
|
||||||
public $by_method = [];
|
public $by_method = [];
|
||||||
public $method_namespace = [];
|
public $method_namespace = [];
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['by_id', 'by_method', 'method_namespace'];
|
return ['by_id', 'by_method', 'method_namespace'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add($json_dict)
|
public function add($json_dict)
|
||||||
{
|
{
|
||||||
$this->by_id[$json_dict['id']] = ['method' => $json_dict['method'], 'type' => $json_dict['type'], 'params' => $json_dict['params']];
|
$this->by_id[$json_dict['id']] = ['method' => $json_dict['method'], 'type' => $json_dict['type'], 'params' => $json_dict['params']];
|
||||||
$this->by_method[$json_dict['method']] = $json_dict['id'];
|
$this->by_method[$json_dict['method']] = $json_dict['id'];
|
||||||
|
|
||||||
$namespace = explode('.', $json_dict['method']);
|
$namespace = explode('.', $json_dict['method']);
|
||||||
if (isset($namespace[1])) {
|
if (isset($namespace[1])) {
|
||||||
$this->method_namespace[] = [$namespace[0] => $namespace[1]];
|
$this->method_namespace[] = [$namespace[0] => $namespace[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->parse_params($json_dict['id']);
|
$this->parse_params($json_dict['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find_by_id($id)
|
public function find_by_id($id)
|
||||||
{
|
{
|
||||||
if (isset($this->by_id[$id])) {
|
if (isset($this->by_id[$id])) {
|
||||||
$method = $this->by_id[$id];
|
$method = $this->by_id[$id];
|
||||||
$method['id'] = $id;
|
$method['id'] = $id;
|
||||||
$method['params'] = $method['params'];
|
$method['params'] = $method['params'];
|
||||||
|
|
||||||
return $method;
|
return $method;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find_by_method($method_name)
|
public function find_by_method($method_name)
|
||||||
{
|
{
|
||||||
if (isset($this->by_method[$method_name])) {
|
if (isset($this->by_method[$method_name])) {
|
||||||
$method = $this->by_id[$this->by_method[$method_name]];
|
$method = $this->by_id[$this->by_method[$method_name]];
|
||||||
$method['id'] = $this->by_method[$method_name];
|
$method['id'] = $this->by_method[$method_name];
|
||||||
$method['params'] = $method['params'];
|
$method['params'] = $method['params'];
|
||||||
|
|
||||||
return $method;
|
return $method;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL;
|
namespace danog\MadelineProto\TL;
|
||||||
|
|
||||||
trait TLParams
|
trait TLParams
|
||||||
@ -17,7 +17,7 @@ trait TLParams
|
|||||||
public function parse_params($key, $mtproto = false)
|
public function parse_params($key, $mtproto = false)
|
||||||
{
|
{
|
||||||
foreach ($this->by_id[$key]['params'] as $kkey => $param) {
|
foreach ($this->by_id[$key]['params'] as $kkey => $param) {
|
||||||
if (preg_match('/^flags\.\d*\?/', $param['type'])) {
|
if (preg_match('/^flags\\.\\d*\\?/', $param['type'])) {
|
||||||
$flag = explode('?', explode('flags.', $param['type'])[1]);
|
$flag = explode('?', explode('flags.', $param['type'])[1]);
|
||||||
$param['pow'] = pow(2, $flag[0]);
|
$param['pow'] = pow(2, $flag[0]);
|
||||||
$param['type'] = $flag[1];
|
$param['type'] = $flag[1];
|
||||||
@ -31,11 +31,11 @@ trait TLParams
|
|||||||
$param['subtype'] = preg_replace(['/.*</', '/>$/'], '', $param['type']);
|
$param['subtype'] = preg_replace(['/.*</', '/>$/'], '', $param['type']);
|
||||||
$param['type'] = 'Vector t';
|
$param['type'] = 'Vector t';
|
||||||
}
|
}
|
||||||
$param['subtype'] = (($mtproto && $param['subtype'] === 'Message') ? 'MT' : '').$param['subtype'];
|
$param['subtype'] = ($mtproto && $param['subtype'] === 'Message' ? 'MT' : '') . $param['subtype'];
|
||||||
$param['subtype'] = (($mtproto && $param['subtype'] === '%Message') ? '%MTMessage' : $param['subtype']);
|
$param['subtype'] = $mtproto && $param['subtype'] === '%Message' ? '%MTMessage' : $param['subtype'];
|
||||||
}
|
}
|
||||||
$param['type'] = (($mtproto && $param['type'] === 'Message') ? 'MT' : '').$param['type'];
|
$param['type'] = ($mtproto && $param['type'] === 'Message' ? 'MT' : '') . $param['type'];
|
||||||
$param['type'] = (($mtproto && $param['type'] === '%Message') ? '%MTMessage' : $param['type']);
|
$param['type'] = $mtproto && $param['type'] === '%Message' ? '%MTMessage' : $param['type'];
|
||||||
$this->by_id[$key]['params'][$kkey] = $param;
|
$this->by_id[$key]['params'][$kkey] = $param;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL\Types;
|
namespace danog\MadelineProto\TL\Types;
|
||||||
|
|
||||||
class Button extends \Volatile implements \JsonSerializable
|
class Button extends \Volatile implements \JsonSerializable
|
||||||
@ -17,7 +17,6 @@ class Button extends \Volatile implements \JsonSerializable
|
|||||||
use \danog\Serializable;
|
use \danog\Serializable;
|
||||||
private $info = [];
|
private $info = [];
|
||||||
private $data = [];
|
private $data = [];
|
||||||
|
|
||||||
public function __magic_construct($API, $message, $button)
|
public function __magic_construct($API, $message, $button)
|
||||||
{
|
{
|
||||||
$this->data = $button;
|
$this->data = $button;
|
||||||
@ -25,31 +24,29 @@ class Button extends \Volatile implements \JsonSerializable
|
|||||||
$this->info['id'] = $message['id'];
|
$this->info['id'] = $message['id'];
|
||||||
$this->info['API'] = $API;
|
$this->info['API'] = $API;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['data', 'info'];
|
return ['data', 'info'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function click($donotwait = false)
|
public function click($donotwait = false)
|
||||||
{
|
{
|
||||||
switch ($this->data['_']) {
|
switch ($this->data['_']) {
|
||||||
default: return false;
|
default:
|
||||||
case 'keyboardButtonUrl': return $this->data['url'];
|
return false;
|
||||||
case 'keyboardButton': return $this->info['API']->method_call('messages.sendMessage', ['peer' => $this->info['peer'], 'message' => $this->data['text'], 'reply_to_msg_id' => $this->info['id']], ['datacenter' => $this->info['API']->datacenter->curdc]);
|
case 'keyboardButtonUrl':
|
||||||
case 'keyboardButtonCallback': return $this->info['API']->method_call('messages.getBotCallbackAnswer', ['peer' => $this->info['peer'], 'msg_id' => $this->info['id'], 'data' => $this->data['data']], ['noResponse' => $donotwait, 'datacenter' => $this->info['API']->datacenter->curdc]);
|
return $this->data['url'];
|
||||||
case 'keyboardButtonGame': return $this->info['API']->method_call('messages.getBotCallbackAnswer', ['peer' => $this->info['peer'], 'msg_id' => $this->info['id'], 'game' => true], ['noResponse' => $donotwait, 'datacenter' => $this->info['API']->datacenter->curdc]);
|
case 'keyboardButton':
|
||||||
|
return $this->info['API']->method_call('messages.sendMessage', ['peer' => $this->info['peer'], 'message' => $this->data['text'], 'reply_to_msg_id' => $this->info['id']], ['datacenter' => $this->info['API']->datacenter->curdc]);
|
||||||
|
case 'keyboardButtonCallback':
|
||||||
|
return $this->info['API']->method_call('messages.getBotCallbackAnswer', ['peer' => $this->info['peer'], 'msg_id' => $this->info['id'], 'data' => $this->data['data']], ['noResponse' => $donotwait, 'datacenter' => $this->info['API']->datacenter->curdc]);
|
||||||
|
case 'keyboardButtonGame':
|
||||||
|
return $this->info['API']->method_call('messages.getBotCallbackAnswer', ['peer' => $this->info['peer'], 'msg_id' => $this->info['id'], 'game' => true], ['noResponse' => $donotwait, 'datacenter' => $this->info['API']->datacenter->curdc]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __debugInfo()
|
public function __debugInfo()
|
||||||
{
|
{
|
||||||
return [
|
return ['data' => $this->data, 'info' => ['peer' => $this->info['peer'], 'id' => $this->info['id']]];
|
||||||
'data' => $this->data,
|
|
||||||
'info' => ['peer' => $this->info['peer'], 'id' => $this->info['id']],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function jsonSerialize()
|
public function jsonSerialize()
|
||||||
{
|
{
|
||||||
return (array) $this->data;
|
return (array) $this->data;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,29 +10,24 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\TL\Types;
|
namespace danog\MadelineProto\TL\Types;
|
||||||
|
|
||||||
class Bytes extends \Volatile implements \JsonSerializable
|
class Bytes extends \Volatile implements \JsonSerializable
|
||||||
{
|
{
|
||||||
use \danog\Serializable;
|
use \danog\Serializable;
|
||||||
private $bytes = [];
|
private $bytes = [];
|
||||||
|
|
||||||
public function __magic_construct($bytes)
|
public function __magic_construct($bytes)
|
||||||
{
|
{
|
||||||
$this->bytes = $bytes;
|
$this->bytes = $bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['bytes'];
|
return ['bytes'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return $this->bytes;
|
return $this->bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function jsonSerialize()
|
public function jsonSerialize()
|
||||||
{
|
{
|
||||||
return utf8_encode($this->bytes);
|
return utf8_encode($this->bytes);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\Threads;
|
namespace danog\MadelineProto\Threads;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,38 +23,32 @@ class SocketHandler extends \Threaded implements \Collectable
|
|||||||
$this->current = $current;
|
$this->current = $current;
|
||||||
$this->error = $error;
|
$this->error = $error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reading connection and receiving message from server. Check the CRC32.
|
* Reading connection and receiving message from server. Check the CRC32.
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
require __DIR__.'/../../../../vendor/autoload.php';
|
require __DIR__ . '/../../../../vendor/autoload.php';
|
||||||
if ($this->error !== true) {
|
if ($this->error !== true) {
|
||||||
if ($this->error === -404) {
|
if ($this->error === -404) {
|
||||||
if ($this->API->datacenter->sockets[$this->current]->temp_auth_key !== null) {
|
if ($this->API->datacenter->sockets[$this->current]->temp_auth_key !== null) {
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['resetting_auth_key']], \danog\MadelineProto\Logger::WARNING);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['resetting_auth_key']], \danog\MadelineProto\Logger::WARNING);
|
||||||
$this->API->datacenter->sockets[$this->current]->temp_auth_key = null;
|
$this->API->datacenter->sockets[$this->current]->temp_auth_key = null;
|
||||||
$this->API->init_authorization();
|
$this->API->init_authorization();
|
||||||
|
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['recreate_temp_auth_key']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['recreate_temp_auth_key']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \danog\MadelineProto\RPCErrorException($this->error, $this->error);
|
throw new \danog\MadelineProto\RPCErrorException($this->error, $this->error);
|
||||||
}
|
}
|
||||||
$this->API->handle_messages($this->current);
|
$this->API->handle_messages($this->current);
|
||||||
$this->setGarbage();
|
$this->setGarbage();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $garbage = false;
|
protected $garbage = false;
|
||||||
|
public function setGarbage()
|
||||||
public function setGarbage():void
|
|
||||||
{
|
{
|
||||||
$this->garbage = true;
|
$this->garbage = true;
|
||||||
}
|
}
|
||||||
|
public function isGarbage()
|
||||||
public function isGarbage():bool
|
|
||||||
{
|
{
|
||||||
return $this->garbage;
|
return $this->garbage;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\Threads;
|
namespace danog\MadelineProto\Threads;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,34 +18,27 @@ namespace danog\MadelineProto\Threads;
|
|||||||
class SocketReader extends \Threaded implements \Collectable
|
class SocketReader extends \Threaded implements \Collectable
|
||||||
{
|
{
|
||||||
public $ready = false;
|
public $ready = false;
|
||||||
|
|
||||||
public function __construct($me, $current)
|
public function __construct($me, $current)
|
||||||
{
|
{
|
||||||
$this->API = $me;
|
$this->API = $me;
|
||||||
$this->current = $current;
|
$this->current = $current;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __sleep()
|
public function __sleep()
|
||||||
{
|
{
|
||||||
return ['current', 'API', 'garbage'];
|
return ['current', 'API', 'garbage'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['shutting_down_reader_pool'].$this->current], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['shutting_down_reader_pool'] . $this->current], \danog\MadelineProto\Logger::NOTICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reading connection and receiving message from server. Check the CRC32.
|
* Reading connection and receiving message from server. Check the CRC32.
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
require __DIR__.'/../../../../vendor/autoload.php';
|
require __DIR__ . '/../../../../vendor/autoload.php';
|
||||||
|
|
||||||
$handler_pool = new \Pool($this->API->settings['threading']['handler_workers']);
|
$handler_pool = new \Pool($this->API->settings['threading']['handler_workers']);
|
||||||
|
|
||||||
$this->ready = true;
|
$this->ready = true;
|
||||||
|
|
||||||
while ($this->API->run_workers) {
|
while ($this->API->run_workers) {
|
||||||
try {
|
try {
|
||||||
$this->API->datacenter->sockets[$this->current]->reading = true;
|
$this->API->datacenter->sockets[$this->current]->reading = true;
|
||||||
@ -64,15 +57,12 @@ class SocketReader extends \Threaded implements \Collectable
|
|||||||
}
|
}
|
||||||
$this->setGarbage();
|
$this->setGarbage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public $garbage = false;
|
public $garbage = false;
|
||||||
|
public function setGarbage()
|
||||||
public function setGarbage():void
|
|
||||||
{
|
{
|
||||||
$this->garbage = true;
|
$this->garbage = true;
|
||||||
}
|
}
|
||||||
|
public function isGarbage()
|
||||||
public function isGarbage():bool
|
|
||||||
{
|
{
|
||||||
return $this->garbage;
|
return $this->garbage;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with the MadelineProto.
|
You should have received a copy of the GNU General Public License along with the MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,7 +21,6 @@ trait Tools
|
|||||||
{
|
{
|
||||||
return $length === 0 ? '' : \phpseclib\Crypt\Random::string($length);
|
return $length === 0 ? '' : \phpseclib\Crypt\Random::string($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* posmod(numeric,numeric) : numeric
|
* posmod(numeric,numeric) : numeric
|
||||||
* Works just like the % (modulus) operator, only returns always a postive number.
|
* Works just like the % (modulus) operator, only returns always a postive number.
|
||||||
@ -29,10 +28,8 @@ trait Tools
|
|||||||
public function posmod($a, $b)
|
public function posmod($a, $b)
|
||||||
{
|
{
|
||||||
$resto = $a % $b;
|
$resto = $a % $b;
|
||||||
|
return $resto < 0 ? $resto + abs($b) : $resto;
|
||||||
return $resto < 0 ? ($resto + abs($b)) : $resto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function array_cast_recursive($array, $force = false)
|
public function array_cast_recursive($array, $force = false)
|
||||||
{
|
{
|
||||||
if (!\danog\MadelineProto\Logger::$has_thread && !$force) {
|
if (!\danog\MadelineProto\Logger::$has_thread && !$force) {
|
||||||
@ -46,28 +43,22 @@ trait Tools
|
|||||||
$array[$key] = $this->array_cast_recursive($value, $force);
|
$array[$key] = $this->array_cast_recursive($value, $force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unpack_signed_int($value)
|
public function unpack_signed_int($value)
|
||||||
{
|
{
|
||||||
if (strlen($value) !== 4) {
|
if (strlen($value) !== 4) {
|
||||||
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_4']);
|
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_4']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return unpack('l', \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($value) : $value)[1];
|
return unpack('l', \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($value) : $value)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unpack_signed_long($value)
|
public function unpack_signed_long($value)
|
||||||
{
|
{
|
||||||
if (strlen($value) !== 8) {
|
if (strlen($value) !== 8) {
|
||||||
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
|
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return unpack('q', \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($value) : $value)[1];
|
return unpack('q', \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($value) : $value)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pack_signed_int($value)
|
public function pack_signed_int($value)
|
||||||
{
|
{
|
||||||
if ($value > 2147483647) {
|
if ($value > 2147483647) {
|
||||||
@ -77,23 +68,19 @@ trait Tools
|
|||||||
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_2147483648'], $value));
|
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_2147483648'], $value));
|
||||||
}
|
}
|
||||||
$res = pack('l', $value);
|
$res = pack('l', $value);
|
||||||
|
|
||||||
return \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($res) : $res;
|
return \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($res) : $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pack_signed_long($value)
|
public function pack_signed_long($value)
|
||||||
{
|
{
|
||||||
if ($value > 9223372036854775807) {
|
if ($value > 9223372036854775807) {
|
||||||
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_9223372036854775807'], $value));
|
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_9223372036854775807'], $value));
|
||||||
}
|
}
|
||||||
if ($value < -9223372036854775808) {
|
if ($value < -9.223372036854776E+18) {
|
||||||
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_9223372036854775808'], $value));
|
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_9223372036854775808'], $value));
|
||||||
}
|
}
|
||||||
$res = \danog\MadelineProto\Logger::$bigint ? ($this->pack_signed_int($value)."\0\0\0\0") : (\danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev(pack('q', $value)) : pack('q', $value));
|
$res = \danog\MadelineProto\Logger::$bigint ? $this->pack_signed_int($value) . "\0\0\0\0" : (\danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev(pack('q', $value)) : pack('q', $value));
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pack_unsigned_int($value)
|
public function pack_unsigned_int($value)
|
||||||
{
|
{
|
||||||
if ($value > 4294967295) {
|
if ($value > 4294967295) {
|
||||||
@ -102,26 +89,21 @@ trait Tools
|
|||||||
if ($value < 0) {
|
if ($value < 0) {
|
||||||
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_0'], $value));
|
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_0'], $value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return pack('V', $value);
|
return pack('V', $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pack_double($value)
|
public function pack_double($value)
|
||||||
{
|
{
|
||||||
$res = pack('d', $value);
|
$res = pack('d', $value);
|
||||||
if (strlen($res) !== 8) {
|
if (strlen($res) !== 8) {
|
||||||
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['encode_double_error']);
|
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['encode_double_error']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($res) : $res;
|
return \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($res) : $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unpack_double($value)
|
public function unpack_double($value)
|
||||||
{
|
{
|
||||||
if (strlen($value) !== 8) {
|
if (strlen($value) !== 8) {
|
||||||
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
|
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return unpack('d', \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($value) : $value)[1];
|
return unpack('d', \danog\MadelineProto\Logger::$BIG_ENDIAN ? strrev($value) : $value)[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\VoIP;
|
namespace danog\MadelineProto\VoIP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,10 +21,9 @@ namespace danog\MadelineProto\VoIP;
|
|||||||
trait AuthKeyHandler
|
trait AuthKeyHandler
|
||||||
{
|
{
|
||||||
private $calls = [];
|
private $calls = [];
|
||||||
|
|
||||||
public function request_call($user)
|
public function request_call($user)
|
||||||
{
|
{
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
||||||
}
|
}
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
@ -32,7 +31,6 @@ trait AuthKeyHandler
|
|||||||
$controller->discard();
|
$controller->discard();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$user = $this->get_info($user);
|
$user = $this->get_info($user);
|
||||||
if (!isset($user['InputUser']) || $user['InputUser']['_'] === 'inputUserSelf') {
|
if (!isset($user['InputUser']) || $user['InputUser']['_'] === 'inputUserSelf') {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
|
||||||
@ -48,19 +46,15 @@ trait AuthKeyHandler
|
|||||||
$res = $this->method_call('phone.requestCall', ['user_id' => $user, 'g_a_hash' => hash('sha256', $g_a->toBytes(), true), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_p2p' => true, 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc]);
|
$res = $this->method_call('phone.requestCall', ['user_id' => $user, 'g_a_hash' => hash('sha256', $g_a->toBytes(), true), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_p2p' => true, 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
$this->calls[$res['phone_call']['id']] = $controller = new \danog\MadelineProto\VoIP(true, $user['user_id'], ['_' => 'inputPhoneCall', 'id' => $res['phone_call']['id'], 'access_hash' => $res['phone_call']['access_hash']], $this, \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED, $res['phone_call']['protocol']);
|
$this->calls[$res['phone_call']['id']] = $controller = new \danog\MadelineProto\VoIP(true, $user['user_id'], ['_' => 'inputPhoneCall', 'id' => $res['phone_call']['id'], 'access_hash' => $res['phone_call']['access_hash']], $this, \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED, $res['phone_call']['protocol']);
|
||||||
$controller->storage = ['a' => $a, 'g_a' => str_pad($g_a->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
$controller->storage = ['a' => $a, 'g_a' => str_pad($g_a->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
||||||
|
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
|
|
||||||
return $controller;
|
return $controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function accept_call($call)
|
public function accept_call($call)
|
||||||
{
|
{
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||||
$controller->discard();
|
$controller->discard();
|
||||||
@ -68,48 +62,38 @@ trait AuthKeyHandler
|
|||||||
});
|
});
|
||||||
if ($this->call_status($call['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED) {
|
if ($this->call_status($call['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED) {
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_1'], $call['id'])]);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_1'], $call['id'])]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['accepting_call'], $this->calls[$call['id']]->getOtherID())], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['accepting_call'], $this->calls[$call['id']]->getOtherID())], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
$dh_config = $this->get_dh_config();
|
$dh_config = $this->get_dh_config();
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['generating_b']], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['generating_b']], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$b = \phpseclib\Math\BigInteger::randomRange($this->two, $dh_config['p']->subtract($this->two));
|
$b = \phpseclib\Math\BigInteger::randomRange($this->two, $dh_config['p']->subtract($this->two));
|
||||||
$g_b = $dh_config['g']->powMod($b, $dh_config['p']);
|
$g_b = $dh_config['g']->powMod($b, $dh_config['p']);
|
||||||
$this->check_G($g_b, $dh_config['p']);
|
$this->check_G($g_b, $dh_config['p']);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$res = $this->method_call('phone.acceptCall', ['peer' => $call, 'g_b' => $g_b->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'udp_p2p' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc]);
|
$res = $this->method_call('phone.acceptCall', ['peer' => $call, 'g_b' => $g_b->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'udp_p2p' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc]);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
|
if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id'])]);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id'])]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ($e->rpc === 'CALL_ALREADY_DECLINED') {
|
if ($e->rpc === 'CALL_ALREADY_DECLINED') {
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['call_already_declined']]);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['call_already_declined']]);
|
||||||
$this->discard_call($call['id'], 'phoneCallDiscardReasonHangup');
|
$this->discard_call($call['id'], 'phoneCallDiscardReasonHangup');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
$this->calls[$res['phone_call']['id']]->storage['b'] = $b;
|
$this->calls[$res['phone_call']['id']]->storage['b'] = $b;
|
||||||
|
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
$this->get_updates_difference();
|
$this->get_updates_difference();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function confirm_call($params)
|
public function confirm_call($params)
|
||||||
{
|
{
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||||
$controller->discard();
|
$controller->discard();
|
||||||
@ -117,52 +101,34 @@ trait AuthKeyHandler
|
|||||||
});
|
});
|
||||||
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED) {
|
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED) {
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_2'], $params['id'])]);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_2'], $params['id'])]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID())], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID())], \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);
|
||||||
$this->check_G($params['g_b'], $dh_config['p']);
|
$this->check_G($params['g_b'], $dh_config['p']);
|
||||||
$key = str_pad($params['g_b']->powMod($this->calls[$params['id']]->storage['a'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
|
$key = str_pad($params['g_b']->powMod($this->calls[$params['id']]->storage['a'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
|
||||||
$res = $this->method_call('phone.confirmCall', ['key_fingerprint' => substr(sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc])['phone_call'];
|
$res = $this->method_call('phone.confirmCall', ['key_fingerprint' => substr(sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc])['phone_call'];
|
||||||
|
|
||||||
$visualization = [];
|
$visualization = [];
|
||||||
$length = new \phpseclib\Math\BigInteger(count($this->emojis));
|
$length = new \phpseclib\Math\BigInteger(count($this->emojis));
|
||||||
foreach (str_split(hash('sha256', $key.str_pad($this->calls[$params['id']]->storage['g_a'], 256, chr(0), \STR_PAD_LEFT), true), 8) as $number) {
|
foreach (str_split(hash('sha256', $key . str_pad($this->calls[$params['id']]->storage['g_a'], 256, chr(0), \STR_PAD_LEFT), true), 8) as $number) {
|
||||||
$number[0] = chr(ord($number[0]) & 0x7F);
|
$number[0] = chr(ord($number[0]) & 0x7f);
|
||||||
$visualization[] = $this->emojis[(int) ((new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString())];
|
$visualization[] = $this->emojis[(int) (new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString()];
|
||||||
}
|
}
|
||||||
$this->calls[$params['id']]->setVisualization($visualization);
|
$this->calls[$params['id']]->setVisualization($visualization);
|
||||||
|
|
||||||
$this->calls[$params['id']]->configuration['shared_config'] = array_merge($this->method_call('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc]), $this->calls[$params['id']]->configuration['shared_config']);
|
$this->calls[$params['id']]->configuration['shared_config'] = array_merge($this->method_call('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc]), $this->calls[$params['id']]->configuration['shared_config']);
|
||||||
$this->calls[$params['id']]->configuration['endpoints'] = array_merge([$res['connection']], $res['alternative_connections'], $this->calls[$params['id']]->configuration['endpoints']);
|
$this->calls[$params['id']]->configuration['endpoints'] = array_merge([$res['connection']], $res['alternative_connections'], $this->calls[$params['id']]->configuration['endpoints']);
|
||||||
$this->calls[$params['id']]->configuration = array_merge([
|
$this->calls[$params['id']]->configuration = array_merge(['recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000, 'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000, 'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER, 'enable_NS' => true, 'enable_AEC' => true, 'enable_AGC' => true, 'auth_key' => $key, 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
|
||||||
'recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000,
|
|
||||||
'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000,
|
|
||||||
'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER,
|
|
||||||
'enable_NS' => true,
|
|
||||||
'enable_AEC' => true,
|
|
||||||
'enable_AGC' => true,
|
|
||||||
|
|
||||||
'auth_key' => $key,
|
|
||||||
'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET,
|
|
||||||
], $this->calls[$params['id']]->configuration);
|
|
||||||
$this->calls[$params['id']]->parseConfig();
|
$this->calls[$params['id']]->parseConfig();
|
||||||
$res = $this->calls[$params['id']]->startTheMagic();
|
$res = $this->calls[$params['id']]->startTheMagic();
|
||||||
|
|
||||||
$this->handle_pending_updates();
|
$this->handle_pending_updates();
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function complete_call($params)
|
public function complete_call($params)
|
||||||
{
|
{
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||||
$controller->discard();
|
$controller->discard();
|
||||||
@ -170,11 +136,9 @@ trait AuthKeyHandler
|
|||||||
});
|
});
|
||||||
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED || !isset($this->calls[$params['id']]->storage['b'])) {
|
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED || !isset($this->calls[$params['id']]->storage['b'])) {
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_3'], $params['id'])]);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_3'], $params['id'])]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_completing'], $this->calls[$params['id']]->getOtherID())], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_completing'], $this->calls[$params['id']]->getOtherID())], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
$dh_config = $this->get_dh_config();
|
$dh_config = $this->get_dh_config();
|
||||||
if (hash('sha256', $params['g_a_or_b'], true) != $this->calls[$params['id']]->storage['g_a_hash']) {
|
if (hash('sha256', $params['g_a_or_b'], true) != $this->calls[$params['id']]->storage['g_a_hash']) {
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['invalid_g_a']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['invalid_g_a']);
|
||||||
@ -182,82 +146,58 @@ trait AuthKeyHandler
|
|||||||
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256);
|
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256);
|
||||||
$this->check_G($params['g_a_or_b'], $dh_config['p']);
|
$this->check_G($params['g_a_or_b'], $dh_config['p']);
|
||||||
$key = str_pad($params['g_a_or_b']->powMod($this->calls[$params['id']]->storage['b'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
|
$key = str_pad($params['g_a_or_b']->powMod($this->calls[$params['id']]->storage['b'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
|
||||||
|
|
||||||
if (substr(sha1($key, true), -8) != $params['key_fingerprint']) {
|
if (substr(sha1($key, true), -8) != $params['key_fingerprint']) {
|
||||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_invalid']);
|
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_invalid']);
|
||||||
}
|
}
|
||||||
$visualization = [];
|
$visualization = [];
|
||||||
$length = new \phpseclib\Math\BigInteger(count($this->emojis));
|
$length = new \phpseclib\Math\BigInteger(count($this->emojis));
|
||||||
|
foreach (str_split(hash('sha256', $key . str_pad($params['g_a_or_b']->toBytes(), 256, chr(0), \STR_PAD_LEFT), true), 8) as $number) {
|
||||||
foreach (str_split(hash('sha256', $key.str_pad($params['g_a_or_b']->toBytes(), 256, chr(0), \STR_PAD_LEFT), true), 8) as $number) {
|
$number[0] = chr(ord($number[0]) & 0x7f);
|
||||||
$number[0] = chr(ord($number[0]) & 0x7F);
|
$visualization[] = $this->emojis[(int) (new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString()];
|
||||||
$visualization[] = $this->emojis[(int) ((new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString())];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->calls[$params['id']]->setVisualization($visualization);
|
$this->calls[$params['id']]->setVisualization($visualization);
|
||||||
$this->calls[$params['id']]->configuration['shared_config'] = array_merge($this->method_call('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc]), $this->calls[$params['id']]->configuration['shared_config']);
|
$this->calls[$params['id']]->configuration['shared_config'] = array_merge($this->method_call('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc]), $this->calls[$params['id']]->configuration['shared_config']);
|
||||||
$this->calls[$params['id']]->configuration['endpoints'] = array_merge([$params['connection']], $params['alternative_connections'], $this->calls[$params['id']]->configuration['endpoints']);
|
$this->calls[$params['id']]->configuration['endpoints'] = array_merge([$params['connection']], $params['alternative_connections'], $this->calls[$params['id']]->configuration['endpoints']);
|
||||||
|
$this->calls[$params['id']]->configuration = array_merge(['recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000, 'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000, 'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER, 'enable_NS' => true, 'enable_AEC' => true, 'enable_AGC' => true, 'auth_key' => $key, 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
|
||||||
$this->calls[$params['id']]->configuration = array_merge([
|
|
||||||
'recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000,
|
|
||||||
'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000,
|
|
||||||
'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER,
|
|
||||||
'enable_NS' => true,
|
|
||||||
'enable_AEC' => true,
|
|
||||||
'enable_AGC' => true,
|
|
||||||
|
|
||||||
'auth_key' => $key,
|
|
||||||
'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET,
|
|
||||||
], $this->calls[$params['id']]->configuration);
|
|
||||||
$this->calls[$params['id']]->parseConfig();
|
$this->calls[$params['id']]->parseConfig();
|
||||||
|
|
||||||
return $this->calls[$params['id']]->startTheMagic();
|
return $this->calls[$params['id']]->startTheMagic();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function call_status($id)
|
public function call_status($id)
|
||||||
{
|
{
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||||
$controller->discard();
|
$controller->discard();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isset($this->calls[$id])) {
|
if (isset($this->calls[$id])) {
|
||||||
return $this->calls[$id]->getCallState();
|
return $this->calls[$id]->getCallState();
|
||||||
}
|
}
|
||||||
|
|
||||||
return \danog\MadelineProto\VoIP::CALL_STATE_NONE;
|
return \danog\MadelineProto\VoIP::CALL_STATE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_call($call)
|
public function get_call($call)
|
||||||
{
|
{
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||||
$controller->discard();
|
$controller->discard();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this->calls[$call];
|
return $this->calls[$call];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function discard_call($call, $reason, $rating = [], $need_debug = true)
|
public function discard_call($call, $reason, $rating = [], $need_debug = true)
|
||||||
{
|
{
|
||||||
if (!class_exists('\danog\MadelineProto\VoIP')) {
|
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['libtgvoip_required']);
|
||||||
}
|
}
|
||||||
if (!isset($this->calls[$call['id']])) {
|
if (!isset($this->calls[$call['id']])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_discarding'], $call['id'])], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_discarding'], $call['id'])], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$res = $this->method_call('phone.discardCall', ['peer' => $call, 'duration' => time() - $this->calls[$call['id']]->whenCreated(), 'connection_id' => $this->calls[$call['id']]->getPreferredRelayID(), 'reason' => $reason], ['datacenter' => $this->datacenter->curdc]);
|
$res = $this->method_call('phone.discardCall', ['peer' => $call, 'duration' => time() - $this->calls[$call['id']]->whenCreated(), 'connection_id' => $this->calls[$call['id']]->getPreferredRelayID(), 'reason' => $reason], ['datacenter' => $this->datacenter->curdc]);
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
@ -269,7 +209,8 @@ trait AuthKeyHandler
|
|||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_set_rating'], $call['id'])], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_set_rating'], $call['id'])], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->method_call('phone.setCallRating', ['peer' => $call, 'rating' => $rating['rating'], 'comment' => $rating['comment']], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('phone.setCallRating', ['peer' => $call, 'rating' => $rating['rating'], 'comment' => $rating['comment']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
}
|
}
|
||||||
if ($need_debug) {//} && isset($this->calls[$call['id']]->storage['not_modified'])) {
|
if ($need_debug) {
|
||||||
|
//} && isset($this->calls[$call['id']]->storage['not_modified'])) {
|
||||||
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_debug_saving'], $call['id'])], \danog\MadelineProto\Logger::VERBOSE);
|
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['call_debug_saving'], $call['id'])], \danog\MadelineProto\Logger::VERBOSE);
|
||||||
$this->method_call('phone.saveCallDebug', ['peer' => $call, 'debug' => $this->calls[$call['id']]->getDebugLog()], ['datacenter' => $this->datacenter->curdc]);
|
$this->method_call('phone.saveCallDebug', ['peer' => $call, 'debug' => $this->calls[$call['id']]->getDebugLog()], ['datacenter' => $this->datacenter->curdc]);
|
||||||
}
|
}
|
||||||
@ -277,7 +218,7 @@ trait AuthKeyHandler
|
|||||||
if (isset($this->settings['pwr']['strict']) && $this->settings['pwr']['strict']) {
|
if (isset($this->settings['pwr']['strict']) && $this->settings['pwr']['strict']) {
|
||||||
$this->pwr_update_handler($update);
|
$this->pwr_update_handler($update);
|
||||||
} else {
|
} else {
|
||||||
in_array($this->settings['updates']['callback'], [['danog\MadelineProto\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['updates']['callback']($update);
|
in_array($this->settings['updates']['callback'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['updates']['callback']($update);
|
||||||
}
|
}
|
||||||
unset($this->calls[$call['id']]);
|
unset($this->calls[$call['id']]);
|
||||||
array_walk($this->calls, function ($controller, $id) {
|
array_walk($this->calls, function ($controller, $id) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,28 +10,20 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\Wrappers;
|
namespace danog\MadelineProto\Wrappers;
|
||||||
|
|
||||||
trait DialogHandler
|
trait DialogHandler
|
||||||
{
|
{
|
||||||
public function get_dialogs($force = true)
|
public function get_dialogs($force = true)
|
||||||
{
|
{
|
||||||
if ($force ||
|
if ($force || !isset($this->dialog_params['offset_date']) || is_null($this->dialog_params['offset_date']) || !isset($this->dialog_params['offset_id']) || is_null($this->dialog_params['offset_id']) || !isset($this->dialog_params['offset_peer']) || is_null($this->dialog_params['offset_peer']) || !isset($this->dialog_params['count']) || is_null($this->dialog_params['count'])) {
|
||||||
!isset($this->dialog_params['offset_date']) || is_null($this->dialog_params['offset_date']) ||
|
|
||||||
!isset($this->dialog_params['offset_id']) || is_null($this->dialog_params['offset_id']) ||
|
|
||||||
!isset($this->dialog_params['offset_peer']) || is_null($this->dialog_params['offset_peer']) ||
|
|
||||||
!isset($this->dialog_params['count']) || is_null($this->dialog_params['count'])
|
|
||||||
) {
|
|
||||||
$this->dialog_params = ['limit' => 0, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty'], 'count' => 0];
|
$this->dialog_params = ['limit' => 0, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty'], 'count' => 0];
|
||||||
}
|
}
|
||||||
$this->updates_state['sync_loading'] = true;
|
$this->updates_state['sync_loading'] = true;
|
||||||
$res = ['dialogs' => [0], 'count' => 1];
|
$res = ['dialogs' => [0], 'count' => 1];
|
||||||
$datacenter = $this->datacenter->curdc;
|
$datacenter = $this->datacenter->curdc;
|
||||||
$peers = [];
|
$peers = [];
|
||||||
|
|
||||||
$this->postpone_updates = true;
|
$this->postpone_updates = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while ($this->dialog_params['count'] < $res['count']) {
|
while ($this->dialog_params['count'] < $res['count']) {
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['getting_dialogs']]);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['getting_dialogs']]);
|
||||||
@ -52,7 +45,6 @@ trait DialogHandler
|
|||||||
$this->postpone_updates = false;
|
$this->postpone_updates = false;
|
||||||
$this->updates_state['sync_loading'] = false;
|
$this->updates_state['sync_loading'] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $peers;
|
return $peers;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2018 Daniil Gentili
|
Copyright 2016-2018 Daniil Gentili
|
||||||
(https://daniil.it)
|
(https://daniil.it)
|
||||||
@ -9,7 +10,6 @@ See the GNU Affero General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace danog\MadelineProto\Wrappers;
|
namespace danog\MadelineProto\Wrappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,15 +30,12 @@ trait Login
|
|||||||
$this->chats = [];
|
$this->chats = [];
|
||||||
$this->users = [];
|
$this->users = [];
|
||||||
$this->state = [];
|
$this->state = [];
|
||||||
|
|
||||||
if (!$this->method_call('auth.logOut', [], ['datacenter' => $this->datacenter->curdc])) {
|
if (!$this->method_call('auth.logOut', [], ['datacenter' => $this->datacenter->curdc])) {
|
||||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['logout_error']);
|
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['logout_error']);
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['logout_ok']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['logout_ok']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bot_login($token)
|
public function bot_login($token)
|
||||||
{
|
{
|
||||||
if ($this->authorized === self::LOGGED_IN) {
|
if ($this->authorized === self::LOGGED_IN) {
|
||||||
@ -46,29 +43,19 @@ trait Login
|
|||||||
$this->logout();
|
$this->logout();
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_bot']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_bot']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->authorization = $this->method_call(
|
$this->authorization = $this->method_call('auth.importBotAuthorization', ['bot_auth_token' => $token, 'api_id' => $this->settings['app_info']['api_id'], 'api_hash' => $this->settings['app_info']['api_hash']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
'auth.importBotAuthorization',
|
|
||||||
[
|
|
||||||
'bot_auth_token' => $token,
|
|
||||||
'api_id' => $this->settings['app_info']['api_id'],
|
|
||||||
'api_hash' => $this->settings['app_info']['api_hash'],
|
|
||||||
], ['datacenter' => $this->datacenter->curdc]
|
|
||||||
);
|
|
||||||
$this->authorized = self::LOGGED_IN;
|
$this->authorized = self::LOGGED_IN;
|
||||||
$this->authorized_dc = $this->datacenter->curdc;
|
$this->authorized_dc = $this->datacenter->curdc;
|
||||||
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
||||||
|
|
||||||
$this->updates = [];
|
$this->updates = [];
|
||||||
$this->updates_key = 0;
|
$this->updates_key = 0;
|
||||||
if (!isset($this->settings['pwr']['pwr']) || !$this->settings['pwr']['pwr']) {
|
if (!isset($this->settings['pwr']['pwr']) || !$this->settings['pwr']['pwr']) {
|
||||||
@file_get_contents('https://api.pwrtelegram.xyz/bot'.$token.'/getme');
|
@file_get_contents('https://api.pwrtelegram.xyz/bot' . $token . '/getme');
|
||||||
}
|
}
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_ok']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_ok']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return $this->authorization;
|
return $this->authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function phone_login($number, $sms_type = 5)
|
public function phone_login($number, $sms_type = 5)
|
||||||
{
|
{
|
||||||
if ($this->authorized === self::LOGGED_IN) {
|
if ($this->authorized === self::LOGGED_IN) {
|
||||||
@ -76,29 +63,16 @@ trait Login
|
|||||||
$this->logout();
|
$this->logout();
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_code_sending']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_code_sending']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->authorization = $this->method_call(
|
$this->authorization = $this->method_call('auth.sendCode', ['phone_number' => $number, 'sms_type' => $sms_type, 'api_id' => $this->settings['app_info']['api_id'], 'api_hash' => $this->settings['app_info']['api_hash'], 'lang_code' => $this->settings['app_info']['lang_code']], ['datacenter' => $this->datacenter->curdc]);
|
||||||
'auth.sendCode',
|
|
||||||
[
|
|
||||||
'phone_number' => $number,
|
|
||||||
'sms_type' => $sms_type,
|
|
||||||
'api_id' => $this->settings['app_info']['api_id'],
|
|
||||||
'api_hash' => $this->settings['app_info']['api_hash'],
|
|
||||||
'lang_code' => $this->settings['app_info']['lang_code'],
|
|
||||||
], ['datacenter' => $this->datacenter->curdc]
|
|
||||||
);
|
|
||||||
$this->authorized_dc = $this->datacenter->curdc;
|
$this->authorized_dc = $this->datacenter->curdc;
|
||||||
|
|
||||||
$this->authorization['phone_number'] = $number;
|
$this->authorization['phone_number'] = $number;
|
||||||
//$this->authorization['_'] .= 'MP';
|
//$this->authorization['_'] .= 'MP';
|
||||||
$this->authorized = self::WAITING_CODE;
|
$this->authorized = self::WAITING_CODE;
|
||||||
$this->updates = [];
|
$this->updates = [];
|
||||||
$this->updates_key = 0;
|
$this->updates_key = 0;
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_code_sent']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_code_sent']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return $this->authorization;
|
return $this->authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function complete_phone_login($code)
|
public function complete_phone_login($code)
|
||||||
{
|
{
|
||||||
if ($this->authorized !== self::WAITING_CODE) {
|
if ($this->authorized !== self::WAITING_CODE) {
|
||||||
@ -106,21 +80,12 @@ trait Login
|
|||||||
}
|
}
|
||||||
$this->authorized = self::NOT_LOGGED_IN;
|
$this->authorized = self::NOT_LOGGED_IN;
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_user']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_user']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$authorization = $this->method_call(
|
$authorization = $this->method_call('auth.signIn', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => $code], ['datacenter' => $this->datacenter->curdc]);
|
||||||
'auth.signIn',
|
|
||||||
[
|
|
||||||
'phone_number' => $this->authorization['phone_number'],
|
|
||||||
'phone_code_hash' => $this->authorization['phone_code_hash'],
|
|
||||||
'phone_code' => $code,
|
|
||||||
], ['datacenter' => $this->datacenter->curdc]
|
|
||||||
);
|
|
||||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
if ($e->rpc === 'SESSION_PASSWORD_NEEDED') {
|
if ($e->rpc === 'SESSION_PASSWORD_NEEDED') {
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_2fa_enabled']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_2fa_enabled']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->authorized = self::WAITING_PASSWORD;
|
$this->authorized = self::WAITING_PASSWORD;
|
||||||
|
|
||||||
$this->authorization = $this->method_call('account.getPassword', [], ['datacenter' => $this->datacenter->curdc]);
|
$this->authorization = $this->method_call('account.getPassword', [], ['datacenter' => $this->datacenter->curdc]);
|
||||||
//$this->authorization['_'] .= 'MP';
|
//$this->authorization['_'] .= 'MP';
|
||||||
return $this->authorization;
|
return $this->authorization;
|
||||||
@ -129,22 +94,17 @@ trait Login
|
|||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_need_signup']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_need_signup']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->authorized = self::WAITING_SIGNUP;
|
$this->authorized = self::WAITING_SIGNUP;
|
||||||
$this->authorization['phone_code'] = $code;
|
$this->authorization['phone_code'] = $code;
|
||||||
|
|
||||||
return ['_' => 'account.needSignup'];
|
return ['_' => 'account.needSignup'];
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
$this->authorized = self::LOGGED_IN;
|
$this->authorized = self::LOGGED_IN;
|
||||||
$this->authorization = $authorization;
|
$this->authorization = $authorization;
|
||||||
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_ok']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_ok']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return $this->authorization;
|
return $this->authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function import_authorization($authorization)
|
public function import_authorization($authorization)
|
||||||
{
|
{
|
||||||
if ($this->authorized === self::LOGGED_IN) {
|
if ($this->authorized === self::LOGGED_IN) {
|
||||||
@ -152,12 +112,10 @@ trait Login
|
|||||||
$this->logout();
|
$this->logout();
|
||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_auth_key']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_auth_key']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
list($dc_id, $auth_key) = $authorization;
|
list($dc_id, $auth_key) = $authorization;
|
||||||
if (!is_array($auth_key)) {
|
if (!is_array($auth_key)) {
|
||||||
$auth_key = ['auth_key' => $auth_key, 'id' => substr(sha1($auth_key, true), -8), 'server_salt' => ''];
|
$auth_key = ['auth_key' => $auth_key, 'id' => substr(sha1($auth_key, true), -8), 'server_salt' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->authorized_dc = $dc_id;
|
$this->authorized_dc = $dc_id;
|
||||||
$this->datacenter->sockets[$dc_id]->session_id = $this->random(8);
|
$this->datacenter->sockets[$dc_id]->session_id = $this->random(8);
|
||||||
$this->datacenter->sockets[$dc_id]->session_in_seq_no = 0;
|
$this->datacenter->sockets[$dc_id]->session_in_seq_no = 0;
|
||||||
@ -169,13 +127,10 @@ trait Login
|
|||||||
$this->datacenter->sockets[$dc_id]->new_outgoing = [];
|
$this->datacenter->sockets[$dc_id]->new_outgoing = [];
|
||||||
$this->datacenter->sockets[$dc_id]->new_incoming = [];
|
$this->datacenter->sockets[$dc_id]->new_incoming = [];
|
||||||
$this->datacenter->sockets[$dc_id]->authorized = true;
|
$this->datacenter->sockets[$dc_id]->authorized = true;
|
||||||
|
|
||||||
$this->authorized = self::LOGGED_IN;
|
$this->authorized = self::LOGGED_IN;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
|
|
||||||
return $this->get_self();
|
return $this->get_self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function export_authorization()
|
public function export_authorization()
|
||||||
{
|
{
|
||||||
if ($this->authorized !== self::LOGGED_IN) {
|
if ($this->authorized !== self::LOGGED_IN) {
|
||||||
@ -183,10 +138,8 @@ trait Login
|
|||||||
}
|
}
|
||||||
$this->get_self();
|
$this->get_self();
|
||||||
$this->authorized_dc = $this->datacenter->curdc;
|
$this->authorized_dc = $this->datacenter->curdc;
|
||||||
|
|
||||||
return [$this->datacenter->curdc, $this->datacenter->sockets[$this->datacenter->curdc]->auth_key['auth_key']];
|
return [$this->datacenter->curdc, $this->datacenter->sockets[$this->datacenter->curdc]->auth_key['auth_key']];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function complete_signup($first_name, $last_name)
|
public function complete_signup($first_name, $last_name)
|
||||||
{
|
{
|
||||||
if ($this->authorized !== self::WAITING_SIGNUP) {
|
if ($this->authorized !== self::WAITING_SIGNUP) {
|
||||||
@ -194,25 +147,13 @@ trait Login
|
|||||||
}
|
}
|
||||||
$this->authorized = self::NOT_LOGGED_IN;
|
$this->authorized = self::NOT_LOGGED_IN;
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['signing_up']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['signing_up']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->authorization = $this->method_call(
|
$this->authorization = $this->method_call('auth.signUp', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => $this->authorization['phone_code'], 'first_name' => $first_name, 'last_name' => $last_name], ['datacenter' => $this->datacenter->curdc]);
|
||||||
'auth.signUp',
|
|
||||||
[
|
|
||||||
'phone_number' => $this->authorization['phone_number'],
|
|
||||||
'phone_code_hash' => $this->authorization['phone_code_hash'],
|
|
||||||
'phone_code' => $this->authorization['phone_code'],
|
|
||||||
'first_name' => $first_name,
|
|
||||||
'last_name' => $last_name,
|
|
||||||
], ['datacenter' => $this->datacenter->curdc]
|
|
||||||
);
|
|
||||||
$this->authorized = self::LOGGED_IN;
|
$this->authorized = self::LOGGED_IN;
|
||||||
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['signup_ok']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['signup_ok']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return $this->authorization;
|
return $this->authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function complete_2fa_login($password)
|
public function complete_2fa_login($password)
|
||||||
{
|
{
|
||||||
if ($this->authorized !== self::WAITING_PASSWORD) {
|
if ($this->authorized !== self::WAITING_PASSWORD) {
|
||||||
@ -220,18 +161,11 @@ trait Login
|
|||||||
}
|
}
|
||||||
$this->authorized = self::NOT_LOGGED_IN;
|
$this->authorized = self::NOT_LOGGED_IN;
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_user']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_user']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
$this->authorization = $this->method_call(
|
$this->authorization = $this->method_call('auth.checkPassword', ['password_hash' => hash('sha256', $this->authorization['current_salt'] . $password . $this->authorization['current_salt'], true)], ['datacenter' => $this->datacenter->curdc]);
|
||||||
'auth.checkPassword',
|
|
||||||
[
|
|
||||||
'password_hash' => hash('sha256', $this->authorization['current_salt'].$password.$this->authorization['current_salt'], true),
|
|
||||||
], ['datacenter' => $this->datacenter->curdc]
|
|
||||||
);
|
|
||||||
$this->authorized = self::LOGGED_IN;
|
$this->authorized = self::LOGGED_IN;
|
||||||
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
$this->datacenter->sockets[$this->datacenter->curdc]->authorized = true;
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_ok']], \danog\MadelineProto\Logger::NOTICE);
|
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['login_ok']], \danog\MadelineProto\Logger::NOTICE);
|
||||||
|
|
||||||
return $this->authorization;
|
return $this->authorization;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user