Apply misc fixes
This commit is contained in:
parent
979d7575fc
commit
23e3c5b12c
2
docs
2
docs
@ -1 +1 @@
|
||||
Subproject commit eda40443bf6215bc8eff7842a5eaaae70b4c4ee3
|
||||
Subproject commit f49ae1bcb6ade347ed852d7c588c740d595b09aa
|
@ -21,10 +21,6 @@ namespace danog\MadelineProto;
|
||||
|
||||
use Amp\Promise;
|
||||
|
||||
if (!\defined('MADELINEPROTO_TEST')) {
|
||||
\define('MADELINEPROTO_TEST', 'NOT PONY');
|
||||
}
|
||||
|
||||
/**
|
||||
* Main API wrapper for MadelineProto.
|
||||
*/
|
||||
|
@ -26,7 +26,6 @@ use phpDocumentor\Reflection\DocBlockFactory;
|
||||
|
||||
class AnnotationsBuilder
|
||||
{
|
||||
use Tools;
|
||||
public function __construct(Logger $logger, array $settings, string $output, array $reflectionClasses, string $namespace)
|
||||
{
|
||||
$this->reflectionClasses = $reflectionClasses;
|
||||
@ -145,6 +144,8 @@ class AnnotationsBuilder
|
||||
}
|
||||
$class = new \ReflectionClass($this->reflectionClasses['MTProto']);
|
||||
$methods = $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC);
|
||||
$class = new \ReflectionClass(Tools::class);
|
||||
$methods = \array_merge($methods, $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC));
|
||||
foreach ($methods as $key => $method) {
|
||||
$name = $method->getName();
|
||||
if ($method == 'methodCallAsyncRead') {
|
||||
|
@ -25,7 +25,6 @@ use function Amp\Promise\all;
|
||||
class CombinedAPI
|
||||
{
|
||||
use \danog\Serializable;
|
||||
use Tools;
|
||||
public $session;
|
||||
public $instance_paths = [];
|
||||
public $instances = [];
|
||||
|
@ -44,7 +44,6 @@ use danog\MadelineProto\Stream\Transport\WsStream;
|
||||
class Connection extends Session
|
||||
{
|
||||
use \danog\Serializable;
|
||||
use Tools;
|
||||
/**
|
||||
* Writer loop.
|
||||
*
|
||||
|
@ -55,7 +55,7 @@ class ContextConnector implements Connector
|
||||
$this->logger->logger('OK!', \danog\MadelineProto\Logger::WARNING);
|
||||
return $result->getSocket();
|
||||
} catch (\Throwable $e) {
|
||||
if (\MADELINEPROTO_TEST === 'pony') {
|
||||
if (\constant("MADELINEPROTO_TEST") === 'pony') {
|
||||
throw $e;
|
||||
}
|
||||
$this->logger->logger('Connection failed: ' . $e, \danog\MadelineProto\Logger::ERROR);
|
||||
|
@ -59,7 +59,6 @@ use danog\MadelineProto\Stream\Transport\WsStream;
|
||||
*/
|
||||
class DataCenter
|
||||
{
|
||||
use \danog\MadelineProto\Tools;
|
||||
use \danog\Serializable;
|
||||
/**
|
||||
* All socket connections to DCs.
|
||||
@ -265,7 +264,7 @@ class DataCenter
|
||||
$this->API->logger->logger('OK!', \danog\MadelineProto\Logger::WARNING);
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
if (\MADELINEPROTO_TEST === 'pony') {
|
||||
if (\constant("MADELINEPROTO_TEST") === 'pony') {
|
||||
throw $e;
|
||||
}
|
||||
$this->API->logger->logger("Connection failed ({$dc_number}): ".$e->getMessage(), \danog\MadelineProto\Logger::ERROR);
|
||||
@ -489,7 +488,7 @@ class DataCenter
|
||||
if (empty($ctxs)) {
|
||||
unset($this->sockets[$dc_number]);
|
||||
$this->API->logger->logger("No info for DC {$dc_number}", \danog\MadelineProto\Logger::ERROR);
|
||||
} elseif (\MADELINEPROTO_TEST === 'pony') {
|
||||
} elseif (\constant("MADELINEPROTO_TEST") === 'pony') {
|
||||
return [$ctxs[0]];
|
||||
}
|
||||
return $ctxs;
|
||||
|
@ -26,7 +26,6 @@ class DocsBuilder
|
||||
{
|
||||
use \danog\MadelineProto\DocsBuilder\Methods;
|
||||
use \danog\MadelineProto\DocsBuilder\Constructors;
|
||||
use Tools;
|
||||
public $td = false;
|
||||
public function __construct($logger, $settings)
|
||||
{
|
||||
|
@ -22,7 +22,6 @@ namespace danog\MadelineProto;
|
||||
class Exception extends \Exception
|
||||
{
|
||||
use TL\PrettyException;
|
||||
public static $rollbar = true;
|
||||
public function __toString()
|
||||
{
|
||||
return $this->file === 'MadelineProto' ? $this->message : '\\danog\\MadelineProto\\Exception'.($this->message !== '' ? ': ' : '').$this->message.' in '.$this->file.':'.$this->line.PHP_EOL.\danog\MadelineProto\Magic::$revision.PHP_EOL.'TL Trace:'.PHP_EOL.$this->getTLTrace();
|
||||
@ -48,9 +47,6 @@ class Exception extends \Exception
|
||||
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));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Complain about missing extensions.
|
||||
|
@ -29,7 +29,6 @@ use function Amp\ByteStream\getStdout;
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
use Tools;
|
||||
const FOREGROUND = ['default' => 39, 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'light_gray' => 37, 'dark_gray' => 90, 'light_red' => 91, 'light_green' => 92, 'light_yellow' => 93, 'light_blue' => 94, 'light_magenta' => 95, 'light_cyan' => 96, 'white' => 97];
|
||||
const BACKGROUND = ['default' => 49, 'black' => 40, 'red' => 41, 'magenta' => 45, 'yellow' => 43, 'green' => 42, 'blue' => 44, 'cyan' => 46, 'light_gray' => 47, 'dark_gray' => 100, 'light_red' => 101, 'light_green' => 102, 'light_yellow' => 103, 'light_blue' => 104, 'light_magenta' => 105, 'light_cyan' => 106, 'white' => 107];
|
||||
const SET = ['bold' => 1, 'dim' => 2, 'underlined' => 3, 'blink' => 4, 'reverse' => 5, 'hidden' => 6];
|
||||
@ -123,12 +122,6 @@ 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::class)) {
|
||||
@\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;
|
||||
}
|
||||
if (!isset($settings['logger']['logger_param']) && isset($settings['logger']['param'])) {
|
||||
$settings['logger']['logger_param'] = $settings['logger']['param'];
|
||||
}
|
||||
@ -264,9 +257,6 @@ class Logger
|
||||
return;
|
||||
}
|
||||
$prefix = $this->prefix;
|
||||
if (\danog\MadelineProto\Magic::$has_thread && \is_object(\Thread::getCurrentThread())) {
|
||||
$prefix .= ' (t)';
|
||||
}
|
||||
if ($param instanceof \Throwable) {
|
||||
$param = (string) $param;
|
||||
} elseif (!\is_string($param)) {
|
||||
|
@ -26,7 +26,6 @@ use Amp\Websocket\ClosedException;
|
||||
use danog\MadelineProto\Connection;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\Impl\SignalLoop;
|
||||
use danog\MadelineProto\MTProtoTools\Crypt;
|
||||
use danog\MadelineProto\NothingInTheSocketException;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
@ -37,8 +36,6 @@ use danog\MadelineProto\Tools;
|
||||
*/
|
||||
class ReadLoop extends SignalLoop
|
||||
{
|
||||
use Tools;
|
||||
use Crypt;
|
||||
/**
|
||||
* Connection instance.
|
||||
*
|
||||
@ -140,14 +137,14 @@ class ReadLoop extends SignalLoop
|
||||
$API->logger->logger($e->getReason());
|
||||
if (\strpos($e->getReason(), ' ') === 0) {
|
||||
$payload = -\substr($e->getReason(), 7);
|
||||
$API->logger->logger("Received {$payload} from DC " . $datacenter, \danog\MadelineProto\Logger::ERROR);
|
||||
$API->logger->logger("Received {$payload} from DC ".$datacenter, \danog\MadelineProto\Logger::ERROR);
|
||||
return $payload;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
if ($payload_length === 4) {
|
||||
$payload = \danog\MadelineProto\Tools::unpackSignedInt(yield $buffer->bufferRead(4));
|
||||
$API->logger->logger("Received {$payload} from DC " . $datacenter, \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
$API->logger->logger("Received {$payload} from DC ".$datacenter, \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
return $payload;
|
||||
}
|
||||
$connection->reading(true);
|
||||
@ -210,7 +207,7 @@ class ReadLoop extends SignalLoop
|
||||
throw new \danog\MadelineProto\SecurityException('message_data_length not divisible by 4');
|
||||
}
|
||||
$message_data = \substr($decrypted_data, 32, $message_data_length);
|
||||
if ($message_key != \substr(\hash('sha256', \substr($shared->getTempAuthKey()->getAuthKey(), 96, 32) . $decrypted_data, true), 8, 16)) {
|
||||
if ($message_key != \substr(\hash('sha256', \substr($shared->getTempAuthKey()->getAuthKey(), 96, 32).$decrypted_data, true), 8, 16)) {
|
||||
throw new \danog\MadelineProto\SecurityException('msg_key mismatch');
|
||||
}
|
||||
$connection->incoming_messages[$message_id] = ['seq_no' => $seq_no];
|
||||
@ -224,7 +221,7 @@ class ReadLoop extends SignalLoop
|
||||
$connection->incoming_messages[$message_id]['response'] = -1;
|
||||
$connection->new_incoming[$message_id] = $message_id;
|
||||
//$connection->last_http_wait = 0;
|
||||
$API->logger->logger('Received payload from DC ' . $datacenter, \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
$API->logger->logger('Received payload from DC '.$datacenter, \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
} finally {
|
||||
$connection->reading(false);
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ use Amp\ByteStream\StreamException;
|
||||
use danog\MadelineProto\Connection;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
use danog\MadelineProto\MTProtoTools\Crypt;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
@ -33,8 +32,6 @@ use danog\MadelineProto\Tools;
|
||||
*/
|
||||
class WriteLoop extends ResumableSignalLoop
|
||||
{
|
||||
use Crypt;
|
||||
use Tools;
|
||||
/**
|
||||
* Connection instance.
|
||||
*
|
||||
@ -128,7 +125,7 @@ class WriteLoop extends ResumableSignalLoop
|
||||
$pad_length += 16 * \danog\MadelineProto\Tools::randomInt($modulus = 16);
|
||||
$pad = \danog\MadelineProto\Tools::random($pad_length);
|
||||
$buffer = yield $connection->stream->getWriteBuffer(8 + 8 + 4 + $pad_length + $length);
|
||||
yield $buffer->bufferWrite("\0\0\0\0\0\0\0\0" . $message_id . \danog\MadelineProto\Tools::packUnsignedInt($length) . $message['serialized_body'] . $pad);
|
||||
yield $buffer->bufferWrite("\0\0\0\0\0\0\0\0".$message_id.\danog\MadelineProto\Tools::packUnsignedInt($length).$message['serialized_body'].$pad);
|
||||
//var_dump("plain ".bin2hex($message_id));
|
||||
$connection->httpSent();
|
||||
$connection->outgoing_messages[$message_id] = $message;
|
||||
@ -280,15 +277,15 @@ class WriteLoop extends ResumableSignalLoop
|
||||
return true;
|
||||
}
|
||||
unset($messages);
|
||||
$plaintext = $shared->getTempAuthKey()->getServerSalt() . $connection->session_id . $message_id . \pack('VV', $seq_no, $message_data_length) . $message_data;
|
||||
$plaintext = $shared->getTempAuthKey()->getServerSalt().$connection->session_id.$message_id.\pack('VV', $seq_no, $message_data_length).$message_data;
|
||||
$padding = \danog\MadelineProto\Tools::posmod(-\strlen($plaintext), 16);
|
||||
if ($padding < 12) {
|
||||
$padding += 16;
|
||||
}
|
||||
$padding = \danog\MadelineProto\Tools::random($padding);
|
||||
$message_key = \substr(\hash('sha256', \substr($shared->getTempAuthKey()->getAuthKey(), 88, 32) . $plaintext . $padding, true), 8, 16);
|
||||
$message_key = \substr(\hash('sha256', \substr($shared->getTempAuthKey()->getAuthKey(), 88, 32).$plaintext.$padding, true), 8, 16);
|
||||
list($aes_key, $aes_iv) = $this->aesCalculate($message_key, $shared->getTempAuthKey()->getAuthKey());
|
||||
$message = $shared->getTempAuthKey()->getID() . $message_key . $this->igeEncrypt($plaintext . $padding, $aes_key, $aes_iv);
|
||||
$message = $shared->getTempAuthKey()->getID().$message_key.$this->igeEncrypt($plaintext.$padding, $aes_key, $aes_iv);
|
||||
$buffer = yield $connection->stream->getWriteBuffer($len = \strlen($message));
|
||||
//$t = \microtime(true);
|
||||
yield $buffer->bufferWrite($message);
|
||||
|
@ -32,7 +32,6 @@ use danog\MadelineProto\Loop\LoopInterface;
|
||||
*/
|
||||
abstract class Loop implements LoopInterface
|
||||
{
|
||||
use \danog\MadelineProto\Tools;
|
||||
private $count = 0;
|
||||
/**
|
||||
* MTProto instance.
|
||||
|
@ -24,7 +24,6 @@ use Amp\Loop;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
use danog\MadelineProto\Loop\ResumableLoopInterface;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
* Resumable signal loop helper trait.
|
||||
@ -33,7 +32,6 @@ use danog\MadelineProto\Tools;
|
||||
*/
|
||||
abstract class ResumableSignalLoop extends SignalLoop implements ResumableLoopInterface
|
||||
{
|
||||
use Tools;
|
||||
private $resume;
|
||||
private $pause;
|
||||
protected $resumeWatcher;
|
||||
|
@ -29,7 +29,6 @@ use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
*/
|
||||
class FeedLoop extends ResumableSignalLoop
|
||||
{
|
||||
use \danog\MadelineProto\Tools;
|
||||
private $incomingUpdates = [];
|
||||
private $parsedUpdates = [];
|
||||
private $channelId;
|
||||
|
@ -28,7 +28,6 @@ use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
*/
|
||||
class SeqLoop extends ResumableSignalLoop
|
||||
{
|
||||
use \danog\MadelineProto\Tools;
|
||||
private $incomingUpdates = [];
|
||||
private $feeder;
|
||||
private $pendingWakeups = [];
|
||||
|
@ -31,7 +31,6 @@ use danog\MadelineProto\RPCErrorException;
|
||||
*/
|
||||
class UpdateLoop extends ResumableSignalLoop
|
||||
{
|
||||
use \danog\MadelineProto\Tools;
|
||||
private $toPts;
|
||||
private $channelId;
|
||||
private $feeder;
|
||||
|
@ -42,6 +42,9 @@ class Lua
|
||||
}
|
||||
public function __wakeup()
|
||||
{
|
||||
if (!\class_exists(\Lua::class)) {
|
||||
throw Exception::extension('lua');
|
||||
}
|
||||
$this->Lua = new \Lua($this->script);
|
||||
$this->madelineproto_lua = 1;
|
||||
$this->Lua->registerCallback('tdcliFunction', [$this, 'tdcliFunction']);
|
||||
|
@ -46,7 +46,6 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
use \danog\Serializable;
|
||||
use \danog\MadelineProto\MTProtoTools\AuthKeyHandler;
|
||||
use \danog\MadelineProto\MTProtoTools\CallHandler;
|
||||
use \danog\MadelineProto\MTProtoTools\Crypt;
|
||||
use \danog\MadelineProto\MTProtoTools\PeerHandler;
|
||||
use \danog\MadelineProto\MTProtoTools\UpdateHandler;
|
||||
use \danog\MadelineProto\MTProtoTools\Files;
|
||||
@ -58,7 +57,6 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
use \danog\MadelineProto\TL\Conversion\BotAPIFiles;
|
||||
use \danog\MadelineProto\TL\Conversion\Extension;
|
||||
use \danog\MadelineProto\TL\Conversion\TD;
|
||||
use \danog\MadelineProto\Tools;
|
||||
use \danog\MadelineProto\VoIP\AuthKeyHandler;
|
||||
use \danog\MadelineProto\Wrappers\DialogHandler;
|
||||
use \danog\MadelineProto\Wrappers\Events;
|
||||
@ -858,10 +856,6 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
Magic::classExists();
|
||||
// Setup logger
|
||||
$this->setupLogger();
|
||||
// We don't like threads
|
||||
if (Magic::$has_thread && \is_object(\Thread::getCurrentThread())) {
|
||||
return;
|
||||
}
|
||||
// Setup language
|
||||
Lang::$current_lang =& Lang::$lang['en'];
|
||||
if (Lang::$lang[$this->settings['app_info']['lang_code'] ?? 'en'] ?? false) {
|
||||
@ -1218,7 +1212,6 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
'logger_level' => Logger::VERBOSE,
|
||||
'max_size' => 100 * 1024 * 1024,
|
||||
// Logging level, available logging levels are: ULTRA_VERBOSE, VERBOSE, NOTICE, WARNING, ERROR, FATAL_ERROR. Can be provided as last parameter to the logging function.
|
||||
'rollbar_token' => '',
|
||||
], 'max_tries' => [
|
||||
'query' => 5,
|
||||
// How many times should I try to call a method or send an object before throwing an exception
|
||||
|
@ -50,13 +50,12 @@ trait CallHandler
|
||||
foreach ($message_ids as $message_id) {
|
||||
if (isset($this->outgoing_messages[$message_id]['body'])) {
|
||||
if ($datacenter) {
|
||||
$res = Tools::call($this->API->datacenter->waitGetConnection($datacenter))->onResolve(function ($e, $r) use ($message_id) {
|
||||
return $r->sendMessage($this->outgoing_messages[$message_id], false);
|
||||
Tools::call($this->API->datacenter->waitGetConnection($datacenter))->onResolve(function ($e, $r) use ($message_id) {
|
||||
Tools::callFork($r->sendMessage($this->outgoing_messages[$message_id], false));
|
||||
});
|
||||
} else {
|
||||
$res = $this->sendMessage($this->outgoing_messages[$message_id], false);
|
||||
Tools::callFork($this->sendMessage($this->outgoing_messages[$message_id], false));
|
||||
}
|
||||
\danog\MadelineProto\Tools::callFork($res);
|
||||
$this->ackOutgoingMessageId($message_id);
|
||||
$this->gotResponseForOutgoingMessageId($message_id);
|
||||
} else {
|
||||
|
@ -20,6 +20,7 @@
|
||||
namespace danog\MadelineProto\MTProtoSession\MsgIdHandler;
|
||||
|
||||
use danog\MadelineProto\MTProtoSession\MsgIdHandler;
|
||||
use tgseclib\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Manages message ids.
|
||||
@ -48,13 +49,13 @@ class MsgIdHandler32 extends MsgIdHandler
|
||||
*/
|
||||
public function checkMessageId($newMessageId, array $aargs): void
|
||||
{
|
||||
$newMessageId = \is_object($newMessageId) ? $newMessageId : new \tgseclib\Math\BigInteger(\strrev($newMessageId), 256);
|
||||
$newMessageId = \is_object($newMessageId) ? $newMessageId : new BigInteger(\strrev($newMessageId), 256);
|
||||
|
||||
$minMessageId = (new \tgseclib\Math\BigInteger(\time() + $this->session->time_delta - 300))->bitwise_leftShift(32);
|
||||
$minMessageId = (new BigInteger(\time() + $this->session->time_delta - 300))->bitwise_leftShift(32);
|
||||
if ($minMessageId->compare($newMessageId) > 0) {
|
||||
$this->session->API->logger->logger('Given message id ('.$newMessageId.') is too old compared to the min value ('.$minMessageId.').', \danog\MadelineProto\Logger::WARNING);
|
||||
}
|
||||
$maxMessageId = (new \tgseclib\Math\BigInteger(\time() + $this->session->time_delta + 30))->bitwise_leftShift(32);
|
||||
$maxMessageId = (new BigInteger(\time() + $this->session->time_delta + 30))->bitwise_leftShift(32);
|
||||
if ($maxMessageId->compare($newMessageId) < 0) {
|
||||
throw new \danog\MadelineProto\Exception('Given message id ('.$newMessageId.') is too new compared to the max value ('.$maxMessageId.'). Consider syncing your date.');
|
||||
}
|
||||
@ -106,7 +107,7 @@ class MsgIdHandler32 extends MsgIdHandler
|
||||
*/
|
||||
public function generateMessageId(): string
|
||||
{
|
||||
$message_id = (new \tgseclib\Math\BigInteger(\time() + $this->session->time_delta))->bitwise_leftShift(32);
|
||||
$message_id = (new BigInteger(\time() + $this->session->time_delta))->bitwise_leftShift(32);
|
||||
if ($message_id->compare($key = $this->getMaxId($incoming = false)) <= 0) {
|
||||
$message_id = $key->add(\danog\MadelineProto\Magic::$four);
|
||||
}
|
||||
|
@ -42,8 +42,6 @@ trait SeqNoHandler
|
||||
$type = isset($this->incoming_messages[$current_msg_id]['content']['_']) ? $this->incoming_messages[$current_msg_id]['content']['_'] : '-';
|
||||
if (isset($this->incoming_messages[$current_msg_id]['seq_no']) && ($seq_no = $this->generateInSeqNo($this->contentRelated($this->incoming_messages[$current_msg_id]['content']))) !== $this->incoming_messages[$current_msg_id]['seq_no']) {
|
||||
$this->API->logger->logger('SECURITY WARNING: Seqno mismatch (should be ' . $seq_no . ', is ' . $this->incoming_messages[$current_msg_id]['seq_no'] . ', ' . $type . ')', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
} elseif (isset($seq_no)) {
|
||||
$this->API->logger->logger('Seqno OK (should be ' . $seq_no . ', is ' . $this->incoming_messages[$current_msg_id]['seq_no'] . ', ' . $type . ')', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
}
|
||||
}
|
||||
public function generateInSeqNo($contentRelated)
|
||||
|
@ -28,14 +28,59 @@ abstract class Session
|
||||
use ResponseHandler;
|
||||
use SeqNoHandler;
|
||||
use CallHandler;
|
||||
/**
|
||||
* Incoming message array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $incoming_messages = [];
|
||||
/**
|
||||
* Outgoing message array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $outgoing_messages = [];
|
||||
/**
|
||||
* New incoming message ID array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $new_incoming = [];
|
||||
/**
|
||||
* New outgoing message ID array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $new_outgoing = [];
|
||||
/**
|
||||
* Pending outgoing messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $pending_outgoing = [];
|
||||
/**
|
||||
* Pending outgoing key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $pending_outgoing_key = 'a';
|
||||
/**
|
||||
* Time delta with server.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $time_delta = 0;
|
||||
/**
|
||||
* Call queue.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $call_queue = [];
|
||||
/**
|
||||
* Ack queue.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $ack_queue = [];
|
||||
/**
|
||||
* Message ID handler.
|
||||
|
@ -21,9 +21,11 @@ namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use Amp\Http\Client\Request;
|
||||
use danog\MadelineProto\DataCenterConnection;
|
||||
use danog\MadelineProto\MTProto;
|
||||
use danog\MadelineProto\MTProto\AuthKey;
|
||||
use danog\MadelineProto\MTProto\PermAuthKey;
|
||||
use danog\MadelineProto\MTProto\TempAuthKey;
|
||||
use danog\PrimeModule;
|
||||
use tgseclib\Math\BigInteger;
|
||||
|
||||
/**
|
||||
@ -108,69 +110,41 @@ trait AuthKeyHandler
|
||||
* ***********************************************************************
|
||||
* Compute p and q
|
||||
*/
|
||||
$pq = new \tgseclib\Math\BigInteger((string) $pq_bytes, 256);
|
||||
$q = new \tgseclib\Math\BigInteger(0);
|
||||
$p = new \tgseclib\Math\BigInteger(@\danog\PrimeModule::auto_single($pq->__toString()));
|
||||
$pq = (string) new BigInteger((string) $pq_bytes, 256);
|
||||
foreach ([
|
||||
'auto_single',
|
||||
'native_single_cpp',
|
||||
'python_single_alt',
|
||||
'python_single',
|
||||
'native_single',
|
||||
'wolfram'
|
||||
] as $method) {
|
||||
$this->logger->logger("Factorizing with $method");
|
||||
|
||||
$q = new BigInteger(0);
|
||||
try {
|
||||
if ($method === 'wolfram') {
|
||||
$p = new BigInteger(yield from $this->wolframSingle($pq));
|
||||
} else {
|
||||
$p = new BigInteger(@PrimeModule::$method($pq));
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logger("While factorizing with $method: $e");
|
||||
}
|
||||
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
|
||||
$q = $pq->divide($p)[0];
|
||||
if ($p->compare($q) > 0) {
|
||||
list($p, $q) = [$q, $p];
|
||||
}
|
||||
}
|
||||
if (!$pq->equals($p->multiply($q))) {
|
||||
$this->logger->logger('Automatic factorization failed, trying native CPP module', \danog\MadelineProto\Logger::ERROR);
|
||||
$p = new \tgseclib\Math\BigInteger(@\danog\PrimeModule::native_single_cpp($pq->__toString()));
|
||||
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
|
||||
$q = $pq->divide($p)[0];
|
||||
if ($p->compare($q) > 0) {
|
||||
list($p, $q) = [$q, $p];
|
||||
if ($pq->equals($p->multiply($q))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$pq->equals($p->multiply($q))) {
|
||||
$this->logger->logger('Automatic factorization failed, trying alt py module', \danog\MadelineProto\Logger::ERROR);
|
||||
$p = new \tgseclib\Math\BigInteger(@\danog\PrimeModule::python_single_alt($pq->__toString()));
|
||||
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
|
||||
$q = $pq->divide($p)[0];
|
||||
if ($p->compare($q) > 0) {
|
||||
list($p, $q) = [$q, $p];
|
||||
throw new \danog\MadelineProto\SecurityException("Couldn't compute p and q, install prime.madelineproto.xyz to fix. Original pq: {$pq}, computed p: {$p}, computed q: {$q}, computed pq: ".$p->multiply($q));
|
||||
}
|
||||
}
|
||||
if (!$pq->equals($p->multiply($q))) {
|
||||
$this->logger->logger('Automatic factorization failed, trying py module', \danog\MadelineProto\Logger::ERROR);
|
||||
$p = new \tgseclib\Math\BigInteger(@\danog\PrimeModule::python_single($pq->__toString()));
|
||||
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
|
||||
$q = $pq->divide($p)[0];
|
||||
if ($p->compare($q) > 0) {
|
||||
list($p, $q) = [$q, $p];
|
||||
}
|
||||
}
|
||||
if (!$pq->equals($p->multiply($q))) {
|
||||
$this->logger->logger('Automatic factorization failed, trying native module', \danog\MadelineProto\Logger::ERROR);
|
||||
$p = new \tgseclib\Math\BigInteger(@\danog\PrimeModule::native_single($pq->__toString()));
|
||||
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
|
||||
$q = $pq->divide($p)[0];
|
||||
if ($p->compare($q) > 0) {
|
||||
list($p, $q) = [$q, $p];
|
||||
}
|
||||
}
|
||||
if (!$pq->equals($p->multiply($q))) {
|
||||
$this->logger->logger('Automatic factorization failed, trying wolfram module', \danog\MadelineProto\Logger::ERROR);
|
||||
$p = new \tgseclib\Math\BigInteger(yield from $this->wolframSingle($pq->__toString()));
|
||||
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
|
||||
$q = $pq->divide($p)[0];
|
||||
if ($p->compare($q) > 0) {
|
||||
list($p, $q) = [$q, $p];
|
||||
}
|
||||
}
|
||||
if (!$pq->equals($p->multiply($q))) {
|
||||
throw new \danog\MadelineProto\SecurityException("Couldn't compute p and q, install prime.madelineproto.xyz to fix. Original pq: {$pq}, computed p: {$p}, computed q: {$q}, computed pq: " . $p->multiply($q));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->logger->logger('Factorization ' . $pq . ' = ' . $p . ' * ' . $q, \danog\MadelineProto\Logger::VERBOSE);
|
||||
$this->logger->logger('Factorization '.$pq.' = '.$p.' * '.$q, \danog\MadelineProto\Logger::VERBOSE);
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Serialize object for req_DH_params
|
||||
@ -178,7 +152,7 @@ trait AuthKeyHandler
|
||||
$p_bytes = $p->toBytes();
|
||||
$q_bytes = $q->toBytes();
|
||||
$new_nonce = \danog\MadelineProto\Tools::random(32);
|
||||
$data_unserialized = ['_' => 'p_q_inner_data' . ($expires_in < 0 ? '' : '_temp'), 'pq' => $pq_bytes, 'p' => $p_bytes, 'q' => $q_bytes, 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'new_nonce' => $new_nonce, 'expires_in' => $expires_in, 'dc' => \preg_replace('|_.*|', '', $datacenter)];
|
||||
$data_unserialized = ['_' => 'p_q_inner_data'.($expires_in < 0 ? '' : '_temp'), 'pq' => $pq_bytes, 'p' => $p_bytes, 'q' => $q_bytes, 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'new_nonce' => $new_nonce, 'expires_in' => $expires_in, 'dc' => \preg_replace('|_.*|', '', $datacenter)];
|
||||
$p_q_inner_data = (yield from $this->TL->serializeObject(['type' => ''], $data_unserialized, 'p_q_inner_data'));
|
||||
/*
|
||||
* ***********************************************************************
|
||||
@ -186,7 +160,7 @@ trait AuthKeyHandler
|
||||
*/
|
||||
$sha_digest = \sha1($p_q_inner_data, true);
|
||||
$random_bytes = \danog\MadelineProto\Tools::random(255 - \strlen($p_q_inner_data) - \strlen($sha_digest));
|
||||
$to_encrypt = $sha_digest . $p_q_inner_data . $random_bytes;
|
||||
$to_encrypt = $sha_digest.$p_q_inner_data.$random_bytes;
|
||||
$encrypted_data = $key->encrypt($to_encrypt);
|
||||
$this->logger->logger('Starting Diffie Hellman key exchange', \danog\MadelineProto\Logger::VERBOSE);
|
||||
/*
|
||||
@ -237,8 +211,8 @@ trait AuthKeyHandler
|
||||
* Get key, iv and decrypt answer
|
||||
*/
|
||||
$encrypted_answer = $server_dh_params['encrypted_answer'];
|
||||
$tmp_aes_key = \sha1($new_nonce . $server_nonce, true) . \substr(\sha1($server_nonce . $new_nonce, true), 0, 12);
|
||||
$tmp_aes_iv = \substr(\sha1($server_nonce . $new_nonce, true), 12, 8) . \sha1($new_nonce . $new_nonce, true) . \substr($new_nonce, 0, 4);
|
||||
$tmp_aes_key = \sha1($new_nonce.$server_nonce, true).\substr(\sha1($server_nonce.$new_nonce, true), 0, 12);
|
||||
$tmp_aes_iv = \substr(\sha1($server_nonce.$new_nonce, true), 12, 8).\sha1($new_nonce.$new_nonce, true).\substr($new_nonce, 0, 4);
|
||||
$answer_with_hash = $this->igeDecrypt($encrypted_answer, $tmp_aes_key, $tmp_aes_iv);
|
||||
/*
|
||||
* ***********************************************************************
|
||||
@ -273,9 +247,9 @@ trait AuthKeyHandler
|
||||
if ($server_nonce != $server_DH_inner_data['server_nonce']) {
|
||||
throw new \danog\MadelineProto\SecurityException('wrong server nonce');
|
||||
}
|
||||
$g = new \tgseclib\Math\BigInteger($server_DH_inner_data['g']);
|
||||
$g_a = new \tgseclib\Math\BigInteger((string) $server_DH_inner_data['g_a'], 256);
|
||||
$dh_prime = new \tgseclib\Math\BigInteger((string) $server_DH_inner_data['dh_prime'], 256);
|
||||
$g = new BigInteger($server_DH_inner_data['g']);
|
||||
$g_a = new BigInteger((string) $server_DH_inner_data['g_a'], 256);
|
||||
$dh_prime = new BigInteger((string) $server_DH_inner_data['dh_prime'], 256);
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Time delta
|
||||
@ -287,7 +261,7 @@ trait AuthKeyHandler
|
||||
$this->checkG($g_a, $dh_prime);
|
||||
for ($retry_id = 0; $retry_id <= $this->settings['max_tries']['authorization']; $retry_id++) {
|
||||
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = new \tgseclib\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||
$b = new BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||
$this->logger->logger('Generating g_b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$g_b = $g->powMod($b, $dh_prime);
|
||||
$this->checkG($g_b, $dh_prime);
|
||||
@ -318,8 +292,8 @@ trait AuthKeyHandler
|
||||
* ***********************************************************************
|
||||
* encrypt client_DH_inner_data
|
||||
*/
|
||||
$data_with_sha = \sha1($data, true) . $data;
|
||||
$data_with_sha_padded = $data_with_sha . \danog\MadelineProto\Tools::random(\danog\MadelineProto\Tools::posmod(-\strlen($data_with_sha), 16));
|
||||
$data_with_sha = \sha1($data, true).$data;
|
||||
$data_with_sha_padded = $data_with_sha.\danog\MadelineProto\Tools::random(\danog\MadelineProto\Tools::posmod(-\strlen($data_with_sha), 16));
|
||||
$encrypted_data = $this->igeEncrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
|
||||
$this->logger->logger('Executing set_client_DH_params...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
/*
|
||||
@ -349,9 +323,9 @@ trait AuthKeyHandler
|
||||
$auth_key_str = $auth_key->toBytes();
|
||||
$auth_key_sha = \sha1($auth_key_str, true);
|
||||
$auth_key_aux_hash = \substr($auth_key_sha, 0, 8);
|
||||
$new_nonce_hash1 = \substr(\sha1($new_nonce . \chr(1) . $auth_key_aux_hash, true), -16);
|
||||
$new_nonce_hash2 = \substr(\sha1($new_nonce . \chr(2) . $auth_key_aux_hash, true), -16);
|
||||
$new_nonce_hash3 = \substr(\sha1($new_nonce . \chr(3) . $auth_key_aux_hash, true), -16);
|
||||
$new_nonce_hash1 = \substr(\sha1($new_nonce.\chr(1).$auth_key_aux_hash, true), -16);
|
||||
$new_nonce_hash2 = \substr(\sha1($new_nonce.\chr(2).$auth_key_aux_hash, true), -16);
|
||||
$new_nonce_hash3 = \substr(\sha1($new_nonce.\chr(3).$auth_key_aux_hash, true), -16);
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check if the client's nonce and the server's nonce are the same
|
||||
@ -403,14 +377,14 @@ trait AuthKeyHandler
|
||||
}
|
||||
}
|
||||
} catch (\danog\MadelineProto\SecurityException $e) {
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: ' . $e->getMessage() . ' in ' . \basename($e->getFile(), '.php') . ' on line ' . $e->getLine() . '. Retrying...', \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: '.$e->getMessage().' in '.\basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...', \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: ' . $e->getMessage() . ' in ' . \basename($e->getFile(), '.php') . ' on line ' . $e->getLine() . '. Retrying...', \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: '.$e->getMessage().' in '.\basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...', \danog\MadelineProto\Logger::WARNING);
|
||||
$req_pq = $req_pq === 'req_pq_multi' ? 'req_pq' : 'req_pq_multi';
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger('An RPCErrorException occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('An RPCErrorException occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: ' . $e . PHP_EOL . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: '.$e.PHP_EOL.' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
|
||||
}
|
||||
}
|
||||
if (!$cdn) {
|
||||
@ -512,8 +486,8 @@ trait AuthKeyHandler
|
||||
$this->logger->logger('DH configuration not modified', \danog\MadelineProto\Logger::VERBOSE);
|
||||
return $this->dh_config;
|
||||
}
|
||||
$dh_config['p'] = new \tgseclib\Math\BigInteger((string) $dh_config['p'], 256);
|
||||
$dh_config['g'] = new \tgseclib\Math\BigInteger($dh_config['g']);
|
||||
$dh_config['p'] = new BigInteger((string) $dh_config['p'], 256);
|
||||
$dh_config['g'] = new BigInteger($dh_config['g']);
|
||||
$this->checkPG($dh_config['p'], $dh_config['g']);
|
||||
return $this->dh_config = $dh_config;
|
||||
}
|
||||
@ -542,24 +516,24 @@ trait AuthKeyHandler
|
||||
$message_data = (yield from $this->TL->serializeObject(['type' => ''], ['_' => 'bind_auth_key_inner', 'nonce' => $nonce, 'temp_auth_key_id' => $temp_auth_key_id, 'perm_auth_key_id' => $perm_auth_key_id, 'temp_session_id' => $temp_session_id, 'expires_at' => $expires_at], 'bindTempAuthKey_inner'));
|
||||
$message_id = $connection->msgIdHandler->generateMessageId();
|
||||
$seq_no = 0;
|
||||
$encrypted_data = \danog\MadelineProto\Tools::random(16) . $message_id . \pack('VV', $seq_no, \strlen($message_data)) . $message_data;
|
||||
$encrypted_data = \danog\MadelineProto\Tools::random(16).$message_id.\pack('VV', $seq_no, \strlen($message_data)).$message_data;
|
||||
$message_key = \substr(\sha1($encrypted_data, true), -16);
|
||||
$padding = \danog\MadelineProto\Tools::random(\danog\MadelineProto\Tools::posmod(-\strlen($encrypted_data), 16));
|
||||
list($aes_key, $aes_iv) = $this->oldAesCalculate($message_key, $datacenterConnection->getPermAuthKey()->getAuthKey());
|
||||
$encrypted_message = $datacenterConnection->getPermAuthKey()->getID() . $message_key . $this->igeEncrypt($encrypted_data . $padding, $aes_key, $aes_iv);
|
||||
$encrypted_message = $datacenterConnection->getPermAuthKey()->getID().$message_key.$this->igeEncrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
||||
$res = yield from $connection->methodCallAsyncRead('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], ['msg_id' => $message_id]);
|
||||
if ($res === true) {
|
||||
$this->logger->logger('Bound temporary and permanent authorization keys, DC ' . $datacenter, \danog\MadelineProto\Logger::NOTICE);
|
||||
$this->logger->logger('Bound temporary and permanent authorization keys, DC '.$datacenter, \danog\MadelineProto\Logger::NOTICE);
|
||||
$datacenterConnection->bind();
|
||||
$datacenterConnection->flush();
|
||||
return true;
|
||||
}
|
||||
} catch (\danog\MadelineProto\SecurityException $e) {
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger('An RPCErrorException occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('An RPCErrorException occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
|
||||
}
|
||||
}
|
||||
throw new \danog\MadelineProto\SecurityException('An error occurred while binding temporary and permanent authorization keys.');
|
||||
@ -574,11 +548,11 @@ trait AuthKeyHandler
|
||||
private function wolframSingle($what): \Generator
|
||||
{
|
||||
$code = (yield from $this->datacenter->fileGetContents('http://www.wolframalpha.com/api/v1/code'));
|
||||
$query = 'Do prime factorization of ' . $what;
|
||||
$query = 'Do prime factorization of '.$what;
|
||||
$params = ['async' => true, 'banners' => 'raw', 'debuggingdata' => false, 'format' => 'moutput', 'formattimeout' => 8, 'input' => $query, 'output' => 'JSON', 'proxycode' => \json_decode($code, true)['code']];
|
||||
$url = 'https://www.wolframalpha.com/input/json.jsp?' . \http_build_query($params);
|
||||
$url = 'https://www.wolframalpha.com/input/json.jsp?'.\http_build_query($params);
|
||||
$request = new Request($url);
|
||||
$request->setHeader('referer', 'https://www.wolframalpha.com/input/?i=' . \urlencode($query));
|
||||
$request->setHeader('referer', 'https://www.wolframalpha.com/input/?i='.\urlencode($query));
|
||||
$res = \json_decode(yield (yield $this->datacenter->getHTTPClient()->request($request))->getBody()->buffer(), true);
|
||||
if (!isset($res['queryresult']['pods'])) {
|
||||
return false;
|
||||
@ -737,22 +711,22 @@ trait AuthKeyHandler
|
||||
return false;
|
||||
}
|
||||
$socket = $this->datacenter->getDataCenterConnection($id);
|
||||
if ($this->authorized === self::LOGGED_IN && !$socket->isAuthorized()) {
|
||||
if ($this->authorized === MTProto::LOGGED_IN && !$socket->isAuthorized()) {
|
||||
foreach ($this->datacenter->getDataCenterConnections() as $authorized_dc_id => $authorized_socket) {
|
||||
if ($this->authorized_dc !== -1 && $authorized_dc_id !== $this->authorized_dc) {
|
||||
continue;
|
||||
}
|
||||
if ($authorized_socket->hasTempAuthKey() && $authorized_socket->hasPermAuthKey() && $authorized_socket->isAuthorized() && $this->authorized === self::LOGGED_IN && !$socket->isAuthorized() && !$authorized_socket->isCDN()) {
|
||||
if ($authorized_socket->hasTempAuthKey() && $authorized_socket->hasPermAuthKey() && $authorized_socket->isAuthorized() && $this->authorized === MTProto::LOGGED_IN && !$socket->isAuthorized() && !$authorized_socket->isCDN()) {
|
||||
try {
|
||||
$this->logger->logger('Trying to copy authorization from dc ' . $authorized_dc_id . ' to dc ' . $id);
|
||||
$this->logger->logger('Trying to copy authorization from dc '.$authorized_dc_id.' to dc '.$id);
|
||||
$exported_authorization = yield from $this->methodCallAsyncRead('auth.exportAuthorization', ['dc_id' => \preg_replace('|_.*|', '', $id)], ['datacenter' => $authorized_dc_id]);
|
||||
$authorization = yield from $this->methodCallAsyncRead('auth.importAuthorization', $exported_authorization, ['datacenter' => $id]);
|
||||
$socket->authorized(true);
|
||||
break;
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$this->logger->logger('Failure while syncing authorization from DC ' . $authorized_dc_id . ' to DC ' . $id . ': ' . $e->getMessage(), \danog\MadelineProto\Logger::ERROR);
|
||||
$this->logger->logger('Failure while syncing authorization from DC '.$authorized_dc_id.' to DC '.$id.': '.$e->getMessage(), \danog\MadelineProto\Logger::ERROR);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger('Failure while syncing authorization from DC ' . $authorized_dc_id . ' to DC ' . $id . ': ' . $e->getMessage(), \danog\MadelineProto\Logger::ERROR);
|
||||
$this->logger->logger('Failure while syncing authorization from DC '.$authorized_dc_id.' to DC '.$id.': '.$e->getMessage(), \danog\MadelineProto\Logger::ERROR);
|
||||
if ($e->rpc === 'DC_ID_INVALID') {
|
||||
break;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
trait Crypt
|
||||
abstract class Crypt
|
||||
{
|
||||
/**
|
||||
* AES KDF function for MTProto v2.
|
||||
@ -35,10 +35,10 @@ trait Crypt
|
||||
public static function aesCalculate(string $msg_key, string $auth_key, bool $to_server = true): array
|
||||
{
|
||||
$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];
|
||||
}
|
||||
/**
|
||||
@ -55,12 +55,12 @@ trait Crypt
|
||||
public static function oldAesCalculate(string $msg_key, string $auth_key, bool $to_server = true): array
|
||||
{
|
||||
$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];
|
||||
}
|
||||
/**
|
||||
|
@ -44,6 +44,7 @@ use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\Transport\PremadeStream;
|
||||
use danog\MadelineProto\Tools;
|
||||
use tgseclib\Crypt\AES;
|
||||
|
||||
use const danog\Decoder\TYPES;
|
||||
|
||||
@ -744,7 +745,7 @@ trait Files
|
||||
return $res;
|
||||
// Wallpapers
|
||||
case 'wallPaper':
|
||||
return $this->getDownloadInfo($res['document']);
|
||||
return $this->getDownloadInfo($messageMedia['document']);
|
||||
// Photos
|
||||
case 'photo':
|
||||
case 'messageMediaPhoto':
|
||||
@ -1204,7 +1205,7 @@ trait Files
|
||||
if ($fingerprint !== $messageMedia['key_fingerprint']) {
|
||||
throw new \danog\MadelineProto\Exception('Fingerprint mismatch!');
|
||||
}
|
||||
$ige = new \tgseclib\Crypt\AES('ige');
|
||||
$ige = new AES('ige');
|
||||
$ige->setIV($messageMedia['iv']);
|
||||
$ige->setKey($messageMedia['key']);
|
||||
$ige->enableContinuousBuffer();
|
||||
|
@ -21,14 +21,12 @@ namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use danog\MadelineProto\MTProto;
|
||||
use danog\MadelineProto\TL\TLCallback;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
* Manages min peers.
|
||||
*/
|
||||
class MinDatabase implements TLCallback
|
||||
{
|
||||
use Tools;
|
||||
const SWITCH_CONSTRUCTORS = ['inputChannel', 'inputUser', 'inputPeerUser', 'inputPeerChannel'];
|
||||
const CATCH_PEERS = ['message', 'messageService', 'peerUser', 'peerChannel', 'messageEntityMentionName', 'messageFwdHeader', 'messageActionChatCreate', 'messageActionChatAddUser', 'messageActionChatDeleteUser', 'messageActionChatJoinedByLink'];
|
||||
const ORIGINS = ['message', 'messageService'];
|
||||
|
@ -22,7 +22,6 @@ namespace danog\MadelineProto\MTProtoTools;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\Magic;
|
||||
use danog\MadelineProto\SecurityException;
|
||||
use danog\MadelineProto\Tools;
|
||||
use tgseclib\Math\BigInteger;
|
||||
|
||||
/**
|
||||
@ -34,7 +33,7 @@ use tgseclib\Math\BigInteger;
|
||||
class PasswordCalculator
|
||||
{
|
||||
use AuthKeyHandler;
|
||||
use Tools;
|
||||
|
||||
/**
|
||||
* The algorithm to use for calculating the hash of new passwords (a PasswordKdfAlgo object).
|
||||
*
|
||||
|
@ -188,9 +188,6 @@ trait PeerHandler
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new \danog\MadelineProto\Exception('Invalid chat provided at key ' . $key . ': ' . \var_export($chat, true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
private function cachePwrChat($id, $full_fetch, $send)
|
||||
@ -199,9 +196,9 @@ trait PeerHandler
|
||||
try {
|
||||
yield from $this->getPwrChat($id, $full_fetch, $send);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$this->logger->logger('While caching: ' . $e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('While caching: '.$e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger('While caching: ' . $e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
$this->logger->logger('While caching: '.$e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
}
|
||||
})());
|
||||
}
|
||||
@ -409,7 +406,7 @@ trait PeerHandler
|
||||
case 'updateEditChannelMessage':
|
||||
return $this->getId($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)) {
|
||||
@ -418,7 +415,7 @@ trait PeerHandler
|
||||
return $this->toSupergroup($matches[1]);
|
||||
}
|
||||
if (\preg_match('/^chat#(\\d*)/', $id, $matches)) {
|
||||
$id = '-' . $matches[1];
|
||||
$id = '-'.$matches[1];
|
||||
}
|
||||
if (\preg_match('/^user#(\\d*)/', $id, $matches)) {
|
||||
return $matches[1];
|
||||
@ -527,12 +524,12 @@ trait PeerHandler
|
||||
if (!isset($this->settings['pwr']['requests']) || $this->settings['pwr']['requests'] === true && $recursive) {
|
||||
$dbres = [];
|
||||
try {
|
||||
$dbres = \json_decode(yield from $this->datacenter->fileGetContents('https://id.pwrtelegram.xyz/db/getusername?id=' . $id), true);
|
||||
$dbres = \json_decode(yield from $this->datacenter->fileGetContents('https://id.pwrtelegram.xyz/db/getusername?id='.$id), true);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logger($e);
|
||||
}
|
||||
if (isset($dbres['ok']) && $dbres['ok']) {
|
||||
yield from $this->resolveUsername('@' . $dbres['result']);
|
||||
yield from $this->resolveUsername('@'.$dbres['result']);
|
||||
return yield from $this->getInfo($id, false);
|
||||
}
|
||||
}
|
||||
@ -646,7 +643,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];
|
||||
@ -832,7 +829,7 @@ trait PeerHandler
|
||||
foreach ($filters as $filter) {
|
||||
yield from $this->recurseAlphabetSearchParticipants($full['InputChannel'], $filter, $q, $total_count, $res);
|
||||
}
|
||||
$this->logger->logger('Fetched ' . \count($res['participants']) . " out of {$total_count}");
|
||||
$this->logger->logger('Fetched '.\count($res['participants'])." out of {$total_count}");
|
||||
$res['participants'] = \array_values($res['participants']);
|
||||
}
|
||||
if (!$fullfetch) {
|
||||
@ -877,7 +874,7 @@ trait PeerHandler
|
||||
return false;
|
||||
}
|
||||
for ($x = 'a'; $x !== 'aa' && $total_count > \count($res['participants']); $x++) {
|
||||
yield from $this->recurseAlphabetSearchParticipants($channel, $filter, $q . $x, $total_count, $res);
|
||||
yield from $this->recurseAlphabetSearchParticipants($channel, $filter, $q.$x, $total_count, $res);
|
||||
}
|
||||
}
|
||||
private function fetchParticipants($channel, $filter, $q, $total_count, &$res): \Generator
|
||||
@ -925,15 +922,15 @@ trait PeerHandler
|
||||
if (isset($participant['rank'])) {
|
||||
$newres['rank'] = $participant['rank'];
|
||||
}
|
||||
if (isset($participant['admin_rights'])) {
|
||||
$newres['admin_rights'] = $participant['admin_rights'];
|
||||
}
|
||||
if (isset($participant['banned_rights'])) {
|
||||
$newres['banned_rights'] = $participant['banned_rights'];
|
||||
}
|
||||
switch ($participant['_']) {
|
||||
case 'channelParticipantSelf':
|
||||
$newres['role'] = 'user';
|
||||
if (isset($newres['admin_rights'])) {
|
||||
$newres['admin_rights'] = $full['Chat']['admin_rights'];
|
||||
}
|
||||
if (isset($newres['banned_rights'])) {
|
||||
$newres['banned_rights'] = $full['Chat']['banned_rights'];
|
||||
}
|
||||
break;
|
||||
case 'channelParticipant':
|
||||
$newres['role'] = 'user';
|
||||
@ -950,7 +947,7 @@ 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);
|
||||
$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) {
|
||||
@ -1002,7 +999,7 @@ trait PeerHandler
|
||||
//$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'];
|
||||
$request = new Request('https://id.pwrtelegram.xyz/db' . $this->settings['pwr']['db_token'] . '/addnewmadeline?d=pls&from=' . $id, 'POST');
|
||||
$request = new Request('https://id.pwrtelegram.xyz/db'.$this->settings['pwr']['db_token'].'/addnewmadeline?d=pls&from='.$id, 'POST');
|
||||
$request->setHeader('content-type', 'application/json');
|
||||
$request->setBody($payload);
|
||||
$result = yield (yield $this->datacenter->getHTTPClient()->request($request))->getBody()->buffer();
|
||||
@ -1010,7 +1007,7 @@ trait PeerHandler
|
||||
$this->qres = [];
|
||||
$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);
|
||||
$this->logger->logger('======= COULD NOT STORE IN DB DUE TO '.$e->getMessage().' =============', \danog\MadelineProto\Logger::VERBOSE);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -1026,7 +1023,7 @@ trait PeerHandler
|
||||
$this->caching_simple_username[$username] = true;
|
||||
$res = yield from $this->methodCallAsyncRead('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);
|
||||
$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') {
|
||||
throw $e;
|
||||
}
|
||||
|
@ -22,14 +22,13 @@ namespace danog\MadelineProto\MTProtoTools;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\MTProto;
|
||||
use danog\MadelineProto\TL\TLCallback;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
* Manages upload and download of files.
|
||||
*/
|
||||
class ReferenceDatabase implements TLCallback
|
||||
{
|
||||
use Tools;
|
||||
|
||||
// Reference from a document
|
||||
const DOCUMENT_LOCATION = 0;
|
||||
// Reference from a photo
|
||||
|
@ -25,7 +25,6 @@ use Amp\DoH\Rfc8484StubResolver;
|
||||
use Amp\Loop;
|
||||
use Amp\Loop\Driver;
|
||||
use ReflectionClass;
|
||||
use function Amp\ByteStream\getInputBufferStream;
|
||||
use function Amp\ByteStream\getStdin;
|
||||
use function Amp\Dns\resolver;
|
||||
use function Amp\Promise\wait;
|
||||
@ -236,7 +235,7 @@ class Magic
|
||||
throw Exception::extension($extension);
|
||||
}
|
||||
}
|
||||
self::$has_thread = \class_exists('\\Thread') && \method_exists('\\Thread', 'getCurrentThread');
|
||||
self::$has_thread = \class_exists(\Thread::class) && \method_exists(\Thread::class, 'getCurrentThread');
|
||||
self::$BIG_ENDIAN = \pack('L', 1) === \pack('N', 1);
|
||||
self::$bigint = PHP_INT_SIZE < 8;
|
||||
self::$ipv6 = (bool) \strlen(@\file_get_contents('http://ipv6.google.com', false, \stream_context_create(['http' => ['timeout' => 1]]))) > 0;
|
||||
@ -390,10 +389,9 @@ class Magic
|
||||
public static function shutdown(int $code = 0)
|
||||
{
|
||||
self::$signaled = true;
|
||||
if (\defined(STDIN::class)) {
|
||||
if (\defined('STDIN')) {
|
||||
getStdin()->unreference();
|
||||
}
|
||||
getInputBufferStream()->unreference();
|
||||
if ($code !== 0) {
|
||||
$driver = Loop::get();
|
||||
$reflectionClass = new ReflectionClass(Driver::class);
|
||||
|
@ -27,7 +27,6 @@ use Amp\Http\Client\Request;
|
||||
*/
|
||||
class MyTelegramOrgWrapper
|
||||
{
|
||||
use Tools;
|
||||
private $logged = false;
|
||||
private $hash = '';
|
||||
private $number;
|
||||
|
@ -23,8 +23,7 @@ class RPCErrorException extends \Exception
|
||||
{
|
||||
use TL\PrettyException;
|
||||
private $fetched = false;
|
||||
public static $rollbar = true;
|
||||
public static $descriptions = ['RPC_MCGET_FAIL' => 'Telegram is having internal issues, please try again later.', 'RPC_CALL_FAIL' => 'Telegram is having internal issues, please try again later.', 'USER_PRIVACY_RESTRICTED' => "The user's privacy settings do not allow you to do this", 'CHANNEL_PRIVATE' => "You haven't joined this channel/supergroup", 'USER_IS_BOT' => "Bots can't send messages to other bots", 'BOT_METHOD_INVALID' => 'This method cannot be run by a bot', 'PHONE_CODE_EXPIRED' => 'The phone code you provided has expired, this may happen if it was sent to any chat on telegram (if the code is sent through a telegram chat (not the official account) to avoid it append or prepend to the code some chars)', 'USERNAME_INVALID' => 'The provided username is not valid', 'ACCESS_TOKEN_INVALID' => 'The provided token is not valid', 'ACTIVE_USER_REQUIRED' => 'The method is only available to already activated users', 'FIRSTNAME_INVALID' => 'The first name is invalid', 'LASTNAME_INVALID' => 'The last name is invalid', 'PHONE_NUMBER_INVALID' => 'The phone number is invalid', 'PHONE_CODE_HASH_EMPTY' => 'phone_code_hash is missing', 'PHONE_CODE_EMPTY' => 'phone_code is missing', 'PHONE_CODE_EXPIRED' => 'The confirmation code has expired', 'API_ID_INVALID' => 'The api_id/api_hash combination is invalid', 'PHONE_NUMBER_OCCUPIED' => 'The phone number is already in use', 'PHONE_NUMBER_UNOCCUPIED' => 'The phone number is not yet being used', 'USERS_TOO_FEW' => 'Not enough users (to create a chat, for example)', 'USERS_TOO_MUCH' => 'The maximum number of users has been exceeded (to create a chat, for example)', 'TYPE_CONSTRUCTOR_INVALID' => 'The type constructor is invalid', 'FILE_PART_INVALID' => 'The file part number is invalid', 'FILE_PARTS_INVALID' => 'The number of file parts is invalid', 'MD5_CHECKSUM_INVALID' => 'The MD5 checksums do not match', 'PHOTO_INVALID_DIMENSIONS' => 'The photo dimensions are invalid', 'FIELD_NAME_INVALID' => 'The field with the name FIELD_NAME is invalid', 'FIELD_NAME_EMPTY' => 'The field with the name FIELD_NAME is missing', 'MSG_WAIT_FAILED' => 'A waiting call returned an error', 'USERNAME_NOT_OCCUPIED' => 'The provided username is not occupied', 'PHONE_NUMBER_BANNED' => 'The provided phone number is banned from telegram', 'AUTH_KEY_UNREGISTERED' => 'The authorization key has expired', 'INVITE_HASH_EXPIRED' => 'The invite link has expired', 'USER_DEACTIVATED' => 'The user was deactivated', 'USER_ALREADY_PARTICIPANT' => 'The user is already in the group', 'MESSAGE_ID_INVALID' => 'The provided message id is invalid', 'PEER_ID_INVALID' => 'The provided peer id is invalid', 'CHAT_ID_INVALID' => 'The provided chat id is invalid', 'MESSAGE_DELETE_FORBIDDEN' => "You can't delete one of the messages you tried to delete, most likely because it is a service message.", 'CHAT_ADMIN_REQUIRED' => 'You must be an admin in this chat to do this', -429 => 'Too many requests', 'PEER_FLOOD' => "You are spamreported, you can't do this"];
|
||||
public static $descriptions = ['RPC_MCGET_FAIL' => 'Telegram is having internal issues, please try again later.', 'RPC_CALL_FAIL' => 'Telegram is having internal issues, please try again later.', 'USER_PRIVACY_RESTRICTED' => "The user's privacy settings do not allow you to do this", 'CHANNEL_PRIVATE' => "You haven't joined this channel/supergroup", 'USER_IS_BOT' => "Bots can't send messages to other bots", 'BOT_METHOD_INVALID' => 'This method cannot be run by a bot', 'PHONE_CODE_EXPIRED' => 'The phone code you provided has expired, this may happen if it was sent to any chat on telegram (if the code is sent through a telegram chat (not the official account) to avoid it append or prepend to the code some chars)', 'USERNAME_INVALID' => 'The provided username is not valid', 'ACCESS_TOKEN_INVALID' => 'The provided token is not valid', 'ACTIVE_USER_REQUIRED' => 'The method is only available to already activated users', 'FIRSTNAME_INVALID' => 'The first name is invalid', 'LASTNAME_INVALID' => 'The last name is invalid', 'PHONE_NUMBER_INVALID' => 'The phone number is invalid', 'PHONE_CODE_HASH_EMPTY' => 'phone_code_hash is missing', 'PHONE_CODE_EMPTY' => 'phone_code is missing', 'API_ID_INVALID' => 'The api_id/api_hash combination is invalid', 'PHONE_NUMBER_OCCUPIED' => 'The phone number is already in use', 'PHONE_NUMBER_UNOCCUPIED' => 'The phone number is not yet being used', 'USERS_TOO_FEW' => 'Not enough users (to create a chat, for example)', 'USERS_TOO_MUCH' => 'The maximum number of users has been exceeded (to create a chat, for example)', 'TYPE_CONSTRUCTOR_INVALID' => 'The type constructor is invalid', 'FILE_PART_INVALID' => 'The file part number is invalid', 'FILE_PARTS_INVALID' => 'The number of file parts is invalid', 'MD5_CHECKSUM_INVALID' => 'The MD5 checksums do not match', 'PHOTO_INVALID_DIMENSIONS' => 'The photo dimensions are invalid', 'FIELD_NAME_INVALID' => 'The field with the name FIELD_NAME is invalid', 'FIELD_NAME_EMPTY' => 'The field with the name FIELD_NAME is missing', 'MSG_WAIT_FAILED' => 'A waiting call returned an error', 'USERNAME_NOT_OCCUPIED' => 'The provided username is not occupied', 'PHONE_NUMBER_BANNED' => 'The provided phone number is banned from telegram', 'AUTH_KEY_UNREGISTERED' => 'The authorization key has expired', 'INVITE_HASH_EXPIRED' => 'The invite link has expired', 'USER_DEACTIVATED' => 'The user was deactivated', 'USER_ALREADY_PARTICIPANT' => 'The user is already in the group', 'MESSAGE_ID_INVALID' => 'The provided message id is invalid', 'PEER_ID_INVALID' => 'The provided peer id is invalid', 'CHAT_ID_INVALID' => 'The provided chat id is invalid', 'MESSAGE_DELETE_FORBIDDEN' => "You can't delete one of the messages you tried to delete, most likely because it is a service message.", 'CHAT_ADMIN_REQUIRED' => 'You must be an admin in this chat to do this', -429 => 'Too many requests', 'PEER_FLOOD' => "You are spamreported, you can't do this"];
|
||||
public static $errorMethodMap = [];
|
||||
private $caller = '';
|
||||
public static function localizeMessage($method, $code, $error)
|
||||
@ -69,9 +68,7 @@ class RPCErrorException extends \Exception
|
||||
$additional = $level['args'];
|
||||
}
|
||||
}
|
||||
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'])) {
|
||||
return;
|
||||
}
|
||||
@ -79,5 +76,6 @@ class RPCErrorException extends \Exception
|
||||
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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ use danog\MadelineProto\TL\TL;
|
||||
*/
|
||||
class RSA
|
||||
{
|
||||
use \danog\MadelineProto\Tools;
|
||||
use \danog\Serializable;
|
||||
/**
|
||||
* Exponent.
|
||||
|
@ -43,7 +43,7 @@ class Serialization
|
||||
public static function realpaths(string $file): array
|
||||
{
|
||||
$file = Absolute::absolute($file);
|
||||
return ['file' => $file, 'lockfile' => $file . '.lock', 'tempfile' => $file . '.temp.session'];
|
||||
return ['file' => $file, 'lockfile' => $file.'.lock', 'tempfile' => $file.'.temp.session'];
|
||||
}
|
||||
/**
|
||||
* Unserialize legacy session.
|
||||
@ -80,7 +80,7 @@ class Serialization
|
||||
if ($e->getFile() === 'MadelineProto' && $e->getLine() === 1) {
|
||||
throw $e;
|
||||
}
|
||||
if (\MADELINEPROTO_TEST === 'pony') {
|
||||
if (\constant("MADELINEPROTO_TEST") === 'pony') {
|
||||
throw $e;
|
||||
}
|
||||
\class_exists('\\Volatile');
|
||||
|
@ -59,7 +59,7 @@ class Shutdown
|
||||
* @param callable $callback The callback to set
|
||||
* @param null|string $id The optional callback ID
|
||||
*
|
||||
* @return The callback ID
|
||||
* @return int The callback ID
|
||||
*/
|
||||
public static function addCallback($callback, $id = null)
|
||||
{
|
||||
|
@ -109,8 +109,6 @@ class CtrStream implements BufferedProxyStreamInterface, BufferInterface
|
||||
*
|
||||
* @param Promise $promise Promise that resolves with a string when new data is available or `null` if the stream has closed.
|
||||
*
|
||||
* @throws PendingReadError Thrown if another read operation is still pending.
|
||||
*
|
||||
* @return \Generator That resolves with a string when the provided promise is resolved and the data is decrypted
|
||||
*/
|
||||
public function bufferReadGenerator(int $length): \Generator
|
||||
@ -122,8 +120,6 @@ class CtrStream implements BufferedProxyStreamInterface, BufferInterface
|
||||
*
|
||||
* @param string $data Bytes to write.
|
||||
*
|
||||
* @throws ClosedException If the stream has already been closed.
|
||||
*
|
||||
* @return Promise Succeeds once the data has been successfully written to the stream.
|
||||
*/
|
||||
public function bufferWrite(string $data): Promise
|
||||
|
@ -140,8 +140,6 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
|
||||
*
|
||||
* @param int $length Read and hash $length bytes
|
||||
*
|
||||
* @throws PendingReadError Thrown if another read operation is still pending.
|
||||
*
|
||||
* @return \Generator That resolves with a string when the provided promise is resolved and the data is added to the hashing context
|
||||
*/
|
||||
public function bufferReadGenerator(int $length): \Generator
|
||||
@ -241,8 +239,6 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
|
||||
/**
|
||||
* Reads data from the stream.
|
||||
*
|
||||
* @throws PendingReadError Thrown if another read operation is still pending.
|
||||
*
|
||||
* @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
|
||||
*/
|
||||
public function bufferRead(int $length): Promise
|
||||
@ -257,8 +253,6 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
|
||||
*
|
||||
* @param string $data Bytes to write.
|
||||
*
|
||||
* @throws ClosedException If the stream has already been closed.
|
||||
*
|
||||
* @return Promise Succeeds once the data has been successfully written to the stream.
|
||||
*/
|
||||
public function bufferWrite(string $data): Promise
|
||||
|
@ -649,7 +649,7 @@ class TL
|
||||
* Serialize parameters.
|
||||
*
|
||||
* @param array $tl TL object definition
|
||||
* @param arrayLike $arguments Arguments
|
||||
* @param array $arguments Arguments
|
||||
* @param string $ctx Context
|
||||
* @param integer $layer Layer
|
||||
*
|
||||
|
@ -22,7 +22,6 @@ namespace danog\MadelineProto\TL;
|
||||
class TLConstructors
|
||||
{
|
||||
use \danog\Serializable;
|
||||
use \danog\MadelineProto\Tools;
|
||||
use TLParams;
|
||||
public $by_id = [];
|
||||
public $by_predicate_and_layer = [];
|
||||
@ -36,8 +35,8 @@ class TLConstructors
|
||||
if (isset($this->by_id[$json_dict['id']]) && (!isset($this->by_id[$json_dict['id']]['layer']) || $this->by_id[$json_dict['id']]['layer'] > $json_dict['layer'])) {
|
||||
return false;
|
||||
}
|
||||
$predicate = (string) (($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message' ? 'MT' : '') . $json_dict['predicate']);
|
||||
$this->by_id[$json_dict['id']] = ['predicate' => $predicate, 'params' => $json_dict['params'], 'type' => ($scheme_type === 'mtproto' && $json_dict['type'] === 'Message' ? 'MT' : '') . $json_dict['type']];
|
||||
$predicate = (string) (($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message' ? 'MT' : '').$json_dict['predicate']);
|
||||
$this->by_id[$json_dict['id']] = ['predicate' => $predicate, 'params' => $json_dict['params'], 'type' => ($scheme_type === 'mtproto' && $json_dict['type'] === 'Message' ? 'MT' : '').$json_dict['type']];
|
||||
if ($scheme_type === 'secret') {
|
||||
$this->by_id[$json_dict['id']]['layer'] = $json_dict['layer'];
|
||||
$this->layers[$json_dict['layer']] = $json_dict['layer'];
|
||||
@ -45,7 +44,7 @@ class TLConstructors
|
||||
} else {
|
||||
$json_dict['layer'] = '';
|
||||
}
|
||||
$this->by_predicate_and_layer[$predicate . $json_dict['layer']] = $json_dict['id'];
|
||||
$this->by_predicate_and_layer[$predicate.$json_dict['layer']] = $json_dict['id'];
|
||||
$this->parseParams($json_dict['id'], $scheme_type === 'mtproto');
|
||||
}
|
||||
public function findByType($type)
|
||||
@ -61,13 +60,14 @@ class TLConstructors
|
||||
public function findByPredicate($predicate, $layer = -1)
|
||||
{
|
||||
if ($layer !== -1) {
|
||||
$chosenid = null;
|
||||
foreach ($this->layers as $alayer) {
|
||||
if ($alayer <= $layer) {
|
||||
if (isset($this->by_predicate_and_layer[$predicate . $alayer])) {
|
||||
$chosenid = $this->by_predicate_and_layer[$predicate . $alayer];
|
||||
if (isset($this->by_predicate_and_layer[$predicate.$alayer])) {
|
||||
$chosenid = $this->by_predicate_and_layer[$predicate.$alayer];
|
||||
}
|
||||
} elseif (!isset($chosenid)) {
|
||||
$chosenid = $this->by_predicate_and_layer[$predicate . $alayer];
|
||||
$chosenid = $this->by_predicate_and_layer[$predicate.$alayer];
|
||||
}
|
||||
}
|
||||
if (!isset($chosenid)) {
|
||||
|
@ -22,7 +22,6 @@ namespace danog\MadelineProto\TL;
|
||||
class TLMethods
|
||||
{
|
||||
use \danog\Serializable;
|
||||
use \danog\MadelineProto\Tools;
|
||||
use TLParams;
|
||||
public $by_id = [];
|
||||
public $by_method = [];
|
||||
|
@ -41,7 +41,7 @@ use function Amp\Promise\wait;
|
||||
/**
|
||||
* Some tools.
|
||||
*/
|
||||
trait Tools
|
||||
abstract class Tools
|
||||
{
|
||||
/**
|
||||
* Sanify TL obtained from JSON for TL serialization.
|
||||
@ -614,7 +614,7 @@ trait Tools
|
||||
/**
|
||||
* Check if is array or similar (traversable && countable && arrayAccess).
|
||||
*
|
||||
* @param arraylike $var Value to check
|
||||
* @param mixed $var Value to check
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
|
@ -26,7 +26,7 @@ trait DialogHandler
|
||||
*
|
||||
* @param boolean $force Whether to refetch all dialogs ignoring cache
|
||||
*
|
||||
* @return \Generator<array<Peer>>
|
||||
* @return \Generator<array<array>>
|
||||
*/
|
||||
public function getDialogs(bool $force = true): \Generator
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user