diff --git a/src/danog/MadelineProto/ApiWrappers/Start.php b/src/danog/MadelineProto/ApiWrappers/Start.php index 65c43ee9..fc9a5514 100644 --- a/src/danog/MadelineProto/ApiWrappers/Start.php +++ b/src/danog/MadelineProto/ApiWrappers/Start.php @@ -37,7 +37,7 @@ trait Start */ private function APIStart(array $settings): \Generator { - if (PHP_SAPI === 'cli') { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { $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); diff --git a/src/danog/MadelineProto/Exception.php b/src/danog/MadelineProto/Exception.php index f0c809ea..0308d623 100644 --- a/src/danog/MadelineProto/Exception.php +++ b/src/danog/MadelineProto/Exception.php @@ -64,7 +64,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 !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { echo $message.'
'; } $file = 'MadelineProto'; diff --git a/src/danog/MadelineProto/Logger.php b/src/danog/MadelineProto/Logger.php index 9d2ec731..e436e326 100644 --- a/src/danog/MadelineProto/Logger.php +++ b/src/danog/MadelineProto/Logger.php @@ -21,6 +21,8 @@ namespace danog\MadelineProto; use Amp\ByteStream\ResourceOutputStream; use Amp\Failure; +use Amp\Loop; + use function Amp\ByteStream\getStderr; use function Amp\ByteStream\getStdout; @@ -87,12 +89,17 @@ class Logger * @var boolean */ public static $printed = false; + /** + * Log rotation loop ID. + */ + private string $rotateId; const ULTRA_VERBOSE = 5; const VERBOSE = 4; const NOTICE = 3; const WARNING = 2; const ERROR = 1; const FATAL_ERROR = 0; + const NO_LOGGER = 0; const DEFAULT_LOGGER = 1; const FILE_LOGGER = 2; @@ -125,14 +132,14 @@ class Logger if (!isset($settings['logger']['logger_param']) && isset($settings['logger']['param'])) { $settings['logger']['logger_param'] = $settings['logger']['param']; } - if (PHP_SAPI !== 'cli' && isset($settings['logger']['logger_param']) && $settings['logger']['logger_param'] === 'MadelineProto.log') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && isset($settings['logger']['logger_param']) && $settings['logger']['logger_param'] === 'MadelineProto.log') { $settings['logger']['logger_param'] = Magic::$script_cwd.'/MadelineProto.log'; } $logger = new self($settings['logger']['logger'], $settings['logger']['logger_param'] ?? '', $prefix, $settings['logger']['logger_level'] ?? Logger::VERBOSE, $settings['logger']['max_size'] ?? 100 * 1024 * 1024); if (!self::$default) { self::$default = $logger; } - if (PHP_SAPI !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { try { \error_reporting(E_ALL); \ini_set('log_errors', 1); @@ -170,22 +177,28 @@ class Logger * * @return void */ - public function __construct(int $mode, $optional = null, string $prefix = '', int $level = self::NOTICE, int $max_size = 100 * 1024 * 1024) + public function __construct(int $mode, $optional = null, string $prefix = '', int $level = self::NOTICE, int $max_size = 10 * 1024 * 1024) { if ($mode === null) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['no_mode_specified']); } + if ($mode === self::NO_LOGGER) { + $mode = (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') ? Logger::ECHO_LOGGER : Logger::FILE_LOGGER; + } + $level = \max($level, self::NOTICE); + $max_size = \max($max_size, 100 * 1024); + $this->mode = $mode; - $this->optional = $mode == 2 ? Tools::absolute($optional) : $optional; + $this->optional = $mode == self::FILE_LOGGER ? Tools::absolute($optional) : $optional; $this->prefix = $prefix === '' ? '' : ', '.$prefix; $this->level = $level; - if ($this->mode === 2 && !\file_exists(\pathinfo($this->optional, PATHINFO_DIRNAME))) { + if ($this->mode === self::FILE_LOGGER && !\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 === self::FILE_LOGGER && !\preg_match('/\\.log$/', $this->optional)) { $this->optional .= '.log'; } - if ($mode === 2 && $max_size !== -1 && \file_exists($this->optional) && \filesize($this->optional) > $max_size) { + if ($mode === self::FILE_LOGGER && $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']]); @@ -195,14 +208,30 @@ class Logger $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) { + if ($this->mode === self::ECHO_LOGGER) { $this->stdout = getStdout(); - if (PHP_SAPI !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { $this->newline = '
'.$this->newline; } - } elseif ($this->mode === 2) { - $this->stdout = new ResourceOutputStream(\fopen($this->optional, 'a+')); - } elseif ($this->mode === 1) { + } elseif ($this->mode === self::FILE_LOGGER) { + Snitch::logFile($this->optional); + $this->stdout = new ResourceOutputStream(\fopen($this->optional, 'a')); + if ($max_size !== -1) { + $this->rotateId = Loop::repeat( + 10*1000, + function () use ($max_size) { + \clearstatcache(true, $this->optional); + if (\filesize($this->optional) >= $max_size) { + $this->stdout = null; + \unlink($this->optional); + $this->stdout = new ResourceOutputStream(\fopen($this->optional, 'a')); + } + $this->logger("Automatically truncated logfile to $max_size"); + } + ); + Loop::unreference($this->rotateId); + } + } elseif ($this->mode === self::DEFAULT_LOGGER) { $result = @\ini_get('error_log'); if ($result === 'syslog') { $this->stdout = getStderr(); @@ -213,6 +242,15 @@ class Logger } } } + /** + * Destructor function. + */ + public function __destruct(): void + { + if ($this->rotateId) { + Loop::cancel($this->rotateId); + } + } /** * Log a message. * @@ -240,7 +278,7 @@ class Logger */ public function logger($param, int $level = self::NOTICE, string $file = ''): void { - if ($level > $this->level || $this->mode === 0) { + if ($level > $this->level || $this->mode === self::NO_LOGGER) { return; } if (!self::$printed) { @@ -252,7 +290,7 @@ class Logger $this->logger('https://github.com/danog/MadelineProto'); $this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]); } - if ($this->mode === 4) { + if ($this->mode === self::CALLABLE_LOGGER) { \call_user_func_array($this->optional, [$param, $level]); return; } @@ -266,25 +304,22 @@ class Logger $file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php'); } $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); - } - break; - default: - $param = Magic::$isatty ? "\33[".$this->colors[$level].'m'.$param."\33[0m".$this->newline : $param.$this->newline; - 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; - } - } - break; + if ($this->mode === self::DEFAULT_LOGGER) { + if ($this->stdout->write($param.$this->newline) instanceof Failure) { + \error_log($param); + } + return; + } + $param = Magic::$isatty ? "\33[".$this->colors[$level].'m'.$param."\33[0m".$this->newline : $param.$this->newline; + if ($this->stdout->write($param) instanceof Failure) { + switch ($this->mode) { + case self::ECHO_LOGGER: + echo $param; + break; + case self::FILE_LOGGER: + \file_put_contents($this->optional, $param, FILE_APPEND); + break; + } } } } diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index 31cc670e..de624968 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -421,6 +421,11 @@ class MTProto extends AsyncConstruct implements TLCallback */ private $TL; + /** + * Snitch. + */ + private Snitch $snitch; + /** * List of properties stored in database (memory or external). * @see DbPropertiesFabric @@ -564,7 +569,10 @@ class MTProto extends AsyncConstruct implements TLCallback 'temp_rekeyed_secret_chats', // Report URI - 'reportDest' + 'reportDest', + + // Packagist install report state + 'packagistReported' ]; } @@ -824,6 +832,9 @@ class MTProto extends AsyncConstruct implements TLCallback */ private function upgradeMadelineProto(): \Generator { + if (!isset($this->snitch)) { + $this->snitch = new Snitch; + } $this->logger->logger(Lang::$current_lang['serialization_ofd'], Logger::WARNING); foreach ($this->datacenter->getDataCenterConnections() as $dc_id => $socket) { if ($this->authorized === self::LOGGED_IN && \strpos($dc_id, '_') === false && $socket->hasPermAuthKey() && $socket->hasTempAuthKey()) { @@ -1281,10 +1292,10 @@ class MTProto extends AsyncConstruct implements TLCallback */ // write to 'logger_param' => Magic::$script_cwd.'/MadelineProto.log', - 'logger' => PHP_SAPI === 'cli' ? 3 : 2, + 'logger' => (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') ? Logger::ECHO_LOGGER : Logger::FILE_LOGGER, // overwrite previous setting and echo logs 'logger_level' => Logger::VERBOSE, - 'max_size' => 100 * 1024 * 1024, + 'max_size' => 10 * 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. ], 'max_tries' => [ 'query' => 5, diff --git a/src/danog/MadelineProto/Magic.php b/src/danog/MadelineProto/Magic.php index 1ebfd9b5..e8bb8f69 100644 --- a/src/danog/MadelineProto/Magic.php +++ b/src/danog/MadelineProto/Magic.php @@ -276,7 +276,7 @@ class Magic self::$revision = 'Revision: '.self::$revision.$latest; } self::$can_parallel = false; - if (PHP_SAPI === 'cli' && !(\class_exists(\Phar::class) && \Phar::running())) { + if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && !(\class_exists(\Phar::class) && \Phar::running())) { try { $back = \debug_backtrace(0); \define('AMP_WORKER', 1); @@ -330,7 +330,7 @@ class Magic ); resolver(new Rfc8484StubResolver($DohConfig)); }*/ - if (PHP_SAPI !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { try { \error_reporting(E_ALL); \ini_set('log_errors', 1); diff --git a/src/danog/MadelineProto/RPCErrorException.php b/src/danog/MadelineProto/RPCErrorException.php index 60c0d939..d5deab2f 100644 --- a/src/danog/MadelineProto/RPCErrorException.php +++ b/src/danog/MadelineProto/RPCErrorException.php @@ -54,7 +54,7 @@ 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 !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { $result = \str_replace(PHP_EOL, '
'.PHP_EOL, $result); } return $result; diff --git a/src/danog/MadelineProto/TL/Conversion/Exception.php b/src/danog/MadelineProto/TL/Conversion/Exception.php index 66783398..956d2ae3 100644 --- a/src/danog/MadelineProto/TL/Conversion/Exception.php +++ b/src/danog/MadelineProto/TL/Conversion/Exception.php @@ -25,7 +25,7 @@ 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 !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { $result = \str_replace(PHP_EOL, '
'.PHP_EOL, $result); } return $result; diff --git a/src/danog/MadelineProto/TL/Exception.php b/src/danog/MadelineProto/TL/Exception.php index dbeef702..174975e3 100644 --- a/src/danog/MadelineProto/TL/Exception.php +++ b/src/danog/MadelineProto/TL/Exception.php @@ -25,7 +25,7 @@ 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 !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { $result = \str_replace(PHP_EOL, '
'.PHP_EOL, $result); } return $result; diff --git a/src/danog/MadelineProto/TL/PrettyException.php b/src/danog/MadelineProto/TL/PrettyException.php index c615e648..3df2e114 100644 --- a/src/danog/MadelineProto/TL/PrettyException.php +++ b/src/danog/MadelineProto/TL/PrettyException.php @@ -79,7 +79,7 @@ trait PrettyException $previous_trace = $this->tl_trace; $this->tl_trace = ''; $eol = PHP_EOL; - if (PHP_SAPI !== 'cli') { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { $eol = '
'.PHP_EOL; } $tl = false; diff --git a/src/danog/MadelineProto/Wrappers/Loop.php b/src/danog/MadelineProto/Wrappers/Loop.php index c44da077..fe0bf868 100644 --- a/src/danog/MadelineProto/Wrappers/Loop.php +++ b/src/danog/MadelineProto/Wrappers/Loop.php @@ -65,7 +65,7 @@ trait Loop $this->loop_callback = null; } static $inited = false; - if (PHP_SAPI !== 'cli' && !$inited) { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && !$inited) { $needs_restart = true; try { \set_time_limit(-1); @@ -206,7 +206,7 @@ trait Loop */ public function closeConnection($message = 'OK!') { - if (PHP_SAPI === 'cli' || isset($GLOBALS['exited']) || \headers_sent()) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' || isset($GLOBALS['exited']) || \headers_sent()) { return; } $this->logger->logger($message); diff --git a/src/danog/MadelineProto/Wrappers/Start.php b/src/danog/MadelineProto/Wrappers/Start.php index 68cceba1..646c432f 100644 --- a/src/danog/MadelineProto/Wrappers/Start.php +++ b/src/danog/MadelineProto/Wrappers/Start.php @@ -36,7 +36,7 @@ trait Start if ($this->authorized === self::LOGGED_IN) { return yield from $this->fullGetSelf(); } - if (PHP_SAPI === 'cli') { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { if (\strpos(yield Tools::readLine('Do you want to login as user or bot (u/b)? '), 'b') !== false) { yield from $this->botLogin(yield Tools::readLine('Enter your bot token: ')); } else { diff --git a/tools/phar.php b/tools/phar.php index 3ea3172e..0c81a763 100644 --- a/tools/phar.php +++ b/tools/phar.php @@ -78,6 +78,8 @@ function ___install_madeline() $release_branch = $release_fallback_branch; } + \define('HAD_MADELINE_PHAR', \file_exists('madeline.phar')); + if (!\file_exists('madeline.phar') || !\file_exists('madeline.phar.version') || \file_get_contents('madeline.phar.version') !== $release) { $phar = \file_get_contents(\sprintf($phar_template, $release_branch)); @@ -117,9 +119,9 @@ function ___install_madeline() } if (\defined('HHVM_VERSION')) { - $phpVersion = 'HHVM ' . HHVM_VERSION; + $phpVersion = 'HHVM '.HHVM_VERSION; } else { - $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION; + $phpVersion = 'PHP '.PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION.'.'.PHP_RELEASE_VERSION; } $opts = ['http' => [ @@ -140,7 +142,7 @@ function ___install_madeline() 'timeout' => 6, ], ]; - //@\file_get_contents("https://packagist.org/downloads/", false, \stream_context_create($opts)); + @\file_get_contents("https://packagist.org/downloads/", false, \stream_context_create($opts)); } } }