This commit is contained in:
Daniil Gentili 2019-09-02 17:08:36 +02:00
parent 72d353fff0
commit e0b293b9a1
99 changed files with 1683 additions and 1673 deletions

5
.gitignore vendored
View File

@ -116,3 +116,8 @@ madeline.php
.vscode/*
.vscode
custom.md
composer.lock
phpunit.xml
vendor
.php_cs.cache
coverage

14
.php_cs.dist Normal file
View File

@ -0,0 +1,14 @@
<?php
$config = new Amp\CodeStyle\Config();
$config->getFinder()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
->in(__DIR__ . '/userbots')
->name(__DIR__ . '/*.php');
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
$config->setCacheFile($cacheDir . '/.php_cs.cache');
return $config;

View File

@ -33,7 +33,8 @@
"require-dev": {
"phpdocumentor/reflection-docblock": "^3.1",
"ennexa/amp-update-cache": "dev-master",
"phpunit/phpunit": "^8"
"phpunit/phpunit": "^8",
"amphp/php-cs-fixer-config": "dev-master"
},
"suggest": {
"ext-libtgvoip": "Install the php-libtgvoip extension to make phone calls (https://github.com/danog/php-libtgvoip)"
@ -62,5 +63,14 @@
"type": "git",
"url": "https://github.com/danog/dns"
}
]
],
"scripts": {
"check": [
"@cs",
"@test"
],
"cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
"test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
}
}

View File

@ -19,10 +19,10 @@
namespace phpseclib\Math;
if (PHP_MAJOR_VERSION < 7 && !(class_exists(\Phar::class) && \Phar::running())) {
if (PHP_MAJOR_VERSION < 7 && !(\class_exists(\Phar::class) && \Phar::running())) {
throw new \Exception('MadelineProto requires php 7 to run natively, use phar.madelineproto.xyz to run on PHP 5.6');
}
if (defined('HHVM_VERSION')) {
if (\defined('HHVM_VERSION')) {
$engines = [['PHP64', ['OpenSSL']], ['BCMath', ['OpenSSL']], ['PHP32', ['OpenSSL']]];
foreach ($engines as $engine) {
try {

View File

@ -1,6 +1,6 @@
<?php
if (!class_exists('ReflectionGenerator')) {
if (!\class_exists('ReflectionGenerator')) {
class ReflectionGenerator
{
private $generator;

View File

@ -20,10 +20,10 @@
namespace danog\MadelineProto;
use Amp\Deferred;
use function Amp\File\put;
use function Amp\File\rename;
use function Amp\File\get;
use function Amp\File\exists;
use function Amp\File\get;
use function Amp\File\put;
use function Amp\File\rename as renameAsync;
class API extends APIFactory
{
@ -48,11 +48,11 @@ class API extends APIFactory
$this->asyncAPIPromise = null;
});
$this->setInitPromise($this->__construct_async($params, $settings, $deferred));
foreach (get_object_vars(new APIFactory('', $this, $this->async)) as $key => $var) {
if (in_array($key, ['namespace', 'API', 'lua', 'async', 'asyncAPIPromise', 'methods', 'asyncInitPromise'])) {
foreach (\get_object_vars(new APIFactory('', $this, $this->async)) as $key => $var) {
if (\in_array($key, ['namespace', 'API', 'lua', 'async', 'asyncAPIPromise', 'methods', 'asyncInitPromise'])) {
continue;
}
if (is_null($this->{$key})) {
if (\is_null($this->{$key})) {
$this->{$key} = new APIFactory($key, $this->API, $this->async);
}
}
@ -60,7 +60,7 @@ class API extends APIFactory
public function __construct_async($params, $settings, $deferred)
{
if (is_string($params)) {
if (\is_string($params)) {
Logger::constructorFromSettings($settings);
$realpaths = Serialization::realpaths($params);
@ -79,32 +79,32 @@ class API extends APIFactory
\danog\MadelineProto\Magic::class_exists();
try {
$unserialized = unserialize($tounserialize);
$unserialized = \unserialize($tounserialize);
} catch (\danog\MadelineProto\Bug74586Exception $e) {
class_exists('\\Volatile');
$tounserialize = str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $tounserialize);
\class_exists('\\Volatile');
$tounserialize = \str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $tounserialize);
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);
}
$unserialized = \danog\Serialization::unserialize($tounserialize);
} catch (\danog\MadelineProto\Exception $e) {
if ($e->getFile() === 'MadelineProto' && $e->getLine() === 1) {
throw $e;
}
if (defined('MADELINEPROTO_TEST') && MADELINEPROTO_TEST === 'pony') {
if (\defined('MADELINEPROTO_TEST') && MADELINEPROTO_TEST === 'pony') {
throw $e;
}
class_exists('\\Volatile');
\class_exists('\\Volatile');
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);
}
$changed = false;
if (strpos($tounserialize, 'O:26:"danog\\MadelineProto\\Button":') !== false) {
$tounserialize = str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $tounserialize);
if (\strpos($tounserialize, 'O:26:"danog\\MadelineProto\\Button":') !== false) {
$tounserialize = \str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $tounserialize);
$changed = true;
}
if (strpos($e->getMessage(), "Erroneous data format for unserializing 'phpseclib\\Math\\BigInteger'") === 0) {
$tounserialize = str_replace('phpseclib\\Math\\BigInteger', 'phpseclib\\Math\\BigIntegor', $tounserialize);
if (\strpos($e->getMessage(), "Erroneous data format for unserializing 'phpseclib\\Math\\BigInteger'") === 0) {
$tounserialize = \str_replace('phpseclib\\Math\\BigInteger', 'phpseclib\\Math\\BigIntegor', $tounserialize);
$changed = true;
}
@ -170,7 +170,7 @@ class API extends APIFactory
$this->async = $async;
if ($this->API) {
if ($this->API->event_handler && class_exists($this->API->event_handler) && is_subclass_of($this->API->event_handler, '\danog\MadelineProto\EventHandler')) {
if ($this->API->event_handler && \class_exists($this->API->event_handler) && \is_subclass_of($this->API->event_handler, '\danog\MadelineProto\EventHandler')) {
$this->API->setEventHandler($this->API->event_handler);
}
}
@ -183,7 +183,7 @@ class API extends APIFactory
public function __destruct()
{
if (\danog\MadelineProto\Magic::$has_thread && is_object(\Thread::getCurrentThread()) || Magic::is_fork()) {
if (\danog\MadelineProto\Magic::$has_thread && \is_object(\Thread::getCurrentThread()) || Magic::is_fork()) {
return;
}
if ($this->asyncInitPromise) {
@ -209,13 +209,13 @@ class API extends APIFactory
private function from_camel_case($input)
{
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
\preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
$ret = $matches[0];
foreach ($ret as &$match) {
$match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
$match = $match == \strtoupper($match) ? \strtolower($match) : \lcfirst($match);
}
return implode('_', $ret);
return \implode('_', $ret);
}
public function my_get_self()
@ -229,15 +229,15 @@ class API extends APIFactory
foreach ($this->API->get_method_namespaces() as $namespace) {
$this->{$namespace} = new APIFactory($namespace, $this->API, $this->async);
}
$methods = get_class_methods($this->API);
$methods = \get_class_methods($this->API);
foreach ($methods as $method) {
if ($method == 'method_call_async_read') {
unset($methods[array_search('method_call', $methods)]);
} elseif (stripos($method, 'async') !== false) {
if (strpos($method, '_async') !== false) {
unset($methods[array_search(str_ireplace('_async', '', $method), $methods)]);
unset($methods[\array_search('method_call', $methods)]);
} elseif (\stripos($method, 'async') !== false) {
if (\strpos($method, '_async') !== false) {
unset($methods[\array_search(\str_ireplace('_async', '', $method), $methods)]);
} else {
unset($methods[array_search(str_ireplace('async', '', $method), $methods)]);
unset($methods[\array_search(\str_ireplace('async', '', $method), $methods)]);
}
}
}
@ -247,24 +247,24 @@ class API extends APIFactory
if ($method == 'method_call_async_read') {
$method = 'method_call';
} elseif (stripos($method, 'async') !== false) {
if (strpos($method, '_async') !== false) {
$method = str_ireplace('_async', '', $method);
} elseif (\stripos($method, 'async') !== false) {
if (\strpos($method, '_async') !== false) {
$method = \str_ireplace('_async', '', $method);
} else {
$method = str_ireplace('async', '', $method);
$method = \str_ireplace('async', '', $method);
}
}
$actual_method = $actual_method === 'get_self_async' ? [$this, 'my_get_self'] : [$this->API, $actual_method];
$this->methods[strtolower($method)] = $actual_method;
if (strpos($method, '_') !== false) {
$this->methods[strtolower(str_replace('_', '', $method))] = $actual_method;
$this->methods[\strtolower($method)] = $actual_method;
if (\strpos($method, '_') !== false) {
$this->methods[\strtolower(\str_replace('_', '', $method))] = $actual_method;
} else {
$this->methods[strtolower($this->from_camel_case($method))] = $actual_method;
$this->methods[\strtolower($this->from_camel_case($method))] = $actual_method;
}
}
$this->API->wrapper = $this;
if ($this->API->event_handler && class_exists($this->API->event_handler) && is_subclass_of($this->API->event_handler, '\danog\MadelineProto\EventHandler')) {
if ($this->API->event_handler && \class_exists($this->API->event_handler) && \is_subclass_of($this->API->event_handler, '\danog\MadelineProto\EventHandler')) {
$this->API->setEventHandler($this->API->event_handler);
}
}
@ -280,7 +280,7 @@ class API extends APIFactory
$methods[] = $method['method'];
}
return array_merge($methods, get_class_methods($this->API));
return \array_merge($methods, \get_class_methods($this->API));
}
public function serialize($filename = null)
@ -307,12 +307,12 @@ class API extends APIFactory
if ($this->API && $this->API->asyncInitPromise) {
yield $this->API->initAsync();
}
$this->serialized = time();
$this->serialized = \time();
$realpaths = Serialization::realpaths($filename);
Logger::log('Waiting for exclusive lock of serialization lockfile...');
$unlock = yield Tools::flock($realpaths['lockfile'], LOCK_EX);
Logger::log('Lock acquired, serializing');
try {
@ -326,8 +326,8 @@ class API extends APIFactory
$this->API->settings['logger']['logger_param'] = [$this->API, 'noop'];
}
}
$wrote = yield put($realpaths['tempfile'], serialize($this));
yield rename($realpaths['tempfile'], $realpaths['file']);
$wrote = yield put($realpaths['tempfile'], \serialize($this));
yield renameAsync($realpaths['tempfile'], $realpaths['file']);
} finally {
if (!$this->getting_api_id) {
$this->API->settings['updates']['callback'] = $update_closure;

View File

@ -139,7 +139,7 @@ class APIFactory extends AsyncConstruct
public function __call($name, $arguments)
{
$yielded = $this->call($this->__call_async($name, $arguments));
$async = $this->lua === false && (is_array(end($arguments)) && isset(end($arguments)['async']) ? end($arguments)['async'] : ($this->async && $name !== 'loop'));
$async = $this->lua === false && (\is_array(\end($arguments)) && isset(\end($arguments)['async']) ? \end($arguments)['async'] : ($this->async && $name !== 'loop'));
if ($async) {
return $yielded;
}
@ -173,7 +173,7 @@ class APIFactory extends AsyncConstruct
yield $this->API->initAsync();
$this->API->logger->logger('Finished init asynchronously');
}
if (isset($this->session) && !is_null($this->session) && time() - $this->serialized > $this->API->settings['serialization']['serialization_interval']) {
if (isset($this->session) && !\is_null($this->session) && \time() - $this->serialized > $this->API->settings['serialization']['serialization_interval']) {
Logger::log("Didn't serialize in a while, doing that now...");
$this->serialize($this->session);
}
@ -187,18 +187,17 @@ class APIFactory extends AsyncConstruct
$this->API->logger->logger('Finished init asynchronously');
}
$lower_name = strtolower($name);
$lower_name = \strtolower($name);
if ($this->namespace !== '' || !isset($this->methods[$lower_name])) {
$name = $this->namespace.$name;
$aargs = isset($arguments[1]) && is_array($arguments[1]) ? $arguments[1] : [];
$aargs = isset($arguments[1]) && \is_array($arguments[1]) ? $arguments[1] : [];
$aargs['apifactory'] = true;
$aargs['datacenter'] = $this->API->datacenter->curdc;
$args = isset($arguments[0]) && is_array($arguments[0]) ? $arguments[0] : [];
$args = isset($arguments[0]) && \is_array($arguments[0]) ? $arguments[0] : [];
return yield $this->API->method_call_async_read($name, $args, $aargs);
} else {
return yield $this->methods[$lower_name](...$arguments);
}
return yield $this->methods[$lower_name](...$arguments);
}
public function &__get($name)
@ -228,7 +227,7 @@ class APIFactory extends AsyncConstruct
$this->API->init();
}
return $this->API->__construct(array_replace_recursive($this->API->settings, $value));
return $this->API->__construct(\array_replace_recursive($this->API->settings, $value));
}
return $this->API->storage[$name] = $value;

View File

@ -26,7 +26,7 @@ class Absolute
{
public static function absolute($file)
{
if (($file[0] !== '/') && ($file[1] !== ':') && !in_array(substr($file, 0, 4), ['phar', 'http'])) {
if (($file[0] !== '/') && ($file[1] !== ':') && !\in_array(\substr($file, 0, 4), ['phar', 'http'])) {
$file = Magic::getcwd().'/'.$file;
}

View File

@ -50,19 +50,19 @@ class AnnotationsBuilder
\danog\MadelineProto\Logger::log('Generating properties...', \danog\MadelineProto\Logger::NOTICE);
$fixture = DocBlockFactory::createInstance();
$class = new \ReflectionClass(APIFactory::class);
$content = file_get_contents($filename = $class->getFileName());
$content = \file_get_contents($filename = $class->getFileName());
foreach ($class->getProperties() as $property) {
if ($raw_docblock = $property->getDocComment()) {
$docblock = $fixture->create($raw_docblock);
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) {
$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);
$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);
}
file_put_contents($filename, $content);
\file_put_contents($filename, $content);
}
/**
@ -71,25 +71,25 @@ class AnnotationsBuilder
private function createInternalClasses()
{
\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) {
if (!strpos($data['method'], '.')) {
if (!\strpos($data['method'], '.')) {
continue;
}
list($namespace, $method) = explode('.', $data['method']);
if (!in_array($namespace, $this->get_method_namespaces())) {
list($namespace, $method) = \explode('.', $data['method']);
if (!\in_array($namespace, $this->get_method_namespaces())) {
continue;
}
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
$type = \str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
foreach ($data['params'] as $param) {
if (in_array($param['name'], ['flags', 'random_id'])) {
if (\in_array($param['name'], ['flags', 'random_id'])) {
continue;
}
$stype = 'type';
if (isset($param['subtype'])) {
$stype = 'subtype';
}
$ptype = str_replace('.', '_', $param[$stype]);
$ptype = \str_replace('.', '_', $param[$stype]);
switch ($ptype) {
case 'true':
case 'false':
@ -98,39 +98,39 @@ class AnnotationsBuilder
$internalDoc[$namespace][$method]['attr'][$param['name']] = $ptype;
}
if ($type === 'Bool') {
$type = strtolower($type);
$type = \strtolower($type);
}
$internalDoc[$namespace][$method]['return'] = $type;
}
fwrite($handle, "<?php\n");
fwrite($handle, "/**\n");
fwrite($handle, " * This file is automatic generated by build_docs.php file\n");
fwrite($handle, " * and is used only for autocomplete in multiple IDE\n");
fwrite($handle, " * don't modify manually.\n");
fwrite($handle, " */\n\n");
fwrite($handle, "namespace danog\\MadelineProto;\n");
\fwrite($handle, "<?php\n");
\fwrite($handle, "/**\n");
\fwrite($handle, " * This file is automatic generated by build_docs.php file\n");
\fwrite($handle, " * and is used only for autocomplete in multiple IDE\n");
\fwrite($handle, " * don't modify manually.\n");
\fwrite($handle, " */\n\n");
\fwrite($handle, "namespace danog\\MadelineProto;\n");
foreach ($internalDoc as $namespace => $methods) {
fwrite($handle, "\ninterface {$namespace}\n{");
\fwrite($handle, "\ninterface {$namespace}\n{");
foreach ($methods as $method => $properties) {
fwrite($handle, "\n /**\n");
\fwrite($handle, "\n /**\n");
if (isset($properties['attr'])) {
fwrite($handle, " * @param array params [\n");
\fwrite($handle, " * @param array params [\n");
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, " */\n");
fwrite($handle, " public function {$method}(");
\fwrite($handle, " * @return {$properties['return']}\n");
\fwrite($handle, " */\n");
\fwrite($handle, " public function {$method}(");
if (isset($properties['attr'])) {
fwrite($handle, 'array $params');
\fwrite($handle, 'array $params');
}
fwrite($handle, ");\n");
\fwrite($handle, ");\n");
}
fwrite($handle, "}\n");
\fwrite($handle, "}\n");
}
fclose($handle);
\fclose($handle);
}
}

View File

@ -36,7 +36,7 @@ class CombinedAPI
public function __magic_construct($session, $paths = [])
{
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
\danog\MadelineProto\Magic::class_exists();
$realpaths = Serialization::realpaths($session);
@ -46,23 +46,23 @@ class CombinedAPI
$this->addInstance($path, $settings);
}
if (file_exists($realpaths['file'])) {
if (!file_exists($realpaths['lockfile'])) {
touch($realpaths['lockfile']);
clearstatcache();
if (\file_exists($realpaths['file'])) {
if (!\file_exists($realpaths['lockfile'])) {
\touch($realpaths['lockfile']);
\clearstatcache();
}
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'r');
$realpaths['lockfile'] = \fopen($realpaths['lockfile'], 'r');
\danog\MadelineProto\Logger::log('Waiting for shared lock of serialization lockfile...');
flock($realpaths['lockfile'], LOCK_SH);
\flock($realpaths['lockfile'], LOCK_SH);
\danog\MadelineProto\Logger::log('Shared lock acquired, deserializing...');
try {
$tounserialize = file_get_contents($realpaths['file']);
$tounserialize = \file_get_contents($realpaths['file']);
} finally {
flock($realpaths['lockfile'], LOCK_UN);
fclose($realpaths['lockfile']);
\flock($realpaths['lockfile'], LOCK_UN);
\fclose($realpaths['lockfile']);
}
$deserialized = unserialize($tounserialize);
$deserialized = \unserialize($tounserialize);
/*foreach ($deserialized['instance_paths'] as $path) {
$this->addInstance($path, isset($paths[$path]) ? $paths[$path] : []);
@ -118,7 +118,7 @@ class CombinedAPI
public function __destruct()
{
if (\danog\MadelineProto\Magic::$has_thread && is_object(\Thread::getCurrentThread()) || Magic::is_fork()) {
if (\danog\MadelineProto\Magic::$has_thread && \is_object(\Thread::getCurrentThread()) || Magic::is_fork()) {
return;
}
@ -131,7 +131,7 @@ class CombinedAPI
$instance->serialize();
}*/
if (is_null($this->session)) {
if (\is_null($this->session)) {
return;
}
if ($filename === '') {
@ -139,24 +139,24 @@ class CombinedAPI
}
Logger::log(\danog\MadelineProto\Lang::$current_lang['serializing_madelineproto']);
$realpaths = Serialization::realpaths($filename);
if (!file_exists($realpaths['lockfile'])) {
touch($realpaths['lockfile']);
clearstatcache();
if (!\file_exists($realpaths['lockfile'])) {
\touch($realpaths['lockfile']);
\clearstatcache();
}
$realpaths['lockfile'] = fopen($realpaths['lockfile'], 'w');
$realpaths['lockfile'] = \fopen($realpaths['lockfile'], 'w');
\danog\MadelineProto\Logger::log('Waiting for exclusive lock of serialization lockfile...');
flock($realpaths['lockfile'], LOCK_EX);
\flock($realpaths['lockfile'], LOCK_EX);
\danog\MadelineProto\Logger::log('Lock acquired, serializing');
try {
$wrote = file_put_contents($realpaths['tempfile'], serialize(['event_handler' => $this->event_handler, 'event_handler_instance' => $this->event_handler_instance, 'instance_paths' => $this->instance_paths]));
rename($realpaths['tempfile'], $realpaths['file']);
$wrote = \file_put_contents($realpaths['tempfile'], \serialize(['event_handler' => $this->event_handler, 'event_handler_instance' => $this->event_handler_instance, 'instance_paths' => $this->instance_paths]));
\rename($realpaths['tempfile'], $realpaths['file']);
} finally {
flock($realpaths['lockfile'], LOCK_UN);
fclose($realpaths['lockfile']);
\flock($realpaths['lockfile'], LOCK_UN);
\fclose($realpaths['lockfile']);
}
$this->serialized = time();
$this->serialized = \time();
return $wrote;
}
@ -170,7 +170,7 @@ class CombinedAPI
}
public function setEventHandler($event_handler)
{
if (!class_exists($event_handler) || !is_subclass_of($event_handler, '\danog\MadelineProto\CombinedEventHandler')) {
if (!\class_exists($event_handler) || !\is_subclass_of($event_handler, '\danog\MadelineProto\CombinedEventHandler')) {
throw new \danog\MadelineProto\Exception('Wrong event handler was defined');
}
@ -188,13 +188,13 @@ class CombinedAPI
if ($method === 'onLoop') {
$this->loop_callback = [$this->event_handler_instance, 'onLoop'];
} elseif ($method === 'onAny') {
foreach (end($this->instances)->API->constructors->by_id as $constructor) {
foreach (\end($this->instances)->API->constructors->by_id as $constructor) {
if ($constructor['type'] === 'Update' && !isset($this->event_handler_methods[$constructor['predicate']])) {
$this->event_handler_methods[$constructor['predicate']] = [$this->event_handler_instance, 'onAny'];
}
}
} else {
$method_name = lcfirst(substr($method, 2));
$method_name = \lcfirst(\substr($method, 2));
$this->event_handler_methods[$method_name] = [$this->event_handler_instance, $method];
}
}
@ -228,7 +228,7 @@ class CombinedAPI
public function loop($max_forks = 0)
{
if (is_callable($max_forks)) {
if (\is_callable($max_forks)) {
return $this->wait($max_forks());
}

View File

@ -33,7 +33,7 @@ abstract class CombinedEventHandler
final public function __sleep()
{
$keys = method_exists($this, '__magic_sleep') ? $this->__magic_sleep() : get_object_vars($this);
$keys = \method_exists($this, '__magic_sleep') ? $this->__magic_sleep() : \get_object_vars($this);
unset($keys['CombinedAPI']);
if (isset($this->CombinedAPI) && $this->CombinedAPI instanceof CombinedAPI) {
foreach ($this->CombinedAPI->instance_paths as $path) {
@ -47,7 +47,7 @@ abstract class CombinedEventHandler
}
}
return array_keys($keys);
return \array_keys($keys);
}
final public function referenceInstance($path)

View File

@ -126,16 +126,16 @@ class Connection extends Session
protected $datacenter;
/**
* Connection ID
* Connection ID.
*
* @var int
*/
private $id = 0;
/**
* DC ID and connection ID concatenated
* DC ID and connection ID concatenated.
*
* @var
* @var
*/
private $datacenterId = '';
@ -237,7 +237,7 @@ class Connection extends Session
}
/**
* Get connection ID
* Get connection ID.
*
* @return integer
*/
@ -247,7 +247,7 @@ class Connection extends Session
}
/**
* Get datacenter concatenated with connection ID
* Get datacenter concatenated with connection ID.
*
* @return string
*/
@ -277,7 +277,7 @@ class Connection extends Session
}
/**
* Check if is a media connection
* Check if is a media connection.
*
* @return boolean
*/
@ -287,7 +287,7 @@ class Connection extends Session
}
/**
* Check if is a CDN connection
* Check if is a CDN connection.
*
* @return boolean
*/

View File

@ -41,7 +41,6 @@ use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectException;
use Amp\Socket\Socket;
use Amp\TimeoutException;
use danog\MadelineProto\MTProto\AuthKey;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProto\TempAuthKey;
use danog\MadelineProto\Stream\Common\BufferedRawStream;
@ -146,10 +145,10 @@ class DataCenter
}
/**
* Set auth key information from saved auth array
* Set auth key information from saved auth array.
*
* @param array $saved Saved auth array
*
*
* @return void
*/
public function setDataCenterConnections(array $saved)
@ -827,7 +826,7 @@ class DataCenter
}
/**
* Get Connection instance for authorization
* Get Connection instance for authorization.
*
* @param string $dc DC ID
*
@ -882,10 +881,10 @@ class DataCenter
/**
* Check if connected to datacenter using HTTP
* Check if connected to datacenter using HTTP.
*
* @param string $datacenter DC ID
*
*
* @return boolean
*/
public function isHttp(string $datacenter)
@ -894,7 +893,7 @@ class DataCenter
}
/**
* Get all DCs
* Get all DCs.
*
* @param boolean $all
* @return void

View File

@ -32,7 +32,7 @@ class DataCenterConnection implements JsonSerializable
const READ_WEIGHT = 1;
const READ_WEIGHT_MEDIA = 5;
const WRITE_WEIGHT = 10;
/**
* Temporary auth key.
*
@ -266,7 +266,7 @@ class DataCenterConnection implements JsonSerializable
}
}
/**
* Create MTProto sessions if needed
* Create MTProto sessions if needed.
*
* @return void
*/
@ -329,7 +329,7 @@ class DataCenterConnection implements JsonSerializable
if ($id === -1 || !isset($this->connections[$id])) {
$this->connections = [];
$this->availableConnections = [];
yield $this->connectMore($count);
} else {
yield $this->connections[$id]->connect($ctx);
@ -337,16 +337,16 @@ class DataCenterConnection implements JsonSerializable
}
/**
* Connect to the DC using count more sockets
* Connect to the DC using count more sockets.
*
* @param integer $count Number of sockets to open
*
*
* @return void
*/
private function connectMore(int $count)
{
$ctx = $this->ctx->getCtx();
$count += $previousCount = count($this->connections);
$count += $previousCount = \count($this->connections);
for ($x = $previousCount; $x < $count; $x++) {
$this->availableConnections[$x] = 0;
$this->connections[$x] = new Connection();
@ -408,7 +408,7 @@ class DataCenterConnection implements JsonSerializable
return $this->connections[0];
}
$max = \max($this->availableConnections);
$key = array_search($max, $this->availableConnections);
$key = \array_search($max, $this->availableConnections);
// Decrease to implement round robin
$this->availableConnections[$key]--;

View File

@ -31,7 +31,7 @@ class DocsBuilder
public function __construct($logger, $settings)
{
$this->logger = $logger;
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
$this->construct_TL($settings['tl_schema']);
if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) {
$this->constructors = $this->td_constructors;
@ -39,10 +39,10 @@ class DocsBuilder
$this->td = true;
}
$this->settings = $settings;
if (!file_exists($this->settings['output_dir'])) {
mkdir($this->settings['output_dir']);
if (!\file_exists($this->settings['output_dir'])) {
\mkdir($this->settings['output_dir']);
}
chdir($this->settings['output_dir']);
\chdir($this->settings['output_dir']);
$this->index = $settings['readme'] ? 'README.md' : 'index.md';
}
@ -51,18 +51,18 @@ class DocsBuilder
public function end($what)
{
return end($what);
return \end($what);
}
public function escape($hwat)
{
return str_replace('_', '\\_', $hwat);
return \str_replace('_', '\\_', $hwat);
}
public function mk_docs()
{
\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'].'
description: '.$this->settings['description'].'
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -79,37 +79,37 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
[Types](types/)');
$this->mk_methodS();
$this->mk_constructors();
foreach (glob('types/*') as $unlink) {
unlink($unlink);
foreach (\glob('types/*') as $unlink) {
\unlink($unlink);
}
if (file_exists('types')) {
rmdir('types');
if (\file_exists('types')) {
\rmdir('types');
}
mkdir('types');
ksort($this->types);
\mkdir('types');
\ksort($this->types);
$index = '';
\danog\MadelineProto\Logger::log('Generating types documentation...', \danog\MadelineProto\Logger::NOTICE);
$last_namespace = '';
foreach ($this->types as $otype => $keys) {
$new_namespace = preg_replace('/_.*/', '', $otype);
$new_namespace = \preg_replace('/_.*/', '', $otype);
//$br = $new_namespace != $last_namespace ? '***<br><br>' : '';
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $otype);
$type = preg_replace('/.*_of_/', '', $type);
$index .= '['.str_replace('_', '\\_', $type).']('.$type.'.md)<a name="'.$type.'"></a>
$type = \str_replace(['.', '<', '>'], ['_', '_of_', ''], $otype);
$type = \preg_replace('/.*_of_/', '', $type);
$index .= '['.\str_replace('_', '\\_', $type).']('.$type.'.md)<a name="'.$type.'"></a>
';
$constructors = '';
foreach ($keys['constructors'] as $data) {
$predicate = str_replace('.', '_', $data['predicate']).(isset($data['layer']) && $data['layer'] !== '' ? '_'.$data['layer'] : '');
$md_predicate = str_replace('_', '\\_', $predicate);
$predicate = \str_replace('.', '_', $data['predicate']).(isset($data['layer']) && $data['layer'] !== '' ? '_'.$data['layer'] : '');
$md_predicate = \str_replace('_', '\\_', $predicate);
$constructors .= '['.$md_predicate.'](../constructors/'.$predicate.'.md)
';
}
$methods = '';
foreach ($keys['methods'] as $data) {
$name = str_replace('.', '_', $data['method']);
$md_name = str_replace('_', '->', $name);
$name = \str_replace('.', '_', $data['method']);
$md_name = \str_replace('_', '->', $name);
$methods .= '[$MadelineProto->'.$md_name.'](../methods/'.$name.'.md)
';
@ -120,7 +120,7 @@ title: '.$type.'
description: constructors and methods of type '.$type.'
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
---
# Type: '.str_replace('_', '\\_', $type).'
# Type: '.\str_replace('_', '\\_', $type).'
[Back to types index](index.md)
@ -128,7 +128,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
';
$header .= isset($this->td_descriptions['types'][$otype]) ? $this->td_descriptions['types'][$otype].PHP_EOL.PHP_EOL : '';
if (!isset($this->settings['td'])) {
if (in_array($type, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'InputPeer', 'NotifyPeer', 'InputNotifyPeer'])) {
if (\in_array($type, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'InputPeer', 'NotifyPeer', 'InputNotifyPeer'])) {
$header .= 'You can directly provide the [Update](Update.md) or [Message](Message.md) object here, MadelineProto will automatically extract the destination chat id.
The following syntaxes can also be used:
@ -152,7 +152,7 @@ $'.$type." = 'https://t.me/danogentili'; // t.me URLs
A [Chat](Chat.md), a [User](User.md), an [InputPeer](InputPeer.md), an [InputDialogPeer](InputDialogPeer.md), an [InputNotifyPeer](InputNotifyPeer.md), an [InputUser](InputUser.md), an [InputChannel](InputChannel.md), a [Peer](Peer.md), an [DialogPeer](DialogPeer.md), [NotifyPeer](NotifyPeer.md), or a [Chat](Chat.md) object can also be used.\n\n\n";
}
if (in_array($type, ['InputEncryptedChat'])) {
if (\in_array($type, ['InputEncryptedChat'])) {
$header .= 'You can directly provide the [Update](Update.md) or [EncryptedMessage](EncryptedMessage.md) object here, MadelineProto will automatically extract the destination chat id.
The following syntax can also be used:
@ -164,7 +164,7 @@ $'.$type.' = -147286699; // Numeric chat id returned by request_secret_chat, can
';
}
if (in_array($type, ['InputFile', 'InputEncryptedFile'])) {
if (\in_array($type, ['InputFile', 'InputEncryptedFile'])) {
$header .= 'The following syntax can also be used:
```
@ -174,22 +174,22 @@ $'.$type.' = \'filename.mp4\'; // The file path can also be used
';
}
if (in_array($type, ['InputPhoto'])) {
if (\in_array($type, ['InputPhoto'])) {
$header .= 'You can also provide a [MessageMedia](MessageMedia.md), [Message](Message.md), [Update](Update.md), [Photo](Photo.md) here, MadelineProto will automatically convert it to the right type.
';
}
if (in_array($type, ['InputDocument'])) {
if (\in_array($type, ['InputDocument'])) {
$header .= 'You can also provide a [MessageMedia](MessageMedia.md), [Message](Message.md), [Update](Update.md), [Document](Document.md) here, MadelineProto will automatically convert it to the right type.
';
}
if (in_array($type, ['InputMedia'])) {
if (\in_array($type, ['InputMedia'])) {
$header .= 'You can also provide a [MessageMedia](MessageMedia.md), [Message](Message.md), [Update](Update.md), [Document](Document.md), [Photo](Photo.md), [InputDocument](InputDocument.md), [InputPhoto](InputPhoto.md) here, MadelineProto will automatically convert it to the right type.
';
}
if (in_array($type, ['InputMessage'])) {
if (\in_array($type, ['InputMessage'])) {
$header .= 'The following syntax can also be used:
```
@ -199,7 +199,7 @@ $'.$type.' = 142; // Numeric message ID
';
}
if (in_array($type, ['KeyboardButton'])) {
if (\in_array($type, ['KeyboardButton'])) {
$header .= 'Clicking these buttons:
To click these buttons simply run the `click` method:
@ -235,7 +235,7 @@ You can also access the properties of the constructor as a normal array, for exa
';
if (!isset($this->settings['td'])) {
if (in_array($type, ['PhoneCall'])) {
if (\in_array($type, ['PhoneCall'])) {
$methods = '';
$constructors = '';
$header .= 'This is an object of type `\\danog\\MadelineProto\\VoIP`.
@ -418,14 +418,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);
}
file_put_contents('types/'.$type.'.md', $header.$constructors.$methods);
\file_put_contents('types/'.$type.'.md', $header.$constructors.$methods);
$last_namespace = $new_namespace;
}
\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
description: List of types
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -436,7 +436,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
'.$index);
\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
description: A UTF8 string of variable length
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -446,7 +446,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
A UTF8 string of variable length. The total length in bytes of the string must not be bigger than 16777215.
');
file_put_contents('types/bytes.md', '---
\file_put_contents('types/bytes.md', '---
title: bytes
description: A string of variable length
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -464,7 +464,7 @@ When JSON-serialized, turns into an array of the following format:
];
```
');
file_put_contents('types/int.md', '---
\file_put_contents('types/int.md', '---
title: integer
description: A 32 bit signed integer ranging from -2147483648 to 2147483647
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -474,7 +474,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
A 32 bit signed integer ranging from `-2147483648` to `2147483647`.
');
file_put_contents('types/int53.md', '---
\file_put_contents('types/int53.md', '---
title: integer
description: A 53 bit signed integer
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -484,7 +484,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
A 53 bit signed integer.
');
file_put_contents('types/long.md', '---
\file_put_contents('types/long.md', '---
title: long
description: A 32 bit signed integer ranging from -9223372036854775808 to 9223372036854775807
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -494,7 +494,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
A 64 bit signed integer ranging from `-9223372036854775808` to `9223372036854775807`.
');
file_put_contents('types/int128.md', '---
\file_put_contents('types/int128.md', '---
title: int128
description: A 128 bit signed integer
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -504,7 +504,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
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
description: A 256 bit signed integer
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -514,7 +514,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
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
description: A 512 bit signed integer
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -524,7 +524,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
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
description: A double precision floating point number
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -534,7 +534,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
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
description: Represents a TL serialized payload
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -544,7 +544,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
Represents a TL serialized payload.
');
file_put_contents('types/X.md', '---
\file_put_contents('types/X.md', '---
title: X
description: Represents a TL serialized payload
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -554,7 +554,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
Represents a TL serialized payload.
');
file_put_contents('constructors/boolFalse.md', '---
\file_put_contents('constructors/boolFalse.md', '---
title: boolFalse
description: Represents a boolean with value equal to false
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -564,7 +564,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
Represents a boolean with value equal to `false`.
');
file_put_contents('constructors/boolTrue.md', '---
\file_put_contents('constructors/boolTrue.md', '---
title: boolTrue
description: Represents a boolean with value equal to true
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -574,7 +574,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
Represents a boolean with value equal to `true`.
');
file_put_contents('constructors/null.md', '---
\file_put_contents('constructors/null.md', '---
title: null
description: Represents a null value
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -584,7 +584,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
Represents a `null` value.
');
file_put_contents('types/Bool.md', '---
\file_put_contents('types/Bool.md', '---
title: Bool
description: Represents a boolean.
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -594,7 +594,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
Represents a boolean.
');
file_put_contents('types/DataJSON.md', '---
\file_put_contents('types/DataJSON.md', '---
title: DataJSON
description: Any json-encodable data
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -638,7 +638,7 @@ class Lang
{
if (!isset(\danog\MadelineProto\Lang::$lang['en'][$key])) {
\danog\MadelineProto\Lang::$lang['en'][$key] = '';
file_put_contents(__DIR__.'/Lang.php', sprintf($this->template, var_export(\danog\MadelineProto\Lang::$lang, true), var_export(\danog\MadelineProto\Lang::$lang['en'], true)));
\file_put_contents(__DIR__.'/Lang.php', \sprintf($this->template, \var_export(\danog\MadelineProto\Lang::$lang, true), \var_export(\danog\MadelineProto\Lang::$lang['en'], true)));
}
}
}

View File

@ -23,13 +23,13 @@ trait Constructors
{
public function mk_constructors()
{
foreach (glob('constructors/'.$this->any) as $unlink) {
unlink($unlink);
foreach (\glob('constructors/'.$this->any) as $unlink) {
\unlink($unlink);
}
if (file_exists('constructors')) {
rmdir('constructors');
if (\file_exists('constructors')) {
\rmdir('constructors');
}
mkdir('constructors');
\mkdir('constructors');
$this->docs_constructors = [];
$this->logger->logger('Generating constructors documentation...', \danog\MadelineProto\Logger::NOTICE);
$got = [];
@ -44,19 +44,19 @@ trait Constructors
$type = $this->constructors->find_by_type(str_replace('%', '', $type))['predicate'];
}*/
$layer = isset($data['layer']) && $data['layer'] !== '' ? '_'.$data['layer'] : '';
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
$php_type = preg_replace('/.*_of_/', '', $type);
$constructor = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['predicate']);
$php_constructor = preg_replace('/.*_of_/', '', $constructor);
$type = \str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
$php_type = \preg_replace('/.*_of_/', '', $type);
$constructor = \str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['predicate']);
$php_constructor = \preg_replace('/.*_of_/', '', $constructor);
if (!isset($this->types[$php_type])) {
$this->types[$php_type] = ['constructors' => [], 'methods' => []];
}
if (!in_array($data, $this->types[$php_type]['constructors'])) {
if (!\in_array($data, $this->types[$php_type]['constructors'])) {
$this->types[$php_type]['constructors'][] = $data;
}
$params = '';
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'])) {
continue;
}
if ($type === 'EncryptedMessage' && $param['name'] === 'bytes' && !isset($this->settings['td'])) {
@ -64,19 +64,19 @@ trait Constructors
$param['type'] = 'DecryptedMessage';
}
$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';
$param[$type_or_subtype] = str_replace(['.', 'true', 'false'], ['_', 'Bool', 'Bool'], $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'];
$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]);
if (\preg_match('/%/', $param[$type_or_subtype])) {
$param[$type_or_subtype] = $this->constructors->find_by_type(\str_replace('%', '', $param[$type_or_subtype]))['predicate'];
}
if (substr($param[$type_or_subtype], -1) === '>') {
$param[$type_or_subtype] = substr($param[$type_or_subtype], 0, -1);
if (\substr($param[$type_or_subtype], -1) === '>') {
$param[$type_or_subtype] = \substr($param[$type_or_subtype], 0, -1);
}
$params .= "'".$param['name']."' => ";
$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]).', ';
}
$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>
';
@ -105,30 +105,30 @@ trait Constructors
$hasreplymarkup = false;
$hasentities = false;
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'])) {
continue;
}
if ($type === 'EncryptedMessage' && $param['name'] === 'bytes' && !isset($this->settings['td'])) {
$param['name'] = 'decrypted_message';
$param['type'] = 'DecryptedMessage';
}
if ($type === 'DecryptedMessageMedia' && in_array($param['name'], ['key', 'iv'])) {
if ($type === 'DecryptedMessageMedia' && \in_array($param['name'], ['key', 'iv'])) {
unset(\danog\MadelineProto\Lang::$lang['en']['object_'.$data['predicate'].'_param_'.$param['name'].'_type_'.$param['type']]);
continue;
}
$ptype = str_replace('.', '_', $param[isset($param['subtype']) ? 'subtype' : 'type']);
$ptype = \str_replace('.', '_', $param[isset($param['subtype']) ? 'subtype' : 'type']);
//$type_or_bare_type = 'types';
/*if (isset($param['subtype'])) {
if ($param['type'] === 'vector') {
$type_or_bare_type = 'constructors';
}
}*/
if (preg_match('/%/', $ptype)) {
$ptype = $this->constructors->find_by_type(str_replace('%', '', $ptype))['predicate'];
if (\preg_match('/%/', $ptype)) {
$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';
if (substr($ptype, -1) === '>') {
$ptype = substr($ptype, 0, -1);
$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) === '>') {
$ptype = \substr($ptype, 0, -1);
}
switch ($ptype) {
case 'true':
@ -136,25 +136,25 @@ trait Constructors
$ptype = 'Bool';
}
$human_ptype = $ptype;
if (strpos($type, 'Input') === 0 && in_array($ptype, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'InputPeer']) && !isset($this->settings['td'])) {
if (\strpos($type, 'Input') === 0 && \in_array($ptype, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'InputPeer']) && !isset($this->settings['td'])) {
$human_ptype = 'Username, chat ID, Update, Message or '.$ptype;
}
if (strpos($type, 'Input') === 0 && in_array($ptype, ['InputMedia', 'InputDocument', 'InputPhoto']) && !isset($this->settings['td'])) {
if (\strpos($type, 'Input') === 0 && \in_array($ptype, ['InputMedia', 'InputDocument', 'InputPhoto']) && !isset($this->settings['td'])) {
$human_ptype = 'MessageMedia, Message, Update or '.$ptype;
}
if (in_array($ptype, ['InputMessage']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputMessage']) && !isset($this->settings['td'])) {
$human_ptype = 'Message ID or '.$ptype;
}
if (in_array($ptype, ['InputEncryptedChat']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputEncryptedChat']) && !isset($this->settings['td'])) {
$human_ptype = 'Secret chat ID, Update, EncryptedMessage or '.$ptype;
}
if (in_array($ptype, ['InputFile']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputFile']) && !isset($this->settings['td'])) {
$human_ptype = 'File path or '.$ptype;
}
if (in_array($ptype, ['InputEncryptedFile']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputEncryptedFile']) && !isset($this->settings['td'])) {
$human_ptype = 'File path or '.$ptype;
}
$table .= '|'.str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || $this->constructors->find_by_predicate(lcfirst($param['type']).'Empty') || ($data['type'] === 'InputMedia' && $param['name'] === 'mime_type') || ($data['type'] === 'DocumentAttribute' && in_array($param['name'], ['w', 'h', 'duration'])) ? 'Optional' : 'Yes').'|';
$table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || $this->constructors->find_by_predicate(\lcfirst($param['type']).'Empty') || ($data['type'] === 'InputMedia' && $param['name'] === 'mime_type') || ($data['type'] === 'DocumentAttribute' && \in_array($param['name'], ['w', 'h', 'duration'])) ? 'Optional' : 'Yes').'|';
if (!isset($this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']])) {
$this->add_to_lang('object_'.$data['predicate'].'_param_'.$param['name'].'_type_'.$param['type']);
@ -166,9 +166,9 @@ trait Constructors
$table .= $this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']].'|';
}
$table .= PHP_EOL;
$pptype = in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype;
$ppptype = in_array($ptype, ['string']) ? '"'.$ptype.'"' : $ptype;
$ppptype = in_array($ptype, ['bytes']) ? '{"_": "bytes", "bytes":"base64 encoded '.$ptype.'"}' : $ppptype;
$pptype = \in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype;
$ppptype = \in_array($ptype, ['string']) ? '"'.$ptype.'"' : $ptype;
$ppptype = \in_array($ptype, ['bytes']) ? '{"_": "bytes", "bytes":"base64 encoded '.$ptype.'"}' : $ppptype;
$params .= ", '".$param['name']."' => ";
$params .= isset($param['subtype']) ? '['.$pptype.', '.$pptype.']' : $pptype;
$lua_params .= ', '.$param['name'].'=';
@ -187,7 +187,7 @@ title: '.$data['predicate'].'
description: '.$description.'
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
---
# Constructor: '.str_replace('_', '\\_', $data['predicate'].$layer).'
# Constructor: '.\str_replace('_', '\\_', $data['predicate'].$layer).'
[Back to constructors index](index.md)
@ -200,7 +200,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
if (isset($this->td_descriptions['constructors'][$data['predicate']])) {
$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)
';
@ -266,19 +266,19 @@ 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);
}
$this->logger->logger('Generating constructors index...', \danog\MadelineProto\Logger::NOTICE);
ksort($this->docs_constructors);
\ksort($this->docs_constructors);
$last_namespace = '';
foreach ($this->docs_constructors as $constructor => &$value) {
$new_namespace = preg_replace('/_.*/', '', $constructor);
$new_namespace = \preg_replace('/_.*/', '', $constructor);
$br = $new_namespace != $last_namespace ? '***
<br><br>' : '';
$value = $br.$value;
$last_namespace = $new_namespace;
}
file_put_contents('constructors/'.$this->index, '---
\file_put_contents('constructors/'.$this->index, '---
title: Constructors
description: List of constructors
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -286,6 +286,6 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
# Constructors
[Back to API documentation index](..)
'.implode('', $this->docs_constructors));
'.\implode('', $this->docs_constructors));
}
}

View File

@ -24,9 +24,13 @@ trait Methods
public function mk_methods()
{
static $bots;
if (!$bots) $bots = json_decode(file_get_contents('https://rpc.madelineproto.xyz/bot.json'), true)['result'];
if (!$bots) {
$bots = \json_decode(\file_get_contents('https://rpc.madelineproto.xyz/bot.json'), true)['result'];
}
static $errors;
if (!$errors) $errors = json_decode(file_get_contents('https://rpc.madelineproto.xyz/v1.json'), true);
if (!$errors) {
$errors = \json_decode(\file_get_contents('https://rpc.madelineproto.xyz/v1.json'), true);
}
$new = ['result' => []];
foreach ($errors['result'] as $code => $suberrors) {
foreach ($suberrors as $method => $suberrors) {
@ -38,30 +42,30 @@ trait Methods
}
}
}
foreach (glob('methods/'.$this->any) as $unlink) {
unlink($unlink);
foreach (\glob('methods/'.$this->any) as $unlink) {
\unlink($unlink);
}
if (file_exists('methods')) {
rmdir('methods');
if (\file_exists('methods')) {
\rmdir('methods');
}
mkdir('methods');
\mkdir('methods');
$this->docs_methods = [];
$this->human_docs_methods = [];
$this->logger->logger('Generating methods documentation...', \danog\MadelineProto\Logger::NOTICE);
foreach ($this->methods->by_id as $id => $data) {
$method = str_replace('.', '_', $data['method']);
$php_method = str_replace('.', '->', $data['method']);
$type = str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
$php_type = preg_replace('/.*_of_/', '', $type);
$method = \str_replace('.', '_', $data['method']);
$php_method = \str_replace('.', '->', $data['method']);
$type = \str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']);
$php_type = \preg_replace('/.*_of_/', '', $type);
if (!isset($this->types[$php_type])) {
$this->types[$php_type] = ['methods' => [], 'constructors' => []];
}
if (!in_array($data, $this->types[$php_type]['methods'])) {
if (!\in_array($data, $this->types[$php_type]['methods'])) {
$this->types[$php_type]['methods'][] = $data;
}
$params = '';
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'])) {
continue;
}
if ($param['name'] === 'data' && $type === 'messages_SentEncryptedMessage' && !isset($this->settings['td'])) {
@ -72,8 +76,8 @@ trait Methods
$param['type'] = 'InputPeer';
}
$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';
$param[$type_or_subtype] = str_replace(['.', 'true', 'false'], ['_', 'Bool', 'Bool'], $param[$type_or_subtype]);
$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] = '['.$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]).', ';
}
@ -85,15 +89,15 @@ trait Methods
}
}
$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>
';
/*
if (!isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']]) && isset($this->td_descriptions['methods'][$data['method']])) {
$this->human_docs_methods[$this->td_descriptions['methods'][$data['method']]['description'].': '.$data['method']] = '* <a href="'.$method.'.html" name="'.$method.'">'.$this->td_descriptions['methods'][$data['method']]['description'].': '.$data['method'].'</a>
';
}*/
/*
if (!isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']]) && isset($this->td_descriptions['methods'][$data['method']])) {
$this->human_docs_methods[$this->td_descriptions['methods'][$data['method']]['description'].': '.$data['method']] = '* <a href="'.$method.'.html" name="'.$method.'">'.$this->td_descriptions['methods'][$data['method']]['description'].': '.$data['method'].'</a>
';
}*/
$params = '';
$lua_params = '';
$pwr_params = '';
@ -114,7 +118,7 @@ trait Methods
$hasreplymarkup = false;
$hasmessage = false;
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'])) {
continue;
}
if ($param['name'] === 'data' && $type === 'messages_SentEncryptedMessage' && !isset($this->settings['td'])) {
@ -129,32 +133,32 @@ trait Methods
$param['type'] = 'Vector t';
$param['subtype'] = 'int';
}
$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) {
case 'true':
case 'false':
$ptype = 'Bool';
}
$human_ptype = $ptype;
if (in_array($ptype, ['InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer']) && !isset($this->settings['td'])) {
$human_ptype = 'Username, chat ID, Update, Message or '.$ptype;
}
if (in_array($ptype, ['InputMedia', 'InputPhoto', 'InputDocument']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputMedia', 'InputPhoto', 'InputDocument']) && !isset($this->settings['td'])) {
$human_ptype = 'MessageMedia, Update, Message or '.$ptype;
}
if (in_array($ptype, ['InputMessage']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputMessage']) && !isset($this->settings['td'])) {
$human_ptype = 'Message ID or '.$ptype;
}
if (in_array($ptype, ['InputEncryptedChat']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputEncryptedChat']) && !isset($this->settings['td'])) {
$human_ptype = 'Secret chat ID, Update, EncryptedMessage or '.$ptype;
}
if (in_array($ptype, ['InputFile']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputFile']) && !isset($this->settings['td'])) {
$human_ptype = 'File path or '.$ptype;
}
if (in_array($ptype, ['InputEncryptedFile']) && !isset($this->settings['td'])) {
if (\in_array($ptype, ['InputEncryptedFile']) && !isset($this->settings['td'])) {
$human_ptype = 'File path or '.$ptype;
}
$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';
if (!isset($this->td_descriptions['methods'][$data['method']]['params'][$param['name']])) {
$this->add_to_lang('method_'.$data['method'].'_param_'.$param['name'].'_type_'.$param['type']);
if (isset($this->td_descriptions['methods'][$data['method']]['description'])) {
@ -163,14 +167,14 @@ trait Methods
}
if (isset($this->td_descriptions['methods'][$data['method']])) {
$table .= '|'.str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.$this->td_descriptions['methods'][$data['method']]['params'][$param['name']].' | '.(isset($param['pow']) || (($id = $this->constructors->find_by_predicate(lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->constructors->find_by_predicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|';
$table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.$this->td_descriptions['methods'][$data['method']]['params'][$param['name']].' | '.(isset($param['pow']) || (($id = $this->constructors->find_by_predicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->constructors->find_by_predicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|';
} else {
$table .= '|'.str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || (($id = $this->constructors->find_by_predicate(lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->constructors->find_by_predicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|';
$table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || (($id = $this->constructors->find_by_predicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->constructors->find_by_predicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|';
}
$table .= PHP_EOL;
$pptype = in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype;
$ppptype = in_array($ptype, ['string']) ? '"'.$ptype.'"' : $ptype;
$ppptype = in_array($ptype, ['bytes']) ? '{"_": "bytes", "bytes":"base64 encoded '.$ptype.'"}' : $ppptype;
$pptype = \in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype;
$ppptype = \in_array($ptype, ['string']) ? '"'.$ptype.'"' : $ptype;
$ppptype = \in_array($ptype, ['bytes']) ? '{"_": "bytes", "bytes":"base64 encoded '.$ptype.'"}' : $ppptype;
$params .= "'".$param['name']."' => ";
$params .= (isset($param['subtype']) ? '['.$pptype.', '.$pptype.']' : $pptype).', ';
@ -200,17 +204,17 @@ title: '.$data['method'].'
description: '.$description.'
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
---
# Method: '.str_replace('_', '\\_', $data['method']).'
# Method: '.\str_replace('_', '\\_', $data['method']).'
[Back to methods index](index.md)
';
/*
if (isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']])) {
$header .= '**'.\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']]."**\n\n\n\n\n";
file_put_contents('methods/'.$method.'.md', $header);
continue;
}*/
/*
if (isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']])) {
$header .= '**'.\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$data['method']]."**\n\n\n\n\n";
file_put_contents('methods/'.$method.'.md', $header);
continue;
}*/
if ($this->td) {
$header .= 'YOU CANNOT USE THIS METHOD IN MADELINEPROTO
@ -221,14 +225,14 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
$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 = '';
if (!isset($this->settings['td'])) {
$example .= '### Can bots use this method: **'.($bot ? 'YES' : 'NO')."**\n\n\n";
$example .= str_replace('[]', '', '### MadelineProto Example ([now async for huge speed and parallelism!](https://docs.madelineproto.xyz/docs/ASYNC.html)):
$example .= \str_replace('[]', '', '### MadelineProto Example ([now async for huge speed and parallelism!](https://docs.madelineproto.xyz/docs/ASYNC.html)):
```php
@ -263,7 +267,7 @@ You can provide bot API reply_markup objects here.
$example .= '
## 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.
';
@ -320,21 +324,21 @@ MadelineProto supports all html entities supported by [html_entity_decode](http:
$example .= "\n\n";
}
}
file_put_contents('methods/'.$method.'.md', $header.$table.$return.$example);
\file_put_contents('methods/'.$method.'.md', $header.$table.$return.$example);
}
$this->logger->logger('Generating methods index...', \danog\MadelineProto\Logger::NOTICE);
ksort($this->docs_methods);
ksort($this->human_docs_methods);
\ksort($this->docs_methods);
\ksort($this->human_docs_methods);
$last_namespace = '';
foreach ($this->docs_methods as $method => &$value) {
$new_namespace = preg_replace('/_.*/', '', $method);
$new_namespace = \preg_replace('/_.*/', '', $method);
$br = $new_namespace != $last_namespace ? '***
<br><br>
' : '';
$value = $br.$value;
$last_namespace = $new_namespace;
}
file_put_contents('methods/api_'.$this->index, '---
\file_put_contents('methods/api_'.$this->index, '---
title: Methods
description: List of methods
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -370,9 +374,9 @@ $MadelineProto->[request_call](https://docs.madelineproto.xyz/request_call.html)
$MadelineProto->[request_secret_chat](https://docs.madelineproto.xyz/request_secret_chat.html)($id);
'.implode('', $this->docs_methods));
'.\implode('', $this->docs_methods));
file_put_contents('methods/'.$this->index, '---
\file_put_contents('methods/'.$this->index, '---
title: Methods
description: What do you want to do?
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
@ -404,6 +408,6 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
* [Create a secret chat bot](https://docs.madelineproto.xyz/docs/SECRET_CHATS.html)
'.implode('', $this->human_docs_methods));
'.\implode('', $this->human_docs_methods));
}
}

View File

@ -23,7 +23,9 @@ class EventHandler extends APIFactory
{
public function __construct($MadelineProto)
{
if (!$MadelineProto) return;
if (!$MadelineProto) {
return;
}
$this->API = $MadelineProto->API;
$this->async = &$MadelineProto->async;
$this->methods = &$MadelineProto->methods;

View File

@ -39,18 +39,18 @@ class Exception extends \Exception
$this->line = $line;
}
parent::__construct($message, $code, $previous);
if (strpos($message, 'socket_accept') === false) {
\danog\MadelineProto\Logger::log($message.' in '.basename($this->file).':'.$this->line, \danog\MadelineProto\Logger::FATAL_ERROR);
if (\strpos($message, 'socket_accept') === false) {
\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;
}
if (strpos($message, 'pg_query') !== false || strpos($message, 'Undefined variable: ') !== false || strpos($message, 'socket_write') !== false || strpos($message, 'socket_read') !== false || strpos($message, 'Received request to switch to DC ') !== false || strpos($message, "Couldn't get response") !== false || strpos($message, 'Re-executing query...') !== false || strpos($message, "Couldn't find peer by provided") !== false || strpos($message, 'id.pwrtelegram.xyz') !== false || strpos($message, 'Please update ') !== false || strpos($message, 'posix_isatty') !== false) {
if (\strpos($message, 'pg_query') !== false || \strpos($message, 'Undefined variable: ') !== false || \strpos($message, 'socket_write') !== false || \strpos($message, 'socket_read') !== false || \strpos($message, 'Received request to switch to DC ') !== false || \strpos($message, "Couldn't get response") !== false || \strpos($message, 'Re-executing query...') !== false || \strpos($message, "Couldn't find peer by provided") !== false || \strpos($message, 'id.pwrtelegram.xyz') !== false || \strpos($message, 'Please update ') !== false || \strpos($message, 'posix_isatty') !== false) {
return;
}
if (self::$rollbar && class_exists('\\Rollbar\\Rollbar')) {
\Rollbar\Rollbar::log(\Rollbar\Payload\Level::error(), $this, debug_backtrace(0));
if (self::$rollbar && \class_exists('\\Rollbar\\Rollbar')) {
\Rollbar\Rollbar::log(\Rollbar\Payload\Level::error(), $this, \debug_backtrace(0));
}
}
@ -63,7 +63,7 @@ class Exception extends \Exception
$additional = 'Follow the instructions @ https://prime.madelineproto.xyz to install it.';
}
$message = 'MadelineProto requires the '.$extensionName.' extension to run. '.$additional;
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
echo $message.'<br>';
}
$file = 'MadelineProto';
@ -78,7 +78,7 @@ class Exception extends \Exception
public static function ExceptionErrorHandler($errno = 0, $errstr = null, $errfile = null, $errline = null)
{
// If error is suppressed with @, don't throw an exception
if (error_reporting() === 0 || strpos($errstr, 'headers already sent') || ($errfile && strpos($errfile, 'vendor/amphp') !== false)) {
if (\error_reporting() === 0 || \strpos($errstr, 'headers already sent') || ($errfile && \strpos($errfile, 'vendor/amphp') !== false)) {
return false;
}

View File

@ -1,6 +1,6 @@
<?php
/**
* Lang module
* Lang module.
*
* This file is part of MadelineProto.
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@ -19,9 +19,9 @@ namespace danog\MadelineProto;
class Lang
{
public static $lang = array (
'it' =>
array (
public static $lang = [
'it' =>
[
'phpseclib_fork' => 'Per favore installa questo fork di phpseclib: https://github.com/danog/phpseclib',
'inst_dc' => 'Istanziamento dei DataCenter...',
'load_rsa' => 'Caricamento delle chiavi RSA...',
@ -161,9 +161,9 @@ class Lang
'done' => 'Fatto!',
'cdn_reupload' => 'Il file non è disponibile sul nostro CDN, richiedo la copia!',
'stored_on_cdn' => 'Il file è scaricabile tramite CDN!',
),
'en' =>
array (
],
'en' =>
[
'req_pq' => 'Requesting pq...',
'done' => 'Done!',
'cdn_reupload' => 'File is not stored on CDN, requesting reupload!',
@ -5157,11 +5157,11 @@ class Lang
'object_channelAdminLogEventActionToggleSlowMode_param_new_value_type_int' => 'New value',
'object_codeSettings_param_allow_app_hash_type_true' => 'Whether to allow a persistent app hash',
'object_channelFull_param_slowmode_next_send_date_type_int' => ' Indicates when the user will be allowed to send another message in the supergroup (unixdate)',
),
);
],
];
// THIS WILL BE OVERWRITTEN BY $lang["en"]
public static $current_lang = array (
public static $current_lang = [
'req_pq' => 'Requesting pq...',
'done' => 'Done!',
'cdn_reupload' => 'File is not stored on CDN, requesting reupload!',
@ -10155,5 +10155,5 @@ class Lang
'object_channelAdminLogEventActionToggleSlowMode_param_new_value_type_int' => 'New value',
'object_codeSettings_param_allow_app_hash_type_true' => 'Whether to allow a persistent app hash',
'object_channelFull_param_slowmode_next_send_date_type_int' => ' Indicates when the user will be allowed to send another message in the supergroup (unixdate)',
);
}
];
}

View File

@ -61,7 +61,7 @@ class Logger
const CALLABLE_LOGGER = 4;
/**
* Construct global logger
* Construct global logger.
*
* @param [type] $mode
* @param [type] $optional
@ -75,19 +75,20 @@ class Logger
self::$default = new self($mode, $optional, $prefix, $level, $max_size);
}
/**
* Construct global static logger from MadelineProto settings
* Construct global static logger from MadelineProto settings.
*
* @param array $settings
* @return void
*/
public static function constructorFromSettings(array $settings) {
public static function constructorFromSettings(array $settings)
{
if (!self::$default) {
// The getLogger function will automatically init the static logger, but we'll do it again anyway
self::$default = self::getLoggerFromSettings(MTProto::getSettings($settings));
}
}
/**
* Get logger from MadelineProto settings
* Get logger from MadelineProto settings.
*
* @param array $settings
* @param string $prefix Optional prefix
@ -95,8 +96,8 @@ class Logger
*/
public static function getLoggerFromSettings(array $settings, string $prefix = ''): self
{
if (isset($settings['logger']['rollbar_token']) && $settings['logger']['rollbar_token'] !== '' && class_exists('\\Rollbar\\Rollbar')) {
@\Rollbar\Rollbar::init(['environment' => 'production', 'root' => __DIR__, 'access_token' => isset($settings['logger']['rollbar_token']) && !in_array($settings['logger']['rollbar_token'], ['f9fff6689aea4905b58eec73f66c791d', '300afd7ccef346ea84d0c185ae831718', '11a8c2fe4c474328b40a28193f8d63f5', 'beef2d426496462ba34dcaad33d44a14']) || $settings['pwr']['pwr'] ? $settings['logger']['rollbar_token'] : 'c07d9b2f73c2461297b0beaef6c1662f'], false, false);
if (isset($settings['logger']['rollbar_token']) && $settings['logger']['rollbar_token'] !== '' && \class_exists('\\Rollbar\\Rollbar')) {
@\Rollbar\Rollbar::init(['environment' => 'production', 'root' => __DIR__, 'access_token' => isset($settings['logger']['rollbar_token']) && !\in_array($settings['logger']['rollbar_token'], ['f9fff6689aea4905b58eec73f66c791d', '300afd7ccef346ea84d0c185ae831718', '11a8c2fe4c474328b40a28193f8d63f5', 'beef2d426496462ba34dcaad33d44a14']) || $settings['pwr']['pwr'] ? $settings['logger']['rollbar_token'] : 'c07d9b2f73c2461297b0beaef6c1662f'], false, false);
} else {
Exception::$rollbar = false;
RPCErrorException::$rollbar = false;
@ -104,8 +105,8 @@ class Logger
if (!isset($settings['logger']['logger_param']) && isset($settings['logger']['param'])) {
$settings['logger']['logger_param'] = $settings['logger']['param'];
}
if (php_sapi_name() !== 'cli') {
if (isset($settings['logger']['logger_param']) && basename($settings['logger']['logger_param']) === 'MadelineProto.log') {
if (PHP_SAPI !== 'cli') {
if (isset($settings['logger']['logger_param']) && \basename($settings['logger']['logger_param']) === 'MadelineProto.log') {
$settings['logger']['logger_param'] = Magic::$script_cwd.'/MadelineProto.log';
}
}
@ -115,12 +116,12 @@ class Logger
self::$default = $logger;
}
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
try {
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', Magic::$script_cwd.'/MadelineProto.log');
error_log('Enabled PHP logging');
\error_reporting(E_ALL);
\ini_set('log_errors', 1);
\ini_set('error_log', Magic::$script_cwd.'/MadelineProto.log');
\error_log('Enabled PHP logging');
} catch (\danog\MadelineProto\Exception $e) {
$logger->logger('Could not enable PHP logging');
}
@ -138,39 +139,39 @@ class Logger
$this->prefix = $prefix === '' ? '' : ', '.$prefix;
$this->level = $level;
if ($this->mode === 2 && !file_exists(pathinfo($this->optional, PATHINFO_DIRNAME))) {
if ($this->mode === 2 && !\file_exists(\pathinfo($this->optional, PATHINFO_DIRNAME))) {
$this->optional = Magic::$script_cwd.'/MadelineProto.log';
}
if ($this->mode === 2 && !preg_match('/\.log$/', $this->optional)) {
if ($this->mode === 2 && !\preg_match('/\.log$/', $this->optional)) {
$this->optional .= '.log';
}
if ($mode === 2 && $max_size !== -1 && file_exists($this->optional) && filesize($this->optional) > $max_size) {
unlink($this->optional);
if ($mode === 2 && $max_size !== -1 && \file_exists($this->optional) && \filesize($this->optional) > $max_size) {
\unlink($this->optional);
}
$this->colors[self::ULTRA_VERBOSE] = implode(';', [self::FOREGROUND['light_gray'], self::SET['dim']]);
$this->colors[self::VERBOSE] = implode(';', [self::FOREGROUND['green'], self::SET['bold']]);
$this->colors[self::NOTICE] = implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]);
$this->colors[self::WARNING] = implode(';', [self::FOREGROUND['white'], self::SET['dim'], self::BACKGROUND['red']]);
$this->colors[self::ERROR] = implode(';', [self::FOREGROUND['white'], self::SET['bold'], self::BACKGROUND['red']]);
$this->colors[self::FATAL_ERROR] = implode(';', [self::FOREGROUND['red'], self::SET['bold'], self::BACKGROUND['light_gray']]);
$this->colors[self::ULTRA_VERBOSE] = \implode(';', [self::FOREGROUND['light_gray'], self::SET['dim']]);
$this->colors[self::VERBOSE] = \implode(';', [self::FOREGROUND['green'], self::SET['bold']]);
$this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]);
$this->colors[self::WARNING] = \implode(';', [self::FOREGROUND['white'], self::SET['dim'], self::BACKGROUND['red']]);
$this->colors[self::ERROR] = \implode(';', [self::FOREGROUND['white'], self::SET['bold'], self::BACKGROUND['red']]);
$this->colors[self::FATAL_ERROR] = \implode(';', [self::FOREGROUND['red'], self::SET['bold'], self::BACKGROUND['light_gray']]);
$this->newline = PHP_EOL;
if ($this->mode === 3) {
$this->stdout = getStdout();
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
$this->newline = '<br>'.$this->newline;
}
} elseif ($this->mode === 2) {
$this->stdout = new ResourceOutputStream(fopen($this->optional, 'a+'));
$this->stdout = new ResourceOutputStream(\fopen($this->optional, 'a+'));
} elseif ($this->mode === 1) {
$result = @ini_get('error_log');
$result = @\ini_get('error_log');
if ($result === 'syslog') {
$this->stdout = getStderr();
} elseif ($result) {
$this->stdout = new ResourceOutputStream(fopen($result, 'a+'));
$this->stdout = new ResourceOutputStream(\fopen($result, 'a+'));
} else {
$this->stdout = getStderr();
}
@ -179,8 +180,8 @@ class Logger
public static function log($param, $level = self::NOTICE)
{
if (!is_null(self::$default)) {
self::$default->logger($param, $level, basename(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php'));
if (!\is_null(self::$default)) {
self::$default->logger($param, $level, \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php'));
} else {
echo $param.PHP_EOL;
}
@ -193,35 +194,35 @@ class Logger
}
if (!self::$printed) {
self::$printed = true;
$this->colors[self::NOTICE] = implode(';', [self::FOREGROUND['light_gray'], self::SET['bold'], self::BACKGROUND['blue']]);
$this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['light_gray'], self::SET['bold'], self::BACKGROUND['blue']]);
$this->logger('MadelineProto');
$this->logger('Copyright (C) 2016-2019 Daniil Gentili');
$this->logger('Licensed under AGPLv3');
$this->logger('https://github.com/danog/MadelineProto');
$this->colors[self::NOTICE] = implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]);
$this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]);
}
if ($this->mode === 4) {
return call_user_func_array($this->optional, [$param, $level]);
return \call_user_func_array($this->optional, [$param, $level]);
}
$prefix = $this->prefix;
if (\danog\MadelineProto\Magic::$has_thread && is_object(\Thread::getCurrentThread())) {
if (\danog\MadelineProto\Magic::$has_thread && \is_object(\Thread::getCurrentThread())) {
$prefix .= ' (t)';
}
if ($param instanceof \Throwable) {
$param = (string) $param;
} elseif (!is_string($param)) {
$param = json_encode($param, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
} elseif (!\is_string($param)) {
$param = \json_encode($param, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
if ($file === null) {
$file = basename(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
$file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
}
$param = str_pad($file.$prefix.': ', 16 + strlen($prefix))."\t".$param;
$param = \str_pad($file.$prefix.': ', 16 + \strlen($prefix))."\t".$param;
switch ($this->mode) {
case 1:
if ($this->stdout->write($param.$this->newline) instanceof Failure) {
error_log($param);
\error_log($param);
}
break;
default:
@ -229,7 +230,7 @@ class Logger
if ($this->stdout->write($param) instanceof Failure) {
switch ($this->mode) {
case 3: echo $param; break;
case 2: file_put_contents($this->optional, $param, FILE_APPEND); break;
case 2: \file_put_contents($this->optional, $param, FILE_APPEND); break;
}
}
break;

View File

@ -109,7 +109,7 @@ class ReadLoop extends SignalLoop
} elseif ($error === 0) {
$API->logger->logger("Got NOOP from DC {$datacenter}", \danog\MadelineProto\Logger::WARNING);
yield $connection->reconnect();
} else if ($error === -429) {
} elseif ($error === -429) {
$API->logger->logger("Got -429 from DC {$datacenter}", \danog\MadelineProto\Logger::WARNING);
Loop::delay(1*1000, [$connection, 'reconnect']);
} else {

View File

@ -36,7 +36,7 @@ abstract class Loop implements LoopInterface
private $count = 0;
/**
* MTProto instance
* MTProto instance.
*
* @var \danog\MadelineProto\MTProto
*/

View File

@ -39,17 +39,16 @@ abstract class ResumableSignalLoop extends SignalLoop implements ResumableLoopIn
public function pause($time = null): Promise
{
if (!is_null($time)) {
if (!\is_null($time)) {
if ($time <= 0) {
return new Success(0);
} else {
$resume = microtime(true) + $time;
if ($this->resumeWatcher) {
Loop::cancel($this->resumeWatcher);
$this->resumeWatcher = null;
}
$this->resumeWatcher = Loop::delay($time * 1000, [$this, 'resume'], $resume);
}
$resume = \microtime(true) + $time;
if ($this->resumeWatcher) {
Loop::cancel($this->resumeWatcher);
$this->resumeWatcher = null;
}
$this->resumeWatcher = Loop::delay($time * 1000, [$this, 'resume'], $resume);
}
$this->resume = new Deferred();

View File

@ -33,7 +33,7 @@ class FeedLoop extends ResumableSignalLoop
private $parsedUpdates = [];
private $channelId;
/**
* Update loop
* Update loop.
*
* @var UpdateLoop
*/
@ -94,9 +94,9 @@ class FeedLoop extends ResumableSignalLoop
public function parse($updates)
{
reset($updates);
\reset($updates);
while ($updates) {
$key = key($updates);
$key = \key($updates);
$update = $updates[$key];
unset($updates[$key]);
if ($update['_'] === 'updateChannelTooLong') {
@ -124,11 +124,11 @@ class FeedLoop extends ResumableSignalLoop
$logger('PTS hole');
$this->updater->setLimit($this->state->pts() + $result);
yield $this->updater->resume();
$updates = array_merge($this->incomingUpdates, $updates);
$updates = \array_merge($this->incomingUpdates, $updates);
$this->incomingUpdates = [];
continue;
}
if (isset($update['message']['id'], $update['message']['to_id']) && !in_array($update['_'], ['updateEditMessage', 'updateEditChannelMessage', 'updateMessageID'])) {
if (isset($update['message']['id'], $update['message']['to_id']) && !\in_array($update['_'], ['updateEditMessage', 'updateEditChannelMessage', 'updateMessageID'])) {
if (!$this->API->check_msg_id($update['message'])) {
$logger('MSGID duplicate');
@ -214,7 +214,7 @@ class FeedLoop extends ResumableSignalLoop
}
if ($to) {
$log .= 'to_id '.json_encode($update['message']['to_id']).', ';
$log .= 'to_id '.\json_encode($update['message']['to_id']).', ';
}
if ($via_bot) {
@ -222,7 +222,7 @@ class FeedLoop extends ResumableSignalLoop
}
if ($entities) {
$log .= 'entities '.json_encode($update['message']['entities']).', ';
$log .= 'entities '.\json_encode($update['message']['entities']).', ';
}
$this->API->logger->logger("Not enough data: for message update $log, getting difference...", \danog\MadelineProto\Logger::VERBOSE);
@ -230,7 +230,6 @@ class FeedLoop extends ResumableSignalLoop
if ($channelId && $to) {
$channelId = false;
}
}
break;
default:
@ -244,7 +243,7 @@ class FeedLoop extends ResumableSignalLoop
if ($channelId !== $this->channelId) {
if (isset($this->API->feeders[$channelId])) {
return yield $this->API->feeders[$channelId]->feedSingle($update);
} else if ($this->channelId) {
} elseif ($this->channelId) {
return yield $this->API->feeders[false]->feedSingle($update);
}
}

View File

@ -72,8 +72,8 @@ class SeqLoop extends ResumableSignalLoop
$updates = null;
}
while ($this->pendingWakeups) {
reset($this->pendingWakeups);
$channelId = key($this->pendingWakeups);
\reset($this->pendingWakeups);
$channelId = \key($this->pendingWakeups);
unset($this->pendingWakeups[$channelId]);
$this->API->feeders[$channelId]->resume();
}
@ -82,10 +82,10 @@ class SeqLoop extends ResumableSignalLoop
public function parse($updates)
{
reset($updates);
\reset($updates);
while ($updates) {
$options = [];
$key = key($updates);
$key = \key($updates);
$update = $updates[$key];
unset($updates[$key]);
@ -100,7 +100,7 @@ class SeqLoop extends ResumableSignalLoop
if (!$this->incomingUpdates) {
yield $this->API->updaters[false]->resume();
}
$this->incomingUpdates = array_merge($this->incomingUpdates, [$update], $updates);
$this->incomingUpdates = \array_merge($this->incomingUpdates, [$update], $updates);
continue;
}

View File

@ -84,10 +84,10 @@ class UpdateLoop extends ResumableSignalLoop
try {
$difference = yield $API->method_call_async_read('updates.getChannelDifference', ['channel' => 'channel#'.$this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true], ['datacenter' => $API->datacenter->curdc, 'postpone' => $first]);
} catch (RPCErrorException $e) {
if (in_array($e->rpc, ['CHANNEL_PRIVATE', 'CHAT_FORBIDDEN'])) {
if (\in_array($e->rpc, ['CHANNEL_PRIVATE', 'CHAT_FORBIDDEN'])) {
$feeder->signal(true);
unset($API->updaters[$this->channelId]);
unset($API->feeders[$this->channelId]);
unset($API->updaters[$this->channelId], $API->feeders[$this->channelId]);
$API->getChannelStates()->remove($this->channelId);
$API->logger->logger("Channel private, exiting $this");
@ -95,11 +95,11 @@ class UpdateLoop extends ResumableSignalLoop
}
throw $e;
} catch (Exception $e) {
if (in_array($e->getMessage(), ['This peer is not present in the internal peer database'])) {
if (\in_array($e->getMessage(), ['This peer is not present in the internal peer database'])) {
$feeder->signal(true);
$API->getChannelStates()->remove($this->channelId);
unset($API->updaters[$this->channelId]);
unset($API->feeders[$this->channelId]);
unset($API->updaters[$this->channelId], $API->feeders[$this->channelId]);
$API->logger->logger("Channel private, exiting $this");
return true;
@ -144,7 +144,7 @@ class UpdateLoop extends ResumableSignalLoop
unset($difference);
break;
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));
}
} else {
$API->logger->logger('Resumed and fetching normal difference...', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
@ -187,7 +187,7 @@ class UpdateLoop extends ResumableSignalLoop
unset($difference);
break;
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));
}
}
}

View File

@ -28,7 +28,7 @@ class Lua
public function __magic_construct($script, $MadelineProto)
{
if (!file_exists($script)) {
if (!\file_exists($script)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['script_not_exist']);
}
$this->MadelineProto = $MadelineProto;
@ -51,12 +51,12 @@ class Lua
$this->Lua->registerCallback('tdcli_function', [$this, 'tdcli_function']);
$this->Lua->registerCallback('madeline_function', [$this, 'madeline_function']);
$this->Lua->registerCallback('var_dump', 'var_dump');
foreach (get_class_methods($this->MadelineProto->API) as $method) {
foreach (\get_class_methods($this->MadelineProto->API) as $method) {
$this->Lua->registerCallback($method, [$this->MadelineProto, $method]);
}
$methods = [];
foreach ($this->MadelineProto->get_methods_namespaced() as $pair) {
$namespace = key($pair);
$namespace = \key($pair);
$method = $pair[$namespace];
if ($namespace === 'upload') {
continue;
@ -64,7 +64,7 @@ class Lua
$methods[$namespace][$method] = [$this->MadelineProto->{$namespace}, $method];
}
foreach ($this->MadelineProto->get_methods_namespaced() as $pair) {
$namespace = key($pair);
$namespace = \key($pair);
$method = $pair[$namespace];
if ($namespace === 'upload') {
continue;
@ -73,7 +73,7 @@ class Lua
}
$this->MadelineProto->lua = true;
foreach ($this->MadelineProto->get_methods_namespaced() as $pair) {
$namespace = key($pair);
$namespace = \key($pair);
$this->MadelineProto->{$namespace}->lua = true;
}
}
@ -85,7 +85,7 @@ class Lua
return 0;
}
$result = $this->MadelineProto->API->method_call($params['_'], $params, ['datacenter' => $this->MadelineProto->API->datacenter->curdc]);
if (is_callable($cb)) {
if (\is_callable($cb)) {
$cb($this->MadelineProto->mtproto_to_td($result), $cb_extra);
}
@ -95,7 +95,7 @@ class Lua
public function madeline_function($params, $cb = null, $cb_extra = null)
{
$result = $this->MadelineProto->API->method_call($params['_'], $params, ['datacenter' => $this->MadelineProto->API->datacenter->curdc]);
if (is_callable($cb)) {
if (\is_callable($cb)) {
$cb($result, $cb_extra);
}
self::convert_objects($result);
@ -110,13 +110,13 @@ class Lua
private function convert_array($array)
{
if (!is_array($array)) {
if (!\is_array($array)) {
return $array;
}
if ($this->is_seqential($array)) {
return array_flip(array_map(function ($el) {
return \array_flip(\array_map(function ($el) {
return $el + 1;
}, array_flip($array)));
}, \array_flip($array)));
}
}
@ -126,7 +126,7 @@ class Lua
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)
@ -168,10 +168,10 @@ class Lua
public static function convert_objects(&$data)
{
array_walk_recursive($data, function (&$value, $key) {
if (is_object($value) && !$value instanceof \phpseclib\Math\BigInteger) {
\array_walk_recursive($data, function (&$value, $key) {
if (\is_object($value) && !$value instanceof \phpseclib\Math\BigInteger) {
$newval = [];
foreach (get_class_methods($value) as $name) {
foreach (\get_class_methods($value) as $name) {
$newval[$name] = [$value, $name];
}
foreach ($value as $key => $name) {

View File

@ -28,8 +28,6 @@ use danog\MadelineProto\Loop\Update\UpdateLoop;
use danog\MadelineProto\MTProtoTools\CombinedUpdatesState;
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
use danog\MadelineProto\MTProtoTools\UpdatesState;
use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpStream;
use danog\MadelineProto\TL\TLCallback;
/**
@ -1160,10 +1158,10 @@ class MTProto extends AsyncConstruct implements TLCallback
}
/**
* Check if connected to datacenter using HTTP
* Check if connected to datacenter using HTTP.
*
* @param string $datacenter DC ID
*
*
* @return boolean
*/
public function isHttp(string $datacenter)

View File

@ -29,14 +29,14 @@ trait MsgIdHandler
public function check_message_id($new_message_id, $aargs)
{
if (!is_object($new_message_id)) {
$new_message_id = new \phpseclib\Math\BigInteger(strrev($new_message_id), 256);
if (!\is_object($new_message_id)) {
$new_message_id = new \phpseclib\Math\BigInteger(\strrev($new_message_id), 256);
}
$min_message_id = (new \phpseclib\Math\BigInteger(time() + $this->time_delta - 300))->bitwise_leftShift(32);
$min_message_id = (new \phpseclib\Math\BigInteger(\time() + $this->time_delta - 300))->bitwise_leftShift(32);
if ($min_message_id->compare($new_message_id) > 0) {
$this->API->logger->logger('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->time_delta + 30))->bitwise_leftShift(32);
$max_message_id = (new \phpseclib\Math\BigInteger(\time() + $this->time_delta + 30))->bitwise_leftShift(32);
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.');
}
@ -47,15 +47,15 @@ trait MsgIdHandler
if (!\danog\MadelineProto\Magic::$has_thread && $new_message_id->compare($key = $this->get_max_id($incoming = 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);
}
if (count($this->outgoing_messages) > $this->API->settings['msg_array_limit']['outgoing']) {
reset($this->outgoing_messages);
$key = key($this->outgoing_messages);
if (\count($this->outgoing_messages) > $this->API->settings['msg_array_limit']['outgoing']) {
\reset($this->outgoing_messages);
$key = \key($this->outgoing_messages);
if (!isset($this->outgoing_messages[$key]['promise'])) {
unset($this->outgoing_messages[$key]);
}
}
$this->max_outgoing_id = $new_message_id;
$this->outgoing_messages[strrev($new_message_id->toBytes())] = [];
$this->outgoing_messages[\strrev($new_message_id->toBytes())] = [];
} else {
if (!$new_message_id->divide(\danog\MadelineProto\Magic::$four)[1]->equals(\danog\MadelineProto\Magic::$one) && !$new_message_id->divide(\danog\MadelineProto\Magic::$four)[1]->equals(\danog\MadelineProto\Magic::$three)) {
throw new \danog\MadelineProto\Exception('message id mod 4 != 1 or 3');
@ -70,33 +70,33 @@ trait MsgIdHandler
$this->API->logger->logger('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->incoming_messages) > $this->API->settings['msg_array_limit']['incoming']) {
reset($this->incoming_messages);
$key = key($this->incoming_messages);
if (\count($this->incoming_messages) > $this->API->settings['msg_array_limit']['incoming']) {
\reset($this->incoming_messages);
$key = \key($this->incoming_messages);
if (!isset($this->incoming_messages[$key]['promise'])) {
unset($this->incoming_messages[$key]);
}
}
$this->max_incoming_id = $new_message_id;
$this->incoming_messages[strrev($new_message_id->toBytes())] = [];
$this->incoming_messages[\strrev($new_message_id->toBytes())] = [];
}
}
public function generate_message_id()
{
$message_id = (new \phpseclib\Math\BigInteger(time() + $this->time_delta))->bitwise_leftShift(32);
$message_id = (new \phpseclib\Math\BigInteger(\time() + $this->time_delta))->bitwise_leftShift(32);
if ($message_id->compare($key = $this->get_max_id($incoming = false)) <= 0) {
$message_id = $key->add(\danog\MadelineProto\Magic::$four);
}
$this->check_message_id($message_id, ['outgoing' => true, 'container' => false]);
return strrev($message_id->toBytes());
return \strrev($message_id->toBytes());
}
public function get_max_id($incoming)
{
$incoming = $incoming ? 'incoming' : 'outgoing';
if (isset($this->{'max_'.$incoming.'_id'}) && is_object($this->{'max_'.$incoming.'_id'})) {
if (isset($this->{'max_'.$incoming.'_id'}) && \is_object($this->{'max_'.$incoming.'_id'})) {
return $this->{'max_'.$incoming.'_id'};
}

View File

@ -65,5 +65,4 @@ trait SeqNoHandler
return \is_string($method) ? !\in_array($method, MTProto::NOT_CONTENT_RELATED) : true;
}
}

View File

@ -56,7 +56,7 @@ abstract class Session
$this->max_outgoing_id = null;
}
/**
* Create MTProto session if needed
* Create MTProto session if needed.
*
* @return void
*/

View File

@ -68,4 +68,4 @@ trait CallHandler
{
return $this->datacenter->getConnection($aargs['datacenter'] ?? $this->datacenter->curdc)->method_call_async_write($method, $args, $aargs);
}
}
}

View File

@ -29,11 +29,11 @@ class CombinedUpdatesState
public function __construct($init = [])
{
$this->states[false] = new UpdatesState();
if (!is_array($init)) {
if (!\is_array($init)) {
return;
}
foreach ($init as $channel => $state) {
if (is_array($state)) {
if (\is_array($state)) {
$state = new UpdatesState($state, $channel);
}
$this->states[$channel] = $state;

View File

@ -24,10 +24,10 @@ trait Crypt
public function aes_calculate($msg_key, $auth_key, $to_server = true)
{
$x = $to_server ? 0 : 8;
$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);
$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);
$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);
$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);
return [$aes_key, $aes_iv];
}
@ -35,12 +35,12 @@ trait Crypt
public function old_aes_calculate($msg_key, $auth_key, $to_server = true)
{
$x = $to_server ? 0 : 8;
$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_c = sha1(substr($auth_key, 64 + $x, 32).$msg_key, 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_iv = substr($sha1_a, 8, 12).substr($sha1_b, 0, 8).substr($sha1_c, 16, 4).substr($sha1_d, 0, 8);
$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_c = \sha1(\substr($auth_key, 64 + $x, 32).$msg_key, 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_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];
}

View File

@ -25,7 +25,7 @@ use danog\MadelineProto\Tools;
use phpseclib\Math\BigInteger;
/**
* Manages SRP password calculation
* Manages SRP password calculation.
*
* @author Daniil Gentili <daniil@daniil.it>
* @link https://docs.madelineproto.xyz MadelineProto documentation
@ -34,54 +34,54 @@ class PasswordCalculator
{
use AuthKeyHandler;
use Tools;
/**
* The algorithm to use for calculating the hash of new passwords (a PasswordKdfAlgo object)
* The algorithm to use for calculating the hash of new passwords (a PasswordKdfAlgo object).
*
* @var array
*/
private $new_algo;
/**
* A secure random string that can be used to compute the password
* A secure random string that can be used to compute the password.
*
* @var string
*/
private $secure_random = '';
/**
* The algorithm to use for calculatuing the hash of the current password (a PasswordKdfAlgo object)
* The algorithm to use for calculatuing the hash of the current password (a PasswordKdfAlgo object).
*
* @var array
*/
private $current_algo;
/**
* SRP b parameter
* SRP b parameter.
*
* @var BigInteger
*/
private $srp_B;
/**
* SRP b parameter for hashing
* SRP b parameter for hashing.
*
* @var BigInteger
*/
private $srp_BForHash;
/**
* SRP ID
* SRP ID.
*
* @var [type]
*/
private $srp_id;
/**
* Logger
* Logger.
*
* @var \danog\MadelineProto\Logger
*/
public $logger;
/**
* Initialize logger
* Initialize logger.
*
* @param \danog\MadelineProto\Logger $logger
*/
@ -91,7 +91,7 @@ class PasswordCalculator
}
/**
* Popupate 2FA configuration
* Popupate 2FA configuration.
*
* @param array $object 2FA configuration object obtained using account.getPassword
* @return void
@ -112,8 +112,8 @@ class PasswordCalculator
$object['current_algo']['g'] = new BigInteger($object['current_algo']['g']);
$object['current_algo']['p'] = new BigInteger((string) $object['current_algo']['p'], 256);
$this->check_p_g($object['current_algo']['p'], $object['current_algo']['g']);
$object['current_algo']['gForHash'] = str_pad($object['current_algo']['g']->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$object['current_algo']['pForHash'] = str_pad($object['current_algo']['p']->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$object['current_algo']['gForHash'] = \str_pad($object['current_algo']['g']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
$object['current_algo']['pForHash'] = \str_pad($object['current_algo']['p']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
break;
default:
@ -128,7 +128,7 @@ class PasswordCalculator
throw new SecurityException('srp_B > p');
}
$this->srp_B = $object['srp_B'];
$this->srp_BForHash = str_pad($object['srp_B']->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$this->srp_BForHash = \str_pad($object['srp_B']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
$this->srp_id = $object['srp_id'];
} else {
$this->current_algo = null;
@ -143,8 +143,8 @@ class PasswordCalculator
$object['new_algo']['g'] = new BigInteger($object['new_algo']['g']);
$object['new_algo']['p'] = new BigInteger((string) $object['new_algo']['p'], 256);
$this->check_p_g($object['new_algo']['p'], $object['new_algo']['g']);
$object['new_algo']['gForHash'] = str_pad($object['new_algo']['g']->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$object['new_algo']['pForHash'] = str_pad($object['new_algo']['p']->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$object['new_algo']['gForHash'] = \str_pad($object['new_algo']['g']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
$object['new_algo']['pForHash'] = \str_pad($object['new_algo']['p']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
break;
default:
@ -155,7 +155,7 @@ class PasswordCalculator
}
/**
* Create a random string (eventually prefixed by the specified string)
* Create a random string (eventually prefixed by the specified string).
*
* @param string $prefix Prefix
* @return string Salt
@ -166,8 +166,8 @@ class PasswordCalculator
}
/**
* Hash specified data using the salt with SHA256
*
* Hash specified data using the salt with SHA256.
*
* The result will be the SHA256 hash of the salt concatenated with the data concatenated with the salt
*
* @param string $data Data to hash
@ -176,11 +176,11 @@ class PasswordCalculator
*/
public function hashSha256(string $data, string $salt): string
{
return hash('sha256', $salt.$data.$salt, true);
return \hash('sha256', $salt.$data.$salt, true);
}
/**
* Hashes the specified password
* Hashes the specified password.
*
* @param string $password Password
* @param string $client_salt Client salt
@ -191,13 +191,13 @@ class PasswordCalculator
{
$buf = $this->hashSha256($password, $client_salt);
$buf = $this->hashSha256($buf, $server_salt);
$hash = hash_pbkdf2('sha512', $buf, $client_salt, 100000, 0, true);
$hash = \hash_pbkdf2('sha512', $buf, $client_salt, 100000, 0, true);
return $this->hashSha256($hash, $server_salt);
}
/**
* Get the InputCheckPassword object for checking the validity of a password using account.checkPassword
* Get the InputCheckPassword object for checking the validity of a password using account.checkPassword.
*
* @param string $password The password
* @return array InputCheckPassword object
@ -213,7 +213,7 @@ class PasswordCalculator
$gForHash = $this->current_algo['gForHash'];
$p = $this->current_algo['p'];
$pForHash = $this->current_algo['pForHash'];
$B = $this->srp_B;
$BForHash = $this->srp_BForHash;
$id = $this->srp_id;
@ -221,39 +221,39 @@ class PasswordCalculator
$x = new BigInteger($this->hashPassword($password, $client_salt, $server_salt), 256);
$g_x = $g->powMod($x, $p);
$k = new BigInteger(hash('sha256', $pForHash.$gForHash, true), 256);
$k = new BigInteger(\hash('sha256', $pForHash.$gForHash, true), 256);
$kg_x = $k->multiply($g_x)->powMod(Magic::$one, $p);
$a = new BigInteger($this->random(2048 / 8), 256);
$A = $g->powMod($a, $p);
$this->check_G($A, $p);
$AForHash = str_pad($A->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$AForHash = \str_pad($A->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
$b_kg_x = $B->powMod(Magic::$one, $p)->subtract($kg_x);
$u = new BigInteger(hash('sha256', $AForHash.$BForHash, true), 256);
$u = new BigInteger(\hash('sha256', $AForHash.$BForHash, true), 256);
$ux = $u->multiply($x);
$a_ux = $a->add($ux);
$S = $b_kg_x->powMod($a_ux, $p);
$SForHash = str_pad($S->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$K = hash('sha256', $SForHash, true);
$SForHash = \str_pad($S->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
$K = \hash('sha256', $SForHash, true);
$h1 = hash('sha256', $pForHash, true);
$h2 = hash('sha256', $gForHash, true);
$h1 = \hash('sha256', $pForHash, true);
$h2 = \hash('sha256', $gForHash, true);
$h1 ^= $h2;
$M1 = hash('sha256', $h1.hash('sha256', $client_salt, true).hash('sha256', $server_salt, true).$AForHash.$BForHash.$K, true);
$M1 = \hash('sha256', $h1.\hash('sha256', $client_salt, true).\hash('sha256', $server_salt, true).$AForHash.$BForHash.$K, true);
return ['_' => 'inputCheckPasswordSRP', 'srp_id' => $id, 'A' => $AForHash, 'M1' => $M1];
}
/**
* Get parameters to be passed to the account.updatePasswordSettings to update/set a 2FA password
* Get parameters to be passed to the account.updatePasswordSettings to update/set a 2FA password.
*
* The input params array can contain password, new_password, email and hint params.
*
*
* @param array $params Input params
* @return array account.updatePasswordSettings parameters
*/
@ -262,7 +262,7 @@ class PasswordCalculator
$oldPassword = $this->getCheckPassword($params['password'] ?? '');
$return = ['password' => $oldPassword, 'new_settings' => ['_' => 'account.passwordInputSettings', 'new_algo' => ['_' => 'passwordKdfAlgoUnknown'], 'new_password_hash' => '', 'hint' => '']];
$new_settings = &$return['new_settings'];
if (isset($params['new_password']) && $params['new_password'] !== '') {
@ -274,7 +274,7 @@ class PasswordCalculator
$x = new BigInteger($this->hashPassword($params['new_password'], $client_salt, $server_salt), 256);
$v = $g->powMod($x, $p);
$vForHash = str_pad($v->toBytes(), 256, chr(0), \STR_PAD_LEFT);
$vForHash = \str_pad($v->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
$new_settings['new_algo'] = [
'_' => 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow',

View File

@ -32,19 +32,19 @@ trait PeerHandler
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)));
}
public function from_supergroup($id)
{
return -$id - pow(10, (int) floor(log(-$id, 10)));
return -$id - \pow(10, (int) \floor(\log(-$id, 10)));
}
public function is_supergroup($id)
{
$log = log(-$id, 10);
$log = \log(-$id, 10);
return ($log - intval($log)) * 1000 < 10;
return ($log - \intval($log)) * 1000 < 10;
}
public function add_support($support)
@ -84,6 +84,7 @@ trait PeerHandler
$this->chats[$user['id']] = $user;
$this->cache_pwr_chat($user['id'], false, true);
}
// no break
case 'userEmpty':
break;
default:
@ -137,7 +138,7 @@ trait PeerHandler
}
break;
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;
}
}
@ -208,7 +209,7 @@ trait PeerHandler
public function get_folder_id($id)
{
if (!is_array($id)) {
if (!\is_array($id)) {
return null;
}
if (!isset($id['folder_id'])) {
@ -218,12 +219,13 @@ trait PeerHandler
}
public function get_id($id)
{
if (is_array($id)) {
if (\is_array($id)) {
switch ($id['_']) {
case 'updateDialogPinned':
case 'updateDialogUnreadMark':
case 'updateNotifySettings':
$id = $id['peer'];
// no break
case 'updateDraftMessage':
case 'inputDialogPeer':
case 'dialogPeer':
@ -291,6 +293,7 @@ trait PeerHandler
return $this->to_supergroup($id['channel_id']);
case 'updateChatParticipants':
$id = $id['participants'];
// no break
case 'updateChatUserTyping':
case 'updateChatParticipantAdd':
case 'updateChatParticipantDelete':
@ -325,24 +328,24 @@ trait PeerHandler
case 'updateEditChannelMessage':
return $this->get_id($id['message']);
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));
}
}
if (is_string($id)) {
if (strpos($id, '#') !== false) {
if (preg_match('/^channel#(\d*)/', $id, $matches)) {
if (\is_string($id)) {
if (\strpos($id, '#') !== false) {
if (\preg_match('/^channel#(\d*)/', $id, $matches)) {
return $this->to_supergroup($matches[1]);
}
if (preg_match('/^chat#(\d*)/', $id, $matches)) {
if (\preg_match('/^chat#(\d*)/', $id, $matches)) {
$id = '-'.$matches[1];
}
if (preg_match('/^user#(\d*)/', $id, $matches)) {
if (\preg_match('/^user#(\d*)/', $id, $matches)) {
return $matches[1];
}
}
}
if (is_numeric($id)) {
if (is_string($id)) {
if (\is_numeric($id)) {
if (\is_string($id)) {
$id = \danog\MadelineProto\Magic::$bigint ? (float) $id : (int) $id;
}
@ -354,7 +357,7 @@ trait PeerHandler
public function get_info_async($id, $recursive = true)
{
if (is_array($id)) {
if (\is_array($id)) {
switch ($id['_']) {
case 'updateEncryption':
return $this->get_secret_chat($id['chat']['id']);
@ -364,6 +367,7 @@ trait PeerHandler
return $this->get_secret_chat($id['chat_id']);
case 'updateNewEncryptedMessage':
$id = $id['message'];
// no break
case 'encryptedMessage':
case 'encryptedMessageService':
$id = $id['chat_id'];
@ -382,7 +386,7 @@ trait PeerHandler
$tried_simple = false;
if (is_numeric($id)) {
if (\is_numeric($id)) {
if (!isset($this->chats[$id])) {
try {
$this->caching_simple[$id] = true;
@ -421,7 +425,7 @@ trait PeerHandler
$dbres = [];
try {
$dbres = json_decode(yield $this->datacenter->fileGetContents('https://id.pwrtelegram.xyz/db/getusername?id='.$id), true);
$dbres = \json_decode(yield $this->datacenter->fileGetContents('https://id.pwrtelegram.xyz/db/getusername?id='.$id), true);
} catch (\Throwable $e) {
$this->logger->logger($e);
}
@ -442,19 +446,18 @@ trait PeerHandler
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
}
if (preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $id, $matches)) {
if (\preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $id, $matches)) {
if ($matches[1] === '') {
$id = $matches[2];
} else {
$invite = yield $this->method_call_async_read('messages.checkChatInvite', ['hash' => $matches[2]], ['datacenter' => $this->datacenter->curdc]);
if (isset($invite['chat'])) {
return yield $this->get_info_async($invite['chat']);
} else {
throw new \danog\MadelineProto\Exception('You have not joined this chat');
}
throw new \danog\MadelineProto\Exception('You have not joined this chat');
}
}
$id = strtolower(str_replace('@', '', $id));
$id = \strtolower(\str_replace('@', '', $id));
if ($id === 'me') {
return yield $this->get_info_async($this->authorization['user']['id']);
}
@ -466,7 +469,7 @@ trait PeerHandler
return yield $this->get_info_async($this->supportUser);
}
foreach ($this->chats as $chat) {
if (isset($chat['username']) && strtolower($chat['username']) === $id) {
if (isset($chat['username']) && \strtolower($chat['username']) === $id) {
return $this->gen_all($chat, $folder_id);
}
}
@ -532,7 +535,7 @@ trait PeerHandler
case 'channelForbidden':
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
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));
}
if ($folder_id) {
$res['FolderPeer'] = ['_' => 'folderPeer', 'peer' => $res['Peer'], 'folder_id' => $folder_id];
@ -549,8 +552,8 @@ trait PeerHandler
public function get_full_info_async($id)
{
$partial = yield $this->get_info_async($id);
if (time() - $this->full_chat_last_updated($partial['bot_api_id']) < (isset($this->settings['peer']['full_info_cache_time']) ? $this->settings['peer']['full_info_cache_time'] : 0)) {
return array_merge($partial, $this->full_chats[$partial['bot_api_id']]);
if (\time() - $this->full_chat_last_updated($partial['bot_api_id']) < (isset($this->settings['peer']['full_info_cache_time']) ? $this->settings['peer']['full_info_cache_time'] : 0)) {
return \array_merge($partial, $this->full_chats[$partial['bot_api_id']]);
}
switch ($partial['type']) {
case 'user':
@ -568,12 +571,12 @@ trait PeerHandler
$res = [];
$res['full'] = $full;
$res['last_update'] = time();
$res['last_update'] = \time();
$this->full_chats[$partial['bot_api_id']] = $res;
$partial = yield $this->get_info_async($id);
return array_merge($partial, $res);
return \array_merge($partial, $res);
}
public function get_pwr_chat_async($id, $fullfetch = true, $send = true)
@ -594,7 +597,7 @@ trait PeerHandler
}
}
if (isset($full['full']['profile_photo']['sizes'])) {
$res['photo'] = yield $this->photosize_to_botapi_async(end($full['full']['profile_photo']['sizes']), $full['full']['profile_photo']);
$res['photo'] = yield $this->photosize_to_botapi_async(\end($full['full']['profile_photo']['sizes']), $full['full']['profile_photo']);
}
break;
case 'chat':
@ -612,7 +615,7 @@ trait PeerHandler
$res['all_members_are_administrators'] = !$res['admins_enabled'];
}
if (isset($full['full']['chat_photo']['sizes'])) {
$res['photo'] = yield $this->photosize_to_botapi_async(end($full['full']['chat_photo']['sizes']), $full['full']['chat_photo']);
$res['photo'] = yield $this->photosize_to_botapi_async(\end($full['full']['chat_photo']['sizes']), $full['full']['chat_photo']);
}
if (isset($full['full']['exported_invite']['link'])) {
$res['invite'] = $full['full']['exported_invite']['link'];
@ -634,7 +637,7 @@ trait PeerHandler
}
}
if (isset($full['full']['chat_photo']['sizes'])) {
$res['photo'] = yield $this->photosize_to_botapi_async(end($full['full']['chat_photo']['sizes']), $full['full']['chat_photo']);
$res['photo'] = yield $this->photosize_to_botapi_async(\end($full['full']['chat_photo']['sizes']), $full['full']['chat_photo']);
}
if (isset($full['full']['exported_invite']['link'])) {
$res['invite'] = $full['full']['exported_invite']['link'];
@ -686,7 +689,7 @@ trait PeerHandler
$res['participants'][$key] = $newres;
}
}
if (!isset($res['participants']) && $fullfetch && in_array($res['type'], ['supergroup', 'channel'])) {
if (!isset($res['participants']) && $fullfetch && \in_array($res['type'], ['supergroup', 'channel'])) {
$total_count = (isset($res['participants_count']) ? $res['participants_count'] : 0) + (isset($res['admins_count']) ? $res['admins_count'] : 0) + (isset($res['kicked_count']) ? $res['kicked_count'] : 0) + (isset($res['banned_count']) ? $res['banned_count'] : 0);
$res['participants'] = [];
$limit = 200;
@ -700,8 +703,8 @@ trait PeerHandler
foreach ($filters as $filter) {
yield $this->recurse_alphabet_search_participants_async($full['InputChannel'], $filter, $q, $total_count, $res);
}
$this->logger->logger('Fetched '.count($res['participants'])." out of $total_count");
$res['participants'] = array_values($res['participants']);
$this->logger->logger('Fetched '.\count($res['participants'])." out of $total_count");
$res['participants'] = \array_values($res['participants']);
}
if (!$fullfetch) {
unset($res['participants']);
@ -719,7 +722,7 @@ trait PeerHandler
return false;
}
for ($x = 'a'; $x !== 'aa' && $total_count > count($res['participants']); $x++) {
for ($x = 'a'; $x !== 'aa' && $total_count > \count($res['participants']); $x++) {
yield $this->recurse_alphabet_search_participants_async($channel, $filter, $q.$x, $total_count, $res);
}
}
@ -740,9 +743,8 @@ trait PeerHandler
$this->logger->logger($e->rpc);
return $has_more;
} else {
throw $e;
}
throw $e;
}
if ($cached = $gres['_'] === 'channels.channelParticipantsNotModified') {
@ -797,9 +799,9 @@ trait PeerHandler
}
$res['participants'][$participant['user_id']] = $newres;
}
$this->logger->logger('Fetched '.count($gres['participants'])." channel participants with filter $filter, query $q, offset $offset, limit $limit, hash $hash: ".($cached ? 'cached' : 'not cached').', '.($offset + count($gres['participants'])).' participants out of '.$gres['count'].', in total fetched '.count($res['participants']).' out of '.$total_count);
$offset += count($gres['participants']);
} while (count($gres['participants']));
$this->logger->logger('Fetched '.\count($gres['participants'])." channel participants with filter $filter, query $q, offset $offset, limit $limit, hash $hash: ".($cached ? 'cached' : 'not cached').', '.($offset + \count($gres['participants'])).' participants out of '.$gres['count'].', in total fetched '.\count($res['participants']).' out of '.$total_count);
$offset += \count($gres['participants']);
} while (\count($gres['participants']));
if ($offset === $limit) {
return true;
@ -821,7 +823,7 @@ trait PeerHandler
foreach ($gres['participants'] as $participant) {
$ids[] = $participant['user_id'];
}
sort($ids, SORT_NUMERIC);
\sort($ids, SORT_NUMERIC);
$gres['hash'] = $this->gen_vector_hash($ids);
$this->channel_participants[$channel['channel_id']][$filter][$q][$offset][$limit] = $gres;
}
@ -843,7 +845,7 @@ trait PeerHandler
}
$this->qres[] = $res;
}
if ($this->last_stored > time() && !$force) {
if ($this->last_stored > \time() && !$force) {
//$this->logger->logger("========== WILL SERIALIZE IN ".($this->last_stored - time())." =============");
return false;
}
@ -852,7 +854,7 @@ trait PeerHandler
}
try {
$payload = json_encode($this->qres);
$payload = \json_encode($this->qres);
//$path = '/tmp/ids'.hash('sha256', $payload);
//file_put_contents($path, $payload);
$id = isset($this->authorization['user']['username']) ? $this->authorization['user']['username'] : $this->authorization['user']['id'];
@ -863,7 +865,7 @@ trait PeerHandler
$this->logger->logger("============ $result =============", \danog\MadelineProto\Logger::VERBOSE);
$this->qres = [];
$this->last_stored = time() + 10;
$this->last_stored = \time() + 10;
} catch (\danog\MadelineProto\Exception $e) {
$this->logger->logger('======= COULD NOT STORE IN DB DUE TO '.$e->getMessage().' =============', \danog\MadelineProto\Logger::VERBOSE);
}
@ -873,10 +875,10 @@ trait PeerHandler
{
try {
$this->caching_simple_username[$username] = true;
$res = yield $this->method_call_async_read('contacts.resolveUsername', ['username' => str_replace('@', '', $username)], ['datacenter' => $this->datacenter->curdc]);
$res = yield $this->method_call_async_read('contacts.resolveUsername', ['username' => \str_replace('@', '', $username)], ['datacenter' => $this->datacenter->curdc]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
$this->logger->logger('Username resolution failed with error '.$e->getMessage(), \danog\MadelineProto\Logger::ERROR);
if (strpos($e->rpc, 'FLOOD_WAIT_') === 0 || $e->rpc === 'AUTH_KEY_UNREGISTERED' || $e->rpc === 'USERNAME_INVALID') {
if (\strpos($e->rpc, 'FLOOD_WAIT_') === 0 || $e->rpc === 'AUTH_KEY_UNREGISTERED' || $e->rpc === 'USERNAME_INVALID') {
throw $e;
}

View File

@ -132,31 +132,31 @@ class ReferenceDatabase implements TLCallback
public function getMethodCallbacks(): array
{
return array_fill_keys(array_keys(self::METHOD_CONTEXT), [[$this, 'addOriginMethod']]);
return \array_fill_keys(\array_keys(self::METHOD_CONTEXT), [[$this, 'addOriginMethod']]);
}
public function getMethodBeforeCallbacks(): array
{
return array_fill_keys(array_keys(self::METHOD_CONTEXT), [[$this, 'addOriginMethodContext']]);
return \array_fill_keys(\array_keys(self::METHOD_CONTEXT), [[$this, 'addOriginMethodContext']]);
}
public function getConstructorCallbacks(): array
{
return array_merge(
array_fill_keys(['document', 'photo', 'fileLocation'], [[$this, 'addReference']]),
array_fill_keys(array_keys(self::CONSTRUCTOR_CONTEXT), [[$this, 'addOrigin']]),
return \array_merge(
\array_fill_keys(['document', 'photo', 'fileLocation'], [[$this, 'addReference']]),
\array_fill_keys(\array_keys(self::CONSTRUCTOR_CONTEXT), [[$this, 'addOrigin']]),
['document' => [[$this, 'addReference'], [$this, 'addOrigin']]]
);
}
public function getConstructorBeforeCallbacks(): array
{
return array_fill_keys(array_keys(self::CONSTRUCTOR_CONTEXT), [[$this, 'addOriginContext']]);
return \array_fill_keys(\array_keys(self::CONSTRUCTOR_CONTEXT), [[$this, 'addOriginContext']]);
}
public function getConstructorSerializeCallbacks(): array
{
return array_fill_keys(array_keys(self::LOCATION_CONTEXT), [$this, 'populateReference']);
return \array_fill_keys(\array_keys(self::LOCATION_CONTEXT), [$this, 'populateReference']);
}
public function getTypeMismatchCallbacks(): array
@ -167,7 +167,7 @@ class ReferenceDatabase implements TLCallback
public function reset()
{
if ($this->cacheContexts) {
$this->API->logger->logger('Found '.count($this->cacheContexts).' pending contexts', \danog\MadelineProto\Logger::ERROR);
$this->API->logger->logger('Found '.\count($this->cacheContexts).' pending contexts', \danog\MadelineProto\Logger::ERROR);
$this->cacheContexts = [];
}
if ($this->cache) {
@ -182,7 +182,7 @@ class ReferenceDatabase implements TLCallback
$this->API->logger->logger('Trying to add reference out of context, report the following message to @danogentili!', \danog\MadelineProto\Logger::ERROR);
$frames = [];
$previous = '';
foreach (debug_backtrace(0) as $k => $frame) {
foreach (\debug_backtrace(0) as $k => $frame) {
if (isset($frame['function']) && $frame['function'] === 'deserialize') {
if (isset($frame['args'][1]['subtype'])) {
if ($frame['args'][1]['subtype'] === $previous) {
@ -205,8 +205,8 @@ class ReferenceDatabase implements TLCallback
}
}
}
$frames = array_reverse($frames);
$tl_trace = array_shift($frames);
$frames = \array_reverse($frames);
$tl_trace = \array_shift($frames);
foreach ($frames as $frame) {
$tl_trace .= "['".$frame."']";
}
@ -219,7 +219,7 @@ class ReferenceDatabase implements TLCallback
return false;
}
$key = count($this->cacheContexts) - 1;
$key = \count($this->cacheContexts) - 1;
switch ($location['_']) {
case 'document':
$locationType = self::DOCUMENT_LOCATION;
@ -254,11 +254,11 @@ class ReferenceDatabase implements TLCallback
public function addOrigin(array $data = [])
{
$key = count($this->cacheContexts) - 1;
$key = \count($this->cacheContexts) - 1;
if ($key === -1) {
throw new \danog\MadelineProto\Exception('Trying to add origin with no origin context set');
}
$originType = array_pop($this->cacheContexts);
$originType = \array_pop($this->cacheContexts);
if (!isset($this->cache[$key])) {
$this->API->logger->logger("Removing origin context $originType for {$data['_']}, nothing in the reference cache!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
@ -311,7 +311,7 @@ class ReferenceDatabase implements TLCallback
}
}
if (!isset($origin['stickerset'])) {
$key = count($this->cacheContexts) - 1;
$key = \count($this->cacheContexts) - 1;
if (!isset($this->cache[$key])) {
$this->cache[$key] = [];
}
@ -319,7 +319,7 @@ class ReferenceDatabase implements TLCallback
foreach ($cache as $location => $reference) {
$this->cache[$key][$location] = $reference;
}
$this->API->logger->logger("Skipped origin $originType ({$data['_']}) for ".count($cache).' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
$this->API->logger->logger("Skipped origin $originType ({$data['_']}) for ".\count($cache).' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
return;
}
@ -333,7 +333,7 @@ class ReferenceDatabase implements TLCallback
foreach ($cache as $location => $reference) {
$this->storeReference($location, $reference, $originType, $origin);
}
$this->API->logger->logger("Added origin $originType ({$data['_']}) to ".count($cache).' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
$this->API->logger->logger("Added origin $originType ({$data['_']}) to ".\count($cache).' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
}
public function addOriginMethodContext(string $type)
@ -348,11 +348,11 @@ class ReferenceDatabase implements TLCallback
public function addOriginMethod(array $data, array $res)
{
$key = count($this->cacheContexts) - 1;
$key = \count($this->cacheContexts) - 1;
if ($key === -1) {
throw new \danog\MadelineProto\Exception('Trying to add origin with no origin context set');
}
$originType = array_pop($this->cacheContexts);
$originType = \array_pop($this->cacheContexts);
if (!isset($this->cache[$key])) {
$this->API->logger->logger("Removing origin context $originType for {$data['_']}, nothing in the reference cache!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
@ -420,7 +420,7 @@ class ReferenceDatabase implements TLCallback
foreach ($cache as $location => $reference) {
$this->storeReference($location, $reference, $originType, $origin);
}
$this->API->logger->logger("Added origin $originType ({$data['_']}) to ".count($cache).' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
$this->API->logger->logger("Added origin $originType ({$data['_']}) to ".\count($cache).' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
}
public function storeReference(string $location, string $reference, int $originType, array $origin)
@ -435,7 +435,7 @@ class ReferenceDatabase implements TLCallback
$this->refreshed[$location] = true;
}
$key = count($this->cacheContexts) - 1;
$key = \count($this->cacheContexts) - 1;
if ($key >= 0) {
$this->cache[$key][$location] = $reference;
}
@ -472,7 +472,7 @@ class ReferenceDatabase implements TLCallback
return $this->db[$location]['reference'];
}
ksort($this->db[$location]['origins']);
\ksort($this->db[$location]['origins']);
$count = 0;
foreach ($this->db[$location]['origins'] as $originType => &$origin) {
@ -481,7 +481,7 @@ class ReferenceDatabase implements TLCallback
switch ($originType) {
// Peer + msg ID
case self::MESSAGE_ORIGIN:
if (is_array($origin['peer'])) {
if (\is_array($origin['peer'])) {
$origin['peer'] = $this->API->get_id($origin['peer']);
}
if ($origin['peer'] < 0) {
@ -569,10 +569,10 @@ class ReferenceDatabase implements TLCallback
switch ($locationType) {
case self::DOCUMENT_LOCATION:
case self::PHOTO_LOCATION:
return $locationType.(is_int($location['id']) ? $this->pack_signed_long($location['id']) : $location['id']);
return $locationType.(\is_int($location['id']) ? $this->pack_signed_long($location['id']) : $location['id']);
case self::PHOTO_LOCATION_LOCATION:
$dc_id = $this->pack_signed_int($location['dc_id']);
$volume_id = is_int($location['volume_id']) ? $this->pack_signed_long($location['volume_id']) : $location['volume_id'];
$volume_id = \is_int($location['volume_id']) ? $this->pack_signed_long($location['volume_id']) : $location['volume_id'];
$local_id = $this->pack_signed_int($location['local_id']);
return $locationType.$dc_id.$volume_id.$local_id;
@ -581,6 +581,6 @@ class ReferenceDatabase implements TLCallback
public function __debugInfo()
{
return ['ReferenceDatabase instance '.spl_object_hash($this)];
return ['ReferenceDatabase instance '.\spl_object_hash($this)];
}
}

View File

@ -36,13 +36,13 @@ trait UpdateHandler
public function pwr_update_handler($update)
{
if (isset($this->settings['pwr']['update_handler'])) {
if (is_array($this->settings['pwr']['update_handler']) && $this->settings['pwr']['update_handler'][0] === false) {
if (\is_array($this->settings['pwr']['update_handler']) && $this->settings['pwr']['update_handler'][0] === false) {
$this->settings['pwr']['update_handler'] = $this->settings['pwr']['update_handler'][1];
}
if (is_string($this->settings['pwr']['update_handler'])) {
if (\is_string($this->settings['pwr']['update_handler'])) {
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);
}
}
@ -64,7 +64,7 @@ trait UpdateHandler
$this->settings['updates']['run_callback'] = true;
}
$params = array_merge(self::DEFAULT_GETUPDATES_PARAMS, $params);
$params = \array_merge(self::DEFAULT_GETUPDATES_PARAMS, $params);
if (empty($this->updates)) {
$this->update_deferred = new Deferred();
@ -79,13 +79,13 @@ trait UpdateHandler
}
if ($params['offset'] < 0) {
$params['offset'] = array_reverse(array_keys((array) $this->updates))[abs($params['offset']) - 1];
$params['offset'] = \array_reverse(\array_keys((array) $this->updates))[\abs($params['offset']) - 1];
}
$updates = [];
foreach ($this->updates as $key => $value) {
if ($params['offset'] > $key) {
unset($this->updates[$key]);
} elseif ($params['limit'] === null || count($updates) < $params['limit']) {
} elseif ($params['limit'] === null || \count($updates) < $params['limit']) {
$updates[] = ['update_id' => $key, 'update' => $value];
}
}
@ -256,7 +256,7 @@ trait UpdateHandler
$this->config['expires'] = 0;
yield $this->get_config_async();
}
if (in_array($update['_'], ['updateUserName', 'updateUserPhone', 'updateUserBlocked', 'updateUserPhoto', 'updateContactRegistered', 'updateContactLink'])) {
if (\in_array($update['_'], ['updateUserName', 'updateUserPhone', 'updateUserBlocked', 'updateUserPhoto', 'updateContactRegistered', 'updateContactLink'])) {
$id = $this->get_id($update);
$this->full_chats[$id]['last_update'] = 0;
yield $this->get_full_info_async($id);
@ -268,7 +268,7 @@ trait UpdateHandler
return;
}
if ($update['_'] === 'updatePhoneCall') {
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
$this->logger->logger('The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.', \danog\MadelineProto\Logger::WARNING);
return;
@ -335,7 +335,7 @@ trait UpdateHandler
if ($update['_'] === 'updateEncryption') {
switch ($update['chat']['_']) {
case 'encryptedChatRequested':
if ($this->settings['secret_chats']['accept_chats'] === false || is_array($this->settings['secret_chats']['accept_chats']) && !in_array($update['chat']['admin_id'], $this->settings['secret_chats']['accept_chats'])) {
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;
}
$this->logger->logger('Accepting secret chat '.$update['chat']['id'], \danog\MadelineProto\Logger::NOTICE);
@ -383,7 +383,7 @@ trait UpdateHandler
public function pwr_webhook($update)
{
$payload = json_encode($update);
$payload = \json_encode($update);
//$this->logger->logger($update, $payload, json_last_error());
if ($payload === '') {
$this->logger->logger('EMPTY UPDATE');
@ -396,8 +396,8 @@ trait UpdateHandler
$result = yield (yield $this->datacenter->getHTTPClient()->request($request))->getBody();
$this->logger->logger('Result of webhook query is '.$result, \danog\MadelineProto\Logger::NOTICE);
$result = json_decode($result, true);
if (is_array($result) && isset($result['method']) && $result['method'] != '' && is_string($result['method'])) {
$result = \json_decode($result, true);
if (\is_array($result) && isset($result['method']) && $result['method'] != '' && \is_string($result['method'])) {
try {
$this->logger->logger('Reverse webhook command returned', yield $this->method_call_async_read($result['method'], $result, ['datacenter' => $this->datacenter->curdc]));
} catch (\Throwable $e) {

View File

@ -65,31 +65,31 @@ class Magic
public static function class_exists()
{
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
set_exception_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionHandler']);
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
\set_exception_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionHandler']);
if (!self::$inited) {
if (!defined('\\phpseclib\\Crypt\\Common\\SymmetricKey::MODE_IGE') || \phpseclib\Crypt\Common\SymmetricKey::MODE_IGE !== 7) {
if (!\defined('\\phpseclib\\Crypt\\Common\\SymmetricKey::MODE_IGE') || \phpseclib\Crypt\Common\SymmetricKey::MODE_IGE !== 7) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['phpseclib_fork']);
}
foreach (['intl', 'xml', 'fileinfo', 'json', 'mbstring'] as $extension) {
if (!extension_loaded($extension)) {
if (!\extension_loaded($extension)) {
throw Exception::extension($extension);
}
}
self::$has_thread = class_exists('\\Thread') && method_exists('\\Thread', 'getCurrentThread');
self::$BIG_ENDIAN = pack('L', 1) === pack('N', 1);
self::$has_thread = \class_exists('\\Thread') && \method_exists('\\Thread', 'getCurrentThread');
self::$BIG_ENDIAN = \pack('L', 1) === \pack('N', 1);
self::$bigint = PHP_INT_SIZE < 8;
self::$ipv6 = (bool) strlen(@file_get_contents('http://v6.ipv6-test.com/api/myip.php', false, stream_context_create(['http' => ['timeout' => 1]]))) > 0;
preg_match('/const V = (\\d+);/', @file_get_contents('https://raw.githubusercontent.com/danog/MadelineProto/master/src/danog/MadelineProto/MTProto.php'), $matches);
self::$ipv6 = (bool) \strlen(@\file_get_contents('http://v6.ipv6-test.com/api/myip.php', false, \stream_context_create(['http' => ['timeout' => 1]]))) > 0;
\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]) {
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 (!defined('\\danog\\MadelineProto\\VoIP::PHP_LIBTGVOIP_VERSION') || !in_array(\danog\MadelineProto\VoIP::PHP_LIBTGVOIP_VERSION, ['1.3.0'])) {
throw new \danog\MadelineProto\Exception(hex2bin(\danog\MadelineProto\Lang::$current_lang['v_tgerror']), 0, null, 'MadelineProto', 1);
if (\class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\defined('\\danog\\MadelineProto\\VoIP::PHP_LIBTGVOIP_VERSION') || !\in_array(\danog\MadelineProto\VoIP::PHP_LIBTGVOIP_VERSION, ['1.3.0'])) {
throw new \danog\MadelineProto\Exception(\hex2bin(\danog\MadelineProto\Lang::$current_lang['v_tgerror']), 0, null, 'MadelineProto', 1);
}
}
self::$emojis = json_decode(self::JSON_EMOJIS);
self::$emojis = \json_decode(self::JSON_EMOJIS);
self::$zero = new \phpseclib\Math\BigInteger(0);
self::$one = new \phpseclib\Math\BigInteger(1);
self::$two = new \phpseclib\Math\BigInteger(2);
@ -102,27 +102,27 @@ class Magic
self::$zeroeight = new \phpseclib\Math\BigInteger('2147483648');
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) {
}
self::$altervista = isset($_SERVER['SERVER_ADMIN']) && strpos($_SERVER['SERVER_ADMIN'], 'altervista.org');
self::$zerowebhost = isset($_SERVER['SERVER_ADMIN']) && strpos($_SERVER['SERVER_ADMIN'], '000webhost.io');
self::$altervista = isset($_SERVER['SERVER_ADMIN']) && \strpos($_SERVER['SERVER_ADMIN'], 'altervista.org');
self::$zerowebhost = isset($_SERVER['SERVER_ADMIN']) && \strpos($_SERVER['SERVER_ADMIN'], '000webhost.io');
self::$can_getmypid = !self::$altervista && !self::$zerowebhost;
self::$revision = @file_get_contents(__DIR__.'/../../../.git/refs/heads/master');
self::$revision = @\file_get_contents(__DIR__.'/../../../.git/refs/heads/master');
if (self::$revision) {
self::$revision = trim(self::$revision);
$latest = @file_get_contents('https://phar.madelineproto.xyz/release');
self::$revision = \trim(self::$revision);
$latest = @\file_get_contents('https://phar.madelineproto.xyz/release');
if ($latest) {
$latest = self::$revision === trim($latest) ? '' : ' (AN UPDATE IS REQUIRED)';
$latest = self::$revision === \trim($latest) ? '' : ' (AN UPDATE IS REQUIRED)';
}
self::$revision = 'Revision: '.self::$revision.$latest;
}
self::$can_parallel = false;
if (php_sapi_name() === 'cli' && !(class_exists('\\Phar') && \Phar::running())) {
if (PHP_SAPI === 'cli' && !(\class_exists('\\Phar') && \Phar::running())) {
try {
$back = debug_backtrace(0);
define('AMP_WORKER', 1);
$promise = \Amp\File\get(end($back)['file']);
$back = \debug_backtrace(0);
\define('AMP_WORKER', 1);
$promise = \Amp\File\get(\end($back)['file']);
do {
try {
if (wait($promise)) {
@ -138,19 +138,19 @@ class Magic
} catch (\Throwable $e) {
}
}
if (!self::$can_parallel && !defined('AMP_WORKER') || true) {
if (!self::$can_parallel && !\defined('AMP_WORKER') || true) {
//define('AMP_WORKER', 1);
}
$backtrace = debug_backtrace(0);
self::$script_cwd = self::$cwd = dirname(end($backtrace)['file']);
$backtrace = \debug_backtrace(0);
self::$script_cwd = self::$cwd = \dirname(\end($backtrace)['file']);
try {
self::$cwd = getcwd();
self::$cwd = \getcwd();
self::$can_getcwd = true;
} catch (\danog\MadelineProto\Exception $e) {
}
// Even an empty handler is enough to catch ctrl+c
if (defined('SIGINT')) {
if (\defined('SIGINT')) {
//if (function_exists('pcntl_async_signals')) pcntl_async_signals(true);
Loop::onSignal(SIGINT, static function () {
getStdin()->unreference();
@ -173,18 +173,18 @@ class Magic
);
resolver(new Rfc8484StubResolver($DohConfig));
}
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
try {
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', Magic::$script_cwd.'/MadelineProto.log');
error_log('Enabled PHP logging');
\error_reporting(E_ALL);
\ini_set('log_errors', 1);
\ini_set('error_log', Magic::$script_cwd.'/MadelineProto.log');
\error_log('Enabled PHP logging');
} catch (\danog\MadelineProto\Exception $e) {
//$this->logger->logger('Could not enable PHP logging');
}
}
$res = json_decode(@file_get_contents('https://rpc.madelineproto.xyz/v3.json'), true);
$res = \json_decode(@\file_get_contents('https://rpc.madelineproto.xyz/v3.json'), true);
if (isset($res['ok']) && $res['ok']) {
RPCErrorException::$errorMethodMap = $res['result'];
RPCErrorException::$descriptions += $res['human_result'];
@ -204,10 +204,10 @@ class Magic
try {
if (self::$pid === null) {
self::$pid = getmypid();
self::$pid = \getmypid();
}
return self::$is_fork = self::$pid !== getmypid();
return self::$is_fork = self::$pid !== \getmypid();
} catch (\danog\MadelineProto\Exception $e) {
return self::$can_getmypid = false;
}
@ -215,6 +215,6 @@ class Magic
public static function getcwd()
{
return self::$can_getcwd ? getcwd() : self::$cwd;
return self::$can_getcwd ? \getcwd() : self::$cwd;
}
}

View File

@ -18,8 +18,8 @@
namespace danog\MadelineProto;
use Amp\Artax\Request;
use Amp\Artax\Cookie\ArrayCookieJar;
use Amp\Artax\Request;
/**
* Wrapper for my.telegram.org.
@ -58,8 +58,7 @@ class MyTelegramOrgWrapper
}
$this->settings = MTProto::getSettings($this->settings);
$this->datacenter = new DataCenter(
new class($this->settings)
{
new class($this->settings) {
public function __construct($settings)
{
$this->logger = Logger::getLoggerFromSettings($settings);
@ -75,11 +74,11 @@ class MyTelegramOrgWrapper
{
$this->number = $number;
$request = new Request(self::MY_TELEGRAM_URL.'/auth/send_password', 'POST');
$request = $request->withBody(http_build_query(['phone' => $number]));
$request = $request->withBody(\http_build_query(['phone' => $number]));
$request = $request->withHeaders($this->getHeaders('origin'));
$response = yield $this->datacenter->getHTTPClient()->request($request);
$result = yield $response->getBody();
$resulta = json_decode($result, true);
$resulta = \json_decode($result, true);
if (!isset($resulta['random_hash'])) {
throw new Exception($result);
@ -94,13 +93,13 @@ class MyTelegramOrgWrapper
}
$request = new Request(self::MY_TELEGRAM_URL.'/auth/login', 'POST');
$request = $request->withBody(http_build_query(['phone' => $this->number, 'random_hash' => $this->hash, 'password' => $password]));
$request = $request->withBody(\http_build_query(['phone' => $this->number, 'random_hash' => $this->hash, 'password' => $password]));
$request = $request->withHeaders($this->getHeaders('origin'));
$request = $request->withHeader('user-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
$response = yield $this->datacenter->getHTTPClient()->request($request);
$result = yield $response->getBody();
switch ($result) {
case 'true':
//Logger::log(['Login OK'], Logger::VERBOSE);
@ -128,18 +127,18 @@ class MyTelegramOrgWrapper
$response = yield $this->datacenter->getHTTPClient()->request($request);
$result = yield $response->getBody();
$title = explode('</title>', explode('<title>', $result)[1])[0];
$title = \explode('</title>', \explode('<title>', $result)[1])[0];
switch ($title) {
case 'App configuration':
return true;
case 'Create new application':
$this->creation_hash = explode('"/>', explode('<input type="hidden" name="hash" value="', $result)[1])[0];
$this->creation_hash = \explode('"/>', \explode('<input type="hidden" name="hash" value="', $result)[1])[0];
return false;
}
$this->logged = false;
throw new Exception($title);
}
@ -154,15 +153,15 @@ class MyTelegramOrgWrapper
$response = yield $this->datacenter->getHTTPClient()->request($request);
$result = yield $response->getBody();
$cose = explode('<label for="app_id" class="col-md-4 text-right control-label">App api_id:</label>
$cose = \explode('<label for="app_id" class="col-md-4 text-right control-label">App api_id:</label>
<div class="col-md-7">
<span class="form-control input-xlarge uneditable-input" onclick="this.select();"><strong>', $result);
$asd = explode('</strong></span>', $cose[1]);
$asd = \explode('</strong></span>', $cose[1]);
$api_id = $asd[0];
$cose = explode('<label for="app_hash" class="col-md-4 text-right control-label">App api_hash:</label>
$cose = \explode('<label for="app_hash" class="col-md-4 text-right control-label">App api_hash:</label>
<div class="col-md-7">
<span class="form-control input-xlarge uneditable-input" onclick="this.select();">', $result);
$asd = explode('</span>', $cose[1]);
$asd = \explode('</span>', $cose[1]);
$api_hash = $asd[0];
return ['api_id' => (int) $api_id, 'api_hash' => $api_hash];
@ -176,15 +175,15 @@ class MyTelegramOrgWrapper
if (yield $this->has_app_async()) {
throw new Exception('The app was already created!');
}
$request = new Request(self::MY_TELEGRAM_URL.'/apps/create', 'POST');
$request = $request->withHeaders($this->getHeaders('app'));
$request = $request->withBody(http_build_query(['hash' => $this->creation_hash, 'app_title' => $settings['app_title'], 'app_shortname' => $settings['app_shortname'], 'app_url' => $settings['app_url'], 'app_platform' => $settings['app_platform'], 'app_desc' => $settings['app_desc']]));
$request = $request->withBody(\http_build_query(['hash' => $this->creation_hash, 'app_title' => $settings['app_title'], 'app_shortname' => $settings['app_shortname'], 'app_url' => $settings['app_url'], 'app_platform' => $settings['app_platform'], 'app_desc' => $settings['app_desc']]));
$response = yield $this->datacenter->getHTTPClient()->request($request);
$result = yield $response->getBody();
if ($result) {
throw new Exception(html_entity_decode($result));
throw new Exception(\html_entity_decode($result));
}
$request = new Request(self::MY_TELEGRAM_URL.'/apps');
@ -192,22 +191,22 @@ class MyTelegramOrgWrapper
$response = yield $this->datacenter->getHTTPClient()->request($request);
$result = yield $response->getBody();
$title = explode('</title>', explode('<title>', $result)[1])[0];
$title = \explode('</title>', \explode('<title>', $result)[1])[0];
if ($title === 'Create new application') {
$this->creation_hash = explode('"/>', explode('<input type="hidden" name="hash" value="', $result)[1])[0];
$this->creation_hash = \explode('"/>', \explode('<input type="hidden" name="hash" value="', $result)[1])[0];
throw new \danog\MadelineProto\Exception('App creation failed');
}
$cose = explode('<label for="app_id" class="col-md-4 text-right control-label">App api_id:</label>
$cose = \explode('<label for="app_id" class="col-md-4 text-right control-label">App api_id:</label>
<div class="col-md-7">
<span class="form-control input-xlarge uneditable-input" onclick="this.select();"><strong>', $result);
$asd = explode('</strong></span>', $cose['1']);
$asd = \explode('</strong></span>', $cose['1']);
$api_id = $asd['0'];
$cose = explode('<label for="app_hash" class="col-md-4 text-right control-label">App api_hash:</label>
$cose = \explode('<label for="app_hash" class="col-md-4 text-right control-label">App api_hash:</label>
<div class="col-md-7">
<span class="form-control input-xlarge uneditable-input" onclick="this.select();">', $result);
$asd = explode('</span>', $cose['1']);
$asd = \explode('</span>', $cose['1']);
$api_hash = $asd['0'];
return ['api_id' => (int) $api_id, 'api_hash' => $api_hash];
@ -254,8 +253,8 @@ class MyTelegramOrgWrapper
$final_headers = [];
foreach ($headers as $header) {
list($key, $value) = explode(':', $header, 2);
$final_headers[trim($key)] = trim($value);
list($key, $value) = \explode(':', $header, 2);
$final_headers[\trim($key)] = \trim($value);
}
return $final_headers;
@ -272,9 +271,9 @@ class MyTelegramOrgWrapper
public function __call($name, $arguments)
{
$name .= '_async';
$async = is_array(end($arguments)) && isset(end($arguments)['async']) ? end($arguments)['async'] : $this->async;
$async = \is_array(\end($arguments)) && isset(\end($arguments)['async']) ? \end($arguments)['async'] : $this->async;
if (!method_exists($this, $name)) {
if (!\method_exists($this, $name)) {
throw new Exception("$name does not exist!");
}
return $async ? $this->{$name}(...$arguments) : $this->wait($this->{$name}(...$arguments));

View File

@ -25,7 +25,7 @@ class PTSException extends \Exception
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 = '')

View File

@ -78,16 +78,16 @@ class RPCErrorException extends \Exception
return $error;
}
$error = preg_replace('/\d+$/', "X", $error);
$error = \preg_replace('/\d+$/', "X", $error);
$description = self::$descriptions[$error] ?? '';
if (!isset(self::$errorMethodMap[$code][$method][$error])
|| !isset(self::$descriptions[$error])
|| $code === 500
) {
$res = json_decode(@file_get_contents('https://rpc.pwrtelegram.xyz/?method='.$method.'&code='.$code.'&error='.$error, false, stream_context_create(['http'=>['timeout' => 3]])), true);
$res = \json_decode(@\file_get_contents('https://rpc.pwrtelegram.xyz/?method='.$method.'&code='.$code.'&error='.$error, false, \stream_context_create(['http'=>['timeout' => 3]])), true);
if (isset($res['ok']) && $res['ok'] && isset($res['result'])) {
$description = $res['result'];
@ -104,9 +104,9 @@ class RPCErrorException extends \Exception
public function __toString()
{
$result = sprintf(\danog\MadelineProto\Lang::$current_lang['rpc_tg_error'], self::localizeMessage($this->caller, $this->code, $this->message)." ({$this->code})", $this->rpc, $this->file, $this->line.PHP_EOL, \danog\MadelineProto\Magic::$revision.PHP_EOL.PHP_EOL).PHP_EOL.$this->getTLTrace().PHP_EOL;
if (php_sapi_name() !== 'cli') {
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
$result = \sprintf(\danog\MadelineProto\Lang::$current_lang['rpc_tg_error'], self::localizeMessage($this->caller, $this->code, $this->message)." ({$this->code})", $this->rpc, $this->file, $this->line.PHP_EOL, \danog\MadelineProto\Magic::$revision.PHP_EOL.PHP_EOL).PHP_EOL.$this->getTLTrace().PHP_EOL;
if (PHP_SAPI !== 'cli') {
$result = \str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
}
return $result;
@ -125,16 +125,15 @@ class RPCErrorException extends \Exception
$this->line = $level['line'];
$this->file = $level['file'];
$additional = $level['args'];
}
}
if (!self::$rollbar || !class_exists(\Rollbar\Rollbar::class)) {
if (!self::$rollbar || !\class_exists(\Rollbar\Rollbar::class)) {
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;
}
if (strpos($this->rpc, 'FLOOD_WAIT_') !== false) {
if (\strpos($this->rpc, 'FLOOD_WAIT_') !== false) {
return;
}
$message === 'Telegram is having internal issues, please try again later.' ? \Rollbar\Rollbar::log(\Rollbar\Payload\Level::critical(), $message) : \Rollbar\Rollbar::log(\Rollbar\Payload\Level::error(), $this, $additional);

View File

@ -35,7 +35,7 @@ class RSA
$this->n = self::getVar($key, 'modulus');
$this->e = self::getVar($key, 'exponent');
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['computing_fingerprint'], Logger::ULTRA_VERBOSE);
$this->fp = substr(sha1((yield $this->serialize_object_async(['type' => 'bytes'], $this->n->toBytes(), 'key')).(yield $this->serialize_object_async(['type' => 'bytes'], $this->e->toBytes(), 'key')), true), -8);
$this->fp = \substr(\sha1((yield $this->serialize_object_async(['type' => 'bytes'], $this->n->toBytes(), 'key')).(yield $this->serialize_object_async(['type' => 'bytes'], $this->e->toBytes(), 'key')), true), -8);
return $this;
}
@ -52,7 +52,7 @@ class RSA
return (new \phpseclib\Math\BigInteger((string) $data, 256))->powMod($this->e, $this->n)->toBytes();
}
/**
* Accesses a private variable from an object
* Accesses a private variable from an object.
*
* @param object $obj
* @param string $var
@ -61,7 +61,7 @@ class RSA
*/
public static function getVar($obj, $var)
{
$reflection = new \ReflectionClass(get_class($obj));
$reflection = new \ReflectionClass(\get_class($obj));
$prop = $reflection->getProperty($var);
$prop->setAccessible(true);
return $prop->getValue($obj);

View File

@ -43,12 +43,12 @@ trait AuthKeyHandler
$b = new \phpseclib\Math\BigInteger($this->random(256), 256);
$params['g_a'] = new \phpseclib\Math\BigInteger((string) $params['g_a'], 256);
$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)];
//$this->logger->logger($key);
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
$key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16);
$key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20);
$this->secret_chats[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputEncryptedChat' => ['_' => 'inputEncryptedChat', 'chat_id' => $params['id'], 'access_hash' => $params['access_hash']], 'in_seq_no_x' => 1, 'out_seq_no_x' => 0, 'in_seq_no' => 0, 'out_seq_no' => 0, 'layer' => 8, 'ttl' => 0, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0], 'key_x' => 'from server', 'mtproto' => 1];
$key['fingerprint'] = \substr(\sha1($key['auth_key'], true), -8);
$key['visualization_orig'] = \substr(\sha1($key['auth_key'], true), 16);
$key['visualization_46'] = \substr(\hash('sha256', $key['auth_key'], true), 20);
$this->secret_chats[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputEncryptedChat' => ['_' => 'inputEncryptedChat', 'chat_id' => $params['id'], 'access_hash' => $params['access_hash']], 'in_seq_no_x' => 1, 'out_seq_no_x' => 0, 'in_seq_no' => 0, 'out_seq_no' => 0, 'layer' => 8, 'ttl' => 0, 'ttr' => 100, 'updated' => \time(), 'incoming' => [], 'outgoing' => [], 'created' => \time(), 'rekeying' => [0], 'key_x' => 'from server', 'mtproto' => 1];
$g_b = $dh_config['g']->powMod($b, $dh_config['p']);
$this->check_G($g_b, $dh_config['p']);
yield $this->method_call_async_read('messages.acceptEncryption', ['peer' => $params['id'], 'g_b' => $g_b->toBytes(), 'key_fingerprint' => $key['fingerprint']], ['datacenter' => $this->datacenter->curdc]);
@ -89,18 +89,18 @@ trait AuthKeyHandler
$dh_config = yield $this->get_dh_config_async();
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
$this->check_G($params['g_a_or_b'], $dh_config['p']);
$key = ['auth_key' => str_pad($params['g_a_or_b']->powMod($this->temp_requested_secret_chats[$params['id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
$key = ['auth_key' => \str_pad($params['g_a_or_b']->powMod($this->temp_requested_secret_chats[$params['id']], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
unset($this->temp_requested_secret_chats[$params['id']]);
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
$key['fingerprint'] = \substr(\sha1($key['auth_key'], true), -8);
//$this->logger->logger($key);
if ($key['fingerprint'] !== $params['key_fingerprint']) {
yield $this->discard_secret_chat_async($params['id']);
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
}
$key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16);
$key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20);
$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];
$key['visualization_orig'] = \substr(\sha1($key['auth_key'], true), 16);
$key['visualization_46'] = \substr(\hash('sha256', $key['auth_key'], true), 20);
$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];
yield $this->notify_layer_async($params['id']);
$this->logger->logger('Secret chat '.$params['id'].' completed successfully!', \danog\MadelineProto\Logger::NOTICE);
}
@ -154,10 +154,10 @@ trait AuthKeyHandler
$b = new \phpseclib\Math\BigInteger($this->random(256), 256);
$params['g_a'] = new \phpseclib\Math\BigInteger((string) $params['g_a'], 256);
$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['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
$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['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->secret_chats[$chat]['rekeying'] = [2, $params['exchange_id']];
$g_b = $dh_config['g']->powMod($b, $dh_config['p']);
@ -177,10 +177,10 @@ trait AuthKeyHandler
$dh_config = yield $this->get_dh_config_async();
$params['g_b'] = new \phpseclib\Math\BigInteger((string) $params['g_b'], 256);
$this->check_G($params['g_b'], $dh_config['p']);
$key = ['auth_key' => str_pad($params['g_b']->powMod($this->temp_rekeyed_secret_chats[$params['exchange_id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
$key = ['auth_key' => \str_pad($params['g_b']->powMod($this->temp_rekeyed_secret_chats[$params['exchange_id']], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
$key['fingerprint'] = \substr(\sha1($key['auth_key'], true), -8);
$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);
if ($key['fingerprint'] !== $params['key_fingerprint']) {
yield $this->method_call_async_read('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]], ['datacenter' => $this->datacenter->curdc]);
@ -192,7 +192,7 @@ trait AuthKeyHandler
$this->secret_chats[$chat]['old_key'] = $this->secret_chats[$chat]['key'];
$this->secret_chats[$chat]['key'] = $key;
$this->secret_chats[$chat]['ttr'] = 100;
$this->secret_chats[$chat]['updated'] = time();
$this->secret_chats[$chat]['updated'] = \time();
$this->updaters[false]->resume();
}
@ -211,7 +211,7 @@ trait AuthKeyHandler
$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]['ttr'] = 100;
$this->secret_chats[$chat]['updated'] = time();
$this->secret_chats[$chat]['updated'] = \time();
unset($this->temp_rekeyed_secret_chats[$params['exchange_id']]);
yield $this->method_call_async_read('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNoop']]], ['datacenter' => $this->datacenter->curdc]);
$this->logger->logger('Secret chat '.$chat.' rekeyed successfully!', \danog\MadelineProto\Logger::VERBOSE);
@ -233,7 +233,7 @@ trait AuthKeyHandler
public function get_secret_chat($chat)
{
return $this->secret_chats[is_array($chat) ? $chat['chat_id'] : $chat];
return $this->secret_chats[\is_array($chat) ? $chat['chat_id'] : $chat];
}
public function discard_secret_chat_async($chat)

View File

@ -27,14 +27,14 @@ trait MessageHandler
public function encrypt_secret_message_async($chat_id, $message)
{
if (!isset($this->secret_chats[$chat_id])) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $chat_id));
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $chat_id));
return false;
}
$message['random_id'] = $this->random(8);
$this->secret_chats[$chat_id]['ttr']--;
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) {
yield $this->rekey_async($chat_id);
}
$message = ['_' => 'decryptedMessageLayer', 'layer' => $this->secret_chats[$chat_id]['layer'], 'in_seq_no' => $this->generate_secret_in_seq_no($chat_id), 'out_seq_no' => $this->generate_secret_out_seq_no($chat_id), 'message' => $message];
@ -42,19 +42,19 @@ trait MessageHandler
}
$this->secret_chats[$chat_id]['outgoing'][$this->secret_chats[$chat_id]['out_seq_no']] = $message;
$message = yield $this->serialize_object_async(['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) {
$padding = $this->posmod(-strlen($message), 16);
$padding = $this->posmod(-\strlen($message), 16);
if ($padding < 12) {
$padding += 16;
}
$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']);
} 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);
$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);
@ -64,11 +64,11 @@ trait MessageHandler
public function handle_encrypted_update_async($message, $test = false)
{
if (!isset($this->secret_chats[$message['message']['chat_id']])) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $message['message']['chat_id']));
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $message['message']['chat_id']));
return false;
}
$auth_key_id = substr($message['message']['bytes'], 0, 8);
$auth_key_id = \substr($message['message']['bytes'], 0, 8);
$old = false;
if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['key']['fingerprint']) {
if (isset($this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint'])) {
@ -84,8 +84,8 @@ trait MessageHandler
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_mismatch']);
}
}
$message_key = substr($message['message']['bytes'], 8, 16);
$encrypted_data = substr($message['message']['bytes'], 24);
$message_key = \substr($message['message']['bytes'], 8, 16);
$encrypted_data = \substr($message['message']['bytes'], 24);
if ($this->secret_chats[$message['message']['chat_id']]['mtproto'] === 2) {
$this->logger->logger('Trying MTProto v2 decryption for chat '.$message['message']['chat_id'].'...', \danog\MadelineProto\Logger::NOTICE);
@ -113,7 +113,7 @@ trait MessageHandler
}
$deserialized = $this->deserialize($message_data, ['type' => '']);
$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) {
yield $this->rekey_async($message['message']['chat_id']);
}
unset($message['message']['bytes']);
@ -126,18 +126,18 @@ trait MessageHandler
{
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);
$message_data_length = unpack('V', substr($decrypted_data, 0, 4))[1];
$message_data = substr($decrypted_data, 4, $message_data_length);
if ($message_data_length > strlen($decrypted_data)) {
$message_data_length = \unpack('V', \substr($decrypted_data, 0, 4))[1];
$message_data = \substr($decrypted_data, 4, $message_data_length);
if ($message_data_length > \strlen($decrypted_data)) {
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']);
}
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');
}
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']);
}
@ -148,21 +148,21 @@ trait MessageHandler
{
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);
$message_data_length = unpack('V', substr($decrypted_data, 0, 4))[1];
$message_data = substr($decrypted_data, 4, $message_data_length);
if ($message_data_length > strlen($decrypted_data)) {
$message_data_length = \unpack('V', \substr($decrypted_data, 0, 4))[1];
$message_data = \substr($decrypted_data, 4, $message_data_length);
if ($message_data_length > \strlen($decrypted_data)) {
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']);
}
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');
}
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');
}
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']);
}

View File

@ -47,7 +47,7 @@ trait ResponseHandler
return;
case 'decryptedMessageActionNotifyLayer':
$this->secret_chats[$update['message']['chat_id']]['layer'] = $update['message']['decrypted_message']['action']['layer'];
if ($update['message']['decrypted_message']['action']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) {
if ($update['message']['decrypted_message']['action']['layer'] >= 17 && \time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) {
yield $this->notify_layer_async($update['message']['chat_id']);
}
if ($update['message']['decrypted_message']['action']['layer'] >= 73) {
@ -90,7 +90,7 @@ trait ResponseHandler
$this->secret_chats[$update['message']['chat_id']]['in_seq_no']++;
if ($update['message']['decrypted_message']['layer'] >= 17) {
$this->secret_chats[$update['message']['chat_id']]['layer'] = $update['message']['decrypted_message']['layer'];
if ($update['message']['decrypted_message']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) {
if ($update['message']['decrypted_message']['layer'] >= 17 && \time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) {
yield $this->notify_layer_async($update['message']['chat_id']);
}
}
@ -99,7 +99,7 @@ trait ResponseHandler
}
break;
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;
}
}

View File

@ -57,9 +57,8 @@ trait SeqNoHandler
yield $this->discard_secret_chat_async($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);
} else {
$C++;
}
$C++;
}
}
//$this->logger->logger($C, $seqno);

View File

@ -30,25 +30,25 @@ class Server
public function __construct($settings)
{
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
\danog\MadelineProto\Logger::constructor(3);
if (!extension_loaded('sockets')) {
if (!\extension_loaded('sockets')) {
throw new Exception(['extension', 'sockets']);
}
if (!extension_loaded('pcntl')) {
if (!\extension_loaded('pcntl')) {
throw new Exception(['extension', 'pcntl']);
}
$this->settings = $settings;
$this->mypid = getmypid();
$this->mypid = \getmypid();
}
public function start()
{
pcntl_signal(SIGTERM, [$this, 'sig_handler']);
pcntl_signal(SIGINT, [$this, 'sig_handler']);
pcntl_signal(SIGCHLD, [$this, 'sig_handler']);
\pcntl_signal(SIGTERM, [$this, 'sig_handler']);
\pcntl_signal(SIGINT, [$this, 'sig_handler']);
\pcntl_signal(SIGCHLD, [$this, 'sig_handler']);
$this->sock = new \Socket($this->settings['type'], SOCK_STREAM, $this->settings['protocol']);
$this->sock->bind($this->settings['address'], $this->settings['port']);
@ -60,7 +60,7 @@ class Server
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
\danog\MadelineProto\Logger::log('Server started! Listening on '.$this->settings['address'].':'.$this->settings['port']);
while (true) {
pcntl_signal_dispatch();
\pcntl_signal_dispatch();
try {
if ($sock = $this->sock->accept()) {
@ -73,7 +73,7 @@ class Server
private function handle($socket)
{
$pid = pcntl_fork();
$pid = \pcntl_fork();
if ($pid == -1) {
die('could not fork');
} elseif ($pid) {
@ -86,12 +86,12 @@ class Server
public function __destruct()
{
if ($this->mypid === getmypid()) {
if ($this->mypid === \getmypid()) {
\danog\MadelineProto\Logger::log('Shutting main process '.$this->mypid.' down');
unset($this->sock);
foreach ($this->pids as $pid) {
\danog\MadelineProto\Logger::log("Waiting for $pid");
pcntl_wait($pid);
\pcntl_wait($pid);
}
\danog\MadelineProto\Logger::log('Done, closing main process');
@ -107,7 +107,7 @@ class Server
exit();
case SIGCHLD:
pcntl_waitpid(-1, $status);
\pcntl_waitpid(-1, $status);
break;
}
}

View File

@ -34,7 +34,7 @@ class Handler extends \danog\MadelineProto\Connection
public function __magic_construct($socket, $extra, $ip, $port, $protocol, $timeout, $ipv6)
{
\danog\MadelineProto\Magic::$pid = getmypid();
\danog\MadelineProto\Magic::$pid = \getmypid();
$this->sock = $socket;
$this->sock->setBlocking(true);
$this->must_open = false;
@ -47,7 +47,7 @@ class Handler extends \danog\MadelineProto\Connection
public function __destruct()
{
echo 'Closing socket in fork '.getmypid().PHP_EOL;
echo 'Closing socket in fork '.\getmypid().PHP_EOL;
unset($this->sock);
$this->destruct_madeline();
}
@ -71,31 +71,31 @@ class Handler extends \danog\MadelineProto\Connection
$first_byte = $this->sock->read(1);
if ($first_byte === chr(239)) {
if ($first_byte === \chr(239)) {
$this->protocol = 'tcp_abridged';
} else {
$first_byte .= $this->sock->read(3);
if ($first_byte === str_repeat(chr(238), 4)) {
if ($first_byte === \str_repeat(\chr(238), 4)) {
$this->protocol = 'tcp_intermediate';
} else {
$this->protocol = 'tcp_full';
$packet_length = unpack('V', $first_byte)[1];
$packet_length = \unpack('V', $first_byte)[1];
$packet = $this->read($packet_length - 4);
if (strrev(hash('crc32b', $first_byte.substr($packet, 0, -4), true)) !== substr($packet, -4)) {
if (\strrev(\hash('crc32b', $first_byte.\substr($packet, 0, -4), true)) !== \substr($packet, -4)) {
throw new Exception('CRC32 was not correct!');
}
$this->in_seq_no++;
$in_seq_no = unpack('V', substr($packet, 0, 4))[1];
$in_seq_no = \unpack('V', \substr($packet, 0, 4))[1];
if ($in_seq_no != $this->in_seq_no) {
throw new Exception('Incoming seq_no mismatch');
}
$buffer = substr($packet, 4, $packet_length - 12);
$buffer = \substr($packet, 4, $packet_length - 12);
}
}
while (true) {
pcntl_signal_dispatch();
\pcntl_signal_dispatch();
$request_id = 0;
try {
@ -103,12 +103,12 @@ class Handler extends \danog\MadelineProto\Connection
$message = $buffer;
$buffer = '';
} else {
$time = time();
$time = \time();
$message = $this->read_message();
}
} catch (\danog\MadelineProto\NothingInTheSocketException $e) {
echo $e;
if (time() - $time < 2) {
if (\time() - $time < 2) {
$this->sock = null;
}
continue;
@ -139,17 +139,17 @@ class Handler extends \danog\MadelineProto\Connection
public function on_request($request_id, $method, $args)
{
if (count($method) === 0 || count($method) > 2) {
if (\count($method) === 0 || \count($method) > 2) {
throw new \danog\MadelineProto\Exception('Invalid method called');
}
array_walk($args, [$this, 'walker']);
\array_walk($args, [$this, 'walker']);
if ($method[0] === '__construct') {
if (count($args) === 1 && is_array($args[0])) {
if (\count($args) === 1 && \is_array($args[0])) {
$args[0]['logger'] = ['logger' => 4, 'logger_param' => [$this, 'logger']];
$args[0]['updates']['callback'] = [$this, 'update_handler'];
} elseif (count($args) === 2 && is_array($args[1])) {
} elseif (\count($args) === 2 && \is_array($args[1])) {
$args[1]['logger'] = ['logger' => 4, 'logger_param' => [$this, 'logger']];
$args[1]['updates']['callback'] = [$this, 'update_handler'];
}
@ -165,42 +165,41 @@ class Handler extends \danog\MadelineProto\Connection
throw new \danog\MadelineProto\Exception('__construct was not called');
}
if (count($method) === 1) {
if (\count($method) === 1) {
return $this->madeline->{$method[0]}(...$args);
}
if (count($method) === 2) {
if (\count($method) === 2) {
return $this->madeline->{$method[0]}->{$method[1]}(...$args);
}
}
private function walker(&$arg)
{
if (is_array($arg)) {
if (\is_array($arg)) {
if (isset($arg['_'])) {
if ($arg['_'] === 'fileCallback' && isset($arg['callback']) && isset($arg['file']) && !method_exists($this, $arg['callback']['callback'])) {
if ($arg['_'] === 'fileCallback' && isset($arg['callback']) && isset($arg['file']) && !\method_exists($this, $arg['callback']['callback'])) {
if (isset($arg['file']['_']) && $arg['file']['_'] === 'stream') {
$arg['file'] = fopen('madelineSocket://', 'r+b', false, Stream::getContext($this, $arg['file']['stream_id']));
$arg['file'] = \fopen('madelineSocket://', 'r+b', false, Stream::getContext($this, $arg['file']['stream_id']));
}
$arg = new \danog\MadelineProto\FileCallback($arg['file'], [$this, $arg['callback']['callback']]);
return;
} elseif ($arg['_'] === 'callback' && isset($arg['callback']) && !method_exists($this, $arg['callback'])) {
} elseif ($arg['_'] === 'callback' && isset($arg['callback']) && !\method_exists($this, $arg['callback'])) {
$arg = [$this, $arg['callback']];
return;
} elseif ($arg['_'] === 'stream' && isset($arg['stream_id'])) {
$arg = fopen('madelineSocket://', 'r+b', false, Stream::getContext($this, $arg['stream_id']));
$arg = \fopen('madelineSocket://', 'r+b', false, Stream::getContext($this, $arg['stream_id']));
return;
} elseif ($arg['_'] === 'bytes' && isset($arg['bytes'])) {
$arg = base64_decode($args['bytes']);
$arg = \base64_decode($args['bytes']);
return;
} else {
array_walk($arg, [$this, 'walker']);
}
\array_walk($arg, [$this, 'walker']);
} else {
array_walk($arg, [$this, 'walker']);
\array_walk($arg, [$this, 'walker']);
}
}
}
@ -226,15 +225,15 @@ class Handler extends \danog\MadelineProto\Connection
$exception['code'] = $e->getCode();
$exception['trace'] = ['_' => 'socketTLTrace', 'frames' => []];
$tl = false;
foreach (array_reverse($e->getTrace()) as $k => $frame) {
foreach (\array_reverse($e->getTrace()) as $k => $frame) {
$tl_frame = ['_' => 'socketTLFrame'];
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] !== '') {
$tl_frame['tl_param'] = (string) $frame['args'][2];
$tl = true;
}
} else {
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;
}
if (isset($frame['file'])) {
@ -245,7 +244,7 @@ class Handler extends \danog\MadelineProto\Connection
$tl_frame['function'] = $frame['function'];
}
if (isset($frame['args'])) {
$args = json_encode($frame['args']);
$args = \json_encode($frame['args']);
if ($args !== false) {
$tl_frame['args'] = $args;
}
@ -275,7 +274,7 @@ class Handler extends \danog\MadelineProto\Connection
try {
$this->logging = true;
$message = ['_' => 'socketMessageLog', 'data' => $message, 'level' => $level, 'thread' => \danog\MadelineProto\Magic::$has_thread && is_object(\Thread::getCurrentThread()), 'process' => \danog\MadelineProto\Magic::is_fork(), 'file' => basename(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['file'], '.php')];
$message = ['_' => 'socketMessageLog', 'data' => $message, 'level' => $level, 'thread' => \danog\MadelineProto\Magic::$has_thread && \is_object(\Thread::getCurrentThread()), 'process' => \danog\MadelineProto\Magic::is_fork(), 'file' => \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['file'], '.php')];
$this->send_message_safe(yield $this->serialize_object_async(['type' => ''], $message, 'log'));
} finally {

View File

@ -26,8 +26,8 @@ class Proxy extends \danog\MadelineProto\Connection
{
public function __magic_construct($socket, $extra, $ip, $port, $protocol, $timeout, $ipv6)
{
\danog\MadelineProto\Logger::log('Got connection '.getmypid().'!');
\danog\MadelineProto\Magic::$pid = getmypid();
\danog\MadelineProto\Logger::log('Got connection '.\getmypid().'!');
\danog\MadelineProto\Magic::$pid = \getmypid();
\danog\MadelineProto\Lang::$current_lang = [];
$this->sock = $socket;
$this->sock->setBlocking(true);
@ -43,7 +43,7 @@ class Proxy extends \danog\MadelineProto\Connection
public function __destruct()
{
\danog\MadelineProto\Logger::log('Closing fork '.getmypid().'!');
\danog\MadelineProto\Logger::log('Closing fork '.\getmypid().'!');
unset($this->sock);
}
@ -52,27 +52,27 @@ class Proxy extends \danog\MadelineProto\Connection
$this->protocol = 'obfuscated2';
$random = $this->sock->read(64);
$reversed = strrev(substr($random, 8, 48));
$key = substr($random, 8, 32);
$keyRev = substr($reversed, 0, 32);
$reversed = \strrev(\substr($random, 8, 48));
$key = \substr($random, 8, 32);
$keyRev = \substr($reversed, 0, 32);
if (isset($this->extra['secret'])) {
$key = hash('sha256', $key.$this->extra['secret'], true);
$keyRev = hash('sha256', $keyRev.$this->extra['secret'], true);
$key = \hash('sha256', $key.$this->extra['secret'], true);
$keyRev = \hash('sha256', $keyRev.$this->extra['secret'], true);
}
$this->obfuscated = ['encryption' => new \phpseclib\Crypt\AES('ctr'), 'decryption' => new \phpseclib\Crypt\AES('ctr')];
$this->obfuscated['encryption']->enableContinuousBuffer();
$this->obfuscated['decryption']->enableContinuousBuffer();
$this->obfuscated['decryption']->setKey($key);
$this->obfuscated['decryption']->setIV(substr($random, 40, 16));
$this->obfuscated['decryption']->setIV(\substr($random, 40, 16));
$this->obfuscated['encryption']->setKey($keyRev);
$this->obfuscated['encryption']->setIV(substr($reversed, 32, 16));
$random = substr_replace($random, substr(@$this->obfuscated['decryption']->encrypt($random), 56, 8), 56, 8);
$this->obfuscated['encryption']->setIV(\substr($reversed, 32, 16));
$random = \substr_replace($random, \substr(@$this->obfuscated['decryption']->encrypt($random), 56, 8), 56, 8);
if (substr($random, 56, 4) !== str_repeat(chr(0xef), 4)) {
if (\substr($random, 56, 4) !== \str_repeat(\chr(0xef), 4)) {
throw new \danog\MadelineProto\Exception('Wrong protocol version');
}
$dc = abs(unpack('s', substr($random, 60, 2))[1]);
$dc = \abs(\unpack('s', \substr($random, 60, 2))[1]);
$socket = $this->extra['madeline'][$dc];
$socket->__construct($socket->proxy, $socket->extra, $socket->ip, $socket->port, $socket->protocol, $timeout = $this->extra['timeout'], $socket->ipv6);
@ -82,7 +82,7 @@ class Proxy extends \danog\MadelineProto\Connection
$write = [];
$except = [];
while (true) {
pcntl_signal_dispatch();
\pcntl_signal_dispatch();
try {
$read = [$this->getSocket(), $socket->getSocket()];

View File

@ -32,18 +32,18 @@ class Stream
public static function getContext($handler, $stream_id)
{
if (!self::$_isRegistered) {
stream_wrapper_register(self::WRAPPER_NAME, get_class());
\stream_wrapper_register(self::WRAPPER_NAME, __CLASS__);
self::$_isRegistered = true;
}
return stream_context_create([self::WRAPPER_NAME => ['handler' => $handler, 'stream_id' => $stream_id]]);
return \stream_context_create([self::WRAPPER_NAME => ['handler' => $handler, 'stream_id' => $stream_id]]);
}
public function stream_open($path, $mode, $options, &$opened_path)
{
$opt = stream_context_get_options($this->context);
$opt = \stream_context_get_options($this->context);
if (!is_array($opt[self::WRAPPER_NAME]) ||
if (!\is_array($opt[self::WRAPPER_NAME]) ||
!isset($opt[self::WRAPPER_NAME]['handler']) ||
!($opt[self::WRAPPER_NAME]['handler'] instanceof Handler) ||
!isset($opt[self::WRAPPER_NAME]['stream_id'])) {

View File

@ -24,26 +24,26 @@ namespace danog\MadelineProto;
class Shutdown
{
/**
* Callbacks to call on shutdown
* Callbacks to call on shutdown.
*
* @var array<callable>
*/
private static $callbacks = [];
/**
* Whether the main shutdown was registered
* Whether the main shutdown was registered.
*
* @var boolean
*/
private static $registered = false;
/**
* Incremental ID for new callback
* Incremental ID for new callback.
*
* @var integer
*/
private static $id = 0;
/**
* Function to be called on shutdown
*
* Function to be called on shutdown.
*
* @return void
*/
public static function shutdown()
@ -53,11 +53,11 @@ class Shutdown
}
}
/**
* Add a callback for script shutdown
*
* Add a callback for script shutdown.
*
* @param callable $callback The callback to set
* @param null|string $id The optional callback ID
*
*
* @return The callback ID
*/
public static function addCallback($callback, $id = null)
@ -67,16 +67,16 @@ class Shutdown
}
self::$callbacks[$id] = $callback;
if (!self::$registered) {
register_shutdown_function([__CLASS__, 'shutdown']);
\register_shutdown_function([__CLASS__, 'shutdown']);
self::$registered = true;
}
return $id;
}
/**
* Remove a callback from the script shutdown callable list
*
* Remove a callback from the script shutdown callable list.
*
* @param null|string $id The optional callback ID
*
*
* @return bool true if the callback was removed correctly, false otherwise
*/
public static function removeCallback($id)
@ -87,4 +87,4 @@ class Shutdown
}
return false;
}
}
}

View File

@ -18,16 +18,16 @@
namespace danog\MadelineProto\Stream\Common;
use Amp\ByteStream\ClosedException;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use function Amp\Socket\connect;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\RawStreamInterface;
use Amp\ByteStream\ClosedException;
use function Amp\Socket\connect;
/**
* Buffered raw stream.
@ -55,7 +55,7 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
public function connectAsync(ConnectionContext $ctx, string $header = ''): \Generator
{
$this->stream = yield $ctx->getStream($header);
$this->memory_stream = fopen('php://memory', 'r+');
$this->memory_stream = \fopen('php://memory', 'r+');
return true;
}
@ -96,7 +96,7 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
public function disconnect()
{
if ($this->memory_stream) {
fclose($this->memory_stream);
\fclose($this->memory_stream);
$this->memory_stream = null;
}
if ($this->stream) {
@ -117,16 +117,16 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
if (!$this->stream) {
throw new ClosedException("MadelineProto stream was disconnected");
}
$size = fstat($this->memory_stream)['size'];
$offset = ftell($this->memory_stream);
$size = \fstat($this->memory_stream)['size'];
$offset = \ftell($this->memory_stream);
$length = $size - $offset;
if ($length === 0 || $size > self::MAX_SIZE) {
$new_memory_stream = fopen('php://memory', 'r+');
$new_memory_stream = \fopen('php://memory', 'r+');
if ($length) {
fwrite($new_memory_stream, fread($this->memory_stream, $length));
fseek($new_memory_stream, 0);
\fwrite($new_memory_stream, \fread($this->memory_stream, $length));
\fseek($new_memory_stream, 0);
}
fclose($this->memory_stream);
\fclose($this->memory_stream);
$this->memory_stream = $new_memory_stream;
}
@ -142,9 +142,9 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
*/
public function getWriteBuffer(int $length, string $append = ''): Promise
{
if (strlen($append)) {
if (\strlen($append)) {
$this->append = $append;
$this->append_after = $length - strlen($append);
$this->append_after = $length - \strlen($append);
}
return new \Amp\Success($this);
@ -162,11 +162,11 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
if (!$this->stream) {
throw new ClosedException("MadelineProto stream was disconnected");
}
$size = fstat($this->memory_stream)['size'];
$offset = ftell($this->memory_stream);
$size = \fstat($this->memory_stream)['size'];
$offset = \ftell($this->memory_stream);
$buffer_length = $size - $offset;
if ($buffer_length >= $length) {
return new Success(fread($this->memory_stream, $length));
return new Success(\fread($this->memory_stream, $length));
}
return $this->call($this->bufferReadAsync($length));
@ -181,11 +181,11 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
*/
public function bufferReadAsync(int $length): \Generator
{
$size = fstat($this->memory_stream)['size'];
$offset = ftell($this->memory_stream);
$size = \fstat($this->memory_stream)['size'];
$offset = \ftell($this->memory_stream);
$buffer_length = $size - $offset;
if ($buffer_length < $length && $buffer_length) {
fseek($this->memory_stream, $offset + $buffer_length);
\fseek($this->memory_stream, $offset + $buffer_length);
}
while ($buffer_length < $length) {
@ -195,12 +195,12 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
throw new \danog\MadelineProto\NothingInTheSocketException();
}
fwrite($this->memory_stream, $chunk);
$buffer_length += strlen($chunk);
\fwrite($this->memory_stream, $chunk);
$buffer_length += \strlen($chunk);
}
fseek($this->memory_stream, $offset);
\fseek($this->memory_stream, $offset);
return fread($this->memory_stream, $length);
return \fread($this->memory_stream, $length);
}
/**
@ -213,7 +213,7 @@ class BufferedRawStream implements BufferedStreamInterface, BufferInterface, Raw
public function bufferWrite(string $data): Promise
{
if ($this->append_after) {
$this->append_after -= strlen($data);
$this->append_after -= \strlen($data);
if ($this->append_after === 0) {
$data .= $this->append;
$this->append = '';

View File

@ -52,7 +52,7 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
*/
public function startReadHash()
{
$this->read_hash = hash_init($this->hash_name);
$this->read_hash = \hash_init($this->hash_name);
}
/**
@ -74,9 +74,9 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
*/
public function getReadHash(): string
{
$hash = hash_final($this->read_hash, true);
$hash = \hash_final($this->read_hash, true);
if ($this->rev) {
$hash = strrev($hash);
$hash = \strrev($hash);
}
$this->read_hash = null;
$this->read_check_after = 0;
@ -102,7 +102,7 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
*/
public function startWriteHash()
{
$this->write_hash = hash_init($this->hash_name);
$this->write_hash = \hash_init($this->hash_name);
}
/**
@ -124,9 +124,9 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
*/
public function getWriteHash(): string
{
$hash = hash_final($this->write_hash, true);
$hash = \hash_final($this->write_hash, true);
if ($this->rev) {
$hash = strrev($hash);
$hash = \strrev($hash);
}
$this->write_hash = null;
$this->write_check_after = 0;
@ -161,16 +161,16 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
throw new \danog\MadelineProto\Exception('Tried to read too much out of frame data');
}
$data = yield $this->read_buffer->bufferRead($length);
hash_update($this->read_hash, $data);
\hash_update($this->read_hash, $data);
$hash = $this->getReadHash();
if ($hash !== yield $this->read_buffer->bufferRead(strlen($hash))) {
if ($hash !== yield $this->read_buffer->bufferRead(\strlen($hash))) {
throw new \danog\MadelineProto\Exception('Hash mismatch');
}
return $data;
}
$data = yield $this->read_buffer->bufferRead($length);
hash_update($this->read_hash, $data);
\hash_update($this->read_hash, $data);
if ($this->read_check_after) {
$this->read_check_pos += $length;
}
@ -187,10 +187,10 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
*/
public function setExtra($hash)
{
$rev = strpos($hash, '_rev');
$rev = \strpos($hash, '_rev');
$this->rev = false;
if ($rev !== false) {
$hash = substr($hash, 0, $rev);
$hash = \substr($hash, 0, $rev);
$this->rev = true;
}
$this->hash_name = $hash;
@ -292,12 +292,12 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
return $this->write_buffer->bufferWrite($length);
}
$length = strlen($data);
$length = \strlen($data);
if ($this->write_check_after && $length + $this->write_check_pos >= $this->write_check_after) {
if ($length + $this->write_check_pos > $this->write_check_after) {
throw new \danog\MadelineProto\Exception('Too much out of frame data was sent, cannot check hash');
}
hash_update($this->write_hash, $data);
\hash_update($this->write_hash, $data);
return $this->write_buffer->bufferWrite($data.$this->getWriteHash());
}
@ -305,7 +305,7 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
$this->write_check_pos += $length;
}
if ($this->write_hash) {
hash_update($this->write_hash, $data);
\hash_update($this->write_hash, $data);
}
return $this->write_buffer->bufferWrite($data);

View File

@ -18,12 +18,6 @@
namespace danog\MadelineProto\Stream\Common;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use function Amp\Socket\connect;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
@ -44,25 +38,25 @@ class SimpleBufferedRawStream extends BufferedRawStream implements BufferedStrea
*/
public function bufferReadAsync(int $length): \Generator
{
$size = fstat($this->memory_stream)['size'];
$offset = ftell($this->memory_stream);
$size = \fstat($this->memory_stream)['size'];
$offset = \ftell($this->memory_stream);
$buffer_length = $size - $offset;
if ($buffer_length < $length && $buffer_length) {
fseek($this->memory_stream, $offset + $buffer_length);
\fseek($this->memory_stream, $offset + $buffer_length);
}
while ($buffer_length < $length) {
$chunk = yield $this->read();
if ($chunk === null) {
fseek($this->memory_stream, $offset);
\fseek($this->memory_stream, $offset);
break;
}
fwrite($this->memory_stream, $chunk);
$buffer_length += strlen($chunk);
\fwrite($this->memory_stream, $chunk);
$buffer_length += \strlen($chunk);
}
fseek($this->memory_stream, $offset);
\fseek($this->memory_stream, $offset);
return fread($this->memory_stream, $length);
return \fread($this->memory_stream, $length);
}
/**

View File

@ -21,9 +21,9 @@ namespace danog\MadelineProto\Stream;
use Amp\CancellationToken;
use Amp\Socket\ClientConnectContext;
use Amp\Uri\Uri;
use danog\MadelineProto\Stream\Transport\DefaultStream;
use danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream;
use danog\MadelineProto\Stream\Transport\DefaultStream;
/**
* Connection context class.
@ -66,7 +66,7 @@ class ConnectionContext
*/
private $uri;
/**
* Whether this connection context will be used by the DNS client
* Whether this connection context will be used by the DNS client.
*
* @var bool
*/
@ -109,7 +109,7 @@ class ConnectionContext
private $key = 0;
/**
* Read callback
* Read callback.
*
* @var callable
*/
@ -149,7 +149,7 @@ class ConnectionContext
public function setUri($uri): self
{
$this->uri = $uri instanceof Uri ? $uri : new Uri($uri);
return $this;
}
@ -197,7 +197,7 @@ class ConnectionContext
return $this->cancellationToken;
}
/**
* Return a clone of the current connection context
* Return a clone of the current connection context.
*
* @return self
*/
@ -220,7 +220,7 @@ class ConnectionContext
}
/**
* Whether this is a test connection
* Whether this is a test connection.
*
* @return bool
*/
@ -229,7 +229,7 @@ class ConnectionContext
return $this->test;
}
/**
* Whether this is a media connection
* Whether this is a media connection.
*
* @return bool
*/
@ -239,7 +239,7 @@ class ConnectionContext
}
/**
* Whether this is a CDN connection
* Whether this is a CDN connection.
*
* @return bool
*/
@ -249,7 +249,7 @@ class ConnectionContext
}
/**
* Whether this connection context will only be used by the DNS client
* Whether this connection context will only be used by the DNS client.
*
* @return bool
*/
@ -257,9 +257,9 @@ class ConnectionContext
{
return $this->isDns;
}
/**
* Whether this connection context will only be used by the DNS client
* Whether this connection context will only be used by the DNS client.
*
* @param boolean $isDns
* @return self
@ -302,13 +302,13 @@ class ConnectionContext
*/
public function setDc($dc): self
{
$int = intval($dc);
$int = \intval($dc);
if (!(1 <= $int && $int <= 1000)) {
throw new Exception("Invalid DC id provided: $dc");
}
$this->dc = $dc;
$this->media = strpos($dc, '_media') !== false;
$this->cdn = strpos($dc, '_cdn') !== false;
$this->media = \strpos($dc, '_media') !== false;
$this->cdn = \strpos($dc, '_cdn') !== false;
return $this;
}
@ -330,7 +330,7 @@ class ConnectionContext
*/
public function getIntDc()
{
$dc = intval($this->dc);
$dc = \intval($this->dc);
if ($this->test) {
$dc += 10000;
}
@ -376,16 +376,16 @@ class ConnectionContext
public function addStream(string $streamName, $extra = null): self
{
$this->nextStreams[] = [$streamName, $extra];
$this->key = count($this->nextStreams) - 1;
$this->key = \count($this->nextStreams) - 1;
return $this;
}
/**
* Set read callback, called every time the socket reads at least a byte
* Set read callback, called every time the socket reads at least a byte.
*
* @param callback $callable Read callback
*
*
* @return void
*/
public function setReadCallback($callable)
@ -394,7 +394,7 @@ class ConnectionContext
}
/**
* Check if a read callback is present
* Check if a read callback is present.
*
* @return boolean
*/
@ -404,7 +404,7 @@ class ConnectionContext
}
/**
* Get read callback
* Get read callback.
*
* @return callable
*/
@ -444,7 +444,7 @@ class ConnectionContext
/**
* Get the inputClientProxy proxy MTProto object
* Get the inputClientProxy proxy MTProto object.
*
* @return array
*/
@ -476,13 +476,13 @@ class ConnectionContext
$string .= ', via ';
$string .= $this->getIpv6() ? 'ipv6' : 'ipv4';
$string .= ' using ';
foreach (array_reverse($this->nextStreams) as $k => $stream) {
foreach (\array_reverse($this->nextStreams) as $k => $stream) {
if ($k) {
$string .= ' => ';
}
$string .= preg_replace('/.*\\\\/', '', $stream[0]);
$string .= \preg_replace('/.*\\\\/', '', $stream[0]);
if ($stream[1] && $stream[0] !== DefaultStream::getName()) {
$string .= ' ('.json_encode($stream[1]).')';
$string .= ' ('.\json_encode($stream[1]).')';
}
}

View File

@ -44,7 +44,7 @@ class AbridgedStream implements BufferedStreamInterface, MTProtoBufferInterface
*/
public function connectAsync(ConnectionContext $ctx, string $header = ''): \Generator
{
$this->stream = yield $ctx->getStream(chr(239).$header);
$this->stream = yield $ctx->getStream(\chr(239).$header);
}
/**
@ -68,11 +68,11 @@ class AbridgedStream implements BufferedStreamInterface, MTProtoBufferInterface
{
$length >>= 2;
if ($length < 127) {
$message = chr($length);
$message = \chr($length);
} else {
$message = chr(127).substr(pack('V', $length), 0, 3);
$message = \chr(127).\substr(\pack('V', $length), 0, 3);
}
$buffer = yield $this->stream->getWriteBuffer(strlen($message) + $length, $append);
$buffer = yield $this->stream->getWriteBuffer(\strlen($message) + $length, $append);
yield $buffer->bufferWrite($message);
return $buffer;
@ -88,9 +88,9 @@ class AbridgedStream implements BufferedStreamInterface, MTProtoBufferInterface
public function getReadBufferAsync(&$length): \Generator
{
$buffer = yield $this->stream->getReadBuffer($l);
$length = ord(yield $buffer->bufferRead(1));
$length = \ord(yield $buffer->bufferRead(1));
if ($length >= 127) {
$length = unpack('V', (yield $buffer->bufferRead(3))."\0")[1];
$length = \unpack('V', (yield $buffer->bufferRead(3))."\0")[1];
}
$length <<= 2;

View File

@ -79,7 +79,7 @@ class FullStream implements BufferedStreamInterface, MTProtoBufferInterface
$this->stream->checkWriteHash($length + 8);
$buffer = yield $this->stream->getWriteBuffer($length + 12, $append);
$this->out_seq_no++;
$buffer->bufferWrite(pack('VV', $length + 12, $this->out_seq_no));
$buffer->bufferWrite(\pack('VV', $length + 12, $this->out_seq_no));
return $buffer;
}
@ -95,11 +95,11 @@ class FullStream implements BufferedStreamInterface, MTProtoBufferInterface
{
$this->stream->startReadHash();
$buffer = yield $this->stream->getReadBuffer($l);
$read_length = unpack('V', yield $buffer->bufferRead(4))[1];
$read_length = \unpack('V', yield $buffer->bufferRead(4))[1];
$length = $read_length - 12;
$this->stream->checkReadHash($read_length - 8);
$this->in_seq_no++;
$in_seq_no = unpack('V', yield $buffer->bufferRead(4))[1];
$in_seq_no = \unpack('V', yield $buffer->bufferRead(4))[1];
if ($in_seq_no != $this->in_seq_no) {
throw new Exception('Incoming seq_no mismatch');
}

View File

@ -92,7 +92,7 @@ class HttpStream implements MTProtoBufferInterface, BufferedProxyStreamInterface
public function getWriteBufferAsync(int $length, string $append = ''): \Generator
{
$headers = 'POST '.$this->uri->getPath()." HTTP/1.1\r\nHost: ".$this->uri->getHost().':'.$this->uri->getPort()."\r\n"."Content-Type: application/x-www-form-urlencoded\r\nConnection: keep-alive\r\nKeep-Alive: timeout=100000, max=10000000\r\nContent-Length: ".$length.$this->header."\r\n\r\n";
$buffer = yield $this->stream->getWriteBuffer(strlen($headers) + $length, $append);
$buffer = yield $this->stream->getWriteBuffer(\strlen($headers) + $length, $append);
yield $buffer->bufferWrite($headers);
return $buffer;
@ -122,27 +122,27 @@ class HttpStream implements MTProtoBufferInterface, BufferedProxyStreamInterface
}
$was_crlf = $piece === "\r\n";
}
$headers = explode("\r\n", $headers);
$headers = \explode("\r\n", $headers);
list($protocol, $code, $description) = explode(' ', $headers[0], 3);
list($protocol, $protocol_version) = explode('/', $protocol);
list($protocol, $code, $description) = \explode(' ', $headers[0], 3);
list($protocol, $protocol_version) = \explode('/', $protocol);
if ($protocol !== 'HTTP') {
throw new \danog\MadelineProto\Exception('Wrong protocol');
}
$code = (int) $code;
unset($headers[0]);
if (array_pop($headers).array_pop($headers) !== '') {
if (\array_pop($headers).\array_pop($headers) !== '') {
throw new \danog\MadelineProto\Exception('Wrong last header');
}
foreach ($headers as $key => $current_header) {
unset($headers[$key]);
$current_header = explode(':', $current_header, 2);
$headers[strtolower($current_header[0])] = trim($current_header[1]);
$current_header = \explode(':', $current_header, 2);
$headers[\strtolower($current_header[0])] = \trim($current_header[1]);
}
$close = $protocol === 'HTTP/1.0';
if (isset($headers['connection'])) {
$close = strtolower($headers['connection']) === 'close';
$close = \strtolower($headers['connection']) === 'close';
}
if ($code !== 200) {

View File

@ -45,7 +45,7 @@ class IntermediatePaddedStream implements BufferedStreamInterface, MTProtoBuffer
*/
public function connectAsync(ConnectionContext $ctx, string $header = ''): \Generator
{
$this->stream = yield $ctx->getStream(str_repeat(chr(221), 4).$header);
$this->stream = yield $ctx->getStream(\str_repeat(\chr(221), 4).$header);
}
/**
@ -69,7 +69,7 @@ class IntermediatePaddedStream implements BufferedStreamInterface, MTProtoBuffer
{
$padding_length = $this->random_int($modulus = 16);
$buffer = yield $this->stream->getWriteBuffer(4 + $length + $padding_length, $append.$this->random($padding_length));
yield $buffer->bufferWrite(pack('V', $padding_length + $length));
yield $buffer->bufferWrite(\pack('V', $padding_length + $length));
return $buffer;
}
@ -84,7 +84,7 @@ class IntermediatePaddedStream implements BufferedStreamInterface, MTProtoBuffer
public function getReadBufferAsync(&$length): \Generator
{
$buffer = yield $this->stream->getReadBuffer($l);
$length = unpack('V', yield $buffer->bufferRead(4))[1];
$length = \unpack('V', yield $buffer->bufferRead(4))[1];
return $buffer;
}

View File

@ -45,7 +45,7 @@ class IntermediateStream implements BufferedStreamInterface, MTProtoBufferInterf
*/
public function connectAsync(ConnectionContext $ctx, string $header = ''): \Generator
{
$this->stream = yield $ctx->getStream(str_repeat(chr(238), 4).$header);
$this->stream = yield $ctx->getStream(\str_repeat(\chr(238), 4).$header);
}
/**
@ -68,7 +68,7 @@ class IntermediateStream implements BufferedStreamInterface, MTProtoBufferInterf
public function getWriteBufferAsync(int $length, string $append = ''): \Generator
{
$buffer = yield $this->stream->getWriteBuffer($length + 4, $append);
yield $buffer->bufferWrite(pack('V', $length));
yield $buffer->bufferWrite(\pack('V', $length));
return $buffer;
}
@ -83,7 +83,7 @@ class IntermediateStream implements BufferedStreamInterface, MTProtoBufferInterf
public function getReadBufferAsync(&$length): \Generator
{
$buffer = yield $this->stream->getReadBuffer($l);
$length = unpack('V', yield $buffer->bufferRead(4))[1];
$length = \unpack('V', yield $buffer->bufferRead(4))[1];
return $buffer;
}

View File

@ -61,35 +61,35 @@ class ObfuscatedStream implements BufferedProxyStreamInterface
do {
$random = $this->random(64);
} while (in_array(substr($random, 0, 4), ['PVrG', 'GET ', 'POST', 'HEAD', str_repeat(chr(238), 4), str_repeat(chr(221), 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), \str_repeat(\chr(221), 4)]) || $random[0] === \chr(0xef) || \substr($random, 4, 4) === "\0\0\0\0");
if (strlen($header) === 1) {
$header = str_repeat($header, 4);
if (\strlen($header) === 1) {
$header = \str_repeat($header, 4);
}
$random = substr_replace($random, $header.substr($random, 56 + strlen($header)), 56);
$random = substr_replace($random, pack('s', $ctx->getIntDc()).substr($random, 60 + 2), 60);
$random = \substr_replace($random, $header.\substr($random, 56 + \strlen($header)), 56);
$random = \substr_replace($random, \pack('s', $ctx->getIntDc()).\substr($random, 60 + 2), 60);
$reversed = strrev($random);
$reversed = \strrev($random);
$key = substr($random, 8, 32);
$keyRev = substr($reversed, 8, 32);
$key = \substr($random, 8, 32);
$keyRev = \substr($reversed, 8, 32);
if (isset($this->extra['secret'])) {
$key = hash('sha256', $key.$this->extra['secret'], true);
$keyRev = hash('sha256', $keyRev.$this->extra['secret'], true);
$key = \hash('sha256', $key.$this->extra['secret'], true);
$keyRev = \hash('sha256', $keyRev.$this->extra['secret'], true);
}
$this->encrypt = new \phpseclib\Crypt\AES('ctr');
$this->encrypt->enableContinuousBuffer();
$this->encrypt->setKey($key);
$this->encrypt->setIV(substr($random, 40, 16));
$this->encrypt->setIV(\substr($random, 40, 16));
$this->decrypt = new \phpseclib\Crypt\AES('ctr');
$this->decrypt->enableContinuousBuffer();
$this->decrypt->setKey($keyRev);
$this->decrypt->setIV(substr($reversed, 40, 16));
$this->decrypt->setIV(\substr($reversed, 40, 16));
$random = substr_replace($random, substr(@$this->encrypt->encrypt($random), 56, 8), 56, 8);
$random = \substr_replace($random, \substr(@$this->encrypt->encrypt($random), 56, 8), 56, 8);
$this->stream = yield $ctx->getStream($random);
}
@ -114,9 +114,9 @@ class ObfuscatedStream implements BufferedProxyStreamInterface
public function getWriteBufferAsync(int $length, string $append = ''): \Generator
{
$this->write_buffer = yield $this->stream->getWriteBuffer($length);
if (strlen($append)) {
if (\strlen($append)) {
$this->append = $append;
$this->append_after = $length - strlen($append);
$this->append_after = $length - \strlen($append);
}
return $this;
@ -162,7 +162,7 @@ class ObfuscatedStream implements BufferedProxyStreamInterface
public function bufferWrite(string $data): Promise
{
if ($this->append_after) {
$this->append_after -= strlen($data);
$this->append_after -= \strlen($data);
if ($this->append_after === 0) {
$data .= $this->append;
$this->append = '';
@ -187,11 +187,11 @@ class ObfuscatedStream implements BufferedProxyStreamInterface
public function setExtra($extra)
{
if (isset($extra['secret'])) {
if (strlen($extra['secret']) > 17) {
$extra['secret'] = hex2bin($extra['secret']);
if (\strlen($extra['secret']) > 17) {
$extra['secret'] = \hex2bin($extra['secret']);
}
if (strlen($extra['secret']) == 17) {
$extra['secret'] = substr($extra['secret'], 1, 16);
if (\strlen($extra['secret']) == 17) {
$extra['secret'] = \substr($extra['secret'], 1, 16);
}
}

View File

@ -54,7 +54,7 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
$port = $uri->getPort();
try {
if (strlen(inet_pton($address) === 16)) {
if (\strlen(\inet_pton($address) === 16)) {
$address = '['.$address.']';
}
} catch (\danog\MadelineProto\Exception $e) {
@ -77,27 +77,27 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
}
$was_crlf = $piece === "\r\n";
}
$headers = explode("\r\n", $headers);
$headers = \explode("\r\n", $headers);
list($protocol, $code, $description) = explode(' ', $headers[0], 3);
list($protocol, $protocol_version) = explode('/', $protocol);
list($protocol, $code, $description) = \explode(' ', $headers[0], 3);
list($protocol, $protocol_version) = \explode('/', $protocol);
if ($protocol !== 'HTTP') {
throw new \danog\MadelineProto\Exception('Wrong protocol');
}
$code = (int) $code;
unset($headers[0]);
if (array_pop($headers).array_pop($headers) !== '') {
if (\array_pop($headers).\array_pop($headers) !== '') {
throw new \danog\MadelineProto\Exception('Wrong last header');
}
foreach ($headers as $key => $current_header) {
unset($headers[$key]);
$current_header = explode(':', $current_header, 2);
$headers[strtolower($current_header[0])] = trim($current_header[1]);
$current_header = \explode(':', $current_header, 2);
$headers[\strtolower($current_header[0])] = \trim($current_header[1]);
}
$close = $protocol === 'HTTP/1.0';
if (isset($headers['connection'])) {
$close = strtolower($headers['connection']) === 'close';
$close = \strtolower($headers['connection']) === 'close';
}
if ($code !== 200) {
@ -111,7 +111,7 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
yield $this->connect($ctx);
}
\danog\MadelineProto\Logger::log(trim($read));
\danog\MadelineProto\Logger::log(\trim($read));
throw new \danog\MadelineProto\Exception($description, $code);
}
@ -125,13 +125,13 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
$read = yield $buffer->bufferRead($length);
}
if ($secure && method_exists($this->getSocket(), 'enableCrypto')) {
if ($secure && \method_exists($this->getSocket(), 'enableCrypto')) {
yield $this->getSocket()->enableCrypto((new ClientTlsContext())->withPeerName($uri->getHost()));
}
\danog\MadelineProto\Logger::log('Connected to '.$address.':'.$port.' via http');
if (strlen($header)) {
yield (yield $this->stream->getWriteBuffer(strlen($header)))->bufferWrite($header);
if (\strlen($header)) {
yield (yield $this->stream->getWriteBuffer(\strlen($header)))->bufferWrite($header);
}
}
@ -185,7 +185,7 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
return '';
}
return 'Proxy-Authorization: Basic '.base64_encode($this->extra['username'].':'.$this->extra['password'])."\r\n";
return 'Proxy-Authorization: Basic '.\base64_encode($this->extra['username'].':'.$this->extra['password'])."\r\n";
}
/**

View File

@ -49,30 +49,30 @@ class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterfac
$secure = $ctx->isSecure();
$ctx->setUri('tcp://'.$this->extra['address'].':'.$this->extra['port'])->secure(false);
$methods = chr(0);
$methods = \chr(0);
if (isset($this->extra['username']) && isset($this->extra['password'])) {
$methods .= chr(2);
$methods .= \chr(2);
}
$this->stream = yield $ctx->getStream(chr(5).chr(strlen($methods)).$methods);
$this->stream = yield $ctx->getStream(\chr(5).\chr(\strlen($methods)).$methods);
$l = 2;
$buffer = yield $this->stream->getReadBuffer($l);
$version = ord(yield $buffer->bufferRead(1));
$method = ord(yield $buffer->bufferRead(1));
$version = \ord(yield $buffer->bufferRead(1));
$method = \ord(yield $buffer->bufferRead(1));
if ($version !== 5) {
throw new \danog\MadelineProto\Exception("Wrong SOCKS5 version: $version");
}
if ($method === 2) {
$auth = chr(1).chr(strlen($this->extra['username'])).$this->extra['username'].chr(strlen($this->extra['password'])).$this->extra['password'];
$auth = \chr(1).\chr(\strlen($this->extra['username'])).$this->extra['username'].\chr(\strlen($this->extra['password'])).$this->extra['password'];
yield $this->stream->write($auth);
$buffer = yield $this->stream->getReadBuffer($l);
$version = ord(yield $buffer->bufferRead(1));
$result = ord(yield $buffer->bufferRead(1));
$version = \ord(yield $buffer->bufferRead(1));
$result = \ord(yield $buffer->bufferRead(1));
if ($version !== 1) {
throw new \danog\MadelineProto\Exception("Wrong authorized SOCKS version: $version");
@ -83,50 +83,50 @@ class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterfac
} elseif ($method !== 0) {
throw new \danog\MadelineProto\Exception("Wrong method: $method");
}
$payload = pack('C3', 0x05, 0x01, 0x00);
$payload = \pack('C3', 0x05, 0x01, 0x00);
try {
$ip = inet_pton($uri->getHost());
$payload .= $ip ? pack('C1', strlen($ip) === 4 ? 0x01 : 0x04).$ip : pack('C2', 0x03, strlen($uri->getHost())).$uri->getHost();
$ip = \inet_pton($uri->getHost());
$payload .= $ip ? \pack('C1', \strlen($ip) === 4 ? 0x01 : 0x04).$ip : \pack('C2', 0x03, \strlen($uri->getHost())).$uri->getHost();
} catch (\danog\MadelineProto\Exception $e) {
$payload .= pack('C2', 0x03, strlen($uri->getHost())).$uri->getHost();
$payload .= \pack('C2', 0x03, \strlen($uri->getHost())).$uri->getHost();
}
$payload .= pack('n', $uri->getPort());
$payload .= \pack('n', $uri->getPort());
yield $this->stream->write($payload);
$l = 4;
$buffer = yield $this->stream->getReadBuffer($l);
$version = ord(yield $buffer->bufferRead(1));
$version = \ord(yield $buffer->bufferRead(1));
if ($version !== 5) {
throw new \danog\MadelineProto\Exception("Wrong SOCKS5 version: $version");
}
$rep = ord(yield $buffer->bufferRead(1));
$rep = \ord(yield $buffer->bufferRead(1));
if ($rep !== 0) {
throw new \danog\MadelineProto\Exception("Wrong SOCKS5 rep: $rep");
}
$rsv = ord(yield $buffer->bufferRead(1));
$rsv = \ord(yield $buffer->bufferRead(1));
if ($rsv !== 0) {
throw new \danog\MadelineProto\Exception("Wrong socks5 final RSV: $rsv");
}
switch (ord(yield $buffer->bufferRead(1))) {
switch (\ord(yield $buffer->bufferRead(1))) {
case 1:
$buffer = yield $this->stream->getReadBuffer($l);
$ip = inet_ntop(yield $buffer->bufferRead(4));
$ip = \inet_ntop(yield $buffer->bufferRead(4));
break;
case 4:
$l = 16;
$buffer = yield $this->stream->getReadBuffer($l);
$ip = inet_ntop(yield $buffer->bufferRead(16));
$ip = \inet_ntop(yield $buffer->bufferRead(16));
break;
case 3:
$l = 1;
$buffer = yield $this->stream->getReadBuffer($l);
$length = ord(yield $buffer->bufferRead(1));
$length = \ord(yield $buffer->bufferRead(1));
$buffer = yield $this->stream->getReadBuffer($length);
$ip = yield $buffer->bufferRead($length);
@ -134,15 +134,15 @@ class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterfac
}
$l = 2;
$buffer = yield $this->stream->getReadBuffer($l);
$port = unpack('n', yield $buffer->bufferRead(2))[1];
$port = \unpack('n', yield $buffer->bufferRead(2))[1];
\danog\MadelineProto\Logger::log(['Connected to '.$ip.':'.$port.' via socks5']);
if ($secure && method_exists($this->getSocket(), 'enableCrypto')) {
if ($secure && \method_exists($this->getSocket(), 'enableCrypto')) {
yield $this->getSocket()->enableCrypto((new ClientTlsContext())->withPeerName($uri->getHost()));
}
if (strlen($header)) {
yield (yield $this->stream->getWriteBuffer(strlen($header)))->bufferWrite($header);
if (\strlen($header)) {
yield (yield $this->stream->getWriteBuffer(\strlen($header)))->bufferWrite($header);
}
}

View File

@ -18,14 +18,12 @@
namespace danog\MadelineProto\Stream\Transport;
use Amp\ByteStream\ClosedException;
use Amp\Promise;
use Amp\Socket\Socket;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\RawStreamInterface;
use function Amp\Socket\connect;
use function Amp\Socket\cryptoConnect;
use danog\MadelineProto\Stream\ProxyStreamInterface;
use Amp\ByteStream\ClosedException;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
* Default stream wrapper.
@ -40,7 +38,7 @@ class DefaultStream extends Socket implements RawStreamInterface, ProxyStreamInt
private $stream;
private $connector = 'Amp\\Socket\\connect';
private $cryptoConnector = 'Amp\\Socket\\cryptoConnect';
public function __construct()
{
}

View File

@ -18,15 +18,13 @@
namespace danog\MadelineProto\Stream\Transport;
use Amp\ByteStream\ClosedException;
use Amp\Promise;
use Amp\Socket\Socket;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\RawStreamInterface;
use function Amp\Socket\connect;
use function Amp\Socket\cryptoConnect;
use danog\MadelineProto\Stream\ProxyStreamInterface;
use Amp\ByteStream\ClosedException;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\ProxyStreamInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
* Premade stream wrapper.
@ -39,7 +37,7 @@ class PremadeStream extends Socket implements RawStreamInterface, ProxyStreamInt
{
use RawStream;
private $stream;
public function __construct()
{
}
@ -95,7 +93,7 @@ class PremadeStream extends Socket implements RawStreamInterface, ProxyStreamInt
{
try {
if ($this->stream) {
if (method_exists($this->stream, 'close')) {
if (\method_exists($this->stream, 'close')) {
$this->stream->close();
}
$this->stream = null;

View File

@ -61,7 +61,7 @@ class WsStream implements RawStreamInterface
$this->compressionFactory = new Rfc7692CompressionFactory();
$handshake = new Handshake(str_replace('tcp://', $ctx->isSecure() ? 'ws://' : 'wss://', $ctx->getStringUri()));
$handshake = new Handshake(\str_replace('tcp://', $ctx->isSecure() ? 'ws://' : 'wss://', $ctx->getStringUri()));
$key = generateKey();
yield $stream->write($this->generateRequest($handshake, $key));

View File

@ -25,15 +25,15 @@ trait BotAPI
{
public function html_entity_decode($stuff)
{
return html_entity_decode(preg_replace('#< *br */? *>#', "\n", $stuff));
return \html_entity_decode(\preg_replace('#< *br */? *>#', "\n", $stuff));
}
public function mb_strlen($text)
{
$length = 0;
$textlength = strlen($text);
$textlength = \strlen($text);
for ($x = 0; $x < $textlength; $x++) {
$char = ord($text[$x]);
$char = \ord($text[$x]);
if (($char & 0xC0) != 0x80) {
$length += 1 + ($char >= 0xf0);
}
@ -56,9 +56,9 @@ trait BotAPI
$new_text = '';
$current_offset = 0;
$current_length = 0;
$text_length = strlen($text);
$text_length = \strlen($text);
for ($x = 0; $x < $text_length; $x++) {
$char = ord($text[$x]);
$char = \ord($text[$x]);
if (($char & 0xC0) != 0x80) {
$current_offset += 1 + ($char >= 0xf0);
if ($current_offset > $offset) {
@ -77,10 +77,10 @@ trait BotAPI
public function mb_str_split($text, $length)
{
$tlength = mb_strlen($text, 'UTF-8');
$tlength = \mb_strlen($text, 'UTF-8');
$result = [];
for ($x = 0; $x < $tlength; $x += $length) {
$result[] = mb_substr($text, $x, $length, 'UTF-8');
$result[] = \mb_substr($text, $x, $length, 'UTF-8');
}
return $result;
@ -180,7 +180,7 @@ trait BotAPI
$newd['entities'] = yield $this->MTProto_to_botAPI_async($data['entities'], $sent_arguments);
}
if (isset($data['media'])) {
$newd = array_merge($newd, yield $this->MTProto_to_botAPI_async($data['media'], $sent_arguments));
$newd = \array_merge($newd, yield $this->MTProto_to_botAPI_async($data['media'], $sent_arguments));
}
return $newd;
@ -222,7 +222,7 @@ trait BotAPI
$newd['forward_from_message_id'] = $data['fwd_from']['channel_post'];
}
if (isset($data['media'])) {
$newd = array_merge($newd, yield $this->MTProto_to_botAPI_async($data['media'], $sent_arguments));
$newd = \array_merge($newd, yield $this->MTProto_to_botAPI_async($data['media'], $sent_arguments));
}
return $newd;
@ -289,7 +289,7 @@ trait BotAPI
}
$res['photo'] = [];
foreach ($data['photo']['sizes'] as $key => $photo) {
if (in_array($photo['_'], ['photoCachedSize', 'photoSize'])) {
if (\in_array($photo['_'], ['photoCachedSize', 'photoSize'])) {
$res['photo'][$key] = yield $this->photosize_to_botapi_async($photo, $data['photo']);
}
}
@ -300,13 +300,13 @@ trait BotAPI
case 'messageMediaDocument':
$type_name = 'document';
$res = [];
if (isset($data['document']['thumbs']) && $data['document']['thumbs'] && in_array(end($data['document']['thumbs'])['_'], ['photoCachedSize', 'photoSize'])) {
$res['thumb'] = yield $this->photosize_to_botapi_async(end($data['document']['thumbs']), [], true);
if (isset($data['document']['thumbs']) && $data['document']['thumbs'] && \in_array(\end($data['document']['thumbs'])['_'], ['photoCachedSize', 'photoSize'])) {
$res['thumb'] = yield $this->photosize_to_botapi_async(\end($data['document']['thumbs']), [], true);
}
foreach ($data['document']['attributes'] as $attribute) {
switch ($attribute['_']) {
case 'documentAttributeFilename':
$pathinfo = pathinfo($attribute['file_name']);
$pathinfo = \pathinfo($attribute['file_name']);
$res['ext'] = isset($pathinfo['extension']) ? '.'.$pathinfo['extension'] : '';
$res['file_name'] = $pathinfo['filename'];
break;
@ -374,11 +374,11 @@ trait BotAPI
$data['document']['_'] = 'bot_'.$type_name;
$res['file_size'] = $data['document']['size'];
$res['mime_type'] = $data['document']['mime_type'];
$res['file_id'] = $this->base64url_encode($this->rle_encode((yield $this->serialize_object_async(['type' => 'File'], $data['document'], 'File')).chr(2)));
$res['file_id'] = $this->base64url_encode($this->rle_encode((yield $this->serialize_object_async(['type' => 'File'], $data['document'], 'File')).\chr(2)));
return [$type_name => $res, 'caption' => isset($data['caption']) ? $data['caption'] : ''];
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['_']));
}
}
@ -487,20 +487,20 @@ trait BotAPI
$text = $this->html_entity_decode($node->textContent);
$length = $this->mb_strlen($text);
$href = $node->getAttribute('href');
if (preg_match('|mention:(.*)|', $href, $matches) || preg_match('|tg://user\?id=(.*)|', $href, $matches)) {
if (\preg_match('|mention:(.*)|', $href, $matches) || \preg_match('|tg://user\?id=(.*)|', $href, $matches)) {
$mention = yield $this->get_info_async($matches[1]);
if (!isset($mention['InputUser'])) {
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
}
$entities[] = ['_' => 'inputMessageEntityMentionName', 'offset' => $offset, 'length' => $length, 'user_id' => $mention['InputUser']];
} elseif (preg_match('|buttonurl:(.*)|', $href)) {
} elseif (\preg_match('|buttonurl:(.*)|', $href)) {
if (!isset($entities['buttons'])) {
$entities['buttons'] = [];
}
if (strpos(substr($href, -4), '|:new|') !== false) {
$entities['buttons'][] = ['_' => 'keyboardButtonUrl', 'text' => $text, 'url' => str_replace(['buttonurl:', ':new'], '', $href), 'new' => true];
if (\strpos(\substr($href, -4), '|:new|') !== false) {
$entities['buttons'][] = ['_' => 'keyboardButtonUrl', 'text' => $text, 'url' => \str_replace(['buttonurl:', ':new'], '', $href), 'new' => true];
} else {
$entities['buttons'][] = ['_' => 'keyboardButtonUrl', 'text' => $text, 'url' => str_replace('buttonurl:', '', $href)];
$entities['buttons'][] = ['_' => 'keyboardButtonUrl', 'text' => $text, 'url' => \str_replace('buttonurl:', '', $href)];
}
break;
} else {
@ -524,19 +524,19 @@ trait BotAPI
return $arguments;
}
if (isset($arguments['parse_mode']['_'])) {
$arguments['parse_mode'] = str_replace('textParseMode', '', $arguments['parse_mode']['_']);
$arguments['parse_mode'] = \str_replace('textParseMode', '', $arguments['parse_mode']['_']);
}
if (stripos($arguments['parse_mode'], 'markdown') !== false) {
if (\stripos($arguments['parse_mode'], 'markdown') !== false) {
$arguments['message'] = \Parsedown::instance()->line($arguments['message']);
$arguments['parse_mode'] = 'HTML';
}
if (stripos($arguments['parse_mode'], 'html') !== false) {
if (\stripos($arguments['parse_mode'], 'html') !== false) {
$new_message = '';
$arguments['message'] = trim($this->html_fixtags($arguments['message']));
$arguments['message'] = \trim($this->html_fixtags($arguments['message']));
$dom = new \DOMDocument();
$dom->loadHTML(mb_convert_encoding($arguments['message'], 'HTML-ENTITIES', 'UTF-8'));
$dom->loadHTML(\mb_convert_encoding($arguments['message'], 'HTML-ENTITIES', 'UTF-8'));
if (!isset($arguments['entities'])) {
$arguments['entities'] = [];
}
@ -568,7 +568,7 @@ trait BotAPI
$text_arr = [];
foreach ($this->multipleExplodeKeepDelimiters(["\n"], $args['message']) as $word) {
if (mb_strlen($word, 'UTF-8') > $max_length) {
if (\mb_strlen($word, 'UTF-8') > $max_length) {
foreach ($this->mb_str_split($word, $max_length) as $vv) {
$text_arr[] = $vv;
}
@ -577,7 +577,7 @@ trait BotAPI
}
}
$multiple_args_base = array_merge($args, ['entities' => [], 'parse_mode' => 'text', 'message' => '']);
$multiple_args_base = \array_merge($args, ['entities' => [], 'parse_mode' => 'text', 'message' => '']);
$multiple_args = [$multiple_args_base];
$i = 0;
foreach ($text_arr as $word) {
@ -592,7 +592,7 @@ trait BotAPI
$i = 0;
$offset = 0;
for ($k = 0; $k < count($args['entities']); $k++) {
for ($k = 0; $k < \count($args['entities']); $k++) {
$entity = $args['entities'][$k];
do {
while ($entity['offset'] > $offset + $this->mb_strlen($multiple_args[$i]['message'])) {
@ -610,7 +610,7 @@ trait BotAPI
$newentity['offset'] = $offset;
$prev_length = $this->mb_strlen($multiple_args[$i]['message']);
$multiple_args[$i]['message'] = rtrim($multiple_args[$i]['message']);
$multiple_args[$i]['message'] = \rtrim($multiple_args[$i]['message']);
$diff = $prev_length - $this->mb_strlen($multiple_args[$i]['message']);
if ($diff) {
@ -627,32 +627,31 @@ trait BotAPI
$entity = $newentity;
continue;
} else {
$prev_length = $this->mb_strlen($multiple_args[$i]['message']);
$multiple_args[$i]['message'] = rtrim($multiple_args[$i]['message']);
$diff = $prev_length - $this->mb_strlen($multiple_args[$i]['message']);
if ($diff) {
$entity['length'] -= $diff;
foreach ($args['entities'] as $key => &$eentity) {
if ($key > $k) {
$eentity['offset'] -= $diff;
}
}
$prev_length = $this->mb_strlen($multiple_args[$i]['message']);
$multiple_args[$i]['message'] = \rtrim($multiple_args[$i]['message']);
$diff = $prev_length - $this->mb_strlen($multiple_args[$i]['message']);
if ($diff) {
$entity['length'] -= $diff;
foreach ($args['entities'] as $key => &$eentity) {
if ($key > $k) {
$eentity['offset'] -= $diff;
}
}
$multiple_args[$i]['entities'][] = $entity;
break;
}
$multiple_args[$i]['entities'][] = $entity;
break;
} while (true);
}
$total = 0;
foreach ($multiple_args as $args) {
if (count($args['entities']) > $max_entity_length) {
$total += count($args['entities']) - $max_entity_length;
if (\count($args['entities']) > $max_entity_length) {
$total += \count($args['entities']) - $max_entity_length;
}
$c = 0;
foreach ($args['entities'] as $entity) {
if (isset($entity['url'])) {
$c += strlen($entity['url']);
$c += \strlen($entity['url']);
}
}
if ($c >= $max_entity_size) {
@ -668,7 +667,7 @@ trait BotAPI
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));
$finalArray = [];
$delimOffset = 0;
foreach ($initialArray as $item) {
@ -685,45 +684,44 @@ trait BotAPI
public function html_fixtags($text)
{
$diff = 0;
preg_match_all('#(.*?)(<(\bu\b|\bs\b|\ba\b|\bb\b|\bstrong\b|\bblockquote\b|\bstrike\b|\bdel\b|\bem\b|i|\bcode\b|\bpre\b)[^>]*>)(.*?)([<]\s*/\s*\3[>])#is', $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
\preg_match_all('#(.*?)(<(\bu\b|\bs\b|\ba\b|\bb\b|\bstrong\b|\bblockquote\b|\bstrike\b|\bdel\b|\bem\b|i|\bcode\b|\bpre\b)[^>]*>)(.*?)([<]\s*/\s*\3[>])#is', $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
if ($matches) {
foreach ($matches as $match) {
if (trim($match[1][0]) != '') {
$mod = htmlentities($match[1][0]);
if (\trim($match[1][0]) != '') {
$mod = \htmlentities($match[1][0]);
$temp = substr($text, 0, $match[1][1] + $diff);
$temp = \substr($text, 0, $match[1][1] + $diff);
$temp .= $mod;
$temp .= substr($text, $match[1][1] + $diff + strlen($match[1][0]));
$temp .= \substr($text, $match[1][1] + $diff + \strlen($match[1][0]));
$diff += strlen($mod) - strlen($match[1][0]);
$diff += \strlen($mod) - \strlen($match[1][0]);
$text = $temp;
}
$mod = htmlentities($match[4][0]);
$mod = \htmlentities($match[4][0]);
$temp = substr($text, 0, $match[4][1] + $diff);
$temp = \substr($text, 0, $match[4][1] + $diff);
$temp .= $mod;
$temp .= substr($text, $match[4][1] + $diff + strlen($match[4][0]));
$temp .= \substr($text, $match[4][1] + $diff + \strlen($match[4][0]));
$diff += strlen($mod) - strlen($match[4][0]);
$diff += \strlen($mod) - \strlen($match[4][0]);
$text = $temp;
}
$diff = 0;
preg_match_all('#<a\s*href=("|\')(.+?)("|\')\s*>#is', $text, $matches, PREG_OFFSET_CAPTURE);
\preg_match_all('#<a\s*href=("|\')(.+?)("|\')\s*>#is', $text, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[2] as $match) {
$mod = htmlentities($match[0]);
$temp = substr($text, 0, $match[1] + $diff);
$mod = \htmlentities($match[0]);
$temp = \substr($text, 0, $match[1] + $diff);
$temp .= $mod;
$temp .= substr($text, $match[1] + $diff + strlen($match[0]));
$temp .= \substr($text, $match[1] + $diff + \strlen($match[0]));
$diff += strlen($mod) - strlen($match[0]);
$diff += \strlen($mod) - \strlen($match[0]);
$text = $temp;
}
return $text;
} else {
return htmlentities($text);
}
return \htmlentities($text);
}
public function build_rows($button_list)
@ -734,7 +732,7 @@ trait BotAPI
$cols = 0;
foreach ($button_list as $button) {
if (isset($button['new'])) {
if (count($buttons) == 0) {
if (\count($buttons) == 0) {
$buttons[] = $button;
} else {
$row = ['_' => 'keyboardButtonRow', 'buttons' => $buttons];

View File

@ -23,22 +23,22 @@ trait BotAPIFiles
{
public function base64url_decode($data)
{
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)
{
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
return \rtrim(\strtr(\base64_encode($data), '+/', '-_'), '=');
}
public function rle_decode($string)
{
$new = '';
$last = '';
$null = chr(0);
foreach (str_split($string) as $cur) {
$null = \chr(0);
foreach (\str_split($string) as $cur) {
if ($last === $null) {
$new .= str_repeat($last, ord($cur));
$new .= \str_repeat($last, \ord($cur));
$last = '';
} else {
$new .= $last;
@ -54,13 +54,13 @@ trait BotAPIFiles
{
$new = '';
$count = 0;
$null = chr(0);
foreach (str_split($string) as $cur) {
$null = \chr(0);
foreach (\str_split($string) as $cur) {
if ($cur === $null) {
$count++;
} else {
if ($count > 0) {
$new .= $null.chr($count);
$new .= $null.\chr($count);
$count = 0;
}
$new .= $cur;
@ -78,14 +78,14 @@ trait BotAPIFiles
$photoSize['location']['secret'] = $photo['location']['secret'] ?? 0;
$photoSize['location']['dc_id'] = $photo['dc_id'] ?? 0;
$photoSize['location']['_'] = $thumbnail ? 'bot_thumbnail' : 'bot_photo';
$data = (yield $this->serialize_object_async(['type' => 'File'], $photoSize['location'], 'File')).chr(2);
$data = (yield $this->serialize_object_async(['type' => 'File'], $photoSize['location'], 'File')).\chr(2);
return [
'file_id' => $this->base64url_encode($this->rle_encode($data)),
'width' => $photoSize['w'],
'height' => $photoSize['h'],
'file_size' => isset($photoSize['size']) ? $photoSize['size'] : strlen($photoSize['bytes']),
'mime_type' => 'image/jpeg',
'file_id' => $this->base64url_encode($this->rle_encode($data)),
'width' => $photoSize['w'],
'height' => $photoSize['h'],
'file_size' => isset($photoSize['size']) ? $photoSize['size'] : \strlen($photoSize['bytes']),
'mime_type' => 'image/jpeg',
'file_name' => $photoSize['location']['volume_id'].'_'.$photoSize['location']['local_id'].$ext
];
}
@ -93,20 +93,20 @@ trait BotAPIFiles
public function unpack_file_id($file_id)
{
$file_id = $this->rle_decode($this->base64url_decode($file_id));
if ($file_id[strlen($file_id) - 1] !== chr(2)) {
if ($file_id[\strlen($file_id) - 1] !== \chr(2)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['last_byte_invalid']);
}
$deserialized = $this->deserialize($file_id);
$res = ['type' => str_replace('bot_', '', $deserialized['_'])];
$res = ['type' => \str_replace('bot_', '', $deserialized['_'])];
switch ($deserialized['_']) {
case 'bot_thumbnail':
case 'bot_photo':
$constructor = ['_' => 'photo', 'sizes' => [], 'dc_id' => $deserialized['dc_id']];
$constructor['id'] = $deserialized['id'];
$constructor['access_hash'] = $deserialized['access_hash'];
unset($deserialized['id']);
unset($deserialized['access_hash']);
unset($deserialized['_']);
unset($deserialized['id'], $deserialized['access_hash'], $deserialized['_']);
$deserialized['_'] = 'fileLocation';
$constructor['sizes'][0] = ['_' => 'photoSize', 'location' => $deserialized];
$res['MessageMedia'] = ['_' => 'messageMediaPhoto', 'photo' => $constructor, 'caption' => ''];
@ -114,48 +114,48 @@ trait BotAPIFiles
return $res;
case 'bot_voice':
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' => ''];
return $res;
case 'bot_video':
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' => ''];
return $res;
case 'bot_video_note':
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' => ''];
return $res;
case 'bot_document':
unset($deserialized['_']);
$constructor = array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => []]);
$constructor = \array_merge($deserialized, ['_' => 'document', 'mime_type' => '', 'attributes' => []]);
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
return $res;
case 'bot_sticker':
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' => ''];
return $res;
case 'bot_gif':
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' => ''];
return $res;
case 'bot_audio':
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' => ''];
return $res;
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));
}
}
}

View File

@ -25,9 +25,9 @@ class Exception extends \Exception
public function __toString()
{
$result = get_class($this).($this->message !== '' ? ': ' : '').$this->message.PHP_EOL.\danog\MadelineProto\Magic::$revision.PHP_EOL.'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):'.PHP_EOL.PHP_EOL.$this->getTLTrace().PHP_EOL;
if (php_sapi_name() !== 'cli') {
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
$result = \get_class($this).($this->message !== '' ? ': ' : '').$this->message.PHP_EOL.\danog\MadelineProto\Magic::$revision.PHP_EOL.'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):'.PHP_EOL.PHP_EOL.$this->getTLTrace().PHP_EOL;
if (PHP_SAPI !== 'cli') {
$result = \str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
}
return $result;

View File

@ -21,7 +21,7 @@ trait Extension
{
public function get_mime_from_extension($extension, $default)
{
$ext = ltrim($extension, '.');
$ext = \ltrim($extension, '.');
if (isset(self::ALL_MIMES[$ext])) {
return self::ALL_MIMES[$ext][0];
}
@ -32,7 +32,7 @@ trait Extension
public function get_extension_from_mime($mime)
{
foreach (self::ALL_MIMES as $key => $value) {
if (array_search($mime, $value) !== false) {
if (\array_search($mime, $value) !== false) {
return '.'.$key;
}
}

View File

@ -23,22 +23,22 @@ trait TD
{
public function tdcli_to_td(&$params, $key = null)
{
if (!is_array($params)) {
if (!\is_array($params)) {
return $params;
}
if (!isset($params['ID'])) {
array_walk($params, [$this, 'tdcli_to_td']);
\array_walk($params, [$this, 'tdcli_to_td']);
return $params;
}
foreach ($params as $key => $value) {
$value = $this->tdcli_to_td($value);
if (preg_match('/_$/', $key)) {
$params[preg_replace('/_$/', '', $key)] = $value;
if (\preg_match('/_$/', $key)) {
$params[\preg_replace('/_$/', '', $key)] = $value;
unset($params[$key]);
}
}
$params['_'] = lcfirst($params['ID']);
$params['_'] = \lcfirst($params['ID']);
unset($params['ID']);
return $params;
@ -48,8 +48,8 @@ trait TD
{
$newparams = ['_' => self::REVERSE[$params['_']]];
foreach (self::TD_PARAMS_CONVERSION[$newparams['_']] as $td => $mtproto) {
if (is_array($mtproto)) {
switch (end($mtproto)) {
if (\is_array($mtproto)) {
switch (\end($mtproto)) {
case 'choose_message_content':
switch ($params[$td]['_']) {
case 'inputMessageText':
@ -57,7 +57,7 @@ trait TD
if (isset($params['disable_web_page_preview'])) {
$newparams['no_webpage'] = $params[$td]['disable_web_page_preview'];
}
$newparams = array_merge($params[$td], $newparams);
$newparams = \array_merge($params[$td], $newparams);
break;
default:
throw new Exception(\danog\MadelineProto\Lang::$current_lang['non_text_conversion']);
@ -65,7 +65,7 @@ trait TD
break;
default:
$newparams[$mtproto[0]] = isset($params[$td]) ? $params[$td] : null;
if (is_array($newparams[$mtproto[0]])) {
if (\is_array($newparams[$mtproto[0]])) {
$newparams[$mtproto[0]] = yield $this->mtproto_to_td_async($newparams[$mtproto[0]]);
}
}
@ -82,23 +82,23 @@ trait TD
public function mtproto_to_td_async(&$params)
{
if (!is_array($params)) {
if (!\is_array($params)) {
return $params;
}
if (!isset($params['_'])) {
array_walk($params, [$this, 'mtproto_to_td']);
\array_walk($params, [$this, 'mtproto_to_td']);
return $params;
}
$newparams = ['_' => $params['_']];
if (in_array($params['_'], self::TD_IGNORE)) {
if (\in_array($params['_'], self::TD_IGNORE)) {
return $params;
}
foreach (self::TD_PARAMS_CONVERSION[$params['_']] as $td => $mtproto) {
if (is_string($mtproto)) {
if (\is_string($mtproto)) {
$newparams[$td] = $mtproto;
} else {
switch (end($mtproto)) {
switch (\end($mtproto)) {
case 'choose_chat_id_from_botapi':
$newparams[$td] = (yield $this->get_info_async($params[$mtproto[0]]))['bot_api_id'] == $this->authorization['user']['id'] ? $params['from_id'] : yield $this->get_info_async($params[$mtproto[0]])['bot_api_id'];
break;
@ -132,7 +132,7 @@ trait TD
$newparams[$td] = isset($params['ttl']) ? $params['ttl'] : 0;
break;
case 'choose_ttl_expires_in':
$newparams[$td] = $newparams['ttl'] - microtime(true);
$newparams[$td] = $newparams['ttl'] - \microtime(true);
break;
case 'choose_message_content':
if ($params['message'] !== '') {
@ -153,7 +153,7 @@ trait TD
} else {
$newparams[$td] = isset($params[$mtproto[0]]) ? $params[$mtproto[0]] : null;
}
if (is_array($newparams[$td])) {
if (\is_array($newparams[$td])) {
$newparams[$td] = yield $this->mtproto_to_td_async($newparams[$td]);
}
}
@ -165,15 +165,15 @@ trait TD
public function td_to_tdcli($params)
{
if (!is_array($params)) {
if (!\is_array($params)) {
return $params;
}
$newparams = [];
foreach ($params as $key => $value) {
if ($key === '_') {
$newparams['ID'] = ucfirst($value);
$newparams['ID'] = \ucfirst($value);
} else {
if (!is_numeric($key) && !preg_match('/_^/', $key)) {
if (!\is_numeric($key) && !\preg_match('/_^/', $key)) {
$key = $key.'_';
}
$newparams[$key] = $this->td_to_tdcli($value);

View File

@ -25,9 +25,9 @@ class Exception extends \Exception
public function __toString()
{
$result = get_class($this).($this->message !== '' ? ': ' : '').$this->message.PHP_EOL.\danog\MadelineProto\Magic::$revision.PHP_EOL.'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):'.PHP_EOL.PHP_EOL.$this->getTLTrace().PHP_EOL;
if (php_sapi_name() !== 'cli') {
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
$result = \get_class($this).($this->message !== '' ? ': ' : '').$this->message.PHP_EOL.\danog\MadelineProto\Magic::$revision.PHP_EOL.'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):'.PHP_EOL.PHP_EOL.$this->getTLTrace().PHP_EOL;
if (PHP_SAPI !== 'cli') {
$result = \str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
}
return $result;

View File

@ -31,12 +31,12 @@ trait PrettyException
public function prettify_tl($init = '')
{
$eol = PHP_EOL;
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
$eol = '<br>'.PHP_EOL;
}
$tl = false;
foreach (array_reverse($this->getTrace()) as $k => $frame) {
if (isset($frame['function']) && in_array($frame['function'], ['serialize_params', 'serialize_object'])) {
foreach (\array_reverse($this->getTrace()) as $k => $frame) {
if (isset($frame['function']) && \in_array($frame['function'], ['serialize_params', 'serialize_object'])) {
if ($frame['args'][2] !== '') {
$this->tl_trace .= $tl ? "['".$frame['args'][2]."']" : "While serializing: \t".$frame['args'][2];
$tl = true;
@ -45,18 +45,18 @@ trait PrettyException
if ($tl) {
$this->tl_trace .= $eol;
}
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;
}
$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['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 .= $eol;
$tl = false;
}
}
$this->tl_trace .= $init !== '' ? "['".$init."']" : '';
$this->tl_trace = implode($eol, array_reverse(explode($eol, $this->tl_trace)));
$this->tl_trace = \implode($eol, \array_reverse(\explode($eol, $this->tl_trace)));
}
}

View File

@ -39,34 +39,34 @@ trait TL
$this->td_methods = new TLMethod();
$this->td_descriptions = ['types' => [], 'constructors' => [], 'methods' => []];
foreach ($files as $scheme_type => $file) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['file_parsing'], basename($file)), \danog\MadelineProto\Logger::VERBOSE);
$filec = file_get_contents(\danog\MadelineProto\Absolute::absolute($file));
$TL_dict = json_decode($filec, true);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['file_parsing'], \basename($file)), \danog\MadelineProto\Logger::VERBOSE);
$filec = \file_get_contents(\danog\MadelineProto\Absolute::absolute($file));
$TL_dict = \json_decode($filec, true);
if ($TL_dict === null) {
$TL_dict = ['methods' => [], 'constructors' => []];
$type = 'constructors';
$layer = null;
$tl_file = explode("\n", $filec);
$tl_file = \explode("\n", $filec);
$key = 0;
$e = null;
$class = null;
$dparams = [];
foreach ($tl_file as $line_number => $line) {
$line = rtrim($line);
if (preg_match('|^//@|', $line)) {
$list = explode(' @', str_replace('//', ' ', $line));
$line = \rtrim($line);
if (\preg_match('|^//@|', $line)) {
$list = \explode(' @', \str_replace('//', ' ', $line));
foreach ($list as $elem) {
if ($elem === '') {
continue;
}
$elem = explode(' ', $elem, 2);
$elem = \explode(' ', $elem, 2);
if ($elem[0] === 'class') {
$elem = explode(' ', $elem[1], 2);
$elem = \explode(' ', $elem[1], 2);
$class = $elem[0];
continue;
}
if ($elem[0] === 'description') {
if (!is_null($class)) {
if (!\is_null($class)) {
$this->td_descriptions['types'][$class] = $elem[1];
$class = null;
} else {
@ -81,7 +81,7 @@ trait TL
}
continue;
}
$line = preg_replace(['|//.*|', '|^\\s+$|'], '', $line);
$line = \preg_replace(['|//.*|', '|^\\s+$|'], '', $line);
if ($line === '') {
continue;
}
@ -93,43 +93,43 @@ trait TL
$type = 'constructors';
continue;
}
if (preg_match('|^===(\d*)===|', $line, $matches)) {
if (\preg_match('|^===(\d*)===|', $line, $matches)) {
$layer = (int) $matches[1];
continue;
}
if (strpos($line, 'vector#') === 0) {
if (\strpos($line, 'vector#') === 0) {
continue;
}
if (strpos($line, ' ?= ') !== false) {
if (\strpos($line, ' ?= ') !== false) {
continue;
}
$name = preg_replace(['/#.*/', '/\\s.*/'], '', $line);
if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
$name = \preg_replace(['/#.*/', '/\\s.*/'], '', $line);
if (\in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
continue;
}
$clean = preg_replace(['/:bytes /', '/;/', '/#[a-f0-9]+ /', '/ [a-zA-Z0-9_]+\\:flags\\.[0-9]+\\?true/', '/[<]/', '/[>]/', '/ /', '/^ /', '/ $/', '/\\?bytes /', '/{/', '/}/'], [':string ', '', ' ', '', ' ', ' ', ' ', '', '', '?string ', '', ''], $line);
$id = hash('crc32b', $clean);
if (preg_match('/^[^\s]+#([a-f0-9]*)/i', $line, $matches)) {
$nid = str_pad($matches[1], 8, '0', \STR_PAD_LEFT);
$clean = \preg_replace(['/:bytes /', '/;/', '/#[a-f0-9]+ /', '/ [a-zA-Z0-9_]+\\:flags\\.[0-9]+\\?true/', '/[<]/', '/[>]/', '/ /', '/^ /', '/ $/', '/\\?bytes /', '/{/', '/}/'], [':string ', '', ' ', '', ' ', ' ', ' ', '', '', '?string ', '', ''], $line);
$id = \hash('crc32b', $clean);
if (\preg_match('/^[^\s]+#([a-f0-9]*)/i', $line, $matches)) {
$nid = \str_pad($matches[1], 8, '0', \STR_PAD_LEFT);
if ($id !== $nid && $scheme_type !== 'botAPI') {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['crc32_mismatch'], $id, $nid, $line), \danog\MadelineProto\Logger::ERROR);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['crc32_mismatch'], $id, $nid, $line), \danog\MadelineProto\Logger::ERROR);
}
$id = $nid;
}
if (!is_null($e)) {
if (!\is_null($e)) {
$this->td_descriptions[$type][$name] = ['description' => $e, 'params' => $dparams];
$e = null;
$dparams = [];
}
$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]['type'] = preg_replace(['/.+\\s+=\\s+/', '/;/'], '', $line);
$TL_dict[$type][$key]['type'] = \preg_replace(['/.+\\s+=\\s+/', '/;/'], '', $line);
if ($layer !== null) {
$TL_dict[$type][$key]['layer'] = $layer;
}
if ($name !== 'vector' && $TL_dict[$type][$key]['type'] !== 'Vector t') {
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 === '') {
continue;
}
@ -139,7 +139,7 @@ trait TL
if ($param === '#') {
continue;
}
$explode = explode(':', $param);
$explode = \explode(':', $param);
$TL_dict[$type][$key]['params'][] = ['name' => $explode[0], 'type' => $explode[1]];
}
}
@ -161,7 +161,7 @@ trait TL
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['translating_obj'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
foreach ($TL_dict['constructors'] as $elem) {
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);
}
@ -169,7 +169,7 @@ trait TL
foreach ($TL_dict['methods'] as $elem) {
$this->{($scheme_type === 'td' ? 'td_' : '').'methods'}->add($elem);
if ($scheme_type === 'secret') {
$this->encrypted_layer = max($this->encrypted_layer, $elem['layer']);
$this->encrypted_layer = \max($this->encrypted_layer, $elem['layer']);
}
}
}
@ -179,11 +179,11 @@ trait TL
if ($this->constructors->find_by_id($id) === false) {
unset($this->td_descriptions['constructors'][$name]);
} else {
if (!count($this->td_descriptions['constructors'][$name]['params'])) {
if (!\count($this->td_descriptions['constructors'][$name]['params'])) {
continue;
}
foreach ($this->td_descriptions['constructors'][$name]['params'] as $k => $param) {
$this->td_descriptions['constructors'][$name]['params'][$k] = str_replace('nullable', 'optional', $param);
$this->td_descriptions['constructors'][$name]['params'][$k] = \str_replace('nullable', 'optional', $param);
}
}
}
@ -193,7 +193,7 @@ trait TL
unset($this->td_descriptions['methods'][$name]);
} else {
foreach ($this->td_descriptions['methods'][$name]['params'] as $k => $param) {
$this->td_descriptions['constructors'][$name]['params'][$k] = str_replace('nullable', 'optional', $param);
$this->td_descriptions['constructors'][$name]['params'][$k] = \str_replace('nullable', 'optional', $param);
}
}
}
@ -204,7 +204,7 @@ trait TL
{
$res = [];
foreach ($this->methods->method_namespace as $pair) {
$a = key($pair);
$a = \key($pair);
$res[$a] = $a;
}
@ -220,7 +220,7 @@ trait TL
{
$this->tl_callbacks = [];
foreach ($objects as $object) {
if (!isset(class_implements(get_class($object))['danog\\MadelineProto\\TL\\TLCallback'])) {
if (!isset(\class_implements(\get_class($object))['danog\\MadelineProto\\TL\\TLCallback'])) {
throw new Exception('Invalid callback object provided!');
}
$new = [
@ -236,10 +236,10 @@ trait TL
if (!isset($this->tl_callbacks[$type][$match])) {
$this->tl_callbacks[$type][$match] = [];
}
if (in_array($type, [TLCallback::TYPE_MISMATCH_CALLBACK, TLCallback::CONSTRUCTOR_SERIALIZE_CALLBACK])) {
if (\in_array($type, [TLCallback::TYPE_MISMATCH_CALLBACK, TLCallback::CONSTRUCTOR_SERIALIZE_CALLBACK])) {
$this->tl_callbacks[$type][$match] = $callback;
} else {
$this->tl_callbacks[$type][$match] = array_merge($callback, $this->tl_callbacks[$type][$match]);
$this->tl_callbacks[$type][$match] = \array_merge($callback, $this->tl_callbacks[$type][$match]);
}
}
}
@ -260,8 +260,8 @@ trait TL
{
switch ($type['type']) {
case 'int':
if (!is_numeric($object)) {
if (is_array($object) && $type['name'] === 'hash') {
if (!\is_numeric($object)) {
if (\is_array($object) && $type['name'] === 'hash') {
$object = $this->gen_vector_hash($object);
} else {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
@ -270,40 +270,40 @@ trait TL
return $this->pack_signed_int($object);
case '#':
if (!is_numeric($object)) {
if (!\is_numeric($object)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
}
return $this->pack_unsigned_int($object);
case 'long':
if (is_object($object)) {
return str_pad(strrev($object->toBytes()), 8, chr(0));
if (\is_object($object)) {
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;
}
if (is_string($object) && strlen($object) === 9 && $object[0] === 'a') {
return substr($object, 1);
if (\is_string($object) && \strlen($object) === 9 && $object[0] === 'a') {
return \substr($object, 1);
}
if (!is_numeric($object)) {
if (!\is_numeric($object)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
}
return $this->pack_signed_long($object);
case 'int128':
if (strlen($object) !== 16) {
if (\strlen($object) !== 16) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_16']);
}
return (string) $object;
case 'int256':
if (strlen($object) !== 32) {
if (\strlen($object) !== 32) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_32']);
}
return (string) $object;
case 'int512':
if (strlen($object) !== 64) {
if (\strlen($object) !== 64) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_64']);
}
@ -311,42 +311,42 @@ trait TL
case 'double':
return $this->pack_double($object);
case 'string':
if (!is_string($object)) {
if (!\is_string($object)) {
throw new Exception("You didn't provide a valid string");
}
$object = pack('C*', ...unpack('C*', $object));
$l = strlen($object);
$object = \pack('C*', ...\unpack('C*', $object));
$l = \strlen($object);
$concat = '';
if ($l <= 253) {
$concat .= chr($l);
$concat .= \chr($l);
$concat .= $object;
$concat .= pack('@'.$this->posmod(-$l - 1, 4));
$concat .= \pack('@'.$this->posmod(-$l - 1, 4));
} else {
$concat .= chr(254);
$concat .= substr($this->pack_signed_int($l), 0, 3);
$concat .= \chr(254);
$concat .= \substr($this->pack_signed_int($l), 0, 3);
$concat .= $object;
$concat .= pack('@'.$this->posmod(-$l, 4));
$concat .= \pack('@'.$this->posmod(-$l, 4));
}
return $concat;
case 'bytes':
if (is_array($object) && isset($object['_']) && $object['_'] === 'bytes') {
$object = base64_decode($object['bytes']);
if (\is_array($object) && isset($object['_']) && $object['_'] === 'bytes') {
$object = \base64_decode($object['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");
}
$l = strlen($object);
$l = \strlen($object);
$concat = '';
if ($l <= 253) {
$concat .= chr($l);
$concat .= \chr($l);
$concat .= $object;
$concat .= pack('@'.$this->posmod(-$l - 1, 4));
$concat .= \pack('@'.$this->posmod(-$l - 1, 4));
} else {
$concat .= chr(254);
$concat .= substr($this->pack_signed_int($l), 0, 3);
$concat .= \chr(254);
$concat .= \substr($this->pack_signed_int($l), 0, 3);
$concat .= $object;
$concat .= pack('@'.$this->posmod(-$l, 4));
$concat .= \pack('@'.$this->posmod(-$l, 4));
}
return $concat;
@ -357,39 +357,39 @@ trait TL
case '!X':
return $object;
case 'Vector t':
if (!is_array($object)) {
if (!\is_array($object)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['array_invalid']);
}
if (isset($object['_'])) {
throw new Exception('You must provide an array of '.$type['subtype'].' objects, not a '.$type['subtype']." object. Example: [['_' => ".$type['subtype'].', ... ]]');
}
$concat = $this->constructors->find_by_predicate('vector')['id'];
$concat .= $this->pack_unsigned_int(count($object));
$concat .= $this->pack_unsigned_int(\count($object));
foreach ($object as $k => $current_object) {
$concat .= yield $this->serialize_object_async(['type' => $type['subtype']], $current_object, $k);
}
return $concat;
case 'vector':
if (!is_array($object)) {
if (!\is_array($object)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['array_invalid']);
}
$concat = $this->pack_unsigned_int(count($object));
$concat = $this->pack_unsigned_int(\count($object));
foreach ($object as $k => $current_object) {
$concat .= yield $this->serialize_object_async(['type' => $type['subtype']], $current_object, $k);
}
return $concat;
case 'Object':
if (is_string($object)) {
if (\is_string($object)) {
return $object;
}
}
$auto = false;
if ($type['type'] === 'InputMessage' && !is_array($object)) {
if ($type['type'] === 'InputMessage' && !\is_array($object)) {
$object = ['_' => 'inputMessageID', 'id' => $object];
} elseif (isset($this->tl_callbacks[TLCallback::TYPE_MISMATCH_CALLBACK][$type['type']]) && (!is_array($object) || isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type'])) {
} elseif (isset($this->tl_callbacks[TLCallback::TYPE_MISMATCH_CALLBACK][$type['type']]) && (!\is_array($object) || isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type'])) {
$object = yield $this->tl_callbacks[TLCallback::TYPE_MISMATCH_CALLBACK][$type['type']]($object);
if (!isset($object[$type['type']])) {
throw new \danog\MadelineProto\Exception("Could not convert {$type['type']} object");
@ -413,10 +413,10 @@ trait TL
if ($constructorData === false) {
$this->logger->logger($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] === '%') {
$type['type'] = substr($type['type'], 1);
$type['type'] = \substr($type['type'], 1);
}
if ($predicate === $type['type'] && !$auto) {
$bare = true;
@ -435,21 +435,21 @@ trait TL
public function serialize_method_async($method, $arguments)
{
if ($method === 'messages.importChatInvite' && isset($arguments['hash']) && is_string($arguments['hash']) && preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $arguments['hash'], $matches)) {
if ($method === 'messages.importChatInvite' && isset($arguments['hash']) && \is_string($arguments['hash']) && \preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $arguments['hash'], $matches)) {
if ($matches[1] === '') {
$method = 'channels.joinChannel';
$arguments['channel'] = $matches[2];
} else {
$arguments['hash'] = $matches[2];
}
} elseif ($method === 'messages.checkChatInvite' && isset($arguments['hash']) && is_string($arguments['hash']) && preg_match('@(?:t|telegram)\.(?:me|dog)/joinchat/([a-z0-9_-]*)@i', $arguments['hash'], $matches)) {
} elseif ($method === 'messages.checkChatInvite' && isset($arguments['hash']) && \is_string($arguments['hash']) && \preg_match('@(?:t|telegram)\.(?:me|dog)/joinchat/([a-z0-9_-]*)@i', $arguments['hash'], $matches)) {
$arguments['hash'] = $matches[1];
} elseif ($method === 'channels.joinChannel' && isset($arguments['channel']) && is_string($arguments['channel']) && preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $arguments['channel'], $matches)) {
} elseif ($method === 'channels.joinChannel' && isset($arguments['channel']) && \is_string($arguments['channel']) && \preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $arguments['channel'], $matches)) {
if ($matches[1] !== '') {
$method = 'messages.importChatInvite';
$arguments['hash'] = $matches[2];
}
} elseif ($method === 'messages.sendMessage' && isset($arguments['peer']['_']) && in_array($arguments['peer']['_'], ['inputEncryptedChat', 'updateEncryption', 'updateEncryptedChatTyping', 'updateEncryptedMessagesRead', 'updateNewEncryptedMessage', 'encryptedMessage', 'encryptedMessageService'])) {
} elseif ($method === 'messages.sendMessage' && isset($arguments['peer']['_']) && \in_array($arguments['peer']['_'], ['inputEncryptedChat', 'updateEncryption', 'updateEncryptedChatTyping', 'updateEncryptedMessagesRead', 'updateNewEncryptedMessage', 'encryptedMessage', 'encryptedMessageService'])) {
$method = 'messages.sendEncrypted';
$arguments = ['peer' => $arguments['peer'], 'message' => $arguments];
if (!isset($arguments['message']['_'])) {
@ -465,9 +465,9 @@ trait TL
if (isset($arguments['file'])) {
if (
(
!is_array($arguments['file']) ||
!\is_array($arguments['file']) ||
!(isset($arguments['file']['_']) && $this->constructors->find_by_predicate($arguments['file']['_']) === 'InputEncryptedFile')
) &&
) &&
$this->settings['upload']['allow_automatic_upload']
) {
$arguments['file'] = yield $this->upload_encrypted_async($arguments['file']);
@ -479,7 +479,7 @@ trait TL
$arguments['message']['media']['iv'] = $arguments['file']['iv'];
}
}
} elseif (in_array($method, ['messages.addChatUser', 'messages.deleteChatUser', 'messages.editChatAdmin', 'messages.editChatPhoto', 'messages.editChatTitle', 'messages.getFullChat', 'messages.exportChatInvite', 'messages.editChatAdmin', 'messages.migrateChat']) && isset($arguments['chat_id']) && (!is_numeric($arguments['chat_id']) || $arguments['chat_id'] < 0)) {
} elseif (\in_array($method, ['messages.addChatUser', 'messages.deleteChatUser', 'messages.editChatAdmin', 'messages.editChatPhoto', 'messages.editChatTitle', 'messages.getFullChat', 'messages.exportChatInvite', 'messages.editChatAdmin', 'messages.migrateChat']) && isset($arguments['chat_id']) && (!\is_numeric($arguments['chat_id']) || $arguments['chat_id'] < 0)) {
$res = yield $this->get_info_async($arguments['chat_id']);
if ($res['type'] !== 'chat') {
throw new \danog\MadelineProto\Exception('chat_id is not a chat id (only normal groups allowed, not supergroups)!');
@ -487,7 +487,7 @@ trait TL
$arguments['chat_id'] = $res['chat_id'];
} elseif ($method === 'photos.updateProfilePhoto') {
if (isset($arguments['id'])) {
if (!is_array($arguments['id'])) {
if (!\is_array($arguments['id'])) {
$method = 'photos.uploadProfilePhoto';
$arguments['file'] = $arguments['id'];
}
@ -496,7 +496,7 @@ trait TL
}
} elseif ($method === 'photos.uploadProfilePhoto') {
if (isset($arguments['file'])) {
if (is_array($arguments['file']) && !in_array($arguments['file']['_'], ['inputFile', 'inputFileBig'])) {
if (\is_array($arguments['file']) && !\in_array($arguments['file']['_'], ['inputFile', 'inputFileBig'])) {
$method = 'photos.uploadProfilePhoto';
$arguments['id'] = $arguments['file'];
}
@ -541,7 +541,7 @@ trait TL
$arguments['flags'] = $flags;
foreach ($tl['params'] as $current_argument) {
if (!isset($arguments[$current_argument['name']])) {
if (isset($current_argument['pow']) && (in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) {
if (isset($current_argument['pow']) && (\in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) {
//$this->logger->logger('Skipping '.$current_argument['name'].' of type '.$current_argument['type');
continue;
}
@ -549,7 +549,7 @@ trait TL
$serialized .= yield $this->serialize_object_async(['type' => 'bytes'], $this->random(15 + 4 * $this->random_int($modulus = 3)), 'random_bytes');
continue;
}
if ($current_argument['name'] === 'data' && isset($tl['method']) && in_array($tl['method'], ['messages.sendEncrypted', 'messages.sendEncryptedFile', 'messages.sendEncryptedService']) && isset($arguments['message'])) {
if ($current_argument['name'] === 'data' && isset($tl['method']) && \in_array($tl['method'], ['messages.sendEncrypted', 'messages.sendEncryptedFile', 'messages.sendEncryptedService']) && isset($arguments['message'])) {
$serialized .= yield $this->serialize_object_async($current_argument, yield $this->encrypt_secret_message_async($arguments['peer']['chat_id'], $arguments['message']), 'data');
continue;
}
@ -564,29 +564,29 @@ trait TL
case 'Vector t':
if (isset($arguments['id'])) {
$serialized .= $this->constructors->find_by_predicate('vector')['id'];
$serialized .= $this->pack_unsigned_int(count($arguments['id']));
$serialized .= $this->random(8 * count($arguments['id']));
$serialized .= $this->pack_unsigned_int(\count($arguments['id']));
$serialized .= $this->random(8 * \count($arguments['id']));
continue 2;
}
}
}
if ($current_argument['name'] === 'hash' && $current_argument['type'] === 'int') {
$serialized .= pack('@4');
$serialized .= \pack('@4');
continue;
}
if ($tl['type'] === 'InputMedia' && $current_argument['name'] === 'mime_type') {
$serialized .= yield $this->serialize_object_async($current_argument, $arguments['file']['mime_type'], $current_argument['name'], $layer);
continue;
}
if ($tl['type'] === 'DocumentAttribute' && in_array($current_argument['name'], ['w', 'h', 'duration'])) {
$serialized .= pack('@4');
if ($tl['type'] === 'DocumentAttribute' && \in_array($current_argument['name'], ['w', 'h', 'duration'])) {
$serialized .= \pack('@4');
continue;
}
if (in_array($current_argument['type'], ['bytes', 'string'])) {
$serialized .= pack('@4');
if (\in_array($current_argument['type'], ['bytes', 'string'])) {
$serialized .= \pack('@4');
continue;
}
if (($id = $this->constructors->find_by_predicate(lcfirst($current_argument['type']).'Empty', isset($tl['layer']) ? $tl['layer'] : -1)) && $id['type'] === $current_argument['type']) {
if (($id = $this->constructors->find_by_predicate(\lcfirst($current_argument['type']).'Empty', isset($tl['layer']) ? $tl['layer'] : -1)) && $id['type'] === $current_argument['type']) {
$serialized .= $id['id'];
continue;
}
@ -618,19 +618,19 @@ trait TL
break;*/
}
}
if (in_array($current_argument['type'], ['DataJSON', '%DataJSON'])) {
$arguments[$current_argument['name']] = ['_' => 'dataJSON', 'data' => json_encode($arguments[$current_argument['name']])];
if (\in_array($current_argument['type'], ['DataJSON', '%DataJSON'])) {
$arguments[$current_argument['name']] = ['_' => 'dataJSON', 'data' => \json_encode($arguments[$current_argument['name']])];
}
if (isset($current_argument['subtype']) && in_array($current_argument['subtype'], ['DataJSON', '%DataJSON'])) {
array_walk($arguments[$current_argument['name']], function (&$arg) {
$arg = ['_' => 'dataJSON', 'data' => json_encode($arg)];
if (isset($current_argument['subtype']) && \in_array($current_argument['subtype'], ['DataJSON', '%DataJSON'])) {
\array_walk($arguments[$current_argument['name']], function (&$arg) {
$arg = ['_' => 'dataJSON', 'data' => \json_encode($arg)];
});
}
if ($current_argument['type'] === 'InputFile'
&& (
!is_array($arguments[$current_argument['name']])
!\is_array($arguments[$current_argument['name']])
|| !(
isset($arguments[$current_argument['name']]['_'])
&& $this->constructors->find_by_predicate($arguments[$current_argument['name']]['_']) === 'InputFile'
@ -641,8 +641,8 @@ trait TL
$arguments[$current_argument['name']] = yield $this->upload_async($arguments[$current_argument['name']]);
}
if ($current_argument['type'] === 'InputEncryptedChat' && (!is_array($arguments[$current_argument['name']]) || isset($arguments[$current_argument['name']]['_']) && $this->constructors->find_by_predicate($arguments[$current_argument['name']]['_'])['type'] !== $current_argument['type'])) {
if (is_array($arguments[$current_argument['name']])) {
if ($current_argument['type'] === 'InputEncryptedChat' && (!\is_array($arguments[$current_argument['name']]) || isset($arguments[$current_argument['name']]['_']) && $this->constructors->find_by_predicate($arguments[$current_argument['name']]['_'])['type'] !== $current_argument['type'])) {
if (\is_array($arguments[$current_argument['name']])) {
$arguments[$current_argument['name']] = (yield $this->get_info_async($arguments[$current_argument['name']]))['InputEncryptedChat'];
} else {
if (!isset($this->secret_chats[$arguments[$current_argument['name']]])) {
@ -660,17 +660,17 @@ trait TL
public function get_length($stream, $type = ['type' => ''])
{
if (is_string($stream)) {
$res = fopen('php://memory', 'rw+b');
fwrite($res, $stream);
fseek($res, 0);
if (\is_string($stream)) {
$res = \fopen('php://memory', 'rw+b');
\fwrite($res, $stream);
\fseek($res, 0);
$stream = $res;
} elseif (!is_resource($stream)) {
} elseif (!\is_resource($stream)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
}
$this->deserialize($stream, $type);
return ftell($stream);
return \ftell($stream);
}
/**
@ -678,81 +678,82 @@ trait TL
*/
public function deserialize($stream, $type = ['type' => ''])
{
if (is_string($stream)) {
$res = fopen('php://memory', 'rw+b');
fwrite($res, $stream);
fseek($res, 0);
if (\is_string($stream)) {
$res = \fopen('php://memory', 'rw+b');
\fwrite($res, $stream);
\fseek($res, 0);
$stream = $res;
} elseif (!is_resource($stream)) {
} elseif (!\is_resource($stream)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
}
switch ($type['type']) {
case 'Bool':
return $this->deserialize_bool(stream_get_contents($stream, 4));
return $this->deserialize_bool(\stream_get_contents($stream, 4));
case 'int':
return $this->unpack_signed_int(stream_get_contents($stream, 4));
return $this->unpack_signed_int(\stream_get_contents($stream, 4));
case '#':
return unpack('V', stream_get_contents($stream, 4))[1];
return \unpack('V', \stream_get_contents($stream, 4))[1];
case 'long':
if (isset($type['idstrlong'])) {
return stream_get_contents($stream, 8);
return \stream_get_contents($stream, 8);
}
return \danog\MadelineProto\Magic::$bigint || isset($type['strlong']) ? stream_get_contents($stream, 8) : $this->unpack_signed_long(stream_get_contents($stream, 8));
return \danog\MadelineProto\Magic::$bigint || isset($type['strlong']) ? \stream_get_contents($stream, 8) : $this->unpack_signed_long(\stream_get_contents($stream, 8));
case 'double':
return $this->unpack_double(stream_get_contents($stream, 8));
return $this->unpack_double(\stream_get_contents($stream, 8));
case 'int128':
return stream_get_contents($stream, 16);
return \stream_get_contents($stream, 16);
case 'int256':
return stream_get_contents($stream, 32);
return \stream_get_contents($stream, 32);
case 'int512':
return stream_get_contents($stream, 64);
return \stream_get_contents($stream, 64);
case 'string':
case 'bytes':
$l = ord(stream_get_contents($stream, 1));
$l = \ord(\stream_get_contents($stream, 1));
if ($l > 254) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['length_too_big']);
}
if ($l === 254) {
$long_len = unpack('V', stream_get_contents($stream, 3).chr(0))[1];
$x = stream_get_contents($stream, $long_len);
$long_len = \unpack('V', \stream_get_contents($stream, 3).\chr(0))[1];
$x = \stream_get_contents($stream, $long_len);
$resto = $this->posmod(-$long_len, 4);
if ($resto > 0) {
stream_get_contents($stream, $resto);
\stream_get_contents($stream, $resto);
}
} else {
$x = $l ? stream_get_contents($stream, $l) : '';
$x = $l ? \stream_get_contents($stream, $l) : '';
$resto = $this->posmod(-($l + 1), 4);
if ($resto > 0) {
stream_get_contents($stream, $resto);
\stream_get_contents($stream, $resto);
}
}
if (!is_string($x)) {
if (!\is_string($x)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['deserialize_not_str']);
}
return $type['type'] === 'bytes' ? new Types\Bytes($x) : $x;
case 'Vector t':
$id = stream_get_contents($stream, 4);
$id = \stream_get_contents($stream, 4);
$constructorData = $this->constructors->find_by_id($id);
if ($constructorData === false) {
$constructorData = $this->methods->find_by_id($id);
$constructorData['predicate'] = 'method_'.$constructorData['method'];
}
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))));
}
switch ($constructorData['predicate']) {
case 'gzip_packed':
return $this->deserialize(gzdecode($this->deserialize($stream, ['type' => 'bytes', 'connection' => $type['connection']])), ['type' => '', 'connection' => $type['connection']]);
return $this->deserialize(\gzdecode($this->deserialize($stream, ['type' => 'bytes', 'connection' => $type['connection']])), ['type' => '', 'connection' => $type['connection']]);
case 'Vector t':
case 'vector':
break;
default:
throw new Exception(\danog\MadelineProto\Lang::$current_lang['vector_invalid'].$constructorData['predicate']);
}
// no break
case 'vector':
$count = unpack('V', stream_get_contents($stream, 4))[1];
$count = \unpack('V', \stream_get_contents($stream, 4))[1];
$result = [];
$type['type'] = $type['subtype'];
for ($i = 0; $i < $count; $i++) {
@ -762,7 +763,7 @@ trait TL
return $result;
}
if ($type['type'] != '' && $type['type'][0] === '%') {
$checkType = substr($type['type'], 1);
$checkType = \substr($type['type'], 1);
$constructorData = $this->constructors->find_by_type($checkType);
if ($constructorData === false) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['constructor_not_found'].$checkType);
@ -770,12 +771,12 @@ trait TL
} else {
$constructorData = $this->constructors->find_by_predicate($type['type']);
if ($constructorData === false) {
$id = stream_get_contents($stream, 4);
$id = \stream_get_contents($stream, 4);
$constructorData = $this->constructors->find_by_id($id);
if ($constructorData === false) {
$constructorData = $this->methods->find_by_id($id);
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'];
}
@ -785,7 +786,7 @@ trait TL
if (!isset($type['subtype'])) {
$type['subtype'] = '';
}
return $this->deserialize(gzdecode($this->deserialize($stream, ['type' => 'bytes'])), ['type' => '', 'connection' => $type['connection'], 'subtype' => $type['subtype']]);
return $this->deserialize(\gzdecode($this->deserialize($stream, ['type' => 'bytes'])), ['type' => '', 'connection' => $type['connection'], 'subtype' => $type['subtype']]);
}
if ($constructorData['type'] === 'Vector t') {
$constructorData['connection'] = $type['connection'];
@ -818,19 +819,20 @@ trait TL
$x[$arg['name']] = false;
continue 2;
}
// no break
default:
if (($x['flags'] & $arg['pow']) === 0) {
continue 2;
}
}
}
if (in_array($arg['name'], ['msg_ids', 'msg_id', 'bad_msg_id', 'req_msg_id', 'answer_msg_id', 'first_msg_id'])) {
if (\in_array($arg['name'], ['msg_ids', 'msg_id', 'bad_msg_id', 'req_msg_id', 'answer_msg_id', 'first_msg_id'])) {
$arg['idstrlong'] = true;
}
if (in_array($arg['name'], ['key_fingerprint', 'server_salt', 'new_server_salt', 'server_public_key_fingerprints', 'ping_id', 'exchange_id'])) {
if (\in_array($arg['name'], ['key_fingerprint', 'server_salt', 'new_server_salt', 'server_public_key_fingerprints', 'ping_id', 'exchange_id'])) {
$arg['strlong'] = true;
}
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';
}
if ($x['_'] === 'rpc_result' && $arg['name'] === 'result') {
@ -843,9 +845,9 @@ trait TL
}
if (isset($type['connection']->outgoing_messages[$x['req_msg_id']]['type'])
&& stripos($type['connection']->outgoing_messages[$x['req_msg_id']]['type'], '<') !== false
&& \stripos($type['connection']->outgoing_messages[$x['req_msg_id']]['type'], '<') !== false
) {
$arg['subtype'] = str_replace(['Vector<', '>'], '', $type['connection']->outgoing_messages[$x['req_msg_id']]['type']);
$arg['subtype'] = \str_replace(['Vector<', '>'], '', $type['connection']->outgoing_messages[$x['req_msg_id']]['type']);
}
}
if (isset($type['connection'])) {
@ -853,11 +855,10 @@ trait TL
}
$x[$arg['name']] = $this->deserialize($stream, $arg);
if ($arg['name'] === 'random_bytes') {
if (strlen($x[$arg['name']]) < 15) {
if (\strlen($x[$arg['name']]) < 15) {
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['rand_bytes_too_small']);
} else {
unset($x[$arg['name']]);
}
unset($x[$arg['name']]);
}
}
if (isset($x['flags'])) {
@ -865,7 +866,7 @@ trait TL
unset($x['flags']);
}
if ($x['_'] === 'dataJSON') {
return json_decode($x['data'], true);
return \json_decode($x['data'], true);
} elseif ($constructorData['type'] === 'JSONValue') {
switch ($x['_']) {
case 'jsonNull':

View File

@ -45,7 +45,7 @@ class TLConstructor
if ($scheme_type === 'secret') {
$this->by_id[$json_dict['id']]['layer'] = $json_dict['layer'];
$this->layers[$json_dict['layer']] = $json_dict['layer'];
ksort($this->layers);
\ksort($this->layers);
} else {
$json_dict['layer'] = '';
}

View File

@ -37,7 +37,7 @@ class TLMethod
{
$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'];
$namespace = explode('.', $json_dict['method']);
$namespace = \explode('.', $json_dict['method']);
if (isset($namespace[1])) {
$this->method_namespace[] = [$namespace[0] => $namespace[1]];
}

View File

@ -24,11 +24,11 @@ trait TLParams
public function parse_params($key, $mtproto = false)
{
foreach ($this->by_id[$key]['params'] as $kkey => $param) {
if (preg_match('/(\w*)\.(\d*)\?(.*)/', $param['type'], $matches)) {
$param['pow'] = pow(2, $matches[2]);
if (\preg_match('/(\w*)\.(\d*)\?(.*)/', $param['type'], $matches)) {
$param['pow'] = \pow(2, $matches[2]);
$param['type'] = $matches[3];
}
if (preg_match('/^(v|V)ector\<(.*)\>$/', $param['type'], $matches)) {
if (\preg_match('/^(v|V)ector\<(.*)\>$/', $param['type'], $matches)) {
$param['type'] = $matches[1] === 'v' ? 'vector' : 'Vector t';
$param['subtype'] = $matches[2];
$param['subtype'] = ($mtproto && $param['subtype'] === 'Message' ? 'MT' : '').$param['subtype'];

View File

@ -41,7 +41,7 @@ class Button implements \JsonSerializable, \ArrayAccess
public function click($donotwait = false, $params = [])
{
if (is_array($donotwait)) {
if (\is_array($donotwait)) {
$async = $donotwait;
} else {
$async = $params;

View File

@ -41,6 +41,6 @@ class Bytes implements \JsonSerializable
public function jsonSerialize()
{
return ['_' => 'bytes', 'bytes' => base64_encode($this->bytes)];
return ['_' => 'bytes', 'bytes' => \base64_encode($this->bytes)];
}
}

View File

@ -20,22 +20,21 @@ namespace danog\MadelineProto;
use Amp\Deferred;
use Amp\Failure;
use Amp\File\StatCache;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
use phpseclib\Math\BigInteger;
use function Amp\ByteStream\getOutputBufferStream;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;
use function Amp\File\exists;
use function Amp\Promise\all;
use function Amp\Promise\any;
use function Amp\Promise\first;
use function Amp\Promise\some;
use function Amp\Promise\timeout;
use function Amp\Promise\wait;
use function Amp\ByteStream\getOutputBufferStream;
use function Amp\File\exists;
use function Amp\File\touch;
use Amp\File\StatCache;
use phpseclib\Math\BigInteger;
/**
* Some tools.
@ -50,7 +49,7 @@ trait Tools
foreach ($ints as $int) {
$hash = $hash->multiply(\danog\MadelineProto\Magic::$twozerotwosixone)->add(\danog\MadelineProto\Magic::$zeroeight)->add(new \phpseclib\Math\BigInteger($int))->divide(\danog\MadelineProto\Magic::$zeroeight)[1];
}
$hash = self::unpack_signed_int(strrev(str_pad($hash->toBytes(), 4, "\0", STR_PAD_LEFT)));
$hash = self::unpack_signed_int(\strrev(\str_pad($hash->toBytes(), 4, "\0", STR_PAD_LEFT)));
} else {
$hash = 0;
foreach ($ints as $int) {
@ -102,33 +101,33 @@ trait Tools
{
$resto = $a % $b;
return $resto < 0 ? $resto + abs($b) : $resto;
return $resto < 0 ? $resto + \abs($b) : $resto;
}
public static 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']);
}
return unpack('l', \danog\MadelineProto\Magic::$BIG_ENDIAN ? strrev($value) : $value)[1];
return \unpack('l', \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($value) : $value)[1];
}
public static 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']);
}
return unpack('q', \danog\MadelineProto\Magic::$BIG_ENDIAN ? strrev($value) : $value)[1];
return \unpack('q', \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($value) : $value)[1];
}
public static function unpack_signed_long_string($value)
{
if (is_int($value)) {
if (\is_int($value)) {
return (string) $value;
}
if (strlen($value) !== 8) {
if (\strlen($value) !== 8) {
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
}
@ -139,25 +138,25 @@ trait Tools
public static function pack_signed_int($value)
{
if ($value > 2147483647) {
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_2147483647'], $value));
throw new TL\Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_2147483647'], $value));
}
if ($value < -2147483648) {
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\Magic::$BIG_ENDIAN ? strrev($res) : $res;
return \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($res) : $res;
}
public static function pack_signed_long($value)
{
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 < -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\Magic::$bigint ? self::pack_signed_int($value)."\0\0\0\0" : (\danog\MadelineProto\Magic::$BIG_ENDIAN ? strrev(pack('q', $value)) : pack('q', $value));
$res = \danog\MadelineProto\Magic::$bigint ? self::pack_signed_int($value)."\0\0\0\0" : (\danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev(\pack('q', $value)) : \pack('q', $value));
return $res;
}
@ -165,32 +164,32 @@ trait Tools
public static function pack_unsigned_int($value)
{
if ($value > 4294967295) {
throw new TL\Exception(sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_4294967296'], $value));
throw new TL\Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_4294967296'], $value));
}
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 static function pack_double($value)
{
$res = pack('d', $value);
if (strlen($res) !== 8) {
$res = \pack('d', $value);
if (\strlen($res) !== 8) {
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['encode_double_error']);
}
return \danog\MadelineProto\Magic::$BIG_ENDIAN ? strrev($res) : $res;
return \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($res) : $res;
}
public static function unpack_double($value)
{
if (strlen($value) !== 8) {
if (\strlen($value) !== 8) {
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
}
return unpack('d', \danog\MadelineProto\Magic::$BIG_ENDIAN ? strrev($value) : $value)[1];
return \unpack('d', \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($value) : $value)[1];
}
public static function wait($promise)
@ -208,7 +207,6 @@ trait Tools
try {
Loop::run(function () use (&$resolved, &$value, &$exception, $promise) {
$promise->onResolve(function ($e, $v) use (&$resolved, &$value, &$exception) {
Loop::stop();
$resolved = true;
$exception = $e;
@ -284,10 +282,10 @@ trait Tools
if ($actual) {
$promise = $actual;
} else {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];
$trace = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];
$file = '';
if (isset($trace['file'])) {
$file .= basename($trace['file'], '.php');
$file .= \basename($trace['file'], '.php');
}
if (isset($trace['line'])) {
$file .= ":{$trace['line']}";
@ -332,7 +330,6 @@ trait Tools
if (!$zis || !$zis->destructing) {
Promise\rethrow(new Failure($e));
}
} else {
if ($logger) {
$logger->logger($e);
@ -373,7 +370,7 @@ trait Tools
}
/**
* Asynchronously lock a file
* Resolves with a callbable that MUST eventually be called in order to release the lock
* Resolves with a callbable that MUST eventually be called in order to release the lock.
*
* @param string $file File to lock
* @param integer $operation Locking mode (see flock)
@ -386,22 +383,22 @@ trait Tools
}
public static function noCache(int $status, string $message)
{
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
http_response_code($status);
\header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
\header('Cache-Control: post-check=0, pre-check=0', false);
\header('Pragma: no-cache');
\http_response_code($status);
return self::echo($message);
}
public static function flockAsync(string $file, int $operation, $polling)
{
if (!yield exists($file)) {
yield touch($file);
yield \touch($file);
StatCache::clear($file);
}
$operation |= LOCK_NB;
$res = fopen($file, 'c');
$res = \fopen($file, 'c');
do {
$result = flock($res, $operation);
$result = \flock($res, $operation);
if (!$result) {
yield self::sleep($polling);
}
@ -409,8 +406,8 @@ trait Tools
return static function () use (&$res) {
if ($res) {
flock($res, LOCK_UN);
fclose($res);
\flock($res, LOCK_UN);
\fclose($res);
$res = null;
}
};
@ -431,20 +428,21 @@ trait Tools
yield $stdout->write($prompt);
}
static $lines = [''];
while (count($lines) < 2 && ($chunk = yield $stdin->read()) !== null) {
$chunk = explode("\n", str_replace(["\r", "\n\n"], "\n", $chunk));
$lines[count($lines) - 1] .= array_shift($chunk);
$lines = array_merge($lines, $chunk);
while (\count($lines) < 2 && ($chunk = yield $stdin->read()) !== null) {
$chunk = \explode("\n", \str_replace(["\r", "\n\n"], "\n", $chunk));
$lines[\count($lines) - 1] .= \array_shift($chunk);
$lines = \array_merge($lines, $chunk);
}
return array_shift($lines);
return \array_shift($lines);
}
public static function echo ($string) {
public static function echo($string)
{
return getOutputBufferStream()->write($string);
}
public static function is_array_or_alike($var)
{
return is_array($var) ||
return \is_array($var) ||
($var instanceof ArrayAccess &&
$var instanceof Traversable &&
$var instanceof Countable);

View File

@ -46,7 +46,7 @@ trait AuthKeyHandler
public function request_call_async($user)
{
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
throw \danog\MadelineProto\Exception::extension('libtgvoip');
}
$user = yield $this->get_info_async($user);
@ -54,7 +54,7 @@ trait AuthKeyHandler
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
}
$user = $user['InputUser'];
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['calling_user'], $user['user_id']), \danog\MadelineProto\Logger::VERBOSE);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['calling_user'], $user['user_id']), \danog\MadelineProto\Logger::VERBOSE);
$dh_config = yield $this->get_dh_config_async();
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_a'], \danog\MadelineProto\Logger::VERBOSE);
$a = \phpseclib\Math\BigInteger::randomRange(\danog\MadelineProto\Magic::$two, $dh_config['p']->subtract(\danog\MadelineProto\Magic::$two));
@ -62,8 +62,8 @@ trait AuthKeyHandler
$g_a = $dh_config['g']->powMod($a, $dh_config['p']);
$this->check_G($g_a, $dh_config['p']);
$controller = new \danog\MadelineProto\VoIP(true, $user['user_id'], $this, \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED);
$controller->storage = ['a' => $a, 'g_a' => str_pad($g_a->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
$res = yield $this->method_call_async_read('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' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]);
$controller->storage = ['a' => $a, 'g_a' => \str_pad($g_a->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
$res = yield $this->method_call_async_read('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' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]);
$controller->setCall($res['phone_call']);
$this->calls[$res['phone_call']['id']] = $controller;
yield $this->updaters[false]->resume();
@ -73,15 +73,15 @@ trait AuthKeyHandler
public function accept_call_async($call)
{
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
throw new \danog\MadelineProto\Exception();
}
if ($this->call_status($call['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_1'], $call['id']));
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_1'], $call['id']));
return false;
}
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['accepting_call'], $this->calls[$call['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['accepting_call'], $this->calls[$call['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
$dh_config = yield $this->get_dh_config_async();
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_b'], \danog\MadelineProto\Logger::VERBOSE);
$b = \phpseclib\Math\BigInteger::randomRange(\danog\MadelineProto\Magic::$two, $dh_config['p']->subtract(\danog\MadelineProto\Magic::$two));
@ -92,7 +92,7 @@ trait AuthKeyHandler
$res = yield $this->method_call_async_read('phone.acceptCall', ['peer' => $call, 'g_b' => $g_b->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'udp_p2p' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]);
} catch (\danog\MadelineProto\RPCErrorException $e) {
if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id']));
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id']));
return true;
}
@ -113,24 +113,24 @@ trait AuthKeyHandler
public function confirm_call_async($params)
{
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
throw \danog\MadelineProto\Exception::extension('libtgvoip');
}
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_2'], $params['id']));
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_2'], $params['id']));
return false;
}
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
$dh_config = yield $this->get_dh_config_async();
$params['g_b'] = new \phpseclib\Math\BigInteger((string) $params['g_b'], 256);
$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);
try {
$res = yield $this->method_call_async_read('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' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc])['phone_call'];
$res = yield $this->method_call_async_read('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' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc])['phone_call'];
} catch (\danog\MadelineProto\RPCErrorException $e) {
if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id']));
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id']));
return true;
}
@ -145,15 +145,15 @@ trait AuthKeyHandler
}
$visualization = [];
$length = new \phpseclib\Math\BigInteger(count(\danog\MadelineProto\Magic::$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) {
$number[0] = chr(ord($number[0]) & 0x7f);
$length = new \phpseclib\Math\BigInteger(\count(\danog\MadelineProto\Magic::$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) {
$number[0] = \chr(\ord($number[0]) & 0x7f);
$visualization[] = \danog\MadelineProto\Magic::$emojis[(int) (new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString()];
}
$this->calls[$params['id']]->setVisualization($visualization);
$this->calls[$params['id']]->configuration['endpoints'] = array_merge($res['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, 'auth_key_id' => substr(sha1($key, true), -8), 'call_id' => substr(hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
$this->calls[$params['id']]->configuration['endpoints'] = \array_merge($res['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, 'auth_key_id' => \substr(\sha1($key, true), -8), 'call_id' => \substr(\hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
$this->calls[$params['id']]->parseConfig();
$res = $this->calls[$params['id']]->startTheMagic();
@ -162,34 +162,34 @@ trait AuthKeyHandler
public function complete_call_async($params)
{
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
throw \danog\MadelineProto\Exception::extension('libtgvoip');
}
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED || !isset($this->calls[$params['id']]->storage['b'])) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_3'], $params['id']));
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_3'], $params['id']));
return false;
}
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_completing'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_completing'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
$dh_config = yield $this->get_dh_config_async();
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']);
}
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
$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);
if (substr(sha1($key, true), -8) != $params['key_fingerprint']) {
$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']) {
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_invalid']);
}
$visualization = [];
$length = new \phpseclib\Math\BigInteger(count(\danog\MadelineProto\Magic::$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) {
$number[0] = chr(ord($number[0]) & 0x7f);
$length = new \phpseclib\Math\BigInteger(\count(\danog\MadelineProto\Magic::$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) {
$number[0] = \chr(\ord($number[0]) & 0x7f);
$visualization[] = \danog\MadelineProto\Magic::$emojis[(int) (new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString()];
}
$this->calls[$params['id']]->setVisualization($visualization);
$this->calls[$params['id']]->configuration['endpoints'] = array_merge($params['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, 'auth_key_id' => substr(sha1($key, true), -8), 'call_id' => substr(hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
$this->calls[$params['id']]->configuration['endpoints'] = \array_merge($params['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, 'auth_key_id' => \substr(\sha1($key, true), -8), 'call_id' => \substr(\hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
$this->calls[$params['id']]->parseConfig();
return $this->calls[$params['id']]->startTheMagic();
@ -197,7 +197,7 @@ trait AuthKeyHandler
public function call_status($id)
{
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
throw \danog\MadelineProto\Exception::extension('libtgvoip');
}
if (isset($this->calls[$id])) {
@ -209,7 +209,7 @@ trait AuthKeyHandler
public function get_call($call)
{
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
throw \danog\MadelineProto\Exception::extension('libtgvoip');
}
@ -218,40 +218,40 @@ trait AuthKeyHandler
public function discard_call_async($call, $reason, $rating = [], $need_debug = true)
{
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
throw \danog\MadelineProto\Exception::extension('libtgvoip');
}
if (!isset($this->calls[$call['id']])) {
return;
}
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_discarding'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_discarding'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
try {
$res = yield $this->method_call_async_read('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 = yield $this->method_call_async_read('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) {
if (!in_array($e->rpc, ['CALL_ALREADY_DECLINED', 'CALL_ALREADY_ACCEPTED'])) {
if (!\in_array($e->rpc, ['CALL_ALREADY_DECLINED', 'CALL_ALREADY_ACCEPTED'])) {
throw $e;
}
}
if (!empty($rating)) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_set_rating'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_set_rating'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
yield $this->method_call_async_read('phone.setCallRating', ['peer' => $call, 'rating' => $rating['rating'], 'comment' => $rating['comment']], ['datacenter' => $this->datacenter->curdc]);
}
if ($need_debug && isset($this->calls[$call['id']])) {
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_debug_saving'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_debug_saving'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
yield $this->method_call_async_read('phone.saveCallDebug', ['peer' => $call, 'debug' => $this->calls[$call['id']]->getDebugLog()], ['datacenter' => $this->datacenter->curdc]);
}
$update = ['_' => 'updatePhoneCall', 'phone_call' => $this->calls[$call['id']]];
if (isset($this->settings['pwr']['strict']) && $this->settings['pwr']['strict']) {
$this->pwr_update_handler($update);
} 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']]);
}
public function checkCalls()
{
array_walk($this->calls, function ($controller, $id) {
\array_walk($this->calls, function ($controller, $id) {
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
$controller->discard();
}

View File

@ -18,7 +18,7 @@
namespace danog\MadelineProto;
if (class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
if (\class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
/**
* Manages storage of VoIP server config.
*/
@ -90,7 +90,7 @@ if (class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
*/
public static function getFinal(): array
{
return array_merge(self::$_configDefault, self::$_config);
return \array_merge(self::$_configDefault, self::$_config);
}
}
}

View File

@ -28,11 +28,11 @@ trait ApiStart
{
public function api_start_async($settings)
{
if (php_sapi_name() === 'cli') {
if (PHP_SAPI === 'cli') {
$stdout = getStdout();
yield $stdout->write('You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)
Note that you can also provide the API parameters directly in the code using the settings: https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id'.PHP_EOL);
if (strpos(yield $this->readLine('Your choice (m/a): '), 'm') !== false) {
if (\strpos(yield $this->readLine('Your choice (m/a): '), 'm') !== false) {
yield $stdout->write('1) Login to my.telegram.org
2) Go to API development tools
3) App title: your app\'s name, can be anything
@ -45,68 +45,65 @@ Note that you can also provide the API parameters directly in the code using the
$app['api_hash'] = yield $this->readLine('6) Enter your API hash: ');
return $app;
}
$this->my_telegram_org_wrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings);
yield $this->my_telegram_org_wrapper->login_async(yield $this->readLine('Enter a phone number that is already registered on Telegram: '));
yield $this->my_telegram_org_wrapper->complete_login_async(yield $this->readLine('Enter the verification code you received in telegram: '));
if (!yield $this->my_telegram_org_wrapper->has_app_async()) {
$app_title = yield $this->readLine('Enter the app\'s name, can be anything: ');
$short_name = yield $this->readLine('Enter the app\'s short name, can be anything: ');
$url = yield $this->readLine('Enter the app/website\'s URL, or t.me/yourusername: ');
$description = yield $this->readLine('Describe your app: ');
$app = yield $this->my_telegram_org_wrapper->create_app_async(['app_title' => $app_title, 'app_shortname' => $short_name, 'app_url' => $url, 'app_platform' => 'web', 'app_desc' => $description]);
} else {
$this->my_telegram_org_wrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings);
yield $this->my_telegram_org_wrapper->login_async(yield $this->readLine('Enter a phone number that is already registered on Telegram: '));
yield $this->my_telegram_org_wrapper->complete_login_async(yield $this->readLine('Enter the verification code you received in telegram: '));
if (!yield $this->my_telegram_org_wrapper->has_app_async()) {
$app_title = yield $this->readLine('Enter the app\'s name, can be anything: ');
$short_name = yield $this->readLine('Enter the app\'s short name, can be anything: ');
$url = yield $this->readLine('Enter the app/website\'s URL, or t.me/yourusername: ');
$description = yield $this->readLine('Describe your app: ');
$app = yield $this->my_telegram_org_wrapper->create_app_async(['app_title' => $app_title, 'app_shortname' => $short_name, 'app_url' => $url, 'app_platform' => 'web', 'app_desc' => $description]);
} else {
$app = yield $this->my_telegram_org_wrapper->get_app_async();
$app = yield $this->my_telegram_org_wrapper->get_app_async();
}
return $app;
}
$this->getting_api_id = true;
if (!isset($this->my_telegram_org_wrapper)) {
if (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
$app['api_id'] = (int) $_POST['api_id'];
$app['api_hash'] = $_POST['api_hash'];
$this->getting_api_id = false;
return $app;
} elseif (isset($_POST['phone_number'])) {
yield $this->web_api_phone_login_async($settings);
} else {
yield $this->web_api_echo_async();
}
} elseif (!$this->my_telegram_org_wrapper->logged_in()) {
if (isset($_POST['code'])) {
yield $this->web_api_complete_login_async();
if (yield $this->my_telegram_org_wrapper->has_app_async()) {
return yield $this->my_telegram_org_wrapper->get_app_async();
}
yield $this->web_api_echo_async();
} elseif (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
$app['api_id'] = (int) $_POST['api_id'];
$app['api_hash'] = $_POST['api_hash'];
$this->getting_api_id = false;
return $app;
} elseif (isset($_POST['phone_number'])) {
yield $this->web_api_phone_login_async($settings);
} else {
$this->my_telegram_org_wrapper = null;
yield $this->web_api_echo_async();
}
} else {
if (isset($_POST['app_title'], $_POST['app_shortname'], $_POST['app_url'], $_POST['app_platform'], $_POST['app_desc'])) {
$app = yield $this->web_api_create_app_async();
$this->getting_api_id = false;
return $app;
}
} else {
$this->getting_api_id = true;
if (!isset($this->my_telegram_org_wrapper)) {
if (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
$app['api_id'] = (int) $_POST['api_id'];
$app['api_hash'] = $_POST['api_hash'];
$this->getting_api_id = false;
return $app;
} elseif (isset($_POST['phone_number'])) {
yield $this->web_api_phone_login_async($settings);
} else {
yield $this->web_api_echo_async();
}
} elseif (!$this->my_telegram_org_wrapper->logged_in()) {
if (isset($_POST['code'])) {
yield $this->web_api_complete_login_async();
if (yield $this->my_telegram_org_wrapper->has_app_async()) {
return yield $this->my_telegram_org_wrapper->get_app_async();
}
yield $this->web_api_echo_async();
} elseif (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
$app['api_id'] = (int) $_POST['api_id'];
$app['api_hash'] = $_POST['api_hash'];
$this->getting_api_id = false;
return $app;
} elseif (isset($_POST['phone_number'])) {
yield $this->web_api_phone_login_async($settings);
} else {
$this->my_telegram_org_wrapper = null;
yield $this->web_api_echo_async();
}
} else {
if (isset($_POST['app_title'], $_POST['app_shortname'], $_POST['app_url'], $_POST['app_platform'], $_POST['app_desc'])) {
$app = yield $this->web_api_create_app_async();
$this->getting_api_id = false;
return $app;
} else {
yield $this->web_api_echo_async("You didn't provide all of the required parameters!");
}
}
$this->asyncInitPromise = null;
exit;
yield $this->web_api_echo_async("You didn't provide all of the required parameters!");
}
$this->asyncInitPromise = null;
exit;
}
public function web_api_phone_login_async($settings)

View File

@ -40,7 +40,7 @@ trait ApiTemplates
public function web_api_echo_template($message, $form)
{
return sprintf($this->web_api_template, $message, $form);
return \sprintf($this->web_api_template, $message, $form);
}
public function get_web_api_template()
@ -117,7 +117,8 @@ trait ApiTemplates
<input type="radio" name="app_platform" value="other"> Other (specify in description)
</label>
<br><br>Enter the app description, can be anything: <br><textarea name="app_desc" required></textarea><br><br>
'));
'
));
}
}
}

View File

@ -41,7 +41,7 @@ trait DialogHandler
public function get_full_dialogs_async($force = true)
{
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'])) {
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'])) {
$this->dialog_params = ['limit' => 100, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty'], 'count' => 0, 'hash' => 0];
}
if (!isset($this->dialog_params['hash'])) {
@ -57,8 +57,8 @@ trait DialogHandler
$last_peer = 0;
$last_date = 0;
$last_id = 0;
$res['messages'] = array_reverse($res['messages']);
foreach (array_reverse($res['dialogs']) as $dialog) {
$res['messages'] = \array_reverse($res['messages']);
foreach (\array_reverse($res['dialogs']) as $dialog) {
$id = $this->get_id($dialog['peer']);
if (!isset($dialogs[$id])) {
$dialogs[$id] = $dialog;
@ -82,7 +82,7 @@ trait DialogHandler
$this->dialog_params['offset_date'] = $last_date;
$this->dialog_params['offset_peer'] = $last_peer;
$this->dialog_params['offset_id'] = $last_id;
$this->dialog_params['count'] = count($dialogs);
$this->dialog_params['count'] = \count($dialogs);
} else {
break;
}

View File

@ -30,7 +30,7 @@ trait Events
public function setEventHandler($event_handler)
{
if (!class_exists($event_handler) || !is_subclass_of($event_handler, '\danog\MadelineProto\EventHandler')) {
if (!\class_exists($event_handler) || !\is_subclass_of($event_handler, '\danog\MadelineProto\EventHandler')) {
throw new \danog\MadelineProto\Exception('Wrong event handler was defined');
}
@ -53,7 +53,7 @@ trait Events
}
}
} else {
$method_name = lcfirst(substr($method, 2));
$method_name = \lcfirst(\substr($method, 2));
$this->event_handler_methods[$method_name] = [$this->event_handler_instance, $method];
}
}

View File

@ -37,7 +37,7 @@ trait Loop
public function loop_async($max_forks = 0)
{
if (is_callable($max_forks)) {
if (\is_callable($max_forks)) {
$this->logger->logger('Running async callable');
return yield $max_forks();
@ -52,20 +52,20 @@ trait Loop
return false;
}
if (in_array($this->settings['updates']['callback'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler'])) {
if (\in_array($this->settings['updates']['callback'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler'])) {
$this->logger->logger('Getupdates event handler is enabled, exiting from loop', \danog\MadelineProto\Logger::FATAL_ERROR);
return false;
}
$this->logger->logger('Starting event loop');
if (!is_callable($this->loop_callback) || (is_array($this->loop_callback) && $this->loop_callback[1] === 'onLoop' && !method_exists(...$this->loop_callback))) {
if (!\is_callable($this->loop_callback) || (\is_array($this->loop_callback) && $this->loop_callback[1] === 'onLoop' && !\method_exists(...$this->loop_callback))) {
$this->loop_callback = null;
}
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
$needs_restart = true;
try {
set_time_limit(-1);
\set_time_limit(-1);
} catch (\danog\MadelineProto\Exception $e) {
$needs_restart = true;
}
@ -74,37 +74,37 @@ trait Loop
}
$this->logger->logger($needs_restart ? 'Will self-restart' : 'Will not self-restart');
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$lockfile = dirname(end($backtrace)['file']).'/bot'.$this->authorization['user']['id'].'.lock';
$backtrace = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$lockfile = \dirname(\end($backtrace)['file']).'/bot'.$this->authorization['user']['id'].'.lock';
unset($backtrace);
$try_locking = true;
if (!file_exists($lockfile)) {
touch($lockfile);
$lock = fopen($lockfile, 'r+');
if (!\file_exists($lockfile)) {
\touch($lockfile);
$lock = \fopen($lockfile, 'r+');
} elseif (isset($GLOBALS['lock'])) {
$try_locking = false;
$lock = $GLOBALS['lock'];
} else {
$lock = fopen($lockfile, 'r+');
$lock = \fopen($lockfile, 'r+');
}
if ($try_locking) {
$try = 1;
$locked = false;
while (!$locked) {
$locked = flock($lock, LOCK_EX | LOCK_NB);
$locked = \flock($lock, LOCK_EX | LOCK_NB);
if (!$locked) {
$this->closeConnection('Bot is already running');
if ($try++ >= 30) {
exit;
}
sleep(1);
\sleep(1);
}
}
}
Shutdown::addCallback(static function () use ($lock) {
flock($lock, LOCK_UN);
fclose($lock);
\flock($lock, LOCK_UN);
\fclose($lock);
});
if ($needs_restart) {
$logger = &$this->logger;
@ -117,24 +117,24 @@ trait Loop
$params = $_GET;
$params['MadelineSelfRestart'] = Tools::random_int();
$url = explode($uri, '?', 2)[0] ?? '';
$url = \explode($uri, '?', 2)[0] ?? '';
$query = http_build_query($params);
$uri = implode('?', [$url, $query]);
$query = \http_build_query($params);
$uri = \implode('?', [$url, $query]);
$payload = $_SERVER['REQUEST_METHOD'].' '.$uri.' '.$_SERVER['SERVER_PROTOCOL']."\r\n".'Host: '.$_SERVER['SERVER_NAME']."\r\n\r\n";
$logger->logger("Connecting to $address:$port");
$a = fsockopen($address, $port);
$a = \fsockopen($address, $port);
$logger->logger("Sending self-restart payload");
$logger->logger($payload);
fwrite($a, $payload);
\fwrite($a, $payload);
$logger->logger("Payload sent with token {$params['MadelineSelfRestart']}, waiting for self-restart");
sleep(10);
fclose($a);
\sleep(10);
\fclose($a);
}, 'restarter');
}
@ -155,7 +155,7 @@ trait Loop
$this->updates = [];
foreach ($updates as $update) {
$r = $this->settings['updates']['callback']($update);
if (is_object($r)) {
if (\is_object($r)) {
$this->callFork($r);
}
}
@ -171,23 +171,23 @@ trait Loop
public function closeConnection($message = 'OK!')
{
if (php_sapi_name() === 'cli' || isset($GLOBALS['exited']) || headers_sent()) {
if (PHP_SAPI === 'cli' || isset($GLOBALS['exited']) || \headers_sent()) {
return;
}
$this->logger->logger($message);
$buffer = @ob_get_contents();
@ob_end_clean();
header('Connection: close');
ignore_user_abort(true);
$buffer .= '<html><body><h1>'.htmlentities($message).'</h1></body></html>';
$buffer = @\ob_get_contents();
@\ob_end_clean();
\header('Connection: close');
\ignore_user_abort(true);
$buffer .= '<html><body><h1>'.\htmlentities($message).'</h1></body></html>';
echo $buffer;
$size = max(ob_get_length(), strlen($buffer));
header("Content-Length: $size");
header('Content-Type: text/html');
ob_end_flush();
flush();
$size = \max(\ob_get_length(), \strlen($buffer));
\header("Content-Length: $size");
\header('Content-Type: text/html');
\ob_end_flush();
\flush();
$GLOBALS['exited'] = true;
if (function_exists('fastcgi_finish_request')) {
if (\function_exists('fastcgi_finish_request')) {
\fastcgi_finish_request();
}
}

View File

@ -19,9 +19,6 @@
namespace danog\MadelineProto\Wrappers;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;
/**
* Manages simple logging in and out.
*/
@ -32,8 +29,8 @@ trait Start
if ($this->authorized === self::LOGGED_IN) {
return yield $this->get_self_async();
}
if (php_sapi_name() === 'cli') {
if (strpos(yield $this->readLine('Do you want to login as user or bot (u/b)? '), 'b') !== false) {
if (PHP_SAPI === 'cli') {
if (\strpos(yield $this->readLine('Do you want to login as user or bot (u/b)? '), 'b') !== false) {
yield $this->bot_login_async(yield $this->readLine('Enter your bot token: '));
} else {
yield $this->phone_login_async(yield $this->readLine('Enter your phone number: '));
@ -48,41 +45,40 @@ trait Start
$this->serialize();
return yield $this->get_self_async();
} else {
if ($this->authorized === self::NOT_LOGGED_IN) {
if (isset($_POST['phone_number'])) {
yield $this->web_phone_login_async();
} elseif (isset($_POST['token'])) {
yield $this->web_bot_login_async();
} else {
yield $this->web_echo_async();
}
} elseif ($this->authorized === self::WAITING_CODE) {
if (isset($_POST['phone_code'])) {
yield $this->web_complete_phone_login_async();
} else {
yield $this->web_echo_async("You didn't provide a phone code!");
}
} elseif ($this->authorized === self::WAITING_PASSWORD) {
if (isset($_POST['password'])) {
yield $this->web_complete_2fa_login_async();
} else {
yield $this->web_echo_async("You didn't provide the password!");
}
} elseif ($this->authorized === self::WAITING_SIGNUP) {
if (isset($_POST['first_name'])) {
yield $this->web_complete_signup_async();
} else {
yield $this->web_echo_async("You didn't provide the first name!");
}
}
if ($this->authorized === self::LOGGED_IN) {
$this->serialize();
return yield $this->get_self_async();
}
exit;
}
if ($this->authorized === self::NOT_LOGGED_IN) {
if (isset($_POST['phone_number'])) {
yield $this->web_phone_login_async();
} elseif (isset($_POST['token'])) {
yield $this->web_bot_login_async();
} else {
yield $this->web_echo_async();
}
} elseif ($this->authorized === self::WAITING_CODE) {
if (isset($_POST['phone_code'])) {
yield $this->web_complete_phone_login_async();
} else {
yield $this->web_echo_async("You didn't provide a phone code!");
}
} elseif ($this->authorized === self::WAITING_PASSWORD) {
if (isset($_POST['password'])) {
yield $this->web_complete_2fa_login_async();
} else {
yield $this->web_echo_async("You didn't provide the password!");
}
} elseif ($this->authorized === self::WAITING_SIGNUP) {
if (isset($_POST['first_name'])) {
yield $this->web_complete_signup_async();
} else {
yield $this->web_echo_async("You didn't provide the first name!");
}
}
if ($this->authorized === self::LOGGED_IN) {
$this->serialize();
return yield $this->get_self_async();
}
exit;
}
public function web_phone_login_async()

View File

@ -27,7 +27,7 @@ trait TOS
public function check_tos_async()
{
if ($this->authorized === self::LOGGED_IN && !$this->authorization['user']['bot']) {
if ($this->tos['expires'] < time()) {
if ($this->tos['expires'] < \time()) {
$this->logger->logger('Fetching TOS...');
$this->tos = yield $this->method_call_async_read('help.getTermsOfServiceUpdate', [], ['datacenter' => $this->datacenter->curdc]);
$this->tos['accepted'] = $this->tos['_'] === 'help.termsOfServiceUpdateEmpty';

View File

@ -70,7 +70,7 @@ trait Templates
public function web_echo_template($message, $form)
{
return sprintf($this->web_template, $form, $message);
return \sprintf($this->web_template, $form, $message);
}
public function get_web_template()

View File

@ -4,16 +4,19 @@ function callMe($allable, ...$args)
{
return $allable(...$args);
}
function returnMe($res) {
function returnMe($res)
{
return $res;
}
if (!function_exists('is_iterable')) {
function is_iterable($var) {
return is_array($var) || $var instanceof Traversable;
if (!\function_exists('is_iterable')) {
function is_iterable($var)
{
return \is_array($var) || $var instanceof Traversable;
}
}
if (!function_exists('error_clear_last')) {
function error_clear_last() {
@trigger_error("");
if (!\function_exists('error_clear_last')) {
function error_clear_last()
{
@\trigger_error("");
}
}

View File

@ -11,7 +11,7 @@ final class APITest extends TestCase
*/
public function testCanUseProtocol($transport, $obfuscated, $protocol, $test_mode, $ipv6): void
{
$ping = ['ping_id' => random_int(PHP_INT_MIN, PHP_INT_MAX)];
$ping = ['ping_id' => \random_int(PHP_INT_MIN, PHP_INT_MAX)];
$MadelineProto = new \danog\MadelineProto\API(
[
'app_info' => [

View File

@ -2,7 +2,7 @@
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
* for using the new PHP 7 random_* API in PHP 5 projects.
*
* @version 2.0.17
* @released 2018-07-04
@ -29,12 +29,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
use phpseclib\Crypt;
if (!defined('PHP_VERSION_ID')) {
if (!\defined('PHP_VERSION_ID')) {
// This constant was introduced in PHP 5.2.7
$RandomCompatversion = array_map('intval', explode('.', PHP_VERSION));
define('PHP_VERSION_ID', $RandomCompatversion[0] * 10000 + $RandomCompatversion[1] * 100 + $RandomCompatversion[2]);
$RandomCompatversion = \array_map('intval', \explode('.', PHP_VERSION));
\define('PHP_VERSION_ID', $RandomCompatversion[0] * 10000 + $RandomCompatversion[1] * 100 + $RandomCompatversion[2]);
$RandomCompatversion = null;
}
/**
@ -43,16 +42,16 @@ if (!defined('PHP_VERSION_ID')) {
if (PHP_VERSION_ID >= 70000) {
return;
}
if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
define('RANDOM_COMPAT_READ_BUFFER', 8);
if (!\defined('RANDOM_COMPAT_READ_BUFFER')) {
\define('RANDOM_COMPAT_READ_BUFFER', 8);
}
$RandomCompatDIR = dirname(__FILE__);
$RandomCompatDIR = \dirname(__FILE__);
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'byte_safe_strings.php';
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'cast_to_int.php';
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'error_polyfill.php';
if (!is_callable('random_bytes')) {
if (!\is_callable('random_bytes')) {
/**
* PHP 5.2.0 - 5.6.x way to implement random_bytes()
* PHP 5.2.0 - 5.6.x way to implement random_bytes().
*
* We use conditional statements here to define the function in accordance
* to the operating environment. It's a micro-optimization.
@ -65,28 +64,28 @@ if (!is_callable('random_bytes')) {
*
* See RATIONALE.md for our reasoning behind this particular order
*/
if (extension_loaded('libsodium')) {
if (\extension_loaded('libsodium')) {
// See random_bytes_libsodium.php
if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
if (PHP_VERSION_ID >= 50300 && \is_callable('\\Sodium\\randombytes_buf')) {
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium.php';
} elseif (method_exists('Sodium', 'randombytes_buf')) {
} elseif (\method_exists('Sodium', 'randombytes_buf')) {
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium_legacy.php';
}
}
/**
* Reading directly from /dev/urandom:
* Reading directly from /dev/urandom:.
*/
if (DIRECTORY_SEPARATOR === '/') {
// DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
// way to exclude Windows.
$RandomCompatUrandom = true;
$RandomCompat_basedir = ini_get('open_basedir');
$RandomCompat_basedir = \ini_get('open_basedir');
if (!empty($RandomCompat_basedir)) {
$RandomCompat_open_basedir = explode(PATH_SEPARATOR, strtolower($RandomCompat_basedir));
$RandomCompatUrandom = array() !== array_intersect(array('/dev', '/dev/', '/dev/urandom'), $RandomCompat_open_basedir);
$RandomCompat_open_basedir = \explode(PATH_SEPARATOR, \strtolower($RandomCompat_basedir));
$RandomCompatUrandom = [] !== \array_intersect(['/dev', '/dev/', '/dev/urandom'], $RandomCompat_open_basedir);
$RandomCompat_open_basedir = null;
}
if (!is_callable('random_bytes') && $RandomCompatUrandom && @is_readable('/dev/urandom')) {
if (!\is_callable('random_bytes') && $RandomCompatUrandom && @\is_readable('/dev/urandom')) {
// Error suppression on is_readable() in case of an open_basedir
// or safe_mode failure. All we care about is whether or not we
// can read it at this point. If the PHP environment is going to
@ -101,7 +100,7 @@ if (!is_callable('random_bytes')) {
$RandomCompatUrandom = false;
}
/**
* mcrypt_create_iv()
* mcrypt_create_iv().
*
* We only want to use mcypt_create_iv() if:
*
@ -118,7 +117,7 @@ if (!is_callable('random_bytes')) {
* - If we're on Windows, we want to use PHP >= 5.3.7 or else
* we get insufficient entropy errors.
*/
if (!is_callable('random_bytes') && (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307) && (DIRECTORY_SEPARATOR !== '/' || (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)) && extension_loaded('mcrypt')) {
if (!\is_callable('random_bytes') && (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307) && (DIRECTORY_SEPARATOR !== '/' || (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)) && \extension_loaded('mcrypt')) {
// See random_bytes_mcrypt.php
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_mcrypt.php';
}
@ -127,12 +126,12 @@ if (!is_callable('random_bytes')) {
* This is a Windows-specific fallback, for when the mcrypt extension
* isn't loaded.
*/
if (!is_callable('random_bytes') && extension_loaded('com_dotnet') && class_exists('COM')) {
$RandomCompat_disabled_classes = preg_split('#\\s*,\\s*#', strtolower(ini_get('disable_classes')));
if (!in_array('com', $RandomCompat_disabled_classes)) {
if (!\is_callable('random_bytes') && \extension_loaded('com_dotnet') && \class_exists('COM')) {
$RandomCompat_disabled_classes = \preg_split('#\\s*,\\s*#', \strtolower(\ini_get('disable_classes')));
if (!\in_array('com', $RandomCompat_disabled_classes)) {
try {
$RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
if (\method_exists($RandomCompatCOMtest, 'GetRandom')) {
// See random_bytes_com_dotnet.php
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_com_dotnet.php';
}
@ -144,39 +143,39 @@ if (!is_callable('random_bytes')) {
$RandomCompatCOMtest = null;
}
/**
* throw new Exception
* throw new Exception.
*/
if (!is_callable('random_bytes')) {
/**
* Safely serialize variables
*
* If a class has a private __sleep() it'll emit a warning
* @return mixed
* @param mixed $arr
*/
function safe_serialize(&$arr)
{
if (is_object($arr)) {
return '';
}
if (!is_array($arr)) {
return serialize($arr);
}
// prevent circular array recursion
if (isset($arr['__phpseclib_marker'])) {
return '';
}
$safearr = [];
$arr['__phpseclib_marker'] = true;
foreach (array_keys($arr) as $key) {
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
if ($key !== '__phpseclib_marker') {
$safearr[$key] = safe_serialize($arr[$key]);
if (!\is_callable('random_bytes')) {
/**
* Safely serialize variables.
*
* If a class has a private __sleep() it'll emit a warning
* @return mixed
* @param mixed $arr
*/
function safe_serialize(&$arr)
{
if (\is_object($arr)) {
return '';
}
if (!\is_array($arr)) {
return \serialize($arr);
}
// prevent circular array recursion
if (isset($arr['__phpseclib_marker'])) {
return '';
}
$safearr = [];
$arr['__phpseclib_marker'] = true;
foreach (\array_keys($arr) as $key) {
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
if ($key !== '__phpseclib_marker') {
$safearr[$key] = safe_serialize($arr[$key]);
}
}
unset($arr['__phpseclib_marker']);
return \serialize($safearr);
}
unset($arr['__phpseclib_marker']);
return serialize($safearr);
}
/**
* We don't have any more options, so let's throw an exception right now
* and hope the developer won't let it fail silently.
@ -188,104 +187,104 @@ if (!is_callable('random_bytes')) {
*/
function random_bytes($length)
{
static $crypto = false, $v;
if ($crypto === false) {
// save old session data
$old_session_id = session_id();
$old_use_cookies = ini_get('session.use_cookies');
$old_session_cache_limiter = session_cache_limiter();
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
if ($old_session_id != '') {
session_write_close();
}
session_id(1);
ini_set('session.use_cookies', 0);
session_cache_limiter('');
session_start();
$v = (isset($_SERVER) ? safe_serialize($_SERVER) : '') . (isset($_POST) ? safe_serialize($_POST) : '') . (isset($_GET) ? safe_serialize($_GET) : '') . (isset($_COOKIE) ? safe_serialize($_COOKIE) : '') . safe_serialize($GLOBALS) . safe_serialize($_SESSION) . safe_serialize($_OLD_SESSION);
$v = $seed = $_SESSION['seed'] = sha1($v, true);
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
$_SESSION['count']++;
session_write_close();
// restore old session data
if ($old_session_id != '') {
session_id($old_session_id);
session_start();
ini_set('session.use_cookies', $old_use_cookies);
session_cache_limiter($old_session_cache_limiter);
} else {
if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION);
} else {
unset($_SESSION);
static $crypto = false, $v;
if ($crypto === false) {
// save old session data
$old_session_id = \session_id();
$old_use_cookies = \ini_get('session.use_cookies');
$old_session_cache_limiter = \session_cache_limiter();
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
if ($old_session_id != '') {
\session_write_close();
}
}
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
//
// http://tools.ietf.org/html/rfc4253#section-7.2
//
// see the is_string($crypto) part for an example of how to expand the keys
$key = sha1($seed . 'A', true);
$iv = sha1($seed . 'C', true);
// ciphers are used as per the nist.gov link below. also, see this link:
//
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
switch (true) {
case class_exists('\\phpseclib\\Crypt\\AES'):
\session_id(1);
\ini_set('session.use_cookies', 0);
\session_cache_limiter('');
\session_start();
$v = (isset($_SERVER) ? safe_serialize($_SERVER) : '') . (isset($_POST) ? safe_serialize($_POST) : '') . (isset($_GET) ? safe_serialize($_GET) : '') . (isset($_COOKIE) ? safe_serialize($_COOKIE) : '') . safe_serialize($GLOBALS) . safe_serialize($_SESSION) . safe_serialize($_OLD_SESSION);
$v = $seed = $_SESSION['seed'] = \sha1($v, true);
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
$_SESSION['count']++;
\session_write_close();
// restore old session data
if ($old_session_id != '') {
\session_id($old_session_id);
\session_start();
\ini_set('session.use_cookies', $old_use_cookies);
\session_cache_limiter($old_session_cache_limiter);
} else {
if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION);
} else {
unset($_SESSION);
}
}
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
//
// http://tools.ietf.org/html/rfc4253#section-7.2
//
// see the is_string($crypto) part for an example of how to expand the keys
$key = \sha1($seed . 'A', true);
$iv = \sha1($seed . 'C', true);
// ciphers are used as per the nist.gov link below. also, see this link:
//
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
switch (true) {
case \class_exists('\\phpseclib\\Crypt\\AES'):
$crypto = new \phpseclib\Crypt\AES('ctr');
break;
case class_exists('\\phpseclib\\Crypt\\Twofish'):
case \class_exists('\\phpseclib\\Crypt\\Twofish'):
$crypto = new \phpseclib\Crypt\Twofish('ctr');
break;
case class_exists('\\phpseclib\\Crypt\\Blowfish'):
case \class_exists('\\phpseclib\\Crypt\\Blowfish'):
$crypto = new \phpseclib\Crypt\Blowfish('ctr');
break;
case class_exists('\\phpseclib\\Crypt\\TripleDES'):
case \class_exists('\\phpseclib\\Crypt\\TripleDES'):
$crypto = new \phpseclib\Crypt\TripleDES('ctr');
break;
case class_exists('\\phpseclib\\Crypt\\DES'):
case \class_exists('\\phpseclib\\Crypt\\DES'):
$crypto = new \phpseclib\Crypt\DES('ctr');
break;
case class_exists('\\phpseclib\\Crypt\\RC4'):
case \class_exists('\\phpseclib\\Crypt\\RC4'):
$crypto = new \phpseclib\Crypt\RC4();
break;
default:
throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded');
}
$crypto->setKey(substr($key, 0, $crypto->getKeyLength() >> 3));
$crypto->setIV(substr($iv, 0, $crypto->getBlockLength() >> 3));
$crypto->enableContinuousBuffer();
}
//return $crypto->encrypt(str_repeat("\0", $length));
// the following is based off of ANSI X9.31:
//
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
//
// OpenSSL uses that same standard for it's random numbers:
//
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
// (do a search for "ANS X9.31 A.2.4")
$result = '';
while (strlen($result) < $length) {
$i = $crypto->encrypt(microtime());
// strlen(microtime()) == 21
$r = $crypto->encrypt($i ^ $v);
// strlen($v) == 20
$v = $crypto->encrypt($r ^ $i);
// strlen($r) == 20
$result .= $r;
}
return substr($result, 0, $length);
$crypto->setKey(\substr($key, 0, $crypto->getKeyLength() >> 3));
$crypto->setIV(\substr($iv, 0, $crypto->getBlockLength() >> 3));
$crypto->enableContinuousBuffer();
}
//return $crypto->encrypt(str_repeat("\0", $length));
// the following is based off of ANSI X9.31:
//
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
//
// OpenSSL uses that same standard for it's random numbers:
//
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
// (do a search for "ANS X9.31 A.2.4")
$result = '';
while (\strlen($result) < $length) {
$i = $crypto->encrypt(\microtime());
// strlen(microtime()) == 21
$r = $crypto->encrypt($i ^ $v);
// strlen($v) == 20
$v = $crypto->encrypt($r ^ $i);
// strlen($r) == 20
$result .= $r;
}
return \substr($result, 0, $length);
}
}
}
if (!is_callable('random_int')) {
if (!\is_callable('random_int')) {
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_int.php';
}
$RandomCompatDIR = null;

View File

@ -14,13 +14,13 @@ If not, see <http://www.gnu.org/licenses/>.
/**
* Various ways to load MadelineProto.
*/
if (!file_exists(__DIR__.'/../vendor/autoload.php')) {
if (!\file_exists(__DIR__.'/../vendor/autoload.php')) {
echo 'You did not run composer update, using madeline.php'.PHP_EOL;
if ($phar = getenv('TRAVIS_PHAR')) {
if ($phar = \getenv('TRAVIS_PHAR')) {
include $phar;
} else {
if (!file_exists('madeline.php')) {
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
if (!\file_exists('madeline.php')) {
\copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
}
include 'madeline.php';
}
@ -31,23 +31,23 @@ if (!file_exists(__DIR__.'/../vendor/autoload.php')) {
/*
* Load .env for settings
*/
if (file_exists('.env')) {
if (\file_exists('.env')) {
echo 'Loading .env...'.PHP_EOL;
$dotenv = Dotenv\Dotenv::create(getcwd());
$dotenv = Dotenv\Dotenv::create(\getcwd());
$dotenv->load();
}
if (getenv('TEST_SECRET_CHAT') == '') {
echo ('TEST_SECRET_CHAT is not defined in .env, please define it (copy .env.example).'.PHP_EOL);
if (\getenv('TEST_SECRET_CHAT') == '') {
echo('TEST_SECRET_CHAT is not defined in .env, please define it (copy .env.example).'.PHP_EOL);
die(1);
}
echo 'Loading settings...'.PHP_EOL;
$settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: [];
$settings = \json_decode(\getenv('MTPROTO_SETTINGS'), true) ?: [];
/*
* Load MadelineProto
*/
echo 'Loading MadelineProto...'.PHP_EOL;
$MadelineProto = new \danog\MadelineProto\API(getcwd().'/testing.madeline', $settings);
$MadelineProto = new \danog\MadelineProto\API(\getcwd().'/testing.madeline', $settings);
$MadelineProto->fileGetContents('https://google.com');
$MadelineProto->start();
@ -82,13 +82,13 @@ try {
/**
* A small example message to use for tests.
*/
$message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd) (Ngimbonga ngaso sonke isikhathi ukusebenza)' : ('Travis ci tests in progress: commit '.getenv('TRAVIS_COMMIT').', job '.getenv('TRAVIS_JOB_NUMBER').', PHP version: '.getenv('TRAVIS_PHP_VERSION'));
$message = (\getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd) (Ngimbonga ngaso sonke isikhathi ukusebenza)' : ('Travis ci tests in progress: commit '.\getenv('TRAVIS_COMMIT').', job '.\getenv('TRAVIS_JOB_NUMBER').', PHP version: '.\getenv('TRAVIS_PHP_VERSION'));
/*
* Try making a phone call
*/
if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to make a call? (y/n): '), 'y') !== false) {
$controller = $MadelineProto->request_call(getenv('TEST_SECRET_CHAT'))->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw');
if (!\getenv('TRAVIS_COMMIT') && \stripos($MadelineProto->readline('Do you want to make a call? (y/n): '), 'y') !== false) {
$controller = $MadelineProto->request_call(\getenv('TEST_SECRET_CHAT'))->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw');
while ($controller->getCallState() < \danog\MadelineProto\VoIP::CALL_STATE_READY) {
$MadelineProto->get_updates();
}
@ -101,7 +101,7 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
/*
* Try receiving a phone call
*/
if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to handle incoming calls? (y/n): '), 'y') !== false) {
if (!\getenv('TRAVIS_COMMIT') && \stripos($MadelineProto->readline('Do you want to handle incoming calls? (y/n): '), 'y') !== false) {
$howmany = $MadelineProto->readline('How many calls would you like me to handle? ');
$offset = 0;
while ($howmany > 0) {
@ -111,7 +111,7 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
switch ($update['update']['_']) {
case 'updatePhoneCall':
if (is_object($update['update']['phone_call']) && $update['update']['phone_call']->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_INCOMING) {
if (\is_object($update['update']['phone_call']) && $update['update']['phone_call']->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_INCOMING) {
$update['update']['phone_call']->accept()->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw');
$howmany--;
}
@ -123,12 +123,12 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
/*
* Secret chat usage
*/
if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to make the secret chat tests? (y/n): '), 'y') !== false) {
if (!\getenv('TRAVIS_COMMIT') && \stripos($MadelineProto->readline('Do you want to make the secret chat tests? (y/n): '), 'y') !== false) {
/**
* Request a secret chat.
*/
$secret_chat_id = $MadelineProto->request_secret_chat(getenv('TEST_SECRET_CHAT'));
echo 'Waiting for '.getenv('TEST_SECRET_CHAT').' (secret chat id '.$secret_chat_id.') to accept the secret chat...'.PHP_EOL;
$secret_chat_id = $MadelineProto->request_secret_chat(\getenv('TEST_SECRET_CHAT'));
echo 'Waiting for '.\getenv('TEST_SECRET_CHAT').' (secret chat id '.$secret_chat_id.') to accept the secret chat...'.PHP_EOL;
/*
* Wait until the other party accepts it
@ -167,13 +167,13 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
'message' => '', // No text message, only media
'media' => [
'_' => 'decryptedMessageMediaDocument',
'thumb' => file_get_contents('tests/faust.preview.jpg'), // The thumbnail must be generated manually, it must be in jpg format, 90x90
'thumb' => \file_get_contents('tests/faust.preview.jpg'), // The thumbnail must be generated manually, it must be in jpg format, 90x90
'thumb_w' => 90,
'thumb_h' => 90,
'mime_type' => mime_content_type('tests/faust.jpg'), // The file's mime type
'mime_type' => \mime_content_type('tests/faust.jpg'), // The file's mime type
'caption' => 'This file was uploaded using @MadelineProto', // The caption
'file_name' => 'faust.jpg', // The file's name
'size' => filesize('tests/faust.jpg'), // The file's size
'size' => \filesize('tests/faust.jpg'), // The file's size
'attributes' => [
['_' => 'documentAttributeImageSize', 'w' => 1280, 'h' => 914], // Image's resolution
],
@ -191,11 +191,11 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
'message' => '',
'media' => [
'_' => 'decryptedMessageMediaPhoto',
'thumb' => file_get_contents('tests/faust.preview.jpg'),
'thumb' => \file_get_contents('tests/faust.preview.jpg'),
'thumb_w' => 90,
'thumb_h' => 90,
'caption' => 'This file was uploaded using @MadelineProto',
'size' => filesize('tests/faust.jpg'),
'size' => \filesize('tests/faust.jpg'),
'w' => 1280,
'h' => 914,
],
@ -203,20 +203,20 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
];
// GIF, secret chat
$secret_media['gif'] = ['peer' => $secret_chat_id, 'file' => 'tests/pony.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => file_get_contents('tests/pony.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => mime_content_type('tests/pony.mp4'), 'caption' => 'test', 'file_name' => 'pony.mp4', 'size' => filesize('tests/faust.jpg'), 'attributes' => [['_' => 'documentAttributeAnimated']]]]];
$secret_media['gif'] = ['peer' => $secret_chat_id, 'file' => 'tests/pony.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/pony.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/pony.mp4'), 'caption' => 'test', 'file_name' => 'pony.mp4', 'size' => \filesize('tests/faust.jpg'), 'attributes' => [['_' => 'documentAttributeAnimated']]]]];
// Sticker, secret chat
$secret_media['sticker'] = ['peer' => $secret_chat_id, 'file' => 'tests/lel.webp', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => file_get_contents('tests/lel.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => mime_content_type('tests/lel.webp'), 'caption' => 'test', 'file_name' => 'lel.webp', 'size' => filesize('tests/lel.webp'), 'attributes' => [['_' => 'documentAttributeSticker', 'alt' => 'LEL', 'stickerset' => ['_' => 'inputStickerSetEmpty']]]]]];
$secret_media['sticker'] = ['peer' => $secret_chat_id, 'file' => 'tests/lel.webp', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/lel.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/lel.webp'), 'caption' => 'test', 'file_name' => 'lel.webp', 'size' => \filesize('tests/lel.webp'), 'attributes' => [['_' => 'documentAttributeSticker', 'alt' => 'LEL', 'stickerset' => ['_' => 'inputStickerSetEmpty']]]]]];
// Document, secret chat
$secret_media['document'] = ['peer' => $secret_chat_id, 'file' => 'tests/60', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => 'magic/magic', 'caption' => 'test', 'file_name' => 'magic.magic', 'size' => filesize('tests/60'), 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'fairy']]]]];
$secret_media['document'] = ['peer' => $secret_chat_id, 'file' => 'tests/60', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => 'magic/magic', 'caption' => 'test', 'file_name' => 'magic.magic', 'size' => \filesize('tests/60'), 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'fairy']]]]];
// Video, secret chat
$secret_media['video'] = ['peer' => $secret_chat_id, 'file' => 'tests/swing.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => file_get_contents('tests/swing.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => mime_content_type('tests/swing.mp4'), 'caption' => 'test', 'file_name' => 'swing.mp4', 'size' => filesize('tests/swing.mp4'), 'attributes' => [['_' => 'documentAttributeVideo']]]]];
$secret_media['video'] = ['peer' => $secret_chat_id, 'file' => 'tests/swing.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/swing.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/swing.mp4'), 'caption' => 'test', 'file_name' => 'swing.mp4', 'size' => \filesize('tests/swing.mp4'), 'attributes' => [['_' => 'documentAttributeVideo']]]]];
// audio, secret chat
$secret_media['audio'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]];
$secret_media['voice'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]];
$secret_media['audio'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]];
$secret_media['voice'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]];
foreach ($secret_media as $type => $smessage) {
\danog\MadelineProto\Logger::log("Encrypting and uploading $type...");
@ -224,7 +224,7 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
}
}
$mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
$mention = $MadelineProto->get_info(\getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
$mention = $mention['user_id']; // Selects only the numeric user id
$media = [];
@ -247,7 +247,7 @@ $media['voice'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/mosconi
$media['document'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/60', 'mime_type' => 'magic/magic', 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'magic.magic']]];
$message = 'yay';
$mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
$mention = $MadelineProto->get_info(\getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
$mention = $mention['user_id']; // Selects only the numeric user id
/*
@ -256,8 +256,8 @@ $MadelineProto->upload('big');
var_dump(time()-$t);
*/
foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]);
foreach (\json_decode(\getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => \mb_strlen($message), 'user_id' => $mention]]]);
\danog\MadelineProto\Logger::log($sentMessage, \danog\MadelineProto\Logger::NOTICE);
foreach ($media as $type => $inputMedia) {
@ -266,7 +266,7 @@ foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
}
}
foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]);
foreach (\json_decode(\getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => \mb_strlen($message), 'user_id' => $mention]]]);
\danog\MadelineProto\Logger::log($sentMessage, \danog\MadelineProto\Logger::NOTICE);
}

View File

@ -11,10 +11,10 @@ You should have received a copy of the GNU General Public License along with Mad
If not, see <http://www.gnu.org/licenses/>.
*/
if (!file_exists(__DIR__.'/../vendor/autoload.php')) {
if (!\file_exists(__DIR__.'/../vendor/autoload.php')) {
echo 'You did not run composer update, using madeline.php'.PHP_EOL;
if (!file_exists('madeline.php')) {
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
if (!\file_exists('madeline.php')) {
\copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
}
include 'madeline.php';
} else {
@ -28,11 +28,11 @@ try {
$MadelineProto = new \danog\MadelineProto\API('MadelineProto_bot.madeline');
} catch (\danog\MadelineProto\Exception $e) {
$MadelineProto = new \danog\MadelineProto\API($settings);
$authorization = $MadelineProto->bot_login(readline('Enter a bot token: '));
$authorization = $MadelineProto->bot_login(\readline('Enter a bot token: '));
\danog\MadelineProto\Logger::log($authorization, \danog\MadelineProto\Logger::NOTICE);
}
if (file_exists('token.php') && $MadelineProto === false) {
if (\file_exists('token.php') && $MadelineProto === false) {
include_once 'token.php';
$MadelineProto = new \danog\MadelineProto\API($settings);
$authorization = $MadelineProto->bot_login($MadelineProto_token);
@ -82,7 +82,7 @@ while (true) {
}
try {
if (isset($update['update']['message']['message']) && preg_match('|/start|', $update['update']['message']['message'])) {
if (isset($update['update']['message']['message']) && \preg_match('|/start|', $update['update']['message']['message'])) {
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => $start, 'reply_to_msg_id' => $update['update']['message']['id'], 'parse_mode' => 'markdown', 'reply_markup' => $reply_markup]);
}
} catch (\danog\MadelineProto\RPCErrorException $e) {
@ -95,7 +95,7 @@ while (true) {
}
try {
if (preg_match('|/start|', $update['update']['message']['message'])) {
if (\preg_match('|/start|', $update['update']['message']['message'])) {
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['to_id'], 'message' => $start, 'reply_to_msg_id' => $update['update']['message']['id'], 'parse_mode' => 'markdown', 'reply_markup' => $reply_markup]);
}
} catch (\danog\MadelineProto\RPCErrorException $e) {
@ -111,18 +111,18 @@ while (true) {
$MadelineProto->messages->setInlineBotResults(['query_id' => $update['update']['query_id'], 'results' => [], 'cache_time' => 0, 'switch_pm' => $sswitch]);
} else {
$toset = ['query_id' => $update['update']['query_id'], 'results' => [], 'cache_time' => 0, 'private' => true];
$rows = explode("\n", $update['update']['query']);
$text = array_shift($rows);
$rows = \explode("\n", $update['update']['query']);
$text = \array_shift($rows);
if (empty($rows)) {
$MadelineProto->messages->setInlineBotResults(['query_id' => $update['update']['query_id'], 'results' => [], 'cache_time' => 0, 'switch_pm' => $sswitch]);
} else {
array_walk($rows, function (&$value, $key) {
$value = explode('|', $value);
array_walk($value, function (&$value, $key) {
$value = ['text' => trim($value), 'url' => 'https://yayponies.eu'];
\array_walk($rows, function (&$value, $key) {
$value = \explode('|', $value);
\array_walk($value, function (&$value, $key) {
$value = ['text' => \trim($value), 'url' => 'https://yayponies.eu'];
});
});
$toset['results'] = [['_' => 'inputBotInlineResult', 'id' => (string) random_int(0, pow(2, 31) - 1), 'type' => 'article', 'title' => $text, 'description' => 'Your keyboard', 'send_message' => ['_' => 'inputBotInlineMessageText', 'message' => $text, 'reply_markup' => ['inline_keyboard' => $rows]]]];
$toset['results'] = [['_' => 'inputBotInlineResult', 'id' => (string) \random_int(0, \pow(2, 31) - 1), 'type' => 'article', 'title' => $text, 'description' => 'Your keyboard', 'send_message' => ['_' => 'inputBotInlineMessageText', 'message' => $text, 'reply_markup' => ['inline_keyboard' => $rows]]]];
$MadelineProto->messages->setInlineBotResults($toset);
}
}

View File

@ -11,10 +11,10 @@ You should have received a copy of the GNU General Public License along with Mad
If not, see <http://www.gnu.org/licenses/>.
*/
if (!file_exists(__DIR__.'/../vendor/autoload.php')) {
if (!\file_exists(__DIR__.'/../vendor/autoload.php')) {
echo 'You did not run composer update, using madeline.php'.PHP_EOL;
if (!file_exists('madeline.php')) {
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
if (!\file_exists('madeline.php')) {
\copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
}
include 'madeline.php';
} else {
@ -36,7 +36,7 @@ try {
} catch (\danog\MadelineProto\Exception $e) {
\danog\MadelineProto\Logger::log($e->getMessage());
}
if (file_exists('token.php') && $MadelineProto === false) {
if (\file_exists('token.php') && $MadelineProto === false) {
include_once 'token.php';
$MadelineProto = new \danog\MadelineProto\API($settings);
$authorization = $MadelineProto->bot_login($pipes_token);
@ -44,11 +44,11 @@ if (file_exists('token.php') && $MadelineProto === false) {
}
if ($uMadelineProto === false) {
echo 'Loading MadelineProto...'.PHP_EOL;
$uMadelineProto = new \danog\MadelineProto\API(array_merge($settings, ['updates' => ['handle_updates' => false]]));
$sentCode = $uMadelineProto->phone_login(readline());
$uMadelineProto = new \danog\MadelineProto\API(\array_merge($settings, ['updates' => ['handle_updates' => false]]));
$sentCode = $uMadelineProto->phone_login(\readline());
\danog\MadelineProto\Logger::log($sentCode, \danog\MadelineProto\Logger::NOTICE);
echo 'Enter the code you received: ';
$code = fgets(STDIN, (isset($sentCode['type']['length']) ? $sentCode['type']['length'] : 5) + 1);
$code = \fgets(STDIN, (isset($sentCode['type']['length']) ? $sentCode['type']['length'] : 5) + 1);
$authorization = $uMadelineProto->complete_phone_login($code);
\danog\MadelineProto\Logger::log($authorization, \danog\MadelineProto\Logger::NOTICE);
if ($authorization['_'] === 'account.noPassword') {
@ -56,14 +56,14 @@ if ($uMadelineProto === false) {
}
if ($authorization['_'] === 'account.password') {
\danog\MadelineProto\Logger::log('2FA is enabled', \danog\MadelineProto\Logger::NOTICE);
$authorization = $uMadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
$authorization = $uMadelineProto->complete_2fa_login(\readline('Please enter your password (hint '.$authorization['hint'].'): '));
}
echo 'Serializing MadelineProto to session.madeline...'.PHP_EOL;
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('session.madeline', $uMadelineProto).' bytes'.PHP_EOL;
}
function inputify(&$stuff)
{
$stuff['_'] = 'input'.ucfirst($stuff['_']);
$stuff['_'] = 'input'.\ucfirst($stuff['_']);
return $stuff;
}
@ -127,7 +127,7 @@ while (true) {
}
try {
if (preg_match('|/start|', $update['update']['message']['message'])) {
if (\preg_match('|/start|', $update['update']['message']['message'])) {
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => $start, 'reply_to_msg_id' => $update['update']['message']['id']]);
}
} catch (\danog\MadelineProto\RPCErrorException $e) {
@ -140,7 +140,7 @@ while (true) {
}
try {
if (preg_match('|/start|', $update['update']['message']['message'])) {
if (\preg_match('|/start|', $update['update']['message']['message'])) {
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['to_id'], 'message' => $start, 'reply_to_msg_id' => $update['update']['message']['id']]);
}
} catch (\danog\MadelineProto\RPCErrorException $e) {
@ -156,19 +156,19 @@ while (true) {
$MadelineProto->messages->setInlineBotResults(['query_id' => $update['update']['query_id'], 'results' => [], 'cache_time' => 0, 'switch_pm' => $sswitch]);
} else {
$toset = ['query_id' => $update['update']['query_id'], 'results' => [], 'cache_time' => 0, 'private' => true];
if (preg_match('|\$\s*$|', $update['update']['query'])) {
$exploded = explode('|', preg_replace('/\$\s*$/', '', $update['update']['query']));
array_walk($exploded, function (&$value, $key) {
$value = preg_replace(['/^\s+/', '/\s+$/'], '', $value);
if (\preg_match('|\$\s*$|', $update['update']['query'])) {
$exploded = \explode('|', \preg_replace('/\$\s*$/', '', $update['update']['query']));
\array_walk($exploded, function (&$value, $key) {
$value = \preg_replace(['/^\s+/', '/\s+$/'], '', $value);
});
$query = array_shift($exploded);
$query = \array_shift($exploded);
foreach ($exploded as $current => $botq) {
$bot = preg_replace('|:.*|', '', $botq);
$bot = \preg_replace('|:.*|', '', $botq);
if ($bot === '' || $uMadelineProto->get_info($bot)['bot_api_id'] === $MadelineProto->API->authorization['user']['id']) {
$toset['switch_pm'] = $sswitch;
break;
}
$select = preg_replace('|'.$bot.':|', '', $botq);
$select = \preg_replace('|'.$bot.':|', '', $botq);
$results = $uMadelineProto->messages->getInlineBotResults(['bot' => $bot, 'peer' => $update['update']['user_id'], 'query' => $query, 'offset' => $offset]);
if (isset($results['switch_pm'])) {
$toset['switch_pm'] = $results['switch_pm'];
@ -176,13 +176,13 @@ while (true) {
}
$toset['gallery'] = $results['gallery'];
$toset['results'] = [];
if (is_numeric($select)) {
if (\is_numeric($select)) {
$toset['results'][0] = $results['results'][$select - 1];
} elseif ($select === '') {
$toset['results'] = $results['results'];
} else {
foreach ($results['results'] as $result) {
if (isset($result['send_message']['message']) && preg_match('|'.$select.'|', $result['send_message']['message'])) {
if (isset($result['send_message']['message']) && \preg_match('|'.$select.'|', $result['send_message']['message'])) {
$toset['results'][0] = $result;
}
}
@ -190,7 +190,7 @@ while (true) {
if (!isset($toset['results'][0])) {
$toset['results'] = $results['results'];
}
if (count($exploded) - 1 === $current || !isset($toset['results'][0]['send_message']['message'])) {
if (\count($exploded) - 1 === $current || !isset($toset['results'][0]['send_message']['message'])) {
break;
}
$query = $toset['results'][0]['send_message']['message'];
@ -199,7 +199,7 @@ while (true) {
if (empty($toset['results'])) {
$toset['switch_pm'] = $sswitch;
} else {
array_walk($toset['results'], 'translate');
\array_walk($toset['results'], 'translate');
}
$MadelineProto->messages->setInlineBotResults($toset);
}

View File

@ -11,10 +11,10 @@ You should have received a copy of the GNU General Public License along with Mad
If not, see <http://www.gnu.org/licenses/>.
*/
if (!file_exists(__DIR__.'/../vendor/autoload.php')) {
if (!\file_exists(__DIR__.'/../vendor/autoload.php')) {
echo 'You did not run composer update, using madeline.php'.PHP_EOL;
if (!file_exists('madeline.php')) {
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
if (!\file_exists('madeline.php')) {
\copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
}
include 'madeline.php';
} else {
@ -33,15 +33,15 @@ try {
}
function base64url_decode($data)
{
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));
}
function rle_decode($string)
{
$base256 = '';
$last = '';
foreach (str_split($string) as $cur) {
if ($last === chr(0)) {
$base256 .= str_repeat($last, ord($cur));
foreach (\str_split($string) as $cur) {
if ($last === \chr(0)) {
$base256 .= \str_repeat($last, \ord($cur));
$last = '';
} else {
$base256 .= $last;
@ -63,12 +63,12 @@ function foreach_offset_length($string)
}
$string = str_replace($a, $b, $string);*/
$res = [];
$strlen = strlen($string);
for ($offset = 0; $offset < strlen($string); $offset++) {
$strlen = \strlen($string);
for ($offset = 0; $offset < \strlen($string); $offset++) {
// for ($length = $strlen - $offset; $length > 0; $length--) {
foreach (['i' => 4, 'q' => 8] as $c => $length) {
$s = substr($string, $offset, $length);
if (strlen($s) === $length) {
$s = \substr($string, $offset, $length);
if (\strlen($s) === $length) {
$number = \danog\PHP\Struct::unpack('<'.$c, $s)[0];
//$number = ord($s);
$res[] = ['number' => $number, 'offset' => $offset, 'length' => $length];
@ -82,7 +82,7 @@ function foreach_offset_length($string)
$res = ['offset' => 0, 'files' => []];
function getfiles($token, &$params)
{
foreach (json_decode(file_get_contents('https://api.telegram.org/bot'.$token.'/getupdates?offset='.$params['offset']), true)['result'] as $update) {
foreach (\json_decode(\file_get_contents('https://api.telegram.org/bot'.$token.'/getupdates?offset='.$params['offset']), true)['result'] as $update) {
$params['offset'] = $update['update_id'] + 1;
if (isset($update['message']['audio'])) {
$params['files'][$update['message']['message_id']] = $update['message']['audio']['file_id'];
@ -100,7 +100,7 @@ function getfiles($token, &$params)
$params['files'][$update['message']['message_id']] = $update['message']['voice']['file_id'];
}
if (isset($update['message']['photo'])) {
$params['files'][$update['message']['message_id']] = end($update['message']['photo'])['file_id'];
$params['files'][$update['message']['message_id']] = \end($update['message']['photo'])['file_id'];
}
}
}
@ -108,9 +108,9 @@ function recurse($array, $prefix = '')
{
$res = [];
foreach ($array as $k => $v) {
if (is_array($v)) {
$res = array_merge(recurse($v, $prefix.$k.'->'), $res);
} elseif (is_int($v)) {
if (\is_array($v)) {
$res = \array_merge(recurse($v, $prefix.$k.'->'), $res);
} elseif (\is_int($v)) {
$res[$prefix.$k] = $v;
}
}
@ -135,17 +135,17 @@ while (true) {
$bot_api_id_b256 = base64url_decode($bot_api_id);
$bot_api_id_rledecoded = rle_decode($bot_api_id_b256);
$message .= PHP_EOL.PHP_EOL;
for ($x = 0; $x < strlen($bot_api_id_rledecoded) - 3; $x++) {
$message .= 'Bytes '.$x.'-'.($x + 4).': '.\danog\PHP\Struct::unpack('<i', substr($bot_api_id_rledecoded, $x, 4))[0].PHP_EOL;
for ($x = 0; $x < \strlen($bot_api_id_rledecoded) - 3; $x++) {
$message .= 'Bytes '.$x.'-'.($x + 4).': '.\danog\PHP\Struct::unpack('<i', \substr($bot_api_id_rledecoded, $x, 4))[0].PHP_EOL;
}
$message .= PHP_EOL.PHP_EOL.
'First 4 bytes: '.ord($bot_api_id_rledecoded[0]).' '.ord($bot_api_id_rledecoded[1]).' '.ord($bot_api_id_rledecoded[2]).' '.ord($bot_api_id_rledecoded[3]).PHP_EOL.
'First 4 bytes (single integer): '.(\danog\PHP\Struct::unpack('<i', substr($bot_api_id_rledecoded, 0, 4))[0]).PHP_EOL.
'bytes 8-16: '.(\danog\PHP\Struct::unpack('<q', substr($bot_api_id_rledecoded, 8, 8))[0]).PHP_EOL.
'bytes 16-24: '.(\danog\PHP\Struct::unpack('<q', substr($bot_api_id_rledecoded, 16, 8))[0]).PHP_EOL.
'Last byte: '.ord(substr($bot_api_id_rledecoded, -1)).PHP_EOL.
'Total length: '.strlen($bot_api_id_b256).PHP_EOL.
'Total length (rledecoded): '.strlen($bot_api_id_rledecoded).PHP_EOL.
'First 4 bytes: '.\ord($bot_api_id_rledecoded[0]).' '.\ord($bot_api_id_rledecoded[1]).' '.\ord($bot_api_id_rledecoded[2]).' '.\ord($bot_api_id_rledecoded[3]).PHP_EOL.
'First 4 bytes (single integer): '.(\danog\PHP\Struct::unpack('<i', \substr($bot_api_id_rledecoded, 0, 4))[0]).PHP_EOL.
'bytes 8-16: '.(\danog\PHP\Struct::unpack('<q', \substr($bot_api_id_rledecoded, 8, 8))[0]).PHP_EOL.
'bytes 16-24: '.(\danog\PHP\Struct::unpack('<q', \substr($bot_api_id_rledecoded, 16, 8))[0]).PHP_EOL.
'Last byte: '.\ord(\substr($bot_api_id_rledecoded, -1)).PHP_EOL.
'Total length: '.\strlen($bot_api_id_b256).PHP_EOL.
'Total length (rledecoded): '.\strlen($bot_api_id_rledecoded).PHP_EOL.
PHP_EOL.'<b>param (value): start-end (length)</b>'.PHP_EOL.PHP_EOL;
$bot_api = foreach_offset_length($bot_api_id_rledecoded);
//$mtproto = $MadelineProto->get_download_info($update['update']['message']['media'])['InputFileLocation'];
@ -177,16 +177,16 @@ while (true) {
}
}
}
ksort($m);
\ksort($m);
foreach ($m as $key => $bn) {
$message .= $bn;
}
foreach ($mtproto as $key => $n) {
$message .= $key.' ('.$n.'): not found'.PHP_EOL;
}
$message .= PHP_EOL.PHP_EOL.'File number: '.\danog\PHP\Struct::unpack('<i', substr($bot_api_id_rledecoded, 8, 4))[0];
$message .= PHP_EOL.PHP_EOL.'File number: '.\danog\PHP\Struct::unpack('<i', \substr($bot_api_id_rledecoded, 8, 4))[0];
if ($update['update']['message']['from_id'] === 101374607) {
$message = \danog\PHP\Struct::unpack('<i', substr($bot_api_id_rledecoded, 8, 4))[0];
$message = \danog\PHP\Struct::unpack('<i', \substr($bot_api_id_rledecoded, 8, 4))[0];
}
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => $message, 'reply_to_msg_id' => $update['update']['message']['id'], 'parse_mode' => 'markdown']);
}
@ -198,7 +198,7 @@ while (true) {
try {
if (isset($update['update']['message']['media']) && $update['update']['message']['media'] == 'messageMediaPhoto' && $update['update']['message']['media'] == 'messageMediaDocument') {
$time = time();
$time = \time();
// $file = $MadelineProto->download_to_dir($update['update']['message']['media'], '/tmp');
// $MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => 'Downloaded to '.$file.' in '.(time() - $time).' seconds', 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
}